1 Data Structures
Claude edited this page 2026-02-20 15:12:17 +00:00

Data Structures

Field-level documentation of the core blockchain data structures. All structures must be serialised in a consensus-critical, bit-identical manner matching the C++ implementation.

Block Header

The block header is the fixed-size preamble of every block.

type BlockHeader struct {
    MajorVersion uint8      // Block format version (0, 1, 2, 3)
    MinorVersion uint64     // Minor version (varint)
    Timestamp    uint64     // Unix timestamp (varint)
    PrevID       Hash       // Hash of the previous block (32 bytes)
    Nonce        uint64     // PoW nonce
    Flags        uint8      // Block flags (PoW=0, PoS=1)
}
Field Type Serialisation Description
major_version uint8 Fixed 1 byte Block format version. 0=initial, 1=HF1, 2=HF3, 3=HF4+
nonce uint64 Fixed 8 bytes Proof-of-Work nonce. Serialised immediately after major_version
prev_id [32]byte Fixed 32 bytes Keccak-256 hash of the previous block
minor_version uint64 Varint Minor version, typically 0
timestamp uint64 Varint Block timestamp in seconds since Unix epoch
flags uint8 Fixed 1 byte Bit 0: PoS flag (0=PoW, 1=PoS)

Note: The serialisation order differs from the struct field order. The canonical wire format is: major_version, nonce, prev_id, minor_version, timestamp, flags.

Block

A block extends the header with a coinbase transaction and a list of transaction hashes.

type Block struct {
    BlockHeader
    MinerTx  Transaction  // Coinbase transaction (block reward + fees)
    TxHashes []Hash       // Hashes of included transactions
}
Field Type Description
miner_tx Transaction The coinbase transaction that pays the block reward
tx_hashes []Hash Ordered list of transaction hashes included in this block

The block hash is computed by hashing the concatenation of: the block header hash, the miner transaction hash, and the Merkle tree root of tx_hashes.

Transaction

Transactions transfer value between addresses. The format has evolved across hardforks.

Transaction Prefix

type TransactionPrefix struct {
    Version    uint64     // Transaction version (varint): 0, 1, 2, or 3
    HardforkID uint8      // Hardfork identifier (only for version >= 3)
    Vin        []TxInput  // Inputs (variant type)
    Extra      []ExtraV   // Extra data (variant type)
    Vout       []TxOutput // Outputs (variant type)
}

Full Transaction

type Transaction struct {
    TransactionPrefix
    Attachment  []AttachmentV   // Service attachments
    Signatures  []SignatureV    // Per-input signatures (variant: NLSAG, ZC_sig, zarcanum_sig)
    Proofs      []ProofV        // Global proofs (range proofs, balance proofs, surjection proofs)
}
Field Type Serialisation Description
version uint64 Varint 0=initial, 1=pre-HF4, 2=post-HF4, 3=post-HF5
hardfork_id uint8 Fixed (v3+ only) Identifies the hardfork rules this tx follows
vin []txin_v Variant array Transaction inputs
extra []extra_v Variant array Extra fields (unlock times, payment IDs, aliases, asset ops)
vout []tx_out_v Variant array Transaction outputs
attachment []attachment_v Variant array Service attachments (comments, encrypted data)
signatures []signature_v Variant array One signature per input
proofs []proof_v Variant array Global proofs (BP+, balance, surjection)

Version-specific serialisation

  • Version 0-1: Uses legacy transaction_v1 format with separate fields for attachments and signatures.
  • Version 2: Zarcanum format. Inputs are txin_zc_input, outputs are tx_out_zarcanum. Signatures are ZC_sig or zarcanum_sig.
  • Version 3: Adds hardfork_id field after vout. Supports asset operations.

Input Types

Transaction inputs are a variant (tagged union) of five possible types:

txin_gen -- Coinbase Input

type TxInGen struct {
    Height uint64  // Block height (varint)
}

Used only in the miner (coinbase) transaction. Specifies the block height, which determines the block reward.

txin_to_key -- Standard Input

type TxInToKey struct {
    Amount     uint64          // Input amount (varint, 0 for confidential)
    KeyOffsets []TxOutRef      // Ring member references (global indices or tx_id:n)
    KImage     KeyImage        // Key image (32 bytes) -- double-spend tag
    EtcDetails []TxInEtcDetail // Optional: signed_parts, attachment_info
}

The standard transparent input type. References a set of outputs (the ring) by their global indices and proves ownership of one via a ring signature. The key image uniquely identifies the real output being spent.

txin_multisig -- Multisig Input

type TxInMultisig struct {
    Amount       uint64          // Input amount (varint)
    MultisigOutID Hash           // Hash identifying the multisig output (32 bytes)
    SigsCount    uint32          // Number of signatures (varint)
    EtcDetails   []TxInEtcDetail // Optional details
}

Spends a multisig output. Requires SigsCount signatures matching the threshold defined in the referenced multisig output.

txin_htlc -- HTLC Input

type TxInHTLC struct {
    TxInToKey              // Inherits all fields from txin_to_key
    HLTCOrigin string      // HTLC preimage or refund proof
}

Spends a hash time-locked contract output. Extends txin_to_key with an HTLC origin string that proves knowledge of the hash preimage (before expiry) or ownership of the refund key (after expiry).

txin_zc_input -- Zarcanum Confidential Input

type TxInZCInput struct {
    KeyOffsets []TxOutRef      // Ring member references
    KImage     KeyImage        // Key image (32 bytes)
    EtcDetails []TxInEtcDetail // Optional details
}

The confidential input type introduced in HF4 (Zarcanum). Unlike txin_to_key, there is no amount field -- the amount is hidden within a Pedersen commitment. The corresponding signature (in the signatures array) is a ZC_sig containing pseudo-output commitments and a CLSAG-GGX signature.

Output Types

Transaction outputs are a variant of two types:

tx_out_bare -- Transparent Output

type TxOutBare struct {
    Amount uint64       // Output amount in atomic units (varint)
    Target TxOutTarget  // Variant: txout_to_key, txout_multisig, or txout_htlc
}

The pre-Zarcanum output type with a visible amount. The target specifies the spending condition:

txout_to_key

type TxOutToKey struct {
    Key     PublicKey  // One-time public key (32 bytes)
    MixAttr uint8     // Mixing attribute: 0=relaxed, 1=no mix, 2+=minimum ring size
}

Standard output payable to a one-time stealth address.

txout_multisig

type TxOutMultisig struct {
    MinimumSigs uint32      // Threshold (varint)
    Keys        []PublicKey  // Participant public keys
}

M-of-N multisig output requiring MinimumSigs signatures from the Keys set.

txout_htlc

type TxOutHTLC struct {
    HTLCHash   Hash       // Hash lock (32 bytes)
    Flags      uint8      // Hash type: 0=SHA256, 1=RIPEMD160
    Expiration uint64     // Expiration height or timestamp (varint)
    PkeyRedeem PublicKey  // Redeemer's key (before expiry)
    PkeyRefund PublicKey  // Refunder's key (after expiry)
}

Hash time-locked contract output with dual spending paths.

tx_out_zarcanum -- Confidential Output

type TxOutZarcanum struct {
    StealthAddress   PublicKey  // One-time stealth address (32 bytes)
    ConcealingPoint  PublicKey  // Group element Q, premultiplied by 1/8
    AmountCommitment PublicKey  // Pedersen commitment, premultiplied by 1/8
    BlindedAssetID   PublicKey  // Group element T, premultiplied by 1/8
    EncryptedAmount  uint64     // Encrypted amount (XOR with shared secret)
    MixAttr          uint8      // Mixing attribute
}

The confidential output type introduced in HF4. The amount is hidden inside AmountCommitment (a Pedersen commitment). The BlindedAssetID hides which asset type the output contains. The EncryptedAmount allows the recipient (who can derive the shared secret) to decrypt the actual amount.

All curve points are premultiplied by 1/8 for efficient batch verification.

Signature Types

Signatures are a variant matching the input type:

