Skip to main content

blvm_protocol/utxo_commitments/
data_structures.rs

1//! UTXO Commitment Data Structures
2//!
3//! Defines the core data structures for UTXO commitments:
4//! - UTXO: Unspent Transaction Output with metadata
5//! - UTXOCommitment: Cryptographic commitment to UTXO set state
6//! - UtxoCommitmentSet: UTXO set with Merkle tree commitment support
7
8use blvm_consensus::types::{Hash, Natural};
9use serde::{Deserialize, Serialize};
10
11/// UTXO Commitment
12///
13/// Cryptographic commitment to the UTXO set state at a specific block height.
14/// Contains the Merkle root hash of the UTXO set and metadata for verification.
15///
16/// Size: 88 bytes on the wire (32 + 8 + 8 + 8 + 32).
17#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
18pub struct UtxoCommitment {
19    /// Merkle root of the UTXO set
20    pub merkle_root: Hash,
21
22    /// Total Bitcoin supply in the UTXO set (satoshis)
23    pub total_supply: u64,
24
25    /// Number of UTXOs in the set
26    pub utxo_count: u64,
27
28    /// Block height at which this commitment was generated
29    pub block_height: Natural,
30
31    /// Block hash at which this commitment was generated
32    pub block_hash: Hash,
33}
34
35impl UtxoCommitment {
36    /// Create a new UTXO commitment
37    pub fn new(
38        merkle_root: Hash,
39        total_supply: u64,
40        utxo_count: u64,
41        block_height: Natural,
42        block_hash: Hash,
43    ) -> Self {
44        Self {
45            merkle_root,
46            total_supply,
47            utxo_count,
48            block_height,
49            block_hash,
50        }
51    }
52
53    /// Serialize commitment to bytes
54    pub fn to_bytes(&self) -> Vec<u8> {
55        let mut bytes = Vec::with_capacity(88);
56        bytes.extend_from_slice(&self.merkle_root);
57        bytes.extend_from_slice(&self.total_supply.to_be_bytes());
58        bytes.extend_from_slice(&self.utxo_count.to_be_bytes());
59        bytes.extend_from_slice(&self.block_height.to_be_bytes());
60        bytes.extend_from_slice(&self.block_hash);
61        bytes
62    }
63
64    /// Deserialize commitment from bytes
65    pub fn from_bytes(data: &[u8]) -> Result<Self, UtxoCommitmentError> {
66        if data.len() != 88 {
67            return Err(UtxoCommitmentError::InvalidSize(data.len()));
68        }
69
70        let mut offset = 0;
71        let merkle_root: Hash = {
72            let mut hash = [0u8; 32];
73            hash.copy_from_slice(&data[offset..offset + 32]);
74            offset += 32;
75            hash
76        };
77
78        let total_supply = u64::from_be_bytes(
79            data[offset..offset + 8]
80                .try_into()
81                .map_err(|_| UtxoCommitmentError::InvalidSize(data.len()))?,
82        );
83        offset += 8;
84
85        let utxo_count = u64::from_be_bytes(
86            data[offset..offset + 8]
87                .try_into()
88                .map_err(|_| UtxoCommitmentError::InvalidSize(data.len()))?,
89        );
90        offset += 8;
91
92        let block_height = u64::from_be_bytes(
93            data[offset..offset + 8]
94                .try_into()
95                .map_err(|_| UtxoCommitmentError::InvalidSize(data.len()))?,
96        );
97        offset += 8;
98
99        let block_hash: Hash = {
100            let mut hash = [0u8; 32];
101            hash.copy_from_slice(&data[offset..offset + 32]);
102            hash
103        };
104
105        Ok(Self {
106            merkle_root,
107            total_supply,
108            utxo_count,
109            block_height,
110            block_hash,
111        })
112    }
113
114    /// Verify commitment matches UTXO set parameters
115    pub fn verify_supply(&self, expected_supply: u64) -> bool {
116        self.total_supply == expected_supply
117    }
118
119    /// Verify commitment matches expected UTXO count
120    pub fn verify_count(&self, expected_count: u64) -> bool {
121        self.utxo_count == expected_count
122    }
123}
124
125/// Error type for UTXO commitment operations
126#[derive(Debug, Clone, PartialEq, Eq)]
127pub enum UtxoCommitmentError {
128    /// Invalid commitment size
129    InvalidSize(usize),
130    /// Merkle tree operation failed
131    MerkleTreeError(String),
132    /// Invalid UTXO data
133    InvalidUtxo(String),
134    /// Commitment verification failed
135    VerificationFailed(String),
136    /// Serialization/deserialization error
137    SerializationError(String),
138    /// Transaction application error (during UTXO set updates)
139    TransactionApplication(String),
140}
141
142impl std::fmt::Display for UtxoCommitmentError {
143    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
144        match self {
145            UtxoCommitmentError::InvalidSize(size) => {
146                write!(f, "Invalid commitment size: {} (expected 88)", size)
147            }
148            UtxoCommitmentError::MerkleTreeError(msg) => {
149                write!(f, "Merkle tree error: {}", msg)
150            }
151            UtxoCommitmentError::InvalidUtxo(msg) => {
152                write!(f, "Invalid UTXO: {}", msg)
153            }
154            UtxoCommitmentError::VerificationFailed(msg) => {
155                write!(f, "Verification failed: {}", msg)
156            }
157            UtxoCommitmentError::SerializationError(msg) => {
158                write!(f, "Serialization error: {}", msg)
159            }
160            UtxoCommitmentError::TransactionApplication(msg) => {
161                write!(f, "Transaction application error: {}", msg)
162            }
163        }
164    }
165}
166
167impl std::error::Error for UtxoCommitmentError {}
168
169/// Result type for UTXO commitment operations
170pub type UtxoCommitmentResult<T> = Result<T, UtxoCommitmentError>;
171
172// ============================================================================
173// FORMAL VERIFICATION
174// ============================================================================
175
176/// Mathematical Specification for UTXO Commitment:
177/// ∀ commitment ∈ UtxoCommitment:
178/// - to_bytes() → Vec<u8] where |bytes| = 88
179/// - from_bytes(to_bytes(commitment)) = commitment (round-trip)
180/// - verify_supply(expected) = true ⟺ commitment.total_supply = expected
181///
182/// Invariants:
183/// - Serialization is deterministic and reversible
184#[doc(hidden)]
185const _UTXO_COMMITMENT_SPEC: () = ();
186
187// End of module