darkfi/runtime/import/db/
db_init.rs1use darkfi_sdk::crypto::contract_id::{
20 ContractId, SMART_CONTRACT_MONOTREE_DB_NAME, SMART_CONTRACT_ZKAS_DB_NAME,
21};
22use darkfi_serial::Decodable;
23use tracing::error;
24use wasmer::{FunctionEnvMut, WasmPtr};
25
26use crate::runtime::{
27 import::{acl::acl_allow, util::wasm_mem_read},
28 vm_runtime::{ContractSection, Env},
29};
30
31use super::DbHandle;
32
33pub(crate) fn db_init(mut ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32) -> i64 {
46 let (env, mut store) = ctx.data_and_store_mut();
47 let cid = env.contract_id;
48
49 if let Err(e) = acl_allow(env, &[ContractSection::Deploy]) {
51 error!(
52 target: "runtime::db::db_init",
53 "[WASM] [{cid}] db_init(): Called in unauthorized section: {e}",
54 );
55 return darkfi_sdk::error::CALLER_ACCESS_DENIED
56 }
57
58 env.subtract_gas(&mut store, 1);
61
62 let mut buf_reader = match wasm_mem_read(env, &store, ptr, ptr_len) {
64 Ok(v) => v,
65 Err(e) => {
66 error!(
67 target: "runtime::db::db_init",
68 "[WASM] [{cid}] db_init(): Failed to read WASM memory: {e}",
69 );
70 return darkfi_sdk::error::DB_INIT_FAILED
71 }
72 };
73
74 let contracts = &env.blockchain.lock().unwrap().contracts;
76
77 let read_cid: ContractId = match Decodable::decode(&mut buf_reader) {
79 Ok(v) => v,
80 Err(e) => {
81 error!(
82 target: "runtime::db::db_init",
83 "[WASM] [{cid}] db_init(): Failed decoding ContractId: {e}",
84 );
85 return darkfi_sdk::error::DB_INIT_FAILED
86 }
87 };
88
89 let db_name: String = match Decodable::decode(&mut buf_reader) {
91 Ok(v) => v,
92 Err(e) => {
93 error!(
94 target: "runtime::db::db_init",
95 "[WASM] [{cid}] db_init(): Failed decoding db_name: {e}",
96 );
97 return darkfi_sdk::error::DB_INIT_FAILED
98 }
99 };
100
101 if buf_reader.position() != ptr_len as u64 {
103 error!(
104 target: "runtime::db::db_init",
105 "[WASM] [{cid}] db_init(): Trailing bytes in argument stream",
106 );
107 return darkfi_sdk::error::DB_INIT_FAILED
108 }
109
110 if [SMART_CONTRACT_ZKAS_DB_NAME, SMART_CONTRACT_MONOTREE_DB_NAME].contains(&db_name.as_str()) {
112 error!(
113 target: "runtime::db::db_init",
114 "[WASM] [{cid}] db_init(): Attempted to init special db ({db_name})",
115 );
116 return darkfi_sdk::error::CALLER_ACCESS_DENIED
117 }
118
119 if cid != read_cid {
121 error!(
122 target: "runtime::db::db_init",
123 "[WASM] [{cid}] db_init(): Unauthorized ContractId",
124 );
125 return darkfi_sdk::error::CALLER_ACCESS_DENIED
126 }
127
128 let tree_handle = match contracts.init(&read_cid, &db_name) {
135 Ok(v) => v,
136 Err(e) => {
137 error!(
138 target: "runtime::db::db_init",
139 "[WASM] [{cid}] db_init(): Failed to init db: {e}",
140 );
141 return darkfi_sdk::error::DB_INIT_FAILED
142 }
143 };
144
145 let db_handle = DbHandle::new(read_cid, tree_handle);
147 let mut db_handles = env.db_handles.borrow_mut();
148
149 if let Some(index) = db_handles.iter().position(|x| x == &db_handle) {
151 return index as i64
152 }
153
154 match db_handles.len().try_into() {
156 Ok(db_handle_idx) => {
157 db_handles.push(db_handle);
158 db_handle_idx
159 }
160 Err(_) => {
161 error!(
162 target: "runtime::db::db_init",
163 "[WASM] [{cid}] db_init(): Too many open DbHandles",
164 );
165 darkfi_sdk::error::DB_INIT_FAILED
166 }
167 }
168}