Operations

Operations

State chain blocks contain an array of operations that modify the in-memory KV store. There are two operation types: set and delete.

Op struct

type Op struct {
    Action string          `json:"action"` // "set" or "delete"
    Key    string          `json:"key"`
    Value  json.RawMessage `json:"value,omitempty"`
}

Field

Description

Action

Either "set" to create/update a key or "delete" to remove it

Key

The key to operate on (see key format below)

Value

JSON value for set operations; omitted for delete

Actions

Set

Creates or updates a key with a JSON value:

{
  "action": "set",
  "key": "sys.dao_keyset",
  "value": {"keys": ["aabb..."], "threshold": 2}
}

Delete

Removes a key from the KV store:

{
  "action": "delete",
  "key": "config.deprecated_param"
}

[!WARNING] System keys cannot be deleted Keys with the sys. prefix cannot be deleted. A delete operation targeting a sys.* key will be rejected during validation.

Key format

Keys must match the regex ^[a-z0-9_.-]+$:

  • Lowercase letters, digits, underscores, dots, and hyphens only.
  • Minimum length: 1 character.
  • Maximum length: 128 characters (MaxKeyLength).

Value constraints

Constraint

Limit

Must be valid JSON

Checked via json.Valid()

Maximum size

65,536 bytes (64 KB)

Required for set

Cannot be empty

System keys

Keys prefixed with sys. have special validation rules:

Key

Value type

Description

sys.dao_keyset

DAOKeyset

The DAO signer quorum configuration

sys.timekeepers

TimekeeperConfig

Trusted timekeeper keys and threshold

sys.minter

{keys: [...]}

Accounts authorized to mint XUSD

sys.oracle

OracleConfig

Oracle keys, threshold, and the key prefix they may write

sys.phase

uint8 (1 or 2)

Tokenomics protocol phase

sys.tokenomics

TokenomicsConfig

Governance-tunable R-curve and payout-cap parameters

sys.network_id

string

Network identifier, pinned at genesis

sys.dao_keyset validation

When setting sys.dao_keyset, the value must be a valid DAOKeyset:

  • At least one key.
  • No duplicate keys.
  • Each key must be exactly 64 hex characters (32-byte ed25519 public key).
  • Each key must be valid hex (not just 64 characters).
  • Threshold must be >= MinDAOThreshold (2).
  • Threshold must be <= number of keys.

The DAOKeyset() accessor also enforces MinDAOThreshold=2 at read time, so even a keyset written by an older version is validated on access.

sys.timekeepers validation

When setting sys.timekeepers, the value must be a valid timekeeper config:

  • At least one key.
  • Each key must be exactly 64 hex characters.
  • Threshold must be between 1 and the number of keys (inclusive).

[!NOTE] Why timekeepers have a threshold Unlike the DAO keyset (where threshold is a multisig authorization requirement), the timekeeper threshold controls how many independent timestamp attestations are needed on lease_accept and lease_settle blocks. Timekeepers are individually trusted nodes — any one of them can independently sign a valid timestamp. The threshold is a defense-in-depth measure: requiring a majority and taking the median timestamp prevents a single compromised timekeeper from biasing the canonical time used to compute XE emission. See attestations for full details.

sys.minter validation

sys.minter names the accounts authorized to mint XUSD (the faucet today; a bridge later). The value mirrors the shape of core.MinterConfig:

  • At least one key.
  • Each key must be exactly 64 hex characters and valid hex.
  • No duplicate keys.

There is no threshold on sys.minter itself: any account whose public key is listed may issue mint blocks on its own chain. If that account is a multisig account, its own keyset threshold still applies through the normal multisig path.

sys.oracle validation

  • At least one key.
  • Each key must be exactly 64 hex characters and valid hex.
  • No duplicate keys.
  • Threshold must be between 1 and the number of keys (inclusive).
  • allowed_prefix must not be empty.

See oracle-scoped blocks for how the prefix changes which keyset signs a block.

sys.phase validation

sys.phase is a bare JSON number and must be 1 or 2. It is additionally one-directional: a block that lowers the phase (2 → 1) is rejected by the transition check. A first write is unconstrained beyond the value check.

sys.tokenomics validation

