Skip to content

feat: switch to on-chain offer-based authorization#1009

Draft
MoonBoi9001 wants to merge 12 commits into
main-dipsfrom
mb9/dips-switch-to-offer-authorization
Draft

feat: switch to on-chain offer-based authorization#1009
MoonBoi9001 wants to merge 12 commits into
main-dipsfrom
mb9/dips-switch-to-offer-authorization

Conversation

@MoonBoi9001
Copy link
Copy Markdown
Member

@MoonBoi9001 MoonBoi9001 commented Apr 15, 2026

TL;DR

Authorization for paid indexing agreements moves from an off-chain signature check inside the indexer to an on-chain offer registered by the payer, which the smart contract verifies at acceptance time. This is the indexer-side half of that switch; the consumer half ships as dipper #610. Indexers without escrow accounts will no longer be auto-rejected during the proposal step.

Motivation

When a payer proposes a paid indexing agreement to an indexer, the indexer's service today recovers the signature on the proposal and rejects anything not signed by an address registered in on-chain escrow. The check duplicates what the smart contract already enforces at acceptance time, and it has a side effect: indexers without any escrow accounts get rejected during negotiation before they can even respond on terms.

A new contracts branch shifts authorization to an on-chain step where the payer registers an offer before the agreement can be accepted, and the contract checks the offer's hash at acceptance. That fits the real order of operations — proposals come first, the payer (in dipper #610) only registers the offer after the indexer has accepted terms — so the indexer-side signature check becomes redundant and is removed.

Summary

  • Remove the indexer-side signature check from proposal validation; the contract enforces it later
  • Delete the now-unused signer-validation logic and its tests
  • Drop the escrow-watcher dependency from the proposal handler since the check it fed has gone
  • Add a conditions placeholder to the agreement layout so it matches the audited contract
  • Keep the existing rejection reason on the wire for compatibility, even though no code emits it
  • Rewrite the handler tests on a small wire-bytes helper; add a regression test for the new layout

@graphprotocol graphprotocol deleted a comment from github-actions Bot Apr 15, 2026
@MoonBoi9001 MoonBoi9001 added the DIPs Decentralized Indexing Payments label Apr 17, 2026
@MoonBoi9001 MoonBoi9001 changed the title feat(dips): switch to offer-based RCA authorization feat: switch to on-chain offer-based authorization May 6, 2026
@MoonBoi9001 MoonBoi9001 force-pushed the mb9/dips-switch-to-offer-authorization branch from 810a480 to 2ceb3cf Compare May 6, 2026 14:23
@MoonBoi9001 MoonBoi9001 force-pushed the mb9/dips-price-rejection-logging branch from 1fd9fee to 736e559 Compare May 7, 2026 05:59
@MoonBoi9001 MoonBoi9001 force-pushed the mb9/dips-switch-to-offer-authorization branch from 290a603 to 3488764 Compare May 7, 2026 05:59
@MoonBoi9001 MoonBoi9001 force-pushed the mb9/dips-price-rejection-logging branch from 736e559 to 15d5184 Compare May 7, 2026 06:52
@MoonBoi9001 MoonBoi9001 force-pushed the mb9/dips-switch-to-offer-authorization branch from 3488764 to 36bb71b Compare May 7, 2026 06:52
MoonBoi9001 and others added 10 commits May 7, 2026 14:58
…tion

The Solidity enum IndexingAgreementVersion has V1 as its first variant,
which encodes as 0 in the ABI. The validation check was comparing against
1, causing all valid V1 proposals to be rejected with
UnsupportedMetadataVersion. Test data also updated to use version 0.

Companion to edgeandnode/dipper#583.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When an RCA proposal is rejected, log the rejection reason, error, and
deployment ID (when decodable) at INFO level. Previously the rejection
was returned via the gRPC response with no server-side log at INFO,
making debugging difficult without access to the client.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Log supported networks, recurring collector address, IPFS URL, and
per-network minimum pricing when DIPs is enabled. Previously only
a warning was emitted when supported_networks was empty.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
min_grt_per_30_days is destructured from a reference, so use .iter()
instead of &ref to avoid &&BTreeMap. min_grt_per_billion_entities is
GRT not Option<GRT>, so remove the if-let-Some wrapper.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Price rejection logs now include chain_id (CAIP-2 identifier) and use
structured tracing fields (offered, minimum) instead of format string
interpolation. Makes it easier to filter and query rejection events
in production log aggregation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pins the expected bytes16 output for a fixed set of RCA inputs. The
same test vector exists in dipper (dipper-rpc/src/indexer.rs). If
either repo's derivation drifts, the test fails with a message
pointing to the counterpart.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The on-chain payment-agreement contract gained a new field
between maxSecondsPerCollection and nonce — a set of flags
that declares optional conditions. The off-chain struct mirrors
the on-chain layout for hashing, so it must match exactly.
The proposal validator used to recover a signature from each
incoming proposal and reject anything not signed by an address
registered in on-chain escrow. The smart contract now enforces
that authorization at acceptance time, so the check is removed.
Rename the test helper to describe what it produces (encoded
agreement bytes) rather than the case it was written for. Add
a roundtrip test that encodes and decodes a non-zero conditions
value so a future struct-layout drift is caught immediately.
@MoonBoi9001 MoonBoi9001 changed the base branch from mb9/dips-price-rejection-logging to mb9/dips-observability-improvements May 7, 2026 07:00
@MoonBoi9001 MoonBoi9001 force-pushed the mb9/dips-switch-to-offer-authorization branch from 36bb71b to faa26d4 Compare May 7, 2026 07:00
Base automatically changed from mb9/dips-observability-improvements to main-dips May 8, 2026 03:29
Commit f709cf2 removed signature verification and signer-authorization
from the validation flow. The supporting types stayed behind: the
SignedCancellationRequest / CancellationRequest structs and their
sign/validate impls, the rca_eip712_domain and
dips_cancellation_eip712_domain helpers, and DipsServer's chain_id and
recurring_collector fields. Drop them along with the DipsConfig field,
its startup validation, and the matching maximal-config example entry.

Also align the module-level docs in dips/lib.rs and dips/server.rs with
the validation steps that actually run today.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The test that used FixedBytes was removed earlier when the dead
signature/cancellation code was cleaned up after the offer-authorization
switch. The import survived and now fails clippy with -D warnings on
--all-targets.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

DIPs Decentralized Indexing Payments

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant