blvm_protocol/utxo_commitments/
data_structures.rs1use blvm_consensus::types::{Hash, Natural};
9use serde::{Deserialize, Serialize};
10
11#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
18pub struct UtxoCommitment {
19 pub merkle_root: Hash,
21
22 pub total_supply: u64,
24
25 pub utxo_count: u64,
27
28 pub block_height: Natural,
30
31 pub block_hash: Hash,
33}
34
35impl UtxoCommitment {
36 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 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 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 pub fn verify_supply(&self, expected_supply: u64) -> bool {
116 self.total_supply == expected_supply
117 }
118
119 pub fn verify_count(&self, expected_count: u64) -> bool {
121 self.utxo_count == expected_count
122 }
123}
124
125#[derive(Debug, Clone, PartialEq, Eq)]
127pub enum UtxoCommitmentError {
128 InvalidSize(usize),
130 MerkleTreeError(String),
132 InvalidUtxo(String),
134 VerificationFailed(String),
136 SerializationError(String),
138 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
169pub type UtxoCommitmentResult<T> = Result<T, UtxoCommitmentError>;
171
172#[doc(hidden)]
185const _UTXO_COMMITMENT_SPEC: () = ();
186
187