Skip to content

feat(payment): commitment binding fields for quote types (ADR-0004)#11

Merged
grumbach merged 3 commits into
mainfrom
adr-0003-signed-quote-fields
Jul 1, 2026
Merged

feat(payment): commitment binding fields for quote types (ADR-0004)#11
grumbach merged 3 commits into
mainfrom
adr-0003-signed-quote-fields

Conversation

@grumbach

Copy link
Copy Markdown
Contributor

Part of ADR-0003: commitment-bound quote pricing — the shared wire-type layer.

What

Adds the signed fields that bind a quote's price to the node's audited storage commitment:

  • PaymentQuote and MerklePaymentCandidateNode gain committed_key_count: u32 + commitment_pin: Option<[u8; 32]> (tail-placed, serde-default).
  • MerklePaymentProof gains commitment_sidecars: Vec<Vec<u8>>.
  • Both signing payloads are extended to cover the new fields — single-node bytes_for_signing and the merkle candidate bytes_to_sign (now 5-field), with the pin tagged (0 = none, 1 = present) so a baseline quote can't collide with one pinning an all-zero hash.

The two fields are covered by the quote signature and the quote hash, so the price a node may charge is tied to how much data it can prove it holds.

Scope

This is only the shared struct/signing change. The node-side pricing + audit and the client-side resolve-before-pay enforcement live in the companion PRs:

  • ant-protocol: shared commitment + pricing (depends on this)
  • ant-node: node-side forced pricing + audit
  • ant-client: resolve-before-pay

Release ordering

This is the first crate in the ADR-0003 release chain — it has no ADR-0003 dependencies and builds standalone. The other three depend on it being published.

This is a breaking quote-format change (the signed payload changes), per the ADR's hard-cutover rollout.

Add `committed_key_count` and `commitment_pin` to `PaymentQuote` and
`MerklePaymentCandidateNode`, and `commitment_sidecars` to
`MerklePaymentProof`. The two fields bind a quote's price to the node's
audited storage commitment: they are covered by the quote signature and
the quote hash, so the price a node may charge is tied to how much data
it can prove it holds.

Both signing payloads are extended to cover the new fields (single-node
`bytes_for_signing` and the merkle candidate `bytes_to_sign` 5-field
form), with the pin tagged (0 = none, 1 = present) so a baseline quote
cannot collide with one pinning an all-zero hash. New fields are tail-
placed with serde defaults.

This is the shared wire-type half of ADR-0003 (commitment-bound quote
pricing); the node-side pricing/audit and the client-side resolve-before-
pay enforcement live in ant-node and ant-client respectively.
…unning ADR)

The commitment-bound quote pricing ADR clashed with Mick's full-node
shunning ADR, which also took numbers 0002/0003. Renumber the pricing
ADR's references to 0004; no functional change (doc comments only).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@mickvandijke mickvandijke changed the title feat(payment): commitment binding fields for quote types (ADR-0003) feat(payment): commitment binding fields for quote types (ADR-0004) Jul 1, 2026
…ields)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@dirvine dirvine left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the current head a7ac7e2620cb6a50151dd0c619fd75e03b02f05c for evmlib #11.

Verified:

  • Cargo.toml is bumped to 0.9.0 for the breaking signed quote/wire-format change.
  • CHANGELOG.md documents ADR-0004 and the hard-cutover signature incompatibility.
  • PaymentQuote::bytes_for_signing covers committed_key_count and a tagged commitment_pin (None vs Some([0; 32]) cannot collide).
  • PaymentQuote::hash continues to include the signed payload plus pubkey/signature, so the new binding fields are hash-covered.
  • MerklePaymentCandidateNode::bytes_to_sign and to_bytes include the same count/pin binding, so Merkle candidate signatures and pool hashes bind the new fields.
  • Current CI is green: 7/7 checks pass, including dry-run publish.

Local note: cargo test --all --no-fail-fast builds, but Anvil-dependent tests fail locally because anvil is not installed on this runner (SpawnFailed: No such file or directory). Non-Anvil tests that ran passed; GitHub CI has the pinned Foundry setup and is green.

No code issues found in this crate. The remaining blockers from the earlier package review are downstream in ant-protocol/ant-node/ant-client, not in evmlib.

Minor non-blocking nit: the PR body still says ADR-0003 in a few places while the committed files now say ADR-0004.

@grumbach grumbach merged commit 28fc354 into main Jul 1, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants