Table of Contents
- Data Structures
- Block Header
- Block
- Transaction
- Input Types
- txin_gen -- Coinbase Input
- txin_to_key -- Standard Input
- txin_multisig -- Multisig Input
- txin_htlc -- HTLC Input
- txin_zc_input -- Zarcanum Confidential Input
- Output Types
- Signature Types
- Proof Types
- Address
- Extra Field Types
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_v1format with separate fields for attachments and signatures. - Version 2: Zarcanum format. Inputs are
txin_zc_input, outputs aretx_out_zarcanum. Signatures areZC_sigorzarcanum_sig. - Version 3: Adds
hardfork_idfield aftervout. 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:
prefixis the address type prefix (e.g.0x1eaf7for standard)spend_public_keyandview_public_keyare 32 bytes eachflagsis 1 byte, present only for auditable addresses (serialisation version >= 1)checksumis the first 4 bytes ofKeccak-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 |