1use ethrex_rlp::encode::RLPEncode;
2
3use crate::{Nibbles, Node, error::TrieError};
4use alloc::collections::BTreeMap;
5use alloc::sync::Arc;
6#[cfg(not(feature = "std"))]
7use alloc::vec::Vec;
8
9#[cfg(feature = "std")]
14use crate::Trie;
15#[cfg(feature = "std")]
16use ethereum_types::H256;
17#[cfg(not(feature = "std"))]
18use spin::Mutex;
19#[cfg(feature = "std")]
20use std::sync::Mutex;
21
22pub type NodeMap = Arc<Mutex<BTreeMap<Vec<u8>, Vec<u8>>>>;
24
25#[cfg(feature = "std")]
27type NodeMapGuard<'a> = std::sync::MutexGuard<'a, BTreeMap<Vec<u8>, Vec<u8>>>;
28#[cfg(not(feature = "std"))]
29type NodeMapGuard<'a> = spin::MutexGuard<'a, BTreeMap<Vec<u8>, Vec<u8>>>;
30
31pub trait TrieDB: Send + Sync {
32 fn get(&self, key: Nibbles) -> Result<Option<Vec<u8>>, TrieError>;
33 fn put_batch(&self, key_values: Vec<(Nibbles, Vec<u8>)>) -> Result<(), TrieError>;
34 fn put_batch_no_alloc(&self, key_values: &[(Nibbles, Node)]) -> Result<(), TrieError> {
36 self.put_batch(
37 key_values
38 .iter()
39 .map(|node| (node.0.clone(), node.1.encode_to_vec()))
40 .collect(),
41 )
42 }
43 fn put(&self, key: Nibbles, value: Vec<u8>) -> Result<(), TrieError> {
44 self.put_batch(vec![(key, value)])
45 }
46 fn commit(&self) -> Result<(), TrieError> {
49 Ok(())
50 }
51
52 fn flatkeyvalue_computed(&self, _key: Nibbles) -> bool {
53 false
54 }
55}
56
57#[derive(Default)]
60pub struct InMemoryTrieDB {
61 inner: NodeMap,
62 prefix: Option<Nibbles>,
63}
64
65impl InMemoryTrieDB {
66 pub const fn new(map: NodeMap) -> Self {
67 Self {
68 inner: map,
69 prefix: None,
70 }
71 }
72
73 pub const fn new_with_prefix(map: NodeMap, prefix: Nibbles) -> Self {
74 Self {
75 inner: map,
76 prefix: Some(prefix),
77 }
78 }
79
80 pub fn new_empty() -> Self {
81 Self {
82 inner: Default::default(),
83 prefix: None,
84 }
85 }
86
87 fn apply_prefix(&self, path: Nibbles) -> Nibbles {
88 match &self.prefix {
89 Some(prefix) => prefix.concat(&path),
90 None => path,
91 }
92 }
93
94 fn lock_inner(&self) -> Result<NodeMapGuard<'_>, TrieError> {
97 #[cfg(feature = "std")]
98 let guard = self.inner.lock().map_err(|_| TrieError::LockError)?;
99 #[cfg(not(feature = "std"))]
100 let guard = self.inner.lock();
101 Ok(guard)
102 }
103
104 pub fn inner(&self) -> NodeMap {
106 Arc::clone(&self.inner)
107 }
108}
109
110#[cfg(feature = "std")]
113impl InMemoryTrieDB {
114 pub fn from_nodes(
116 root_hash: H256,
117 state_nodes: &BTreeMap<H256, Node>,
118 ) -> Result<Self, TrieError> {
119 let mut embedded_root = Trie::get_embedded_root(state_nodes, root_hash)?;
120 let mut hashed_nodes = vec![];
121 embedded_root.commit(
122 Nibbles::default(),
123 &mut hashed_nodes,
124 ðrex_crypto::NativeCrypto,
125 );
126
127 let hashed_nodes = hashed_nodes
128 .into_iter()
129 .map(|(k, v)| (k.into_vec(), v))
130 .collect();
131
132 let in_memory_trie = Arc::new(Mutex::new(hashed_nodes));
133 Ok(Self::new(in_memory_trie))
134 }
135}
136
137impl TrieDB for InMemoryTrieDB {
138 fn get(&self, key: Nibbles) -> Result<Option<Vec<u8>>, TrieError> {
139 Ok(self
140 .lock_inner()?
141 .get(self.apply_prefix(key).as_ref())
142 .cloned())
143 }
144
145 fn put_batch(&self, key_values: Vec<(Nibbles, Vec<u8>)>) -> Result<(), TrieError> {
146 let mut db = self.lock_inner()?;
147
148 for (key, value) in key_values {
149 let prefixed_key = self.apply_prefix(key);
150 db.insert(prefixed_key.into_vec(), value);
151 }
152
153 Ok(())
154 }
155}