darkfi/runtime/import/
merkle.rs1use std::io::Cursor;
20
21use darkfi_sdk::{
22 crypto::{MerkleNode, MerkleTree},
23 hex::AsHex,
24 wasm,
25};
26use darkfi_serial::{serialize, Decodable, Encodable, WriteExt};
27use tracing::{debug, error};
28use wasmer::{FunctionEnvMut, WasmPtr};
29
30use super::acl::acl_allow;
31use crate::runtime::vm_runtime::{ContractSection, Env};
32
33pub(crate) fn merkle_add(mut ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, len: u32) -> i64 {
41 let (env, mut store) = ctx.data_and_store_mut();
42 let cid = env.contract_id;
43
44 if let Err(e) = acl_allow(env, &[ContractSection::Update]) {
46 error!(
47 target: "runtime::merkle::merkle_add",
48 "[WASM] [{cid}] merkle_add(): Called in unauthorized section: {e}"
49 );
50 return darkfi_sdk::error::CALLER_ACCESS_DENIED
51 }
52
53 env.subtract_gas(&mut store, 1);
56
57 env.subtract_gas(&mut store, 33 );
59
60 let memory_view = env.memory_view(&store);
61 let Ok(mem_slice) = ptr.slice(&memory_view, len) else {
62 error!(
63 target: "runtime::merkle::merkle_add",
64 "[WASM] [{cid}] merkle_add(): Failed to make slice from ptr"
65 );
66 return darkfi_sdk::error::INTERNAL_ERROR
67 };
68
69 let mut buf = vec![0_u8; len as usize];
70 if let Err(e) = mem_slice.read_slice(&mut buf) {
71 error!(
72 target: "runtime::merkle::merkle_add",
73 "[WASM] [{cid}] merkle_add(): Failed to read from memory slice: {e}"
74 );
75 return darkfi_sdk::error::INTERNAL_ERROR
76 };
77
78 let mut buf_reader = Cursor::new(buf);
85 let db_info_index: u32 = match Decodable::decode(&mut buf_reader) {
87 Ok(v) => v,
88 Err(e) => {
89 error!(
90 target: "runtime::merkle::merkle_add",
91 "[WASM] [{cid}] merkle_add(): Failed to decode db_info DbHandle: {e}"
92 );
93 return darkfi_sdk::error::INTERNAL_ERROR
94 }
95 };
96 let db_info_index = db_info_index as usize;
97
98 let db_roots_index: u32 = match Decodable::decode(&mut buf_reader) {
99 Ok(v) => v,
100 Err(e) => {
101 error!(
102 target: "runtime::merkle::merkle_add",
103 "[WASM] [{cid}] merkle_add(): Failed to decode db_roots DbHandle: {e}"
104 );
105 return darkfi_sdk::error::INTERNAL_ERROR
106 }
107 };
108 let db_roots_index = db_roots_index as usize;
109
110 let db_handles = env.db_handles.borrow();
111 let n_dbs = db_handles.len();
112
113 if n_dbs <= db_info_index || n_dbs <= db_roots_index {
114 error!(
115 target: "runtime::merkle::merkle_add",
116 "[WASM] [{cid}] merkle_add(): Requested DbHandle that is out of bounds"
117 );
118 return darkfi_sdk::error::INTERNAL_ERROR
119 }
120 let db_info = &db_handles[db_info_index];
121 let db_roots = &db_handles[db_roots_index];
122
123 if db_info.contract_id != env.contract_id || db_roots.contract_id != env.contract_id {
125 error!(
126 target: "runtime::merkle::merkle_add",
127 "[WASM] [{cid}] merkle_add(): Unauthorized to write to DbHandle"
128 );
129 return darkfi_sdk::error::CALLER_ACCESS_DENIED
130 }
131
132 let root_key: Vec<u8> = match Decodable::decode(&mut buf_reader) {
134 Ok(v) => v,
135 Err(e) => {
136 error!(
137 target: "runtime::merkle::merkle_add",
138 "[WASM] [{cid}] merkle_add(): Failed to decode key vec: {e}"
139 );
140 return darkfi_sdk::error::INTERNAL_ERROR
141 }
142 };
143
144 let tree_key: Vec<u8> = match Decodable::decode(&mut buf_reader) {
146 Ok(v) => v,
147 Err(e) => {
148 error!(
149 target: "runtime::merkle::merkle_add",
150 "[WASM] [{cid}] merkle_add(): Failed to decode key vec: {e}"
151 );
152 return darkfi_sdk::error::INTERNAL_ERROR
153 }
154 };
155
156 let coins: Vec<MerkleNode> = match Decodable::decode(&mut buf_reader) {
158 Ok(v) => v,
159 Err(e) => {
160 error!(
161 target: "runtime::merkle::merkle_add",
162 "[WASM] [{cid}] merkle_add(): Failed to decode MerkleNode: {e}"
163 );
164 return darkfi_sdk::error::INTERNAL_ERROR
165 }
166 };
167
168 if buf_reader.position() != (len as u64) {
170 error!(
171 target: "runtime::merkle::merkle_add",
172 "[WASM] [{cid}] merkle_add(): Mismatch between given length, and cursor length"
173 );
174 return darkfi_sdk::error::INTERNAL_ERROR
175 }
176
177 let lock = env.blockchain.lock().unwrap();
179 let mut overlay = lock.overlay.lock().unwrap();
180 let ret = match overlay.get(&db_info.tree, &tree_key) {
182 Ok(v) => v,
183 Err(e) => {
184 error!(
185 target: "runtime::merkle::merkle_add",
186 "[WASM] [{cid}] merkle_add(): Internal error getting from tree: {e}"
187 );
188 return darkfi_sdk::error::INTERNAL_ERROR
189 }
190 };
191
192 let Some(return_data) = ret else {
193 error!(
194 target: "runtime::merkle::merkle_add",
195 "[WASM] [{cid}] merkle_add(): Return data is empty"
196 );
197 return darkfi_sdk::error::INTERNAL_ERROR
198 };
199
200 debug!(
201 target: "runtime::merkle::merkle_add",
202 "Serialized tree: {} bytes",
203 return_data.len()
204 );
205 debug!(
206 target: "runtime::merkle::merkle_add",
207 " {}",
208 return_data.hex()
209 );
210
211 let mut decoder = Cursor::new(&return_data);
212 let set_size: u32 = match Decodable::decode(&mut decoder) {
213 Ok(v) => v,
214 Err(e) => {
215 error!(
216 target: "runtime::merkle::merkle_add",
217 "[WASM] [{cid}] merkle_add(): Unable to read set size: {e}"
218 );
219 return darkfi_sdk::error::INTERNAL_ERROR
220 }
221 };
222
223 let mut tree: MerkleTree = match Decodable::decode(&mut decoder) {
224 Ok(v) => v,
225 Err(e) => {
226 error!(
227 target: "runtime::merkle::merkle_add",
228 "[WASM] [{cid}] merkle_add(): Unable to deserialize Merkle tree: {e}"
229 );
230 return darkfi_sdk::error::INTERNAL_ERROR
231 }
232 };
233
234 let coins_len = coins.len();
236 for coin in coins {
237 tree.append(coin);
238 }
239
240 let mut tree_data = Vec::new();
242 if tree_data.write_u32(set_size + coins_len as u32).is_err() ||
243 tree.encode(&mut tree_data).is_err()
244 {
245 error!(
246 target: "runtime::merkle::merkle_add",
247 "[WASM] [{cid}] merkle_add(): Couldn't reserialize modified tree"
248 );
249 return darkfi_sdk::error::INTERNAL_ERROR
250 }
251
252 if overlay.insert(&db_info.tree, &tree_key, &tree_data).is_err() {
254 error!(
255 target: "runtime::merkle::merkle_add",
256 "[WASM] [{cid}] merkle_add(): Couldn't insert to db_info tree"
257 );
258 return darkfi_sdk::error::INTERNAL_ERROR
259 }
260
261 let Some(latest_root) = tree.root(0) else {
264 error!(
265 target: "runtime::merkle::merkle_add",
266 "[WASM] [{cid}] merkle_add(): Unable to read the root of tree"
267 );
268 return darkfi_sdk::error::INTERNAL_ERROR
269 };
270
271 debug!(
272 target: "runtime::merkle::merkle_add",
273 "[WASM] [{cid}] merkle_add(): Appending Merkle root to db: {latest_root:?}"
274 );
275 let latest_root_data = serialize(&latest_root);
276 assert_eq!(latest_root_data.len(), 32);
277
278 let mut value_data = Vec::with_capacity(32 + 1);
279 env.tx_hash.inner().encode(&mut value_data).expect("Unable to serialize tx_hash");
280 env.call_idx.encode(&mut value_data).expect("Unable to serialize call_idx");
281 assert_eq!(value_data.len(), 32 + 1);
282
283 if overlay.insert(&db_roots.tree, &latest_root_data, &value_data).is_err() {
284 error!(
285 target: "runtime::merkle::merkle_add",
286 "[WASM] [{cid}] merkle_add(): Couldn't insert to db_roots tree"
287 );
288 return darkfi_sdk::error::INTERNAL_ERROR
289 }
290
291 debug!(
293 target: "runtime::merkle::merkle_add",
294 "[WASM] [{cid}] merkle_add(): Replacing latest Merkle root pointer"
295 );
296
297 if overlay.insert(&db_info.tree, &root_key, &latest_root_data).is_err() {
298 error!(
299 target: "runtime::merkle::merkle_add",
300 "[WASM] [{cid}] merkle_add(): Couldn't insert latest root to db_info tree"
301 );
302 return darkfi_sdk::error::INTERNAL_ERROR
303 }
304
305 drop(overlay);
311 drop(lock);
312 drop(db_handles);
313 let spent_gas = coins_len * 32;
314 env.subtract_gas(&mut store, spent_gas as u64);
315
316 wasm::entrypoint::SUCCESS
317}