test(drive-abci): rehearse a reproducible scheduled host fault and the existing recovery path - #4808
DCG-Claude wants to merge 3 commits into
Conversation
…e existing recovery path Adds a test-only hook at the scheduled-event integration point of run_block_proposal_v0 (after the DAO events, before the ordinary state transitions) behind the testing-config feature, and a strategy module that keeps three block failure classes apart: a paid consensus failure that stays in the block and is charged, a node-local failure that stops one node until it re-executes the same block, and a reproducible host fault that fails every proposal on every node before any transaction is looked at. The last test rehearses the recovery path that exists for the third class: an execution and fee identical hotfix, a restart from disk, and the replay of the very proposal that faulted, compared block for block against a never-faulted twin. Production builds are byte-identical: the hook does not exist without the feature. Refs #4688 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…_block_proposal Armed, the hook fails the whole proposal with the injected internal error for an empty proposal, which is the class every node reproduces and no transaction removal can route around. Unarmed, the same empty proposal runs through to a valid outcome. The synthetic state gets an epoch 0 with its proposers tree and one validator set so the closing per-block events can complete. Refs #4688 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… recovery path Adds a reference chapter that keeps a deterministic paid failure, a node-local failure and a reproducible per-block fault apart, cites where each surfaces in rs-drive-abci and in Tenderdash 1.7, explains why a signalling upgrade cannot progress on a halted chain, states the hotfix and replay recovery the rehearsal tests exercise, and reports that a repair which changes execution or fees has no demonstrated progressing path under the selected policy. The historical network gated exceptions are described as evidence of coordinated releases, not as a procedure. The scheduled host fault strategy module joins the PR nextest gate next to the process proposal collision module. Refs #4688 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
📖 Book Preview built successfully. Download the preview from the workflow artifacts. Updated at 2026-09-17T22:49:16.258Z |
|
|
Codecov Report❌ Patch coverage is ❌ Your patch check has failed because the patch coverage (46.45%) is below the target coverage (50.00%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## v5.0-dev #4808 +/- ##
=============================================
- Coverage 86.36% 75.40% -10.97%
=============================================
Files 2766 2799 +33
Lines 366105 411517 +45412
=============================================
- Hits 316191 310296 -5895
- Misses 49914 101221 +51307
🚀 New features to boost your workflow:
|
|
The codecov patch and project numbers on this head are a reporting artifact, not missing coverage, so I am not rerunning the job or pushing for it. What the numbers rest on: the Rust workspace job for This is the known self-hosted-runner line-table mismatch seen on other v5.0-dev PRs; a rerun adds a second upload with the same stale mapping. Neither codecov check is in the v5.0-dev rulesets. 🤖 Posted autonomously by DashVM (Claude Fable 5.1) on behalf of pasta. |
thepastaclaw
left a comment
There was a problem hiding this comment.
⚠️ DEGRADED — Final validation — Phase 1 + Phase 2
⚠️ DEGRADED review. The primary review models were unavailable (gpt-6-astraunavailable: All credentials for model gpt-6-astra are cooling down (last error: usage_limit_reached: The usage limit has been reache), so this review ran on stand-in models:gpt-5.6-luna→muse-spark-1.3-contributor,gpt-5.6-sol→muse-spark-1.3-contributor,gpt-5.6-terra→muse-spark-1.3-contributor,gpt-6-astra→muse-spark-1.3-contributor. Both review phases and the independent verifiers still ran, but on weaker models, with Phase 1 capped athigheffort. Treat the verdict as provisional; a full-strength re-review will run on the next push once the primary models are back.
Test-only rehearsal of the three block-failure classes with no production impact. I independently verified the safety claims: the fault hook in run_block_proposal_v0 and the new PlatformTestConfig field plus message constant are all #[cfg(feature = "testing-config")] gated, default to false in both constructors, and testing_configs is #[serde(skip)] so the flag is unreachable from config files. No version-table, consensus-error, fee, serialization, or wire-format changes. No in-scope findings from any lane.
Review provenance
Source: reviewer 1: muse-spark-1.3-contributor (agent: phase1-reviewer, role: general); reviewer 2: muse-spark-1.3-contributor (agent: phase1-reviewer, role: architecture-layering); reviewer 3: muse-spark-1.3-contributor (agent: phase1-reviewer, role: platform-versioning); reviewer 4: muse-spark-1.3-contributor (agent: phase1-reviewer, role: rust-quality); reviewer 5: muse-spark-1.3-contributor (agent: phase1-reviewer, role: security-auditor); reviewer 6: muse-spark-1.3-contributor (standing in for gpt-6-astra) (agent: phase2-reviewer, role: general); reviewer 7: muse-spark-1.3-contributor (standing in for gpt-6-astra) (agent: phase2-reviewer, role: architecture-layering); reviewer 8: muse-spark-1.3-contributor (standing in for gpt-6-astra) (agent: phase2-reviewer, role: platform-versioning); reviewer 9: muse-spark-1.3-contributor (standing in for gpt-6-astra) (agent: phase2-reviewer, role: rust-quality); reviewer 10: muse-spark-1.3-contributor (standing in for gpt-6-astra) (agent: phase2-reviewer, role: security-auditor); final verifier: muse-spark-1.3-contributor (standing in for gpt-6-astra) (agent: astra-verifier, role: final-verifier)
- Degraded mode:
gpt-6-astraunavailable: All credentials for model gpt-6-astra are cooling down (last error: usage_limit_reached: The usage limit has been reache (detected by probe, since 2026-09-18T05:22:01Z); stand-insgpt-5.6-luna→muse-spark-1.3-contributor,gpt-5.6-sol→muse-spark-1.3-contributor,gpt-5.6-terra→muse-spark-1.3-contributor,gpt-6-astra→muse-spark-1.3-contributor; Phase 1 effort capped athigh - Triage:
normalbymuse-spark-1.3-contributor(standing in forgpt-6-astra) (effort low) — Large test-only fault hook gated behind testing-config plus docs and strategy tests with no production consensus, funds, crypto, or migration change. - Phase 1 reviewers:
muse-spark-1.3-contributor— general (completed, effort high); agentphase1-reviewer,muse-spark-1.3-contributor— architecture-layering (completed, effort high); agentphase1-reviewer,muse-spark-1.3-contributor— platform-versioning (completed, effort high); agentphase1-reviewer,muse-spark-1.3-contributor— rust-quality (completed, effort high); agentphase1-reviewer,muse-spark-1.3-contributor— security-auditor (completed, effort high); agentphase1-reviewer - Phase 1 model:
muse-spark-1.3-contributor— not quota-gated; passed overgemini-3.8-flash-high(lane failed),glm-5.3-flash(zai below 15% reserve: 5h 99% left, weekly 14% left) - Fresh verifier:
muse-spark-1.3-contributor(standing in forgpt-6-astra) — final-verifier; agentastra-verifier - Phase 2 reviewers:
muse-spark-1.3-contributor(standing in forgpt-6-astra) — general (completed, effort high); agentphase2-reviewer,muse-spark-1.3-contributor(standing in forgpt-6-astra) — architecture-layering (completed, effort high); agentphase2-reviewer,muse-spark-1.3-contributor(standing in forgpt-6-astra) — platform-versioning (completed, effort high); agentphase2-reviewer,muse-spark-1.3-contributor(standing in forgpt-6-astra) — rust-quality (completed, effort high); agentphase2-reviewer,muse-spark-1.3-contributor(standing in forgpt-6-astra) — security-auditor (completed, effort high); agentphase2-reviewer
Out-of-scope follow-up suggestions (1)
These are valid observations, but they are outside this PR's scope and should be handled in separate issues or author/maintainer-requested PRs rather than blocking this review.
- Real scheduled-jobs phase will need full versioning — This PR deliberately rehearses with a test hook before any guest runtime exists; when the jobs phase lands (hook moves inside it, paid trap results, fee schedule, possible new transitions/errors), that work will need a new vN implementation, dispatcher arm, PlatformVersion slots, activation gates, and estimation/execution/proof coverage.
- Follow-up: Track the versioned rollout of the jobs phase in the smart-contract workstream (issue #4688) when execution or fees change.
Issue being fixed or feature implemented
Part of the smart-contract plan in #4626 (workstream issue #4688, task FIX-03). Once contracts run inside blocks, three very different failures share one word: a guest that traps (a paid result), a node that cannot load a compiled module (that node stops), and a defect in how every node drives the scheduled phase (every block fails). The owner's selected policy for anything that changes execution or fees is the normal protocol upgrade, with no emergency pause, no activation-height override, no recovery binary and no guest-skip rule. Before the jobs phase is built, this PR keeps the three classes apart with tests that drive the real block-execution entry points, reproduces the third class at the scheduled-event integration point, rehearses the recovery path that exists for it, and reports the limitation of that path in a reference chapter.
Refs #4688
What was done?
Test-only fault hook at the scheduled-event integration point (
packages/rs-drive-abci/src/config.rs,packages/rs-drive-abci/src/execution/engine/run_block_proposal/v0/mod.rs).PlatformTestConfiggainsscheduled_event_host_fault: bool(defaultfalsein bothDefaultanddefault_minimal_verifications()) and the constantSCHEDULED_EVENT_HOST_FAULT_MESSAGE. Inrun_block_proposal_v0, directly afterrun_dao_platform_eventsand beforeprocess_raw_state_transitions, a block gated by#[cfg(feature = "testing-config")]returnsErr(Error::Execution(ExecutionError::CorruptedCodeExecution(SCHEDULED_EVENT_HOST_FAULT_MESSAGE)))when the flag is set. This follows the four existingtesting_configsreads inside shippedv0modules and thetest_fault_injectionseam inprocess_raw_state_transitions. Production builds (console,grovedbg,replay) never enabletesting-config, so the compiledrun_block_proposal_v0is byte-identical; novNgeneration, no version table, no fee schedule, no consensus error, no proto or SDK surface changes.Unit tests through the dispatcher (
packages/rs-drive-abci/src/execution/engine/run_block_proposal/mod.rs):should_fail_the_whole_proposal_at_the_scheduled_event_point_when_the_host_fault_is_armedpins that an empty proposal returnsErrwith the injected message (a whole-proposal failure, not aValidationResulterror and not a per-transition result);should_not_fail_the_proposal_at_the_scheduled_event_point_when_unarmedpins that the same proposal is valid with the flag off. The synthetic state carries an epoch 0 with its proposers tree and one validator set so the closing per-block events complete.Strategy module (
packages/rs-drive-abci/tests/strategy_tests/test_cases/scheduled_host_fault_tests.rs, registered intest_cases/mod.rs). All requests go throughtenderdash_abci::ApplicationonFullAbciApplication; twin platforms are built from one seed and compared block for block.paid_failure_stays_in_the_block_pays_and_the_chain_advances(class 1): the dashpay all-mutable contract with a skipped-position update at block 3 produces aPaidConsensusErrorwith code 10411 and positivegas_used, and the chain reaches block 10 withverify_state_transition_results.node_local_fault_stops_only_that_node_and_it_commits_the_same_block_after_repair(class 2): twins A and B commit five blocks; B executes the next block; A, armed, fails it with the injected exception and its committed root is unchanged; disarmed, A re-executes the identical request to B's app hash andtx_results; both finalize throughfinalize_blockand hold the same committed root and height.reproducible_scheduled_fault_halts_every_node_before_ordinary_transactions(class 3): both twins armed; everyprepare_proposalandprocess_proposalfails on both nodes for two proposers, rounds 0 to 2, with and without transactions, while signalling latest+1, and for an epoch-change block; committed roots, heights, the versions counter (read withfetch_versions_with_counter) andnext_epoch_protocol_version()are unchanged.execution_identical_hotfix_replays_the_faulted_proposal_and_the_chain_continues(class 3 recovery): control node C prepares and processes a concrete proposal R (non-empty, signalling latest+1, first block of epoch 1); A, armed, fails R as proposer and twice as validator with nothing left behind; A is disarmed and reopened from disk withTempPlatform::open_with_tempdir; A processes the unchanged R to C's app hash andtx_results; both finalize R, land in epoch 1 with the versions counter holding exactly{latest+1: 1}and the created identities present on both;continue_chain_for_strategyruns five more blocks on each and the committed roots stay equal.CI gate (
.github/workflows/tests-rs-workspace.yml): the two nextest filters now includetest(~scheduled_host_fault)in the PR phase and exclude it from the push-only phase, next to the collision module; the comment block above them is extended. actionlint reports the same pre-existing shellcheck notes as on the base branch and nothing new.Book chapter (
book/src/architecture/block-failure-classes.md, listed inbook/src/SUMMARY.mdunder Architecture): the three classes with their surfaces inrs-drive-abciand Tenderdash 1.7 (internal/consensus/block_executor.go,internal/consensus/prevoter.go,internal/consensus/replay.go,internal/state/execution.go, verified on tag v1.7.0), why a signalling upgrade cannot progress on a halted chain (vote written inside the block, tally on an epoch-change block, activation on a later block), the hotfix-and-replay recovery the tests rehearse, the historicalevo1gates and emergency parameter updates described as evidence of coordinated releases rather than a procedure, the limitation, how to run the rehearsal, and rules for the jobs phase.How Has This Been Tested?
Locally on macOS (Darwin 24.6.0, arm64), each command redirected to a file with its exit code captured:
Results: 5
run_block_proposalunit tests pass; the 4 scheduled host fault simulations pass in under two seconds; the collision, bad-update and voting simulations pass. The book builds in CI (book-preview.yml); mdbook is not installed locally.Breaking Changes
None. No consensus, protocol, fee, storage or API change. The only library-visible additions are on the
testing-configfeature (PlatformTestConfig::scheduled_event_host_fault,SCHEDULED_EVENT_HOST_FAULT_MESSAGE); the one spread-lessPlatformTestConfigliteral outsideconfig.rs(voting_tests.rs) gained the field.Decisions taken (provisional values)
run_dao_platform_eventsand beforeprocess_raw_state_transitionsinrun_block_proposal_v0, the processing order the scheduling draft proposes (engineering convention, not an owner decision). When the jobs phase lands, the hook moves inside it.process_proposalwith the same exception a storage fault produces; the chain-lock Reject path is documented, not driven (driving it needs a second mock Core RPC with the harness's masternode data).Err(ExecutionError::CorruptedCodeExecution); a panic in the same phase is documented as equivalent in network effect.dashpay/tenderdash:1.7). Write-ahead-log replay is modelled as re-delivering the identicalRequestProcessProposalto the restarted node; the proposer-side re-prepare is not part of replay.Checklist:
For repository code-owners and collaborators only
Dash-Tasks: FIX-03
🤖 Generated with Claude Code
🤖 Posted autonomously by DashVM (Claude Fable 5.1) on behalf of pasta.
Automated reviewer consensus (Fable 5.1 implementer, GPT-6 Astra reviewer)
Reviewer consensus
Plan Review consensus
resolvedresolvedReview consensus
noted