Quick Start
Create, sign, and verify your first Aqua tree in Rust with aqua-rs-sdk-core.
Aqua Protocol v4 is under active development. The published components — aqua-rs-sdk-core and aqua-template-registry — are an early community release with a deliberately limited functionality scope. Version numbers have not yet been increased, backward compatibility is not yet provided, and breaking changes are expected and may occur without notice. The full aqua-rs-sdk, which extends this core, is scheduled for a later publication. For production use today, refer to the stable v3 documentation.
This guide goes from an empty directory to a verified Aqua tree in one small Rust program: create a genesis revision for a piece of content, sign it with an Ed25519 key, and run the full verification pipeline.
Prerequisites
- A stable Rust toolchain (
rustcandcargo; the crate uses edition 2021) git— cargo fetches the SDK directly from GitHub
Create a project and add dependencies
1cargo new aqua-hello2cd aqua-helloAdd the dependencies to Cargo.toml:
1[dependencies]2aqua-rs-sdk-core = { git = "https://github.com/inblockio/aqua-rs-sdk-core" }3tokio = { version = "1", features = ["full"] }4hex = "0.4"aqua-rs-sdk-core is not on crates.io yet (publication is planned), so the dependency points at the Git repository. tokio provides the async runtime for the signing and verification calls; hex decodes a signing key supplied as hex.
Write the program
Replace src/main.rs with:
1use aqua_rs_sdk_core::schema::{AquaTreeWrapper, FileData, SigningCredentials};2use aqua_rs_sdk_core::Aquafier;3use std::path::PathBuf;4 5#[tokio::main]6async fn main() -> Result<(), Box<dyn std::error::Error>> {7 let aquafier = Aquafier::new();8 9 // 1. Create a genesis revision for some content.10 let file = FileData::new(11 "hello.txt".to_string(),12 b"hello world".to_vec(),13 PathBuf::from("hello.txt"),14 );15 let tree = aquafier.create_genesis_revision(file.clone(), None)?;16 17 // 2. Sign it with an Ed25519 key (a did:key identity).18 // The fallback below is a fixed demo secret (the bytes 1..=32) so19 // that this example runs out of the box. NEVER use a hard-coded or20 // predictable key in production: generate a fresh one with21 // aqua_rs_sdk_core::generate_ed25519() and keep it out of your22 // source code.23 let secret: Vec<u8> = std::env::var("MY_ED25519_SECRET_HEX")24 .map(|h| hex::decode(h).expect("MY_ED25519_SECRET_HEX must be hex"))25 .unwrap_or_else(|_| (1..=32).collect());26 let creds = SigningCredentials::Did { did_key: secret };27 let signed = aquafier28 .sign_aqua_tree(AquaTreeWrapper::new(tree, None, None), &creds, None, None)29 .await?;30 31 // 3. Verify the full pipeline: structure, hashes, schema, signature.32 let result = aquafier33 .verify_aqua_tree(34 AquaTreeWrapper::new(signed.aqua_tree, Some(file.clone()), None),35 vec![file],36 )37 .await?;38 39 println!("verified: {}", result.is_verified());40 Ok(())41}The three calls mirror the protocol lifecycle: create_genesis_revision builds a new tree, sign_aqua_tree appends a signature revision attesting to the tree's tip, and verify_aqua_tree runs the complete verification pipeline over the result.
Run it
1cargo runThe first build fetches and compiles the SDK from GitHub. The program prints:
1verified: truetrue means the tree verified — is_verified() accepts both the verified and verified_with_warnings outcomes, and this program produces no warnings. Every check passed — structural validity, recomputed revision hashes, payload schema conformance, file content (checked by size and content hash, never by filename), and the Ed25519 signature — under the default strict verification policy.
The tree itself is a plain JSON document. The example below is abridged from one of the SDK's deterministic test fixtures (sign_did_example.aqua.json) and shows the same three revision kinds your program produced — a genesis anchor, a typed object revision, and a signature revision (hashes shortened with … for readability):
1{2 "revisions": {3 "0x1620ce6f…b7ce0b": {4 "revision_type": "0x1620479a…11e899",5 "nonce": "0x1a5f4934…6b96d580",6 "local_timestamp": 1783616147,7 "version": "https://aqua-protocol.org/docs/v4/schema",8 "method": "scalar",9 "structural_links": [10 "0x162000f3…a3fe53"11 ]12 },13 "0x1620f791…d5ac28": {14 "previous_revision": "0x1620ce6f…b7ce0b",15 "revision_type": "0x162000f3…a3fe53",16 "nonce": "0x4313fd67…e8ec226e",17 "local_timestamp": 1783616148,18 "version": "https://aqua-protocol.org/docs/v4/schema",19 "method": "scalar",20 "payloads": {21 "type": "file",22 "hash": "0xd87ca20f…04450b9d",23 "hash_type": "FIPS_202-SHA3-256",24 "descriptor": "",25 "size": 12,26 "content_type": "text/plain"27 }28 },29 "0x16200ca0…803609": {30 "previous_revision": "0x1620ce6f…b7ce0b",31 "revision_type": "0x1620baf1…8b659a",32 "nonce": "0x43b3b02c…ce008f2e",33 "local_timestamp": 1783616148,34 "version": "https://aqua-protocol.org/docs/v4/schema",35 "method": "scalar",36 "signer": "did:key:z6MkneMkZqwqRiU5mJzSG3kDwzt9P8C59N4NGTfBLfSGE7c7",37 "signature": {38 "signature_type": "ed25519",39 "signature": "0xe52bceee…c170c20d",40 "signature_public_identifier": "0x79b5562e…ad049664"41 }42 }43 },44 "file_index": {45 "0x1620ce6f…b7ce0b": "anchor_0x1620ce",46 "0x1620f791…d5ac28": "test.txt"47 }48}Two differences in your run. First, the SDK hashes object revisions with the tree method by default, so your object revision also carries a leaves array of per-field digests — the fixture above was created with the scalar method, which has no leaves. Second, the fixture's signature revision targets the genesis anchor (its previous_revision names the anchor), while your program signed the tree's tip, so your signature's previous_revision names the object revision. To inspect your own tree, add serde_json = "1" to the dependencies and print serde_json::to_string_pretty(&signed.aqua_tree)? before the verification call.
What just happened
- A genesis anchor declared the tree's type.
create_genesis_revisionbuilt a two-revision tree: a genesis anchor whosestructural_linksname the built-infiletemplate, followed by an object revision typed by that template. The object'spayloadsrecords the content hash, size, and MIME type ofhello.txt— not the content itself. - A signature revision attested to a revision hash.
sign_aqua_treeappended a signature revision branching off the tree's tip — in your program, the object revision. Itssigneris thedid:keyidentity derived from the Ed25519 key, and what it signs includes the target's revision hash — so the signature covers the target's entire content indirectly. - Every link is a multihash. Each revision is stored under the hash of its own canonical form, rendered as
0x+ 68 hex characters.previous_revisionandrevision_typeare such links, and the hash algorithm (SHA3-256 here, codec0x16) travels inside the multihash — revisions carry no algorithm field. revision_typeis a template multihash, never a keyword. The anchor names theanchor_template, the object names thefiletemplate, and the signature names thesignature_ed25519template. Types are content hashes, not strings.- Verification recomputed everything.
verify_aqua_treeresolved the anchor's structural links, recomputed every revision hash against its map key, validated the object's payload against thefiletemplate's JSON Schema, checked the file content by size and hash, and cryptographically verified the signature — failing closed on any mismatch.
Next steps
Core Concepts
The Aqua tree, the four revision kinds, templates, and verification — the mental model behind the three calls you just made
aqua-rs-sdk-core
The full aqua-rs-sdk-core API: typed objects, custom templates, exports, and selective disclosure
Template Registry
Publish and retrieve templates by publisher DID with aqua-template-registry
Audit Trails for AI Agents
Record AI-agent sessions as sequences of signed, individually verifiable artifacts
Protocol Reference
The readable reference for the v4 wire format, backed by the normative protocol specification
Troubleshooting
See also
- Welcome — what Aqua Protocol v4 is and what is published today
- Core Concepts — the data model behind this example
- Release Status & Versioning — release status and scope of the v4 components
- v3 documentation — the stable JavaScript SDK
- aqua-rs-sdk-core on GitHub — source, examples, and the normative protocol specification
