darkfi/runtime/import/db/
db_set.rs1use darkfi_sdk::wasm;
20use darkfi_serial::Decodable;
21use tracing::error;
22use wasmer::{FunctionEnvMut, WasmPtr};
23
24use crate::runtime::{
25 import::{acl::acl_allow, util::wasm_mem_read},
26 vm_runtime::{ContractSection, Env},
27};
28
29pub(crate) fn db_set(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32) -> i64 {
40 db_set_internal(ctx, ptr, ptr_len, false)
41}
42
43pub(crate) fn db_set_local(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32) -> i64 {
54 db_set_internal(ctx, ptr, ptr_len, true)
55}
56
57fn db_set_internal(
63 mut ctx: FunctionEnvMut<Env>,
64 ptr: WasmPtr<u8>,
65 ptr_len: u32,
66 local: bool,
67) -> i64 {
68 let lt = if local { "db_set_local" } else { "db_set" };
69 let (env, mut store) = ctx.data_and_store_mut();
70 let cid = env.contract_id;
71
72 if let Err(e) = acl_allow(env, &[ContractSection::Deploy, ContractSection::Update]) {
74 error!(
75 target: "runtime::db::{lt}",
76 "[WASM] [{cid}] {lt}(): Called in unauthorized section: {e}",
77 );
78 return darkfi_sdk::error::CALLER_ACCESS_DENIED
79 }
80
81 env.subtract_gas(&mut store, ptr_len as u64);
85
86 let mut buf_reader = match wasm_mem_read(env, &store, ptr, ptr_len) {
88 Ok(v) => v,
89 Err(e) => {
90 error!(
91 target: "runtime::db::{lt}",
92 "[WASM] [{cid}] {lt}(): Failed to read wasm memory: {e}",
93 );
94 return darkfi_sdk::error::DB_SET_FAILED
95 }
96 };
97
98 let db_handle_index: u32 = match Decodable::decode(&mut buf_reader) {
100 Ok(v) => v,
101 Err(e) => {
102 error!(
103 target: "runtime::db::{lt}",
104 "[WASM] [{cid}] {lt}(): Failed to decode DbHandle: {e}",
105 );
106 return darkfi_sdk::error::DB_SET_FAILED
107 }
108 };
109
110 let db_handle_index = db_handle_index as usize;
111
112 if env.contract_section == ContractSection::Deploy && db_handle_index == 0 {
115 error!(
116 target: "runtime::db::{lt}",
117 "[WASM] [{cid}] {lt}(): Tried to write to zkas db",
118 );
119 return darkfi_sdk::error::CALLER_ACCESS_DENIED
120 }
121
122 let key: Vec<u8> = match Decodable::decode(&mut buf_reader) {
124 Ok(v) => v,
125 Err(e) => {
126 error!(
127 target: "runtime::db::{lt}",
128 "[WASM] [{cid}] {lt}(): Failed to decode key vec: {e}",
129 );
130 return darkfi_sdk::error::DB_SET_FAILED
131 }
132 };
133
134 let value: Vec<u8> = match Decodable::decode(&mut buf_reader) {
135 Ok(v) => v,
136 Err(e) => {
137 error!(
138 target: "runtime::db::{lt}",
139 "[WASM] [{cid}] {lt}(): Failed to decode value vec: {e}",
140 );
141 return darkfi_sdk::error::DB_SET_FAILED
142 }
143 };
144
145 if buf_reader.position() != ptr_len as u64 {
147 error!(
148 target: "runtime::db::{lt}",
149 "[WASM] [{cid}] {lt}(): Trailing bytes in argument stream",
150 );
151 return darkfi_sdk::error::DB_SET_FAILED
152 }
153
154 let db_handles = if local { env.local_db_handles.borrow() } else { env.db_handles.borrow() };
156
157 if db_handles.len() <= db_handle_index {
159 error!(
160 target: "runtime::db::{lt}",
161 "[WASM] [{cid}] {lt}(): Requested DbHandle that is out of bounds",
162 );
163 return darkfi_sdk::error::DB_SET_FAILED
164 }
165
166 let db_handle = &db_handles[db_handle_index];
168
169 if db_handle.contract_id != env.contract_id {
171 error!(
172 target: "runtime::db::{lt}",
173 "[WASM] [{cid}] {lt}(): Unauthorized to write to DbHandle",
174 );
175 return darkfi_sdk::error::CALLER_ACCESS_DENIED
176 }
177
178 if local {
180 let mut db = env.tx_local.lock();
182 let db_cid = db.get_mut(&cid).unwrap();
183 let Some(tree) = db_cid.get_mut(&db_handle.tree) else {
184 error!(
185 target: "runtime::db::{lt}",
186 "[WASM] [{cid}] {lt}(): Could not insert to tx-local tree",
187 );
188 return darkfi_sdk::error::DB_SET_FAILED
189 };
190
191 tree.insert(key, value);
192 } else if env
193 .blockchain
194 .lock()
195 .unwrap()
196 .overlay
197 .lock()
198 .unwrap()
199 .insert(&db_handle.tree, &key, &value)
200 .is_err()
201 {
202 error!(
203 target: "runtime::db::{lt}",
204 "[WASM] [{cid}] {lt}(): Couldn't insert to on-chain tree",
205 );
206 return darkfi_sdk::error::DB_SET_FAILED
207 }
208
209 wasm::entrypoint::SUCCESS
210}