Skip to content

test: mutation proof for #3310's install-warn test (DO NOT MERGE) - #615

Closed
MichaelTaylor3d wants to merge 10 commits into
developfrom
proof/3310-install-warn-mutation
Closed

MichaelTaylor3d wants to merge 10 commits into
developfrom
proof/3310-install-warn-mutation

Conversation

@MichaelTaylor3d

Copy link
Copy Markdown
Contributor

Deliberately deletes the production warn in server.rs's install-refusal branch to prove install_reward_chain_port_refuses_a_second_install_with_a_warn (PR #614) can actually fail. Expect Test + coverage RED. THROWAWAY -- close and delete after the red is observed. Refs #3310.

MichaelTaylor3d and others added 10 commits September 14, 2026 05:07
…d dig-rewards-coin

Money-bug containment for dig_ecosystem#3303/#3286: exact `=` pins on
dig-node-service's direct edge stop the resolved chia-sdk-driver/chia-sdk-types/
chia-puzzle-types versions moving under us. This constrains OUR compile target
only -- Cargo.lock still carries a second, transitive chia-sdk-driver 0.30.0 and
chia-puzzle-types 0.26.0 line via other crates, and this pin does not evict
those. Containment, not correction.

chia-protocol/chia-bls/chia-sha2 stay caret: an `=` on a wire type poisons every
crate that depends on chia-protocol directly.

dig-rewards-coin = "0.5" (not the ticket's stale "0.4"): 0.5.0 is the release
that already refuses `epoch_seconds == 0` inside `read_distributor` itself.

Refs #3310

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…-rewards-coin

Adds RealRewardsChainPort (crates/dig-node-service/src/rewards/): distributor_report
served for real over dig-wallet's CorroboratedChainSource and
dig_rewards_coin::state::read_distributor, via a guarded read
(read_distributor_guarded) that refuses launch constants carrying
epoch_seconds == 0 BEFORE calling into dig-rewards-coin at all -- defense in
depth over that crate's own identical refusal (state.rs:1015), since
chia-sdk-driver-0.36.0's commit_incentives backfill loop never terminates on
that value and has no await point a timeout could interrupt.

store_id/root are recovered from the launcher's creating spend's CREATE_COIN
memo (chain_source.rs), following dig-mirror-coin's read_parent_outputs
pattern: authenticate the puzzle reveal against the coin's puzzle hash before
running it, never trust an unauthenticated memo alone.

The other four RewardsChainPort methods (funded_distributors,
distributor_state, submit_entry_writes, spend_new_epoch) answer Unavailable --
out of this ticket's scope (funder-registry and prover-cycle work tracked
separately).

Installed once from server.rs's enable_chain_sync-gated block, logging a
false (already-installed) return at WARN.

Refs #3310

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
CI's `cargo fmt --all -- --check` and `--locked` builds both failed on
the prior commit: rustfmt wanted several closures/return-types
reformatted, and Cargo.lock was missing the `chia-sdk-test`,
`clvm-traits` and `clvmr` entries the new adapter's Cargo.toml lines
require, which `--locked` refuses to backfill.

Refs #3310

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…t, fix constants fixture

- LaunchCommentError::ChainSource/Malformed tuple payloads were flagged
  dead_code by clippy: a derived Debug impl does not count as reading a
  private field. Add a manual Display impl that formats each variant's
  payload, and switch chain_port.rs's build_report call site from {error:?}
  to {error} so the reason reaches a log reader.

- adapter_source_never_imports_withdraw_committed_incentives was
  self-defeating: it include_str!s its own file and the test's own name
  and assertion messages contain the literal string it searches for, so
  it could never pass. Scope the scan to production_region(), everything
  before the file's own #[cfg(test)] marker.

- launcher_spend_with's RewardDistributorConstants fixture set
  reserve_inner_puzzle_hash/reserve_full_puzzle_hash to Bytes32::default()
  without calling .with_launcher_id(launcher_id), which recomputes both
  fields from curried tree hashes. chia-sdk-driver's
  RewardDistributor::from_launcher_solution requires constants ==
  constants.with_launcher_id(launcher_id), so this fixture deterministically
  failed to decode on every invocation (not flaky/timing-dependent).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ll-path evidence

Drives RealRewardsChainPort::distributor_report end to end against a
distributor launched by dig_rewards_coin::launch_dig_distributor in
chia-sdk-test's peer simulator, over a MockChainSource loaded from the
simulator's real coin records/spends. store_id/root are asserted
against the values launched with -- recoverable only by actually
running the launcher's parent spend and decoding its CLVM memo, so no
fixture shortcut can pass this test.

Also covers install_reward_chain_port's single-install refusal (true
then false, with the WARN server.rs's own call site logs).

Node exposes no lighter test constructor to an external integration
test crate, so the install-path test uses Node::from_env(), the same
constructor openrpc_drift_guard.rs's own test uses. launch_fixture
returns Box<dyn std::error::Error> rather than pulling in anyhow for
one test file.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…identity verdict

ChainSource::parent_spend returning Ok(None) is a chain-source gap (the
source does not yet hold the launcher's creating spend), not a genuine
"this is not a DIG distributor" classification. Give it its own
LaunchCommentError::ParentSpendUnavailable variant so chain_port.rs can
map it to ChainPortError::Unavailable, agreeing with the other absence
path (read_distributor_guarded's own Ok(None)), instead of rendering a
transport lag as a definitive negative identity claim.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Add one bounded tracing::warn! on distributor_report's error path,
  firing once per failure->success transition (not per call, via an
  AtomicBool), so an installed-but-degraded chain source is no longer
  indistinguishable from "no port installed."
- Extract current_distributor_epoch's arithmetic into a pure
  epoch_ordinal fn and unit-test it directly (non-zero multi-epoch case,
  the saturating_sub clock-skew branch, and the bare-launch zero case) --
  the only non-trivial computed field in the report mapping, previously
  unexercised by anything but a zero-valued default.
- Add launch_comment_error_to_port_error, wiring chain_source.rs's new
  ParentSpendUnavailable variant to ChainPortError::Unavailable, with a
  regression test, and a companion test confirming
  GuardedReadError::NonTerminatingEpochSeconds still maps to the named
  refusal (Other), never to Unavailable.
- Add a unit test proving a failing chain source surfaces as a named
  ChainPortError::Unavailable, never Ok(_) with a default-valued report.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
install_reward_chain_port_refuses_a_second_install_with_a_warn
previously captured and asserted against a warn it emitted itself
inside the test's own closure -- deleting server.rs's real warn line
would have left it green. Replace the self-emission with a source-text
check against server.rs's own production region (the same shape
adapter_source_never_imports_withdraw_committed_incentives already uses),
so the assertion can only be satisfied by what server.rs actually ships.

Also softens the A3 module doc's overstated "no fixture value can
produce the right store_id/root" claim: true of this file today, not a
structural guarantee.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…e text not runtime behaviour

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@MichaelTaylor3d
MichaelTaylor3d deleted the proof/3310-install-warn-mutation branch September 14, 2026 12:45
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