Skip to content

fix(sortition): derive committee seed after request [skip-line-limit] - #1792

Merged
hmzakhalid merged 1 commit into
mainfrom
fix/future-sortition-entropy
Aug 12, 2026
Merged

fix(sortition): derive committee seed after request [skip-line-limit]#1792
hmzakhalid merged 1 commit into
mainfrom
fix/future-sortition-entropy

Conversation

@hmzakhalid

@hmzakhalid hmzakhalid commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • derive the committee seed from the block after an E3 request instead of randomness visible inside the request transaction
  • have ciphernodes wait for the same block hash before ranking tickets, then cache the seed on the first submission
  • use EIP-2935 history where available and raise the minimum/default submission window to 60 seconds

Fixes zenith-security/2026-07-interfold#5

Notes

This closes requester revert grinding. It uses chain-native block-hash entropy, so it does not claim the stronger block-producer resistance of VRF.

Testing

  • pnpm --filter @interfold/contracts test
  • pnpm --filter @interfold/contracts validate:upgrade
  • pnpm --filter @interfold/contracts size:check
  • cargo test -p e3-evm -p e3-sortition
  • pnpm --filter @interfold/sdk exec vitest run tests/events.test.ts
  • pnpm check:committee
  • pnpm check:docs
  • pnpm check:invariants
  • pnpm format:check

Summary by CodeRabbit

  • New Features

    • Committee selection now uses entropy from a future block, reducing request-time seed manipulation.
    • Added delayed seed resolution with block-history fallback support.
    • Added clearer errors when entropy is unavailable.
  • Bug Fixes

    • Improved handling of delayed sortition events, confirmations, provider failures, and legacy requests.
  • Documentation

    • Updated operator, protocol, and troubleshooting guidance for entropy-based sortition.
    • Clarified that submission windows are deployment-specific and must allow entropy finalization.

@vercel

vercel Bot commented Aug 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
crisp Ready Ready Preview Aug 12, 2026 2:01pm
interfold-dashboard Ready Ready Preview Aug 12, 2026 2:01pm
interfold-docs Ready Ready Preview Aug 12, 2026 2:01pm

Request Review

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6c56adea-a1b8-49e8-8d79-9316d8acb55a

📥 Commits

Reviewing files that changed from the base of the PR and between 4b48a76 and 69f8522.

📒 Files selected for processing (1)
  • crates/evm/src/ciphernode_registry/actor.rs

📝 Walkthrough

Walkthrough

The registry now commits a future entropy block for each committee request. The committee seed is resolved from that block hash and the E3 ID after confirmation. Rust sortition, contracts, SDK types, tests, deployment settings, and documentation now use separate computation and committee seeds.

Changes

Delayed entropy sortition

Layer / File(s) Summary
Registry entropy contract and ABI
packages/interfold-contracts/contracts/registry/CiphernodeRegistryOwnable.sol, packages/interfold-contracts/contracts/interfaces/ICiphernodeRegistry.sol, packages/interfold-contracts/artifacts/..., packages/interfold-contracts/contracts/Interfold.sol, crates/evm/src/contracts.rs, packages/interfold-contracts/deploy/..., packages/interfold-contracts/scripts/...
The registry records the next block as entropyBlock, resolves and caches the committee seed, supports EIP-2935 history lookup, and renames legacy seed fields.
Confirmation-aware registry event reader
crates/evm/src/ciphernode_registry/actor.rs, crates/evm/src/ciphernode_registry/events.rs, crates/ciphernode-builder/src/ciphernode_builder.rs
The EVM reader decodes registry logs, waits for confirmations, derives delayed seeds, supports legacy events, reconnects providers, and forwards events with timeouts.
Delayed seed handling in Sortition
crates/sortition/src/sortition/..., crates/events/src/interfold_event/e3_requested.rs
Sortition stores resolved seeds, queues requests until seeds arrive, ranks tickets with the resolved seed, and removes temporary state during lifecycle completion.
Validation, deployment timing, and protocol documentation
packages/interfold-contracts/test/..., packages/interfold-sdk/..., docs/pages/..., agent/..., README.md, crates/sortition/Readme.md
Tests mine entropy blocks and verify delayed and historical seed resolution. Documentation describes separate seeds, confirmation timing, submission windows, and block-hash retention.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Requester
  participant CiphernodeRegistryOwnable
  participant CiphernodeRegistrySolReader
  participant Sortition
  Requester->>CiphernodeRegistryOwnable: requestCommittee(legacySeed)
  CiphernodeRegistryOwnable->>CiphernodeRegistryOwnable: record next block as entropyBlock
  CiphernodeRegistrySolReader->>CiphernodeRegistrySolReader: wait for confirmations and derive committee seed
  CiphernodeRegistrySolReader->>Sortition: forward CommitteeRequested with resolved seed
  Sortition->>Sortition: rank tickets using committee seed
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: deriving the committee seed after the E3 request.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/future-sortition-entropy

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/interfold-contracts/contracts/interfaces/ICiphernodeRegistry.sol (1)

