Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
dc140ee
test(platform): add a mock fee generation with doubled storage and a …
DCG-Claude Sep 12, 2026
4182a76
fix(drive-abci): record the genesis fee generation in the initial pla…
DCG-Claude Sep 12, 2026
4caf506
test(drive-abci): pin storage refunds on either side of a fee-generat…
DCG-Claude Sep 12, 2026
423ef28
test(strategy-tests): replay a chain across a fee-generation boundary…
DCG-Claude Sep 12, 2026
a66c793
test(strategy-tests): sign chain locks and keep the workload across t…
DCG-Claude Sep 12, 2026
9ec6d87
docs(book): describe the mock fee generation, boundary strategy tests…
DCG-Claude Sep 12, 2026
087c6f4
test(strategy-tests): require a delete that crosses the fee-generatio…
DCG-Claude Sep 12, 2026
509b18d
test(drive-abci): follow the rebased saved-state and document id rule…
DCG-Claude Sep 24, 2026
8e774b9
test(platform): compare whole fee schedules after the saved-state rou…
DCG-Claude Oct 26, 2026
0b6b4dc
docs(book): show the mock version registry with its current default set
DCG-Claude Oct 26, 2026
2275184
fix(drive-abci): return an error for an unknown fee version in a save…
DCG-Claude Oct 26, 2026
e7e4a13
test(drive-abci): record submitted strategy transitions only when a t…
DCG-Claude Oct 26, 2026
60b345e
test(drive-abci): match the typed error for an unknown saved fee version
DCG-Claude Oct 26, 2026
172f7e5
Merge remote-tracking branch 'origin/v5.1-dev' into dashvm/r05-05
QuantumExplorer Nov 3, 2026
df8de4a
test(platform-version): base the doubled-storage mock on FEE_VERSION4
QuantumExplorer Nov 3, 2026
8cae901
Merge remote-tracking branch 'origin/v5.1-dev' into dashvm/r05-05
DCG-Claude Nov 9, 2026
883001f
test(drive-abci): price boundary refunds from the storing epoch's rec…
DCG-Claude Nov 9, 2026
c358297
test(drive-abci): describe the genesis fee entry as history and requi…
DCG-Claude Nov 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions book/src/fees/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,12 @@ Fee versions are stored in the `FEE_VERSIONS` array and looked up by number. The
`uses_version_fee_multiplier_permille` field allows a global scaling factor
(permille = divide by 1000; a value of 1000 means no change).

The platform state keeps a fee history keyed by epoch: the genesis generation
is recorded when the chain is initialised, and each later generation at the
epoch change that activates it. The history is saved with the state, and a
saved state naming a number the build does not know fails to load. Refunds do
not read it: they take the storing epoch's rate as described above.

## Key Source Files

| File | Contents |
Expand Down
30 changes: 30 additions & 0 deletions book/src/testing/strategy-tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,36 @@ let continued = continue_chain_for_strategy(
This is invaluable for testing restart scenarios and verifying that state persists
correctly across platform restarts.

A continuation is not automatically the same workload as an uninterrupted run:
`continue_chain_for_strategy` reseeds its random generator from the
`StrategyRandomness` it is given, and `state_transitions_for_block` redeploys
any `start_contracts` still in the strategy at the continuation's first block.
To compare a continued run with an uninterrupted one, split both at the same
block, hand the second segment the mutated `strategy` the first segment
returned (its operations are remapped to the deployed contract id; clear its
`start_contracts`, which the harness puts back after deploying them), the
`identities`, the `signer` and the nonce counters, and reseed both
continuations from the same entropy. `state_transitions_per_block`
on the outcome lists what the strategy submitted per block, so a test can prove
the two runs executed one workload before comparing their results.

### Crossing a Fee-Version Boundary

`test_cases/fee_version_boundary_tests.rs` upgrades a chain from the latest
protocol version to the `TEST_PLATFORM_V4` mock, whose only difference is a fee
generation with a doubled storage rate (see the versioning chapter's mock
versions section). With `upgrading_info` voting for the mock from block 1 and
60 blocks per epoch, epoch 0 collects the votes, the first block of epoch 1
locks the mock in, and the first block of epoch 2 activates it and records the
new generation in the fee history. Each simulation runs the same workload
twice, continuously and reopened from the persisted state at the same block
(`store_platform_state: true`, then `TempPlatform::open_with_tempdir`), with
`independent_process_proposal_verification` on so every block is also
validated as a non-proposer. The two runs must agree on the root hash, the
per-block transition results, the identity balances and the fee history, and
at least one document written before the boundary must be deleted after it so
a refund priced at the storing epoch's rate runs against persisted bytes.

## How Strategy Tests Differ from Unit Tests

| Aspect | Unit Tests | Strategy Tests |
Expand Down
20 changes: 19 additions & 1 deletion book/src/versioning/platform-version.md
Original file line number Diff line number Diff line change
Expand Up @@ -360,8 +360,9 @@ specific behaviors without polluting the production constants:
{
if version >> TEST_PROTOCOL_VERSION_SHIFT_BYTES > 0 {
let test_version = version - (1 << TEST_PROTOCOL_VERSION_SHIFT_BYTES);
// DEFAULT_PLATFORM_TEST_VERSIONS is [TEST_PLATFORM_V2, TEST_PLATFORM_V3, TEST_PLATFORM_V4]
let versions = PLATFORM_TEST_VERSIONS
.get_or_init(|| vec![TEST_PLATFORM_V2, TEST_PLATFORM_V3]);
.get_or_init(|| Vec::from(DEFAULT_PLATFORM_TEST_VERSIONS));
return versions.get(test_version as usize - 2).ok_or(/* ... */);
}
}
Expand All @@ -371,6 +372,23 @@ This is a clever design: tests can exercise version upgrade logic (like
"what happens when we transition from test version 2 to test version 3?")
without needing to create real protocol versions.

`TEST_PLATFORM_V4` (`version/mocks/v4_test.rs`) is the latest protocol
version's tables with one substitution: its fee schedule is
`TEST_FEE_VERSION_DOUBLED_STORAGE`
(`version/mocks/fee_doubled_storage_test.rs`), the latest schedule with a new
`fee_version_number` and a doubled storage disk usage rate. No shipped schedule
carries a number other than 1, so this is the only fee generation that
exercises the registry lookup, the epoch-change hook and the saved-state round
trip of the fee history, and a refund of bytes stored in an epoch that ran the
mock is priced at its doubled rate. Its number sits in the same shifted
range as the mock protocol versions (`(1 << TEST_PROTOCOL_VERSION_SHIFT_BYTES)
+ 1`), and `FeeVersion::get` resolves that range through the test registry only
under `mock-versions`: a production node that finds such a number in its saved
state rejects it instead of falling back to a real schedule. When a new
protocol version is introduced, move the mock's base to its table, and the
doubled-storage schedule to its fee schedule, so it keeps tracking the latest
behaviour.

## Why Immutable Snapshots?

You might wonder: why not use a mutable configuration object? Why not a
Expand Down
Loading
Loading