merkle.rs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  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::{MerkleNode, MerkleTree};
  20. use darkfi_serial::{serialize, Decodable, Encodable, WriteExt};
  21. use log::{debug, error, warn};
  22. use wasmer::{FunctionEnvMut, WasmPtr};
  23. use super::acl::acl_allow;
  24. use crate::runtime::vm_runtime::{ContractSection, Env};
  25. /// Adds data to merkle tree. The tree, database connection, and new data to add is
  26. /// read from `ptr` at offset specified by `len`.
  27. /// Returns `0` on success; otherwise, returns an error-code corresponding to a
  28. /// [`ContractError`] (defined in the SDK).
  29. /// See also the method `merkle_add` in `sdk/src/merkle.rs`.
  30. pub(crate) fn merkle_add(mut ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, len: u32) -> i64 {
  31. let (env, mut store) = ctx.data_and_store_mut();
  32. let cid = env.contract_id;
  33. // Enforce function ACL
  34. if let Err(e) = acl_allow(env, &[ContractSection::Update]) {
  35. error!(
  36. target: "runtime::merkle::merkle_add",
  37. "[WASM] [{}] merkle_add(): Called in unauthorized section: {}", cid, e,
  38. );
  39. return darkfi_sdk::error::CALLER_ACCESS_DENIED
  40. }
  41. // Subtract used gas. Here we count the length read from the memory slice.
  42. // This makes calling the function which returns early have some (small) cost.
  43. env.subtract_gas(&mut store, len as u64);
  44. let memory_view = env.memory_view(&store);
  45. let Ok(mem_slice) = ptr.slice(&memory_view, len) else {
  46. error!(
  47. target: "runtime::merkle::merkle_add",
  48. "[WASM] [{}] merkle_add(): Failed to make slice from ptr", cid,
  49. );
  50. return darkfi_sdk::error::INTERNAL_ERROR
  51. };
  52. let mut buf = vec![0_u8; len as usize];
  53. if let Err(e) = mem_slice.read_slice(&mut buf) {
  54. error!(
  55. target: "runtime::merkle::merkle_add",
  56. "[WASM] [{}] merkle_add(): Failed to read from memory slice: {}", cid, e,
  57. );
  58. return darkfi_sdk::error::INTERNAL_ERROR
  59. };
  60. // The buffer should deserialize into:
  61. // - db_info
  62. // - db_roots
  63. // - root_key (as Vec<u8>) (key being the name of the sled key in info_db where the latest root is)
  64. // - tree_key (as Vec<u8>) (key being the name of the sled key in info_db where the Merkle tree is)
  65. // - coins (as Vec<MerkleNode>) (the coins being added into the Merkle tree)
  66. let mut buf_reader = Cursor::new(buf);
  67. // FIXME: There's a type DbHandle=u32, but this should maybe be renamed
  68. let db_info_index: u32 = match Decodable::decode(&mut buf_reader) {
  69. Ok(v) => v,
  70. Err(e) => {
  71. error!(
  72. target: "runtime::merkle::merkle_add",
  73. "[WASM] [{}] merkle_add(): Failed to decode db_info DbHandle: {}", cid, e,
  74. );
  75. return darkfi_sdk::error::INTERNAL_ERROR
  76. }
  77. };
  78. let db_info_index = db_info_index as usize;
  79. let db_roots_index: u32 = match Decodable::decode(&mut buf_reader) {
  80. Ok(v) => v,
  81. Err(e) => {
  82. error!(
  83. target: "runtime::merkle::merkle_add",
  84. "[WASM] [{}] merkle_add(): Failed to decode db_roots DbHandle: {}", cid, e,
  85. );
  86. return darkfi_sdk::error::INTERNAL_ERROR
  87. }
  88. };
  89. let db_roots_index = db_roots_index as usize;
  90. let db_handles = env.db_handles.borrow();
  91. let n_dbs = db_handles.len();
  92. if n_dbs <= db_info_index || n_dbs <= db_roots_index {
  93. error!(
  94. target: "runtime::merkle::merkle_add",
  95. "[WASM] [{}] merkle_add(): Requested DbHandle that is out of bounds", cid,
  96. );
  97. return darkfi_sdk::error::INTERNAL_ERROR
  98. }
  99. let db_info = &db_handles[db_info_index];
  100. let db_roots = &db_handles[db_roots_index];
  101. // Make sure that the contract owns the dbs it wants to write to
  102. if db_info.contract_id != env.contract_id || db_roots.contract_id != env.contract_id {
  103. error!(
  104. target: "runtime::merkle::merkle_add",
  105. "[WASM] [{}] merkle_add(): Unauthorized to write to DbHandle", cid,
  106. );
  107. return darkfi_sdk::error::CALLER_ACCESS_DENIED
  108. }
  109. // This `key` represents the sled key in info where the latest root is
  110. let root_key: Vec<u8> = match Decodable::decode(&mut buf_reader) {
  111. Ok(v) => v,
  112. Err(e) => {
  113. error!(
  114. target: "runtime::merkle::merkle_add",
  115. "[WASM] [{}] merkle_add(): Failed to decode key vec: {}", cid, e,
  116. );
  117. return darkfi_sdk::error::INTERNAL_ERROR
  118. }
  119. };
  120. // This `key` represents the sled key in info where the Merkle tree is
  121. let tree_key: Vec<u8> = match Decodable::decode(&mut buf_reader) {
  122. Ok(v) => v,
  123. Err(e) => {
  124. error!(
  125. target: "runtime::merkle::merkle_add",
  126. "[WASM] [{}] merkle_add(): Failed to decode key vec: {}", cid, e,
  127. );
  128. return darkfi_sdk::error::INTERNAL_ERROR
  129. }
  130. };
  131. // This `coin` represents the leaf we're adding to the Merkle tree
  132. let coins: Vec<MerkleNode> = match Decodable::decode(&mut buf_reader) {
  133. Ok(v) => v,
  134. Err(e) => {
  135. error!(
  136. target: "runtime::merkle::merkle_add",
  137. "[WASM] [{}] merkle_add(): Failed to decode MerkleNode: {}", cid, e,
  138. );
  139. return darkfi_sdk::error::INTERNAL_ERROR
  140. }
  141. };
  142. // Nothing to do so just return here
  143. if coins.is_empty() {
  144. warn!(
  145. target: "runtime::merkle::merkle_add",
  146. "[WASM] [{}] merkle_add(): Nothing to add! Returning.", cid,
  147. );
  148. return darkfi_sdk::entrypoint::SUCCESS
  149. }
  150. // Make sure we've read the entire buffer
  151. if buf_reader.position() != (len as u64) {
  152. error!(
  153. target: "runtime::merkle::merkle_add",
  154. "[WASM] [{}] merkle_add(): Mismatch between given length, and cursor length", cid,
  155. );
  156. return darkfi_sdk::error::INTERNAL_ERROR
  157. }
  158. // Locking should happen for the entire duration of this fn. This is unsafe otherwise.
  159. let lock = env.blockchain.lock().unwrap();
  160. let mut overlay = lock.overlay.lock().unwrap();
  161. // Read the current tree
  162. let ret = match overlay.get(&db_info.tree, &tree_key) {
  163. Ok(v) => v,
  164. Err(e) => {
  165. error!(
  166. target: "runtime::merkle::merkle_add",
  167. "[WASM] [{}] merkle_add(): Internal error getting from tree: {}", cid, e,
  168. );
  169. return darkfi_sdk::error::INTERNAL_ERROR
  170. }
  171. };
  172. let Some(return_data) = ret else {
  173. error!(
  174. target: "runtime::merkle::merkle_add",
  175. "[WASM] [{}] merkle_add(): Return data is empty", cid,
  176. );
  177. return darkfi_sdk::error::INTERNAL_ERROR
  178. };
  179. debug!(
  180. target: "runtime::merkle::merkle_add",
  181. "Serialized tree: {} bytes",
  182. return_data.len()
  183. );
  184. debug!(
  185. target: "runtime::merkle::merkle_add",
  186. " {:02x?}",
  187. return_data
  188. );
  189. let mut decoder = Cursor::new(&return_data);
  190. let set_size: u32 = match Decodable::decode(&mut decoder) {
  191. Ok(v) => v,
  192. Err(e) => {
  193. error!(
  194. target: "runtime::merkle::merkle_add",
  195. "[WASM] [{}] merkle_add(): Unable to read set size: {}", cid, e,
  196. );
  197. return darkfi_sdk::error::INTERNAL_ERROR
  198. }
  199. };
  200. let mut tree: MerkleTree = match Decodable::decode(&mut decoder) {
  201. Ok(v) => v,
  202. Err(e) => {
  203. error!(
  204. target: "runtime::merkle::merkle_add",
  205. "[WASM] [{}] merkle_add(): Unable to deserialize Merkle tree: {}", cid, e,
  206. );
  207. return darkfi_sdk::error::INTERNAL_ERROR
  208. }
  209. };
  210. // Here we add the new coins into the tree.
  211. let mut new_roots = vec![];
  212. assert!(!coins.is_empty());
  213. for coin in coins {
  214. tree.append(coin);
  215. let Some(root) = tree.root(0) else {
  216. error!(
  217. target: "runtime::merkle::merkle_add",
  218. "[WASM] [{}] merkle_add(): Unable to read the root of tree", cid,
  219. );
  220. return darkfi_sdk::error::INTERNAL_ERROR
  221. };
  222. new_roots.push(root);
  223. }
  224. // And we serialize the tree back to bytes
  225. let mut tree_data = Vec::new();
  226. if tree_data.write_u32(set_size + new_roots.len() as u32).is_err() ||
  227. tree.encode(&mut tree_data).is_err()
  228. {
  229. error!(
  230. target: "runtime::merkle::merkle_add",
  231. "[WASM] [{}] merkle_add(): Couldn't reserialize modified tree", cid,
  232. );
  233. return darkfi_sdk::error::INTERNAL_ERROR
  234. }
  235. // Apply changes to overlay
  236. if overlay.insert(&db_info.tree, &tree_key, &tree_data).is_err() {
  237. error!(
  238. target: "runtime::merkle::merkle_add",
  239. "[WASM] [{}] merkle_add(): Couldn't insert to db_info tree", cid,
  240. );
  241. return darkfi_sdk::error::INTERNAL_ERROR
  242. }
  243. // Here we add the Merkle root to our set of roots
  244. // Since each update to the tree is atomic, we only need to add the last root.
  245. assert!(!new_roots.is_empty());
  246. let latest_root = new_roots.last().unwrap();
  247. debug!(
  248. target: "runtime::merkle::merkle_add",
  249. "[WASM] [{}] merkle_add(): Appending Merkle root to db: {:?}", cid, latest_root,
  250. );
  251. let latest_root_data = serialize(latest_root);
  252. assert_eq!(latest_root_data.len(), 32);
  253. let blockheight_data = serialize(&env.verifying_block_height);
  254. assert_eq!(blockheight_data.len(), 8);
  255. if overlay.insert(&db_roots.tree, &latest_root_data, &blockheight_data).is_err() {
  256. error!(
  257. target: "runtime::merkle::merkle_add",
  258. "[WASM] [{}] merkle_add(): Couldn't insert to db_roots tree", cid,
  259. );
  260. return darkfi_sdk::error::INTERNAL_ERROR
  261. }
  262. // Write a pointer to the latest known root
  263. debug!(
  264. target: "runtime::merkle::merkle_add",
  265. "[WASM] [{}] merkle_add(): Replacing latest Merkle root pointer", cid,
  266. );
  267. if overlay.insert(&db_info.tree, &root_key, &latest_root_data).is_err() {
  268. error!(
  269. target: "runtime::merkle::merkle_add",
  270. "[WASM] [{}] merkle_add(): Couldn't insert latest root to db_info tree", cid,
  271. );
  272. return darkfi_sdk::error::INTERNAL_ERROR
  273. }
  274. // Subtract used gas.
  275. // Here we count:
  276. // * The size of the Merkle tree we deserialized from the db.
  277. // * The size of the Merkle tree we serialized into the db.
  278. // * The size of the new Merkle roots we wrote into the db.
  279. drop(overlay);
  280. drop(lock);
  281. drop(db_handles);
  282. let spent_gas = return_data.len() + tree_data.len() + (new_roots.len() * 32);
  283. env.subtract_gas(&mut store, spent_gas as u64);
  284. darkfi_sdk::entrypoint::SUCCESS
  285. }