Consensus
The consensus
policy sends the same request to multiple upstreams and returns the result only when enough of them agree. This improves correctness, detects misbehaving nodes, and provides deterministic behavior during faults.
Consensus can only be configured at network level since it requires multiple upstreams to compare results.
Configuration
projects:
- id: main
networks:
- architecture: evm
evm:
chainId: 42161
failsafe:
- matchMethod: "*" # Configure per-method thresholds if needed
consensus:
maxParticipants: 4
agreementThreshold: 2
disputeBehavior: returnError # acceptMostCommonValidResult | preferBlockHeadLeader | onlyBlockHeadLeader
lowParticipantsBehavior: acceptMostCommonValidResult # returnError | preferBlockHeadLeader | onlyBlockHeadLeader
preferNonEmpty: true
preferLargerResponses: true
ignoreFields:
eth_getBlockByNumber: ["timestamp"]
punishMisbehavior: # (optional) To exclude bad upstreams from consensus for a while
disputeThreshold: 10
disputeWindow: 10m
sitOutPenalty: 30m
Key options
maxParticipants
Number of upstreams to query in each consensus round. The policy selects the first N healthy upstreams based on their scores.
agreementThreshold
Minimum number of identical responses needed to reach consensus. For example, with maxParticipants: 3
and agreementThreshold: 2
, at least 2 upstreams must return the same result.
disputeBehavior
When upstreams disagree (no group meets threshold):
acceptMostCommonValidResult
: Use preferences and select the best valid result among groups that meet threshold. If none meet threshold, returns dispute.returnError
: Always return a dispute error in disagreement scenarios.preferBlockHeadLeader
: If the block head leader has a non-error result, return it; otherwise fall back toacceptMostCommonValidResult
logic.onlyBlockHeadLeader
: Return the leader’s non-error result if available; otherwise dispute.
Behavior options
preferNonEmpty
Prioritize meaningful data over empty, and empty over errors. Applies with acceptMostCommonValidResult
:
- Above threshold: If both a non-empty and a consensus-valid error group meet threshold, pick the best non-empty (by count, then size).
- Below threshold: With exactly one non-empty and at least one empty, pick the non-empty.
- Prevents short-circuiting to empty/consensus-error when a non-empty may still arrive.
preferLargerResponses
Prefer larger non-empty results:
- Below threshold (AcceptMostCommon): choose the largest non-empty.
- Above threshold with multiple valid groups: choose the largest non-empty.
- If a smaller non-empty meets threshold but a larger non-empty exists:
acceptMostCommonValidResult
: choose the largestreturnError
: dispute (don’t accept the smaller)
ignoreFields
Per-method fields ignored when computing canonical hashes (useful for timestamps etc.).
lowParticipantsBehavior
When fewer than agreementThreshold
valid responses are available:
acceptMostCommonValidResult
: Apply preferences to pick a valid result; still respects threshold semantics.returnError
: Return a low-participants error.preferBlockHeadLeader
: If the block head leader has a non-error result, return it; otherwise fall back toacceptMostCommonValidResult
.onlyBlockHeadLeader
: If the leader has a non-error result, return it; if the leader only has an error, return that error; otherwise return a low-participants error.
Block Head Leader: The upstream reporting the highest block number. This is determined by each upstream's state poller and ensures you're getting data from the most synchronized node.
How it works
- Send the request to up to
maxParticipants
(if less upstreams it continues with the available ones); group identical results/errors. - If any valid group meets
agreementThreshold
, it wins - If no winner, apply behaviors:
- Low participants →
lowParticipantsBehavior
- Otherwise →
disputeBehavior
- Low participants →
- Preferences (non-empty, larger responses) may override selection in specific contexts (see above).
- Ties without preferences → dispute.
- All upstreams return identical error → return that error; otherwise return low-participants error.
Misbehavior tracking
punishMisbehavior
Temporarily removes upstreams that consistently disagree with the consensus:
disputeThreshold
: Number of disputes before punishment (e.g., 3 strikes)disputeWindow
: Time window for counting disputes (e.g., 10m)sitOutPenalty
: How long the upstream is cordoned (e.g., 30m)
Performance
Consensus increases costs and latency since it waits for multiple responses. Use it selectively for critical workloads and specific methods rather than all requests.