Storage migration on Sigil is an upgrade-safe physical migration. It must not change chain IDs, address derivation, account balances, staking amounts, validator identities, transaction semantics, canonical serialisation, or canonical state roots.

Inventory

Production AkashaKV stores already exist for compute, NFT, governance, Tower finality, labor, usernames, GAL, DEX, Nova, contracts, and recovery. The remaining RocksDB surfaces are limited to the legacy block/archive store and the sigil-blockstore-repair repair/import binary. RocksDB is not a production runtime backend. It may be opened only by binaries built with the legacy-rocksdb-import feature, and only as a legacy read source for migration or repair.

Old layout

Legacy nodes used:
  • data/blocks/: RocksDB block/archive store, including height and hash indexes.
  • Domain stores (compute/, nft/, tower/, labor/, username/, gal/, dex/, nova/, contracts/, recovery/): already AkashaKV-backed in current Sigil.
  • Snapshot payloads could contain data/blocks/ on old archives.

New layout

Fresh and migrated nodes use:
  • data/akashakv/: production block, transaction, receipt, archive query, and migration metadata store.
  • data/weft/: local off-chain Weft artifact store containing canonical manifests, chunks, and availability advertisements.
  • Existing domain AkashaKV directories remain authoritative for compute, NFT, governance, Tower, labor, usernames, GAL, DEX, Nova, contracts, and recovery.
  • Snapshot payloads must contain data/akashakv/ and verify the restored block at the manifest height.
The unified AkashaKV storage keyspaces:
PrefixContents
blocks/by-heightCanonical block bodies indexed by height.
blocks/by-hashBlock hash → height lookup.
tx/by-hashTransaction envelope storage.
tx/by-height-indexPer-block transaction index.
receipts/by-txPer-transaction receipts.
receipts/by-blockPer-block receipts roll-up.
state/*Per-partition state (account, nonce, validator, system-contract, dex, labor, compute, nova, username, gal).
finality/towerTower epoch lock state.
governance/proposalGovernance proposals and votes.
metadata/migrationMigration manifest and provenance.
All variable-length key components are length-prefixed and include a declared component count. Exact key A cannot alias key A+B.

Startup migration

On node boot:
  1. Acquire data/.akashakv-migration.lock.
  2. If data/akashakv/ exists, validate the migration manifest before serving.
  3. If incomplete data/akashakv.staging/ exists, delete it and restart migration.
  4. If legacy data/blocks/ looks like RocksDB and no final AkashaKV directory exists:
    • Production binaries fail closed and instruct the operator to use a legacy-rocksdb-import build.
    • Importer builds open RocksDB read-only, stream records in height order, write AkashaKV staging, flush, verify every copied block by height and hash index from the AkashaKV target, write migration-manifest.json, and atomically rename staging to data/akashakv/.
  5. Fresh nodes create data/akashakv/ directly and never create data/blocks/.
The manifest records from_backend, to_backend, source height/hash/root, migrated root, AkashaKV revision, timestamps, and migration tool version. The legacy importer migrates the production block/archive store only. It verifies block bytes, hash indexes, latest height, and the latest block header state root after the AkashaKV write. If an operator has a custom RocksDB state table outside data/blocks/, that table requires an explicit importer before upgrade.

Rollback and crash behaviour

  • Legacy RocksDB data is never mutated or deleted by migration.
  • If verification fails, startup fails and only incomplete AkashaKV staging is removed.
  • If staging exists without a completed manifest, staging is deleted and migration restarts.
  • If a completed manifest exists but the final AkashaKV directory is missing, startup fails closed.
  • If a manifest source root differs from migrated root, startup fails closed.
  • Validators must not sign until storage verification completes.

Weave model

Weave is Sigil’s off-chain artifact and evidence layer; it is not consensus state. Sigil stores only commitments:
  • Weave CID / content id.
  • BLAKE3 hash.
  • Byte length.
  • Media type.
  • Schema.
  • Producer DID.
  • Signature.
  • Created height.
This applies to labor evidence blobs, compute artifacts, agent traces, contract-served frontend bundles, Nova assets, NFT metadata, governance evidence packs, model manifests, audit archives, and replay bundles. Block execution must not depend on retrieving Weave bytes. Validators may validate a committed byte sequence or root when the bytes are part of deterministic transaction validation, but Weave availability itself is not consensus-critical.

Weft for large artifacts

Weft is the Weave large-blob model for sharded artifact distribution. Sigil commits to canonical Weft manifest bytes with ArtifactCommitment and can attach a typed WeftRootCommitment containing the Weft Merkle root, chunk size, chunk count, payload length, and manifest CID. The production node wires an executable local Weft store at data/weft/:
  • manifests/<root>.json
  • chunks/<chunk-id>.bin
  • advertisements/<root>.json
Operator RPCs: sigil_weftPublish, sigil_weftPublishFile, sigil_weftFetch, sigil_weftFetchFile, sigil_weftStatus. Each verifies BLAKE3 hash, byte length, and Merkle root before returning bytes. A DHT-compatible adapter ships under the dht feature with record keys:
  • /weft/v1/manifest/<root>
  • /weft/v1/chunk/<chunk-id>
  • /weft/v1/availability/<root>
The default Sigil path uses the local store unless an operator explicitly links and configures a DHT-backed service.

Operator checks

curl -s http://127.0.0.1:26657/rpc \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"sigil_getStorageStatus","params":{}}' | jq
Verify an artifact commitment:
curl -s http://127.0.0.1:26657/rpc \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"sigil_verifyArtifact","params":{"commitment":{"cid":"weave:blake3:<hex>","blake3":"<hex>","byte_len":12,"media_type":"application/json","schema":"sigil.test.v1","producer_did":"did:oas:test:producer","signature":"","created_height":1},"bytes_hex":"7b226f6b223a747275657d"}}' | jq

Pre-upgrade verification

Run these tests before upgrading canary or mainnet validators:
cargo test -p sigil-node storage_migration
cargo test -p sigil-node akashakv_backend
cargo test -p sigil-node snapshot_restore
cargo test -p sigil-node rpc_conformance --features contracts,wasm,compute,nova
cargo test -p sigil-node executor_labor --lib
cargo test -p sigil-node --test dex_execution
cargo test -p sigil-node --test nova_durable
python3 scripts/validate-launch-readiness.py akashakv-pin
python3 scripts/validate-launch-readiness.py pre-genesis-feature-readiness
python3 scripts/validate-launch-readiness.py storage-backend-readiness
python3 scripts/validate-launch-readiness.py weft-readiness

Upgrade procedure

  1. Back up the full data directory and current binary.
  2. Deploy a production binary without legacy-rocksdb-import to fresh AkashaKV nodes.
  3. For upgraded legacy nodes, run the importer build once (or deploy an importer image), let startup complete migration, and verify sigil_getStorageStatus.
  4. Replace the importer binary with the normal production binary.
  5. Confirm backend = akashakv, migration_status = verified, and the latest verified height/root match the finalised block header.
  6. Only then allow validators to sign.
Mainnet, canary, and testnet do not need a genesis restart for a storage-only migration. A genesis restart is only required if the deployment also changes genesis supply, chain id, initial validator set, or other consensus-visible material.