sys.tokenomics is decoded with unknown fields disallowed and then checked for cross-field consistency, including:

  • r_floor > 0 and r_init > r_floor; v_half > 0.
  • Price tiers strictly increasing: price_tier_1 < price_tier_2 < price_tier_3.
  • r_price_floor_tier_1 >= r_price_floor_tier_2 >= r_floor.
  • r_collusion_factor_milli strictly inside (0, 1000).
  • hermite_fdv_min_usd > 0 and < hermite_fdv_max_usd; hermite_ceiling_milli > hermite_floor_milli > 0.
  • Every ×1000-scaled ratio within the sanity range [1, 100000].

See compute economics for what these parameters drive.

KV Store

The KVStore is an in-memory key-value store that holds the accumulated state of all applied operations.

type KVStore struct {
    data map[string]json.RawMessage
}

Methods

Method

Description

ApplyOps(ops []Op)

Apply a batch of set/delete operations

Get(key) (json.RawMessage, bool)

Retrieve a value by key

GetByPrefix(prefix) map[string]json.RawMessage

Retrieve all keys matching a prefix

GetAll() map[string]json.RawMessage

Dump the entire store

DAOKeyset() (*DAOKeyset, error)

Parse and return the current DAO keyset from sys.dao_keyset

OracleConfig() (*OracleConfig, error)

Parse sys.oracle; (nil, nil) when the oracle is not configured

Phase() (uint8, error)

Parse sys.phase; returns 1 when the key is absent

Tokenomics() (*TokenomicsConfig, error)

Parse sys.tokenomics; (nil, nil) when unset, so callers fall back to compile-time defaults

NetworkID() string

Read sys.network_id; empty string when unset

ApplyOps

Operations are applied in order. A set overwrites any existing value; a delete removes the key. There is no transaction rollback -- if a block is accepted, all its ops are applied.

func (kv *KVStore) ApplyOps(ops []Op) {
    for _, op := range ops {
        switch op.Action {
        case ActionSet:
            kv.data[op.Key] = json.RawMessage(append([]byte(nil), op.Value...))
        case ActionDelete:
            delete(kv.data, op.Key)
        }
    }
}

Block hash computation

The block hash is computed over the block's canonical binary encoding -- index, previous hash, every op in order, and the timestamp -- and excludes the signatures. This is critical because it allows DAO members to sign the same hash independently -- they agree on what the block does, not on who else has signed it.

[!INFO] Signature collection Because the hash excludes signatures, a coordinator can compute the hash, distribute it to DAO members for signing, collect the signatures, and assemble the final block. Members do not need to be online simultaneously.

Common use cases

DAO keyset rotation

Adding a new signer and increasing the threshold:

{
  "ops": [
    {
      "action": "set",
      "key": "sys.dao_keyset",
      "value": {
        "keys": [
          "aabb11...existing1",
          "ccdd22...existing2",
          "eeff33...new_member"
        ],
        "threshold": 2
      }
    }
  ]
}

Timekeeper configuration

Setting up trusted timekeepers for compute lease attestations:

{
  "ops": [
    {
      "action": "set",
      "key": "sys.timekeepers",
      "value": {
        "keys": [
          "1122...timekeeper_a",
          "3344...timekeeper_b",
          "5566...timekeeper_c"
        ],
        "threshold": 2
      }
    }
  ]
}

Arbitrary configuration

Beyond the reserved sys.* namespace, the KV store can hold any governance-related data:

{
  "ops": [
    {"action": "set", "key": "config.announcement", "value": "maintenance window 2026-08-10"},
    {"action": "delete", "key": "config.deprecated_flag"}
  ]
}

[!NOTE] Emission parameters are not free-form config Emission is driven by sys.tokenomics (the R-curve and payout-cap parameter set) and by the per-epoch values the oracle publishes -- not by ad-hoc config.* keys. Both are schema-validated on write.

Op validation

Every operation in a block is validated before the block is accepted:

Check

Rule

Key format

Must match ^[a-z0-9_.-]+$

Key length

1 to 128 characters

Set value present

set ops must have a non-empty value

Set value size

Value must be <= 65,536 bytes

Set value JSON

Value must be valid JSON

System key rules

sys.* keys have additional schema validation

Delete system keys

sys.* keys cannot be deleted

Known action

action must be exactly set or delete

Transition rules

Value-dependent checks against existing state (e.g. sys.phase may only move forwards)

Block has ops

Block must contain at least one operation