73-84: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Regenerate the checked-in registry artifacts.

CiphernodeRegistryOwnable.json, its artifacts.d.ts, and both mock artifacts still define CommitteeRequested with seed and without ticketPrice. Regenerate these artifacts to match the six-argument event emitted by CiphernodeRegistryOwnable.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/interfold-contracts/contracts/interfaces/ICiphernodeRegistry.sol`
around lines 73 - 84, Regenerate the checked-in registry artifacts for
CommitteeRequested so CiphernodeRegistryOwnable.json, its artifacts.d.ts, and
both mock artifacts match the six-argument event definition: use entropyBlock
instead of seed and include ticketPrice. Do not alter the Solidity event
declaration.
packages/interfold-contracts/artifacts/contracts/interfaces/IBondingRegistry.sol/IBondingRegistry.json (1)

754-754: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Preserve LicenseTransferShortfall in a legacy ABI.

The package publishes and exports its artifacts. Consumers using the current ABI cannot decode historical logs for this event.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/interfold-contracts/artifacts/contracts/interfaces/IBondingRegistry.sol/IBondingRegistry.json`
at line 754, Preserve the LicenseTransferShortfall event definition in the
published legacy ABI artifact represented by IBDondingRegistry.json, restoring
its complete ABI entry so consumers can decode historical logs. Keep the
existing artifact structure and event signature consistent with the contract
interface.
🧹 Nitpick comments (1)
crates/evm/src/ciphernode_registry/actor.rs (1)

216-218: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The Ok(None) branch is unreachable.

parse_registry_log returns Ok(Some(..)) on every success path, and a None from the extractors becomes an error through .context(..)? at Line 152. InterfoldEvmEvent::Processed(id) is therefore never produced. Change the return type to Result<EvmEvent> and drop the branch, or document the case that is meant to yield Ok(None).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/evm/src/ciphernode_registry/actor.rs` around lines 216 - 218, Update
the parsing flow around parse_registry_log and the parsed match so its return
type is Result<EvmEvent>, remove the unreachable Ok(None) and
InterfoldEvmEvent::Processed(id) branch, and preserve the existing error
propagation for extractor failures.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@agent/flow-trace/03_E3_REQUEST_AND_COMMITTEE.md`:
- Around line 107-112: Update the requestCommittee call flow so the legacy
argument is explicitly defined: reuse the existing seed symbol as the legacySeed
argument, or pass seed directly and identify the callee parameter as
legacy-only. Ensure the trace no longer shows an undefined legacySeed and
clearly preserves the ABI-compatible input.

In `@crates/ciphernode-builder/src/ciphernode_builder.rs`:
- Line 1040: Update the reorg_confirmations default in the chain configuration
flow to a non-zero value so reorg protection remains enabled when the setting is
unset. Preserve explicitly configured values, including zero if supported, and
ensure the derived confirmation value is passed through the existing
seed/entropy handling path.

In `@crates/evm/src/ciphernode_registry/actor.rs`:
- Around line 103-146: Bound the entropy-block retry loop in the reader flow
around the `let seed = loop` block with the proposed `ENTROPY_WAIT_TIMEOUT`
deadline, declared alongside `EVENT_FORWARD_TIMEOUT`. On expiry, stop retrying
and reject the current log with a named failure so `ctx.wait` does not suspend
mailbox processing indefinitely; preserve the existing provider reconnect and
successful seed derivation behavior.

