db.rs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2023 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::{
  20. crypto::ContractId,
  21. db::{
  22. CALLER_ACCESS_DENIED, DB_CONTAINS_KEY_FAILED, DB_DEL_FAILED, DB_GET_FAILED, DB_INIT_FAILED,
  23. DB_LOOKUP_FAILED, DB_SET_FAILED, DB_SUCCESS,
  24. },
  25. };
  26. use darkfi_serial::{deserialize, serialize, Decodable};
  27. use log::{debug, error, info};
  28. use wasmer::{FunctionEnvMut, WasmPtr};
  29. use crate::{
  30. runtime::vm_runtime::{ContractSection, Env, SMART_CONTRACT_ZKAS_DB_NAME},
  31. zk::{empty_witnesses, VerifyingKey, ZkCircuit},
  32. zkas::ZkBinary,
  33. };
  34. /// Internal wasm runtime API for sled trees
  35. pub struct DbHandle {
  36. pub contract_id: ContractId,
  37. pub tree: [u8; 32],
  38. }
  39. impl DbHandle {
  40. pub fn new(contract_id: ContractId, tree: [u8; 32]) -> Self {
  41. Self { contract_id, tree }
  42. }
  43. }
  44. /// Only deploy() can call this. Creates a new database instance for this contract.
  45. pub(crate) fn db_init(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, len: u32) -> i32 {
  46. let env = ctx.data();
  47. // Exit as soon as possible
  48. if env.contract_section != ContractSection::Deploy {
  49. error!(target: "runtime::db::db_init()", "db_init called in unauthorized section");
  50. return CALLER_ACCESS_DENIED
  51. }
  52. let memory_view = env.memory_view(&ctx);
  53. let contracts = &env.blockchain.lock().unwrap().contracts;
  54. let contract_id = &env.contract_id;
  55. let Ok(mem_slice) = ptr.slice(&memory_view, len) else {
  56. error!(target: "runtime::db::db_init()", "Failed to make slice from ptr");
  57. return DB_INIT_FAILED
  58. };
  59. let mut buf = vec![0_u8; len as usize];
  60. if let Err(e) = mem_slice.read_slice(&mut buf) {
  61. error!(target: "runtime::db::db_init()", "Failed to read from memory slice: {}", e);
  62. return DB_INIT_FAILED
  63. };
  64. let mut buf_reader = Cursor::new(buf);
  65. let cid: ContractId = match Decodable::decode(&mut buf_reader) {
  66. Ok(v) => v,
  67. Err(e) => {
  68. error!(target: "runtime::db::db_init()", "Failed to decode ContractId: {}", e);
  69. return DB_INIT_FAILED
  70. }
  71. };
  72. let db_name: String = match Decodable::decode(&mut buf_reader) {
  73. Ok(v) => v,
  74. Err(e) => {
  75. error!(target: "runtime::db::db_init()", "Failed to decode db_name: {}", e);
  76. return DB_INIT_FAILED
  77. }
  78. };
  79. // Disabled until cursor_remaining feature is available on master.
  80. // Then enable #![feature(cursor_remaining)] in src/lib.rs
  81. /*if !buf_reader.is_empty() {
  82. error!(target: "runtime::db::db_init()", "Trailing bytes in argument stream");
  83. return DB_DEL_FAILED
  84. }*/
  85. if db_name == SMART_CONTRACT_ZKAS_DB_NAME {
  86. error!(target: "runtime::db::db_init()", "Attempted to lookup zkas db");
  87. return CALLER_ACCESS_DENIED
  88. }
  89. if &cid != contract_id {
  90. error!(target: "runtime::db::db_init()", "Unauthorized ContractId for db_init");
  91. return CALLER_ACCESS_DENIED
  92. }
  93. let tree_handle = match contracts.init(&cid, &db_name) {
  94. Ok(v) => v,
  95. Err(e) => {
  96. error!(target: "runtime::db::db_init()", "Failed to init db: {}", e);
  97. return DB_INIT_FAILED
  98. }
  99. };
  100. // TODO: Make sure we don't duplicate the DbHandle in the vec.
  101. // It should behave like an ordered set.
  102. let mut db_handles = env.db_handles.borrow_mut();
  103. db_handles.push(DbHandle::new(cid, tree_handle));
  104. (db_handles.len() - 1) as i32
  105. }
  106. /// Everyone can call this. Lookups up a database handle from its name.
  107. pub(crate) fn db_lookup(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, len: u32) -> i32 {
  108. let env = ctx.data();
  109. match env.contract_section {
  110. ContractSection::Deploy |
  111. ContractSection::Exec |
  112. ContractSection::Update |
  113. ContractSection::Metadata => {
  114. // pass
  115. }
  116. _ => {
  117. error!(target: "runtime::db::db_lookup()", "db_lookup called in unauthorized section");
  118. return CALLER_ACCESS_DENIED
  119. }
  120. }
  121. let memory_view = env.memory_view(&ctx);
  122. let contracts = &env.blockchain.lock().unwrap().contracts;
  123. let Ok(mem_slice) = ptr.slice(&memory_view, len) else {
  124. error!(target: "runtime::db::db_lookup()", "Failed to make slice from ptr");
  125. return DB_LOOKUP_FAILED
  126. };
  127. let mut buf = vec![0_u8; len as usize];
  128. if let Err(e) = mem_slice.read_slice(&mut buf) {
  129. error!(target: "runtime::db::db_lookup()", "Failed to read from memory slice: {}", e);
  130. return DB_LOOKUP_FAILED
  131. };
  132. let mut buf_reader = Cursor::new(buf);
  133. let cid: ContractId = match Decodable::decode(&mut buf_reader) {
  134. Ok(v) => v,
  135. Err(e) => {
  136. error!(target: "runtime::db::db_lookup()", "Failed to decode ContractId: {}", e);
  137. return DB_LOOKUP_FAILED
  138. }
  139. };
  140. let db_name: String = match Decodable::decode(&mut buf_reader) {
  141. Ok(v) => v,
  142. Err(e) => {
  143. error!(target: "runtime::db::db_lookup()", "Failed to decode db_name: {}", e);
  144. return DB_LOOKUP_FAILED
  145. }
  146. };
  147. if db_name == SMART_CONTRACT_ZKAS_DB_NAME {
  148. error!(target: "runtime::db::db_lookup()", "Attempted to lookup zkas db");
  149. return CALLER_ACCESS_DENIED
  150. }
  151. // Disabled until cursor_remaining feature is available on master.
  152. // Then enable #![feature(cursor_remaining)] in src/lib.rs
  153. /*if !buf_reader.is_empty() {
  154. error!(target: "runtime::db::db_lookup()", "Trailing bytes in argument stream");
  155. return DB_LOOKUP_FAILED
  156. }*/
  157. let tree_handle = match contracts.lookup(&cid, &db_name) {
  158. Ok(v) => v,
  159. Err(_) => return DB_LOOKUP_FAILED,
  160. };
  161. // TODO: Make sure we don't duplicate the DbHandle in the vec.
  162. // It should behave like an ordered set.
  163. let mut db_handles = env.db_handles.borrow_mut();
  164. db_handles.push(DbHandle::new(cid, tree_handle));
  165. (db_handles.len() - 1) as i32
  166. }
  167. /// Set a value within the transaction.
  168. pub(crate) fn db_set(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, len: u32) -> i32 {
  169. let env = ctx.data();
  170. if env.contract_section != ContractSection::Deploy &&
  171. env.contract_section != ContractSection::Update
  172. {
  173. error!(target: "runtime::db::db_set()", "db_set called in unauthorized section");
  174. return CALLER_ACCESS_DENIED
  175. }
  176. let memory_view = env.memory_view(&ctx);
  177. let Ok(mem_slice) = ptr.slice(&memory_view, len) else {
  178. error!(target: "runtime::db::db_set()", "Failed to make slice from ptr");
  179. return DB_SET_FAILED
  180. };
  181. let mut buf = vec![0_u8; len as usize];
  182. if let Err(e) = mem_slice.read_slice(&mut buf) {
  183. error!(target: "runtime::db::db_set()", "Failed to read from memory slice: {}", e);
  184. return DB_SET_FAILED
  185. };
  186. let mut buf_reader = Cursor::new(buf);
  187. // FIXME: There's a type DbHandle=u32, but this should maybe be renamed
  188. let db_handle: u32 = match Decodable::decode(&mut buf_reader) {
  189. Ok(v) => v,
  190. Err(e) => {
  191. error!(target: "runtime::db::db_set()", "Failed to decode DbHandle: {}", e);
  192. return DB_SET_FAILED
  193. }
  194. };
  195. let db_handle = db_handle as usize;
  196. let key: Vec<u8> = match Decodable::decode(&mut buf_reader) {
  197. Ok(v) => v,
  198. Err(e) => {
  199. error!(target: "runtime::db::db_set()", "Failed to decode key vec: {}", e);
  200. return DB_SET_FAILED
  201. }
  202. };
  203. let value: Vec<u8> = match Decodable::decode(&mut buf_reader) {
  204. Ok(v) => v,
  205. Err(e) => {
  206. error!(target: "runtime::db::db_set()", "Failed to decode value vec: {}", e);
  207. return DB_SET_FAILED
  208. }
  209. };
  210. // Disabled until cursor_remaining feature is available on master.
  211. // Then enable #![feature(cursor_remaining)] in src/lib.rs
  212. /*if !buf_reader.is_empty() {
  213. error!(target: "runtime::db::db_set()", "Trailing bytes in argument stream");
  214. return DB_DEL_FAILED
  215. }*/
  216. let db_handles = env.db_handles.borrow();
  217. if db_handles.len() <= db_handle {
  218. error!(target: "runtime::db::db_set()", "Requested DbHandle that is out of bounds");
  219. return DB_SET_FAILED
  220. }
  221. let handle_idx = db_handle;
  222. let db_handle = &db_handles[handle_idx];
  223. if db_handle.contract_id != env.contract_id {
  224. error!(target: "runtime::db::db_set()", "Unauthorized to write to DbHandle");
  225. return CALLER_ACCESS_DENIED
  226. }
  227. if env
  228. .blockchain
  229. .lock()
  230. .unwrap()
  231. .overlay
  232. .lock()
  233. .unwrap()
  234. .insert(&db_handle.tree, &key, &value)
  235. .is_err()
  236. {
  237. error!(target: "runtime::db::db_set()", "Couldn't insert to db_handle tree");
  238. return DB_SET_FAILED
  239. }
  240. DB_SUCCESS
  241. }
  242. /// Remove a key from the database.
  243. pub(crate) fn db_del(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, len: u32) -> i32 {
  244. let env = ctx.data();
  245. if env.contract_section != ContractSection::Deploy &&
  246. env.contract_section != ContractSection::Update
  247. {
  248. error!(target: "runtime::db::db_del()", "db_del called in unauthorized section");
  249. return CALLER_ACCESS_DENIED
  250. }
  251. let memory_view = env.memory_view(&ctx);
  252. let Ok(mem_slice) = ptr.slice(&memory_view, len) else {
  253. error!(target: "runtime::db::db_del()", "Failed to make slice from ptr");
  254. return DB_DEL_FAILED
  255. };
  256. let mut buf = vec![0_u8; len as usize];
  257. if let Err(e) = mem_slice.read_slice(&mut buf) {
  258. error!(target: "runtime::db::db_del()", "Failed to read from memory slice: {}", e);
  259. return DB_DEL_FAILED
  260. };
  261. let mut buf_reader = Cursor::new(buf);
  262. // FIXME: There's a type DbHandle=u32, but this should maybe be renamed
  263. let db_handle: u32 = match Decodable::decode(&mut buf_reader) {
  264. Ok(v) => v,
  265. Err(e) => {
  266. error!(target: "runtime::db::db_del()", "Failed to decode DbHandle: {}", e);
  267. return DB_DEL_FAILED
  268. }
  269. };
  270. let db_handle = db_handle as usize;
  271. let key: Vec<u8> = match Decodable::decode(&mut buf_reader) {
  272. Ok(v) => v,
  273. Err(e) => {
  274. error!(target: "runtime::db::db_del()", "Failed to decode key vec: {}", e);
  275. return DB_DEL_FAILED
  276. }
  277. };
  278. // Disabled until cursor_remaining feature is available on master.
  279. // Then enable #![feature(cursor_remaining)] in src/lib.rs
  280. /*if !buf_reader.is_empty() {
  281. error!(target: "runtime::db::db_del()", "Trailing bytes in argument stream");
  282. return DB_DEL_FAILED
  283. }*/
  284. let db_handles = env.db_handles.borrow();
  285. if db_handles.len() <= db_handle {
  286. error!(target: "runtime::db::db_del()", "Requested DbHandle that is out of bounds");
  287. return DB_DEL_FAILED
  288. }
  289. let handle_idx = db_handle;
  290. let db_handle = &db_handles[handle_idx];
  291. if db_handle.contract_id != env.contract_id {
  292. error!(target: "runtime::db::db_del()", "Unauthorized to write to DbHandle");
  293. return CALLER_ACCESS_DENIED
  294. }
  295. if env.blockchain.lock().unwrap().overlay.lock().unwrap().remove(&db_handle.tree, &key).is_err()
  296. {
  297. error!(target: "runtime::db::db_del()", "Couldn't remove key from db_handle tree");
  298. return DB_DEL_FAILED
  299. }
  300. DB_SUCCESS
  301. }
  302. /// Will read a key from the key-value store.
  303. pub(crate) fn db_get(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, len: u32) -> i64 {
  304. let env = ctx.data();
  305. if env.contract_section != ContractSection::Deploy &&
  306. env.contract_section != ContractSection::Exec &&
  307. env.contract_section != ContractSection::Metadata
  308. {
  309. error!(target: "runtime::db::db_get()", "db_get called in unauthorized section");
  310. return CALLER_ACCESS_DENIED.into()
  311. }
  312. let memory_view = env.memory_view(&ctx);
  313. let Ok(mem_slice) = ptr.slice(&memory_view, len) else {
  314. error!(target: "runtime::db::db_get()", "Failed to make slice from ptr");
  315. return DB_GET_FAILED.into()
  316. };
  317. let mut buf = vec![0_u8; len as usize];
  318. if let Err(e) = mem_slice.read_slice(&mut buf) {
  319. error!(target: "runtime::db::db_get()", "Failed to read from memory slice: {}", e);
  320. return DB_GET_FAILED.into()
  321. };
  322. let mut buf_reader = Cursor::new(buf);
  323. // FIXME: There's a type DbHandle=u32, but this should maybe be renamed
  324. let db_handle: u32 = match Decodable::decode(&mut buf_reader) {
  325. Ok(v) => v,
  326. Err(e) => {
  327. error!(target: "runtime::db::db_get()", "Failed to decode DbHandle: {}", e);
  328. return DB_GET_FAILED.into()
  329. }
  330. };
  331. let db_handle = db_handle as usize;
  332. let key: Vec<u8> = match Decodable::decode(&mut buf_reader) {
  333. Ok(v) => v,
  334. Err(e) => {
  335. error!(target: "runtime::db::db_get()", "Failed to decode key from vec: {}", e);
  336. return DB_GET_FAILED.into()
  337. }
  338. };
  339. // Disabled until cursor_remaining feature is available on master.
  340. // Then enable #![feature(cursor_remaining)] in src/lib.rs
  341. /*if !buf_reader.is_empty() {
  342. error!(target: "runtime::db::db_get()", "Trailing bytes in argument stream");
  343. return DB_GET_FAILED.into()
  344. }*/
  345. let db_handles = env.db_handles.borrow();
  346. if db_handles.len() <= db_handle {
  347. error!(target: "runtime::db::db_get()", "Requested DbHandle that is out of bounds");
  348. return DB_GET_FAILED.into()
  349. }
  350. let handle_idx = db_handle;
  351. let db_handle = &db_handles[handle_idx];
  352. let ret =
  353. match env.blockchain.lock().unwrap().overlay.lock().unwrap().get(&db_handle.tree, &key) {
  354. Ok(v) => v,
  355. Err(e) => {
  356. error!(target: "runtime::db::db_get()", "Internal error getting from tree: {}", e);
  357. return DB_GET_FAILED.into()
  358. }
  359. };
  360. let Some(return_data) = ret else {
  361. debug!(target: "runtime::db::db_get()", "returned empty vec");
  362. return -127
  363. };
  364. // Copy Vec<u8> to the VM
  365. let mut objects = env.objects.borrow_mut();
  366. objects.push(return_data.to_vec());
  367. (objects.len() - 1) as i64
  368. }
  369. /// Everyone can call this. Will check if a given db contains given key.
  370. pub(crate) fn db_contains_key(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, len: u32) -> i32 {
  371. let env = ctx.data();
  372. if env.contract_section != ContractSection::Deploy &&
  373. env.contract_section != ContractSection::Exec &&
  374. env.contract_section != ContractSection::Update &&
  375. env.contract_section != ContractSection::Metadata
  376. {
  377. error!(target: "runtime::db::db_contains_key()", "db_contains_key called in unauthorized section");
  378. return CALLER_ACCESS_DENIED
  379. }
  380. let memory_view = env.memory_view(&ctx);
  381. let Ok(mem_slice) = ptr.slice(&memory_view, len) else {
  382. error!(target: "runtime::db::db_contains_key()", "Failed to make slice from ptr");
  383. return DB_CONTAINS_KEY_FAILED
  384. };
  385. let mut buf = vec![0_u8; len as usize];
  386. if let Err(e) = mem_slice.read_slice(&mut buf) {
  387. error!(target: "runtime::db::db_contains_key()", "Failed to read from memory slice: {}", e);
  388. return DB_CONTAINS_KEY_FAILED
  389. };
  390. let mut buf_reader = Cursor::new(buf);
  391. // FIXME: There's a type DbHandle=u32, but this should maybe be renamed
  392. let db_handle: u32 = match Decodable::decode(&mut buf_reader) {
  393. Ok(v) => v,
  394. Err(e) => {
  395. error!(target: "runtime::db::db_contains_key()", "Failed to decode DbHandle: {}", e);
  396. return DB_CONTAINS_KEY_FAILED
  397. }
  398. };
  399. let db_handle = db_handle as usize;
  400. let key: Vec<u8> = match Decodable::decode(&mut buf_reader) {
  401. Ok(v) => v,
  402. Err(e) => {
  403. error!(target: "runtime::db::db_contains_key()", "Failed to decode key vec: {}", e);
  404. return DB_CONTAINS_KEY_FAILED
  405. }
  406. };
  407. // Disabled until cursor_remaining feature is available on master.
  408. // Then enable #![feature(cursor_remaining)] in src/lib.rs
  409. /*if !buf_reader.is_empty() {
  410. error!(target: "runtime::db::db_contains_key()", "Trailing bytes in argument stream");
  411. return DB_CONTAINS_KEY_FAILED
  412. }*/
  413. let db_handles = env.db_handles.borrow();
  414. if db_handles.len() <= db_handle {
  415. error!(target: "runtime::db::db_contains_key()", "Requested DbHandle that is out of bounds");
  416. return DB_CONTAINS_KEY_FAILED
  417. }
  418. let handle_idx = db_handle;
  419. let db_handle = &db_handles[handle_idx];
  420. match env.blockchain.lock().unwrap().overlay.lock().unwrap().contains_key(&db_handle.tree, &key)
  421. {
  422. Ok(v) => i32::from(v), // <- 0=false, 1=true
  423. Err(e) => {
  424. error!(target: "runtime::db::db_contains_key()", "sled.tree.contains_key failed: {}", e);
  425. DB_CONTAINS_KEY_FAILED
  426. }
  427. }
  428. }
  429. /// Only `deploy()` can call this. Given a zkas circuit, create a VerifyingKey and insert
  430. /// them both into the db.
  431. pub(crate) fn zkas_db_set(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, len: u32) -> i32 {
  432. let env = ctx.data();
  433. if env.contract_section != ContractSection::Deploy {
  434. error!(target: "runtime::db::zkas_db_set()", "zkas_db_set called in unauthorized section");
  435. return CALLER_ACCESS_DENIED
  436. }
  437. let memory_view = env.memory_view(&ctx);
  438. let contract_id = &env.contract_id;
  439. let Ok(mem_slice) = ptr.slice(&memory_view, len) else {
  440. error!(target: "runtime::db::zkas_db_set()", "Failed to make slice from ptr");
  441. return DB_SET_FAILED
  442. };
  443. let mut buf = vec![0u8; len as usize];
  444. if let Err(e) = mem_slice.read_slice(&mut buf) {
  445. error!(target: "runtime::db::zkas_db_set()", "Failed to read from memory slice: {}", e);
  446. return DB_SET_FAILED
  447. };
  448. let mut buf_reader = Cursor::new(buf);
  449. let zkas_bincode: Vec<u8> = match Decodable::decode(&mut buf_reader) {
  450. Ok(v) => v,
  451. Err(e) => {
  452. error!(target: "runtime::db::zkas_db_set()", "Failed to decode zkas bincode bytes: {}", e);
  453. return DB_SET_FAILED
  454. }
  455. };
  456. // Make sure that we're actually working on legitimate bincode.
  457. let Ok(zkbin) = ZkBinary::decode(&zkas_bincode) else {
  458. error!(target: "runtime::db::zkas_db_set()", "Invalid zkas bincode passed to function");
  459. return DB_SET_FAILED
  460. };
  461. // Because of `Runtime::Deploy`, we should be sure that the zkas db is index zero.
  462. let db_handles = env.db_handles.borrow();
  463. let db_handle = &db_handles[0];
  464. // Redundant check
  465. if &db_handle.contract_id != contract_id {
  466. error!(target: "runtime::db::zkas_db_set()", "Internal error, zkas db at index 0 incorrect");
  467. return DB_SET_FAILED
  468. }
  469. // Check if there is existing bincode and compare it. Return DB_SUCCESS if
  470. // they're the same. The assumption should be that VerifyingKey was generated
  471. // already so we can skip things after this guard.
  472. match env
  473. .blockchain
  474. .lock()
  475. .unwrap()
  476. .overlay
  477. .lock()
  478. .unwrap()
  479. .get(&db_handle.tree, &serialize(&zkbin.namespace))
  480. {
  481. Ok(v) => {
  482. if let Some(bytes) = v {
  483. // We allow a panic here because this db should never be corrupted in this way.
  484. let (existing_zkbin, _): (Vec<u8>, Vec<u8>) =
  485. deserialize(&bytes).expect("deserialize tuple");
  486. if existing_zkbin == zkas_bincode {
  487. debug!(target: "runtime::db::zkas_db_set()", "Existing zkas bincode is the same. Skipping.");
  488. return DB_SUCCESS
  489. }
  490. }
  491. }
  492. Err(e) => {
  493. error!(target: "runtime::db::zkas_db_set()", "Internal error getting from tree: {}", e);
  494. return DB_SET_FAILED
  495. }
  496. };
  497. // We didn't find any existing bincode, so let's create a new VerifyingKey and write it all.
  498. info!(target: "runtime::db::zkas_db_set()", "Creating VerifyingKey for {} zkas circuit", zkbin.namespace);
  499. let witnesses = empty_witnesses(&zkbin);
  500. let circuit = ZkCircuit::new(witnesses, zkbin.clone());
  501. let vk = VerifyingKey::build(13, &circuit);
  502. let mut vk_buf = vec![];
  503. if let Err(e) = vk.write(&mut vk_buf) {
  504. error!(target: "runtime::db::zkas_db_set()", "Failed to serialize VerifyingKey: {}", e);
  505. return DB_SET_FAILED
  506. }
  507. let key = serialize(&zkbin.namespace);
  508. let value = serialize(&(zkas_bincode, vk_buf));
  509. if env
  510. .blockchain
  511. .lock()
  512. .unwrap()
  513. .overlay
  514. .lock()
  515. .unwrap()
  516. .insert(&db_handle.tree, &key, &value)
  517. .is_err()
  518. {
  519. error!(target: "runtime::db::zkas_db_set()", "Couldn't insert to db_handle tree");
  520. return DB_SET_FAILED
  521. }
  522. DB_SUCCESS
  523. }