smt.rs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2024 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use std::io::Cursor;
  19. use darkfi_sdk::crypto::{
  20. pasta_prelude::*,
  21. smt::{PoseidonFp, SparseMerkleTree, StorageAdapter, EMPTY_NODES_FP, SMT_FP_DEPTH},
  22. };
  23. use darkfi_serial::{serialize, Decodable, Encodable, WriteExt};
  24. use halo2_proofs::pasta::pallas;
  25. use log::{debug, error, warn};
  26. use num_bigint::BigUint;
  27. use wasmer::{FunctionEnvMut, WasmPtr};
  28. use super::acl::acl_allow;
  29. use crate::runtime::vm_runtime::{ContractSection, Env};
  30. pub struct SledStorage<'a> {
  31. overlay: &'a mut sled_overlay::SledDbOverlay,
  32. tree_key: &'a [u8],
  33. }
  34. impl<'a> StorageAdapter for SledStorage<'a> {
  35. type Value = pallas::Base;
  36. fn put(&mut self, key: BigUint, value: pallas::Base) -> bool {
  37. if self.overlay.insert(self.tree_key, &key.to_bytes_le(), &value.to_repr()).is_err() {
  38. error!(
  39. target: "runtime::smt::SledStorage::put",
  40. "[WASM] sparse_merkle_insert_batch(): inserting key {:?}, value {:?} into DB tree: {:?}",
  41. key, value, self.tree_key
  42. );
  43. return false
  44. }
  45. true
  46. }
  47. fn get(&self, key: &BigUint) -> Option<pallas::Base> {
  48. let Ok(value) = self.overlay.get(self.tree_key, &key.to_bytes_le()) else {
  49. error!(
  50. target: "runtime::smt::SledStorage::get",
  51. "[WASM] sparse_merkle_insert_batch(): fetching key {:?} from DB tree: {:?}",
  52. key, self.tree_key
  53. );
  54. return None
  55. };
  56. let value = value?;
  57. let mut repr = [0; 32];
  58. repr.copy_from_slice(&value);
  59. let value = pallas::Base::from_repr(repr);
  60. if value.is_none().into() {
  61. None
  62. } else {
  63. Some(value.unwrap())
  64. }
  65. }
  66. }
  67. pub(crate) fn sparse_merkle_insert_batch(
  68. mut ctx: FunctionEnvMut<Env>,
  69. ptr: WasmPtr<u8>,
  70. len: u32,
  71. ) -> i64 {
  72. let (env, mut store) = ctx.data_and_store_mut();
  73. let cid = env.contract_id;
  74. // Enforce function ACL
  75. if let Err(e) = acl_allow(env, &[ContractSection::Update]) {
  76. error!(
  77. target: "runtime::smt::sparse_merkle_insert_batch",
  78. "[WASM] [{}] sparse_merkle_insert_batch(): Called in unauthorized section: {}", cid, e,
  79. );
  80. return darkfi_sdk::error::CALLER_ACCESS_DENIED
  81. }
  82. // Subtract used gas. Here we count the length read from the memory slice.
  83. // This makes calling the function which returns early have some (small) cost.
  84. env.subtract_gas(&mut store, len as u64);
  85. let memory_view = env.memory_view(&store);
  86. let Ok(mem_slice) = ptr.slice(&memory_view, len) else {
  87. error!(
  88. target: "runtime::smt::sparse_merkle_insert_batch",
  89. "[WASM] [{}] sparse_merkle_insert_batch(): Failed to make slice from ptr", cid,
  90. );
  91. return darkfi_sdk::error::INTERNAL_ERROR
  92. };
  93. let mut buf = vec![0_u8; len as usize];
  94. if let Err(e) = mem_slice.read_slice(&mut buf) {
  95. error!(
  96. target: "runtime::smt::sparse_merkle_insert_batch",
  97. "[WASM] [{}] sparse_merkle_insert_batch(): Failed to read from memory slice: {}", cid, e,
  98. );
  99. return darkfi_sdk::error::INTERNAL_ERROR
  100. };
  101. // The buffer should deserialize into:
  102. // - db_smt
  103. // - db_roots
  104. // - nullifiers (as Vec<pallas::Base>)
  105. let mut buf_reader = Cursor::new(buf);
  106. let db_info_index: u32 = match Decodable::decode(&mut buf_reader) {
  107. Ok(v) => v,
  108. Err(e) => {
  109. error!(
  110. target: "runtime::smt::sparse_merkle_insert_batch",
  111. "[WASM] [{}] sparse_merkle_insert_batch(): Failed to decode db_info DbHandle: {}", cid, e,
  112. );
  113. return darkfi_sdk::error::INTERNAL_ERROR
  114. }
  115. };
  116. let db_info_index = db_info_index as usize;
  117. let db_smt_index: u32 = match Decodable::decode(&mut buf_reader) {
  118. Ok(v) => v,
  119. Err(e) => {
  120. error!(
  121. target: "runtime::smt::sparse_merkle_insert_batch",
  122. "[WASM] [{}] sparse_merkle_insert_batch(): Failed to decode db_smt DbHandle: {}", cid, e,
  123. );
  124. return darkfi_sdk::error::INTERNAL_ERROR
  125. }
  126. };
  127. let db_smt_index = db_smt_index as usize;
  128. let db_roots_index: u32 = match Decodable::decode(&mut buf_reader) {
  129. Ok(v) => v,
  130. Err(e) => {
  131. error!(
  132. target: "runtime::smt::sparse_merkle_insert_batch",
  133. "[WASM] [{}] sparse_merkle_insert_batch(): Failed to decode db_roots DbHandle: {}", cid, e,
  134. );
  135. return darkfi_sdk::error::INTERNAL_ERROR
  136. }
  137. };
  138. let db_roots_index = db_roots_index as usize;
  139. let db_handles = env.db_handles.borrow();
  140. let n_dbs = db_handles.len();
  141. if n_dbs <= db_info_index || n_dbs <= db_smt_index || n_dbs <= db_roots_index {
  142. error!(
  143. target: "runtime::smt::sparse_merkle_insert_batch",
  144. "[WASM] [{}] sparse_merkle_insert_batch(): Requested DbHandle that is out of bounds", cid,
  145. );
  146. return darkfi_sdk::error::INTERNAL_ERROR
  147. }
  148. let db_info = &db_handles[db_info_index];
  149. let db_smt = &db_handles[db_smt_index];
  150. let db_roots = &db_handles[db_roots_index];
  151. // Make sure that the contract owns the dbs it wants to write to
  152. if db_info.contract_id != env.contract_id ||
  153. db_smt.contract_id != env.contract_id ||
  154. db_roots.contract_id != env.contract_id
  155. {
  156. error!(
  157. target: "runtime::smt::sparse_merkle_insert_batch",
  158. "[WASM] [{}] sparse_merkle_insert_batch(): Unauthorized to write to DbHandle", cid,
  159. );
  160. return darkfi_sdk::error::CALLER_ACCESS_DENIED
  161. }
  162. // This `key` represents the sled key in info where the latest root is
  163. let root_key: Vec<u8> = match Decodable::decode(&mut buf_reader) {
  164. Ok(v) => v,
  165. Err(e) => {
  166. error!(
  167. target: "runtime::smt::sparse_merkle_insert_batch",
  168. "[WASM] [{}] sparse_merkle_insert_batch(): Failed to decode key vec: {}", cid, e,
  169. );
  170. return darkfi_sdk::error::INTERNAL_ERROR
  171. }
  172. };
  173. // This `nullifier` represents the leaf we're adding to the Merkle tree
  174. let nullifiers: Vec<pallas::Base> = match Decodable::decode(&mut buf_reader) {
  175. Ok(v) => v,
  176. Err(e) => {
  177. error!(
  178. target: "runtime::smt::sparse_merkle_insert_batch",
  179. "[WASM] [{}] sparse_merkle_insert_batch(): Failed to decode pallas::Base: {}", cid, e,
  180. );
  181. return darkfi_sdk::error::INTERNAL_ERROR
  182. }
  183. };
  184. // Nothing to do so just return here
  185. if nullifiers.is_empty() {
  186. warn!(
  187. target: "runtime::smt::sparse_merkle_insert_batch",
  188. "[WASM] [{}] sparse_merkle_insert_batch(): Nothing to add! Returning.", cid
  189. );
  190. return darkfi_sdk::entrypoint::SUCCESS
  191. }
  192. // Make sure we've read the entire buffer
  193. if buf_reader.position() != (len as u64) {
  194. error!(
  195. target: "runtime::smt::sparse_merkle_insert_batch",
  196. "[WASM] [{}] sparse_merkle_insert_batch(): Mismatch between given length, and cursor length", cid,
  197. );
  198. return darkfi_sdk::error::INTERNAL_ERROR
  199. }
  200. let hasher = PoseidonFp::new();
  201. let leaves: Vec<_> = nullifiers.into_iter().map(|x| (x, x)).collect();
  202. // Used in gas calc
  203. let leaves_len = leaves.len();
  204. let lock = env.blockchain.lock().unwrap();
  205. let mut overlay = lock.overlay.lock().unwrap();
  206. let smt_store = SledStorage { overlay: &mut overlay, tree_key: &db_smt.tree };
  207. let mut smt = SparseMerkleTree::<
  208. SMT_FP_DEPTH,
  209. { SMT_FP_DEPTH + 1 },
  210. pallas::Base,
  211. PoseidonFp,
  212. SledStorage,
  213. >::new(smt_store, hasher, &EMPTY_NODES_FP);
  214. if let Err(e) = smt.insert_batch(leaves) {
  215. error!(
  216. target: "runtime::smt::sparse_merkle_insert_batch",
  217. "[WASM] [{}] sparse_merkle_insert_batch(): SMT failed to insert batch: {}", cid, e,
  218. );
  219. return darkfi_sdk::error::INTERNAL_ERROR
  220. };
  221. // Here we add the SMT root to our set of roots
  222. // Since each update to the tree is atomic, we only need to add the last root.
  223. let latest_root = smt.root();
  224. debug!(
  225. target: "runtime::smt::sparse_merkle_insert_batch",
  226. "[WASM] [{}] sparse_merkle_insert_batch(): Appending SMT root to db: {:?}", cid, latest_root,
  227. );
  228. let latest_root_data = serialize(&latest_root);
  229. assert_eq!(latest_root_data.len(), 32);
  230. let blockheight_data = serialize(&(env.verifying_block_height as u32));
  231. // This is hardcoded but should not be
  232. let tx_idx: u16 = 0;
  233. let call_idx: u16 = 0;
  234. assert_eq!(blockheight_data.len(), 4);
  235. // Little-endian
  236. assert_eq!(blockheight_data[3], 0);
  237. let mut value_data = Vec::with_capacity(7);
  238. value_data.write_slice(&blockheight_data[..3]).expect("Unable to serialize blockheight data");
  239. tx_idx.encode(&mut value_data).expect("Unable to serialize tx_id");
  240. call_idx.encode(&mut value_data).expect("Unable to serialize call_idx");
  241. assert_eq!(value_data.len(), 7);
  242. if overlay.insert(&db_roots.tree, &latest_root_data, &value_data).is_err() {
  243. error!(
  244. target: "runtime::smt::sparse_merkle_insert_batch",
  245. "[WASM] [{}] sparse_merkle_insert_batch(): Couldn't insert to db_roots tree", cid,
  246. );
  247. return darkfi_sdk::error::INTERNAL_ERROR
  248. }
  249. // Write a pointer to the latest known root
  250. debug!(
  251. target: "runtime::smt::sparse_merkle_insert_batch",
  252. "[WASM] [{}] sparse_merkle_insert_batch(): Replacing latest SMT root pointer", cid,
  253. );
  254. if overlay.insert(&db_info.tree, &root_key, &latest_root_data).is_err() {
  255. error!(
  256. target: "runtime::smt::sparse_merkle_insert_batch",
  257. "[WASM] [{}] sparse_merkle_insert_batch(): Couldn't insert latest root to db_info tree", cid,
  258. );
  259. return darkfi_sdk::error::INTERNAL_ERROR
  260. }
  261. // Subtract used gas.
  262. // Here we count:
  263. // * The number of nullifiers we inserted into the DB
  264. drop(overlay);
  265. drop(lock);
  266. drop(db_handles);
  267. let spent_gas = leaves_len * 32;
  268. env.subtract_gas(&mut store, spent_gas as u64);
  269. darkfi_sdk::entrypoint::SUCCESS
  270. }