Skip to main content

platform_version/version/
v14.rs

1use crate::version::consensus_versions::ConsensusVersions;
2use crate::version::dpp_versions::dpp_asset_lock_versions::v1::DPP_ASSET_LOCK_VERSIONS_V1;
3use crate::version::dpp_versions::dpp_contract_versions::v6::CONTRACT_VERSIONS_V6;
4use crate::version::dpp_versions::dpp_costs_versions::v1::DPP_COSTS_VERSIONS_V1;
5use crate::version::dpp_versions::dpp_document_versions::v4::DOCUMENT_VERSIONS_V4;
6use crate::version::dpp_versions::dpp_factory_versions::v1::DPP_FACTORY_VERSIONS_V1;
7use crate::version::dpp_versions::dpp_identity_versions::v1::IDENTITY_VERSIONS_V1;
8use crate::version::dpp_versions::dpp_method_versions::v3::DPP_METHOD_VERSIONS_V3;
9use crate::version::dpp_versions::dpp_state_transition_conversion_versions::v2::STATE_TRANSITION_CONVERSION_VERSIONS_V2;
10use crate::version::dpp_versions::dpp_state_transition_method_versions::v2::STATE_TRANSITION_METHOD_VERSIONS_V2;
11use crate::version::dpp_versions::dpp_state_transition_serialization_versions::v3::STATE_TRANSITION_SERIALIZATION_VERSIONS_V3;
12use crate::version::dpp_versions::dpp_state_transition_versions::v4::STATE_TRANSITION_VERSIONS_V4;
13use crate::version::dpp_versions::dpp_token_versions::v3::TOKEN_VERSIONS_V3;
14use crate::version::dpp_versions::dpp_validation_versions::v5::DPP_VALIDATION_VERSIONS_V5;
15use crate::version::dpp_versions::dpp_voting_versions::v2::VOTING_VERSION_V2;
16use crate::version::dpp_versions::DPPVersion;
17use crate::version::drive_abci_versions::drive_abci_checkpoint_parameters::v1::DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1;
18use crate::version::drive_abci_versions::drive_abci_method_versions::v10::DRIVE_ABCI_METHOD_VERSIONS_V10;
19use crate::version::drive_abci_versions::drive_abci_query_versions::v2::DRIVE_ABCI_QUERY_VERSIONS_V2;
20use crate::version::drive_abci_versions::drive_abci_structure_versions::v2::DRIVE_ABCI_STRUCTURE_VERSIONS_V2;
21use crate::version::drive_abci_versions::drive_abci_validation_versions::v10::DRIVE_ABCI_VALIDATION_VERSIONS_V10;
22use crate::version::drive_abci_versions::drive_abci_withdrawal_constants::v3::DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V3;
23use crate::version::drive_abci_versions::DriveAbciVersion;
24use crate::version::drive_versions::v9::DRIVE_VERSION_V9;
25use crate::version::fee::v3::FEE_VERSION3;
26use crate::version::protocol_version::PlatformVersion;
27use crate::version::system_data_contract_versions::v3::SYSTEM_DATA_CONTRACT_VERSIONS_V3;
28use crate::version::system_limits::v4::SYSTEM_LIMITS_V4;
29use crate::version::ProtocolVersion;
30
31pub const PROTOCOL_VERSION_14: ProtocolVersion = 14;
32
33/// v14 hosts thirty-one consensus changes:
34///
35/// 1. **Contract-level ranked aggregates**: an index can
36///    declare that its groups are rankable by an aggregate, so a query like
37///    "top 5 restaurants by average grade" is served from an ordered
38///    secondary tree in O(log n + k) with a proof, instead of being rejected.
39/// 2. **The shared-prefix aggregate index fix**: a data contract declaring
40///    an aggregating (countable / summable) index that terminates at a
41///    property which is also the prefix of a compound index (e.g. summable
42///    `[a]` next to `[a, b]`) registered successfully but rejected every
43///    document insert for most flag combinations, because Drive could not
44///    legally hang the compound continuation tree under the aggregating
45///    per-value tree. The v2 document index walkers (plus the v1 update
46///    walker) that fix it gate here as well: tree types derive through a
47///    shared continuation-demotion helper (provable count-bearing value
48///    trees with compound continuations demote to `CountSumTree`, since
49///    grovedb rejects count-suppressed children under provable count
50///    parents by design) and continuation inserts route through the
51///    completed zero-contribution wrapper matrix. No state migration is
52///    needed: shapes without compound continuations produce bit-identical
53///    operations, the broken shapes could never hold documents, and the
54///    one previously-insertable shape the demotion changes (a provable
55///    count-bearing value tree whose continuations were all sum-bearing —
56///    insertable pre-v14 only through an unenforced grovedb batch guard)
57///    simply gets `CountSumTree` value trees for values first seen at
58///    v14+, which readers treat identically.
59/// 3. **The contested vote poll index cross-check**: the index named by a
60///    document create transition's prefunded voting balance keys the vote
61///    poll, its stored info, its end-date entry and its prefunded
62///    specialized balance, while the contested index the contender is
63///    inserted under always comes from the document type. Up to v13 nothing
64///    tied the two together, so a submitter could register and fund a
65///    contest under a vote poll describing a different index than the one
66///    the contest was created on — which halts the chain when that poll
67///    ends — or open a contest for a document that is not a contested
68///    resource at all. State validation also prevents a non-contested create
69///    from occupying a live contested document's id before the contest winner
70///    is awarded into primary storage. Drive's contested insert also recreates
71///    an abstain or lock vote tree over the storage an earlier poll's cleanup
72///    left orphaned (it only removed the trees that received votes), so a
73///    resource can be contested again instead of failing with
74///    `CorruptedContractIndexes`.
75/// 4. **Relative daily withdrawal limit**: the flat 2000 Dash per 24 hours that
76///    applied from v8 becomes 15% of the total credits Platform held a day ago
77///    (`SYSTEM_LIMITS_V4.daily_withdrawal_limit_percent`, read by
78///    `daily_withdrawal_limit` v2 through `DPP_METHOD_VERSIONS_V3`), never below
79///    one maximal withdrawal (`max_withdrawal_amount`) so every accepted
80///    withdrawal eventually fits and cannot block the pooling queue. The base has
81///    no fixed cap: what Core will mine bounds pooling through the Core-anchored
82///    limit of note 74 instead. The credit inflows of the active window — every
83///    credit mint, recorded per block by `record_credit_inflows_for_withdrawals`
84///    in the credit inflows sum tree — are added to the base, so the limit
85///    counts net outflow and a matching deposit -> withdraw cycle does not
86///    consume the budget of other users (#4471), mirroring Core v24's net
87///    credit-pool rule. Both the inflows and the pooled reservations count over the
88///    interval after the base snapshot only — an entry the snapshot already
89///    reflects is neither added nor subtracted again. The base is
90///    the total credits recorded at the latest block at least 24 hours before
91///    the current one: `DRIVE_ABCI_METHOD_VERSIONS_V10` turns on
92///    `record_total_credits_history_for_withdrawals`, which checks the total
93///    credits every block once fees and epoch rewards are in, writes it under
94///    the withdrawals tree keyed by block time whenever it changed (an entry
95///    describes the total until the next one) and prunes entries older than the
96///    one the limit reads, and `DRIVE_VERSION_V9`'s identity withdrawal table
97///    bumps `calculate_current_withdrawal_limit` to 1 to read that lagged
98///    value. Until an entry is a day old — the first day after activation — the
99///    flat 2000 Dash keeps applying, so the lag cannot be skipped by inflating
100///    the total before or at activation. The lag is the guardrail: a sudden
101///    jump in the total credits does not raise the limit for a day. Amounts
102///    already pooled in the last 24 hours keep counting against the maximum
103///    exactly as before. Pre-V24 Core caps unlocks at `LimitAmountV22` (2000
104///    Dash) per *block*, with the amount checked only at block level, so any
105///    daily total is still minable across blocks; V24 limits the net drop of
106///    its credit pool per 576-block window, which note 74 follows.
107/// 5. **Time-range indexes**: an index can declare a `timeRange` transform
108///    that buckets a required system timestamp (`$createdAt` /
109///    `$updatedAt` / `$transferredAt`) into fixed-length, regularly-spaced,
110///    optionally overlapping windows declared in seconds (`range` / `step`,
111///    plus an optional `phase < step` alignment offset). Each grid gets its
112///    own index subtree — the level is keyed by the property name qualified
113///    with the grid — so several grids may bucket one timestamp side by
114///    side. A document is stored once per containing bucket per grid (the
115///    v2 insert/delete and v1 update walkers carry the fan-out; the
116///    per-document write amplification is capped per index by
117///    `SystemLimits::max_time_range_overlap_factor`), and the v1
118///    `getDocuments` handler resolves the new `IN_TIME_RANGE` operator —
119///    a typed `TimeRangeSelection` operand: `NEWEST`/`OLDEST` (resolved to
120///    a bucket-start equality from committed block time) or `BY_START`
121///    (naming any window, current or historic, by its grid-aligned start),
122///    with a `grid` member naming one grid where several bucket the field
123///    — making trending/leaderboard document and count/sum/avg queries
124///    provable over the current or any named window. `unique: true` is
125///    admitted only for non-overlapping windows (`range == step`) sourced
126///    from the immutable `$createdAt`.
127/// 6. **Deterministic token reward math**: `DistributionFunction::evaluate`
128///    (logarithmic, inverted-logarithmic, exponential and polynomial perpetual
129///    distributions) computes `ln`/`exp`/`pow` through the pinned pure-Rust
130///    `libm` crate instead of the platform C library. musl's `log` takes an
131///    FMA path on aarch64 and a non-FMA path on x86_64, so the two disagree by
132///    1 ulp on some inputs; a contract owner could pick parameters whose reward
133///    sat within that ulp of an integer, and `floor` then minted different
134///    amounts on the two architectures, splitting the app hash both at claim
135///    time and at contract registration (validation evaluates the start
136///    value). Gated on `distribution_function_evaluate_version` so both
137///    architectures switch at the same height; pre-v14 blocks replay on the
138///    old math byte-for-byte. `log`/`exp` have no architecture dispatch and
139///    `pow`'s only arch-touching call is the correctly-rounded `sqrt`, so the
140///    result is bit-identical on every target Platform builds for. The goal
141///    is determinism, not correct rounding: on a boundary tuple the host
142///    libm (glibc, macOS) can still be 1 ulp away, so anything predicting
143///    rewards with host math may differ from consensus by one unit.
144///
145/// The first two are orthogonal by construction: the ranked upgrade decides the
146/// *property-name* tree type, the demotion decides the *value* tree type
147/// one level below it, and a demoted `CountSumTree` value tree contributes
148/// its (count, sum) to a ranked indexed parent exactly as the provable
149/// variant did — so ranked secondaries keep ranking correctly over
150/// shared-prefix shapes.
151///
152/// Until a contract uses the ranked or time-range grammar, those features
153/// change nothing. Every other change these notes describe applies
154/// regardless, including the table changes below, some of which touch no
155/// contract (identity creation, for one):
156///
157/// * `CONTRACT_VERSIONS_V6` points `document_type_schema` at the v3 document
158///   meta-schema, which hosts the ranked index keywords
159///   (`rankedCountable` / `rankedSummable` / `rankedAverageable`), the
160///   `refersTo` reference keyword and the `timeRange` index transform. v13
161///   keeps validating against meta-schema v2, where those keys are rejected
162///   as unknown properties, so a pre-v14 contract cannot smuggle them in.
163///   It also bumps `validate_schema_compatibility` to 1, which strips the
164///   top-level `indices` key before diffing the old and new document type
165///   schemas: index immutability is enforced by `validate_update` v1's
166///   name-keyed comparison, so a contract update that merely reorders the
167///   `indices` array validates cleanly instead of hitting the
168///   unsupported-keyword hard error (an internal error under v13).
169/// * `DRIVE_VERSION_V9` carries `DRIVE_DOCUMENT_METHOD_VERSIONS_V4`, adding
170///   the `detect_ranked_mode` routing slot, plus the grove-method slots for
171///   creating the three indexed tree variants and the verify-method slot for
172///   `verify_ranked_top_k_proof`. All are 0 today. The same table bumps the
173///   four index walkers to v2 and the document update walker to v1 for the
174///   shared-prefix fix; those same walker versions carry the time-range
175///   bucket fan-out, so both features gate on one table entry. It also sets
176///   `insert_contested.fetch_charter_election_windows` to `Some(0)`: a
177///   moderation election (an `electedCharter` contest) runs on its target
178///   contract's join and vote windows, which the document create join check
179///   and the contested insert read.
180/// * `DRIVE_ABCI_QUERY_VERSIONS_V2` bumps
181///   `document_query_helpers.compute_aggregate_mode_and_check_limit` 0 → 2,
182///   opening two routes on the v1 document-query handler: the ranked path
183///   (a grouped aggregate whose single `order_by` names the selected
184///   aggregate — `ORDER BY <agg> [ASC|DESC] LIMIT n [OFFSET m]`) and the
185///   boolean-`HAVING` range path (a grouped aggregate carrying exactly one
186///   `having` clause on the selected aggregate — `GROUP BY p HAVING <agg>
187///   <op> <value> LIMIT n`), the latter served as a value-bounded range
188///   read of the covering ranked index's axis secondary. v13 and earlier
189///   keep the v1 table and therefore keep rejecting both shapes, so
190///   mixed-version networks agree across the upgrade. The same table accepts
191///   `getIdentityByNonUniquePublicKeyHash` request V1, answered with one proof
192///   of the index selection and the identity; V0 keeps its separate proofs and
193///   stays accepted, and v13 and earlier refuse V1 as 4.1 nodes do.
194/// * `DRIVE_ABCI_VALIDATION_VERSIONS_V10` bumps
195///   `document_create_transition_structure_validation` 0 → 1, requiring a
196///   contested create transition's prefunded voting balance to name the
197///   same vote poll the document itself resolves to, and rejecting one on a
198///   document that resolves to no contested index. It also bumps document
199///   create state validation to 2, enforcing `refersTo` document references
200///   and rejecting a non-contested create whose id is already present in the
201///   contested tree. Document replace state validation 1 enforces the same
202///   reference checks, re-validates a `refersTo: deletableDocument`
203///   reference on every replace (a dead one must be repointed or cleared),
204///   and lets an `immutable` one be cleared once its target is deleted.
205///   Document create structure validation 1 and replace structure
206///   validation 0 (extended in place) refuse a `distinctFrom` identifier
207///   property equal to the value it must differ from
208///   (`DocumentPropertyNotDistinctError`, 10419); transfer and purchase
209///   structure validation 0, extended in place, judge the stored document's
210///   `$ownerId` declarations against the new owner.
211///   v13 keeps the v9 table and therefore keeps accepting all of these, so
212///   replay of pre-upgrade blocks is unchanged.
213/// * `DRIVE_ABCI_VALIDATION_VERSIONS_V10` also bumps the identity create from
214///   addresses `advanced_structure` 0 → 1: a key whose proof of possession fails
215///   is refused unpaid instead of charging the inputs a penalty, since the
216///   address witnesses do not sign those proofs. v13 keeps the paid refusal of v0.
217/// * `DRIVE_ABCI_VALIDATION_VERSIONS_V10` also bumps the identity create
218///   `advanced_structure` 0 → 1: an identity id other than the one the asset lock
219///   derives and a key whose proof of possession fails are refused unpaid instead of
220///   charging the asset lock a penalty, since the asset lock signature covers
221///   neither the identity id nor the key signatures. A key structure failure is
222///   still charged. v13 keeps the paid refusals of v0.
223/// * `DOCUMENT_VERSIONS_V4` bumps `document_serialization_version` to
224///   default 3: documents are stamped with the contract version their bytes
225///   conform to (a varint after the format prefix), enabling the
226///   `requiredSince` property keyword — a contract update may add a new
227///   required property annotated with the version that update creates.
228///   Documents stamped below a property's `requiredSince` keep the
229///   presence-flagged layout they were written with, so the latest contract
230///   alone reconstructs every stamp's layout and no historical contract
231///   lookups are ever needed. Reads dispatch on the byte prefix, so
232///   formats 0–2 (all pre-v14 documents) deserialize exactly as before with
233///   an unstamped (pre-annotation) layout.
234/// 7. **Client-side GroveDB proof envelope floor (not a version-table
235///    entry)**: clients refuse the legacy V0 proof envelope at every protocol
236///    version through
237///    `drive::verify::grovedb_proof_envelope::MINIMUM_GROVEDB_PROOF_ENVELOPE_VERSION`,
238///    so nothing about it is gated on v14. The note keeps its number so the
239///    later notes keep theirs.
240/// 8. **Epoch-based perpetual distribution claims stop wrapping**:
241///    `RewardDistributionType::max_cycle_moment` (the cap on how far one claim
242///    may redeem, selected by
243///    `TOKEN_VERSIONS_V3.reward_distribution_max_cycle_moment_version` 1)
244///    computes `start + interval * cycles` in `u64` with saturating
245///    arithmetic and narrows back to `EpochIndex` only after capping at the
246///    last completed cycle moment (`current cycle moment - interval`, the
247///    previous epoch for an interval of one as before; for wider intervals the
248///    same cycles are paid, but the cap now sits on a cycle boundary, the only
249///    shape in which `evaluate_interval`'s fixed-amount step count and its
250///    per-cycle loop agree). Up to v13 the sum was taken in `u16`: a
251///    fixed-amount function allows 32,767 cycles, so any epoch interval of
252///    three or more with a nonzero start (or two with a start at epoch two
253///    or later) pushed the cap past `u16::MAX`. Release builds wrap, the cap landed below the
254///    start, `evaluate_interval` saw an empty range and the claim was
255///    refused with `InvalidTokenClaimNoCurrentRewards` on every attempt. The
256///    v0 arithmetic is kept, wrapping explicitly, so those refusals replay.
257/// 9. **Evonode reward cycles weighted by the epochs they span**: the
258///    per-cycle evaluator in `DistributionFunction::evaluate_interval` asks
259///    the participation ratio for the epochs a cycle covers
260///    (`TOKEN_VERSIONS_V3.distribution_function_cycle_epochs_version` 1:
261///    `cycle moment - interval + 1 ..= cycle moment`). Up to v13 it passed the
262///    cycle's step index as if it were an epoch, which coincides only for an
263///    interval of one; for a wider interval it named epochs before the
264///    distribution started, outside the epoch window the claim loads, and an
265///    `EvonodesByParticipation` claim with a function other than a fixed
266///    amount failed as an internal error (reachable only once item 8 let the
267///    cap stop wrapping). Interval-one distributions are unchanged.
268/// 10. **A zero epoch interval is rejected at registration**:
269///     `RewardDistributionType::validate_structure_interval` v1
270///     (`CONTRACT_VERSIONS_V6.token_versions.validate_structure_interval`)
271///     refuses an `EpochBasedDistribution` with `interval: 0` with the new
272///     `InvalidTokenDistributionEpochIntervalTooShortError` (code 10828) on
273///     contract create and update. Up to v13 the epoch arm enforced nothing,
274///     so such a contract registered and every claim on it failed as an
275///     internal error, since no cycle can be computed from a zero step. Block
276///     and time minimums are unchanged.
277/// 11. **Gas paid by the contract owner**: a token-paid document action's
278///     `gasFeesPaidBy` (offered by the document type's token cost, asked for by
279///     the transition's `$tokenPaymentInfo`) is acted on. Both values were
280///     carried but ignored up to v13, where the signer always paid. Batch
281///     transform v2 resolves one payer for the batch (`GasFeesPaidBy::resolve`)
282///     and reads the contract owner's balance into the action; batch advanced
283///     structure v1 refuses a request the document type does not offer
284///     (`GasFeesPaidByNotAllowedError`, 40129) or a batch naming two payers
285///     (`InconsistentGasFeesPaidByInBatchError`, 40130); `validate_fees_of_event`
286///     v1 judges the fee against the sponsor's balance, refusing an insisting
287///     batch unpaid when it falls short (`GasSponsorInsufficientBalanceError`,
288///     40222) and handing a preferring one back to the signer; `execute_event`
289///     v1 charges whoever was admitted. The batch's signer funds the principal
290///     and the processing fee its own `user_fee_increase` adds: the sponsor is
291///     judged on and charged the fee without the increase, the signer's balance
292///     and key budget have to cover the increase (refused unpaid with
293///     `IdentityInsufficientBalanceError`, 40210, when the balance does not),
294///     and execution charges it to the signer as a fee of its own. Its minimum
295///     balance pre-check v1
296///     (`identity_minimum_balance_pre_check`) asks no more of a batch that
297///     requests sponsorship. A failed batch is never sponsored, so check tx
298///     validates the state of a sponsored batch whose signer is under the fee
299///     minimum in full, on the first check and on every recheck (mempool
300///     policy, not consensus).
301/// 12. **Optional token costs**: a document type's token cost may declare
302///     `optional: true` (v3 meta-schema). A transition that leaves
303///     `$tokenPaymentInfo` out then pays no token and its signer pays the gas
304///     in credits, as on an action without a token cost (the base action
305///     transformer waives the cost, and no sponsorship applies). With the
306///     payment info present the token is charged exactly as for a required
307///     cost, and too small a token balance stays a rejection. Contracts up to
308///     v13 cannot carry the flag, so the waiver is inert before this version.
309/// 13. **Pre-programmed distribution amounts are bounded**:
310///     `TokenPreProgrammedDistribution::validate_amounts` rejects a release
311///     whose amounts total more than `i64::MAX` with the new
312///     `PreProgrammedDistributionAmountOverLimitError` (code 10277). It runs
313///     on contract create (`DRIVE_ABCI_VALIDATION_VERSIONS_V10`'s create
314///     `basic_structure` 2) and, for the tokens an update adds, on contract
315///     update (`CONTRACT_VERSIONS_V6`'s `validate_update` 1). A release is
316///     stored as a sum tree, so up to v13 such a create passed validation and
317///     failed inside Drive as an internal error: never paid for, and stripped
318///     from every proposal. An update failed the same way on a single amount
319///     over the limit (its fee estimation takes the insert path), but was
320///     accepted when only the total overflowed, since it wrote no distribution
321///     storage; from v14 it writes it (`update_contract` 2) and would fail.
322///     Tokens a contract already has are not judged, so a contract holding
323///     such a token stays updatable.
324/// 14. **Tokens of one contract sharing a pre-programmed release time**:
325///     `DRIVE_TOKEN_METHOD_VERSIONS_V2` bumps
326///     `add_pre_programmed_distributions` to 1, which queues the release-time
327///     tree the tokens share once instead of once per token. Queued twice,
328///     the batch is refused as an internal error by a node with
329///     `batching_consistency_verification` on; the default is off, and there
330///     GroveDB folds the identical inserts, so the stored state is unchanged
331///     and only the processing fee drops, by the existence read the later
332///     tokens no longer make.
333///
334/// 15. **Tokens added by a contract update are set up like registered ones**:
335///     `update_contract` v2 (`DRIVE_CONTRACT_METHOD_VERSIONS_V4`) creates the
336///     perpetual, pre-programmed and once-per-identity distribution storage
337///     of a token the update adds, and mints its base supply to the token's
338///     `newTokensDestinationIdentity`, or to the contract owner without one,
339///     with the total supply starting at the base supply. v1 did neither: a
340///     claim on such a token failed as an internal error, and the token sat at
341///     a total supply of zero with nobody holding any of it. Nothing is minted
342///     retroactively for a token an update added under an earlier version.
343///
344/// 16. **Contract moderation**: a data contract may declare, in its config,
345///     a banlist and/or a suspension list of identities and who edits them
346///     (the owner, or the owner and up to `SystemLimits::max_contract_moderators`
347///     named identities, each of which must exist). `CONTRACT_VERSIONS_V6`
348///     makes config V2 the config of every new contract (`max_version` and
349///     `default_current_version` 2), which carries
350///     the declaration; a contract create or update carrying a V2 config is
351///     inactive before this version (`StateTransition::active_version_range`).
352///     `DPP_VALIDATION_VERSIONS_V5.validate_config_update = 2` fixes the lists
353///     a contract keeps at its creation: an update turns none on and none off,
354///     and may only change the moderators.
355///     `ContractUserModeration` (state transition type 24, gated by
356///     `CONTRACT_USER_MODERATION_INITIAL_PROTOCOL_VERSION`) bans, unbans,
357///     suspends until a block time (at most
358///     `SystemLimits::max_contract_suspension_until`) and unsuspends one
359///     identity, signed by the owner or a moderator with a CRITICAL key; a
360///     ban and a suspension carry a reason, stored with the entry: a text of
361///     at most `SystemLimits::max_contract_moderation_reason_length` bytes,
362///     an optional code nothing checks, reserved for ban codes a contract may
363///     declare in a later version, and up to
364///     `SystemLimits::max_contract_moderation_reason_documents` documents the
365///     reason is about, named by type and id and not looked up. A contract may also keep a warning list
366///     (`[64, contract, 2] / 224`): a warn appends a warning, the block time and
367///     a reason, to the identity's entry, at most
368///     `SystemLimits::max_contract_warnings_per_identity` at a time, and a
369///     clearWarnings deletes the entry; warnings bar nothing and are what a
370///     status query and the identity's clients read;
371///     `DRIVE_ABCI_VALIDATION_VERSIONS_V10` turns its gates on, moves the
372///     contract update's basic structure to 2 and the contract create and
373///     update state validation (already 1 here) checks the named moderators.
374///     `batch_state_transition.contract_moderation_gate = Some(0)` makes the
375///     batch transformer refuse, paid, the document transitions of a banned or
376///     suspended signer, its deletions excepted (and its retractions, item 72),
377///     and collect a lapsed
378///     suspension, which
379///     `documents_batch_transition` 1 (`DRIVE_STATE_TRANSITION_METHOD_VERSIONS_V4`)
380///     deletes when the batch executes; the same field gates the other
381///     party of a transfer or a purchase, so a barred identity neither
382///     receives nor sells a document. Token transitions are not gated.
383///     `DRIVE_CONTRACT_METHOD_VERSIONS_V4` bumps `insert_contract` to 2,
384///     which creates the list trees (`[64, contract, 2] / 128`, `/ 192` and `/ 224`, inside the contract's other tree), and
385///     adds the `moderation` method table; the verify and
386///     query tables gain the status and entries methods.
387///
388/// 17. **Document action fees and the contract fee claim**: a document type
389///     may charge a fixed fee in credits for an action on one of its documents
390///     (the `actionFees` keyword of the v3 document meta-schema, read by
391///     `try_from_schema` 3), split between the contract's owner pot and its
392///     moderators pot and priced as written or scaled by the fee multiplier of
393///     the epoch. The fees of a document type never change (document type
394///     `validate_update` 1), and a `moderators` part needs declared moderation
395///     (contract create and update basic structure 2). Whoever pays the gas
396///     pays the fee, the contract owner never into their own owner pot, and
397///     only for an action that executes: `validate_fees_of_event` 1 and
398///     `execute_event` 1 (`DRIVE_ABCI_METHOD_VERSIONS_V10`) settle the payer
399///     and move the credits with the batch's own operations, outside the fee;
400///     `apply_drive_operations` 1 merges every write of one identity balance,
401///     fee pot or prefunded specialized balance in a batch into one, so a fee
402///     leaving the balance a purchase price or a voting fund also leaves takes
403///     both, and refuses a batch writing one token balance or supply twice.
404///     Fee validation estimates for the payer it settles on and hands that
405///     payer to `execute_event` 1.
406///     `DRIVE_CONTRACT_METHOD_VERSIONS_V4` gains the `fee_pots` method table:
407///     the pots are sum items under two sum trees of the prefunded specialized
408///     balances (`[40, 64]` and `[40, 192]`), which `create_initial_state_structure`
409///     4 and the upgrade to this version create, so they stay inside the total
410///     credits the platform checks every block, and the epoch each pot was
411///     last claimed in is an item of the contract's other tree (`32` and `96`).
412///     `ContractFeeClaim` (state transition type 25, gated by
413///     `CONTRACT_FEE_CLAIM_INITIAL_PROTOCOL_VERSION`) pays a pot out, at most
414///     once per epoch each: the owner pot to the contract owner, the moderators
415///     pot in equal shares to the moderation team, what the split leaves over
416///     staying in the pot. `DRIVE_ABCI_VALIDATION_VERSIONS_V10` turns its gates
417///     on, `DRIVE_STATE_TRANSITION_METHOD_VERSIONS_V4` adds its converter, and
418///     the verify table gains `verify_contract_fee_pots`.
419/// 18. **Document ids commit to the identity contract nonce**: up to v13 a new
420///     document's id hashed the contract, owner, document type and the entropy
421///     of the create transition, and the create check only asks whether a
422///     document exists under the id right now. The owner of a deleted
423///     document could therefore create another one under the same id by
424///     reusing the entropy, with different content, and everything that
425///     referenced the id (a `refersTo` property, a like, a moderation removal
426///     record) then pointed at the new content, which defeats
427///     `documentsMutable: false` for a deletable document type.
428///     `DOCUMENT_VERSIONS_V4` sets `generate_document_id` to 1: the id also
429///     hashes a domain tag and the identity contract nonce of the create
430///     transition, which is consumed at most once, so an id can be produced
431///     at most once. The entropy stays in the hash (ids remain
432///     unpredictable) and on the wire (the transition format is unchanged);
433///     batch advanced structure validation 1, which only this version
434///     selects, recomputes the id through `Document::generate_document_id`
435///     and bills both passes of the double SHA-256 by the real preimage
436///     length (4 blocks for most document type names) where v13 bills a
437///     flat 2.
438///     Ids of documents created before the upgrade can not be produced by
439///     the new derivation either. A client that still derives the entropy
440///     only id has every create rejected with
441///     `InvalidDocumentTransitionIdError`. Every create path of the clients
442///     in this repository derives through `Document::generate_document_id`:
443///     `DocumentCreateTransitionV0::from_document` for dpp, rs-sdk and the
444///     bindings built on them, and in wasm-dpp2 the `DocumentCreateTransition`
445///     constructor (which also writes the id back onto the JavaScript
446///     `Document`), `Document.generateId` with its `identityContractNonce`
447///     argument, `setIdForCreation` and the `identityContractNonce`
448///     constructor option.
449/// 19. **Document deletion by moderators**: a document type of a contract
450///     that declares moderation may set `moderatorAbilities.delete` (meta-schema
451///     v3, fixed when the type is created, refused on a type that keeps
452///     history, is indexOnly or restricts creation; for references such a type
453///     is no longer permanent, so a permanentDocument reference refuses it, and
454///     a moderatedDocument or a deletableDocument reference takes it, see 64). A
455///     moderation declaration may then keep
456///     no list at all. `ContractUserModeration` gains the `DeleteDocument`
457///     action: the owner or a moderator deletes a document of such a type,
458///     except the owner's and the moderators' own, with a reason like a
459///     ban's. The deletion leaves a record under the contract
460///     (`[64, contract, 2] / 16 / <document type> / <document id>`: the
461///     document's owner, the moderator, the block time and the reason), paid
462///     for by the moderator and never deleted; `insert_contract` 2 creates
463///     the records tree of each such document type, `update_contract` 2 the
464///     tree of one an update adds, and either the tree above them with the
465///     contract's first. The deleted document's
466///     owner gets no storage refund: `apply_drive_operations = 1`
467///     (`DRIVE_VERSION_V9`) attributes the removal of a batch that carries
468///     the forfeiture to nobody, so the credits stay in the storage pools.
469///     A record is final, since a document id is produced at most once (18).
470///     Neither the type's deletion token cost nor its `actionFees` deletion
471///     fee is charged.
472///     The moderation method table, the verify table and the query table gain
473///     the document removal methods (`getContractDocumentRemovals`).
474///     `moderatorAbilities.deleteWithin` bounds the deletion in time: so many
475///     seconds after a document's last modification (`$updatedAt`, or
476///     `$createdAt` on a type whose documents never change; the type must
477///     require its clock), past which no moderator deletes it, the
478///     contract owner included (`DocumentModerationWindowElapsedError`); a
479///     document's own owner still deletes it as `canBeDeleted` allows. A
480///     replace opens the window again. Fixed with the type, like the flag.
481///
482/// 20. **Document transitions agree to their action fee**: version 2 of the
483///     document base transition, the default from this version
484///     (`STATE_TRANSITION_SERIALIZATION_VERSIONS_V3`) and inactive before it
485///     (`StateTransition::active_version_range`, since earlier software
486///     cannot decode it), carries an action fee agreement: the owner and moderators amounts the signer saw declared,
487///     which must match the document type's exactly, and for a fee priced by
488///     the fee multiplier the multiplier they knew with the increase, in
489///     percent, they accept. Batch advanced structure 1
490///     (`DRIVE_ABCI_VALIDATION_VERSIONS_V10`) refuses, as a paid nonce bump
491///     that charges no fee, an action that charges a fee without an agreement
492///     (40132), with one to other amounts or another pricing (40133), or
493///     whose epoch's multiplier rose beyond the tolerance (40134), so a
494///     contract whose fees change cannot make a signed transition pay them.
495///     Check tx judges the agreements again on every recheck, off the action
496///     the transformer rebuilt with the contract and the multiplier as they
497///     are then, so a batch a block would refuse leaves the mempool instead
498///     of failing there (mempool policy, not consensus).
499///
500/// 21. **Document restore by moderators**: the removal record a moderator's
501///     deletion leaves (19) also holds a double SHA-256 of the document as
502///     serialized under its type at the deletion (`ContractDocumentRemoval::
503///     document_hash`), and `ContractUserModeration` gains the
504///     `RestoreDocument` action: the owner or any current moderator brings
505///     the document back, as it was, within
506///     `SystemLimits::contract_document_restore_window_ms` (a week) of the
507///     removal. The bytes must decode under the type and hash to what the
508///     record holds; refused otherwise, or without a record (41119), past the
509///     window (41120), on a hash mismatch (41121), once restored (41122), or
510///     when another document took a value of one of the type's unique indexes
511///     meanwhile (40105). The document goes back through the ordinary insert,
512///     its storage flags naming its owner (the signer pays, the owner keeps
513///     the refund of a later deletion), and the record is marked restored in
514///     place (`ContractDocumentRemoval::restoration`: who, when) rather than
515///     deleted; a restored document deleted again gets a fresh record in place
516///     of the marked one, which the deletion transform reads to know. Neither
517///     the type's creation token cost nor its `actionFees` creation fee is
518///     charged, and no fee agreement is asked. `moderatorAbilities.delete` is
519///     now also refused on a type with a contested index, whose deletions
520///     could never be undone. The record grows on the wire
521///     (`getContractDocumentRemovals`: `document_hash`, `restoration`).
522///
523/// 22. **Elected moderation teams, the declaration and the interim**: a data
524///     contract may declare, when it is created, that its moderators are a team
525///     elected by masternodes and evonodes (`ContractModerators::Elected`, a third kind
526///     beside the owner and an appointed set, in the same config V2). The
527///     declaration is frozen: the join and vote windows (at most four weeks, at
528///     least one day on mainnet and 0 elsewhere, one week by default), in
529///     seconds and bounded by `SYSTEM_LIMITS_V4`;
530///     whether the seat can be contested again once a team is seated
531///     (`seatContestable`, required with no default), and for a contestable
532///     seat the challenge cool-down (`challengeCoolDown`, in seconds, two weeks
533///     to three years, refused on a seat that can not be contested; in Rust
534///     one `Option<u32>`), which nothing reads until challenges come after
535///     this version, a seat never being contested again here; an optional,
536///     unbounded election delay in seconds after the contract's creation
537///     before the first charter may be filed (`electionDelay`, read by the
538///     `moderation: "electionOpen"` reference requirement of item 24); how many
539///     members a seated team's leader may add after the election
540///     (`maxAddedModerators`, 0 when left out, at most
541///     `SYSTEM_LIMITS_V4.max_contract_moderation_added_moderators`, 15); the
542///     document types the team moderates, each with the abilities the seated
543///     team holds on it; who moderates until the first team is seated (the owner, an
544///     appointed set, or nobody, with the moderated types not yet usable or
545///     used unmoderated meanwhile); and whether the owner is protected from the
546///     team. `validate_moderation_config` v0 checks
547///     it against the contract's document types (10900), and
548///     `validate_config_update` 2 refuses every change to it, and entering or
549///     leaving elected moderation, with `DataContractConfigUpdateError`. The
550///     interim moderators moderate and claim the pot as the merged kinds do;
551///     with nobody named, nobody may claim the moderators pot, which
552///     accumulates for the team to come, and with the types not yet usable
553///     `contract_moderation_gate` v0 refuses, paid, every document transition
554///     of a moderated type (`ContractModeratedDocumentTypeNotYetUsableError`,
555///     41200) until a charter is seated (item 40).
556///
557/// 23. **Contested indexes without a Lock choice, and ties to the earliest
558///     contender**: a contested unique index may declare `"resolution": 1`,
559///     `ContestedIndexResolution::MasternodeVoteNoLocking` (meta-schema v3,
560///     parser generation 3). Such a contest offers no Lock choice
561///     (`VoteChoiceNotAllowedForVotePollError`, 40307, from `validate_state` 1
562///     of the masternode vote) and always ends with a winner. Its end date is
563///     the end of the join window until a second contender joins, when
564///     `add_contested_document_for_contract_operations` 1 moves it to the full
565///     poll duration, removing the join window's end date when no other contest
566///     ends then, so a contest with a single contender is awarded without the
567///     vote window. `check_for_ended_vote_polls` 1 awards a tie to the
568///     **earliest** contender (creation time, block height, core height,
569///     document id) for every resolution, where the shipped rule awarded the
570///     latest; DPNS contests ending from this version on follow the new rule.
571///     Before reading the contests due, it removes any end date left with no
572///     contest among the first `maximum_vote_polls_to_process` due, since each
573///     would take a slot of that read and end nothing.
574///
575/// 24. **Contract references may require elected moderation, a minimum age, a
576///     minimum time since the last update, an owner relation to the writer or
577///     config flags of the referenced contract**: a `contract` `refersTo`
578///     declaration may carry `contractRequirements`, what the referenced
579///     contract must declare beyond existing, with `moderation: "elected"` or
580///     `"electionOpen"` (elected, and the contract's own `electionDelay` since
581///     its creation has passed, or it declares none),
582///     `minimumAgeSeconds` (the contract's recorded creation time must be at
583///     least that many seconds before the block time of the write),
584///     `minimumSecondsSinceUpdate` (the same of the later of its creation and
585///     last update times; a contract without a recorded creation time never
586///     meets either), `owner` (`"self"`: the contract is owned by the
587///     `$ownerId` of the referring document, `"other"`: by anyone else),
588///     `readonly: true` (its config is read-only, so it can never be updated
589///     again), `keepsHistory: true` (its config keeps history) and
590///     `ownerProtected` (its elected moderation declaration protects the owner
591///     from the team, or does not, as the value says; a contract without
592///     elected moderation meets neither value) as the requirements
593///     (meta-schema v3, `apply_property_reference` 0,
594///     `ContractReferenceRequirements` on
595///     `DocumentPropertyReferenceTarget::Contract`). The document reference
596///     validation checks them against the contract it fetched for the
597///     existence check and the write itself (its owner and block time), so
598///     they cost no further read, and refuses the first unmet requirement with
599///     `ReferencedContractRequirementNotMetError` (40135). A replace re-checks
600///     them when it changes the reference. `owner` is judged against the
601///     writer, which a transfer or a purchase changes without any write, so
602///     on a document type whose documents can be transferred or traded a
603///     declaration carrying it is re-checked, whole, on every replace, as a
604///     `$ownerId` writer gate is: the new owner has to repoint the reference,
605///     so registration refuses one held by an `immutable` property of such a
606///     type. The other requirements are facts about the referenced contract and
607///     never bring a reference back. A changed `contractRequirements` is an
608///     incompatible schema change on update.
609///
610/// 25. **Typed arrays of scalars in document schemas**: a document property
611///     may be `type: "array"` with an `items` element schema instead of
612///     `byteArray` (meta-schema v3, `parse_typed_array` 0,
613///     `DocumentPropertyType::TypedArray`). An element is an integer, a
614///     number, a string, a boolean, a byte array or an identifier; objects
615///     and arrays of arrays are refused. On the array `minItems` and
616///     `maxItems` count elements, `maxItems` is required (with `minItems`
617///     not above it) and at most `SYSTEM_LIMITS_V4.max_typed_array_items`
618///     (1024), and `uniqueItems` refuses a document repeating an element. An
619///     element's `enum` has members of the element type only (none on a byte
620///     array or identifier element), and an integer element's `minimum` and
621///     `maximum` are integers; the parser reads them so random documents stay
622///     inside them. The array is stored inline, a varint element count followed by the
623///     elements, each encoded exactly as a required scalar property of its
624///     type: an identifier element is 32 raw bytes, an integer element takes
625///     the width its bounds give it, a fixed-size byte array element is raw.
626///     A contract update may not change how an element encodes
627///     (`validate_update` 1). The array cannot be an index property or one
628///     side of a `propertyAgreement`. Its identifier and byte array elements
629///     are conversion paths (`find_identifier_and_binary_paths` 1). A byte array
630///     refuses `items`, and an identifier (a byte array with the identifier
631///     `contentMediaType`) now refuses `uniqueItems`, which would demand that
632///     no byte repeat.
633///
634/// 26. **Distinct identifier properties**: the `distinctFrom` property
635///     keyword (meta-schema v3, `apply_distinct_from` 0, `DistinctFrom` on
636///     `DocumentProperty`) requires an identifier property's value to differ
637///     from the value of a named property of the same document, or from the
638///     document's `$ownerId`; on the `items` of a typed array of identifiers
639///     it binds every element. A pure structure rule: document create
640///     structure validation 1 and replace structure validation 0 call
641///     `validate_distinct_from_properties` (`validate_distinct_from` 0) on the
642///     transition's data and owner id after the schema validation, transfer
643///     and purchase structure validation 0 call it on the stored document and
644///     its new owner (the three generation-0 modules were extended in place:
645///     the call is inert before this version, where no property carries the
646///     keyword), and each refuses an equal pair with
647///     `DocumentPropertyNotDistinctError` (10419); an absent named property
648///     passes. The parser checks the target at contract
649///     registration and update (it must exist, be an identifier and not be
650///     the declaring property), and a changed `distinctFrom` is an
651///     incompatible schema change on update.
652///
653/// 27. **`encryptedFor` on byte array properties**: a byte array property may
654///     declare how its ciphertext was produced, so wallets read the recipe
655///     from the contract instead of a side channel: `recipient` (an identifier
656///     property of the same document type, or `$ownerId`), `recipientKey` and
657///     `senderKey` (integer properties of the same type bounded to u32,
658///     carrying key ids) and `scheme` (`ecdh-secp256k1-aes256-cbc`, the
659///     dashpay contact request scheme: a 16-byte IV followed by AES-256-CBC
660///     with PKCS7 padding under the ECDH shared key). Meta-schema v3 admits it
661///     on byte arrays that are not identifiers, `apply_encrypted_for` 0 parses
662///     it onto `DocumentProperty::encrypted_for` and checks the three named
663///     properties exist with the right types at registration. Document create
664///     structure validation 1 and replace structure validation 0 (extended in
665///     place, inert before this version) call
666///     `validate_encrypted_property_shapes` (`validate_encrypted_property_shapes`
667///     0, `None` before this version) to check the ciphertext shape of every declared property a transition supplies,
668///     at least the IV plus one block and a multiple of the block, and refuse
669///     it with `InvalidEncryptedPropertyShapeError` (10420). Nothing else about
670///     the ciphertext is verifiable on chain. A changed `encryptedFor` is an
671///     incompatible schema change on update.
672///
673/// 28. **Property and document type names are word characters only**:
674///     meta-schema v3 refuses `-` in a property name (top-level or nested,
675///     and in the property paths of `refersTo` declarations) and generation
676///     3 of the document type parser refuses it in a document type name,
677///     under full validation. Every earlier meta-schema and generation
678///     admitted `-`, which the dotted and `list[]` path syntax was never
679///     written for; a census of every contract create and update on mainnet
680///     and testnet (2026-09-23) found no name carrying one, so nothing stored
681///     is affected. Stored contracts are read as they are.
682///
683/// 29. **Identity key references may require a purpose and a document type
684///     bound**: an `identityPublicKey` `refersTo` declaration may carry
685///     `keyRequirements`, what the referenced key must be beyond existing and
686///     not being disabled, with `purpose` (the key's purpose, by its wire name,
687///     any but `system`) and `boundTo` (the key's contract bounds must be
688///     exactly the declaring contract and the named document type of it) as
689///     the requirements (meta-schema v3, `apply_property_reference` 0,
690///     `IdentityKeyReferenceRequirements` on
691///     `DocumentPropertyReferenceTarget::IdentityPublicKey`).
692///     `create_document_types_from_document_schemas` 1, edited in place (the
693///     check is inert before this version, where no parsed reference carries
694///     requirements), refuses a contract whose `boundTo` names a document type
695///     it does not have or one no key of the required purpose can be bound
696///     to, so the check never needs a second contract fetch and a declared
697///     requirement can be met. The document reference validation
698///     checks the requirements against the key it fetched for the existence
699///     check, so they cost no further read, and refuses the first unmet one
700///     with `ReferencedIdentityKeyRequirementNotMetError` (40136). A changed
701///     `keyRequirements` is an incompatible schema change on update.
702///
703/// 30. **Key references on the key id property**: an `identityPublicKey`
704///     `refersTo` declaration may sit on the key id property itself, an
705///     integer with `minimum` 0 and `maximum` 4294967295 (a `KeyID` is a
706///     `u32`), naming through `identityProperty` whose key the value is:
707///     `"$ownerId"` (the writer), `"$creatorId"` (the document's creator,
708///     only on a document type that records creator ids) or the path of an
709///     identifier property of the same document type (which must exist, be
710///     an identifier and not carry an `identityPublicKey` reference of its
711///     own); the last two are checked at contract registration (40125). The
712///     declaration takes no `keyIdProperty`; the identifier form is unchanged
713///     and every other `refersTo` form stays identifier-only (meta-schema v3,
714///     `apply_property_reference` 0, `DocumentPropertyType::KeyIdWithReference`
715///     over `KeyReferenceIdentityProperty`). At document create and replace the
716///     reference validation reads the key id from the property, resolves the
717///     identity (the writer, the creator the action carries, or the named
718///     property's value; a key id set while that property is unset, or on a
719///     document that records no creator, one written before its type recorded
720///     creator ids, being refused with 40125) and fetches that key, so the key
721///     fetch is the only read; a key that does not exist refuses the write,
722///     paid, with
723///     `ReferencedIdentityKeyNotFoundError` (40123) and a disabled one with
724///     `ReferencedIdentityKeyDisabledError` (40124), as for the identifier
725///     form. A replace re-validates `$ownerId` touched or not, as the
726///     `$ownerId` writer gate is, since the writer may not be the one who
727///     wrote the key id; `$creatorId` when the key id changed; a property
728///     path when the key id or that property changed (a transfer itself is
729///     never checked: the reference governs writing, not holding). A
730///     `keyIdProperty` may not name a property carrying this form (40125 at
731///     registration). `keyRequirements` (item 29) sit on this form exactly
732///     as on the identifier form, checked by the same key check and by the
733///     same `boundTo` registration rule. Adding it to, removing it from or
734///     changing it on an existing property is an incompatible schema change
735///     on update, like the rest of a `refersTo`; a property an update adds
736///     may carry it, so a `$creatorId` one can meet documents written before
737///     their type recorded creator ids.
738///
739/// 31. **`refersTo` on the elements of a typed array**: an identifier element
740///     of a typed array may carry a `refersTo` declaration on its `items`,
741///     which every element then declares (meta-schema v3 `documentArrayItem`
742///     reuses the property `refersTo` definition by `$ref` and refuses
743///     `identityPublicKey` in both forms, which pair one key id with the
744///     reference).
745///     `parse_typed_array` 0 folds it into the element through the same
746///     `apply_property_reference` 0 a scalar identifier goes through, so the
747///     element is `IdentifierWithReference(target)` inside `item_type`, and
748///     `DocumentPropertyType::reference` reports either kind. Contract
749///     registration (`data_contract_reference_validation` 0) checks the
750///     declaration as a single one, and document create state validation 2
751///     and replace state validation 1 (`document_reference_validation` 0,
752///     extended in place: both are only reached from protocol version 14,
753///     where the element arm is the only new path) check every element as a
754///     single reference, refusing the first that fails with that
755///     reference's error (40120, 40127, 40135 and the rest), its path the
756///     element's list path (`reasons[2]`). A replace re-validates the
757///     elements of a changed list the stored list did not hold (the replace
758///     action carries `stored_changed_values`), and all of them when a
759///     property bound by a `propertyAgreement` changed, for a `$ownerId`
760///     agreement or for `deletableDocument` elements. A repeated element and
761///     a foreign contract holding the referenced document type are fetched
762///     once per list. Registration caps the references one document
763///     can carry at `SYSTEM_LIMITS_V4.max_references_per_document` (256; one
764///     per property declaring a reference, key id references of item 30
765///     included, `maxItems` per typed array of referencing elements;
766///     backfilled into the earlier tables), and
767///     refuses an `immutable` property holding a `deletableDocument`
768///     reference no replace could clear (a typed array of them, or a single
769///     one inside an immutable object), which could never be replaced once
770///     a target is deleted, and a single top-level one frozen only under a
771///     condition (see 66), which a replace could clear once its target is
772///     deleted and a later one the condition leaves free set to another
773///     document. A changed
774///     element `refersTo` is an incompatible schema change on update.
775///
776/// 32. **Document references resolved through a unique index**: a
777///     `permanentDocument` `refersTo`, on an identifier property or on the
778///     elements of a typed array (item 31), may carry a `lookup`
779///     (meta-schema v3, `apply_property_reference` 0, parsed to the appended
780///     `DocumentPropertyReferenceTarget::PermanentDocumentLookup`, so an id
781///     reference keeps its variant and its encoding): the value is then
782///     not the referenced document's id, and the referenced document is the
783///     one the named unique index of the referenced document type finds for
784///     a key assembled from the referring document. `keys` maps every index
785///     property to a property path of the referring type, `$ownerId` or `.`
786///     (the value, or the element, exactly once). A `deletableDocument`
787///     reference may take one too (`DeletableDocumentLookup`, appended): it
788///     then means a document with this key exists now, since the key may find
789///     a later document once the one it found is deleted, so every replace
790///     re-validates it, an immutable property may not hold it, and it is the
791///     one deletable form a reference expression and `ownerRefersTo` (never
792///     `creatorRefersTo`) take. Generation 3 of the parser
793///     checks on every parse that each property a key reads is a stored,
794///     required, single value of the referring type;
795///     `create_document_types_from_document_schemas` 1, edited in place like
796///     for item 29 (inert before this version, where no parsed reference
797///     carries a lookup), checks a lookup into a document type of the same
798///     contract under full validation (the index exists, is unique, carries
799///     no `timeRange` and is not on an indexOnly type, the keys cover it
800///     exactly, every source shares its index property's value kind, and the
801///     key cannot move off the document it found: its schema properties are
802///     immutable, none an optional `deletableDocument` reference by id, which
803///     a replace may clear once its document is deleted (item 73), and
804///     `$ownerId` is only a part on a type that is neither transferable nor
805///     tradeable), and the contract reference validation
806///     checks one into another contract, refusing it with
807///     `ReferencedDocumentLookupInvalidError` (40137). The document
808///     reference validation (generation 0, reached only from this version)
809///     queries the index for each value's key, billed as a document fetch,
810///     refuses a write with no match with `ReferencedEntityNotFoundError`
811///     (40120, an element named by its list path), checks a
812///     `propertyAgreement` against the document found, and on replace
813///     re-validates when a property the key reads changed. A key may read
814///     `$ownerId` only on a referring type that is neither transferable nor
815///     tradeable, checked on every parse. A changed `lookup` is an
816///     incompatible schema change on update. Chained queries and composite
817///     by-id joins refuse a lookup reference as a join property, and
818///     preallocated indexes are never bound through one.
819/// 33. **Reference expressions (`anyOf` / `allOf`)**: a `refersTo`, on an
820///     identifier property or on the elements of a typed array (item 31), may
821///     be `{ "anyOf": [operand, ...] }`, holding if at least one operand
822///     holds, or `{ "allOf": [operand, ...] }`, holding if every operand holds
823///     for the same value, in place of one target (meta-schema v3, which
824///     admits either combinator only as the declaration's one key,
825///     `apply_property_reference` 0, parsed to the appended
826///     `DocumentPropertyReferenceTarget::AnyOf` and `AllOf`, so every single
827///     target keeps its variant and its encoding; decoding refuses a nesting
828///     deeper than `MAX_REFERENCE_EXPRESSION_DECODE_DEPTH`, 16, so the bytes of
829///     a consensus error cannot recurse without bound). An operand is a leaf,
830///     an `identity`, a `permanentDocument` (by id or with a `lookup`, item
831///     32), a `listElement`, a `deletableDocument` with a `lookup` (which
832///     re-validates the expression on every replace), or an expression of the
833///     other combinator; a list names two or more operands. `contract`,
834///     `token`, `deletableDocument` by id and
835///     `identityPublicKey` leaves, the key id form, a combinator directly
836///     inside the same combinator and keys beside a combinator are refused on
837///     every parse. Registration caps a list at
838///     `SYSTEM_LIMITS_V4.max_reference_operands` (4) and the nesting at
839///     `max_reference_expression_depth` (4 combinators on any path to a leaf),
840///     both backfilled into the earlier tables, refuses two alike operands of
841///     one list (a leaf naming the declaring contract explicitly counting as
842///     the one omitting it), counts every leaf against
843///     `max_references_per_document`, and checks each leaf as the same
844///     declaration alone (`create_document_types_from_document_schemas` 1 and
845///     `data_contract_reference_validation` 0, both walking
846///     `DocumentPropertyReferenceTarget::leaves_with_paths`, which is the
847///     declaration itself at an empty path for a single target, so their
848///     output is unchanged where no expression can parse), a failing leaf
849///     named by where it sits (`resignation.memberId.anyOf[1].allOf[0]`). The
850///     document reference validation (`document_reference_validation` 0,
851///     reached only from this version) evaluates each value operand by operand
852///     in declared order: an `anyOf` stops at the first operand that holds and
853///     otherwise refuses with the last operand's error, an `allOf` stops at the
854///     first that fails and refuses with its error, so a refusal is always a
855///     leaf's own error and no new error exists; every read is billed, the
856///     failed operands' included. A `propertyAgreement` belongs to its leaf and
857///     is checked only against that leaf's document. A replace re-validates an
858///     expression when its value, or a property one of its leaves binds,
859///     changed. A changed expression is an incompatible schema change on
860///     update. Chained queries and composite by-id joins refuse an expression
861///     join property, and preallocated indexes are never bound through one.
862/// 34. **References on the document's writer or creator (`ownerRefersTo`,
863///     `creatorRefersTo`)**: a document type may declare one `refersTo`
864///     declaration of its own, under the doctype-level `ownerRefersTo`
865///     keyword (meta-schema v3, which reuses the property declaration by
866///     `$ref`), whose value is the document's `$ownerId`, the writer, instead
867///     of a property's: a single target, or a reference expression (item 33)
868///     whose every leaf is one of the targets that can hold a writer:
869///     `identity`, and a `permanentDocument` found through a `lookup`, where
870///     `.` is the writer (and, for the writer alone, a `deletableDocument`
871///     found through one, item 32); `contract`, `token` and a document by id (which the
872///     writer's identity id never is) and `identityPublicKey` (which needs a
873///     key id) are refused, as a leaf too. Parser generation 3 reads it from
874///     the stored schema once the core parse has run the meta-schema, on
875///     every parse, through the same `apply_property_reference` 0 an
876///     identifier property's goes through, onto
877///     `DocumentTypeV2::owner_reference`, and refuses it on a type whose
878///     documents can be transferred or traded, since neither is a write. Every
879///     enumeration of a type's references goes through
880///     `DocumentTypeRef::reference_declarations`, which yields it first: its
881///     lookup's referring side is checked on every parse, a lookup into a
882///     type of the same contract by
883///     `create_document_types_from_document_schemas` 1 (edited in place like
884///     for item 29, inert before this version, whose parsers never set an
885///     owner reference), and the whole declaration at registration by the
886///     contract reference validation (`data_contract_reference_validation` 0,
887///     extended in place, only reached from this version), which names it
888///     `<documentType>.$ownerId` and lets its `propertyAgreement` name the
889///     writer on the referring side. It counts one against
890///     `max_references_per_document`. Document create state validation 2 and
891///     replace state validation 1 (`document_reference_validation` 0, extended
892///     in place, both only reached from this version) check the writer against
893///     the target exactly as a property's value is checked: on every create,
894///     and on a replace under the rules of its target (a changed property its
895///     lookup or a `propertyAgreement` reads, every replace for a `$ownerId`
896///     pair), and refuse the write with the error the target reports for a
897///     property (40120 and the rest) at the path `$ownerId`; an `identity`
898///     target fetches nothing, the transition having proved the writer exists.
899///     Adding, removing or changing it is an incompatible schema change on
900///     update (`validate_schema_compatibility` 1 freezes it as the shared rule
901///     set freezes `refersTo`). Its counterpart for a type whose documents can
902///     be transferred or traded is `creatorRefersTo`, whose value is the
903///     document's `$creatorId`, the creator, which never changes: the same
904///     two targets (`.` the creator), only on a type that records creator ids
905///     (`should_use_creator_id`: a transferable or tradeable type of a
906///     format-1 contract), so a type declares at most one of the two; stored
907///     as `DocumentTypeV2::creator_reference`, enumerated second by
908///     `reference_declarations`, named `$creatorId` (and
909///     `<documentType>.$creatorId` at registration), checked against the
910///     writer on a create and the stored creator on a replace under the same
911///     rules, never on a transfer or a purchase, and frozen on update the same
912///     way.
913/// 35. **References to an element of a list of a referenced document**: a
914///     new `refersTo` target, `listElement` (meta-schema v3,
915///     `apply_property_reference` 0, parsed to the appended
916///     `DocumentPropertyReferenceTarget::ListElement`, so every earlier
917///     variant keeps its encoding), on an identifier property, on the
918///     elements of a typed array (item 31), as a leaf of a reference
919///     expression (item 33), or on the writer or the creator (item 34, whose
920///     identity then must be listed; a third target those two take next to
921///     `identity` and a `permanentDocument` lookup, since an identity id can
922///     be an element of a list of identities): the value must be an element
923///     of the typed array
924///     of identifiers `inList` held by one document of `documentType`, the
925///     document whose `$id` the `propertyAgreement` pair with `$id` on the
926///     referenced side reads from an identifier property of the referring
927///     type (stored, optional or not; generation 3 of the parser checks it
928///     under full validation). `$id` joins `$ownerId` and `$creatorId` as a
929///     referenced-side agreement name for every document reference. In every
930///     other respect a list element is a document reference: `contractId`,
931///     `documentType` and its other agreement pairs are checked at
932///     registration as a `permanentDocument`'s are (the type must forbid
933///     deletion), and the list must be a stored typed array of identifiers
934///     fixed once a document is written (the type is immutable or lists the
935///     list's top-level property under `immutable`).
936///     `create_document_types_from_document_schemas` 1, edited in place like
937///     for items 29 and 32 (inert before this version, where no parsed
938///     reference is a list element), checks a list in the same contract
939///     under full validation, and the contract reference validation checks
940///     one in another contract, refusing it with
941///     `ReferencedDocumentListInvalidError` (40138). The document reference
942///     validation (generation 0, reached only from this version) fetches the
943///     list's document by the `$id` pair's value, once per write and shared
944///     with any other reference of the same document (every by-id document
945///     fetch of one write is now memoized), checks the other pairs against it,
946///     and refuses a value the list does not hold, or one set while the `$id`
947///     property is not, with `ReferencedEntityNotFoundError` (40120, the list
948///     element declaration as its entity type, an element named by its list
949///     path); the list is collected once, each value a set lookup. A replace
950///     checks it again when its value or a referring side of any pair
951///     changed, as every agreement is. Each value counts against
952///     `SystemLimits::max_references_per_document` like every other
953///     reference. A changed `listElement` is an incompatible schema change on
954///     update.
955///
956///
957/// 36. **Transient properties are never stored**: a transient property is
958///     judged on the transition and dropped before its document is stored.
959///     Up to v13 only a create dropped it and a replace stored whatever it
960///     carried; `document_from_replace_transition_action` 1 (paired with the
961///     contract-version stamp, edited in place, only selected by this
962///     version) drops the transient values of a replace by top-level name as
963///     a create does. The rules that read a stored value refuse a transient
964///     one, by the property's path and every enclosing object's
965///     (`is_transient`): at registration (parser generation 3 under full
966///     validation) every `transient` entry must name a top-level property,
967///     since Drive drops values by top-level name, and no index may read a
968///     transient property, which every document would leave in the index's
969///     null branch; a lookup's referenced side refuses such an index too
970///     (`referenced_side_error`); the contract reference validation
971///     (`data_contract_reference_validation` 0, extended in place, only
972///     reached from this version) refuses a `propertyAgreement` whose
973///     referenced property is transient, which no stored document carries,
974///     and a key reference that stores the key id while its identity is
975///     transient, in either form (`identityProperty` on the key id,
976///     `keyIdProperty` on the identity). A transient referring side of an
977///     agreement stays allowed: it is a write gate, judged on the
978///     transition. Changing the `transient` list on contract update was an
979///     unsupported keyword to the schema compatibility check, an internal
980///     error that dropped the transition unpaid; `validate_schema_compatibility`
981///     1 freezes the set of names it lists (sorted and deduplicated before
982///     the diff, so a reordering is no change) as it freezes `refersTo`, an
983///     incompatible schema change.
984///     A census of every mainnet and testnet contract (2026-09-23) found
985///     `transient` only on DPNS-shaped `domain` types, which are immutable,
986///     index no transient property and list top-level properties only.
987///
988/// 37. **The moderation charters system contract**
989///     (`SystemDataContract::ModerationCharters`, schema v1, the first piece of
990///     decentralized moderation teams) carries seven document types, all
991///     immutable, the four a charter is made of undeletable and the three team
992///     changes deletable. A `reason` is a ground for a moderation
993///     action, keyed by its owner and a three-letter `code` unique among the
994///     owner's reasons. A `submittedCharter` is a leader's proposal to
995///     moderate one contract on that contract's own terms: its
996///     `targetContractId` refers to a contract declaring elected moderation
997///     (item 24, `moderation: "elected"`, so teams form during the contract's
998///     election delay), its `reasons` are a typed array (item 25) of
999///     references to reasons (item 31), and it carries an optional
1000///     `moderatorsShare` and a `rewardSplit`. A `joinRequest` is an identity's
1001///     offer to serve on a proposal, one per identity per proposal, whose
1002///     `recipientId` must be the proposal's owner (`propertyAgreement`) and
1003///     name a decryption key bound to `submittedCharter` (item 29), whose
1004///     `senderKeyId` is an encryption key of the writer bound to `joinRequest`
1005///     (item 30) and whose `encryptedMessage` declares its envelope (item 27).
1006///     An `electedCharter` is a proposal put to the vote with its team: only
1007///     the proposal's owner may create one, for the proposal's own target
1008///     (`propertyAgreement`), its `targetContractId` requires
1009///     `moderation: "electionOpen"`, and its `members` are identities each of
1010///     which filed a join request for that proposal (item 32, a lookup through
1011///     the join request's unique index) and none of which is the leader
1012///     (item 26). Once a charter is seated, its leader adds members from the
1013///     same join requests (`addedModerator`, the same lookup) and takes them
1014///     back by deleting the addition, and removes elected members
1015///     (`removedModerator`, whose `memberId` is a `listElement` of the
1016///     charter's `members`), putting one back by deleting the removal; each
1017///     exists at most once per member and charter (unique indexes), so the
1018///     team that acts is the leader plus the elected members less the
1019///     removals plus the additions (`ElectedCharter::active_members`). A
1020///     member asks to leave with a deletable `resignationRequest`, which only
1021///     a member may file (`ownerRefersTo` with an `anyOf` of a `listElement`
1022///     into the elected charter's `members` and a `deletableDocument` lookup
1023///     of an `addedModerator`, items 32 to 35) and which carries a message
1024///     encrypted to the leader; the leader acts on it by deleting the addition
1025///     or removing an elected member. The cap on
1026///     additions, the target's `maxAddedModerators`, is a consensus rule of
1027///     item 40.
1028///     Its `byTargetContract` index is a contested unique index
1029///     with `"resolution": 1`, the masternode vote without a Lock choice of
1030///     item 23, so an elected charter create opens or joins the contest for
1031///     its target. `SYSTEM_DATA_CONTRACT_VERSIONS_V3` registers it
1032///     (`moderation_charters: 1`). A proposal holds no rule beyond its schema:
1033///     the reward split sums to 100 through the contract's
1034///     `propertyConstraints` rule (item 39), so 11001 is never produced, and
1035///     the description fits 4096 bytes through the schema's own `maxBytes`
1036///     (item 38); every document validation checks both. Genesis registers it
1037///     on chains born at this version (`create_genesis_state` v1, behind the
1038///     app-connect branch), `transition_to_version_14` inserts it on upgrade,
1039///     and the Drive system contract cache serves it from this version
1040///     (`MODERATION_CHARTERS_CONTRACT_INITIAL_PROTOCOL_VERSION`). Item 40 seats
1041///     the winning team.
1042///
1043/// 38. **`maxBytes` on strings**: a property keyword for the bound plain JSON
1044///     Schema cannot count, the most UTF-8 bytes a string may take
1045///     (`maxLength` counts characters, which are up to four bytes each). It
1046///     goes on a string property, or on the `items` of a typed array of
1047///     strings where it bounds every element, and is 1 to 65535 and no lower
1048///     than `minLength`, checked at registration. Meta-schema v3 admits it and
1049///     `apply_max_bytes` 0 folds it into `StringPropertySizes::max_bytes`, so
1050///     `max_byte_size`, `max_size` and random documents respect it. The
1051///     document validation (`DataContract::validate_document_properties` 0,
1052///     extended in place, inert before this version) calls
1053///     `validate_max_bytes_properties` (`validate_max_bytes` 0, `None` before
1054///     this version) after the JSON schema, on every create and replace and in
1055///     every client that validates a document, and refuses a longer value with
1056///     `DocumentPropertyMaxBytesExceededError` (10421, naming the element as
1057///     `tags[2]` for an item). On update it moves like `maxLength`: it may be
1058///     raised or removed, not added or lowered. The moderation charters
1059///     contract (item 37) declares it on the proposal's description, replacing
1060///     the charter-specific description check, its error 11002 and
1061///     `SystemLimits::max_moderation_charter_description_length`.
1062///
1063/// 39. **Property constraints**: the doctype-level `propertyConstraints`
1064///     keyword (meta-schema v3, `parse_property_constraints` 0) names rules a
1065///     document's properties must meet, each a condition: a comparison
1066///     (`equal`, `notEqual`, `lessThan`, `lessThanOrEqual`, `greaterThan`,
1067///     `greaterThanOrEqual`) of two integer expressions built from integer
1068///     literals, paths of integer or boolean properties (a boolean reading as 1
1069///     for true and 0 for false), `add`, `subtract`, `multiply`, `divide`,
1070///     `modulo` and `power`, `min` and `max` over two or more operands and
1071///     `abs` over one, and sizes: `length` and `byteLength`, the characters and
1072///     UTF-8 bytes of a string property, and `count`, the items
1073///     of an array or byte array property, each 0 for a property the document
1074///     leaves out, `countPresent`, how many of two or more distinct properties
1075///     of any type the document holds, each as `present` tests it, so a rule
1076///     bounds how many of a group are set, and the system times and heights `$createdAt`, `$updatedAt`
1077///     and `$transferredAt` (block times in milliseconds), each also with
1078///     `BlockHeight` or `CoreBlockHeight` appended, of the document's creation,
1079///     last update (create, replace, price update) and last transfer (create,
1080///     transfer, purchase), which a rule may read only on a type listing them
1081///     in `required`; `in`, whether an integer expression takes one of two or
1082///     more distinct integer values; `equal` or `notEqual` of a string property
1083///     and a `{ "const": string }` or of two bare paths naming string
1084///     properties, or `in` of a string property and two or more distinct
1085///     strings, a string the document leaves out equalling no constant and no
1086///     other string unless an `ifAbsent` gives it a string default
1087///     (`{ "ifAbsent": ["status", "open"] }`, whose default an `enum` must list
1088///     too); `equal`, `notEqual` or `in` of an identifier property (one
1089///     declaring `refersTo` included) or of `$ownerId`, the document's owner,
1090///     likewise, with base58 identifier constants or another identifier operand
1091///     and no default, an identifier the document leaves out equalling none;
1092///     `startsWith` or `endsWith`, whether a string (a constant or a string
1093///     property, at least one a property) starts or ends with another, byte for
1094///     byte; `contains`, whether a typed array property holds an element equal
1095///     to an integer expression, a string or an identifier operand (a constant,
1096///     a property, or `$ownerId`), as its elements are, an array the document
1097///     leaves out holding nothing; `present` or `absent` naming a property of
1098///     any type, whether the document holds it (the one way to tell a property
1099///     left out from one set to 0); `anyOf` or `allOf` over two or more
1100///     conditions; `not` over one; `ifThen` over two (the second holding
1101///     whenever the first does, evaluated only then) or `ifThenElse` over three
1102///     (the second when the first holds, the third when it does not, only the
1103///     branch taken evaluated), no two alike; `notIn`, an `in` negated in as
1104///     many nodes. In an operand, a property the document leaves out counts as
1105///     0, or as the value of an `ifAbsent` operand naming it. `countOf` and
1106///     `sumOf` operands read a total from state: how many documents of a type
1107///     of the same contract match a filter (keys of that type or `$ownerId`,
1108///     values read from the document written), or an integer property's total
1109///     over them, as the count or sum tree will keep it once the write is done;
1110///     the batch transformer reads them into the action
1111///     (`Drive::fetch_property_constraint_aggregate`, billed; in place in
1112///     transformer 0, reading nothing before this version), a transfer or
1113///     purchase reads again those depending on the owner, a price update those
1114///     of the rules it judges, and a rule reading one it is not given is not
1115///     judged by an SDK pre-check and an error in consensus, which reads them
1116///     all.
1117///     Arithmetic is exact `i128`: `divide` and `modulo` are Euclidean (the
1118///     remainder is never negative), and an overflow, a zero divisor, a
1119///     negative exponent or a value that is not an integer refuses the document
1120///     rather than wrapping. Conditions are checked in declared order and no
1121///     further than the outcome needs (`anyOf` stops at the first that holds,
1122///     `allOf` at the first that fails), a fault in one that is checked refuses
1123///     the document whatever the others say, and `not` never turns a fault into
1124///     a pass, so an earlier condition guards a later one. The parser checks
1125///     that every path an operand reads names an integer or boolean property,
1126///     every path a `length` or `byteLength` measures a string property, every
1127///     path a `count` counts an array or byte array property, every string
1128///     `startsWith` or `endsWith` tests a string property (a constant tested
1129///     against one with an `enum` starting or ending one of its values), every
1130///     array a `contains` looks in a typed array of the kind it looks for (a
1131///     string constant in the elements' `enum` when they declare one), every
1132///     system time or height a rule reads one the type lists in `required`
1133///     (none on an indexOnly type), every path compared with identifiers an
1134///     identifier property, every path compared with strings a string property
1135///     (whose `enum`, if it declares one, lists every constant it is compared
1136///     with), and every path `present`, `absent` or `countPresent` tests a
1137///     property of any type, none transient nor inside a transient object; that every
1138///     comparison and `in` reads a property or the owner; that nothing is
1139///     compared with itself; that strings and identifiers are only compared for
1140///     equality, and never with each other; that no `in` lists a value twice
1141///     and no `countPresent` a path twice;
1142///     that an `anyOf` or `allOf` holds none directly of its own kind and a
1143///     `not` no `not` or `notIn`; that an indexOnly type, whose deletes carry
1144///     no owner, reads no `$ownerId`; and that no condition or operand nests
1145///     deeper than
1146///     `MAX_PROPERTY_CONSTRAINT_PARSE_DEPTH` (64), on every parse. Under full
1147///     validation it holds the limits `SystemLimits::max_property_constraints`
1148///     (16 rules) and `max_property_constraint_nodes` (32 per rule, every
1149///     comparison, `in`, listed value, `const`, presence test and logical
1150///     operator counting as one, a `countPresent` as one plus one per path), and that no `anyOf` or `allOf` lists the same
1151///     condition twice, and at most `max_property_constraint_aggregates` (4)
1152///     distinct totals per type; once every type is parsed, that a tree keeps
1153///     each total (`documentsCountable` or `documentsSummable`, or an index
1154///     whose properties are exactly the filter's keys) and that no type with a
1155///     contested index totals its own documents, in
1156///     `create_document_types_from_document_schemas` 1, in place and inert
1157///     before this version. `DataContract::validate_document_properties` 0
1158///     (extended in place, inert before this version, and taking the document's
1159///     owner for `$ownerId`) calls `validate_property_constraints`
1160///     (`validate_property_constraints` 0) after the schema validation, so
1161///     document create and replace, and any client validating a document,
1162///     refuse a broken rule with `DocumentPropertyConstraintViolatedError`
1163///     (10422), naming the rule and why. A transfer and a purchase, which give
1164///     the document a new owner, are judged against the rules reading
1165///     `$ownerId` or the transfer's time and heights, with the new values, and
1166///     a price update, which sets the update's time and heights, against the
1167///     rules reading those (`validate_property_constraints_for_system_change`,
1168///     in their structure validation, in place and inert before this version;
1169///     the price update's call is new there). `validate_document_properties`
1170///     takes the document version's system values (`DocumentSystemValues`):
1171///     consensus gives the writer and the block's time and heights on create,
1172///     and on replace the stored creation and transfer values with the block's
1173///     as the update. The rules change nothing stored and read no state but
1174///     their totals. They
1175///     are fixed when the document type is created: a changed
1176///     `propertyConstraints` is an incompatible schema change on update. The
1177///     moderation charters contract declares its first one: a
1178///     `submittedCharter`'s `rewardSplit` members add up to 100, replacing the
1179///     charter-specific check, whose error 11001 keeps its place in
1180///     `BasicError` but is never produced.
1181///     A rule reads `$revision`, an integer operand (`SystemValue::Revision`),
1182///     1 on a create and one more for each later write, on a type keeping a
1183///     revision (`requires_revision`); a transfer, a purchase and a price
1184///     update, which move it, are judged against the rules reading it. A rule
1185///     reads the stored version of the document a write replaces through
1186///     `$old.` (`STORED_DOCUMENT_PREFIX`), as the condition of item 66 does: a
1187///     property (`$old.status`, in any read a bare path takes, checked as the
1188///     path after it), `$old.$ownerId`, and a time, a height or `$revision`
1189///     (`SystemRead::stored`); only on a type keeping a revision and not
1190///     indexOnly, never in a `countOf` or `sumOf` filter, and never in a rule
1191///     of `deleteConstraints`, which reads the stored document by its plain
1192///     paths (parser generation 3; `validate_stored_version_reads` once the
1193///     moderator abilities are parsed). `DocumentSystemValues::stored` gives
1194///     it: `StoredVersion::Absent` on a create, where a property under it is
1195///     absent, `$old.$ownerId` equals no identifier and a stored time, height
1196///     or revision reads 0; on a replace the document replaced, its properties
1197///     rebuilt from the written ones and `stored_changed_values`, its owner,
1198///     times, heights and revision taken from the fetched document by the batch
1199///     transformer and kept on the action beside the totals
1200///     (`PropertyConstraintReads`, which replaces the boxed totals) when a
1201///     rule or a condition reads them; on a transfer, a purchase or a price
1202///     update the document before it, the write judged only against the rules
1203///     reading what it changes, of either version. A moderator's change of a
1204///     document's fields (`DocumentSystemValues::changed_fields`) is judged
1205///     against the rules reading a field it writes, of either version,
1206///     `$revision` or a total, and a moderator's restore (`SystemChange::Restore`,
1207///     through `validate_property_constraints_for_system_change`) against the
1208///     rules reading a total, with `$old.` reading the restored document: rules
1209///     never change once registered, so no other rule could give another
1210///     verdict than at the document's last write. A rule reading a stored
1211///     version a client does not give is not judged, and one consensus does
1212///     not give is an error, as for a total.
1213///     A rule may also read a value of the document a reference of the type
1214///     points at, `{ "referenced": [reference, field] }`, wherever a path
1215///     stands: `field` is a property path of the referenced type, its `$id`,
1216///     `$ownerId` or `$creatorId`, or a time or height it requires, read as
1217///     that property is; one the parse cannot type (a schema field of another
1218///     type, maybe another contract's) compared with a string constant or
1219///     another such field is read as what it holds (a string, an identifier
1220///     the constant spells base58, a byte array it spells hex, two fields by
1221///     value), one node. `reference` is the dotted path of a stored property of
1222///     the type, a nested one included. The parser (`parse_property_constraints`
1223///     0 and meta-schema v3, in place) reads it as the path
1224///     `$referenced.<reference>.$.<field>`; generation 3 refuses it, under full
1225///     validation, outside `propertyConstraints`, on an indexOnly type,
1226///     through anything but a stored property holding one reference
1227///     to one document by id or by a `findBy` without a function, beside what
1228///     a transfer, a purchase or a price update of a type that has them
1229///     changes (`$revision` and `$old.` reads included), beside what a
1230///     moderator's change of the fields a type keeps for them is judged
1231///     against (such a field, of either version, `$revision`, or any total),
1232///     and beside any total where a moderator's restore, judged against every
1233///     rule reading one, can bring a document back (10231);
1234///     and
1235///     `create_document_types_from_document_schemas` 1, in place, checks what
1236///     it reads of a type of the same contract (10231: the field exists, is
1237///     stored and of the kind read, a time or `$creatorId` the type records, a
1238///     constant its `enum` lists and that spells a value of the field's type,
1239///     two fields compared hold one kind, through a `moderatedDocument` only
1240///     `$id`, `$ownerId` and kept fields). Such a rule is not judged with the others,
1241///     and no total it reads is read for a write that does not judge it:
1242///     `PropertyConstraint::violation` leaves it unjudged unless
1243///     `DocumentSystemValues::referenced_documents`, so the structure
1244///     validation, transfers, purchases, price updates, moderator restores and
1245///     changes of fields and the SDK pre-checks pass over it; document create
1246///     state validation 2 and replace state validation 1 (in place) judge it
1247///     after the references hold (`validate_referencing_property_constraints`,
1248///     versioned with `validate_property_constraints`, 0), on the values the
1249///     reference check read (item 63).
1250///
1251/// 40. **Elected moderation teams moderate from their stored charter**: seating
1252///     writes nothing. Awarding the contest of item 37 writes the winning
1253///     `electedCharter`, the only one ever stored for its target, so the
1254///     charter seated on an elected contract is the one the charter contract's
1255///     `byTargetContract` index finds, and the moderation paths read it, each
1256///     read a billed document query of the system contract. Once one is seated,
1257///     only its team moderates the contract: the leader (the charter's owner)
1258///     and the active members (its `members` less removals, plus additions),
1259///     each alone, found by one point read of the unique `removedModerator`
1260///     index for an elected member or of `addedModerator` for anyone else; the
1261///     interim moderators
1262///     are refused (41101). The team holds the abilities the declaration gives
1263///     it: a deletion or restore needs `deleteDocuments` on the type, a list
1264///     action the ability on some moderated type
1265///     (`ContractModerationAbilityNotGrantedError`, 41201). The leader and the
1266///     active members are protected (41102), with the owner when the
1267///     declaration says so, and the interim moderators no longer are. A
1268///     `notYetUsable` interim stops blocking the moderated types
1269///     (`contract_moderation_gate` v0). An `addedModerator` past the target's
1270///     `maxAddedModerators` additions the charter holds is refused,
1271///     paid (`ModerationCharterAddedModeratorLimitReachedError`, 41202), by a
1272///     hook in the batch's `validate_state` v0 that only a create of the
1273///     charter contract reaches. A document action on a moderated type may
1274///     agree to the seated proposal's `moderatorsShare` of the declared
1275///     moderators part (rounded down) instead of the whole, and is charged
1276///     that: the batch transformer (state v2) reads the charter and its
1277///     proposal only for such an agreement, and advanced structure validation
1278///     and every recheck judge it (`DocumentActionFeeModeratorsShareMismatchError`,
1279///     40139, for any other lower amount or with no seated charter). The
1280///     interim team's claim of the moderators pot is refused once a charter is
1281///     seated (41113). No table moves: every generation involved is unreleased,
1282///     but for the shipped batch `validate_state` v0, which no batch of an
1283///     earlier version reaches through the new hook.
1284///
1285/// 41. **A seated team's pot, action counts and reasons**: the leader or an
1286///     active member of a seated team claims the moderators pot for the team,
1287///     and it is split by the proposal's `rewardSplit`: the leader share to the
1288///     leader, the equal share between the other members (the leader's when it
1289///     has none), and the action share between the whole team by each one's
1290///     count of bans, suspensions, warnings and document deletions since the
1291///     last settle, equally when nobody acted. Every part rounds down and the
1292///     remainder stays in the pot. The counts are `member id -> u32` items
1293///     without storage flags under key `48` of an elected contract's other tree,
1294///     created with the contract (`insert_contract_moderation_trees` v0), and
1295///     every settle deletes them. An `addedModerator` or `removedModerator`
1296///     created or deleted settles the pot first, to the team as it was, by a
1297///     hook in the batch's `validate_state` v0 beside the cap on additions: it
1298///     ignores the once-per-epoch limit and writes no last claim. The proof of a
1299///     claim by a seated team's member, whom the contract does not name as a
1300///     recipient, shows the claimant's balance alone. A moderation reason gains
1301///     `reasonDocumentId` (tag bit 2 where it is stored), and a seated team's
1302///     ban, suspension, warning or deletion must name a `reason` document its
1303///     proposal lists (`ModerationReasonNotListedError`, 41203). No table moves
1304///     but the four
1305///     new Drive method slots, `0` at every version. The counts are read with
1306///     the `getContractModerationActionCounts` query (an elected contract
1307///     only), whose proof reads the whole counts tree; it adds a fifth contract
1308///     method slot (`prove_contract_moderation_action_counts`), a verify slot
1309///     (`verify_contract_moderation_action_counts`) and the query's bounds
1310///     (`contract_moderation_action_counts`), `0` at every version as well.
1311///
1312/// 42. **Repaid identity debt reaches the processing fee pool**: an identity
1313///     whose fee the balance could not fully cover keeps the unpaid processing
1314///     part as a debt (its negative credit balance), and credits it receives
1315///     while its balance is empty still repay that debt first. The repaid part
1316///     now goes to the processing fee pool of the epoch it is repaid in, where
1317///     the unpaid fee would have gone; before, it reached no balance the credit
1318///     sum counts. `add_to_identity_balance` 1 marks it with a
1319///     `LowLevelDriveOperation::RepaidIdentityDebt`, and every apply routes it:
1320///     `apply_drive_operations` 1 writes it to the pool after the batch (so it
1321///     adds to the end of block fee distribution the same batch may write,
1322///     unbilled), `apply_balance_change_from_fee_to_identity` 1, which now takes
1323///     the block info, writes it in its own batch (the fee paid is unchanged),
1324///     and `add_epoch_pool_to_proposers_payout_operations` 1 hands the epoch
1325///     payouts to the block's `apply_drive_operations` instead of converting
1326///     them to a plain grove batch, skips a share whose `payToId` has no
1327///     balance and caps each share at what is left of its masternode's payout.
1328///     After paying valid shares, a proposer without a balance returns its
1329///     remaining allocation, including any last-proposer rounding remainder, to
1330///     the applying block's current epoch processing pool. An existing zero
1331///     balance remains a valid recipient; other balance read errors propagate.
1332///     `SystemOperationType::AddToCurrentEpochProcessingPool` defers the return
1333///     until after ordinary writes and repaid debt, unbilled and in the same
1334///     transaction before commit. Estimates and zero returns do not access or
1335///     mutate that pool. Generic lowering and older apply generations refuse
1336///     this operation instead of silently dropping it.
1337///     An apply that meets one it does not route fails (`CorruptedCodeExecution`)
1338///     instead of dropping it. `apply_drive_operations` 1 also merges every
1339///     credit and debit one batch makes to an identity's balance into one net
1340///     write: each converts against the balance committed before the batch, so
1341///     a second write replaced the first and two credits to an indebted
1342///     identity repaid its debt twice.
1343///
1344/// 43. **The end-date cleanup of ended contested vote polls**: a block ends at
1345///     most `maximum_vote_polls_to_process` vote polls, the earliest end date
1346///     first, and removes their entries from the end-date queries.
1347///     `remove_contested_resource_vote_poll_end_date_query_operations` 2
1348///     (`DRIVE_VOTE_METHOD_VERSIONS_V3`) removes an end date only once none of
1349///     its vote polls remain: it reads the entries under the date and keeps the
1350///     date while any of them is not removed in the same batch, so the polls
1351///     left end in a later block.
1352///
1353/// 44. **The total supply ceiling bounds every mint and direct purchase**: a
1354///     token's total supply is stored in a sum item, so it can never pass
1355///     `i64::MAX`. Token mint and token direct purchase state validation 1
1356///     treat `i64::MAX` as the max supply when the token configures none (and
1357///     cap a configured one there), refusing a mint or purchase past it with
1358///     `TokenMintPastMaxSupplyError`, as a paid consensus error. State
1359///     validation 0 checked only a configured max supply, so such a transition
1360///     failed in execution as an internal error instead. Both now read the
1361///     total supply on every mint and purchase, and pay for that read.
1362///
1363/// 45. **A masternode vote towards an identity names a contender**: a
1364///     `ResourceVoteChoice::TowardsIdentity` vote for an identity that is not a
1365///     contender of the poll is refused, unpaid, with
1366///     `VoteChoiceNotAllowedForVotePollError` (40307) by `validate_state` 1 of
1367///     the masternode vote, which reads the contender's document reference
1368///     under the poll. The reserved keys of the poll's stored info, abstain
1369///     tree and lock tree are refused before that read. Before, a vote for an
1370///     unknown identity failed with an internal error, and a vote towards a
1371///     reserved key was counted as Lock or Abstain. `check_for_ended_vote_polls`
1372///     1 also ignores the lock tally of a contest resolved without locking. No
1373///     table moves: both generations are selected by this version alone.
1374///
1375/// 46. **A raw state transition is exactly one encoded transition**:
1376///     `decode_raw_state_transitions` 1 (`DRIVE_ABCI_METHOD_VERSIONS_V10`)
1377///     decodes with `StateTransition::deserialize_from_bytes_untrusted_exact_in_version`,
1378///     so bytes left over after the transition are an invalid encoding
1379///     (`SerializedObjectParsingError`, 10002), refused unpaid in `check_tx` and
1380///     in block processing. Version 0 ignored them, so the transition with
1381///     anything appended executed as the original under another transaction
1382///     hash. Version 1 also reports a transition whose version is outside its
1383///     active range as `StateTransitionNotActiveError` (10603) instead of a
1384///     decode failure, naming whichever boundary of that range was missed: its
1385///     start for a version not active yet, its end for one already superseded.
1386///
1387/// 47. **A storage refund is clawed back from the epochs it was priced for**:
1388///     removing data in epoch E refunds its owner the shares of epochs E+1
1389///     onward, and the refund waits for the next epoch change to be taken out of
1390///     the epoch storage pools. `add_distribute_storage_fee_to_epochs_operations`
1391///     1 (`DRIVE_ABCI_METHOD_VERSIONS_V10`) restores and subtracts it from the
1392///     epoch after the previous block's epoch, the one every pending refund was
1393///     priced in, so each of those epochs gives back its own share. The shares
1394///     of epochs that closed before the current one, skipped by a halt, and the
1395///     rounding leftovers come out of the current epoch. Version 0 started from
1396///     the epoch after the current one, so the current epoch kept most of its
1397///     refunded share and the later epochs gave back more than theirs. The
1398///     total taken out equals the refund in both.
1399///
1400/// 48. **An evonode's token claim covers only the epochs it read**: an
1401///     `EvonodesByParticipation` perpetual distribution weighs each cycle by the
1402///     claimant's share of the blocks proposed in the epochs it spans, from their
1403///     finalized epoch infos. Up to v13 the claim read at most
1404///     `drive_abci.query.max_returned_elements` (100) of them but evaluated its
1405///     whole range, up to 128 cycles (32,767 for a fixed amount), from the last
1406///     paid moment or, on a first claim, from the start of the distribution. An
1407///     evonode more than 100 epochs behind (about 2.5 years on mainnet, 4 days on
1408///     testnet) had every claim of a function other than a fixed amount fail as an
1409///     internal error, with its last paid moment never advancing, while a fixed
1410///     amount applied the share of the epochs read to the whole range. A claim
1411///     reaching an epoch whose info the fee distribution of the block had not
1412///     written yet (the previous epoch, in the first block of an epoch) failed or
1413///     was weighed the same way. `evonode_participation_rewards` 1
1414///     (`DRIVE_TOKEN_METHOD_VERSIONS_V2`) reads the epochs after the cycle start of
1415///     the last paid moment, at most `SYSTEM_LIMITS_V4.max_evonode_reward_claim_epochs`
1416///     (100, backfilled into the earlier tables) or one whole cycle when a cycle is
1417///     longer, and pays through the last whole cycle it read, which the claim stores
1418///     as the last paid moment, so an evonode that is behind is paid over several
1419///     claims. An epoch without finalized info before the last one read, one in which
1420///     no block was produced, counts as an epoch without blocks, and a claim that
1421///     read no whole cycle is refused, paid, with `InvalidTokenClaimNoCurrentRewards`.
1422///     `get_finalized_epoch_infos` now takes its limit from the caller; every other
1423///     caller passes the query bound it read before.
1424///
1425/// 49. **Documents with a time to live**: the doctype-level `ttl` keyword (meta-schema v3,
1426///     document type parser generation 3) makes the platform delete each document of the
1427///     type `ttl` seconds after its `$createdAt`, at most
1428///     `max_document_expirations_per_block` (128, `SYSTEM_LIMITS_V4`) weighing at most
1429///     `max_document_expiration_weight_per_block` (1,024 in documents plus their index levels)
1430///     per block after the block's state transitions (`expire_documents` 0 in
1431///     `DRIVE_ABCI_METHOD_VERSIONS_V10`). The keyword requires `$createdAt`, is refused
1432///     with `documentsKeepHistory`, `indexOnly` and a contested index, is at least
1433///     `min_document_ttl_seconds` (one hour) and at most `max_document_ttl_seconds` (one
1434///     year) at registration, and is fixed on update (`validate_update` 1). References treat such a type as deletable. Its
1435///     documents are stored without storage flags, indexed in the documents expirations
1436///     tree under `Misc` (created by `create_initial_state_structure` 4 and
1437///     `transition_to_version_14`), and pay the `document_ttl` group of `FEE_VERSION3`: a
1438///     price per byte for the time they live (tiers up to seven days, then per 9.125 days),
1439///     paid out to the epochs they live in (at most one era) through the lifetime storage fee
1440///     pools under `Pools` (`add_distribute_block_fees_into_pools_operations` 1),
1441///     plus their deletion prepaid as processing (per index level and per document byte; a
1442///     change that grows a document prepays its added bytes). From its expiry on, a
1443///     document can no longer be replaced, transferred, bought, repriced or restored by a
1444///     moderator (`DocumentExpiredError`, 40140), judged from its own `$createdAt`; its
1445///     owner may still delete it where `canBeDeleted` allows. See
1446///     `book/src/data-model/document-ttl.md`.
1447///
1448/// 50. **A contest accepts at most 1,000 contenders, and its end reaches every
1449///     one**: document create state validation 2 (`DRIVE_ABCI_VALIDATION_VERSIONS_V10`)
1450///     refuses, paid, a document that would add a contender to a contest holding
1451///     `max_contenders_per_contest` (`SYSTEM_LIMITS_V4`, 1,000) already
1452///     (`DocumentContestMaximumContendersReachedError`, 40141).
1453///     `add_contested_indices_for_contract_operations` 1
1454///     (`DRIVE_DOCUMENT_METHOD_VERSIONS_V4`) writes the last index value of a
1455///     poll started from this version as a count tree, so the join reads the
1456///     count in one element fetch; a poll started before keeps its plain tree
1457///     and has its contenders counted by a keys query of at most 1,000.
1458///     `maximum_contenders_to_consider` rises from 100 to 10,000, so the tally
1459///     of an ended poll, and the cleanup built from it, cover every contender
1460///     of a poll within the cap, and up to 10,000 of one that grew past it
1461///     before this version. `check_for_ended_vote_polls` 1 compares every tied
1462///     contender; version 0 compared at most 100.
1463///
1464/// 51. **The fund a contender pays doubles for every 50 contenders a contest
1465///     holds past 250**: the fund to join a contest is its fund doubled once
1466///     the contest holds `contested_document_contenders_before_fund_doubling`
1467///     (`FEE_VERSION3`, 250) contenders and again for every
1468///     `contested_document_contenders_per_fund_doubling` (50) more: 0.1 DASH
1469///     for the first 250 DPNS contenders, 0.2 for the next 50, up to 3,276.8
1470///     for the 951st to the 1,000th, so filling a contest costs 327,695 DASH
1471///     where it cost 100. A contender's prefunded voting balance is the most it
1472///     pays: document create state validation 2 refuses, paid, one stating less
1473///     than the fund to join (`DocumentContestNotPaidForError`, carrying that
1474///     fund), the first contender of a new contest included, and charges one
1475///     stating more only the fund to join, the rest staying with it. Document
1476///     create structure validation 1 leaves the amount to state validation;
1477///     version 0 wants exactly the contest's fund.
1478///
1479/// 52. **Property constraints judge what is stored, and read `$defs`**: to
1480///     `present` and `absent` (item 39), an object none of whose members is
1481///     present (`{}`, or `{ "inner": {} }` around one) is absent, since a
1482///     stored document reads it back as no object at all. A create or replace
1483///     carrying `meta: {}` was judged with `meta` present, and a later
1484///     transfer, purchase or price update, judged on the stored document, with
1485///     it absent. The parser (generation 3) reads the schema of a property
1486///     given as a `$ref` to the contract's `$defs` from the definition, as the
1487///     core parse does, when it checks a rule's string constants and defaults
1488///     against the property's `enum` and an `encryptedFor` key id's bounds; it
1489///     refused every such contract with a decoding error before. The stored
1490///     version a rule reads through `$old.` (item 39) is judged as stored too,
1491///     and a `$old` key the written data carries itself, which no property can
1492///     name, is dropped before a rule reads it
1493///     (`DocumentSystemValues::judged_data`).
1494///
1495/// 53. **Properties the platform generates (`generatedFrom`)**: the property
1496///     keyword (meta-schema v3, `apply_generated_from` 0, `GeneratedFrom` on
1497///     `DocumentProperty`) names a built-in `function` and its `params`,
1498///     properties of the same document type, as
1499///     `{ "function": "sys.stringTransformations.homographSafeASCII", "params": ["label"] }`.
1500///     System functions are named under `sys.`, leaving other names to
1501///     functions a contract may bring later. The `sys.stringTransformations`
1502///     functions take one string and change ASCII characters only, keeping
1503///     every other character, without Unicode tables: `lowercase`,
1504///     `uppercase`, `capitalize`, `camelCase`, `snakeCase`, and
1505///     `homographSafeASCII`, which lowercases, then maps `o` to `0` and `i`
1506///     and `l` to `1`, DPNS's label normalization over ASCII. The parser
1507///     checks at registration and update that `params` holds as many
1508///     properties as the function takes, each another string property that
1509///     is not generated itself, that neither the property nor a param is
1510///     transient or inside a transient object, and that every param sits
1511///     inside every object holding the property; a changed declaration is an
1512///     incompatible schema change, and `validate_update` 1 refuses a property
1513///     an update adds over params that all already existed
1514///     (`DocumentTypeUpdateError`, 40212); meta-schema v3 refuses the keyword
1515///     beside `$ref`, whose definition would replace it.
1516///     `fill_generated_properties` (0) writes a declared property a document
1517///     leaves out, from its params, in the action transformers of document
1518///     create, replace and index-only delete, before the contest resolution
1519///     and every check read the data, in `Document::try_from_create_transition`
1520///     and `try_from_replace_transition`, and in
1521///     `index_only_transition_entry_path_query`, the builder the prover and
1522///     the verifier share, with which proofs are built and checked. The client
1523///     transition builders, the SDK's contest fund lookup and the JS and FFI
1524///     property-constraint pre-checks call `regenerate_generated_properties`
1525///     (same slot) instead, which replaces a value the document holds and
1526///     removes it when a param is absent, so a transition built from a
1527///     fetched and edited document carries the value of its new params and
1528///     its contest is detected from it.
1529///     `DataContract::validate_document_properties` 0 calls
1530///     `validate_generated_from_properties` (`validate_generated_from` 0)
1531///     after the schema and `maxBytes`, and refuses a supplied value that is
1532///     not what the function generates, one without its params, or a document
1533///     repeating a key on the way to the property or a param, with
1534///     `DocumentPropertyNotGeneratedError` (10424). Every call site was
1535///     extended in place and is inert before this version, where the three
1536///     slots are `None` and the meta-schemas refuse the keyword.
1537///
1538/// 54. **An aggregate keyword names a top-level property**: `summable` and
1539///     `averageable` on an index, and `documentsSummable` and
1540///     `documentsAverageable` on a document type, name the integer property
1541///     each document adds to the sum. Drive reads its value from the top level
1542///     of the document, but the parser resolves the name among the flattened
1543///     properties and required fields, which also hold the dotted path of a
1544///     property nested in an object, and meta-schemas v1 and v2 bound only the
1545///     name's length. A contract naming `payment.amount` registered, and every
1546///     document create of the type then failed in Drive as an internal error.
1547///     Meta-schema v3 (`CONTRACT_VERSIONS_V6`) gives the four keywords the
1548///     property-name pattern `^[a-zA-Z0-9_]{1,64}$`, so a create or an update
1549///     carrying a dotted name is refused under full validation
1550///     (`JsonSchemaError`, 10101, paid in a block; `check_tx` does not fully
1551///     validate a contract). A contract stored with one still loads, since a
1552///     stored contract is parsed without full validation, but can no longer be
1553///     updated; no contract on mainnet or testnet names one.
1554/// 55. **A preallocated index's agreement source fits a tree key**: contract
1555///     create and update state validation 1 refuse, paid, a
1556///     `propertyAgreement` pair through which a preallocated index is keyed
1557///     when its referenced property can hold a value over 255 bytes
1558///     (`ReferencedDocumentPropertyAgreementInvalidError`, 40126): creating a
1559///     referenced document writes that value as a tree key, which failed with
1560///     an internal error for a value over 255 bytes, and for any value once
1561///     the property's midway size, which sized the estimate, passed 255
1562///     bytes. `add_document_for_contract_operations` 1 now estimates that
1563///     layer from the referring property, as an entry insert does, and
1564///     preallocates nothing for a referenced value wider than the referring
1565///     property can hold, which no referring document can agree with.
1566///
1567/// 56. **A `propertyAgreement` pair compares values, not index keys**:
1568///     document reference validation 0 judges each pair as two single values
1569///     (`Value::same_scalar_data`): strings as text, byte arrays and
1570///     identifiers as bytes, integers as numbers at any width, floats by
1571///     their `f64` bits (an integer against a float read as the float it
1572///     converts to, as a `number` carried as an integer is stored), booleans
1573///     as booleans. An identifier or byte array carried as an array of
1574///     `U8`s is the bytes it lists, as before; any other array agrees with
1575///     nothing. It compared the two sides' index key encodings, under which
1576///     `""` agreed with `"\0"`, and two equal values over 255 bytes, which
1577///     an unindexed string of 64 characters or more can hold, were refused
1578///     (`ReferencedDocumentPropertyMismatchError`, 40127).
1579///
1580/// 57. **Moderator abilities, and fields only moderators write**: the two
1581///     doctype keywords of moderator deletion (19) become one object,
1582///     `moderatorAbilities` (meta-schema v3): `delete` for
1583///     `canBeDeletedByModerators`, `deleteWithin` for
1584///     `canBeDeletedByModeratorsFor`, and `changeFields`, the top-level
1585///     properties only the contract's moderators write. The whole object is
1586///     fixed with the type (40212). `deleteKeepsRecord` (default true) says
1587///     whether a moderator's deletion leaves its removal record: without one the
1588///     type has no records tree, the query refuses it, a restore is refused
1589///     (41119) and the deletion is proved by the document's absence, which the
1590///     verifier learns from the contract. `deleteRefundsOwner` (default false)
1591///     says whether the owner is refunded its storage instead of forfeiting it
1592///     (the batch then carries no `ForfeitStorageRefunds`). `deleteKeepsFields`
1593///     lists property paths at any depth, and the timestamps and block heights
1594///     the type requires, whose values the removal record keeps, copied from
1595///     the document as it was deleted: what stays public once it is gone. It
1596///     needs a record, and is fixed with the type. A record keeping any
1597///     carries them behind bit 1 of its tag byte, encoded as the document
1598///     encodes its properties (a presence byte and the value per kept path,
1599///     the paths themselves not written) and read under the document's type,
1600///     and a record keeping none is written as before; the removals
1601///     response carries the bytes as `kept_fields` (field 8), and a
1602///     `moderatedDocument` reference's `where` pair on a kept property is
1603///     checked against the record's value. A property `changeFields` lists must be declared,
1604///     optional, stored, not immutable, neither a reference nor read by one,
1605///     neither generated nor a generation parameter, and in no contested index,
1606///     on a type that is not indexOnly; a type listing any keeps `$revision` even
1607///     when `documentsMutable` is false, and a lookup key or a list element's
1608///     list may not read such a field of the type it refers to.
1609///     `ContractUserModeration` gains the `ChangeDocumentFields` action: a
1610///     moderator (for a seated team, holding the new `changeDocumentFields`
1611///     ability, appended to `ModerationAbility`, on the type, and citing a
1612///     listed reason) sets or removes those fields on any document of the type,
1613///     whoever owns it. The changed document is judged as a replace judges one
1614///     (schema, the `propertyConstraints` reading a field it changes, `$revision`
1615///     or a total, with the stored document under `$old.` (item 39), `distinctFrom`,
1616///     `encryptedFor` shapes, unique indexes through
1617///     `validate_moderated_document_uniqueness`, the restore's check
1618///     generalized and renamed), its references are not checked again, and it
1619///     is stored with the replace's update, `$revision` one higher and
1620///     `$updatedAt` untouched; the moderator pays, refunds of what the change
1621///     frees stay the owner's. A change that changes nothing is refused (10905),
1622///     and a seated team's change does not count toward its action share. An
1623///     elected declaration must give its team `changeDocumentFields` on every
1624///     type that lists fields. The proof
1625///     is the document as it now stands. The batch transformer (in place,
1626///     inert before 14) refuses a document's owner who sets, changes or removes
1627///     such a field without moderating the contract, in the mempool too. New errors:
1628///     `InvalidContractModerationDocumentFieldsError` (10905),
1629///     `DocumentFieldNotChangeableByModeratorsError` (41123) and
1630///     `DocumentModeratorFieldNotWritableError` (41124), appended.
1631/// 58. **The last moderator's stamp (`$moderatedAt`, `$moderatedBy`)**: two
1632///     system properties of a document whose type keeps fields for its
1633///     moderators (57), the block time and the identity of the last moderator
1634///     to write them. A `changeDocumentFields` sets both, and so does the batch
1635///     transformer (in place, inert before 14) for a create or replace whose
1636///     signer moderates the contract and writes such a field; a replace that
1637///     leaves the fields alone carries them over, and transfers, purchases,
1638///     price updates and restores keep them. Document serialization format 3
1639///     (this version's) records them behind bits 512 and 1024 of its time
1640///     field flags, so a document without them is written as before. Parser
1641///     generation 3 lets an index name either on such a type, never in a
1642///     unique index (10231); the shipped index key, query value and size
1643///     arms for the two names (`get_raw_for_document_type` v0,
1644///     `serialize_value_for_key` v0, Drive's estimated key sizes) are reached
1645///     only through such an index.
1646///
1647/// 59. **`skipIfAbsent` at any position, `true` or an array, on every type**:
1648///     document meta-schema v3 and the generation-3 parser take
1649///     `skipIfAbsent: true` (skip on every optional property of the index)
1650///     or an array naming the skip set, and a skip property may sit at any
1651///     position of the index, under a `timeRange` window too. A stored type
1652///     may declare it (the array may then leave some optional properties on
1653///     the null key), except on a contested index or next to
1654///     `nullSearchable: false`; on an indexOnly type the skip set is every
1655///     optional property of the index and each optional property needs a
1656///     skip index of its own, without a `timeRange`. No `rankedCountable`
1657///     `at` level may sit above a skip property; on a stored type a ranking
1658///     at a skip property may not share its level with an index keeping the
1659///     null layout for it, and a skip property that is a byte array needs
1660///     `minItems` of at least 1. The v2 insert and delete walkers write an index's
1661///     entry only for a document carrying its skip set and build a level
1662///     only when an entry of the document sits at or below it; update 1
1663///     moves a replaced document into or out of a skip index; every index
1664///     picker (server and verifier) admits a skip index only for a query
1665///     binding each skip property, on a stored type with a constraint no
1666///     missing value can meet. A contract valid before keeps its layout and
1667///     queries: it could only skip on an indexOnly index's first property,
1668///     where both rules agree.
1669///
1670/// 60. **Integer-range indexes**: an index can declare an `integerRange`
1671///     transform (`on`, `range`, `step`, optional `phase < step`) that
1672///     buckets a required user integer property of at most 64 bits into
1673///     windows starting at `phase + k * step`; a start below the lowest
1674///     value of the property's integer type is clamped to it, so every
1675///     value is in at least one window. It shares the time-range machinery:
1676///     the grid-qualified level key, the walkers' fan-out (the insert, delete
1677///     and update walkers read one `IndexBucketing`), the overlap cap
1678///     (`SystemLimits::max_time_range_overlap_factor`) and the resolution
1679///     provenance that keeps raw queries off a bucketed index. The v1
1680///     `getDocuments` handler resolves the new `IN_INTEGER_RANGE` operator,
1681///     a typed `IntegerRangeSelection` naming one window by its start, to a
1682///     window-start equality from the query alone. `unique: true` needs
1683///     non-overlapping windows; the uniqueness probe (v1) looks in the
1684///     candidate's window and lets a document change its value within its
1685///     own window. An indexOnly type cannot declare one (its entries would
1686///     collide across rows that share a window); neither kind of bucketed
1687///     index can be a `refersTo` lookup target or a `propertyConstraints`
1688///     answering index; a nested source must sit in required objects and
1689///     the grid-qualified level key fits 255 bytes; and a document `ttl`
1690///     prices every window an integer-range index writes.
1691///
1692/// 61. **A `refersTo` may find its document by a hash the document reveals**:
1693///     a `findBy` entry may be a function, `"<referenced property>": {
1694///     "function": "sys.hash.sha256d", "params": [...] }` (meta-schema v3
1695///     `findByFunction`, parser generation 3, `apply_property_reference` 0):
1696///     the document is found by that property holding the SHA-256 of the
1697///     SHA-256 of the params' bytes joined in order, a property path of the
1698///     document (the property carrying the reference included),
1699///     `{ "const": text }`, `"."` for a value without a path (each element
1700///     of a typed array, the writer, the creator), or `"$ownerId"` for the
1701///     writer's id (`LookupKeyParam::Writer`), a string counting as its
1702///     UTF-8, a byte array as its bytes, an identifier as its 32 bytes. The
1703///     parser holds the function as the lookup's computed key
1704///     (`LookupKeySource::Hash`). The function is `SystemFunction::Hash`, a
1705///     `sys.hash` namespace beside the string transformations of
1706///     `generatedFrom`, which refuses it. A string or byte array property may
1707///     now carry a `refersTo` whose `findBy` reads its value
1708///     (`DocumentProperty::revealed_reference`, `PropertyReference::Revealed`):
1709///     through a function, or as `"."`, which fills an index property holding
1710///     the same kind of value (`DocumentReferenceLookup::referenced_side_error`,
1711///     told the property carrying the reference) and is judged as an
1712///     identifier's value is, on a create and on the replaces that re-validate
1713///     it (`key_values` and the write-time fetch read `"."` as a `Value`; a
1714///     refusal carries an all-zero entity id, the value being no id, and a
1715///     `deletableDocument` one may not sit under an `immutable` property). The
1716///     document an index finds must hold each string or byte array part of the
1717///     key exactly, since the key encoding reads the empty string as `"\0"` and
1718///     an empty byte array as no value, and a key part no index entry can hold
1719///     (longer than 255 bytes) finds nothing without a read, for a property
1720///     source of those kinds too (`fetch_document_through_lookup`); the
1721///     property keeps its type. The document a function's key finds is a
1722///     commitment made earlier, so the reference is judged when the document is
1723///     created only: its params may be transient or optional, every stored value
1724///     it reads must be fixed once written, and a replace leaves it alone.
1725///     Document create structure validation 1 refuses a create missing a param,
1726///     repeating a key on the way to one, or whose variable-length param holds
1727///     the one-byte separator that must follow it
1728///     (`DocumentReferencePreimageInvalidError`, 10423). A reference judged
1729///     on the create alone (`DocumentReferenceLookup::is_checked_on_create_only`:
1730///     beside a `findBy` function, or any `findBy` on a document type whose
1731///     documents are never replaced, `documentsMutable: false`, since a replace
1732///     is the one write that judges a reference again), and not beside
1733///     `inList`, may declare `minimumAgeBlocks` (inside its `constraints`,
1734///     beside `findBy`), judged by
1735///     document create state validation 2 against the found document's
1736///     `$createdAtBlockHeight` (`ReferencedDocumentRequirementNotMetError`,
1737///     40142), and `consume`, which deletes the found document with the create
1738///     (`DocumentCreateTransitionAction` `consumed_documents`, a batch touching
1739///     it elsewhere refused with 40120). The hash is computed once per key and
1740///     billed as `ValidationOperation::DoubleSha256` by the blocks it hashes,
1741///     beside the document fetch. Such a `deletableDocument` reference, judged
1742///     on the create alone, may sit on an `immutable` property, which
1743///     `validate_no_immutable_deletable_element_references` otherwise refuses,
1744///     and its `findBy` may read `$ownerId` on a transferable or tradeable
1745///     referring type (item 32 refuses that otherwise): a transfer or a
1746///     purchase moves the writer part of its key, but no later write judges it.
1747///     A `where` entry `{"$ownerId": "$ownerId"}` makes the commitment the
1748///     writer's own, and `consume` requires it, into the declaring contract,
1749///     on a type whose owners may delete, that keeps no history, declares no
1750///     delete token cost or delete action fee and requires no stricter
1751///     signature security level than the declaring type; batch advanced
1752///     structure 1 refuses a contract-bound key whose bounds leave out a type
1753///     the created type may consume (`ContractBoundedKeyOutOfBoundsError`,
1754///     20014). The consumed deletes are converted with the create's own
1755///     operations pending, so a type may consume its own documents. The
1756///     `where` entries beside a function are judged with it, on the create
1757///     alone, so the properties they read must be fixed once written or
1758///     transient; on a mutable type such a reference may not be an `anyOf`
1759///     operand; and no property a function reads may be listed under
1760///     `moderatorAbilities.changeFields` (57). `creatorRefersTo` takes a
1761///     `deletableDocument` target judged on the create alone, and the `findBy` of an
1762///     `ownerRefersTo` or `creatorRefersTo` may leave the value out beside
1763///     one. The declaration reproduces the DPNS preorder hash of a name under
1764///     a parent byte for byte; the DPNS contract and its create trigger are
1765///     unchanged. See `book/src/data-model/documents.md`.
1766///
1767///     `chooseFirst` (`LookupChooseFirst`), the other entry of a reference's
1768///     `constraints`, sits on a `deletableDocument` reference whose `findBy`
1769///     holds exactly the entry `"$ownerId": "$ownerId"` and a function filling
1770///     `among`, reading neither the writer nor `"."`, whose hash every
1771///     commitment to the same values holds, whoever made it:
1772///     `{ "among", "validWhen": { "<property>": <function> }, "by" }`,
1773///     `validWhen` an owner-bound function (reading `"$ownerId"`, standing for
1774///     each commitment's owner, and exactly the properties the `findBy`
1775///     function reads) and `by` the order the commitments are chosen in
1776///     (properties ascending or descending, `ChooseFirstOrder`, a last `$id`
1777///     breaking ties). Document reference validation 0, in place, refuses a
1778///     found document past its type's `ttl` (40120) or not holding `validWhen`
1779///     computed with the writer (40120, `DoubleSha256`, `WriterPreimage`), and
1780///     reads in one billed query the documents holding the found one's value
1781///     at `among` in `by` order (`fetch_documents_holding_in_order`, through
1782///     the index over `among` and the ordered properties), as far as the found
1783///     one's value of the first, at most
1784///     `SYSTEM_LIMITS_V4.max_choose_first_candidates` (1,000; backfilled into
1785///     the earlier tables, which nothing reads there). The first that comes
1786///     strictly before the found one, by the keys the index holds them under,
1787///     is not past its type's `ttl` and holds `validWhen` computed with its own
1788///     owner (`DoubleSha256` each) refuses the create
1789///     (`ReferencedDocumentPrecededError`, 40149). A copied hash names another
1790///     owner and never refuses, one equal on every `by` property is no
1791///     competitor, and when none of the documents read refuses, the create
1792///     stands. The query and the competitors' hashes bill at most
1793///     `FEE_VERSION3.document_reference.choose_first_credits_per_candidate`
1794///     (100,000; a new fee group, unread before this version) times that
1795///     limit, and check tx, which validates no state of such a create,
1796///     reserves that whole budget and the create's `findBy` and `validWhen`
1797///     hashes on top of its estimated fee (not consensus). Registration, on
1798///     the same contract and on another (`DocumentReferenceLookup`'s
1799///     `referring_side_error` and `referenced_side_error`, and the parser's
1800///     `validate_reference_lookup_sources`), requires the `validWhen` property
1801///     to be a stored 32-byte byte array fixed once written; every `by`
1802///     property to be recorded on every document, fixed once written and not
1803///     transient (a last `$id` in the direction of the property before it,
1804///     ascending alone: the index keeps ids that way and the capped query reads
1805///     them so); the referenced type to expire (`ttl`), to hold the index over
1806///     `among` and the `by` properties (not unique under a last `$id`) and no
1807///     unique index holding `among`, or the `validWhen` property, without
1808///     `$ownerId`; at most one `chooseFirst` per type, not on typed array
1809///     elements or expression operands, a `where` holding nothing but
1810///     `"$ownerId": "$ownerId"` (no condition), and no gas sponsorship of the
1811///     declaring type's creates (a sponsored create is judged, state included,
1812///     before anyone pays). `constraints` holds `minimumAgeBlocks`,
1813///     `chooseFirst` or both and nothing else, and either one beside `findBy`
1814///     is refused. Document create structure validation 1 refuses a create
1815///     missing a param of `validWhen` (10423). Inert before this version: only
1816///     meta-schema v3 admits `constraints` and the `"$ownerId"` param, so the
1817///     writer reaching `hash_lookup_key` in place in reference validation 0
1818///     and batch state 0 changes nothing earlier.
1819///
1820/// 62. **Null flags follow each index's own path**: the v2 index-level
1821///     insert and delete walkers give each sub-level the null flags of its
1822///     parent and its own value. They carried the flags from one sibling
1823///     sub-level into the next, so a unique index could store its entry in
1824///     the `[0]` tree meant for a missing value, and a `nullSearchable:
1825///     false` index an entry for a document missing all of its values,
1826///     because of another index's values; update 1 and the document cost
1827///     model already judged each index alone. Entries written before
1828///     (by that carrying, or by update 0, which laid out a unique index
1829///     with some values missing as the bare reference and never skipped a
1830///     `nullSearchable: false` entry) are found where they are stored: where
1831///     an earlier writer could disagree with the rule, the v2 delete walker
1832///     and update 1 read the stored `[0]`, unbilled, and remove or refresh
1833///     the entry there; a type with a `ttl` skips the read.
1834///
1835/// 63. **`refersTo` finds its document with `findBy` and checks it with
1836///     `where`**: the reference keywords the notes above describe are spelled
1837///     anew in meta-schema v3 and parser generation 3 (`apply_property_reference`
1838///     0), in place, before this version reaches a network. `lookup: { index,
1839///     keys }` is `findBy`, the key parts directly (`{ "<index property>":
1840///     <source> }`, a function entry included, see 61), without the index
1841///     name: the index is the unique one of the referenced document type whose
1842///     properties are exactly those `findBy` names, not bucketing its first
1843///     property (`DocumentReferenceLookup::resolve_index`, run at contract
1844///     parse or registration and when the document is fetched; a type's
1845///     indexes never change after it is registered). A plain `propertyAgreement`
1846///     pair `{ "<referring>": "<referenced>" }` is a `where` entry keyed the
1847///     other way, `{ "<referenced>": "<referring>" }`, so every map of a
1848///     `refersTo` is keyed by the referenced document's property; the parsed
1849///     model keeps `property_agreement` keyed by the referring property, and a
1850///     referring value may be compared once. `listElement` is a
1851///     `permanentDocument` with `inList`, found by `findBy { "$id":
1852///     "<property>" }`, the one `findBy` entry that names `$id`. Without
1853///     `findBy` the value is the document's `$id`, as before. The parser refuses
1854///     `lookup`, `propertyAgreement` and the `listElement` type on every parse,
1855///     naming what replaced each, so a contract written with them never loads
1856///     with another meaning. `ReferencedDocumentLookupInvalidError` (40137)
1857///     carries the properties `findBy` names in place of an index name. The
1858///     moderation charters system contract is written in the new keywords;
1859///     the parsed declarations, and so validation and execution, are
1860///     unchanged.
1861///     A `where` entry may instead hold a condition (`WhereCondition`, parsed
1862///     into `where_conditions` beside `property_agreement`, a field appended
1863///     to every document reference variant and `ListElementReference`): `{
1864///     "const": v }`, `{ "notEqual": b }` (a referring property, `"$ownerId"`
1865///     or a `const`), `{ "in": [...] }` (two to thirty literals of one kind)
1866///     or an ordering (`greaterThan`, `greaterThanOrEqual`, `lessThan`,
1867///     `lessThanOrEqual`) of an integer by an integer property, an integer
1868///     `const` or a time or height of the referring document; a literal reads
1869///     as the referenced property's type says. Document reference validation
1870///     0 (in place) checks them against the document found, or the removal
1871///     record for one asked about again (every entry when a rule reads
1872///     through the reference), refusing with 40127 whose referring property is
1873///     the condition as written; one bounded by the writer or the last update
1874///     or transfer is asked about on every replace, and none of those may sit
1875///     beside a `findBy` function (10231). Contract create and update state
1876///     validation (data contract reference validation 0, in place) refuses one
1877///     that cannot hold with 40126: a literal no value of the referenced
1878///     property equals (its kind, `enum`, length, size or range), an `in`
1879///     repeating a value once read, a `notEqual` bounded by the reference
1880///     property itself, an ordering no value of the property meets, and an
1881///     entry of a `moderatedDocument` reference a rule reads through that
1882///     reads what a removal record does not keep. The same validation checks
1883///     every reference a `propertyConstraints` rule reads through (item 39) on
1884///     every replace, the existence check's read, billed as before, a foreign
1885///     contract fetched and billed once per write, and records for the rule
1886///     the values it reads of the document found, or of a kept
1887///     `moderatedDocument`'s removal record, so a rule adds no read; and
1888///     registration refuses a rule reading a field another contract's type
1889///     does not give it, or comparing two fields of different kinds, with
1890///     `ReferencedDocumentRuleReadInvalidError` (40148, appended to
1891///     `StateError`).
1892/// 64. **`refersTo: moderatedDocument`**: a third kind of document reference,
1893///     between `permanentDocument` and `deletableDocument` and disjoint from
1894///     both (`DocumentReferenceKind`, `DocumentTypeV2Getters::document_reference_kind`),
1895///     in place in meta-schema v3, parser generation 3 and the generation 0
1896///     reference validators. Its target is a document type whose documents
1897///     leave state only when the contract's moderators remove them, each
1898///     removal on the record: `canBeDeleted: false`, no `ttl`, and
1899///     `moderatorAbilities.delete` with `deleteKeepsRecord` not false. Such a
1900///     type is no longer a `deletableDocument` target
1901///     (`ReferencedDocumentTypeModeratedError`, 40144), and a
1902///     `moderatedDocument` reference to any other type is refused
1903///     (`ReferencedDocumentTypeNotModeratedError`, 40143), at registration
1904///     and at write time. The id form only: no `findBy`, `inList` or operand
1905///     of an expression. The document must exist when the reference is
1906///     written; a replace re-validates it as a permanent one (the value or a
1907///     property its `where` reads changed, or always for a writer gate), and a
1908///     value the stored document held whose document a moderator removed
1909///     resolves to the removal record, read and billed: a `where` pair asked
1910///     about again compares the record's document owner for `$ownerId` and the
1911///     id for `$id`, and refuses any other property
1912///     (`ReferencedDocumentRemovedError`, 40145); a writer gate may compare
1913///     only those two (parser, 10231), being asked about on every replace. A
1914///     value is held when it is the stored document's at its path, compared
1915///     through the stored values the replace action carries for a changed
1916///     top-level property. The write-time kind check still lets a
1917///     `deletableDocument` reference to a moderated type through, which a
1918///     contract registered before this note may hold. Chained and composite joins
1919///     through it prove, as one more component of the merged proof, the
1920///     removal records of the joined ids beside their documents, and report
1921///     each removed document by its record (`removed_outer_documents = 4` on
1922///     `ChainedDocuments`, `removed = 4` on a composite `SubQueryResult`,
1923///     additive); a joined id with neither a document nor a record is refused
1924///     as a missing permanent target is. StateError discriminants 156-158.
1925///
1926/// 65. **An index may hold a value of the document a reference points at**: an
1927///     index property `"<reference property>.<field>"` (`DerivedIndexProperty`,
1928///     `DocumentTypeV2Getters::derived_index_properties`), such as a reply's
1929///     `postId.$ownerId`, in place in parser generation 3 (`admit_derived_index_properties`,
1930///     `apply_derived_index_properties`) and `create_document_types_from_document_schemas`
1931///     1 (`resolve_derived_index_properties`, which gives a schema field its type on the
1932///     referenced type on every parse). The document never stores the value: before Drive
1933///     keys a document of such a type, on insert (`add_document` 1), update (`update_document`
1934///     1, one read for both versions) and delete (`delete_read_document`, shared by owner and
1935///     moderator deletes and `ttl` expiry), it reads the referenced document, billed with the
1936///     write, or, for a `moderatedDocument` target a moderator removed, the owner and the
1937///     values its removal record keeps (`ContractDocumentRemoval::kept_values`, read at a
1938///     path by `kept_value_at`), and puts the values into the document's properties under
1939///     the derived names, where `get_raw_for_document_type` 0 reads them (a missing one is
1940///     refused, never keyed under null) and the serialization ignores them. A create reads nothing more: the
1941///     document reference validation 0, given a map, records the values from the documents it
1942///     fetched, and the create action carries them to Drive. A dry run keys the document
1943///     under a value of each field's type. `serialize_value_for_key` 0,
1944///     `deserialize_value_for_key` 0 and Drive's estimated key sizes take a derived name's type
1945///     from the declaration. Registration (full validation, `InvalidContractStructure`)
1946///     admits one only where the value can not change once written: a same-contract
1947///     `permanentDocument` or `moderatedDocument` reference by id, on a reference property
1948///     fixed once written; `$ownerId` of a type that can not change hands, `$creatorId` of a
1949///     type recording it, or a stored schema property fixed once written and indexable;
1950///     through `moderatedDocument`, `$ownerId` or a schema property the referenced type keeps
1951///     under `moderatorAbilities.deleteKeepsFields` (a kept path or one inside a kept object,
1952///     `is_path_listed`, checked in every build); not `$id`; not in a unique or contested
1953///     index, or as a `timeRange` or `integerRange` source; not on an indexOnly type. A
1954///     `skipIfAbsent` array may name one (`reads_through_reference`), which `skipIfAbsent:
1955///     true` leaves out; `resolve_derived_index_properties` refuses one that is never absent
1956///     (a required reference reading `$ownerId`, `$creatorId`, or a field required with every
1957///     object around it) or a byte array that may be empty. The v2 walkers, update 1 and the
1958///     SDK cost walker count a null skip value as absent (`document_carries`), as a derived
1959///     value is when its reference or field is. A `startAt` or `startAfter` cursor, placed by
1960///     what the named document stores, is refused on an index whose derived properties the
1961///     query does not fix with `==`. Every step is inert without a derived index property,
1962///     which only generation 3 declares.
1963///
1964/// 66. **Properties frozen under a condition**: an `immutable` entry of
1965///     meta-schema v3 and parser generation 3, in place, may be
1966///     `{ "property", "when" }` beside a property name. The condition takes
1967///     the grammar of a `propertyConstraints` rule, reads no `countOf` or
1968///     `sumOf`, and is judged on the document the replace writes (its
1969///     `$updatedAt` the replace's block time, so `$updatedAt - $createdAt`
1970///     is the document's age), with the stored document's properties read
1971///     through `$old.<path>` (`STORED_DOCUMENT_PREFIX`), and its owner, times,
1972///     heights and revision through `$old.$ownerId`, `$old.$updatedAt` and the
1973///     rest, which a `propertyConstraints` rule reads too (item 39), as it
1974///     reads `$revision`. Document replace state validation 1, extended in
1975///     place, refuses a replace changing, adding or removing a property whose
1976///     condition holds, or faults, with `DocumentImmutablePropertyChangedError`
1977///     (40128); the stored properties are rebuilt from the written ones and
1978///     `stored_changed_values`, and the replace action's `added_data_fields`
1979///     is gone. `immutableAllowSetting`, which `{ "present": "$old.<p>" }`
1980///     now says, is refused on every parse, naming its replacement. A
1981///     conditional property is not fixed once written
1982///     (`schema_property_is_fixed_once_written`), a `deletableDocument`
1983///     reference by id may be listed only without a condition, and on
1984///     contract update (document type update validation 1) a condition is
1985///     kept as it is or dropped for listing the property without one.
1986///
1987/// 67. **A seated team deletes a settled document together**: past a type's
1988///     `deleteWithin` window no moderator deletes a document alone (41116); the
1989///     new `moderatorAbilities.deleteSettled: { leader, approvals,
1990///     approversPredateDocument }` (meta-schema
1991///     v3, `DocumentTypeV2::moderator_settled_deletion`, fixed with the type,
1992///     40212) lets the members of an elected contract's seated team delete it
1993///     once `approvals` of them approve, the leader among them when `leader` is
1994///     set. It needs `deleteWithin` and an elected declaration giving the team
1995///     `deleteDocuments` on the type (10231, 10900), `approvals` from 1 to the
1996///     members the declared team can hold (its leader,
1997///     `SystemLimits::max_moderation_charter_elected_members` and the
1998///     declaration's `maxAddedModerators`), the upper bound checked at
1999///     registration only; a seated team whose charter elects fewer members,
2000///     and so holds fewer than the rule asks for, must have all it can hold
2001///     approve. Its `approversPredateDocument` (default `true` when `approvals`
2002///     is above 1, which then needs `$createdAt` in `required` at
2003///     registration, 10231) counts a member the leader added only for
2004///     documents created after its addition (the `addedModerator`'s
2005///     `$createdAt` earlier than the document's): a proposal or approval by a
2006///     later one is refused, checked before an approval already given, and an
2007///     approval that reads the team drops the approval of a member taken off
2008///     and added again too late; the leader and the elected members always
2009///     count.
2010///     `ContractUserModeration` gains two actions (appended), shaped like a
2011///     token group's action: `DeleteSettledDocument` proposes the deletion, kept
2012///     under the contract as a team action (other tree key `24`, `M` active and
2013///     `X` closed, each `action id -> { I: the action, S: SumTree(member ->
2014///     SumItem(1)) }`, created with the contract) by an id computed from the
2015///     contract, the proposer, its nonce, the document and the reason,
2016///     naming the document as it is (its last modification and `$revision`)
2017///     and the reason; and
2018///     `ApproveTeamAction { action_id }` approves it. Nothing lapses, but an
2019///     approval of a document changed since (its `$revision` moved, a
2020///     moderator's change of its fields included) is refused. Each approval is
2021///     its own sum item, never rewritten; when the approvals given could meet
2022///     the rule the team is read and the approvals of members who left are
2023///     dropped, refunded to them, and the one whose counted approvals meet it
2024///     deletes the document as `DeleteDocument` does, moves the action with the
2025///     approvals that counted to the closed actions (refunding each), and counts
2026///     toward the action share for every counted approver. The storage refund
2027///     forfeiture of a moderator's deletion now takes the document operations
2028///     alone (the document's bytes and any index subtree the deletion empties,
2029///     whoever paid for them), applied as a GroveDB batch of their own when the
2030///     batch also frees moderation storage someone is owed (a restored removal
2031///     record replaced, approvals moved or dropped), which is refunded as ever.
2032///     The proof is the signer's approval, active or closed
2033///     (`VerifiedContractTeamActionSignature`, appended); the new
2034///     `getContractTeamActions` (each action with its approval count, the sum
2035///     of its approvals tree) and `getContractTeamActionSigners` queries read
2036///     them. New errors, appended: `DocumentTypeNotDeletableOnceSettledError`
2037///     (41204), `ContractModerationTeamNotSeatedError` (41205),
2038///     `DocumentNotSettledError` (41206), `ContractTeamActionDoesNotExistError`
2039///     (41207), `ContractTeamActionAlreadySignedError` (41208),
2040///     `SettledDeletionNotRestorableError` (41209): a deletion the team approved
2041///     is never restored, by the leader or any member,
2042///     `ContractTeamActionAlreadyCompletedError` (41210),
2043///     `ContractTeamActionDocumentChangedError` (41211) and
2044///     `ContractTeamMemberAddedAfterDocumentError` (41212).
2045///
2046/// 68. **A preallocated index may be bound through `moderatedDocument`**:
2047///     `Index::preallocation_bindings`, in place, binds through a same-contract
2048///     `moderatedDocument` reference as through a `permanentDocument` one, and a
2049///     binding records its kind (`PreallocationBinding::kind`). Through a moderated
2050///     reference a binding holds only when the removal record of the referenced
2051///     document keeps every key it binds, the referenced `$id`, `$ownerId` or a property
2052///     the referenced type lists under `moderatorAbilities.deleteKeepsFields`
2053///     (`is_path_listed`), never `$creatorId`
2054///     (`PreallocationBinding::is_kept_on_removal`). `create_document_types_from_document_schemas`
2055///     1 and `set_document_schema` refuse, under full validation, a preallocated index
2056///     with no binding that holds (`validate_preallocated_indexes_kept_on_removal`,
2057///     `InvalidContractStructure`); the reference validation 0 checks the key width of a
2058///     `where` pair only through a binding that holds; and the Drive insert of a referenced document
2059///     (`add_document_for_contract_operations` 1) and the document cost model
2060///     preallocate only through one that holds
2061///     (`Index::preallocation_bindings_for_target`, now given the referenced type).
2062///     A moderator's removal leaves the trees, like its record, and a restore,
2063///     which puts the document back through the create path, finds them in place.
2064///     Inert for every contract that could be registered before: a moderated
2065///     reference never bound a preallocated index.
2066///
2067/// 69. **Index entries that outlive a delete (`outlivesDelete`)**: an index
2068///     keyword of meta-schema v3 and parser generation 3, in place
2069///     (`Index::outlives_delete`, `IndexLevelTypeInfo::outlives_delete`,
2070///     `IndexLevel::outlives_delete_at_or_below`), admitted only on a
2071///     `timeRange` index with a `ttl` of an indexOnly type, without a sum and
2072///     on a type without `entryPayload`; every schema property must also sit
2073///     in an index that neither skips nor outlives deletes, the proof index
2074///     may not outlive deletes (`index_only_proof_index`), and the flag is
2075///     fixed with the index (`find_first_outlives_delete_change`). A delete
2076///     leaves such an index's entries to expire with their window: document
2077///     index-only delete state validation 0 and Drive's row-integrity gate do
2078///     not probe it, and the delete walkers (top and index level 2) skip it
2079///     (`level_removes_entry`, with `IndexLevel::cleared_on_delete_at_or_below`). The row commitment leaves `$createdAt` out when
2080///     every index involving it outlives deletes
2081///     (`index_only_row_commits_created_at`, read off the index structure's
2082///     root, `IndexLevel::created_at_indexed_only_by_outliving`, and shared by
2083///     the commitment, the delete transition's construction, advanced
2084///     structure validation 0, which then refuses a carried `$createdAt`, and
2085///     Drive's indexOnly delete, which refuses one too). Document create state
2086///     validation 1 and the within-batch collision tracker do not probe such
2087///     an index, and the indexOnly terminal insert writes over an entry
2088///     already standing there, without reading it. Registration requires the
2089///     index's key (its properties but `$createdAt`, and its terminal) to hold
2090///     the key of an index a delete clears that skips nothing, so no two
2091///     documents in state share one of its entries. Inert for every contract
2092///     without the keyword, which every earlier grammar refuses.
2093/// 70. **A contested type sums only small values**: parser generation 3, in
2094///     place, refuses under full validation a document type with a contested
2095///     index and a summed property (`summable`, `averageable`,
2096///     `documentsSummable` or `documentsAverageable`) unless the property's
2097///     schema declares a `minimum` of at least -2^27 and a `maximum` of at most
2098///     2^27 (`SYSTEM_LIMITS_V4.max_contested_summed_value_magnitude`, `None` in
2099///     the earlier tables). The end of a contest writes the winner's document
2100///     into the type's sums with no transition to refuse, so the values must be
2101///     small enough that the sums stay in `i64`, which they do short of 2^36
2102///     documents. A stored contract still parses.
2103/// 71. **Documents deleted only when consumed (`canBeDeleted:
2104///     "onlyWhenConsumed"`)**: a third `canBeDeleted` value of meta-schema v3
2105///     and parser generation 3, in place
2106///     (`parse_can_be_deleted_only_when_consumed_keyword`, passed to the core
2107///     parse as `indexOnly` is, `false` for generations 1 and 2;
2108///     `DocumentTypeV2Getters::documents_deleted_only_when_consumed`). The
2109///     owner's delete reads it as `false` (document delete advanced structure
2110///     validation refuses it, 10404), and a `refersTo` with `consume` may
2111///     target the type (`DocumentReferenceLookup::referenced_side_error`,
2112///     which refused every type its owner can not delete). Its documents can
2113///     leave state, so the type is a `deletableDocument` target, never a
2114///     `permanentDocument` or `moderatedDocument` one
2115///     (`documents_can_disappear`, `document_reference_kind`). A consumed
2116///     document is deleted without its owner's `canBeDeleted` guard
2117///     (`ForceDeleteDocument` beside a contested create,
2118///     `force_delete_document_for_contract_operations` in
2119///     `AddDocumentAndDeleteConsumed`), so Drive's delete guard stays strict
2120///     for the owner's delete. Refused on a type that keeps history or is
2121///     indexOnly (10231), and fixed on update (`validate_update` v1, 40212).
2122///     Inert for every contract without the value, which every earlier grammar
2123///     refuses.
2124///
2125/// 72. **A barred author may still retract (`retractedWhen`)**: a document
2126///     type of meta-schema v3 and parser generation 3, in place, may declare
2127///     `retractedWhen`, one condition in the grammar of an `immutable` entry's
2128///     `when` (`$old.` reads, no `countOf` or `sumOf`), only on a mutable type
2129///     of a contract keeping a banlist or a suspension list (10231 on every
2130///     parse), and fixed on update (document type update validation 1, 40212).
2131///     `contract_moderation_gate` v0, in place, lets a banned or suspended
2132///     signer's replaces on such a type through with its bar
2133///     (`ContractModerationRefusal::retraction_bar`, `refused` now optional),
2134///     and the shared transformer, after fetching the stored document, refuses
2135///     with the bar (41107, 41108), paid with the nonce bumped, each whose
2136///     written document does not meet the condition or whose condition
2137///     faults. Every other rule of the type still judges the replace. So an
2138///     author whose documents can not be deleted can still take one back. Inert
2139///     before this version: the gate and the keyword exist only here.
2140///
2141/// 73. **An index that counts another index's entries
2142///     (`summableOffCountIndex`)**: an index keyword of meta-schema v3 and
2143///     parser generation 3, in place (`Index::summable_off_count_index`,
2144///     `IndexLevelTypeInfo::summable_off_count_index`), admitted only on an
2145///     indexOnly type with `rangeSummable`, naming a source index of the type
2146///     that holds every document once; its other properties must be fixed by
2147///     the source through unchanging `where` values of same-contract
2148///     `permanentDocument` or `moderatedDocument` references
2149///     (`validate_summable_off_count_indexes_lossless`, judging a value as a
2150///     lookup's key part is judged, `why_value_can_change`: an optional
2151///     `deletableDocument` reference by id a replace may clear once its
2152///     document is deleted is not fixed, and from this version neither is a
2153///     findBy key part, a findBy function's param or a `where` value beside
2154///     one), and one summed value per type is kept. Such an index keeps one `Element::SumItem` per group
2155///     in place of a value tree and entries: the index walkers (insert and
2156///     delete index level 2) move it by one per document, preallocation
2157///     creates it at zero, and document create state validation 1, document index-only delete
2158///     state validation 0, the within-batch collision tracker and the proof
2159///     index never use it. `rankedSummable` and `rankedAverageable` gain the
2160///     `{ "at": ... }` form on such an index only, stamped on the index
2161///     levels (`IndexLevel::ranked_sum_grouping`, `ranked_average_grouping`,
2162///     `sum_propagating`) and laid out by Drive as sum chains, count-and-sum
2163///     chains where an average ranking or `rangeCountable` adds counts
2164///     (`property_name_tree_type_and_ranked_axes_for_level`,
2165///     `ranked_chain_value_tree_type`); its `rankedCountable` is parsed into
2166///     that Sum ranking, since a document count there is its sums (no
2167///     `rangeCountable` needed). Sum, average and ranked queries name
2168///     the source index for the summed value, and a count query reads such
2169///     an index's sums, its document counts: a point read
2170///     (`document_count_of_element`), and a ranked or having-range read on
2171///     its Sum secondaries (`read_axis_for`), and a range read through the
2172///     sum surface's range forms (`counter_sums_query`). A range total
2173///     through any index whose path passes through a ranked level (its own,
2174///     or one another index ranks at a shared level) is refused cleanly
2175///     (`refuse_a_range_total_through_a_ranked_index`). Drive's batch methods,
2176///     `apply_drive_operations` and `convert_drive_operations_to_grove_operations`
2177///     at version 1, refuse a batch moving one document type's counters for
2178///     more than one document (`refuse_repeated_counter_moves`). Needs
2179///     grovedb's `GROVE_V4`, which admits a bare `SumItem` under a
2180///     `ProvableCountProvableSumIndexedTree`. Inert for every contract without
2181///     the keyword, which every earlier grammar refuses. For any index, the
2182///     range-total verifiers at version 1 (`DRIVE_VERIFY_METHOD_VERSIONS_V3`:
2183///     `verify_aggregate_count_proof`, `verify_carrier_aggregate_count_proof`,
2184///     `verify_aggregate_sum_proof`, `verify_carrier_aggregate_sum_proof`,
2185///     `verify_aggregate_count_and_sum_proof` and
2186///     `verify_carrier_aggregate_count_and_sum_proof`) verify a proof showing
2187///     the range holds nothing (an equality value no document holds, or an
2188///     empty tree of a kind the read does not aggregate), which grovedb's
2189///     aggregate verifiers refuse, as a zero total or no carrier branch
2190///     (`or_empty_range_total`), and the unproven range totals, keyed on the
2191///     same verifier versions, read an absent value as zero
2192///     (`aggregate_or_zero_when_absent`); and
2193///     `verify_composite_documents_proof` 1 reads the sum-bearing items of a
2194///     `documentsSummable` type as documents. Their
2195///     version 0, which every earlier protocol version selects, refuses both
2196///     proofs, and the unproven total fails, as released; the prover is
2197///     unchanged.
2198///
2199/// 74. **Withdrawals also fit a Core-anchored limit**: pooling
2200///     (`pool_withdrawals_into_transactions_queue` 2, which reuses version 1's
2201///     pooling through a shared helper) admits withdrawals up to the smaller of
2202///     the daily withdrawal limit (note 4) and
2203///     `calculate_core_anchored_withdrawal_limit`, a stricter copy of Core v24's
2204///     relative net unlock rule (dash#7712) read from Core's own credit pool
2205///     balances at chain locked heights: the pool may drop by at most
2206///     `core_credit_pool_unlock_limit_percent` (15; Core allows 20) of its
2207///     highest balance at a window start Core may use for the unlock (Core's
2208///     window, `core_credit_pool_window_blocks` 576 or
2209///     `regtest_core_credit_pool_window_blocks` 100, back from the chain locked
2210///     height, up to Core's asset unlock validity, `core_expiration_blocks` 48,
2211///     later), at least
2212///     `core_credit_pool_unlock_limit_floor` (1500 Dash; Core's floor is 2000),
2213///     less what is queued or broadcast and not completed yet. The formula is
2214///     `core_credit_pool_unlock_limit` 0 in `DPP_METHOD_VERSIONS_V3`. Before
2215///     pooling, `scan_core_blocks_for_withdrawals` reads the Core blocks the
2216///     chain locked height passed (at most `core_blocks_scanned_per_block_limit`,
2217///     32, per block) and records each one's credit pool balance, read from the
2218///     block's coinbase alone (`getspecialtxes`), under the withdrawals tree. The
2219///     Platform-side accounting can grant more than Core will mine (an asset lock published to
2220///     Platform after Core mined it, a whole epoch of Core rewards minted in one
2221///     block); over Core's limit an unlock waits unmined and is re-signed, and
2222///     while Core's mempool holds more than the limit Core InstantSend-locks no
2223///     withdrawal at all. The balance tree is created at genesis and by
2224///     `transition_to_version_14`, and `cleanup_expired_locks_of_withdrawal_amounts`
2225///     1 prunes it by Core height.
2226///
2227/// 75. **No reference by id to an indexOnly document type**: the contract
2228///     reference validation 0 (`validate_data_contract_references`), in place,
2229///     refuses a `permanentDocument`, `deletableDocument` or
2230///     `moderatedDocument` reference without `findBy` (or with `inList`) whose
2231///     referenced document type, in the declaring contract or another, is
2232///     indexOnly (`ReferencedDocumentTypeIndexOnlyError`, 40146, StateError
2233///     discriminant 171). Such a type's documents exist only as index entries,
2234///     and Drive refuses to fetch one by id, so every write resolving the
2235///     reference failed with an internal error, dropped unpaid. A `findBy`
2236///     into one keeps its own refusal (40137, or 10231 in the declaring
2237///     contract). Inert before this version: only parser generation 3 admits
2238///     an indexOnly document type.
2239///
2240/// 76. **Every revealed nullifier is recorded once**: each action of an
2241///     outputs-only Orchard bundle reveals a nullifier (that of a dummy spend,
2242///     which becomes the new note's `rho`). The spends already recorded and
2243///     checked theirs; now `Shield`, `ShieldFromAssetLock` and
2244///     `ShieldFromIdentity` do too. `transform_into_action` 1 of the shield and
2245///     the shield from asset lock (`DRIVE_ABCI_VALIDATION_VERSIONS_V10`), and
2246///     `transform_into_action` 0 of the shield from identity in place, refuse a
2247///     nullifier repeated inside the bundle or already recorded, with
2248///     `NullifierAlreadySpentError`: unpaid for the first two, as for the
2249///     spends, and a paid nonce bump for the identity-signed one. The
2250///     high-level operations of the shield and the shield from asset lock 1
2251///     (`DRIVE_STATE_TRANSITION_METHOD_VERSIONS_V4`), and of the shield from
2252///     identity 0 in place, record the nullifiers. Recording them is metered
2253///     storage for the shield and the shield from identity; the shield from
2254///     asset lock's flat pool fee already prices a note and a nullifier write
2255///     per action. The shield from identity's admission floor
2256///     (`compute_shielded_identity_balance_write_fee` 0, the client's estimate
2257///     of its complete fee) uses versioned allowances of 400 effective bytes
2258///     per action and 500 flat bytes, covering the complete execution-event
2259///     admission estimate. Actual fees remain metered. Before the first PV14
2260///     candidate's transitions, the activation transaction adds the rho of
2261///     every retained CREDIT note to the permanent nullifier set, including
2262///     historical shielding outputs. Existing entries and their flags remain
2263///     unchanged. The protocol upgrade ladder runs this one-time migration
2264///     when crossing into PV14, with 2048 notes per page and 2048 inserts per
2265///     batch; token pools are not backfilled.
2266///
2267/// 77. **Owner identities for shared and extended-address masternodes**: from
2268///     v24 on, Dash Core lists shared masternodes, which have no owner, payout
2269///     or collateral address, and extended-address masternodes, which have a
2270///     `payouts` list instead of a `payoutAddress`. `create_owner_identity` 1
2271///     needs both addresses and fails on such a masternode with
2272///     `DashCoreBadResponseError`, which fails the block. With
2273///     `create_owner_identity` 2 and `update_masternode_identities` 1
2274///     (`DRIVE_ABCI_METHOD_VERSIONS_V10`), a masternode without an owner
2275///     address gets no owner identity, only its voter and operator identities;
2276///     one with an owner address and either a legacy payout address or a sole
2277///     payout with a matching P2PKH script gets the version 1 identity,
2278///     TRANSFER key id 0 and OWNER key id 1, byte for byte; other payout shapes
2279///     get only OWNER key id 1. Legacy payout-address rotation is unchanged.
2280///     Payout-list changes retain, re-enable or add the sole supported P2PKH
2281///     TRANSFER key and disable obsolete TRANSFER keys. Split, empty or
2282///     unsupported lists disable all TRANSFER authority while preserving OWNER
2283///     and balance. Historical updaters keep their payout-list policy. This
2284///     version must be active on a network before its Dash Core activates V24,
2285///     since earlier versions keep failing on these masternodes.
2286///
2287/// 78. **Versioned Core masternode address resolution**: `update_masternode_list` 1
2288///     resolves nested platform addresses first, then falls back to legacy ports,
2289///     before storing the masternode state. Earlier protocol versions keep their
2290///     flat-field interpretation. The stored layout and validator construction
2291///     remain unchanged: new validators read the resolved stored ports, and an
2292///     existing validator is refreshed on a ban, service or P2P-port change.
2293///     Each diff starts from the old persisted representation so transient address
2294///     data retained before activation cannot make a running node disagree with
2295///     a restarted one. Payout lists remain outside the persisted representation.
2296///
2297/// 80. **A BLS12_381 signature must verify**: `verify_identity_signed_signature`
2298///     1 (`STATE_TRANSITION_METHOD_VERSIONS_V2`), the signature check that
2299///     identity-signature validation runs for every identity-signed
2300///     transition, refuses a signature by a BLS12_381 key that does not verify
2301///     (`InvalidStateTransitionSignatureError`, unpaid, as for ECDSA keys).
2302///     Generation 0 refused one only when the key or the signature could not be
2303///     read, and earlier versions replay through it. Identity-signature
2304///     validation v0, in place, passes the platform version to the check; the
2305///     tables of every earlier version select generation 0, the code it called
2306///     before.
2307///
2308/// 81. **Token shielded pools**: a token configuration in format version 1
2309///     (`TokenConfiguration::V1`, admitted by `CONTRACT_VERSIONS_V6`'s
2310///     `token_configuration_format` bounds) can set `hasShieldedPool`, which
2311///     gives the token its own Orchard pool under
2312///     `[Tokens, TOKEN_SHIELDED_POOLS_KEY, token_id]` laid out like the credit
2313///     pool. A pooled token must leave its freeze, unfreeze and destroy-frozen-
2314///     funds rules unassigned, since notes have no owner to freeze. Seven batch
2315///     token transitions (`TokenShield`, `TokenUnshield`,
2316///     `TokenShieldedTransfer`, `TokenMintToPool`, `TokenBurnFromPool`,
2317///     `TokenClaimToPool` and `TokenDirectPurchaseToPool`, validated through
2318///     `DRIVE_ABCI_VALIDATION_VERSIONS_V10` and gated by
2319///     `TOKEN_SHIELDED_POOL_INITIAL_PROTOCOL_VERSION`) move tokens between an
2320///     identity balance, the supply and the pool or inside it; the identity
2321///     signs and pays the fee in credits, and every bundle binds its pool into
2322///     the Orchard sighash, since all pools share the empty-tree anchor an
2323///     unbound bundle would verify against: a spend bundle binds the token id
2324///     and the batch owner (a burn binds the burner: the batch owner, or the
2325///     proposer of a group action), plus the recipient and amount where tokens
2326///     leave the pool; an outputs-only bundle (`TokenShield`,
2327///     `TokenMintToPool`, `TokenClaimToPool`, `TokenDirectPurchaseToPool`),
2328///     whose anchor is never checked against a pool, binds a per-kind tag,
2329///     the token id and the batch owner (for a group action mint, the
2330///     proposer).
2331///     A batch carrying any of these bundles, or a document whose token cost
2332///     is paid out of a pool, has to hold the compute fee the bundles will be
2333///     charged (`compute_shielded_verification_fee` per bundle-carrying
2334///     sub-transition): the batch minimum balance pre-check v1
2335///     (`identity_minimum_balance_pre_check`) reserves it on top of the flat
2336///     per-sub-transition minimum, which is orders of magnitude smaller. A
2337///     batch without a bundle is asked for the flat minimum, unchanged, and
2338///     one that asks the contract owner to pay its gas is asked for its
2339///     principal alone as in item 11, the compute fee being gas. The floor
2340///     refuses only what fee validation would refuse later, but it refuses it
2341///     before the Halo 2 work: `TokenClaimToPool`'s proof is skipped in check
2342///     tx, since its claimable amount is only known against state, so without
2343///     the floor a signer between the two numbers cleared the mempool with no
2344///     verification run and every validator then did the verification inside
2345///     block validation, only to refuse the batch unpaid, leaving the same
2346///     bytes replayable. The same holds for the bundle of a group action's
2347///     non-proposing signer, whose proof check tx also skips.
2348///     The pool balances are a term of the token conservation check
2349///     (`calculate_total_tokens_balance` v1 in `DRIVE_TOKEN_METHOD_VERSIONS_V2`).
2350///     `record_token_shielded_pool_anchors`
2351///     (`DRIVE_ABCI_METHOD_VERSIONS_V10`) records and prunes the anchors of the
2352///     pools a block touched. The pools root tree is inserted by
2353///     `transition_to_version_14` and by `create_initial_state_structure` v4;
2354///     the six shielded queries accept an optional `token_id` to target a token
2355///     pool.
2356///
2357/// 82. **An expiring type sums only values that keep its sums in range**:
2358///     parser generation 3, in place, refuses under full validation a document
2359///     type with a `ttl` and a summed property (`summable`, `averageable`,
2360///     `documentsSummable` or `documentsAverageable`) unless the property's
2361///     schema declares a `minimum` of at least 0, or a `minimum` of at least
2362///     -2^27 and a `maximum` of at most 2^27
2363///     (`SYSTEM_LIMITS_V4.max_expiring_signed_summed_value_magnitude`, `None` in
2364///     the earlier tables). The cleanup deletes expired documents at the end of
2365///     a block with no transition to refuse, and removing a negative value
2366///     raises the sums it was in; removing values that are never negative only
2367///     lowers them, and values within ±2^27 keep them in `i64` short of 2^36
2368///     documents. A stored contract still parses. No earlier version parses
2369///     `ttl`.
2370///
2371/// 83. **Unambiguous document properties**: `validate_document` generation 1 rejects
2372///     repeated text keys in nested maps, including maps inside arrays, before property
2373///     size, path and schema validation. Create, replace, indexOnly delete and moderator
2374///     field changes use the same check. Rejection uses ValueError (10103) through the
2375///     existing paid-invalid flow; generation 0 remains selected before this version.
2376///
2377/// 84. **Document token payments obey the issuer's movement policy**:
2378///     document-base state validation 2 supersedes 1
2379///     (`DRIVE_ABCI_VALIDATION_VERSIONS_V10`). A transparent transfer or burn
2380///     payment of a paused token is refused (`TokenIsPausedError`, 40711).
2381///     A transfer to a frozen document contract owner is refused
2382///     (`IdentityTokenAccountFrozenError`, 40702, naming that owner) only when
2383///     the token issuer's `allowTransferToFrozenBalance` is false; its default
2384///     is true, and external issuers are included. Reads are billed in order:
2385///     payer freeze, payer balance, pause, recipient info, then issuer metadata
2386///     only if frozen, and the issuer contract only when external. Owner
2387///     self-payments emit no transfer and retain only their payer checks.
2388///     Shielded payments retain their separate pool validation; native burn
2389///     policy and earlier protocol tables are unchanged.
2390///
2391/// 85. **Rules that gate the owner's delete (`deleteConstraints`), and `$id`
2392///     in a total's filter**: a document type of meta-schema v3 and parser
2393///     generation 3, in place, may declare `deleteConstraints`, named rules in
2394///     the `propertyConstraints` grammar (`parse_delete_constraints`,
2395///     `apply_delete_constraints_v0`, run by `apply_property_constraints` 0
2396///     on `parse_property_constraints`; `DocumentTypeV2Getters::delete_constraints`).
2397///     Document delete state validation 1 (`DRIVE_ABCI_VALIDATION_VERSIONS_V10`)
2398///     runs the checks of version 0, then reads the totals the rules read
2399///     (`read_delete_constraint_aggregates`, billed, each as it will be once
2400///     the document is gone) and judges every rule on the stored document
2401///     (`validate_delete_constraints`, versioned with
2402///     `validate_property_constraints`), refusing the first one broken with
2403///     `DocumentDeleteConstraintViolatedError` (state code 40147, discriminant
2404///     172), paid. A `countOf` or `sumOf` filter may match by `"$id"`, the
2405///     document's own id (`AggregateBinding::Id`, an identifier key, in
2406///     `propertyConstraints` too: the shared batch transformer's aggregate read,
2407///     in place, passes the document's id), so a poll is deleted only while no
2408///     vote names it. Refused on a type with `canBeDeleted: false`,
2409///     `"onlyWhenConsumed"` or `indexOnly` (10231, every parse), held to the rule
2410///     limits apart from `propertyConstraints`, frozen on update (10246), and a
2411///     `refersTo` with `consume` may not target such a type
2412///     (`DocumentReferenceLookup::referenced_side_error`). Moderator deletes and
2413///     `ttl` expiries are not judged. Inert before this version: the earlier
2414///     meta-schemas refuse the keyword and the `$id` filter value, and their
2415///     tables select delete state validation 0.
2416///
2417/// 86. **Bounded schema depth check**: `validate_max_depth` 1
2418///     (`CONTRACT_VERSIONS_V6`) no longer walks a `$ref` whose target is a
2419///     scalar and never clears its visited set, so every ref target is
2420///     expanded at most once and the check is bounded in schema size. Before
2421///     this a crafted `$defs` chain with `$ref`s to scalars cleared the cycle
2422///     guard and made the check, run during contract registration in block
2423///     execution, exponential. Verdict, depth and size are unchanged for
2424///     schemas without a scalar `$ref` target; earlier versions replay
2425///     through generation 0.
2426///
2427/// 87. **Moderator document restores obey `propertyConstraints`**: moderation state
2428///     validation 0, in place, judges the rules of the restored type that read a
2429///     `countOf` or `sumOf` total (`SystemChange::Restore`, item 39), the only values
2430///     that can have moved while the document was gone, after uniqueness and before
2431///     constructing restoration operations. The retained document supplies its original
2432///     id, owner, properties, times, heights and revision, and is the stored version a
2433///     rule reads through `$old.`. The shared aggregate reader
2434///     adds it to the live totals as an insertion, with no contribution from its removal
2435///     record. A failing rule returns paid `DocumentPropertyConstraintViolatedError`
2436///     (10422) in a block, charging the moderator and consuming its nonce while leaving
2437///     the document absent and the removal record unrestored. Mempool admission refuses
2438///     it without persisting fees or a nonce change. Types without rules retain their fees.
2439///     Full property schema validation and `deleteConstraints` are not added to restore.
2440///     Earlier versions are unchanged: contract moderation is inactive before version 14.
2441///
2442/// 88. **Rules that read the bytes of a byte array**: the `propertyConstraints`
2443///     grammar (item 39; meta-schema v3 and `parse_property_constraints` 0, in
2444///     place) gains a `byteAt` integer operand, `{ "byteAt": [path, index] }`,
2445///     the byte (0 to 255) at a literal index from 0 to 65535 of a byte array
2446///     property, 0 when the array does not hold it or the document leaves it
2447///     out, one node; and `startsWith` and `endsWith` test byte arrays when a
2448///     side names a byte array property, the other a `{ "const": hex }` or
2449///     another byte array property, three nodes, not holding for an array left
2450///     out (`PropertyConstraint::BytesAffix`). Parser generation 3 refuses a read
2451///     of anything but a stored byte array property, an index at or past its
2452///     `maxItems`, a constant longer than it, a constant that is not an even
2453///     number of hex digits, a default for a byte array, and an `equal`,
2454///     `notEqual`, `in` or `contains` of one (10231). `immutable` conditions,
2455///     `retractedWhen` and `deleteConstraints` read bytes the same way.
2456///     Inert before this version: the earlier meta-schemas refuse
2457///     `propertyConstraints` and their parsers ignore it.
2458///
2459/// 89. **Non-transferable tokens**: a format 1 token configuration
2460///     (`TokenConfigurationV1`) gains `transferable`, `true` when absent and
2461///     fixed at creation (no `TokenConfigUpdate` item). With `false` the batch
2462///     advanced structure validation 1 (`DRIVE_ABCI_VALIDATION_VERSIONS_V10`)
2463///     refuses every `TokenTransfer` from the contract the action carries
2464///     (`TokenNotTransferableError`, 40726, paid, and in check tx); the
2465///     document type parser, in place, refuses a cost in the contract's own
2466///     such token that pays the contract owner instead of burning it
2467///     (`NonTransferableTokenPaymentMustBurnError`, 10280); data contract
2468///     create and update state validation 0, in place, refuse a cost in
2469///     another contract's such token (40726), reusing the read that checks the
2470///     token exists, external burns being refused already (10261);
2471///     document-base state validation 2 refuses a payment to the contract
2472///     owner in the contract's own such token again (40726), from the
2473///     configuration in hand; `validate_shielded_pool_rules` refuses it with a
2474///     shielded pool (`NonTransferableTokenShieldedPoolError`, 10279, unpaid
2475///     at the pre-activation gate); and the pool threshold
2476///     `TokenConfigUpdate` items are refused on a format 1 configuration
2477///     without a pool. Mints, claims, direct purchases, burns, freezes and
2478///     burn payments for the contract's own documents are unchanged.
2479///     Inert before this version: only format 1 can be non-transferable, and
2480///     the pre-activation gate refuses that format on every earlier version.
2481///
2482/// 90. **Unsigned integers are keyed in value order**: `serialize_value_for_key`
2483///     and `deserialize_value_for_key` 1 (`CONTRACT_VERSIONS_V6`) key a property,
2484///     or derived index property, of an unsigned integer type by its plain
2485///     big-endian bytes (`DocumentPropertyType::encode_value_for_tree_keys_v1`).
2486///     Generation 0 flipped the top bit as for a signed value, so the values from
2487///     the middle of the type's range up (128 and above for a `u8`) sorted below
2488///     the others in every index: range queries, ordering, range counts and sums
2489///     across that point came out wrong, and a count or sum over a range whose
2490///     bounds straddled it was refused. A key keeps its width. The `$` system
2491///     fields keep their keys, and so do the paths of a contest's vote poll
2492///     (`serialize_value_for_vote_poll_key`), which the masternodes' vote records
2493///     address, and so does a property that ends a `rangeSummable` index, in
2494///     every index of its type: the tree of its values keeps a sum in every
2495///     node, and values of both signs that fit the old order can leave the
2496///     signed 64-bit range in every balanced tree of the new one (an update
2497///     before this version can make a summed property unsigned while it holds
2498///     negative values).
2499///     `transition_to_version_14` first moves every other key generation 0 wrote
2500///     (`Drive::rekey_unsigned_integer_index_values`) with GroveDB's `move_op`
2501///     (`GROVE_V4`, from the GroveDB bump to `b50a583377`), in batches of
2502///     `max_rekey_batch_moves` moves (`SYSTEM_LIMITS_V4`), twins that trade
2503///     keys in one batch. A moved subtree keeps its stored bytes, so its hashes,
2504///     aggregates and Merk shapes are unchanged; only the tree holding the moved
2505///     keys takes another shape. Contract validation refuses an `integerRange`
2506///     on a property that keeps the earlier keys, whose grid reads value order.
2507///     The features of this version that key
2508///     integers themselves (an `integerRange` window start, an indexOnly member
2509///     key, its row commitment and synthesized id) use the new keys from the
2510///     start. Earlier versions replay through generation 0.
2511///
2512/// 91. **Property type shorthands, `identifier` and `bytes`**: a property
2513///     schema may write `"type": "identifier"` for `"type": "array",
2514///     "byteArray": true, "minItems": 32, "maxItems": 32, "contentMediaType":
2515///     "application/x.dash.dpp.identifier"`, and `"type": "bytes", "size": n`
2516///     for `"type": "array", "byteArray": true, "minItems": n, "maxItems": n`,
2517///     on a property at any level, the `items` of a typed array and a
2518///     `schemaDefs` definition. `DocumentType::expand_property_type_shorthands`
2519///     0 (`expand_property_type_shorthands`, new in `CONTRACT_VERSIONS_V6`,
2520///     `None` in the earlier tables) rewrites them into the long form before
2521///     anything reads the schema: parser generation 3, in place, expands the
2522///     document type schema and the contract's `$defs` before the meta-schema
2523///     (v3, unchanged), the core parse with its `$ref` walks, the validator it
2524///     compiles and every later stage; `validate_document` 1, in place,
2525///     expands before compiling a stored contract's validator;
2526///     `validate_schema_compatibility` 1, in place, expands the old and the
2527///     new document type schemas and `$defs` before diffing, so rewriting a
2528///     property or a definition between the two spellings is no change; and
2529///     the check_tx schema-depth pre-check walks the rewritten schema, as the
2530///     block's check does. The document type, the stored contract and the
2531///     transition keep the schema as sent. Refused (10231) under full
2532///     validation: `byteArray`, `minItems`, `maxItems` or `contentMediaType`
2533///     beside a shorthand, `size` on `identifier`, and `bytes` without a
2534///     `size` from 1 to `SYSTEM_LIMITS_V4.max_field_value_size` (5120).
2535///     Without full validation nothing is refused and a shorthand that can not
2536///     be rewritten is left as sent, so a contract stored before this version
2537///     keeps loading even where it holds one no reader looks at (the `$defs`
2538///     of a contract without document types, which are left unexpanded, or an
2539///     entry a repeated key shadows), as the upgrade's read of every stored
2540///     contract requires. The schema validation fee is charged on the long
2541///     form. Inert before this version: the expansion rewrites nothing there,
2542///     meta-schemas v0 to v2 refuse both names (no JSON Schema type), and
2543///     parser generations 0 to 2 refuse them as unsupported property types.
2544///
2545/// 92. **Indexes on the elements of a typed array**: an index may name a
2546///     top-level typed array property, at any position, one per index, and
2547///     keys a document once by each distinct element, an element keyed as a
2548///     property of the element type is. Parser generation 3 (in place) admits
2549///     it and refuses, under full validation: a
2550///     unique or contested index, `nullSearchable: false`, a ranking above the
2551///     array, a second array (10231); a `maxItems` above
2552///     `SYSTEM_LIMITS_V4.max_indexed_array_items` (16), or
2553///     `max_windowed_indexed_array_items` (4) on an index with a `timeRange`
2554///     or `integerRange`, and elements past the key limits of their type or
2555///     byte array elements that may be empty (10205); and a type whose
2556///     document can write more than `max_index_entries_per_document` (256)
2557///     index entries (10231). On every parse it adds the array to the index's
2558///     skip set (`skip_if_absent` keeps the declared keyword) and stamps its
2559///     index level with the array's `maxItems`
2560///     (`IndexLevel::stamp_indexed_arrays`). `serialize_value_for_key` and
2561///     `deserialize_value_for_key` 1 (90, in place) key a typed array
2562///     property's value as one element, keyed as a property of the element's
2563///     type is, an unsigned element in value order, and
2564///     `get_raw_array_elements_for_document_type` 0 (new, `DOCUMENT_VERSIONS_V4`,
2565///     `None` before) gives a document's sorted, distinct element keys. The
2566///     v2 insert and delete walkers (in place) write and remove one value tree
2567///     per element at a stamped level, a document with no element reaching
2568///     none of its branches; the v1 update (in place) diffs the old and new
2569///     entries of an index naming an array, or bucketing its first property,
2570///     inserting and refreshing first and deleting last. The document cost
2571///     and the TTL drain budget count an array's `maxItems`, and the document
2572///     `ttl` cleanup weight counts the levels from the array on once per
2573///     element it allows. Queries read the elements with `contains` (one
2574///     element: an equality on its key, cursors allowed when the cursor
2575///     document holds it) and `containsAny` (an `in` over several: a page
2576///     drops a document's repeats, on the server and in verification, and
2577///     takes no cursor); grouping v1 groups them, grouping v0 refuses them,
2578///     an index naming an array is read only with its elements bound, and
2579///     count, sum and average requests read several elements only grouped
2580///     per element. An indexOnly type's index of a typed array is admitted,
2581///     on every parse (`apply_index_only`, 10231), when another index keeping
2582///     one entry per document (no `$createdAt`, skip, `outlivesDelete` or
2583///     typed array) has its whole key inside the array index's key without
2584///     the array, the array is top-level, alone in the index and declares
2585///     `uniqueItems`, and the index is `preallocated` or a
2586///     `summableOffCountIndex` index only as 95 says; such an index is never
2587///     the proof index, a counter's source or the only index keeping another
2588///     required property. Its row commitment holds the list in order (an empty, null or
2589///     absent list alike), its entry probes fan out per element, the create's
2590///     state probe skips it, and synthesis rebuilds an entry as a document
2591///     listing its one element. Every indexOnly entry insert bills its
2592///     commitment's double-SHA256 by its preimage, the dry run by the widest
2593///     preimage the type allows. Inert before this version: generations 0 to
2594///     2 refuse a typed array in an index, meta-schemas v0 to v2 have none,
2595///     and indexOnly types exist from this version only.
2596///
2597/// 93. **Fee estimates size sum and count trees, and sum items, as they are
2598///     stored**: grovedb's `GROVE_V4`
2599///     (`average_case_propagated_aggregate_kind` 1) estimates a sum, big sum,
2600///     count or count-sum tree that a batch creates together with its contents
2601///     as that tree rather than as a plain tree. The `apply: false` estimate of
2602///     a document insert under a countable or summable index (which creates the
2603///     value tree and its `0` bucket with the document's reference) no longer
2604///     comes in below the applied storage fee: by 9 bytes per aggregate of each
2605///     tree created, 18 bytes for a summable index. A replaced root key of such
2606///     a tree is sized the same way in the estimate's replaced bytes, so an
2607///     estimate that rewrites a sum tree's root (an identity or token balance
2608///     change among them) charges 9 more replaced bytes per tree. `GROVE_V4`
2609///     also sizes an inserted `SumItem` or `ItemWithSumItem`, and a replaced
2610///     `ItemWithSumItem`, with its sum at the fixed 9-byte width the apply
2611///     charges, up to 8 bytes more per item, in both estimators
2612///     (`average_case_sum_item_cost_size` 1 and
2613///     `worst_case_sum_item_cost_size` 1). Applied fees are unchanged. Inert
2614///     before this version: `GROVE_V1` to `GROVE_V3` keep the old sizing.
2615///
2616/// 94. **`where` entries over typed arrays**: a `refersTo` `where` (63) may
2617///     compare a referenced typed array as a list. An equality between two
2618///     typed arrays (`"tags": "tags"`, kept in `property_agreement`) holds for
2619///     the same elements in the same order; `{ "contains": b }`
2620///     (`WhereCondition::Contains`, appended) for a list holding an element
2621///     equal to `b`, a referring property of the element kind or `"$ownerId"`
2622///     (a writer gate on identifier elements, asked about on every replace);
2623///     `{ "containsAll": b }` (`WhereCondition::ContainsAll`, appended) for a
2624///     list holding every element of the referring typed array `b`. Elements
2625///     compare as two single values do (`where_lists_equal`, by
2626///     `Value::same_scalar_data`): an identifier equals its 32 bytes and an
2627///     integer is the same at any width; a list left out is the
2628///     empty one, so two left out are equal and every list holds all of one
2629///     left out, while a `contains` value left out is held by no list. Meta-schema
2630///     v3 and parser generation 3 (in place) read both keys, refusing them on
2631///     `$ownerId`, `$creatorId` and `$id` and a `containsAll` of the writer.
2632///     Contract create and update state validation (data contract reference
2633///     validation 0, in place) admits a typed array pair, until now refused
2634///     with 40126, when both sides are stored typed arrays whose elements share
2635///     one value kind other than a float, and refuses with 40126: a typed array
2636///     paired with anything else, a `contains` or `containsAll` of a property
2637///     that is no typed array, of float elements, bounded by the reference
2638///     property itself or by a value of another kind (the writer only among
2639///     identifiers), a `moderatedDocument` `contains` of the writer whose list
2640///     no removal record keeps. `const`, `in`, `notEqual` and the orderings
2641///     still refuse a typed array. Document reference validation 0 (in place)
2642///     checks them against the document found or the removal record, refusing
2643///     with 40127, and refuses an entry whose referring path is no object on
2644///     the way as a mismatch. Before comparing, it bills the list elements
2645///     such an entry reads, both lists for an equality and a `containsAll`, the
2646///     referenced one for a `contains`, at
2647///     `FEE_VERSION3.document_reference.where_list_credits_per_element` (100
2648///     credits, a field added in place to `FEE_DOCUMENT_REFERENCE_VERSION1`,
2649///     which every schedule carries and only this version reads). A pair of
2650///     lists keys a preallocated or `summableOffCountIndex` index only by its
2651///     elements, as 95 says. Inert before this version: only parser generation
2652///     3 reads a `where`, and this module and that validation are reached from
2653///     this version only.
2654///
2655/// 95. **Preallocated and counter indexes keyed by the elements of a list**:
2656///     an indexOnly type's index naming a typed array (92) may be
2657///     `preallocated` or a `summableOffCountIndex` index when a `where`
2658///     equality (94) makes the array equal to a typed array of the referenced
2659///     document. `Index::preallocation_bindings` binds such an index property
2660///     through the pair (`PreallocatedKeySource::ReferencedDocumentListElements`,
2661///     appended) and `Index::count_index_derivations` derives it; `contains`
2662///     and `containsAll` bind nothing. Parser generation 3 (in place,
2663///     `apply_index_only`) admits either keyword on an array index only so
2664///     bound (10231 otherwise) and asks a `summableOffCountIndex` array index,
2665///     which keeps no entries, for no other index keeping its documents apart;
2666///     the contract-level rules (55, 68 and the counter's lossless rule) judge
2667///     the list as a whole. Contract create and update state validation (data
2668///     contract reference validation 0, in place) refuses with 40126 a list
2669///     pair keying a preallocated index whose referenced elements can hold more
2670///     than 255 bytes. Drive (in place): the v1 document insert preallocates
2671///     such an index's trees under each distinct element of the referenced
2672///     document's list, keyed as the referring type keys its elements, and
2673///     nothing for a list no referring document can hold (empty, absent or no
2674///     list; longer than the referring array's `maxItems` or shorter than its
2675///     `minItems`; repeating an element where it declares `uniqueItems`; or
2676///     holding an element keyed as empty or wider than the referring
2677///     elements); the v2 insert and delete walkers move one counter per
2678///     element where the counter's own level is the array; the document cost
2679///     model follows. The v1 insert's preallocation also inserts a plain tree
2680///     (a value tree, a `0` bucket) under a tree the same walk created
2681///     without reading whether it exists, and the dry run of a document change
2682///     (`estimate_document_change_as_insert_operations` 1) preallocates
2683///     nothing, as an applied change never does. Inert before this version: only parser
2684///     generation 3 admits `preallocated`, `summableOffCountIndex`, an indexed
2685///     typed array and a `where`, and every contract that registers today
2686///     binds no typed array.
2687///
2688/// 96. **A hash key's data is 20 bytes**: key structure validation v1
2689///     (`STATE_TRANSITION_METHOD_VERSIONS_V2`, in place) refuses an
2690///     ECDSA_HASH160, BIP13_SCRIPT_HASH or EDDSA_25519_HASH160 key whose data
2691///     is not 20 bytes (`InvalidIdentityPublicKeyDataError`, 10511), after its
2692///     other rules. Each transition keeps the outcome of its key structure
2693///     check: charged in identity create and identity create from addresses,
2694///     unpaid in identity update and identity create from the shielded pool.
2695///     Such a key otherwise fails when its hash is taken, as an internal error
2696///     that keeps the transition out of every block. The data of an
2697///     ECDSA_SECP256K1 or BLS12_381 key is left to its proof of possession,
2698///     which refuses data that is not a public key. Earlier versions select
2699///     generation 0, which does not check the size of a hash key's data.
2700///
2701/// The app-connect system contract (`SystemDataContract::AppConnect`, schema v1)
2702/// carries only the wallet's `loginKeyResponse`: a flat indexOnly entry keyed by
2703/// the app's ephemeral key hash and the responding identity, with the wallet's
2704/// ephemeral key and encrypted grant in `entryPayload`. Genesis registers it on
2705/// chains born at this version; `transition_to_version_14` inserts it on upgrade.
2706/// The Drive and trusted SDK caches serve it only from protocol version 14.
2707///
2708///
2709/// * `ShieldFromIdentity` (state transition type 21) activates:
2710///   `SHIELD_FROM_IDENTITY_INITIAL_PROTOCOL_VERSION = 14` gates it in
2711///   `is_allowed`, and `DRIVE_ABCI_VALIDATION_VERSIONS_V10` is the first
2712///   table whose `shield_from_identity_state_transition` row enables basic
2713///   structure, identity signature, and nonce validation. It moves credits
2714///   from an identity balance straight into the shielded pool: the funding
2715///   side is identity-signed like `IdentityCreditTransferToAddresses`, the
2716///   pool side is an outputs-only Orchard bundle like `Shield`, bound to the
2717///   funding identity (next item), and the fee is metered plus the shielded
2718///   compute fee, paid from the identity.
2719///
2720/// * The credit pool's outputs-only bundles bind `kind tag || owner` into their
2721///   Orchard sighash (`DPP_METHOD_VERSIONS_V3` sets `credit_pool_bundle_binding`
2722///   to `Some(0)`): `Shield` (`0x84`) the SHA-256 of its input addresses,
2723///   checked by `validate_shielded_proof` v1; `ShieldFromIdentity` (`0x85`) its
2724///   identity id; `ShieldFromAssetLock` (`0x86`) its asset lock identifier,
2725///   checked by the `transform_into_action` v1 that
2726///   `DRIVE_ABCI_VALIDATION_VERSIONS_V10` selects. A third party can no longer
2727///   wrap a proved bundle in a transition of their own. v13 keeps both checks
2728///   unbound. A sender rebuilding the same notes (Faerie Gold) is not stopped:
2729///   that needs the bundles' dummy nullifiers recorded and checked.
2730///   `ShieldFromAssetLock` also gains transition version 1
2731///   (`STATE_TRANSITION_SERIALIZATION_VERSIONS_V3`), the only version 14
2732///   admits: version 0 is refused at decode by `active_version_range`, before
2733///   any proof work, uncharged and with its asset lock left unspent, so one
2734///   still waiting when 14 activates is not burned by the bound check.
2735///
2736/// * `IdentityTopUpFromShieldedPool` (state transition type 22) activates at the
2737///   same gate (`IDENTITY_TOP_UP_FROM_SHIELDED_POOL_INITIAL_PROTOCOL_VERSION = 14`,
2738///   `DRIVE_ABCI_VALIDATION_VERSIONS_V10` row). It spends shielded notes like
2739///   `Unshield` and credits an EXISTING identity's balance instead of a platform
2740///   address: pool-paid flat fee (`compute_shielded_identity_top_up_fee`), no
2741///   platform signature, the target identity and gross amount bound into the
2742///   Orchard sighash, and no system-credit adjustment (pool and identity balances
2743///   are both conservation-equation terms).
2744///
2745/// The wire surface changes only additively: `GetDocumentsRequestV1`
2746/// already carries `selects` / `group_by` / `order_by` / `limit` /
2747/// `offset`; the ranked response is an additive `ResultData.ranked`
2748/// variant, whose `skipped` field is likewise additive; and the v1
2749/// where-clause operator enum gains `IN_TIME_RANGE = 11` and
2750/// `IN_INTEGER_RANGE = 12`, which pre-v14 servers reject as unknown
2751/// operators rather than misread (the v0 wire has neither).
2752/// Contract-bound authentication keys activate through contract-bounds validation v2,
2753/// identity-signature validation v1 and batch advanced-structure v1. Identity creation
2754/// validates key bounds (state v1) and identity-update state v1 retains the contract
2755/// lookup fees; Drive identity methods v2 index and refresh the bound keys. The same v1
2756/// contract-info methods also store the current-key alias of a contract-level encryption or
2757/// decryption key bound under `MultipleReferenceToLatest` in its purpose subtree, where the
2758/// current-key query reads it; v0 wrote it one level up, where its sibling reference could
2759/// not resolve, so registering such a key failed inside Drive on every earlier version.
2760/// Contract group bounds on authentication keys ride the same versions: contract-bounds
2761/// validation v2 admits them, batch transform v2 resolves the member contract's group
2762/// memberships into the action (only for a group-bound signing key) for advanced-structure v1 to judge, and shielded-proof validation v1 refuses them in identity creation from the
2763/// shielded pool, whose sighash preimage layout predates them.
2764/// A transition carrying such a key is inactive before this version (`active_version_range`),
2765/// so earlier protocol versions reject it without charging, as a binary that cannot decode it does.
2766/// Authentication keys may carry a budget and an expiry (the version 1 public key format, which
2767/// `StateTransition::active_version_range` admits from 14). Key structure validation v1
2768/// (`STATE_TRANSITION_METHOD_VERSIONS_V2`) and `validate_identity_public_keys_limits` decide
2769/// which keys may carry them; Drive identity methods v2 write the remaining budget when the key
2770/// is added; identity-signature validation v1 refuses a key whose budget is spent;
2771/// `validate_fees_of_event` v1 refuses an expired key and a spend the remaining budget does not
2772/// cover (only metered processing may overshoot); `execute_event` v1 deducts what was spent.
2773/// Shielded-proof validation v1 refuses a key that carries a budget or an expiry in identity
2774/// creation from the shielded pool, whose sighash preimage does not cover the limits.
2775/// `IdentityKeyLimitsUpdate` (state transition type 23, gated by
2776/// `IDENTITY_KEY_LIMITS_UPDATE_INITIAL_PROTOCOL_VERSION`) raises a key's total budget, and the
2777/// remaining budget with it, or moves its expiry later; it only ever loosens limits. Signed by a
2778/// MASTER key or by a CRITICAL key without limits (`DRIVE_ABCI_VALIDATION_VERSIONS_V10` turns
2779/// its gates on; Drive identity methods v2 rewrite the key and raise the remaining budget).
2780pub const PLATFORM_V14: PlatformVersion = PlatformVersion {
2781    protocol_version: PROTOCOL_VERSION_14,
2782    drive: DRIVE_VERSION_V9, // changed: drive document method versions v4 — v2 index walkers (shared-prefix aggregate indexes become insertable) + the detect_ranked_mode slot; contract method versions v4: the moderation list trees, the document removal record trees and the moderation method table; apply_drive_operations 1 (a moderator's document deletion refunds nobody for what its document operations remove unless its type sets `deleteRefundsOwner`, those operations applied as a GroveDB batch of their own when the batch also frees moderation storage someone is owed, a restored removal record replaced or team action approvals moved or dropped, which is refunded to whoever its flags name; every write of one identity balance, fee pot or prefunded specialized balance in a batch merged into one; a batch writing one token balance or supply twice refused; a batch moving one document type's summableOffCountIndex counters for more than one document refused; repaid identity debt credited to the processing fee pool); convert_drive_operations_to_grove_operations 1 (refuses that counter batch too, then converts as before); index uniqueness gains validate_moderated_document_uniqueness (a moderator's document restore or field change); vote method versions v3: the end-date cleanup of ended contested vote polls removes an end date only once none of its polls remain; token method versions v2: calculate_total_tokens_balance 1 (token shielded pool balances join token conservation) and evonode_participation_rewards 1 (an evonode's token claim covers only the epochs it read); add_contested_indices_for_contract_operations 1: a poll's last index value is a count tree
2783    drive_abci: DriveAbciVersion {
2784        structs: DRIVE_ABCI_STRUCTURE_VERSIONS_V2, // changed: saved platform state structure 1 keeps masternodes and validator sets as one aux entry each
2785        methods: DRIVE_ABCI_METHOD_VERSIONS_V10, // changed: records the per-block total credits history for the daily withdrawal limit; record_token_shielded_pool_anchors records and prunes the anchors of the token pools a block touched; decode_raw_state_transitions, execute_event, validate_fees_of_event and add_distribute_storage_fee_to_epochs_operations each move to 1 — the table's own per-slot comments carry the full list
2786        validation_and_processing: DRIVE_ABCI_VALIDATION_VERSIONS_V10, // changed: contested-index cross-check + refersTo document reference validation; the ContractUserModeration gates and the batch transformer's contract_moderation_gate; a contest accepts at most max_contenders_per_contest contenders and maximum_contenders_to_consider rises to 10,000; a contender's fund doubles past 250 contenders and for every 50 more; the three shielded-fee token pool transitions gain basic structure validation and document_base_transition_state_validation 2 admits a document token cost paid from a token pool and enforces pause and the issuer's frozen-recipient policy on transparent payments; the ShieldFromAssetLock transform_into_action 1 checks its bundle against the bound preimage; identity create and identity create from addresses advanced_structure 1 refuse unpaid a failure in a field the funding signature does not cover
2787        withdrawal_constants: DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V3, // changed: prune bound for the total credits history
2788        query: DRIVE_ABCI_QUERY_VERSIONS_V2, // changed: ranked + boolean-HAVING routing gate; the v1 handler also resolves IN_TIME_RANGE from committed block time; getIdentityByNonUniquePublicKeyHash accepts request V1 (one proof)
2789        checkpoints: DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1,
2790    },
2791    dpp: DPPVersion {
2792        costs: DPP_COSTS_VERSIONS_V1,
2793        validation: DPP_VALIDATION_VERSIONS_V5, // changed: validate_config_update 2 admits the contract moderation declaration of config V2
2794        state_transition_serialization_versions: STATE_TRANSITION_SERIALIZATION_VERSIONS_V3, // changed: the indexOnly delete-by-values kind (documentIndexOnlyDelete) joins the wire; ShieldFromAssetLock moves to version 1 alone; the ContractUserModeration transition
2795        state_transition_conversion_versions: STATE_TRANSITION_CONVERSION_VERSIONS_V2,
2796        state_transition_method_versions: STATE_TRANSITION_METHOD_VERSIONS_V2, // changed: public keys in creation may carry a budget or an expiry, and a hash key's data must be 20 bytes; verify_identity_signed_signature 1: a BLS12_381 signature must verify
2797        state_transitions: STATE_TRANSITION_VERSIONS_V4,
2798        contract_versions: CONTRACT_VERSIONS_V6, // changed: token_configuration_format max_version 1 admits the shielded pool opt-in; v3 document meta-schema hosts the ranked, refersTo, requiredSince and timeRange keywords; validate_structure_interval v1 rejects a zero epoch interval; config max_version 2 (the contract moderation declaration) and validate_moderation_config; validate_document 1 rejects repeated nested text keys; serialize_value_for_key 1 keys unsigned integers in value order (except a property ending a rangeSummable index); generation 3 indexes the elements of typed arrays, on indexOnly types under the item 92 rules
2799        document_versions: DOCUMENT_VERSIONS_V4, // changed: document serialization format 3 — the contract version stamp that enables `requiredSince` properties
2800        identity_versions: IDENTITY_VERSIONS_V1,
2801        voting_versions: VOTING_VERSION_V2,
2802        token_versions: TOKEN_VERSIONS_V3, // changed: distribution_function_evaluate v1 — deterministic libm for token reward math; reward_distribution_max_cycle_moment v1: the epoch claim cap no longer wraps; distribution_function_cycle_epochs v1: evonode cycles weighted by the epochs they span
2803        asset_lock_versions: DPP_ASSET_LOCK_VERSIONS_V1,
2804        methods: DPP_METHOD_VERSIONS_V3, // changed: daily_withdrawal_limit v2 — a percentage of the total credits a day ago; credit_pool_bundle_binding Some(0) — the credit pool's outputs-only bundles bind a kind tag and their owner
2805        factory_versions: DPP_FACTORY_VERSIONS_V1,
2806    },
2807    system_data_contracts: SYSTEM_DATA_CONTRACT_VERSIONS_V3, // changed: DashPay v2 adds profile payment address fields (DIP-33); withdrawals v2 admits the terminal FAILED status
2808    // The TTL ephemeral-bytes rate (270 credits/byte to processing) rides
2809    // the shared storage table; it is dead below v14 (the `ttl` grammar
2810    // does not parse), so no table fork is needed.
2811    fee_version: FEE_VERSION3, // changed: contested document contribution reduced to 0.1 DASH; masternode vote cost reduced to 0.00002 DASH; moderation election fund of 0.5 DASH; a contender's fund doubles past 250 contenders and for every 50 more; registration surcharge for once-per-identity token distributions
2812    system_limits: SYSTEM_LIMITS_V4, // changed: daily withdrawal limit becomes 15% of the total credits a day ago + time-range overlap-factor cap (24) + time-range TTL cap (1 week) and per-write drop cap (32); max_contract_moderators, max_contract_suspension_until, max_contract_moderation_reason_length, max_contract_warnings_per_identity, max_contract_moderation_reason_documents and contract_document_restore_window_ms (a week); max_contenders_per_contest (1,000); historical CREDIT nullifier backfill pages and insert batches are each bounded to 2048 entries; max_rekey_batch_moves (10,000) for the unsigned index value key rewrite; a refersTo chooseFirst reads at most 1,000 competitors; an indexed typed array holds at most 16 elements (4 under a window), and a document writes at most 256 index entries
2813    consensus: ConsensusVersions {
2814        tenderdash_consensus_version: 1,
2815    },
2816};
2817
2818#[cfg(test)]
2819mod tests {
2820    use super::*;
2821    use crate::version::v13::PLATFORM_V13;
2822
2823    #[test]
2824    fn should_change_only_the_contested_document_and_once_per_identity_fees_at_protocol_14() {
2825        for protocol_version in 1..14 {
2826            let version = PlatformVersion::get(protocol_version).expect("known protocol version");
2827            let fund_fees = &version.fee_version.vote_resolution_fund_fees;
2828            assert_eq!(
2829                fund_fees.contested_document_vote_resolution_fund_required_amount, 20_000_000_000,
2830                "protocol {protocol_version} must preserve the 0.2 DASH contribution"
2831            );
2832            assert_eq!(
2833                version
2834                    .fee_version
2835                    .vote_resolution_fund_fees
2836                    .contested_document_single_vote_cost,
2837                10_000_000,
2838                "protocol {protocol_version} must preserve the 0.0001 DASH vote"
2839            );
2840            // No moderation election exists before 14; its amount is the contested one, so
2841            // a shipped path choosing between the two cannot change what it charges
2842            assert_eq!(
2843                fund_fees.moderation_vote_resolution_fund_required_amount,
2844                fund_fees.contested_document_vote_resolution_fund_required_amount,
2845                "protocol {protocol_version}"
2846            );
2847            assert_eq!(
2848                (
2849                    fund_fees.contested_document_contenders_before_fund_doubling,
2850                    fund_fees.contested_document_contenders_per_fund_doubling
2851                ),
2852                (0, 0),
2853                "protocol {protocol_version}: every contender paid the same fund"
2854            );
2855        }
2856
2857        let mut expected_fees = PLATFORM_V13.fee_version.clone();
2858        expected_fees
2859            .vote_resolution_fund_fees
2860            .contested_document_vote_resolution_fund_required_amount = 10_000_000_000;
2861        // A masternode vote costs a fifth of what it did: 0.00002 DASH from the contest's fund
2862        expected_fees
2863            .vote_resolution_fund_fees
2864            .contested_document_single_vote_cost = 2_000_000;
2865        // An application in a moderation election prefunds its masternode votes with 0.5 DASH
2866        expected_fees
2867            .vote_resolution_fund_fees
2868            .moderation_vote_resolution_fund_required_amount = 50_000_000_000;
2869        // The fund a contender pays doubles once the contest holds 250 contenders, and again for
2870        // every 50 more
2871        expected_fees
2872            .vote_resolution_fund_fees
2873            .contested_document_contenders_before_fund_doubling = 250;
2874        expected_fees
2875            .vote_resolution_fund_fees
2876            .contested_document_contenders_per_fund_doubling = 50;
2877        // The once-per-identity token distribution exists from protocol version 14 on, and a
2878        // token that uses it pays the surcharge of the other distribution kinds.
2879        assert_eq!(
2880            expected_fees
2881                .data_contract_registration
2882                .token_uses_once_per_identity_distribution_fee,
2883            0
2884        );
2885        expected_fees
2886            .data_contract_registration
2887            .token_uses_once_per_identity_distribution_fee = 10_000_000_000;
2888        assert_eq!(PLATFORM_V14.fee_version, expected_fees);
2889    }
2890
2891    /// The ranked / boolean-HAVING routing gate lives in v14's own query
2892    /// table, so flipping it touches only v14: a v13 node keeps running
2893    /// the v0 helper, which rejects every non-empty HAVING, so a
2894    /// mixed-version network agrees until the upgrade vote carries.
2895    ///
2896    /// v14 selects the v2 helper, which routes the ranked shape
2897    /// (`ORDER BY <agg> LIMIT n`) to `dispatch_ranked_v1` and the
2898    /// boolean-HAVING range shape (exactly one `having` clause on the
2899    /// selected aggregate) to `dispatch_having_v1`. A change that made
2900    /// v13 non-zero here would be consensus-breaking for
2901    /// already-deployed nodes, which is exactly what the v13 half of
2902    /// this assertion guards.
2903    #[test]
2904    fn ranked_having_routing_gate_is_v14_only() {
2905        assert_eq!(
2906            PLATFORM_V13
2907                .drive_abci
2908                .query
2909                .document_query_helpers
2910                .compute_aggregate_mode_and_check_limit,
2911            0
2912        );
2913        assert_eq!(
2914            PLATFORM_V14
2915                .drive_abci
2916                .query
2917                .document_query_helpers
2918                .compute_aggregate_mode_and_check_limit,
2919            2
2920        );
2921    }
2922
2923    /// Contested indexes without a Lock choice (item 23): the three method
2924    /// versions that read the resolution are selected by v14 only, so a v13
2925    /// replay keeps the shipped rules (a full poll for every contest, ties to
2926    /// the latest contender, a Lock vote accepted on any contest).
2927    #[test]
2928    fn no_locking_contests_are_selected_by_v14_only() {
2929        assert_eq!(
2930            PLATFORM_V13
2931                .drive_abci
2932                .methods
2933                .voting
2934                .check_for_ended_vote_polls,
2935            0
2936        );
2937        assert_eq!(
2938            PLATFORM_V14
2939                .drive_abci
2940                .methods
2941                .voting
2942                .check_for_ended_vote_polls,
2943            1
2944        );
2945        assert_eq!(
2946            PLATFORM_V13
2947                .drive_abci
2948                .validation_and_processing
2949                .state_transitions
2950                .masternode_vote_state_transition
2951                .state,
2952            0
2953        );
2954        assert_eq!(
2955            PLATFORM_V14
2956                .drive_abci
2957                .validation_and_processing
2958                .state_transitions
2959                .masternode_vote_state_transition
2960                .state,
2961            1
2962        );
2963        assert_eq!(
2964            PLATFORM_V13
2965                .drive
2966                .methods
2967                .document
2968                .insert_contested
2969                .add_contested_document_for_contract_operations,
2970            0
2971        );
2972        assert_eq!(
2973            PLATFORM_V14
2974                .drive
2975                .methods
2976                .document
2977                .insert_contested
2978                .add_contested_document_for_contract_operations,
2979            1
2980        );
2981    }
2982
2983    /// The ranked index keywords are gated by the meta-schema version, so v14
2984    /// must select meta-schema v3 while v13 stays on v2.
2985    #[test]
2986    fn ranked_index_keywords_are_gated_by_meta_schema_v3() {
2987        assert_eq!(
2988            PLATFORM_V13
2989                .dpp
2990                .contract_versions
2991                .document_type_versions
2992                .schema
2993                .document_type_schema,
2994            2
2995        );
2996        assert_eq!(
2997            PLATFORM_V14
2998                .dpp
2999                .contract_versions
3000                .document_type_versions
3001                .schema
3002                .document_type_schema,
3003            3
3004        );
3005    }
3006
3007    /// The ranked grammar lives in its own document-type parser generation
3008    /// rather than behind a version gate inside a shipped one, so v14 must
3009    /// select generation 3 while v13 stays on generation 2. Pinned here
3010    /// because it is the whole reason generations 0/1/2 can stay byte-identical
3011    /// to what consensus already ran: a historical block replayed at v13 is
3012    /// parsed by a generation that has never heard of the ranked keywords.
3013    /// The grove v4 cleanup gates (batch overwrite inspection + delete-tree
3014    /// actual-type cleanup) exist for the indexed trees that ranked indexes
3015    /// lay down, so v14 must select grove protocol 4 while v13 stays on 3.
3016    /// The gates are cost-neutral — they derive the old element from data the
3017    /// merk apply already loads — and the fee-constant tests pin identical
3018    /// fees on both sides of the boundary. Platform flows cannot themselves
3019    /// overwrite a ranked index (the flags are immutable on contract update
3020    /// and new indexes cannot be added to an existing document type), so the
3021    /// cleanup behavior itself is exercised by grovedb's own overwrite suites
3022    /// at the pinned revision; this test pins that v14 actually activates
3023    /// them.
3024    #[test]
3025    fn grove_v4_cleanup_gates_activate_at_v14() {
3026        assert_eq!(PLATFORM_V13.drive.grove_version.protocol_version, 3);
3027        assert_eq!(PLATFORM_V14.drive.grove_version.protocol_version, 4);
3028    }
3029
3030    #[test]
3031    fn ranked_grammar_gets_its_own_parser_generation() {
3032        assert_eq!(
3033            PLATFORM_V13
3034                .dpp
3035                .contract_versions
3036                .document_type_versions
3037                .class_method_versions
3038                .try_from_schema,
3039            2
3040        );
3041        assert_eq!(
3042            PLATFORM_V14
3043                .dpp
3044                .contract_versions
3045                .document_type_versions
3046                .class_method_versions
3047                .try_from_schema,
3048            3
3049        );
3050    }
3051
3052    /// The contested vote poll index cross-check changes accept/reject
3053    /// behavior for document create transitions, so it lives in v14's own
3054    /// validation table: a v13 node keeps running structure validation v0,
3055    /// which validates only the prefunded amount and ignores the index name.
3056    /// A change that made v13 non-zero here would retroactively reject
3057    /// transitions already in the chain.
3058    #[test]
3059    fn contested_index_cross_check_is_v14_only() {
3060        assert_eq!(
3061            PLATFORM_V13
3062                .drive_abci
3063                .validation_and_processing
3064                .state_transitions
3065                .batch_state_transition
3066                .document_create_transition_structure_validation,
3067            0
3068        );
3069        assert_eq!(
3070            PLATFORM_V14
3071                .drive_abci
3072                .validation_and_processing
3073                .state_transitions
3074                .batch_state_transition
3075                .document_create_transition_structure_validation,
3076            1
3077        );
3078        assert_eq!(
3079            PLATFORM_V13
3080                .drive_abci
3081                .validation_and_processing
3082                .state_transitions
3083                .batch_state_transition
3084                .document_create_transition_state_validation,
3085            1
3086        );
3087        assert_eq!(
3088            PLATFORM_V14
3089                .drive_abci
3090                .validation_and_processing
3091                .state_transitions
3092                .batch_state_transition
3093                .document_create_transition_state_validation,
3094            2
3095        );
3096        assert_eq!(
3097            PLATFORM_V13
3098                .drive
3099                .methods
3100                .document
3101                .insert_contested
3102                .add_contested_vote_subtree_for_non_identities_operations,
3103            0
3104        );
3105        assert_eq!(
3106            PLATFORM_V14
3107                .drive
3108                .methods
3109                .document
3110                .insert_contested
3111                .add_contested_vote_subtree_for_non_identities_operations,
3112            1
3113        );
3114    }
3115}