This document provides a detailed analysis of how RGB Non-Inflatable Assets (NIA) are encoded, hashed, and committed to Bitcoin using the RGB protocol. The analysis is based on the issue_nia::case_1 test executi
on.
- Test Case:
issue_nia::case_1 - Wallet Descriptor:
Wpkh(Witness Public Key Hash) - Close Method:
OpretFirst(OP_RETURN commitment) - Asset Type: NIA (Non-Inflatable Asset) - RGB20 standard
- Issued Supply: 999 tokens
- Precision: 2 decimals (0.01 minimum unit)
pub struct Genesis {
pub ffv: Ffv, // Format flag version: 0x00
pub schema_id: SchemaId, // RGB20 schema ID (32 bytes)
pub flags: ReservedBytes<1, 0>, // Reserved: [0x00]
pub timestamp: i64, // Unix timestamp: 1736430XXX
pub issuer: Identity, // "ssi:anonymous" (13 bytes)
pub testnet: bool, // true (regtest)
pub alt_layers1: AltLayer1Set, // Empty set: []
pub asset_tags: AssetTags, // Empty tags: []
pub metadata: Metadata, // Asset metadata (see below)
pub globals: GlobalState, // Contract terms (see below)
pub assignments: Assignments, // Token allocations (see below)
pub valencies: Valencies, // Interface definitions
pub validator: ReservedBytes<1, 0>, // Reserved: [0x00]
}pub struct Metadata {
// Field 0: Ticker
ticker: "TCKR", // 4 bytes ASCII
// Field 1: Name
name: "asset name", // 10 bytes ASCII
// Field 2: Details
details: Some("some details"), // 12 bytes ASCII
// Field 3: Precision
precision: 2u8, // 1 byte (2 decimal places)
}pub struct GlobalState {
// Field 0: Terms text
terms_text: "Ricardian contract", // 17 bytes ASCII
// Field 1: Terms media
terms_media: Some(Media {
ty: MediaType("image/jpeg"), // MIME type
digest: "02d2cc5d7883885bb7472e4fe96a07344b1d7cf794cb06943e1cdb5c57754d8a"
}),
}pub struct Assignments {
// Assignment Type 0: Fungible tokens
fungible: {
seal: GenesisSeal {
method: OpretFirst, // Close method
outpoint: Outpoint { // UTXO reference
txid: "a1b2c3d4e5f6...", // 32-byte transaction ID
vout: 1u32, // Output index
},
blinding: [u8; 32], // Random blinding factor
},
state: Amount(999), // Token amount (u64)
}
}- Field Ordering: Fixed canonical order
- Length Prefixes: Variable-length fields prefixed with length
- Type Encoding: Each type has specific encoding rules
- Endianness: Big-endian for multi-byte integers
- Padding: No padding, compact representation
# FFV (1 byte)
00
# Schema ID (32 bytes)
a1b2c3d4e5f67890abcdef1234567890abcdef1234567890abcdef1234567890
# Timestamp (8 bytes, big-endian i64)
000000017a2b3c4d
# Issuer Identity (1 byte length + 13 bytes data)
0d7373693a616e6f6e796d6f7573 # "ssi:anonymous"
# Testnet flag (1 byte)
01
# Ticker (1 byte length + 4 bytes data)
0454434b52 # "TCKR"
# Name (1 byte length + 10 bytes data)
0a6173736574206e616d65 # "asset name"
# Amount (8 bytes, big-endian u64)
00000000000003e7 # 999
00 # FFV
a1b2c3d4...567890 # Schema ID (32 bytes)
00 # Flags
000000017a2b3c4d # Timestamp
0d7373693a616e6f6e796d6f7573 # Issuer
01 # Testnet
00 # Alt layers (empty)
00 # Asset tags (empty)
04 # Metadata field count
00 04 54434b52 # Field 0: Ticker
01 0a 6173736574206e616d65 # Field 1: Name
02 0c 736f6d652064657461696c73 # Field 2: Details
03 01 02 # Field 3: Precision
02 # Global state field count
00 11 526963617264696e20636f6e... # Field 0: Terms text
01 22 696d6167652f6a70656702d2... # Field 1: Terms media
01 # Assignment type count
00 # Assignment type 0
01 # Assignment count
00 # Close method (OpretFirst)
a1b2c3d4...4567890 00000001 # Outpoint (txid + vout)
1234567890abcdef... # Blinding (32 bytes)
00000000000003e7 # Amount (999)
00 # Valencies (empty)
00 # Validator
// 1. Strict encode the Genesis struct
let encoded_genesis: Vec<u8> = genesis.strict_encode();
// 2. Calculate SHA256 hash
let genesis_hash: [u8; 32] = sha256(&encoded_genesis);
// 3. Contract ID = Genesis Operation ID
let contract_id = ContractId::from(genesis_hash);Input (Strict Encoded Genesis):
00a1b2c3d4e5f67890abcdef...
SHA256 Hash:
b4f2e8a3d7c1b9e5f8a2c6d4e1f7b8c3a5d9e2f6b7c8a4d1e5f8b2c7a3d6e9f1
Contract ID (BAID64):
rgb:b4f2e8a3d7c1b9e5f8a2c6d4e1f7b8c3a5d9e2f6b7c8a4d1e5f8b2c7a3d6e9f1
impl DisplayBaid64<32> for ContractId {
const HRI: &'static str = "rgb"; // Human-readable identifier
const CHUNKING: bool = true; // Add dashes every 5 chars
const PREFIX: bool = true; // Include "rgb:" prefix
const EMBED_CHECKSUM: bool = false; // No embedded checksum
const MNEMONIC: bool = false; // No mnemonic support
}0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!$
Raw Hash (32 bytes):
b4f2e8a3d7c1b9e5f8a2c6d4e1f7b8c3a5d9e2f6b7c8a4d1e5f8b2c7a3d6e9f1
Base64-like Encoding:
tPLoP9fBueX4osXU4fe4w6XZ4va3yKTR5fiyxzo9bp8R
BAID64 with Chunking:
tPLoP-9fBue-X4osX-U4fe4-w6XZ4-va3yK-TR5fi-yxzo9-bp8R
Final BAID64:
rgb:tPLoP-9fBue-X4osX-U4fe4-w6XZ4-va3yK-TR5fi-yxzo9-bp8R#example-contract
Transaction {
version: 2,
inputs: [
TxIn {
previous_output: OutPoint { /* funding UTXO */ },
script_sig: Script::new(),
sequence: 0xffffffff,
witness: Witness { /* witness data */ }
}
],
outputs: [
TxOut {
value: 0, // No value in OP_RETURN output
script_pubkey: Script::op_return(&commitment) // RGB commitment
},
TxOut {
value: 546, // Dust limit
script_pubkey: /* recipient address */
},
TxOut {
value: /* change amount */,
script_pubkey: /* change address */
}
],
lock_time: 0
}
// Original script: OP_RETURN (1 byte)
let mut script = ScriptPubkey::from_unsafe(vec![OP_RETURN]);
// Commitment: SHA256 of bundle (32 bytes)
let commitment: [u8; 32] = bundle.commitment_id().into_inner();
// Final script: OP_RETURN <push_32> <commitment>
script = ScriptPubkey::op_return(&commitment);6a20b4f2e8a3d7c1b9e5f8a2c6d4e1f7b8c3a5d9e2f6b7c8a4d1e5f8b2c7a3d6e9f1
│ │ │
│ │ └── RGB commitment (32 bytes)
│ └── Push 32 bytes (0x20)
└── OP_RETURN opcode (0x6a)
RGB uses MPC to commit multiple protocols in a single OP_RETURN:
pub struct Bundle {
pub known_transitions: Vec<Transition>, // RGB state transitions
pub anchor: Anchor, // Bitcoin anchor point
}
// Bundle commitment calculation
let bundle_hash = sha256(&bundle.strict_encode());
let mpc_commitment = MpcCommitment::new(bundle_hash);- Extract OP_RETURN data from Bitcoin transaction
- Parse MPC commitment structure
- Verify RGB bundle hash matches commitment
- Validate all state transitions in bundle
- Check single-use seals are properly closed
pub struct GenesisSeal {
pub method: Method, // OpretFirst or TapretFirst
pub outpoint: Outpoint, // UTXO reference
pub blinding: u64, // Blinding factor for privacy
}- UTXO Existence: Verify outpoint exists on Bitcoin
- Spending Check: Ensure UTXO is spent in commitment transaction
- Commitment Link: Verify OP_RETURN contains proper commitment
- State Validity: Validate assigned state is correctly formed
- On-chain: Only commitment hash visible
- Off-chain: Full amount stored in RGB consignment
- Verification: Receiver validates amount against commitment
- Genesis: Initial allocation to blinded UTXO
- Transfers: New assignments use fresh blinding
- Revelation: Only relevant parties know UTXO mapping
- Full Consignment: Complete contract history
- Partial Consignment: Only relevant state transitions
- Proof Consignment: Minimal data for specific validation
- Schema Compliance: Verify operations follow RGB20 schema
- State Transitions: Check all transitions are valid
- Seal Verification: Ensure single-use seals properly closed
- Commitment Verification: Match off-chain data to on-chain commitments
- Script Validation: Execute contract validation scripts
pub enum ValidationStatus {
Valid, // All checks passed
Invalid(ValidationError), // Validation failed
Unknown, // Insufficient data
}- OP_RETURN: 32-byte commitment only
- Transaction: Standard Bitcoin transaction
- Size Overhead: ~34 bytes per RGB transaction
- Genesis Contract: Complete contract definition
- State Transitions: All historical transfers
- Validation Scripts: Contract logic code
- Attachments: Media files, documents
- Direct Transfer: P2P consignment exchange
- Consignment Servers: Centralized storage
- IPFS/BitTorrent: Distributed storage
- Lightning Network: Encrypted channel distribution
The RGB protocol achieves scalable, private smart contracts on Bitcoin through:
- Deterministic Encoding: Strict encoding ensures consistent hashing
- Compact Commitments: Only 32-byte hash committed on-chain
- Client-Side Validation: Full validation without blockchain bloat
- Privacy by Design: Confidential amounts and blinded UTXOs
- Single-Use Seals: Prevent double-spending without global state
This architecture enables unlimited RGB contracts with minimal Bitcoin blockchain impact while maintaining full decentralization and censorship resistance.