darkfi/runtime/import/db/
zkas_db_set.rs1use darkfi_sdk::wasm;
20use darkfi_serial::{deserialize, serialize, Decodable};
21use tracing::{debug, error, info};
22use wasmer::{FunctionEnvMut, WasmPtr};
23
24use crate::{
25 runtime::{
26 import::{acl::acl_allow, util::wasm_mem_read},
27 vm_runtime::{ContractSection, Env},
28 },
29 zk::{empty_witnesses, VerifyingKey, ZkCircuit},
30 zkas::ZkBinary,
31};
32
33pub(crate) fn zkas_db_set(mut ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_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::Deploy]) {
46 error!(
47 target: "runtime::db::zkas_db_set",
48 "[WASM] [{cid}] zkas_db_set(): Called in unauthorized section: {e}",
49 );
50 return darkfi_sdk::error::CALLER_ACCESS_DENIED
51 }
52
53 let mut buf_reader = match wasm_mem_read(env, &store, ptr, ptr_len) {
55 Ok(v) => v,
56 Err(e) => {
57 error!(
58 target: "runtime::db::zkas_db_set",
59 "[WASM] [{cid}] zkas_db_set(): Failed to read wasm memory: {e}",
60 );
61 return darkfi_sdk::error::DB_SET_FAILED
62 }
63 };
64
65 let zkbin_bytes: Vec<u8> = match Decodable::decode(&mut buf_reader) {
67 Ok(zkbin) => zkbin,
68 Err(e) => {
69 error!(
70 target: "runtime::db::zkas_db_set",
71 "[WASM] [{cid}] zkas_db_set(): Could not deserialize bytes from buffer: {e}"
72 );
73 return darkfi_sdk::error::DB_SET_FAILED
74 }
75 };
76
77 if buf_reader.position() != ptr_len as u64 {
79 error!(
80 target: "runtime::db::zkas_db_set",
81 "[WASM] [{cid}] zkas_db_set(): Trailing bytes in argument stream",
82 );
83 return darkfi_sdk::error::DB_SET_FAILED
84 }
85
86 let zkbin = match ZkBinary::decode(&zkbin_bytes, false) {
88 Ok(zkbin) => zkbin,
89 Err(e) => {
90 error!(
91 target: "runtime::db::zkas_db_set",
92 "[WASM] [{cid}] zkas_db_set(): Invalid zkas bincode passed to function: {e}"
93 );
94 return darkfi_sdk::error::DB_SET_FAILED
95 }
96 };
97
98 let gas_cost =
102 (zkbin.literals.len() + zkbin.witnesses.len() + zkbin.opcodes.len()) as u64 * 100;
103 env.subtract_gas(&mut store, gas_cost);
104
105 let db_handles = env.db_handles.borrow();
107 let db_handle = &db_handles[0];
108 if db_handle.contract_id != cid {
110 error!(
111 target: "runtime::db::zkas_db_set",
112 "[WASM] [{cid}] zkas_db_set(): Internal error, zkas db at index 0 incorrect"
113 );
114 return darkfi_sdk::error::DB_SET_FAILED
115 }
116
117 match env
121 .blockchain
122 .lock()
123 .unwrap()
124 .overlay
125 .lock()
126 .unwrap()
127 .get(&db_handle.tree, &serialize(&zkbin.namespace))
128 {
129 Ok(v) => {
130 if let Some(bytes) = v {
131 let (existing_zkbin, _): (Vec<u8>, Vec<u8>) =
133 deserialize(&bytes).expect("deserialize tuple");
134
135 if existing_zkbin == zkbin_bytes {
136 debug!(
137 target: "runtime::db::zkas_db_set",
138 "[WASM] [{cid}] zkas_db_set(): Existing zkas bincode is the same. Skipping."
139 );
140 return wasm::entrypoint::SUCCESS
141 }
142 }
143 }
144 Err(e) => {
145 error!(
146 target: "runtime::db::zkas_db_set",
147 "[WASM] [{cid}] zkas_db_set(): Internal error getting from tree: {e}"
148 );
149 return darkfi_sdk::error::DB_SET_FAILED
150 }
151 };
152
153 info!(
155 target: "runtime::db::zkas_db_set",
156 "[WASM] [{cid}] zkas_db_set(): Creating VerifyingKey for {} zkas circuit",
157 zkbin.namespace,
158 );
159
160 let witnesses = match empty_witnesses(&zkbin) {
161 Ok(w) => w,
162 Err(e) => {
163 error!(
164 target: "runtime::db::zkas_db_set",
165 "[WASM] [{cid}] zkas_db_set(): Failed to create empty witnesses: {e}"
166 );
167 return darkfi_sdk::error::DB_SET_FAILED
168 }
169 };
170
171 let circuit = ZkCircuit::new(witnesses, &zkbin);
173 let vk = VerifyingKey::build(zkbin.k, &circuit);
174 let mut vk_buf = vec![];
175 if let Err(e) = vk.write(&mut vk_buf) {
176 error!(
177 target: "runtime::db::zkas_db_set",
178 "[WASM] [{cid}] zkas_db_set(): Failed to serialize VerifyingKey: {e}"
179 );
180 return darkfi_sdk::error::DB_SET_FAILED
181 }
182
183 let key = serialize(&zkbin.namespace);
185 let value = serialize(&(zkbin_bytes, vk_buf));
186 if env
187 .blockchain
188 .lock()
189 .unwrap()
190 .overlay
191 .lock()
192 .unwrap()
193 .insert(&db_handle.tree, &key, &value)
194 .is_err()
195 {
196 error!(
197 target: "runtime::db::zkas_db_set",
198 "[WASM] [{cid}] zkas_db_set(): Couldn't insert to db_handle tree"
199 );
200 return darkfi_sdk::error::DB_SET_FAILED
201 }
202 drop(db_handles);
203
204 env.subtract_gas(&mut store, (key.len() + value.len()) as u64);
206
207 wasm::entrypoint::SUCCESS
208}