quilibrium_verkle/
node.rs1use sha2::{Sha512, Digest};
2use num_bigint::BigUint;
3use bls48581;
4use std::sync::Once;
5
6static INIT_BLS: Once = Once::new();
7
8fn ensure_bls_init() {
9 INIT_BLS.call_once(|| {
10 bls48581::init();
11 });
12}
13
14pub const BRANCH_NODES: usize = 64;
16pub const BRANCH_BITS: usize = 6;
18pub const BRANCH_MASK: usize = BRANCH_NODES - 1;
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub enum NodeType {
24 Nil = 0,
25 Leaf = 1,
26 Branch = 2,
27}
28
29#[derive(Clone)]
31pub enum VectorCommitmentNode {
32 Leaf(VectorCommitmentLeafNode),
33 Branch(Box<VectorCommitmentBranchNode>),
34}
35
36impl VectorCommitmentNode {
37 pub fn commit(&mut self, recalculate: bool) -> Vec<u8> {
39 match self {
40 VectorCommitmentNode::Leaf(leaf) => leaf.commit(recalculate),
41 VectorCommitmentNode::Branch(branch) => branch.commit(recalculate),
42 }
43 }
44
45 pub fn get_size(&self) -> BigUint {
47 match self {
48 VectorCommitmentNode::Leaf(leaf) => leaf.size.clone(),
49 VectorCommitmentNode::Branch(branch) => branch.size.clone(),
50 }
51 }
52
53 pub fn is_leaf(&self) -> bool {
55 matches!(self, VectorCommitmentNode::Leaf(_))
56 }
57
58 pub fn is_branch(&self) -> bool {
60 matches!(self, VectorCommitmentNode::Branch(_))
61 }
62
63 pub fn as_leaf(&self) -> Option<&VectorCommitmentLeafNode> {
65 match self {
66 VectorCommitmentNode::Leaf(leaf) => Some(leaf),
67 _ => None,
68 }
69 }
70
71 pub fn as_leaf_mut(&mut self) -> Option<&mut VectorCommitmentLeafNode> {
73 match self {
74 VectorCommitmentNode::Leaf(leaf) => Some(leaf),
75 _ => None,
76 }
77 }
78
79 pub fn as_branch(&self) -> Option<&VectorCommitmentBranchNode> {
81 match self {
82 VectorCommitmentNode::Branch(branch) => Some(branch),
83 _ => None,
84 }
85 }
86
87 pub fn as_branch_mut(&mut self) -> Option<&mut VectorCommitmentBranchNode> {
89 match self {
90 VectorCommitmentNode::Branch(branch) => Some(branch),
91 _ => None,
92 }
93 }
94}
95
96#[derive(Debug, Clone)]
98pub struct VectorCommitmentLeafNode {
99 pub key: Vec<u8>,
101 pub value: Vec<u8>,
103 pub hash_target: Option<Vec<u8>>,
105 pub commitment: Option<Vec<u8>>,
107 pub size: BigUint,
109}
110
111impl VectorCommitmentLeafNode {
112 pub fn new(key: Vec<u8>, value: Vec<u8>) -> Self {
114 Self {
115 key,
116 value,
117 hash_target: None,
118 commitment: None,
119 size: BigUint::from(1u32),
120 }
121 }
122
123 pub fn new_with_hash(key: Vec<u8>, value: Vec<u8>, hash_target: Vec<u8>) -> Self {
125 Self {
126 key,
127 value,
128 hash_target: Some(hash_target),
129 commitment: None,
130 size: BigUint::from(1u32),
131 }
132 }
133
134 pub fn commit(&mut self, recalculate: bool) -> Vec<u8> {
135 if self.commitment.is_none() || recalculate {
136 let mut hasher = Sha512::new();
138 hasher.update([0u8]);
140 hasher.update(&self.key);
142 if let Some(ref hash_target) = self.hash_target {
144 hasher.update(hash_target);
145 } else {
146 hasher.update(&self.value);
147 }
148 self.commitment = Some(hasher.finalize().to_vec());
149 }
150 self.commitment.as_ref().unwrap().clone()
151 }
152}
153
154#[derive(Clone)]
156pub struct VectorCommitmentBranchNode {
157 pub prefix: Vec<usize>,
159 pub children: [Option<VectorCommitmentNode>; BRANCH_NODES],
161 pub commitment: Option<Vec<u8>>,
163 pub size: BigUint,
165 pub leaf_count: usize,
167 pub longest_branch: usize,
169}
170
171impl VectorCommitmentBranchNode {
172 pub fn new(prefix: Vec<usize>) -> Self {
174 const INIT: Option<VectorCommitmentNode> = None;
176 let children = [INIT; BRANCH_NODES];
177
178 Self {
179 prefix,
180 children,
181 commitment: None,
182 size: BigUint::from(0u32),
183 leaf_count: 0,
184 longest_branch: 0,
185 }
186 }
187
188 pub fn get_polynomial(&mut self) -> Vec<u8> {
191 let mut data = Vec::with_capacity(BRANCH_NODES * 64);
192
193 for child_opt in &mut self.children {
194 if let Some(child) = child_opt {
195 let child_commit = child.commit(false);
196
197 let commit = if let Some(branch) = child.as_branch() {
199 let mut hasher = sha2::Sha512::new();
200 hasher.update([1u8]); for &p in &branch.prefix {
204 hasher.update((p as u32).to_be_bytes());
205 }
206
207 hasher.update(&child_commit);
208 hasher.finalize().to_vec()
209 } else {
210 child_commit
212 };
213
214 data.extend_from_slice(&commit);
215 } else {
216 data.extend_from_slice(&vec![0u8; 64]);
218 }
219 }
220
221 data
222 }
223
224 pub fn prove(&mut self, index: usize) -> Option<Vec<u8>> {
227 if index >= BRANCH_NODES {
228 return None;
229 }
230
231 let data = self.get_polynomial();
233
234 ensure_bls_init();
236
237 let proof = bls48581::prove_raw(&data, index as u64, 64);
239 Some(proof)
240 }
241
242 pub fn set_child(&mut self, index: usize, child: VectorCommitmentNode) {
244 if index < BRANCH_NODES {
245 self.children[index] = Some(child);
246 self.commitment = None; }
248 }
249
250 pub fn get_child(&self, index: usize) -> Option<&VectorCommitmentNode> {
252 if index < BRANCH_NODES {
253 self.children[index].as_ref()
254 } else {
255 None
256 }
257 }
258
259 pub fn get_child_mut(&mut self, index: usize) -> Option<&mut VectorCommitmentNode> {
261 if index < BRANCH_NODES {
262 self.children[index].as_mut()
263 } else {
264 None
265 }
266 }
267
268 pub fn commit(&mut self, recalculate: bool) -> Vec<u8> {
269 if self.commitment.is_none() || recalculate {
270 let mut vector: Vec<Vec<u8>> = Vec::with_capacity(BRANCH_NODES);
272
273 for child_opt in &mut self.children {
274 if let Some(child) = child_opt {
275 let child_commit = child.commit(recalculate);
276
277 let commit = if let Some(branch) = child.as_branch() {
279 let mut hasher = Sha512::new();
280 hasher.update([1u8]); for &p in &branch.prefix {
284 hasher.update((p as u32).to_be_bytes());
285 }
286
287 hasher.update(&child_commit);
288 hasher.finalize().to_vec()
289 } else {
290 child_commit
292 };
293
294 vector.push(commit);
295 } else {
296 vector.push(vec![0u8; 64]);
298 }
299 }
300
301 let mut data = Vec::with_capacity(BRANCH_NODES * 64);
303 for commit in &vector {
304 data.extend_from_slice(commit);
305 }
306
307 ensure_bls_init();
309
310 let commitment = bls48581::commit_raw(&data, 64);
313
314 self.commitment = Some(commitment);
315
316 self.size = BigUint::from(0u32);
318 for child_opt in &self.children {
319 if let Some(child) = child_opt {
320 self.size += child.get_size();
321 }
322 }
323 }
324
325 self.commitment.as_ref().unwrap().clone()
326 }
327}