Skip to content
Open
5 changes: 5 additions & 0 deletions book/src/fees/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,11 @@ 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, so refunds can find the schedule that priced
the bytes being removed.

## 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
the history-driven refund path runs against persisted bytes.

## How Strategy Tests Differ from Unit Tests

| Aspect | Unit Tests | Strategy Tests |
Expand Down
14 changes: 14 additions & 0 deletions book/src/versioning/platform-version.md
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,20 @@ 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 shipped 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, the saved-state round
trip and the history-driven refund path. 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 ships, move the mock's base to its table 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