Draft
Conversation
…RCA (#942) * feat(dips): implement SignedRCA validation and storage Implement RecurringCollectionAgreement (RCA) protocol for DIPS, aligned with the on-chain IndexingAgreement contract. Changes: - RcaStore trait and PostgreSQL implementation for RCA storage - EIP-712 signature verification via escrow-based authorization - validate_and_create_rca() with full validation pipeline: signature, IPFS manifest, network, pricing, deadline/expiry - Database migration for pending_rca_proposals table The indexer agent queries pending_rca_proposals directly and decides acceptance on-chain via RecurringCollector contract. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(dips): improve configuration ergonomics and validation - Add #[serde(default)] to DipsConfig for minimal config files - Validate recurring_collector != Address::ZERO at startup - Warn when tokens_per_second is empty (all proposals rejected) - Bump pricing rejection logs to info level for visibility Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs(dips): add module-level documentation Add comprehensive documentation explaining architecture, validation flow, trust model, and component responsibilities. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test(dips): expand unit test coverage to 43 tests Add comprehensive test suite with AAA pattern: - validate_and_create_rca: 11 tests covering all validation paths - PriceCalculator: 7 tests (previously 0) - SignerValidator implementations: 5 tests - Test doubles: FailingIpfsFetcher, FailingRcaStore, RejectingSignerValidator Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(dips): add IPFS fetch timeout and retry with backoff Add resilience to IPFS manifest fetching: - 30 second timeout per attempt - Up to 4 attempts with exponential backoff (10s, 20s, 40s) - Worst case: ~190 seconds before rejection Dipper gRPC timeout should be >= 220s. See edgeandnode/dipper#557. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
…etworks (#947) * feat(dips): improve config ergonomics with GRT pricing and explicit networks Changes human-readable GRT per 30 days pricing config and adds explicit network support list. Addresses #943 and #944. Config changes: - Add supported_networks list (proposals for unlisted networks rejected) - Add min_grt_per_30_days per-network base pricing (GRT/30 days) - Add min_grt_per_million_entities_per_30_days global entity pricing - Add 90+ networks with calculated pricing examples from IISA model Pricing derived from archive node costs (storage $25/TB, memory $1.50/GB, CPU $10/vCPU) divided by expected subgraph count per indexer. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test(dips): add startup validation tests and fix backoff comment - Fix IPFS retry comment: actual delays are 10s, 20s, 40s (not 1s, 2s, 4s) - Add 5 tests for DIPS startup validation: - test_dips_absent_in_minimal_config - test_dips_config_defaults_recurring_collector_zero - test_dips_config_defaults_empty_supported_networks - test_dips_partial_config_uses_defaults - test_dips_maximal_config_parses Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(dips): use ceiling division to protect indexer minimums When converting GRT/30days to wei/second, truncating division caused indexers to accept slightly less than their configured minimum (up to 0.2% loss). Changed to ceiling division so minimums round UP, ensuring indexers never accept offers below their stated price floor. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
When Dipper sends an RCA and times out (network partition, crash after INSERT but before response), it retries. Previously, the retry failed with a duplicate key error, causing Dipper to mark the agreement as failed even though it was stored successfully. Now uses ON CONFLICT DO NOTHING so retries succeed. Both first attempt and retry return success, enabling Dipper to safely retry without creating inconsistent state. Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
…n reasons (#954) * feat(dips): add /dips/info endpoint and rejection reasons to gRPC Add a public /dips/info HTTP endpoint on port 7600 that advertises the indexer's DIPS pricing configuration (min GRT per 30 days per network, min GRT per million entities, supported networks, and protocol version). This allows the Dipper to discover indexer pricing before sending RCA proposals. Update the gRPC protobuf to include a RejectReason enum on SubmitAgreementProposalResponse, distinguishing PRICE_TOO_LOW from OTHER rejection reasons. The server maps DipsError::TokensPerSecondTooLow and TokensPerEntityPerSecondTooLow to PRICE_TOO_LOW, with all other errors mapped to OTHER. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(dips): gate EscrowSignerValidator behind db feature The signers module was importing indexer_monitor unconditionally, but that crate is only available with the db feature. This caused compilation failures when using only the rpc feature (as dipper does). Changes: - Move EscrowSignerValidator and its imports into a conditionally compiled module (#[cfg(feature = "db")]) - Keep SignerValidator trait, NoopSignerValidator, and RejectingSignerValidator always available since they have no external dependencies - Gate escrow validator tests with #[cfg(all(test, feature = "db"))] - Restore dips_cancellation_eip712_domain function that was accidentally removed during the V2 migration (needed for backwards compatibility) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(dips): rename proto enum values to follow naming conventions The protobuf convention is to prefix enum values with the enum name. Changed PRICE_TOO_LOW -> REJECT_REASON_PRICE_TOO_LOW and OTHER -> REJECT_REASON_OTHER to match REJECT_REASON_UNSPECIFIED. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test(dips): add unit tests for reject_reason_from_error Tests verify the mapping from DipsError variants to RejectReason: - TokensPerSecondTooLow -> PriceTooLow - TokensPerEntityPerSecondTooLow -> PriceTooLow - All other errors (UnsupportedNetwork, InvalidSignature, etc.) -> Other Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(dips): extract GRT formatting to helper function The format_grt() function converts wei (10^-18 GRT) to a human-readable GRT string with up to 18 decimal places, trimming trailing zeros. This removes duplicated formatting logic in the dips_info_state setup. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test(dips): add tests for GRT formatting edge cases Tests cover: - Zero value - Whole numbers (1, 1000 GRT) - Small values less than 1 GRT (0.5 GRT) - Very small values (1 wei = 0.000000000000000001 GRT) - Mixed values with decimals - Trailing zeros are trimmed - Values with many decimal places - Large values with decimals Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: apply nightly rustfmt * fix: use maybe_dips_info for optional builder field * fix: make DipsInfoResponse and DipsInfoPricing public * chore: remove dips_version field from /dips/info response V1 never existed in production, so versioning is unnecessary. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: use GRT per billion entities instead of per million The entity pricing unit has been changed from "GRT per million entities" to "GRT per billion entities" for better human readability. At scale, "0.2 GRT per million entities" sounds negligible but actually translates to ~$4.50/TB/month - a meaningful cost that indexers might overlook. Using "200 GRT per billion entities" makes the cost more apparent. Changes: - Config: min_grt_per_million_entities_per_30_days -> min_grt_per_billion_entities_per_30_days - Default value: 0.2 -> 200 (same economics, just different unit) - /dips/info endpoint: field renamed in response - Internal conversion divisor: 1_000_000 -> 1_000_000_000 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(dips): add SIGNER_NOT_AUTHORISED rejection reason (#961) SignerNotAuthorised errors were mapped to RejectReason::Other, which causes dipper to block the indexer for 30 days. Signer authorization is a transient config issue that resolves once the operator registers the signer on the escrow contract, so a dedicated rejection reason allows dipper to apply a much shorter lookback window. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> * feat(dips): align RCA struct with indexing-payments-management-audit contracts (#964) The RecurringCollector contract on the `indexing-payments-management-audit` branch removed `bytes16 agreementId` from the RCA struct and replaced it with `uint256 nonce`. Agreement IDs are now derived on-chain via `bytes16(keccak256(abi.encode(payer, dataService, serviceProvider, deadline, nonce)))`. The `deadline` and `endsAt` fields also changed from `uint256` to `uint64`. Updates the sol! struct definition, adds `derive_agreement_id`, simplifies `validate_and_create_rca` by removing fallible U256-to-u64 conversion, and updates all test RCA constructions. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> * chore: remove misleading "v2" from DIPs migration and docs (#965) There is no DIPs v1 -- the off-chain voucher system was abandoned before deployment. DIPs refers exclusively to the on-chain RCA system. Rename the migration from dips_v2 to dips_pending_proposals and clean up doc comments that referenced "V2". Also clarifies the migration ownership comment in service.rs: the indexer-service does not run migrations by convention, the agent owns DDL, and the SQL files here are for local dev and tests only. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> * feat(dips): add specific rejection reasons to gRPC proto (#966) The RejectReason proto enum only had 4 values (Unspecified, PriceTooLow, Other, SignerNotAuthorised), so 6 of the 8 validation failures in indexer-service mapped to the generic Other. Dipper uses the reason to set exclusion periods and Other gets 30 days, meaning transient issues like DeadlineExpired would incorrectly exclude an indexer for a month. Added DeadlineExpired, UnsupportedNetwork, SubgraphManifestUnavailable, UnexpectedServiceProvider, AgreementExpired, and UnsupportedMetadataVersion to the proto and updated reject_reason_from_error to map each DipsError variant to its specific reason. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Contributor
Pull Request Test Coverage Report for Build 22678528353Details
💛 - Coveralls |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.