Variant Used with Description
NLSAG_sig txin_to_key (v0-1) Classic CryptoNote ring signature: vector of (c, r) pairs
void_sig txin_gen No signature needed for coinbase inputs
ZC_sig txin_zc_input (v2) Zarcanum sig: pseudo-out commitments + CLSAG-GGX
zarcanum_sig txin_zc_input (PoS v2) Full Zarcanum PoS proof: CLSAG-GGXXG + BP++ + Schnorr

ZC_sig structure

type ZCSig struct {
    PseudoOutAmountCommitment PublicKey                   // Premultiplied by 1/8
    PseudoOutBlindedAssetID   PublicKey                   // Premultiplied by 1/8
    CLSAGs_GGX                CLSAG_GGX_Signature         // Ring signature
}

zarcanum_sig structure

type ZarcanumSig struct {
    D                        PublicKey                     // Scalar commitment
    C                        PublicKey                     // Point C
    CPrime                   PublicKey                     // Point C'
    E                        PublicKey                     // Point E
    ResponseC                Scalar                        // Challenge scalar
    Y0, Y1, Y2, Y3, Y4      Scalar                        // Response scalars
    ERangeProof              BPPE_Signature                // BP++ for stake amount
    PseudoOutAmountCommitment PublicKey                    // Premultiplied by 1/8
    CLSAG_GGXXG              CLSAG_GGXXG_Signature        // 5-base ring signature
}

Proof Types

Global proofs are stored in the transaction's proofs array:

Variant Description
zc_asset_surjection_proof BGE proofs (one per output) proving asset type conservation
zc_outs_range_proof BP+ range proof + aggregation proof for output amounts
zc_balance_proof Double Schnorr signature proving input/output balance
asset_operation_proof Proves asset operation commitment is well-formed
asset_operation_ownership_proof Schnorr proof of asset ownership
asset_operation_ownership_proof_eth ETH signature proof of asset ownership

Address

Account Public Address

type AccountPublicAddress struct {
    SpendPublicKey PublicKey  // 32 bytes
    ViewPublicKey  PublicKey  // 32 bytes
    Flags          uint8     // Bit 0: auditable flag
}
Field Size Description
spend_public_key 32 bytes Used to authorise spending
view_public_key 32 bytes Used to detect incoming outputs
flags 1 byte 0x01 = auditable address

Address Encoding

Addresses are encoded as:

base58(varint(prefix) || spend_public_key || view_public_key [|| flags] || checksum)

Where:

  • prefix is the address type prefix (e.g. 0x1eaf7 for standard)
  • spend_public_key and view_public_key are 32 bytes each
  • flags is 1 byte, present only for auditable addresses (serialisation version >= 1)
  • checksum is the first 4 bytes of Keccak-256(prefix || keys [|| flags])

The CryptoNote base58 encoding splits the input into 8-byte blocks (last block may be shorter) and encodes each independently, producing 11 characters per 8-byte block.

Address Prefix Table

Type Prefix Starts with Auditable Integrated
Standard 0x1eaf7 iTHN No No
Integrated 0xdeaf7 iTHn No Yes
Auditable 0x3ceff7 iThN Yes No
Auditable integrated 0x8b077 iThn Yes Yes

Integrated addresses embed a payment ID within the address itself, eliminating the need for a separate payment ID field in the transaction.

Extra Field Types

The extra array in a transaction can contain any of the following variant types:

Type Description
tx_service_attachment Service-specific data (ID, instruction, body, flags)
tx_comment Human-readable comment
tx_payer Sender's address (for receiver identification)
tx_receiver Receiver's address
tx_derivation_hint Hint for key derivation
tx_crypto_checksum Encrypted key derivation for sender decryption
extra_alias_entry Alias registration or update
extra_user_data Arbitrary user data
zarcanum_tx_data_v1 Zarcanum-specific: explicit fee field
asset_descriptor_operation Asset register/emit/update/burn
etc_tx_details_unlock_time Per-tx unlock time
etc_tx_details_unlock_time2 Per-output unlock times
etc_tx_details_expiration_time Transaction expiration
etc_tx_details_flags Transaction flags (e.g. separate signature mode)
etc_tx_time Real timestamp for PoS blocks
crypto::public_key Transaction public key
extra_attachment_info Attachment hash and size
extra_padding Padding bytes