In `@crates/sortition/src/sortition/actor.rs`:
- Around line 50-53: Persist and restore sortition_seeds and pending_requests
across actor restarts, or deterministically rebuild them from durable E3 and
registry events before enabling effects; update the actor initialization and
event-handling paths around these fields while preserving E3Requested replay
gating. Add restart coverage for both request-before-seed and
seed-before-request orders, asserting exactly one ticket-generation attempt per
E3.

In
`@packages/interfold-contracts/contracts/registry/CiphernodeRegistryOwnable.sol`:
- Around line 626-675: Prevent sortition seed loss when no ticket is submitted
before the blockhash retention horizon by adding a permissionless
resolveSortitionSeed(uint256 e3Id) entrypoint that invokes _resolveSortitionSeed
and persists the result. Ensure callers can pin the seed once sortitionSeed
reports it ready, while preserving the existing resolved-seed behavior used by
submitTicket.

In `@packages/interfold-sdk/src/events/types.ts`:
- Line 88: Update the SDK release metadata for the public CommitteeRequestedData
field rename from seed to entropyBlock: add release notes describing the
breaking change and bump the SDK version before publishing, following the
event-schema compatibility guidance in agent/INVARIANTS.md.

---

Outside diff comments:
In
`@packages/interfold-contracts/artifacts/contracts/interfaces/IBondingRegistry.sol/IBondingRegistry.json`:
- Line 754: Preserve the LicenseTransferShortfall event definition in the
published legacy ABI artifact represented by IBDondingRegistry.json, restoring
its complete ABI entry so consumers can decode historical logs. Keep the
existing artifact structure and event signature consistent with the contract
interface.

In `@packages/interfold-contracts/contracts/interfaces/ICiphernodeRegistry.sol`:
- Around line 73-84: Regenerate the checked-in registry artifacts for
CommitteeRequested so CiphernodeRegistryOwnable.json, its artifacts.d.ts, and
both mock artifacts match the six-argument event definition: use entropyBlock
instead of seed and include ticketPrice. Do not alter the Solidity event
declaration.

---

Nitpick comments:
In `@crates/evm/src/ciphernode_registry/actor.rs`:
- Around line 216-218: Update the parsing flow around parse_registry_log and the
parsed match so its return type is Result<EvmEvent>, remove the unreachable
Ok(None) and InterfoldEvmEvent::Processed(id) branch, and preserve the existing
error propagation for extractor failures.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 159a169e-ac7d-4274-a803-b154561ae8b8

📥 Commits

Reviewing files that changed from the base of the PR and between 1a29064 and ae8541d.

📒 Files selected for processing (38)
  • README.md
  • agent/INVARIANTS.md
  • agent/flow-trace/00_INDEX.md
  • agent/flow-trace/03_E3_REQUEST_AND_COMMITTEE.md
  • crates/ciphernode-builder/src/ciphernode_builder.rs
  • crates/events/src/interfold_event/e3_requested.rs
  • crates/evm/src/ciphernode_registry/actor.rs
  • crates/evm/src/ciphernode_registry/events.rs
  • crates/evm/src/contracts.rs
  • crates/sortition/Readme.md
  • crates/sortition/src/sortition/actor.rs
  • crates/sortition/src/sortition/handlers/lifecycle.rs
  • crates/sortition/src/sortition/handlers/registry.rs
  • crates/sortition/src/sortition/handlers/request.rs
  • docs/pages/ciphernode-operators/tickets-and-sortition.mdx
  • docs/pages/computation-flow.mdx
  • docs/pages/internals/sortition.mdx
  • docs/pages/tutorials/operator-troubleshooting.mdx
  • packages/interfold-contracts/artifacts/contracts/interfaces/IBondingRegistry.sol/IBondingRegistry.json
  • packages/interfold-contracts/artifacts/contracts/interfaces/ICiphernodeRegistry.sol/ICiphernodeRegistry.json
  • packages/interfold-contracts/artifacts/contracts/interfaces/IInterfold.sol/IInterfold.json
  • packages/interfold-contracts/artifacts/contracts/interfaces/ISlashingManager.sol/ISlashingManager.json
  • packages/interfold-contracts/artifacts/contracts/token/InterfoldTicketToken.sol/InterfoldTicketToken.json
  • packages/interfold-contracts/contracts/Interfold.sol
  • packages/interfold-contracts/contracts/interfaces/ICiphernodeRegistry.sol
  • packages/interfold-contracts/contracts/registry/CiphernodeRegistryOwnable.sol
  • packages/interfold-contracts/deploy/protocol/example.protocol.config.json
  • packages/interfold-contracts/scripts/deployInterfold.ts
  • packages/interfold-contracts/test/E3Lifecycle/E3Integration.spec.ts
  • packages/interfold-contracts/test/E3Lifecycle/Sortition.spec.ts
  • packages/interfold-contracts/test/Pricing/DustRotation.spec.ts
  • packages/interfold-contracts/test/Pricing/PullPaymentsAndAllowlist.spec.ts
  • packages/interfold-contracts/test/Registry/CiphernodeRegistryOwnable.spec.ts
  • packages/interfold-contracts/test/Slashing/CommitteeExpulsion.spec.ts
  • packages/interfold-contracts/test/fixtures/constants.ts
  • packages/interfold-contracts/test/fixtures/helpers.ts
  • packages/interfold-sdk/src/events/types.ts
  • packages/interfold-sdk/tests/events.test.ts

