feat(rewards)!: recoverable_base_units can say "not recoverable" - #631
Conversation
Refs DIG-Network/dig_ecosystem#3442 Salvaged phase-A WIP; does not yet build -- needs dig-rpc-protocol 0.15 cascade.
…ystem#3442) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…tem#3442) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
1a7f27a to
dd5bb22
Compare
MichaelTaylor3d
left a comment
There was a problem hiding this comment.
Gate verdict: PASS at head dd5bb22 (dig_ecosystem#3442). No blocking findings; zero threads opened.
Checked:
- No None-to-0 path:
unwrap_or/unwrap_or_default/as u64do not touchrecoverableanywhere in the post-PR tree. chain_port.rs:232 carriescommitment.recoverable_base_units()verbatim; dispatch.rs:1126 maps the Option straight onto the wire. The temporary whole-call refusal is gone. - Tests sit at the decision: three tests drive
handle_rpcfordig.listRewardDistributorCommitmentsand assert the serialized JSON (key present withnull,0,4500). Two more use a real simulator launch throughRealRewardsChainPort. The nearest wrong implementations (None->0, Some(0)->None, Some(x)->0) each fail at least one test. - Peak anchor:
snapshot.observed()is minted only by dig-rewards-coin 0.10read_distributor, which refuses an absent peak height or timestamp (state.rs:1441-1448) and holds them as non-Option fields. SPEC 4.5 ("never 0 for an absent peak") holds, and the peak is now from the same read (SPEC 4.6 cl.6). - dependency_tree.rs still asserts exactly-one dig-rpc-protocol, now 0.15. Cargo.lock shows rpc 0.15, peer 0.17, download 0.26, selector 0.15.
- Commit headers are all 100 characters or fewer; the PR body carries the release-ordering line (dig-app #3446). All checks green, merge state CLEAN.
Non-blocking notes (no thread):
ChainPortError::ChainPeakUnavailable(port.rs:185, doc at port.rs:275) is no longer produced by the real adapter, because dig-rewards-coin refuses upstream. The variant is still a valid contract for other adapters and is still mapped in dispatch.rs:115. A follow-up could document that, or add a test that an absent peak refuses the whole call. No dig-node test pins that guarantee now.- The first commit message ("WIP anchor ... does not yet build") is fine only because the PR is squash-merged.
Not run: no build or tests locally (read-only gate); relied on the CI "Test + coverage", Clippy and Rustfmt checks, all pass.
loop-security verdict: PASSHead audited: dd5bb22 (dig_ecosystem#3442). Read-only, from git objects plus dig-rewards-coin 0.10.0 source in the cargo registry. Money figure (None vs 0 vs share): clear. Removed second peak read: clear, and better than before. Panics from RPC input: none added. The deleted code had Dependencies: Authz/exposure: unchanged. The method is still Tests: the new tests ( Defence-in-depth (no gate, ticket suggested):
Not covered: I did not build or run the tests, and I did not read the dig-peer, dig-download or dig-peer-selector source for the dependency-only bumps. I relied on the Cargo.lock diff showing no new transitive packages. The release-ordering constraint (no user-facing 0.15 release until dig-app #3446) is for the orchestrator. |
Summary
dig_ecosystem#3442 phase A:
recoverable_base_unitsisOption<u64>end to end, so "the chain refuses this clawback" (None) is never rendered as0(the #3439 defect).dependency_tree.rsliterals updated).CommitmentSlot.recoverable_base_unitsisOption<u64>;chain_port.rscarries dig-rewards-coin 0.10's answer unchanged.dig.listRewardDistributorCommitmentsdispatch maps theOptionstraight onto the wire; the TEMPORARY whole-call refusal is deleted.ChainPortError::InvalidWithdrawalShareis KEPT: still produced bychain_port.rs(bps does not fit u16 / > 10_000) and by dispatch'srange_checked_report.Tests (each observed RED under its revert)
unrecoverable_commitment_serializes_recoverable_as_present_null(dispatch; None -> 0 made it fail)zero_recoverable_commitment_serializes_as_zero(dispatch; Some(0) -> None made it fail)positive_recoverable_commitment_serializes_verbatim(dispatch; Some(x) -> 0 made it fail)an_epoch_started_commitment_is_reported_as_none_not_zero(chain_port, real simulator launch)a_not_started_commitment_with_zero_share_is_reported_as_some_zero(chain_port, real launch with bps 0)Local: fmt, clippy
--workspace --all-targets -D warnings,cargo test -p dig-node-core -p dig-node-serviceall green.Out of scope (split per bump-deps-on-touch): dig-dht 0.16 is blocked (dig_ecosystem#3223); the dig-constants split is dig_ecosystem#3193. No version bump (develop flow).
RELEASE ORDERING (loop-decider, #3442): do not release a user-facing dig-node on dig-rpc-protocol 0.15 until dig-app's Option-aware decoder (DIG-Network/dig_ecosystem#3446) has landed.
Refs DIG-Network/dig_ecosystem#3442
🤖 Generated with Claude Code