Skip to main content

Global State

Applies to both RGB lines

Both lines have append-only global state; the encoding differs. See Two RGB lines.

Global state is contract data that is not bound to any Bitcoin output: an asset's ticker, name, precision, issued supply, legal terms, or a record of each later issuance. It is part of the contract, but nobody "owns" or spends it.

Three things are often misunderstood:

  • It is not public. Like everything in RGB, it is client-side data. It is visible only to people who receive a consignment containing it. For example, everyone who receives the asset also receives its genesis, and with it the ticker and supply. Nobody else does.
  • It is append-only. An operation can add new global values. It can never change or delete existing ones. There are no global variables to update.
  • There is no voting or consensus behind it. An operation that adds global state is valid if it follows the contract's rules, which are the schema (B) or the codex (A). In Line B it must also spend at least one owned input. Its ordering comes from the Bitcoin transactions that anchor it. Two parties can't disagree about it, because the seals they spend are single-use.

Typical pattern: the right to change something is an owned state (for example IFA's inflation allowance in Line B). Using that right emits new global data (the newly issued amount).

Each global state type in the schema is declared as (rgb-consensus 0.11.1 src/schema/state.rs):

pub struct GlobalStateSchema {
pub sem_id: SemId, // strict type of each value
pub max_items: u24, // how many values one operation may add
}

GlobalStateSchema::once(sem_id) allows a single value. Genesis and transitions carry new values in their globals field.

For example, the NIA schema (rgb-schemas 0.11.1 src/nia.rs) declares three global types, each once: spec (RGBContract.AssetSpec), terms (RGBContract.ContractTerms) and issuedSupply (RGBContract.Amount). This is what rgb state shows for them:

Global:
spec := ticker "DEMO", name "Demo asset", details ~, precision centi
terms := text "Demo terms", media ~
issuedSupply := 100000000

AluVM scripts can read global state: ldg reads the current operation's values and ldc reads the contract's accumulated values (rgb-consensus src/vm/op_contract.rs).

What global state can't do​

  • Read the clock or the chain. Validation scripts in both lines are deterministic and have no access to time, block height or network data.
  • Be updated in place. To "change" a value, a contract appends a new one, and the contract's API decides which value counts (for example, the latest).
  • Fork. Every recipient who validates the same history gets the same global state.

Privacy trade-off​

Global data reaches every future holder of the contract's state. Don't put anything in it that later recipients shouldn't see. Per-transfer data that doesn't need to be kept belongs elsewhere: in Line B's operation metadata, or in an owned state value.