Governance Metadata - On-Chain Binding
Abstract
This CIP extends CIP-0100 | Governance Metadata to introduce a standardized onChain property.
The onChain property encapsulates the on-chain effects using CIP-0116 | Standard JSON encoding for Domain Types standard encoding,
enabling verification that metadata content matches on-chain action and preventing metadata replay attacks.
This can be applied to all types of governance metadata, including governance actions, votes, DRep registrations/updates, and Constitutional Committee resignations.
Motivation: Why is this CIP necessary?
Without a standardized mechanism to bind metadata to specific on-chain effects, there are potential security vulnerabilities in metadata replay attacks and multi-author misattachment.
Vulnerability have been discussed via CIPs Issue #970 by Crypto2099 and further within CIPs Issue #978 by gitmachtl.
Metadata Replay
A malicious actor could;
- Copy the metadata from a legitimate treasury withdrawal governance action
- Modify only the withdrawal destination address in the on-chain action
- Submit this as a new governance action with the copied metadata
From a voter's perspective, examining the metadata would show legitimate content (proper title, abstract, rationale, references, and author signatures). However, the actual on-chain effect would send funds to a different, malicious address.
In high-volume voting environments such attacks could succeed if voters don't manually verify that the metadata matches the on-chain effects. Relying on manual verification by voters is error prone and inefficient.
Multi-Author Misattachment
When metadata is jointly authored multiple parties signing the same body before the on-chain action is constructed there is a window between signing and submission in which the signed payload can be attached to the wrong on-chain effect.
Concretely, consider a multi-author treasury withdrawal:
- Authors A, B, and C draft and sign metadata describing a withdrawal of ₳50,000 to address
stake1...legit. - Author C, who controls submission, swaps the on-chain
ProposalProcedureto send the funds elsewhere or to a different recipient in a list of withdrawals and submits using the original signed metadata. - Verifiers see three valid author signatures over a body that describes the legitimate withdrawal, but the actual on-chain effect differs.
Without onChain,
the author signatures only attest to the prose narrative.
Anchoring the signed body to the exact on-chain effect closes this gap: any divergence between the bound onChain value and the submitted action invalidates the binding,
and tools can refuse to display the metadata as endorsed.
Specification
The onChain Property
The onChain property is a new optional property within the body object of CIP-0100 governance metadata.
JSON-LD Context
The onChain property is defined in the JSON-LD @context under the CIP169 namespace.
Its context maps the well-known CIP-0116 governance terms (deposit, reward_account,
gov_action, rewards, constitution, credentials, voter, …) explicitly, and adds a
@vocab default so that every other reachable term — nested, or added by a future
CIP-0116 revision — still resolves to a CIP-0116 IRI (see
cip-0169.common.jsonld for the complete context):
{
"@context": {
"CIP116": "https://github.com/cardano-foundation/CIPs/blob/master/CIP-0116/README.md#",
"CIP169": "https://github.com/cardano-foundation/CIPs/blob/master/CIP-0169/README.md#",
"body": {
"@id": "CIP100:body",
"@context": {
"onChain": {
"@id": "CIP169:onChain",
"@context": {
"@vocab": "https://github.com/cardano-foundation/CIPs/blob/master/CIP-0116/README.md#",
"deposit": "CIP116:deposit",
"reward_account": "CIP116:reward_account",
"gov_action": { "@id": "CIP116:gov_action", "@context": { "...": "..." } }
}
}
}
}
}
}The @vocab default is deliberate and important: any term left undefined would be dropped
during canonicalization, which would silently exclude part of the on-chain payload from the
author signature and defeat the purpose of this CIP. Explicit mappings keep the well-known
structure self-documenting with precise IRIs, while @vocab guarantees no term — at any
nesting depth — can ever be silently dropped.
A real document merges this fragment with its downstream body vocabulary (CIP-108/119/136); see test-vector.md for full worked examples.
Note
This CIP uses CIP169 as the namespace identifier for the onChain property itself, while every property inside onChain lives in the CIP116 namespace.
Structure
The onChain property MUST conform to one of the CIP-0116 Conway-era governance types listed below.
Field names and discriminator values follow CIP-0116 verbatim,
snake_case property names (e.g. reward_account, gov_action, gov_action_id) and a tag discriminator carrying snake_case enum values (e.g. treasury_withdrawals_action, register_drep).
Inner certificate/governance-action variants are discriminated by their own tag field per CIP-0116.
Warning
The anchor property MUST be omitted from any CIP-0116 object whose anchor points to this metadata document. Including such an anchor would create a circular dependency, and it is not part of the on-chain effect being verified.
This applies to:
ProposalProcedure.anchor- The inner
VotingProcedure.anchor(when present) register_drep,update_drep, andresign_committee_coldcertificateanchorfields
Exception: Constitution.anchor (inside new_constitution actions) is retained. That anchor points to the constitution document itself a separate artifact from the governance metadata.
Supported Types
For Governance Actions:
The onChain property conforms to the CIP-0116 ProposalProcedure type (without anchor),
whose gov_action field's tag is one of the Conway-era governance action types:
info_actionparameter_change_actionhard_fork_initiation_actiontreasury_withdrawals_actionno_confidenceupdate_committeenew_constitution
See CIP-0116 cardano-conway.json for complete type definitions.
For Votes:
The onChain property conforms to the CIP-0116 VotingProcedures type; a map of Voter → GovActionId → VotingProcedure.
Reusing the existing CIP-0116 container naturally binds the metadata to the (voter, action, vote) tuple(s) being attested without introducing a CIP-0169-specific wrapper type.
For DRep Registration:
The onChain property conforms to the CIP-0116 register_drep certificate (without anchor).
For DRep Update:
The onChain property conforms to the CIP-0116 update_drep certificate (without anchor).
For Committee Cold Credential Resignation:
The onChain property conforms to the CIP-0116 resign_committee_cold certificate (without anchor).
Verification Process
Tools SHOULD implement the following verification when processing CIP-0169 metadata:
- Parse On-Chain Data: Extract the on-chain data which the metadata is attached to
- Parse Metadata: Retrieve and parse the governance metadata
- Author Signature Check: Validate the author signatures are all correct
- Compare: Verify that
body.onChainmatches the actual on-chain effect - Alert: If the
onChaindoes not match or author signatures invalid, warn the user
See test-vector.md for worked negative vectors of both a schema failure (a forbidden self-referential anchor) and an on-chain mismatch (a metadata replay that only step 4 can catch).
Examples
Worked examples with reproducible hashes and populated author signatures are documented in
test-vector.md. They cover governance actions (info_action,
parameter_change_action, treasury_withdrawals_action, new_constitution), votes (DRep and
Constitutional Committee), and certificates (register_drep, update_drep,
resign_committee_cold), plus negative vectors. The raw files are in examples/.
Validation
The schema uses JSON Schema 2020-12 and references the CIP-0116 Conway domain types.
Validate an instance with ajv-cli. Note that
ajv-cli selects its input parser from the file extension, so validate a .json copy of the
.jsonld example:
cp examples/treasury-withdrawal.jsonld /tmp/example.json
ajv validate --spec=draft2020 \
-s cip-0169.common.schema.json \
-r ../CIP-0116/cardano-conway.json \
-d /tmp/example.json \
--all-errors --strict=false-r registers the referenced CIP-0116 schema so $refs resolve offline.
--strict=false allows the OpenAPI-style discriminator keyword (advisory, not enforced).
The documents under examples/invalid/ are expected to fail validation.
Rationale: How does this CIP achieve its goals?
By including the on-chain effects within the signed metadata body using the onChain property.
Metadata is bound to specific on-chain effects,
with author signature cryptographically locking it in.
This makes any metadata replay attacks, machine detectable.
This allows governance tools to automatically verify this for voters.
Why Extend CIP-0100?
CIP-0100 provides the base structure for governance metadata. This extension optionally adds security-critical information while maintaining backward compatibility.
Why Use CIP-0116 Encoding?
CIP-0116 provides standardized JSON encoding for Cardano domain types, allowing the reuse of existing tooling.
Why Exclude the Self-Referential Anchor?
ProposalProcedure, VotingProcedure, and the DRep / committee resignation certificates each carry an anchor whose URL and hash point at this metadata document.
Embedding that anchor inside the metadata it describes would create a circular dependency — the document would have to be hashed before it could be assembled.
It also adds nothing to verification: the verifier already has the document in hand, so a pointer to it is redundant.
These self-referential anchors are therefore excluded from the onChain encoding.
All other CIP-0116 properties — including anchors that point to other artifacts — are retained.
The notable example is Constitution.anchor inside a new_constitution action: it points to the constitution document, which is a separate artifact from the governance metadata,
and is itself part of the on-chain effect being voted on.
That anchor is kept as-is.
Open Questions
- Whether downstream metadata CIPs (CIP-108, CIP-119, CIP-136) should
requireonChainonce tooling adopts it, or keep it optional indefinitely. Making it required is a hard backward-compatibility break and probably best deferred.
Path to Active
Acceptance Criteria
This CIP is considered Active when:
- The specification is merged into the CIPs repository
- At least two governance metadata authoring tools implement support
- At least three governance verification tool implements on-chain comparison
- Examples are available
- Illustrative examples and test vectors via /examples/ and test-vector.md
- Live Preview testnet examples with verbatim signed documents in /examples/preview/
Implementation Plan
- Create Typescript Library for CIP-0169 metadata creation and validation
- Add CIP-0169 validation to a governance/transaction inspection tool
- Add to a CLI governance building tool
Copyright
This CIP is licensed under CC-BY-4.0.