Comment thread agent/flow-trace/03_E3_REQUEST_AND_COMMITTEE.md Outdated
Comment thread crates/ciphernode-builder/src/ciphernode_builder.rs Outdated
Comment thread crates/evm/src/ciphernode_registry/actor.rs Outdated
Comment thread crates/sortition/src/sortition/actor.rs Outdated
Comment thread packages/interfold-sdk/src/events/types.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
crates/evm/src/ciphernode_registry/actor.rs (1)

353-360: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

attach inherits the zero-confirmation default.

attach forwards to setup, so every caller of attach gets confirmations = 0 and no provider factory. Add the confirmation depth and the optional factory to this signature, or document that attach is for tests only.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/evm/src/ciphernode_registry/actor.rs` around lines 353 - 360, Update
CiphernodeRegistrySolReader::attach to accept and forward the confirmation depth
and optional provider factory to setup, ensuring callers do not inherit the
zero-confirmation default. Preserve the existing processor and provider
parameters while keeping the setup path consistent with the expanded
configuration.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/evm/src/ciphernode_registry/actor.rs`:
- Around line 98-154: Change the committee-request entropy resolution around the
tokio::time::timeout block so expiration schedules the log for retry instead of
propagating the timeout through with_context into InterfoldEvmEvent::Rejected.
Move the potentially 300-second entropy wait, including derive_sortition_seed
resolution, outside the actor’s synchronous mailbox handling so CiphernodeAdded,
TicketSubmitted, and CommitteePublished events continue processing while it
retries.
- Around line 192-195: Update CiphernodeRegistrySolReader::setup to avoid the
zero-confirmation default by requiring or supplying a non-zero confirmation
depth, and update attach to accept and forward confirmations plus the optional
ProviderFactory; alternatively restrict attach to test usage as requested. Apply
the changes at crates/evm/src/ciphernode_registry/actor.rs lines 192-195 and
353-360, ensuring all attach callers provide the intended chain-read
configuration.

---

Nitpick comments:
In `@crates/evm/src/ciphernode_registry/actor.rs`:
- Around line 353-360: Update CiphernodeRegistrySolReader::attach to accept and
forward the confirmation depth and optional provider factory to setup, ensuring
callers do not inherit the zero-confirmation default. Preserve the existing
processor and provider parameters while keeping the setup path consistent with
the expanded configuration.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 86210264-c7a3-4cb9-ba77-e7faa151e711

📥 Commits

Reviewing files that changed from the base of the PR and between 910ded0 and 4b48a76.

📒 Files selected for processing (5)
  • agent/flow-trace/03_E3_REQUEST_AND_COMMITTEE.md
  • crates/ciphernode-builder/src/ciphernode_builder.rs
  • crates/evm/src/ciphernode_registry/actor.rs
  • crates/sortition/src/sortition/actor.rs
  • docs/pages/internals/sortition.mdx
🚧 Files skipped from review as they are similar to previous changes (4)
  • crates/sortition/src/sortition/actor.rs
  • crates/ciphernode-builder/src/ciphernode_builder.rs
  • docs/pages/internals/sortition.mdx
  • agent/flow-trace/03_E3_REQUEST_AND_COMMITTEE.md

Comment thread crates/evm/src/ciphernode_registry/actor.rs
Comment thread crates/evm/src/ciphernode_registry/actor.rs Outdated
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.

1 participant