feat: dedicated fast-path loop for DIPs proposal acceptance#1200
Open
MoonBoi9001 wants to merge 11 commits intofeat/dips-on-chain-cancelfrom
Open
feat: dedicated fast-path loop for DIPs proposal acceptance#1200MoonBoi9001 wants to merge 11 commits intofeat/dips-on-chain-cancelfrom
MoonBoi9001 wants to merge 11 commits intofeat/dips-on-chain-cancelfrom
Conversation
…ong lived allocation
Three fixes that together enable end-to-end DIPs on-chain acceptance: 1. Pass SubgraphService (not HorizonStaking) to RewardsManager.getRewards in the allocation stakeUsageSummary call. 2. Decouple DIPs proposal acceptance from the 120s reconciliation loop into a dedicated 5s polling loop (startProposalAcceptanceLoop). The 300s RCA deadline left insufficient slack with the old 240s+ latency. 3. Log full revert context (reason, data, message, contract target) when on-chain acceptance fails, instead of just the parsed error (which was null for unknown custom errors). Test metadata version updated to 0 to match the Solidity enum IndexingAgreementVersion.V1 (first variant = 0). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…greement The audit-branch SubgraphService contract splits the previous packed SignedRCA argument into separate rca (now 11 fields including conditions) and signature arguments. The agent was still building calldata using the old 2-arg signature, so every acceptIndexingAgreement call resolved to a non-existent selector on the deployed contract and reverted with FailedCall() inside the multicall path. Unpack proposal.signedRca at both call sites (acceptWithExistingAllocation and acceptWithNewAllocation) and pass rca and signature as the second and third arguments. Add the conditions field to the two test fixtures so the mocks match the updated tuple shape. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The dips rule was created on the 15s reconciliation loop by iterating pending_rca_proposals, but the fast 5s accept loop clears that row as soon as the acceptIndexingAgreement receipt lands. On fast chains the receipt consistently beats the next reconcile tick, so graph-node never gets told to deploy the subgraph and the agent spins on unallocate attempts for the just-created DIPs allocation. Extract the per-proposal rule logic into ensureDipsRuleForProposal and call it eagerly from processProposal before executeTransaction fires. Reconciliation still calls it as defense-in-depth. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
c4d0d52 to
861cddf
Compare
The DIPs accept path created the allocation on-chain via acceptIndexingAgreement without first telling graph-node to deploy the subgraph. If the main reconcile loop ticked after the allocation was created but before graph-node had started indexing, it read an undefined indexingStatus, hit the !indexingStatus branch of failsHealthCheck, and queued an unallocate for the allocation the accept path had just created. Call graphNode.ensure before dispatching to acceptWith*Allocation so indexingStatus always resolves on the next reconcile tick. ensure is idempotent for existing deployments. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Motivation
The indexer-agent's DIPs proposal acceptance has been tied to the 120s reconciliation loop, which requires two or more cycles (240-360s) before the agent attempts on-chain acceptance. The
RecurringCollectionAgreementdeadline is 300s, so the reconciliation cadence leaves little to no slack and agreements can expire before the agent attempts acceptance at all.This PR adds a dedicated 5s polling loop for
pending_rca_proposals, independent of reconciliation, so acceptance happens promptly within the deadline.Summary
1. Dedicated fast-path loop for proposal acceptance
Added
startProposalAcceptanceLoop()which pollspending_rca_proposalsevery 5 seconds and callsprocessProposalfor each entry. Runs independently of the 120s reconciliation cycle. Reconciliation continues to callacceptPendingProposalson its own cadence as a catch-up path.2. Wrong contract in
getRewardscallAllocationManager.stakeUsageSummary()calledRewardsManager.getRewards(HorizonStaking, allocationId)butHorizonStakingis not a registered rewards issuer --SubgraphServiceis. Every allocation operation (including DIPs acceptance) reverted with "Not a rewards issuer".3. Opaque contract revert errors
When on-chain acceptance failed, the log showed
error: nullbecausetryParseCustomErrorcouldn't decode unknown custom errors. Added full revert context (reason, data, message, contract target) to the rejection log so the root cause is immediately visible.See companion PRs: edgeandnode/dipper#583, graphprotocol/indexer-rs#983.
Generated with Claude Code