Skip to content

Protocol Versioning

NOOSChain block execution is protocol-versioned. Each block stores a protocol_version, and that version selects the deterministic execution rules used for that block.

The core idea is simple:

A historical block must always execute with the rules that were active for that block, not whatever rules are newest in the current binary.

For implementation details and upgrade checklists, see Nooschain Developer Protocol Versioning.

Why Protocol Versioning Exists

NOOSChain is replayable. A node should be able to take historical blocks, execute them again, and reproduce the same state roots and block commitments.

That only works if historical execution semantics are stable. If old blocks were reinterpreted under newer code, the same transaction could succeed instead of fail, fail instead of succeed, consume a nonce differently, resolve a signer differently, or produce different state changes.

Protocol versioning prevents that class of replay divergence. Old blocks keep their recorded protocol version forever.

What A Protocol Version Controls

A protocol version controls deterministic block execution semantics, including:

  • Transaction handlers
  • Signer and actor resolution
  • Nonce behavior
  • Permission checks
  • Bucket policy behavior
  • Bucket-key and record execution behavior
  • Smart-contract execution requirements used during block execution
  • Deterministic success and failure behavior

These rules are part of the meaning of a block. State roots and block hashes are only meaningful relative to the protocol version used to execute the block.

What It Does Not Control

Protocol versioning does not choose:

  • Consensus backend
  • Node role
  • Operator authentication
  • Admin GUI behavior
  • Local observability output
  • Encrypted payload custody policy by itself
  • State-root engine version by itself
  • External sidecar wire protocol version

Those systems may interact with protocol versions, but they are separate concepts.

How Versions Are Chosen

New blocks use the active protocol version for their height. Historical blocks use the protocol_version already stored on the block.

The current registry supports protocol 1, and latest currently points to v1. Future upgrades should add a new protocol definition and activate it at a block height through protocol_upgrades.

At a high level:

  1. A node proposes or syncs a block.
  2. The block records its protocol_version.
  3. Block execution dispatches through the matching protocol definition.
  4. Replay later uses the historical block's recorded version.
  5. Unsupported versions fail closed.

computeBlockHash() includes protocol_version, so a block commitment describes both the ordered transactions and the execution semantics.

Protocol Version Vs State-Root Engine Version

protocol_version controls transaction execution semantics: which handlers run, how actors are resolved, how permissions are checked, and which deterministic state changes are produced.

state_root_engine_version controls how materialized state leaves are folded into the block state root.

They can evolve separately. A protocol upgrade may not require a state-root engine migration, and a state-root engine migration may not require changing transaction semantics. Some larger upgrades may coordinate both.

For state-root activation details, see State-Root Activation Operations and State-Root Engine Migration Internals.

Protocol Version Vs Smart-Contract Runtime Version

The chain protocol version is the block execution version.

Smart-contract runtime activation, runtime rollout policies, package provenance, and sidecar compatibility are represented separately. They may be pinned to a chain protocol version when deterministic execution depends on runtime behavior, but they are not the same value as block.protocol_version.

Likewise, a sidecar protocol version describes the external runtime or state-root sidecar handshake. Do not treat sidecar protocol versions as chain protocol versions.

Sync, Replay, And Snapshots

Sync validates remote block protocol versions before trusting a peer's block data. If the node does not support a remote block's version, sync fails closed.

Replay verification reads canonical block protocol_version and dispatches through that historical protocol. Unsupported versions are replay errors.

Snapshots include protocol version metadata so restored or verified state can be tied back to the execution semantics that produced it.

Protocol-version mismatches can also participate in conflict handling during sync or replay validation.

Operator Inspection

Check protocol registry wiring and persisted chain protocol metadata:

powershell
npm run verify:protocol

Inspect chain/protocol observability:

powershell
npm run noos -- observability chain
npm run noos -- node overview

Operator-facing protocol info includes the latest version supported by the binary, the active version for the next block, and configured protocol-upgrade rows.

Development Chain Warning

Existing local development chains created before block protocol versions may have historical block hashes or failed transactions that do not replay under current code.

Do not add compatibility hacks that inspect old failures or reproduce old bugs dynamically. For development, reset or reinitialize the dev database when you need a clean protocol-versioned chain.

Audience-first NOOSChain documentation.