Skip to main content

State model

Applies to both RGB lines

Both lines split contract state into an owned part bound to Bitcoin outputs and a public part, but they encode it very differently. See Two RGB lines.

An RGB contract's state is built up by operations: genesis, then the operations that follow it. Each operation can create two kinds of state:

  • Owned state is assigned to a single-use seal, a Bitcoin output. Whoever can spend the output can move the state, by spending the output in a transaction that commits to a new operation. Balances, NFTs and issuance rights are owned state. See Owned state.
  • Global state is data that the operation publishes to the contract and that nobody owns: ticker, name, issued supply, terms. It is append-only. See Global state.

Both are client-side data. Nothing but a 32-byte commitment reaches the blockchain, and each holder sees only the history they received.

The two encodings​

State is typed by the schema. Each owned or global state type has a number and a declared type (rgb-consensus 0.11.1 src/schema/state.rs):

KindDeclared asHolds
Owned, declarativeOwnedStateSchema::DeclarativeNothing: a right with no value (e.g. the IFA linkRight)
Owned, fungibleOwnedStateSchema::Fungible(FungibleType::Unsigned64Bit)A u64 amount; it's the only fungible type
Owned, structuredOwnedStateSchema::Structured(SemId)A strict-typed value, e.g. an NFT allocation
GlobalGlobalStateSchema { sem_id, max_items: u24 }Up to max_items strict-typed values of that type
MetadataMetaDetails { sem_id, .. }Per-operation strict-typed data that isn't kept as state

A transition carries all three (src/operation/operations.rs):

pub struct Transition {
pub ffv: Ffv,
pub contract_id: ContractId,
pub nonce: u64,
pub transition_type: TransitionType,
pub metadata: Metadata,
pub globals: GlobalState,
pub inputs: Inputs, // NonEmptyOrdSet<Opout, U16>: at least one spent seal
pub assignments: Assignments<GraphSeal>, // new owned state
pub signature: Option<Signature>,
}

Here is the real state of a NIA (non-inflatable asset) contract issued offline with rgb-cmd 0.11.1:

rgb -n regtest state -a rgb:Ca0d5l5K-Cr4Wm6I-owUkn6t-2NHrgjk-R1KRreF-tVBhAR0
Global:
spec := ticker "DEMO", name "Demo asset", details ~, precision centi
terms := text "Demo terms", media ~
issuedSupply := 100000000

Owned:
State Seal Witness
assetOwner:
100000000 b449f7eaa3f98c145b27ad0eeb7b5679ceb567faef7a52479bc995792b65f804:1 ~ -- third-party

Removed in both lines​

  • State extensions and valencies (public "anyone can claim" operations in RGB v0.10) exist in neither line. Every Line B transition must spend at least one owned input.
  • Confidential amounts. Pedersen commitments and bulletproofs are gone. Amounts are explicit to everyone who receives the history; privacy comes from client-side validation and blinded seals.
  • Zero-knowledge proofs of state or history are not implemented in either line. Line A's zk-AluVM is designed to make them possible later.

Where contract rules live​

v0.11 (rgb-cmd)v0.12 (rgb-wallet)
RulesA schema (NIA, IFA, CFA, UDA, PFA in rgb-schemas 0.11.1), written in Rust, plus optional AluVM scriptsA codex (verifier scripts in zk-AluVM) plus an API that gives names and types to the field elements
Typed meaningIn consensus, through SemIdIn the API layer, outside consensus
SeeSchemasWhat's new in v0.12

Both lines describe state values with strict types.