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 multi_get(&self, keys: &[Nibbles]) -> Vec<Result<Option<Vec<u8>>, TrieError>> {
38 keys.iter().map(|k| self.get(k.clone())).collect()
39 }
40 fn put_batch(&self, key_values: Vec<(Nibbles, Vec<u8>)>) -> Result<(), TrieError>;
41 fn put_batch_no_alloc(&self, key_values: &[(Nibbles, Node)]) -> Result<(), TrieError> {
43 self.put_batch(
44 key_values
45 .iter()
46 .map(|node| (node.0.clone(), node.1.encode_to_vec()))
47 .collect(),
48 )
49 }
50 fn put(&self, key: Nibbles, value: Vec<u8>) -> Result<(), TrieError> {
51 self.put_batch(vec![(key, value)])
52 }
53 fn commit(&self) -> Result<(), TrieError> {
56 Ok(())
57 }
58
59 fn flatkeyvalue_computed(&self, _key: Nibbles) -> bool {
60 false
61 }
62}
63
64#[derive(Default)]
67pub struct InMemoryTrieDB {
68 inner: NodeMap,
69 prefix: Option<Nibbles>,
70}
71
72impl InMemoryTrieDB {
73 pub const fn new(map: NodeMap) -> Self {
74 Self {
75 inner: map,
76 prefix: None,
77 }
78 }
79
80 pub const fn new_with_prefix(map: NodeMap, prefix: Nibbles) -> Self {
81 Self {
82 inner: map,
83 prefix: Some(prefix),
84 }
85 }
86
87 pub fn new_empty() -> Self {
88 Self {
89 inner: Default::default(),
90 prefix: None,
91 }
92 }
93
94 fn apply_prefix(&self, path: Nibbles) -> Nibbles {
95 match &self.prefix {
96 Some(prefix) => prefix.concat(&path),
97 None => path,
98 }
99 }
100
101 fn lock_inner(&self) -> Result<NodeMapGuard<'_>, TrieError> {
104 #[cfg(feature = "std")]
105 let guard = self.inner.lock().map_err(|_| TrieError::LockError)?;
106 #[cfg(not(feature = "std"))]
107 let guard = self.inner.lock();
108 Ok(guard)
109 }
110
111 pub fn inner(&self) -> NodeMap {
113 Arc::clone(&self.inner)
114 }
115}
116
117#[cfg(feature = "std")]
120impl InMemoryTrieDB {
121 pub fn from_nodes(
123 root_hash: H256,
124 state_nodes: &BTreeMap<H256, Node>,
125 ) -> Result<Self, TrieError> {
126 let mut embedded_root = Trie::get_embedded_root(state_nodes, root_hash)?;
127 let mut hashed_nodes = vec![];
128 embedded_root.commit(
129 Nibbles::default(),
130 &mut hashed_nodes,
131 ðrex_crypto::NativeCrypto,
132 );
133
134 let hashed_nodes = hashed_nodes
135 .into_iter()
136 .map(|(k, v)| (k.into_vec(), v))
137 .collect();
138
139 let in_memory_trie = Arc::new(Mutex::new(hashed_nodes));
140 Ok(Self::new(in_memory_trie))
141 }
142}
143
144impl TrieDB for InMemoryTrieDB {
145 fn get(&self, key: Nibbles) -> Result<Option<Vec<u8>>, TrieError> {
146 Ok(self
147 .lock_inner()?
148 .get(self.apply_prefix(key).as_ref())
149 .cloned())
150 }
151
152 fn put_batch(&self, key_values: Vec<(Nibbles, Vec<u8>)>) -> Result<(), TrieError> {
153 let mut db = self.lock_inner()?;
154
155 for (key, value) in key_values {
156 let prefixed_key = self.apply_prefix(key);
157 db.insert(prefixed_key.into_vec(), value);
158 }
159
160 Ok(())
161 }
162}