darkfi/runtime/import/db/
db_contains_key.rs1use darkfi_serial::Decodable;
20use tracing::error;
21use wasmer::{FunctionEnvMut, WasmPtr};
22
23use crate::runtime::{
24 import::{acl::acl_allow, util::wasm_mem_read},
25 vm_runtime::{ContractSection, Env},
26};
27
28pub(crate) fn db_contains_key(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32) -> i64 {
39 db_contains_key_internal(ctx, ptr, ptr_len, false)
40}
41
42pub(crate) fn db_contains_key_local(
53 ctx: FunctionEnvMut<Env>,
54 ptr: WasmPtr<u8>,
55 ptr_len: u32,
56) -> i64 {
57 db_contains_key_internal(ctx, ptr, ptr_len, true)
58}
59
60fn db_contains_key_internal(
68 mut ctx: FunctionEnvMut<Env>,
69 ptr: WasmPtr<u8>,
70 ptr_len: u32,
71 local: bool,
72) -> i64 {
73 let lt = if local { "db_contains_key_local" } else { "db_contains_key" };
74 let (env, mut store) = ctx.data_and_store_mut();
75 let cid = env.contract_id;
76
77 if let Err(e) =
79 acl_allow(env, &[ContractSection::Deploy, ContractSection::Metadata, ContractSection::Exec])
80 {
81 error!(
82 target: "runtime::db::{lt}",
83 "[WASM] [{cid}] {lt}(): Called in unauthorized section: {e}",
84 );
85 return darkfi_sdk::error::CALLER_ACCESS_DENIED
86 }
87
88 env.subtract_gas(&mut store, 1);
91
92 let mut buf_reader = match wasm_mem_read(env, &store, ptr, ptr_len) {
94 Ok(v) => v,
95 Err(e) => {
96 error!(
97 target: "runtime::db::{lt}",
98 "[WASM] [{cid}] {lt}(): Failed to read wasm memory: {e}",
99 );
100 return darkfi_sdk::error::DB_CONTAINS_KEY_FAILED
101 }
102 };
103
104 let db_handle_index: u32 = match Decodable::decode(&mut buf_reader) {
106 Ok(v) => v,
107 Err(e) => {
108 error!(
109 target: "runtime::db::{lt}",
110 "[WASM] [{cid}] {lt}(): Failed to decode DbHandle: {e}",
111 );
112 return darkfi_sdk::error::DB_CONTAINS_KEY_FAILED
113 }
114 };
115
116 let db_handle_index = db_handle_index as usize;
117
118 let key: Vec<u8> = match Decodable::decode(&mut buf_reader) {
120 Ok(v) => v,
121 Err(e) => {
122 error!(
123 target: "runtime::db::{lt}",
124 "[WASM] [{cid}] {lt}(): Failed to decode key vec: {e}",
125 );
126 return darkfi_sdk::error::DB_CONTAINS_KEY_FAILED
127 }
128 };
129
130 if buf_reader.position() != ptr_len as u64 {
132 error!(
133 target: "runtime::db::{lt}",
134 "[WASM] [{cid}] {lt}(): Trailing bytes in argument stream",
135 );
136 return darkfi_sdk::error::DB_CONTAINS_KEY_FAILED
137 }
138
139 let db_handles = if local { env.local_db_handles.borrow() } else { env.db_handles.borrow() };
141
142 if db_handles.len() <= db_handle_index {
144 error!(
145 target: "runtime::db::{lt}",
146 "[WASM] [{cid}] {lt}(): Requested DbHandle out of bounds",
147 );
148 return darkfi_sdk::error::DB_CONTAINS_KEY_FAILED
149 }
150
151 let db_handle = &db_handles[db_handle_index];
153
154 if local {
156 let db = env.tx_local.lock();
157 let Some(db_cid) = db.get(&db_handle.contract_id) else {
158 error!(
159 target: "runtime::db::{lt}",
160 "[WASM] [{cid}] {lt}(): Could not find db for {}",
161 db_handle.contract_id,
162 );
163 return darkfi_sdk::error::DB_CONTAINS_KEY_FAILED
164 };
165
166 let Some(tree) = db_cid.get(&db_handle.tree) else {
167 error!(
168 target: "runtime::db::{lt}",
169 "[WASM] [{cid}] {lt}(): Could not find db tree for {}",
170 db_handle.contract_id,
171 );
172 return darkfi_sdk::error::DB_CONTAINS_KEY_FAILED
173 };
174
175 return i64::from(tree.contains_key(&key))
177 }
178
179 match env.blockchain.lock().unwrap().overlay.lock().unwrap().contains_key(&db_handle.tree, &key)
181 {
182 Ok(v) => i64::from(v), Err(e) => {
184 error!(
185 target: "runtime::db::{lt}",
186 "[WASM] [{cid}] {lt}(): sled.tree.contains_key failed: {e}",
187 );
188 darkfi_sdk::error::DB_CONTAINS_KEY_FAILED
189 }
190 }
191}