Witness Revision
Schema specification for Witness Revisions in Aqua Protocol v4
Witness Revision
A Witness Revision provides cryptographic proof that a revision existed at a specific point in time. It anchors revision hashes to external systems like blockchains (Ethereum), decentralized networks (Nostr), or Trusted Timestamping Authorities (TSA). This creates an immutable, verifiable timestamp that cannot be backdated.
Overview
Witness revisions provide:
- Timestamping: Cryptographic proof of when a revision existed
- Immutability: Blockchain or TSA anchoring prevents backdating
- Verifiability: Anyone can verify the witness independently
- Batch Efficiency: Multiple revisions can be witnessed in a single transaction via Merkle trees
- Decentralization: Uses public blockchains or decentralized networks
Schema Structure
Common Fields
| Field | Type | Required | Description |
|---|---|---|---|
previous_revision | string | Yes | Hash reference to the revision being witnessed |
revision_type | string | Yes | Always "witness" for witness revisions |
nonce | string | Yes | Random 16-byte hex string for uniqueness |
local_timestamp | number | Yes | Unix timestamp when the witness was created locally |
version | string | Yes | Protocol version: "https://aqua-protocol.org/docs/v4/schema" |
method | string | Yes | Canonicalization method: "scalar" (typical) or "tree" |
hash_type | string | Yes | Hash algorithm: "FIPS_202-SHA3-256" |
witness | object | Yes | Witness value object containing proof details |
Witness Value Object
The witness field contains details about the witnessing transaction:
| Field | Type | Required | Description |
|---|---|---|---|
merkle_proof | array | Yes | Array of hex strings forming the Merkle proof path |
sender_account_address | string | Yes | Address that submitted the witness transaction |
transaction_hash | string | Yes | Transaction hash on the blockchain or network |
smart_contract_address | string | Yes | Address of the witness contract (or endpoint URL) |
network | string | Yes | Network identifier: "mainnet", "sepolia", "holesky", "tsa", or "nostr" |
merkle_root | string | Yes | Root hash of the Merkle tree stored on-chain |
timestamp | number | Yes | Unix timestamp from the blockchain/network |
Network Types
1. Ethereum Networks
Mainnet
- Network:
"mainnet" - Purpose: Production witnessing on Ethereum mainnet
- Cost: Higher gas fees
- Security: Maximum security and permanence
Sepolia (Testnet)
- Network:
"sepolia" - Purpose: Testing and development
- Cost: Free testnet ETH
- Security: Testnet only, subject to resets
Holesky (Testnet)
- Network:
"holesky" - Purpose: Testing and development
- Cost: Free testnet ETH
- Security: Testnet only, newer Ethereum testnet
2. Trusted Timestamping Authority (TSA)
- Network:
"tsa" - Purpose: RFC 3161 compliant timestamping
- Provider: DigiCert or other TSA services
- Verification: Via TSA public certificates
3. Nostr
- Network:
"nostr" - Purpose: Decentralized social network timestamping
- Verification: Via Nostr relays and events
- Cost: Typically free
Example
Ethereum Witness (Sepolia)
1{2 "previous_revision": "0x3f8a7b2c9d1e4f5a6b8c0d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a",3 "revision_type": "witness",4 "nonce": "0x7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f",5 "local_timestamp": 1704067200,6 "version": "https://aqua-protocol.org/docs/v4/schema",7 "method": "scalar",8 "hash_type": "FIPS_202-SHA3-256",9 "witness": {10 "merkle_proof": [11 "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",12 "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",13 "0x567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234"14 ],15 "sender_account_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb8",16 "transaction_hash": "0x9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",17 "smart_contract_address": "0x5FbDB2315678afecb367f032d93F642f64180aa3",18 "network": "sepolia",19 "merkle_root": "0xa3bf4f1b2b0b822cd15d6c15b0f00a089f86d081884c7d659a2feaa0c55ad015",20 "timestamp": 170406725021 }22}Single Revision Witness
When witnessing a single revision (no batching), the Merkle proof is empty:
1{2 "previous_revision": "0x3f8a7b2c9d1e4f5a6b8c0d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a",3 "revision_type": "witness",4 "nonce": "0x9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b",5 "local_timestamp": 1704070800,6 "version": "https://aqua-protocol.org/docs/v4/schema",7 "method": "scalar",8 "hash_type": "FIPS_202-SHA3-256",9 "witness": {10 "merkle_proof": [],11 "sender_account_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb8",12 "transaction_hash": "0x8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d",13 "smart_contract_address": "0x5FbDB2315678afecb367f032d93F642f64180aa3",14 "network": "mainnet",15 "merkle_root": "0x3f8a7b2c9d1e4f5a6b8c0d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a",16 "timestamp": 170407085017 }18}Note: When merkle_proof is empty, merkle_root equals previous_revision.
Merkle Tree Batching
To reduce costs, multiple revisions can be witnessed in a single transaction using Merkle trees.
Process
- Collect Revisions: Gather multiple revision hashes to witness
- Build Merkle Tree: Create a Merkle tree from the revision hashes
- Submit Root: Submit only the Merkle root to the blockchain
- Generate Proofs: For each revision, generate its Merkle proof
- Create Witnesses: Create witness revisions with proofs
Example: Witnessing 4 Revisions
Revision Hashes:
- Rev1: 0xaaaa...
- Rev2: 0xbbbb...
- Rev3: 0xcccc...
- Rev4: 0xdddd...
Merkle Tree:
Root
/ \
H12 H34
/ \ / \
Rev1 Rev2 Rev3 Rev4
Submit to blockchain: Root hash only
Witness for Rev1:
merkle_proof: [H12's sibling (Rev2), H12's parent's sibling (H34)]
merkle_root: Root
Proof Verification
To verify a revision was witnessed:
- Start with revision hash
- Apply Merkle proof hashes (sibling hashes)
- Compute up the tree to get root
- Verify computed root matches
merkle_root - Verify
merkle_rootis on blockchain attransaction_hash
Validation Rules
A Witness Revision is valid if:
- Structure: Contains all required fields with correct types
- Revision Type: The
revision_typeis exactly"witness" - Previous Revision: References a valid existing revision
- Network: One of the supported network values
- Timestamp Consistency:
witness.timestampshould be close tolocal_timestamp- Both should be reasonable (not far in future)
- Merkle Proof: If present, must be valid array of hex strings
- Transaction Verification: The
transaction_hashexists on the specifiednetwork - Merkle Root Verification: If batched, Merkle proof must lead to merkle_root
- On-Chain Verification: The
merkle_rootis stored at thesmart_contract_addressin the transaction - Address Format: All addresses must be valid hex strings
Witness Smart Contract
Ethereum Contract Interface
The witness contract typically has a method like:
1function witness(bytes32 merkleRoot) public returns (bool)Verification Process
- Query blockchain for transaction at
transaction_hash - Verify transaction called the
smart_contract_address - Extract the witnessed value (merkle_root) from transaction data
- Verify it matches the
merkle_rootin the witness revision - Check transaction timestamp matches
timestampfield
Common Use Cases
1. Document Notarization
Document Object → Signature → Witness (Ethereum)
Proves the document existed and was signed at a specific time.
2. Batch Processing
100 Documents → Compute Hashes → Build Merkle Tree → Single Witness Transaction
Economical witnessing of many documents at once.
3. Legal Evidence
Evidence Object → Signature (Parties) → Witness (Mainnet)
Creates tamper-proof timestamp for legal proceedings.
4. Supply Chain
Shipment Event → Witness (Every checkpoint) → Audit Trail
Immutable record of supply chain events.
5. Credential Issuance
VC Issuance → Signature (Issuer) → Witness (Public verification)
Publicly verifiable credential issuance timestamps.
Timestamp Interpretation
local_timestamp
- Created by client when preparing witness revision
- Not trusted (can be manipulated)
- Used for user display and rough ordering
witness.timestamp
- Provided by blockchain/TSA
- Trusted (immutable on-chain)
- Authoritative time proof
- Should be used for verification and legal purposes
Best Practice: Always use witness.timestamp for critical timestamp verification.
Cost Considerations
Ethereum
| Network | Cost | When to Use |
|---|---|---|
| Mainnet | ~$5-50 per transaction | Production, legal, high-value |
| Sepolia | Free (testnet) | Development, testing |
| Holesky | Free (testnet) | Development, testing |
Gas Optimization: Batch multiple witnesses into one transaction using Merkle trees.
TSA
- Typically $0.10-1.00 per timestamp
- Good for compliance requirements
- RFC 3161 standard
Nostr
- Free (decentralized network)
- Lower trust than blockchain
- Good for social proof
Implementation Notes
Creating a Witness Revision
- Identify the revision(s) to witness
- Choose network (mainnet, sepolia, etc.)
- If batching, build Merkle tree
- Submit transaction to blockchain
- Wait for transaction confirmation
- Extract transaction details
- Generate Merkle proofs (if batched)
- Create witness revision(s)
Verifying a Witness Revision
Single Revision (No Batching)
1. Verify merkle_proof is empty
2. Verify merkle_root equals previous_revision
3. Query blockchain for transaction_hash
4. Verify transaction exists and is confirmed
5. Extract witnessed value from transaction
6. Verify it matches merkle_root
7. Check transaction timestamp
Batched Revision
1. Verify merkle_proof is non-empty
2. Compute Merkle root using proof and previous_revision
3. Verify computed root matches merkle_root
4. Query blockchain for transaction_hash
5. Verify merkle_root is stored on-chain
6. Validate transaction timestamp
Error Handling
Common issues and solutions:
| Issue | Solution |
|---|---|
| Transaction not found | Wait longer (may not be confirmed yet) |
| Wrong network | Check transaction on correct network |
| Merkle proof invalid | Regenerate proof from original tree |
| Timestamp mismatch | Check blockchain time vs local time |
| Gas estimation failed | Check wallet balance and gas price |
Security Considerations
1. Network Selection
- Use mainnet for production/legal purposes
- Use testnets only for development
- Consider compliance requirements
2. Confirmation Depth
- Wait for sufficient confirmations (6+ for mainnet)
- More confirmations = higher security
- Balance security vs speed requirements
3. Merkle Proof Storage
- Store proofs securely
- Without proof, batched witness can't be verified
- Consider proof backup strategies
4. Timestamp Trust
- Trust blockchain timestamp over local_timestamp
- Account for block time variability
- Consider block reorganizations
5. Cost Management
- Batch witnesses to reduce costs
- Monitor gas prices
- Use appropriate network for use case
Advanced Topics
Multi-Network Witnessing
Witness the same revision on multiple networks for redundancy:
Object → Signature → Witness (Ethereum) → Witness (Nostr) → Witness (TSA)
Each witness provides independent proof.
Periodic Re-Witnessing
For long-term preservation, periodically re-witness important revisions:
2024: Object → Witness (Mainnet)
2025: Link to Object → Witness (Mainnet)
2026: Link to 2025 → Witness (Mainnet)
Cross-Chain Verification
Witness on multiple blockchains for increased trust:
Object → Witness (Ethereum Mainnet) → Witness (Polygon) → Witness (Arbitrum)
Relationship with Other Revisions
- Object Revisions: Primary target for witnessing
- Signature Revisions: Often witnessed after signing
- Link Revisions: Can be witnessed to prove connection timestamp
- Template Revisions: Rarely witnessed (they're standalone)
See Also
- Object Revision - What typically gets witnessed
- Signature Revision - Often combined with witnessing
- RFC 3161 - Timestamping - TSA standard
- Ethereum Smart Contracts - On-chain witnessing
- Merkle Trees - Batch witnessing structure
