fix: compare hashes instead of CIDs for anchor proof validation#754
fix: compare hashes instead of CIDs for anchor proof validation#754
Conversation
The blockchain only stores the 32-byte hash, not the CID codec. When validating single-event anchors where the original event uses dag-jose codec, reconstruction assumed dag-cbor, causing validation failure. Since the security property we care about is that the hash matches, compare hashes directly rather than full CIDs.
stbrody
left a comment
There was a problem hiding this comment.
So it feels like the code is making some incorrect assumptions about the codec right now
Probably the "right" fix would be to update the ChainInclusionProof to store the hash instead of the Cid, since we can't reliably reconstruct the full Cid if the blockchain txn doesn't include the codec.
That said, this seems like a perfectly fine workaround and is definitely the quicker fix, so LGTM
Yeah agreed. I don't think this is a new bug, probably CAS never anchored a single-node tree so this wasn't hit before self-anchoring. At least I think the merkle tree construction is the same implementation. The main benefit of fixing the validation instead is that nodes can auto-heal these events on a version bump. Otherwise, it seems like every node needs to do manual intervention not to have the concluder endlessly failing to validate the affected events. |
The blockchain only stores the 32-byte hash, not the CID codec. When single event batches are anchored, no tree node wrapper is added so the proof is just the raw (
dag-jose) event CID. However, the validation reconstruction assumed the codec to bedag-cbor(what is used to encode the tree), causing validation failures even for the node that did the anchoring (as well as others).Since the security property we care about is that the hash matches, this patch instead compares the hashes directly rather than full CIDs.
Here are the logs from our node anchoring a single event, then immediately getting the concluder stuck in a loop, failing to validate it:
{ "timestamp": "2025-12-19T13:49:10.002266Z", "level": "INFO", "fields": { "message": "Anchoring root CID: bagcqcerapdx4z23gwfeyowfq3q7n7orcrqnafwtbz6wdkijgqdjy2mgxgzuq on chain 100" }, "target": "ceramic_anchor_evm::evm_transaction_manager" } { "timestamp": "2025-12-19T13:49:10.161033Z", "level": "INFO", "fields": { "message": "Connected to EVM chain with ID: 100" }, "target": "ceramic_anchor_evm::evm_transaction_manager" } { "timestamp": "2025-12-19T13:49:10.197830Z", "level": "INFO", "fields": { "message": "Starting wallet balance: 23476419449376212335 wei" }, "target": "ceramic_anchor_evm::evm_transaction_manager" } { "timestamp": "2025-12-19T13:56:11.821410Z", "level": "INFO", "fields": { "message": "Anchor transaction submitted: 0x2ea17b24e5ebc069cc5ab69706f0d82011a560dd7fabf69960af3483eda1b7a6" }, "target": "ceramic_anchor_evm::evm_transaction_manager" } { "timestamp": "2025-12-19T13:56:31.842508Z", "level": "INFO", "fields": { "message": "Transaction 0x2ea17b24e5ebc069cc5ab69706f0d82011a560dd7fabf69960af3483eda1b7a6 confirmed with 4 confirmations" }, "target": "ceramic_anchor_evm::evm_transaction_manager" } { "timestamp": "2025-12-19T13:56:31.864128Z", "level": "INFO", "fields": { "message": "Ending wallet balance: 23476419390560577133 wei" }, "target": "ceramic_anchor_evm::evm_transaction_manager" } { "timestamp": "2025-12-19T13:56:31.864165Z", "level": "INFO", "fields": { "message": "Total gas cost: 58815635202 wei" }, "target": "ceramic_anchor_evm::evm_transaction_manager" } { "timestamp": "2025-12-19T13:56:31.864218Z", "level": "INFO", "fields": { "message": "store anchor batch: proof=bafyreibssfsa2l6od43y3nok4ioo33xorp2eryvsbd6kscvsm6ty3fxbrm, events=1" }, "target": "ceramic_anchor_service::anchor" } { "timestamp": "2025-12-19T13:56:32.811501Z", "level": "WARN", "fields": { "message": "failed to poll_next_batch of conclusion_events", "err": "Execution error: Application error encountered: Failed to discover chain proof: InvalidProof(\"the root CID is not in the transaction (anchor proof root=bagcqcerapdx4z23gwfeyowfq3q7n7orcrqnafwtbz6wdkijgqdjy2mgxgzuq, blockchain transaction root=bafyreibapdx4z23gwfeyowfq3q7n7orcrqnafwtbz6wdkijgqdjy2mgxgy)\")" }, "target": "ceramic_pipeline::concluder" } { "timestamp": "2025-12-19T13:56:33.743869Z", "level": "WARN", "fields": { "message": "failed to poll_next_batch of conclusion_events", "err": "Execution error: Application error encountered: Failed to discover chain proof: InvalidProof(\"the root CID is not in the transaction (anchor proof root=bagcqcerapdx4z23gwfeyowfq3q7n7orcrqnafwtbz6wdkijgqdjy2mgxgzuq, blockchain transaction root=bafyreibapdx4z23gwfeyowfq3q7n7orcrqnafwtbz6wdkijgqdjy2mgxgy)\")" }, "target": "ceramic_pipeline::concluder" }