1use std::{collections::BTreeMap, io::Cursor};
20
21use darkfi_sdk::{
22 crypto::contract_id::{
23 ContractId, NATIVE_CONTRACT_IDS_BYTES, NATIVE_CONTRACT_ZKAS_DB_NAMES,
24 SMART_CONTRACT_MONOTREE_DB_NAME, SMART_CONTRACT_ZKAS_DB_NAME,
25 },
26 monotree::{MemoryDb, Monotree, SledOverlayDb, SledTreeDb, EMPTY_HASH},
27};
28use darkfi_serial::{deserialize, serialize};
29use sled_overlay::{sled, SledDbOverlayStateDiff};
30use tracing::{debug, error};
31
32use crate::{
33 zk::{empty_witnesses, VerifyingKey, ZkCircuit},
34 zkas::ZkBinary,
35 Error, Result,
36};
37
38use super::{parse_record, SledDbOverlayPtr};
39
40pub const SLED_CONTRACTS_TREE: &[u8] = b"_contracts";
41pub const SLED_CONTRACTS_TREES_TREE: &[u8] = b"_contracts_trees";
42pub const SLED_BINCODE_TREE: &[u8] = b"_wasm_bincode";
43
44#[derive(Clone)]
47pub struct ContractStore {
48 pub wasm: sled::Tree,
55 pub state: sled::Tree,
65 pub state_trees: sled::Tree,
76}
77
78impl ContractStore {
79 pub fn new(db: &sled::Db) -> Result<Self> {
81 let wasm = db.open_tree(SLED_BINCODE_TREE)?;
82 let state = db.open_tree(SLED_CONTRACTS_TREE)?;
83 let state_trees = db.open_tree(SLED_CONTRACTS_TREES_TREE)?;
84 Ok(Self { wasm, state, state_trees })
85 }
86
87 pub fn get(&self, contract_id: ContractId) -> Result<Vec<u8>> {
90 if let Some(bincode) = self.wasm.get(serialize(&contract_id))? {
91 return Ok(bincode.to_vec())
92 }
93
94 Err(Error::WasmBincodeNotFound)
95 }
96
97 pub fn lookup(
102 &self,
103 db: &sled::Db,
104 contract_id: &ContractId,
105 tree_name: &str,
106 ) -> Result<sled::Tree> {
107 debug!(target: "blockchain::contractstore::lookup", "Looking up state tree for {contract_id}:{tree_name}");
108
109 let contract_id_bytes = serialize(contract_id);
111 if !self.state.contains_key(&contract_id_bytes)? {
112 return Err(Error::ContractNotFound(contract_id.to_string()))
113 }
114
115 let state_pointers = self.state.get(&contract_id_bytes)?.unwrap();
116 let state_pointers: Vec<[u8; 32]> = deserialize(&state_pointers)?;
117
118 let ptr = contract_id.hash_state_id(tree_name);
121 if !state_pointers.contains(&ptr) {
122 return Err(Error::ContractStateNotFound)
123 }
124
125 let tree = db.open_tree(ptr)?;
127 Ok(tree)
128 }
129
130 pub fn remove(&self, db: &sled::Db, contract_id: &ContractId, tree_name: &str) -> Result<()> {
138 debug!(target: "blockchain::contractstore::remove", "Removing state tree for {contract_id}:{tree_name}");
139
140 let contract_id_bytes = serialize(contract_id);
142 if !self.state.contains_key(&contract_id_bytes)? {
143 return Err(Error::ContractNotFound(contract_id.to_string()))
144 }
145
146 let state_pointers = self.state.get(&contract_id_bytes)?.unwrap();
147 let mut state_pointers: Vec<[u8; 32]> = deserialize(&state_pointers)?;
148
149 let ptr = contract_id.hash_state_id(tree_name);
152 if !state_pointers.contains(&ptr) {
153 return Err(Error::ContractStateNotFound)
154 }
155 if !self.state_trees.contains_key(ptr)? {
156 return Err(Error::ContractStateNotFound)
157 }
158
159 state_pointers.retain(|x| *x != ptr);
161 self.state.insert(contract_id_bytes, serialize(&state_pointers))?;
162 self.state_trees.remove(ptr)?;
163
164 db.drop_tree(ptr)?;
166
167 Ok(())
168 }
169
170 pub fn get_zkas(
173 &self,
174 db: &sled::Db,
175 contract_id: &ContractId,
176 zkas_ns: &str,
177 ) -> Result<(ZkBinary, VerifyingKey)> {
178 debug!(target: "blockchain::contractstore::get_zkas", "Looking up \"{contract_id}:{zkas_ns}\" zkas circuit & vk");
179
180 let zkas_tree = self.lookup(db, contract_id, SMART_CONTRACT_ZKAS_DB_NAME)?;
181
182 let Some(zkas_bytes) = zkas_tree.get(serialize(&zkas_ns))? else {
183 return Err(Error::ZkasBincodeNotFound)
184 };
185
186 let (zkbin, vkbin): (Vec<u8>, Vec<u8>) = deserialize(&zkas_bytes).unwrap();
189
190 let zkbin = ZkBinary::decode(&zkbin, false).unwrap();
192
193 let circuit = ZkCircuit::new(empty_witnesses(&zkbin).unwrap(), &zkbin);
195
196 let mut vk_buf = Cursor::new(vkbin);
198 let vk = VerifyingKey::read::<Cursor<Vec<u8>>, ZkCircuit>(&mut vk_buf, circuit).unwrap();
199
200 Ok((zkbin, vk))
201 }
202
203 pub fn get_all_wasm(&self) -> Result<Vec<(ContractId, Vec<u8>)>> {
207 let mut bincodes = vec![];
208
209 for bincode in self.wasm.iter() {
210 let bincode = bincode.unwrap();
211 let contract_id = deserialize(&bincode.0)?;
212 bincodes.push((contract_id, bincode.1.to_vec()));
213 }
214
215 Ok(bincodes)
216 }
217
218 pub fn get_all_states(&self) -> Result<Vec<(ContractId, Vec<blake3::Hash>)>> {
222 let mut contracts = vec![];
223
224 for contract in self.state.iter() {
225 contracts.push(parse_record(contract.unwrap())?);
226 }
227
228 Ok(contracts)
229 }
230
231 pub fn get_state_tree_value(
233 &self,
234 db: &sled::Db,
235 contract_id: &ContractId,
236 tree_name: &str,
237 key: &[u8],
238 ) -> Result<Vec<u8>> {
239 debug!(target: "blockchain::contractstore::get_state_tree_value", "Looking up state tree value for {contract_id}:{tree_name}");
240
241 let state_tree = self.lookup(db, contract_id, tree_name)?;
243
244 match state_tree.get(key)? {
246 Some(value) => Ok(value.to_vec()),
247 None => Err(Error::DatabaseError(format!(
248 "State tree {contract_id}:{tree_name} doesn't contain key: {key:?}"
249 ))),
250 }
251 }
252
253 pub fn get_state_tree_records(
256 &self,
257 db: &sled::Db,
258 contract_id: &ContractId,
259 tree_name: &str,
260 ) -> Result<BTreeMap<Vec<u8>, Vec<u8>>> {
261 debug!(target: "blockchain::contractstore::get_state_tree_records", "Looking up state tree records for {contract_id}:{tree_name}");
262
263 let state_tree = self.lookup(db, contract_id, tree_name)?;
265
266 let mut ret = BTreeMap::new();
268 for record in state_tree.iter() {
269 let (key, value) = record.unwrap();
270 ret.insert(key.to_vec(), value.to_vec());
271 }
272
273 Ok(ret)
274 }
275
276 pub fn get_state_monotree(&self, db: &sled::Db) -> Result<Monotree<MemoryDb>> {
281 debug!(target: "blockchain::contractstore::get_state_monotree", "Initializing global monotree...");
283 let mut root = None;
284 let monotree_db = MemoryDb::new();
285 let mut tree = Monotree::new(monotree_db);
286
287 for state_record in self.state.iter() {
289 let (contract_id, state_pointers): (ContractId, Vec<[u8; 32]>) =
291 parse_record(state_record?)?;
292 let state_monotree_ptr = contract_id.hash_state_id(SMART_CONTRACT_MONOTREE_DB_NAME);
293
294 if !state_pointers.contains(&state_monotree_ptr) {
296 return Err(Error::ContractStateNotFound)
297 }
298 if !self.state_trees.contains_key(state_monotree_ptr)? {
299 return Err(Error::ContractStateNotFound)
300 }
301
302 let state_tree = db.open_tree(state_monotree_ptr)?;
304 let state_monotree_db = SledTreeDb::new(&state_tree);
305 let state_monotree = Monotree::new(state_monotree_db);
306
307 let state_monotree_root = match state_monotree.get_headroot()? {
309 Some(hash) => hash,
310 None => *EMPTY_HASH,
311 };
312 debug!(target: "blockchain::contractstore::get_state_monotree", "Contract {contract_id} root: {}", blake3::Hash::from(state_monotree_root));
313 root = tree.insert(root.as_ref(), &contract_id.to_bytes(), &state_monotree_root)?;
314 debug!(target: "blockchain::contractstore::get_state_monotree", "New global root: {}", blake3::Hash::from(root.unwrap()));
315 }
316
317 debug!(target: "blockchain::contractstore::get_state_monotree", "Initializing wasm bincodes monotree...");
319 let mut wasm_monotree_root = None;
320 let wasm_monotree_db = MemoryDb::new();
321 let mut wasm_monotree = Monotree::new(wasm_monotree_db);
322 for record in self.wasm.iter() {
323 let (key, value) = record?;
324
325 if NATIVE_CONTRACT_IDS_BYTES.contains(&deserialize(&key)?) {
327 continue
328 }
329
330 let key = blake3::hash(&key);
332 let value = blake3::hash(&value);
333 debug!(target: "blockchain::contractstore::get_state_monotree", "Inserting key {key} with value: {value}");
334 wasm_monotree_root = wasm_monotree.insert(
335 wasm_monotree_root.as_ref(),
336 key.as_bytes(),
337 value.as_bytes(),
338 )?;
339 }
340
341 let wasm_monotree_root = match wasm_monotree_root {
343 Some(hash) => hash,
344 None => *EMPTY_HASH,
345 };
346 debug!(target: "blockchain::contractstore::get_state_monotree", "New root: {}", blake3::Hash::from(wasm_monotree_root));
347 root = tree.insert(
348 root.as_ref(),
349 blake3::hash(SLED_BINCODE_TREE).as_bytes(),
350 &wasm_monotree_root,
351 )?;
352 debug!(target: "blockchain::contractstore::get_state_monotree", "New global root: {}", blake3::Hash::from(root.unwrap()));
353 tree.set_headroot(root.as_ref());
354
355 Ok(tree)
356 }
357}
358
359pub struct ContractStoreOverlay(SledDbOverlayPtr);
361
362impl ContractStoreOverlay {
363 pub fn new(overlay: &SledDbOverlayPtr) -> Result<Self> {
364 overlay.lock().unwrap().open_tree(SLED_BINCODE_TREE, true)?;
365 overlay.lock().unwrap().open_tree(SLED_CONTRACTS_TREE, true)?;
366 overlay.lock().unwrap().open_tree(SLED_CONTRACTS_TREES_TREE, true)?;
367 Ok(Self(overlay.clone()))
368 }
369
370 pub fn get(&self, contract_id: ContractId) -> Result<Vec<u8>> {
373 if let Some(bincode) =
374 self.0.lock().unwrap().get(SLED_BINCODE_TREE, &serialize(&contract_id))?
375 {
376 return Ok(bincode.to_vec())
377 }
378
379 Err(Error::WasmBincodeNotFound)
380 }
381
382 pub fn insert(&self, contract_id: ContractId, bincode: &[u8]) -> Result<()> {
385 if let Err(e) =
386 self.0.lock().unwrap().insert(SLED_BINCODE_TREE, &serialize(&contract_id), bincode)
387 {
388 error!(target: "blockchain::contractstoreoverlay::insert", "Failed to insert bincode to Wasm tree: {e}");
389 return Err(e.into())
390 }
391
392 Ok(())
393 }
394
395 pub fn init(&self, contract_id: &ContractId, tree_name: &str) -> Result<[u8; 32]> {
406 debug!(target: "blockchain::contractstoreoverlay::init", "Initializing state overlay tree for {contract_id}:{tree_name}");
407 let mut lock = self.0.lock().unwrap();
408
409 let contract_id_bytes = serialize(contract_id);
412 let mut state_pointers: Vec<[u8; 32]> =
413 if lock.contains_key(SLED_CONTRACTS_TREE, &contract_id_bytes)? {
414 let bytes = lock.get(SLED_CONTRACTS_TREE, &contract_id_bytes)?.unwrap();
415 deserialize(&bytes)?
416 } else {
417 vec![]
418 };
419
420 let ptr = contract_id.hash_state_id(tree_name);
422 if state_pointers.contains(&ptr) {
423 return Err(Error::ContractAlreadyInitialized)
424 }
425
426 state_pointers.push(ptr);
428 lock.insert(SLED_CONTRACTS_TREE, &contract_id_bytes, &serialize(&state_pointers))?;
429 lock.insert(SLED_CONTRACTS_TREES_TREE, &ptr, &contract_id_bytes)?;
430 lock.open_tree(&ptr, false)?;
431
432 Ok(ptr)
433 }
434
435 pub fn lookup(&self, contract_id: &ContractId, tree_name: &str) -> Result<[u8; 32]> {
440 debug!(target: "blockchain::contractstoreoverlay::lookup", "Looking up state tree for {contract_id}:{tree_name}");
441 let mut lock = self.0.lock().unwrap();
442
443 let contract_id_bytes = serialize(contract_id);
445 if !lock.contains_key(SLED_CONTRACTS_TREE, &contract_id_bytes)? {
446 return Err(Error::ContractNotFound(contract_id.to_string()))
447 }
448
449 let state_pointers = lock.get(SLED_CONTRACTS_TREE, &contract_id_bytes)?.unwrap();
450 let state_pointers: Vec<[u8; 32]> = deserialize(&state_pointers)?;
451
452 let ptr = contract_id.hash_state_id(tree_name);
455 if !state_pointers.contains(&ptr) {
456 return Err(Error::ContractStateNotFound)
457 }
458 if !lock.contains_key(SLED_CONTRACTS_TREES_TREE, &ptr)? {
459 return Err(Error::ContractStateNotFound)
460 }
461
462 lock.open_tree(&ptr, false)?;
464 Ok(ptr)
465 }
466
467 pub fn get_zkas(
470 &self,
471 contract_id: &ContractId,
472 zkas_ns: &str,
473 ) -> Result<(ZkBinary, VerifyingKey)> {
474 debug!(target: "blockchain::contractstoreoverlay::get_zkas", "Looking up \"{contract_id}:{zkas_ns}\" zkas circuit & vk");
475
476 let zkas_tree = self.lookup(contract_id, SMART_CONTRACT_ZKAS_DB_NAME)?;
477
478 let Some(zkas_bytes) = self.0.lock().unwrap().get(&zkas_tree, &serialize(&zkas_ns))? else {
479 return Err(Error::ZkasBincodeNotFound)
480 };
481
482 let (zkbin, vkbin): (Vec<u8>, Vec<u8>) = deserialize(&zkas_bytes).unwrap();
485
486 let zkbin = ZkBinary::decode(&zkbin, false).unwrap();
488
489 let circuit = ZkCircuit::new(empty_witnesses(&zkbin).unwrap(), &zkbin);
491
492 let mut vk_buf = Cursor::new(vkbin);
494 let vk = VerifyingKey::read::<Cursor<Vec<u8>>, ZkCircuit>(&mut vk_buf, circuit).unwrap();
495
496 Ok((zkbin, vk))
497 }
498
499 pub fn get_state_monotree(&self) -> Result<Monotree<MemoryDb>> {
508 let mut lock = self.0.lock().unwrap();
509
510 debug!(target: "blockchain::contractstoreoverlay::get_state_monotree", "Retrieving state pointers...");
512 let mut states_monotrees_pointers = vec![];
513 for state_record in lock.iter(SLED_CONTRACTS_TREE)? {
514 let (contract_id, mut state_pointers): (ContractId, Vec<[u8; 32]>) =
516 parse_record(state_record?)?;
517 let state_monotree_ptr = contract_id.hash_state_id(SMART_CONTRACT_MONOTREE_DB_NAME);
518
519 if !state_pointers.contains(&state_monotree_ptr) {
521 return Err(Error::ContractStateNotFound)
522 }
523 if !lock.contains_key(SLED_CONTRACTS_TREES_TREE, &state_monotree_ptr)? {
524 return Err(Error::ContractStateNotFound)
525 }
526
527 if NATIVE_CONTRACT_IDS_BYTES.contains(&contract_id.to_bytes()) {
529 state_pointers.retain(|ptr| !NATIVE_CONTRACT_ZKAS_DB_NAMES.contains(ptr));
530 }
531
532 states_monotrees_pointers.push((contract_id, state_pointers, state_monotree_ptr));
533 }
534
535 debug!(target: "blockchain::contractstoreoverlay::get_state_monotree", "Initializing global monotree...");
537 let mut root = None;
538 let monotree_db = MemoryDb::new();
539 let mut tree = Monotree::new(monotree_db);
540
541 for (contract_id, state_pointers, state_monotree_ptr) in states_monotrees_pointers {
543 debug!(target: "blockchain::contractstoreoverlay::get_state_monotree", "Updating monotree for contract: {contract_id}");
547 let mut rebuild = false;
548 let mut inserts = vec![];
549 'outer: for state_ptr in &state_pointers {
550 if state_ptr == &state_monotree_ptr {
552 continue
553 }
554
555 for (state_key, state_cache) in &lock.state.caches {
557 if state_key != state_ptr {
558 continue
559 }
560
561 if !state_cache.state.removed.is_empty() {
563 rebuild = true;
564 break 'outer
565 }
566
567 for (key, value) in &state_cache.state.cache {
569 let key = blake3::hash(key);
570 let value = blake3::hash(value);
571 inserts.push((key, value))
572 }
573 break
574 }
575 }
576
577 if rebuild {
579 debug!(target: "blockchain::contractstoreoverlay::get_state_monotree", "Rebuilding monotree...");
581 inserts = vec![];
582 for state_ptr in state_pointers {
583 lock.open_tree(&state_ptr, false)?;
585
586 if state_ptr == state_monotree_ptr {
588 lock.clear(&state_ptr)?;
589 continue
590 }
591
592 for record in lock.iter(&state_ptr)? {
594 let (key, value) = record?;
595 let key = blake3::hash(&key);
596 let value = blake3::hash(&value);
597 inserts.push((key, value))
598 }
599 }
600 }
601
602 let state_monotree_db = SledOverlayDb::new(&mut lock, &state_monotree_ptr)?;
604 let mut state_monotree = Monotree::new(state_monotree_db);
605 let mut state_monotree_root =
606 if rebuild { None } else { state_monotree.get_headroot()? };
607 let state_monotree_root_str = match state_monotree_root {
608 Some(hash) => blake3::Hash::from(hash),
609 None => blake3::Hash::from(*EMPTY_HASH),
610 };
611 debug!(target: "blockchain::contractstoreoverlay::get_state_monotree", "Current root: {state_monotree_root_str}");
612
613 for (key, value) in &inserts {
615 debug!(target: "blockchain::contractstoreoverlay::get_state_monotree", "Inserting key {key} with value: {value}");
616 state_monotree_root = state_monotree.insert(
617 state_monotree_root.as_ref(),
618 key.as_bytes(),
619 value.as_bytes(),
620 )?;
621 }
622
623 state_monotree.set_headroot(state_monotree_root.as_ref());
625
626 let state_monotree_root = match state_monotree_root {
628 Some(hash) => hash,
629 None => *EMPTY_HASH,
630 };
631 debug!(target: "blockchain::contractstoreoverlay::get_state_monotree", "New root: {}", blake3::Hash::from(state_monotree_root));
632 root = tree.insert(root.as_ref(), &contract_id.to_bytes(), &state_monotree_root)?;
633 }
634
635 debug!(target: "blockchain::contractstoreoverlay::get_state_monotree", "Initializing wasm bincodes monotree...");
637 let mut wasm_monotree_root = None;
638 let wasm_monotree_db = MemoryDb::new();
639 let mut wasm_monotree = Monotree::new(wasm_monotree_db);
640 for record in lock.iter(SLED_BINCODE_TREE)? {
641 let (key, value) = record?;
642
643 if NATIVE_CONTRACT_IDS_BYTES.contains(&deserialize(&key)?) {
645 continue
646 }
647
648 let key = blake3::hash(&key);
650 let value = blake3::hash(&value);
651 debug!(target: "blockchain::contractstoreoverlay::get_state_monotree", "Inserting key {key} with value: {value}");
652 wasm_monotree_root = wasm_monotree.insert(
653 wasm_monotree_root.as_ref(),
654 key.as_bytes(),
655 value.as_bytes(),
656 )?;
657 }
658
659 let wasm_monotree_root = match wasm_monotree_root {
661 Some(hash) => hash,
662 None => *EMPTY_HASH,
663 };
664 debug!(target: "blockchain::contractstoreoverlay::get_state_monotree", "New root: {}", blake3::Hash::from(wasm_monotree_root));
665 root = tree.insert(
666 root.as_ref(),
667 blake3::hash(SLED_BINCODE_TREE).as_bytes(),
668 &wasm_monotree_root,
669 )?;
670 debug!(target: "blockchain::contractstoreoverlay::get_state_monotree", "New global root: {}", blake3::Hash::from(root.unwrap()));
671 tree.set_headroot(root.as_ref());
672
673 Ok(tree)
674 }
675
676 pub fn update_state_monotree(
683 &self,
684 diff: &SledDbOverlayStateDiff,
685 tree: &mut Monotree<MemoryDb>,
686 ) -> Result<()> {
687 if let Some((state_cache, _)) = diff.caches.get(SLED_CONTRACTS_TREE) {
690 if !state_cache.removed.is_empty() {
691 debug!(target: "blockchain::contractstoreoverlay::update_state_monotree", "Rebuilding global monotree...");
692 *tree = self.get_state_monotree()?;
693 return Ok(());
694 }
695 }
696
697 let mut lock = self.0.lock().unwrap();
699 debug!(target: "blockchain::contractstoreoverlay::update_state_monotree", "Retrieving contracts updates...");
700
701 let mut contracts_updates = BTreeMap::new();
704 if let Some((state_cache, _)) = diff.caches.get(SLED_CONTRACTS_TREES_TREE) {
705 for contract_id_bytes in state_cache.removed.values() {
707 contracts_updates.insert(contract_id_bytes.clone(), (true, vec![]));
708 }
709 }
710
711 for (state_key, state_cache) in &diff.caches {
713 if lock.state.protected_tree_names.contains(state_key) {
717 continue
718 }
719
720 let state_key = deserialize(state_key)?;
722
723 if NATIVE_CONTRACT_ZKAS_DB_NAMES.contains(&state_key) {
725 continue
726 }
727
728 let Some(contract_id_bytes) = lock.get(SLED_CONTRACTS_TREES_TREE, &state_key)? else {
730 return Err(Error::ContractStateNotFound)
731 };
732 let contract_id: ContractId = deserialize(&contract_id_bytes)?;
733
734 let state_monotree_ptr = contract_id.hash_state_id(SMART_CONTRACT_MONOTREE_DB_NAME);
736 if state_monotree_ptr == state_key {
737 continue
738 }
739
740 let (rebuild, mut inserts) = match contracts_updates.get(&contract_id_bytes) {
742 Some(r) => r.clone(),
743 None => (false, vec![]),
744 };
745
746 if rebuild {
749 continue
750 }
751
752 if !state_cache.0.removed.is_empty() {
755 contracts_updates.insert(contract_id_bytes, (true, vec![]));
756 continue
757 }
758
759 for (key, (_, value)) in &state_cache.0.cache {
761 let key = blake3::hash(key);
762 let value = blake3::hash(value);
763 inserts.push((key, value))
764 }
765 contracts_updates.insert(contract_id_bytes, (rebuild, inserts));
766 }
767
768 let mut root = tree.get_headroot()?;
770 let root_str = match root {
771 Some(hash) => blake3::Hash::from(hash),
772 None => blake3::Hash::from(*EMPTY_HASH),
773 };
774 debug!(target: "blockchain::contractstoreoverlay::update_state_monotree", "Updating global monotree with root: {root_str}");
775
776 for (contract_id_bytes, (rebuild, mut inserts)) in contracts_updates {
778 let contract_id: ContractId = deserialize(&contract_id_bytes)?;
779 let state_monotree_ptr = contract_id.hash_state_id(SMART_CONTRACT_MONOTREE_DB_NAME);
780 debug!(target: "blockchain::contractstoreoverlay::update_state_monotree", "Updating monotree for contract: {contract_id}");
781
782 if rebuild {
784 let state_pointers = lock.get(SLED_CONTRACTS_TREE, &contract_id_bytes)?.unwrap();
786 let mut state_pointers: Vec<[u8; 32]> = deserialize(&state_pointers)?;
787
788 if NATIVE_CONTRACT_IDS_BYTES.contains(&contract_id.to_bytes()) {
790 state_pointers.retain(|ptr| !NATIVE_CONTRACT_ZKAS_DB_NAMES.contains(ptr));
791 }
792
793 debug!(target: "blockchain::contractstoreoverlay::update_state_monotree", "Rebuilding monotree...");
795 for state_ptr in state_pointers {
796 lock.open_tree(&state_ptr, false)?;
798
799 if state_ptr == state_monotree_ptr {
801 lock.clear(&state_ptr)?;
802 continue
803 }
804
805 for record in lock.iter(&state_ptr)? {
807 let (key, value) = record?;
808 let key = blake3::hash(&key);
809 let value = blake3::hash(&value);
810 inserts.push((key, value))
811 }
812 }
813 }
814
815 let state_monotree_db = SledOverlayDb::new(&mut lock, &state_monotree_ptr)?;
817 let mut state_monotree = Monotree::new(state_monotree_db);
818 let mut state_monotree_root =
819 if rebuild { None } else { state_monotree.get_headroot()? };
820 let state_monotree_root_str = match state_monotree_root {
821 Some(hash) => blake3::Hash::from(hash),
822 None => blake3::Hash::from(*EMPTY_HASH),
823 };
824 debug!(target: "blockchain::contractstoreoverlay::update_state_monotree", "Current root: {state_monotree_root_str}");
825
826 for (key, value) in &inserts {
828 debug!(target: "blockchain::contractstoreoverlay::update_state_monotree", "Inserting key {key} with value: {value}");
829 state_monotree_root = state_monotree.insert(
830 state_monotree_root.as_ref(),
831 key.as_bytes(),
832 value.as_bytes(),
833 )?;
834 }
835
836 state_monotree.set_headroot(state_monotree_root.as_ref());
838
839 let state_monotree_root = match state_monotree_root {
841 Some(hash) => hash,
842 None => *EMPTY_HASH,
843 };
844 debug!(target: "blockchain::contractstoreoverlay::update_state_monotree", "New root: {}", blake3::Hash::from(state_monotree_root));
845 root = tree.insert(root.as_ref(), &contract_id.to_bytes(), &state_monotree_root)?;
846 }
847
848 let Some((state_cache, _)) = diff.caches.get(SLED_CONTRACTS_TREES_TREE) else {
850 debug!(target: "blockchain::contractstoreoverlay::update_state_monotree", "New global root: {}", blake3::Hash::from(root.unwrap()));
851 tree.set_headroot(root.as_ref());
852 return Ok(())
853 };
854
855 if state_cache.cache.is_empty() && state_cache.removed.is_empty() {
857 debug!(target: "blockchain::contractstoreoverlay::update_state_monotree", "New global root: {}", blake3::Hash::from(root.unwrap()));
858 tree.set_headroot(root.as_ref());
859 return Ok(())
860 }
861
862 debug!(target: "blockchain::contractstoreoverlay::update_state_monotree", "Updating wasm bincodes monotree...");
864 let mut wasm_monotree_root = None;
865 let wasm_monotree_db = MemoryDb::new();
866 let mut wasm_monotree = Monotree::new(wasm_monotree_db);
867 for record in lock.iter(SLED_BINCODE_TREE)? {
868 let (key, value) = record?;
869
870 if NATIVE_CONTRACT_IDS_BYTES.contains(&deserialize(&key)?) {
872 continue
873 }
874
875 let key = blake3::hash(&key);
877 let value = blake3::hash(&value);
878 debug!(target: "blockchain::contractstoreoverlay::update_state_monotree", "Inserting key {key} with value: {value}");
879 wasm_monotree_root = wasm_monotree.insert(
880 wasm_monotree_root.as_ref(),
881 key.as_bytes(),
882 value.as_bytes(),
883 )?;
884 }
885
886 let wasm_monotree_root = match wasm_monotree_root {
888 Some(hash) => hash,
889 None => *EMPTY_HASH,
890 };
891 debug!(target: "blockchain::contractstoreoverlay::update_state_monotree", "New root: {}", blake3::Hash::from(wasm_monotree_root));
892 root = tree.insert(
893 root.as_ref(),
894 blake3::hash(SLED_BINCODE_TREE).as_bytes(),
895 &wasm_monotree_root,
896 )?;
897 debug!(target: "blockchain::contractstoreoverlay::update_state_monotree", "New global root: {}", blake3::Hash::from(root.unwrap()));
898 tree.set_headroot(root.as_ref());
899
900 Ok(())
901 }
902}