Blockchain Anchoring
Anchoring creates an immutable audit trail for important events or payloads by writing a compact reference to a blockchain. TrustWeave standardises the experience so you can leverage tamper evidence without becoming a chain expert.
1
2
3
4
dependencies {
implementation("org.trustweave:anchors-anchor-core:0.6.0")
implementation("org.trustweave:common:0.6.0")
}
Result: Adds the anchoring registry and clients to your project so the examples below compile.
Why anchor data?
- Integrity – recompute a digest and compare it to the anchor; any change breaks the link.
- Provenance – the anchor’s block height or timestamp proves when the information existed.
- Portability –
AnchorRefstructures capture chain ID, transaction hash, optional contract/app ID, and metadata that verifiers can consume.
Anchoring complements verifiable credentials: you can notarise VC digests, presentation receipts, workflow checkpoints—anything that needs an immutable trail.
How TrustWeave anchors payloads
| Step | Implementation |
|---|---|
| 1. Choose a chain | Register a BlockchainAnchorClient (in-memory, Algorand, Polygon, Ethereum, Base, Arbitrum, Indy, or your own adapter). Chains use CAIP-2 IDs such as algorand:testnet. |
| 2. Canonicalise payload | Kotlinx Serialization + JSON Canonicalization Scheme ensure deterministic bytes. |
| 3. Submit | writePayload stores the digest on chain and returns AnchorResult with an AnchorRef. |
| 4. Verify | readPayload rehydrates the JSON, or recompute the digest locally and compare to the stored reference. |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import kotlinx.coroutines.runBlocking
import org.trustweave.trust.TrustWeave
import org.trustweave.credential.model.vc.VerifiableCredential
import org.trustweave.anchor.exceptions.BlockchainException
runBlocking {
val trustWeave = TrustWeave.build { /* configure kms, did, anchor, ... */ }
val anchorResult = trustWeave.blockchains.anchor(
data = credential,
serializer = VerifiableCredential.serializer(),
chainId = "algorand:testnet"
)
println("Anchored tx: ${anchorResult.ref.txHash}")
try {
val anchor = trustWeave.blockchains.anchor(credential, VerifiableCredential.serializer(), "algorand:testnet")
println("Anchored tx: ${anchor.ref.txHash}")
} catch (e: BlockchainException.ChainNotRegistered) {
println("Chain not registered: ${e.chainId}; available: ${e.availableChains}")
}
}
Configuring clients
- In-memory – perfect for tutorials and unit tests.
- Algorand – use
AlgorandBlockchainAnchorClientOptions(algodUrl,algodToken, optional private key). - Polygon / Ganache – specify RPC endpoints, signer keys, and (optionally) contract addresses.
- Indy – configure pool parameters and wallet credentials for permissioned ledgers.
- Custom – implement
BlockchainAnchorClientorBlockchainAnchorClientProvider(discovered via SPI).
Reading and verifying
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import kotlinx.coroutines.runBlocking
import org.trustweave.trust.TrustWeave
import org.trustweave.credential.model.vc.VerifiableCredential
import org.trustweave.anchor.exceptions.BlockchainException
runBlocking {
val trustWeave = TrustWeave.build { /* configure kms, did, anchor, ... */ }
val data = trustWeave.blockchains.read(
ref = anchorRef,
serializer = VerifiableCredential.serializer()
)
println("Read credential: ${data.id}")
try {
val payload = trustWeave.blockchains.read(anchorRef, VerifiableCredential.serializer())
println("Read: ${payload.id}")
} catch (e: BlockchainException.ChainNotRegistered) {
println("Chain not registered: ${e.chainId}")
}
}
blockchains.readreturns the deserialized value or throwsBlockchainException(for example if the chain is not registered).- For higher assurance, recompute the digest from the canonical payload and compare it to the data stored on chain.
- Keep connection credentials (RPC tokens, private keys) in a secret store for production deployments.
Practical usage tips
- Persist AnchorRefs with credentials so verifiers can revalidate without bespoke lookups.
- Retry-friendly anchoring – public chains may require exponential back-off; design idempotent submissions.
- Integrate with revocation – anchor revocation lists or proofs to create audit trails for credential status changes.
- Testing – use the in-memory client or spin up Ganache/Testnet clients for end-to-end tests.
- Error handling – anchoring uses
AnchorResulton success and throwsBlockchainExceptionon many failures. See Error handling. - Input validation – TrustWeave automatically validates chain ID format and registration before anchoring.
See also
- Blockchain Anchor Integration Guides – Implementation guides for Algorand, Ethereum, Base, Arbitrum, Polygon, and Ganache
- Quick Start – Step 5 for an end-to-end example.
- Wallet API Reference – Anchoring helpers for wallet-integrated flows.
- Architecture Overview for the DID ➜ credential ➜ anchor flow.
- Verifiable Credentials to understand what you may want to anchor.
- Blockchain-Anchored Revocation for anchoring credential revocation status lists.
Related How-To Guides
- Anchor to Blockchain - Step-by-step guide for anchoring data to blockchains
Explore integrations:
- Blockchain Integrations - Algorand, Polygon, Ethereum, and more
- Use Case Scenarios - Real-world anchoring examples