Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions frame/validator-set/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ with `InsufficientBond`. Callers that pre-funded 1 001 ORB to register can stop.
- No migration ships with this change: `ValidatorBondOf` was verified empty on
testnet (0 entries, empty pending queue) before removing it, so there are no
reserves left stranded. A chain that *had* live bonds would need one.
- `spec_version` moves 7 → 8 at release, since the removed Config constant and
storage item change the metadata. `transaction_version` stays at 2:
`register_validator` keeps its call index and its empty signature.

### Verification
50 pallet tests; runtime, `try-runtime` and `runtime-benchmarks` all compile. A
Expand Down
60 changes: 59 additions & 1 deletion template/runtime/RUNTIME_VERSIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,67 @@ to `spec_version` / `transaction_version` must add a row here in the same PR.
The genesis reset (`69d1b837`) set `spec_version` back to 1 and
`transaction_version` to 1 for the public testnet launch.

### spec 8 — tx 2 — 2026-08-08

Bundles the whole audit-remediation batch plus the config/feature work that
preceded it. `transaction_version` stays at 2 — no call index or dispatch
signature changed; the metadata moves, so `spec_version` does.

**Features / config**

- **validator-set 0.2.0 — registration bond removed** (#121). The 1 000 ORB
`register_validator` bond is gone: `ValidatorBond` and `Currency` Config
items, the `ValidatorBondOf` map, both bond events and `InsufficientBond`.
Governance approval already gated the active set, so the bond only added a
funding step for hand-onboarded operators. No migration — `ValidatorBondOf`
was queried on testnet first and found empty (0 entries, empty queue, 3
validators all sudo-added), so nothing stays reserved.
- **shielded-pool — minimum shield amount removed** (#121). `MinShieldAmount`
and `AmountTooSmall` are gone; any non-zero amount is shieldable, zero still
refused via `InvalidAmount`. This shifts the numeric index of every `Error`
variant declared after `AmountTooSmall` — clients matching on error *names*
are unaffected; anything decoding by index needs fresh metadata.
- **shielded-pool — sealed-tree pruning** (#122). New Config
`SealedTreePrunedBelowLevel` (production 10) and an `on_idle` sweep that
reclaims ~99.8% of a sealed tree's `MerkleNodes` (1,048,574 → 2,046 per
tree); `get_merkle_path` recomputes pruned siblings from `MerkleLeaves` on
demand. Benchmarked at 12.68 µs/node, so the 512-node per-block ceiling
costs ~6.5 ms. No migration — nothing prunes until a tree seals at 2^20
leaves, and the sweep reaches already-sealed trees on its own.
- **runtime config split into modules** (#121). `template/runtime/src/configs/`.
No consensus effect on its own.
- **legacy `shieldedPool_*` RPC server retired** (#119). Node-side only.

**Security (audit remediation)**

- **zk-verifier — deserialization bounds + circuit-id de-aliasing** (#123).
`MAX_VK_BYTES` / `MAX_PROOF_BYTES` cap the length prefix before
`Vec::with_capacity`; circuit ids no longer alias to the same `u8`, and
genesis asserts VK arity.
- **shielded-pool — zero-hash ladder and tree-depth shift bounded** (#124).
`zero_hash_at_level` is iterative (a recursive call could exhaust the 1 MB
Wasm stack and abort the process); a const assertion pins tree `DEPTH < 32`
so `capacity()` cannot shift into a `u32`.
- **shielded-pool 0.16.0 — non-canonical and zero commitments/nullifiers
refused** (#125). Both are raw-byte storage keys while byte→field reduces
mod the BN254 `p`, so `n` and `n + p` were two keys for one element — a
double-spend vector. `is_canonical` is now checked on every write path
(`shield`, `private_transfer`, `unshield`); zero commitments refused
separately since zero is canonical but indistinguishable from an empty tree
slot. Shifts `Error` indices (breaking for index-decoders, not name-matchers).
- **precompile 0.5.0 — ABI decoder truncation/overflow fixed** (#126).
Offsets/lengths were narrowed with `low_u32()`; a wrapping length built an
inverted slice range and panicked the runtime (`wasm unreachable`, reachable
from an unsigned gas-free `eth_call`). Words are now rejected when they don't
fit their type, and all offset/length arithmetic is checked. No ABI change.
- **shielded-pool 0.17.0 — duplicate nullifier in `private_transfer` refused**
(#127). Two equal non-dummy nullifiers spent one input twice (both cleared
the used-set check, the second `mark_as_used` was idempotent). `execute` now
rejects a duplicate with `NullifierAlreadyUsed`. Defense in depth.

| spec | tx | Date | Commit | Change |
|------|----|------|--------|--------|
| 7 | 2 | 2026-08-06 | — | Several pallet changes shipping in one upgrade (7 was never deployed, so they collapse into a single bump). **validator-set:** the 1 000 ORB `register_validator` bond is removed — `ValidatorBond` and `Currency` Config items, the `ValidatorBondOf` map, both bond events and `InsufficientBond` are gone. Governance approval already gated the active set; the bond only added a funding step for hand-onboarded testnet operators. No migration: `ValidatorBondOf` was verified empty on testnet before removal. **shielded-pool 0.15.0:** `MinShieldAmount` and `AmountTooSmall` removed — any non-zero amount is shieldable, zero still rejected via `InvalidAmount`. This shifts the numeric index of every `Error` variant after `AmountTooSmall`; clients matching on error *names* are unaffected. Also adds `SealedTreePrunedBelowLevel` and an `on_idle` sweep that reclaims ~99.8% of a sealed tree's `MerkleNodes`, with `get_merkle_path` recomputing pruned siblings on demand. **shielded-pool 0.14.0:** historic-root window re-anchored from insert counts to block numbers. New Config `RootRetentionBlocks` (300 blocks); `MaxHistoricRoots` (raised to 16384) becomes a queue-length cap rather than the window. `HistoricPoseidonRoots` now stores an expiry block instead of a bool; `HistoricRootsOrder` replaced by the slot-indexed `HistoricRootsQueue` + `Head`/`Tail`. `STORAGE_VERSION` 2 → 3 with `MigrateToV3` in the tuple. Weights re-benchmarked against the v3 layout. The amount-overflow pool rejection moves from `Custom(2)` to `Custom(4)`, which had two meanings. **Applied migrations removed (`72ff7b88`):** the v1/v2 modules are gone from shielded-pool and zk-verifier 0.11.0 — testnet was already past both, so they were no-ops, and `MigrateToV1` rebuilt the whole Merkle tree in one block. `spec_version` moves because storage layout and `on_runtime_upgrade` both change; `transaction_version` stays — no call signature changed. |
| 7 | 2 | 2026-08-05 | — | Two pallet changes shipping in one upgrade. **shielded-pool 0.14.0:** historic-root window re-anchored from insert counts to block numbers. New Config `RootRetentionBlocks` (300 blocks); `MaxHistoricRoots` (raised to 16384) becomes a queue-length cap rather than the window. `HistoricPoseidonRoots` now stores an expiry block instead of a bool; `HistoricRootsOrder` replaced by the slot-indexed `HistoricRootsQueue` + `Head`/`Tail`. `STORAGE_VERSION` 2 → 3 with `MigrateToV3` in the tuple. Weights re-benchmarked against the v3 layout. The amount-overflow pool rejection moves from `Custom(2)` to `Custom(4)`, which had two meanings. **Applied migrations removed (`72ff7b88`):** the v1/v2 modules are gone from shielded-pool and zk-verifier 0.11.0 — testnet was already past both, so they were no-ops, and `MigrateToV1` rebuilt the whole Merkle tree in one block. `spec_version` moves because storage layout and `on_runtime_upgrade` both change; `transaction_version` stays — no call signature changed. |
| 6 | 2 | 2026-08-03 | — | `pallet-account-mapping` and its precompile (index 14, address 0x0800) removed, along with the `private_link` circuit (id 5) and its verification key. Index 14 is retired and must not be reassigned. zk-verifier 0.10.0 gains `purge_circuit` (call index 7, Root) plus `STORAGE_VERSION` 1 and `MigrateToV1`, which drops the stranded circuit-5 key that no extrinsic could reach. `transaction_version` moves because the new call index changes extrinsic encoding. |
| 5 | 1 | 2026-07-30 | — | shielded-pool 0.12.0: multi-tree forest. Full trees seal (`TreeSealed`, permanent `SealedTreeRoots` anchors) and inserts roll over to a fresh tree — the 2^20-note network ceiling is gone. New Config `MaxLeavesPerTree` (2^20), `STORAGE_VERSION` 2 (`MigrateToV2`, version-only), runtime API v2 (`get_forest_info`, `get_root_for_leaf`). No circuit/extrinsic/ABI changes. |
| 4 | 1 | 2026-07-30 | `63caafca` | shielded-pool 0.11.0: `MerkleNodes` storage (internal nodes written on every insert) + `MigrateToV1` migration (backfill, `STORAGE_VERSION` 1). O(depth) Merkle proofs. Weights re-benchmarked. The upgrade block runs the one-shot migration (~3s at ~90k leaves). |
Expand Down
2 changes: 1 addition & 1 deletion template/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: Cow::Borrowed("orbinum"),
impl_name: Cow::Borrowed("orbinum"),
authoring_version: 1,
spec_version: 7,
spec_version: 8,
impl_version: 1,
apis: RUNTIME_API_VERSIONS,
transaction_version: 2,
Expand Down
Loading