runtime/import/db: Apply gas subtraction to remaining db.rs functions

This commit is contained in:
parazyd
2024-01-18 13:23:08 +01:00
parent 9fb2febfb3
commit a3ed654d3a

View File

@@ -51,9 +51,9 @@ impl DbHandle {
///
/// This function should **only** be allowed in `ContractSection::Deploy`, as that
/// is called when a contract is being (re)deployed and databases have to be created.
pub(crate) fn db_init(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32) -> i64 {
let env = ctx.data();
let cid = &env.contract_id;
pub(crate) fn db_init(mut ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32) -> i64 {
let (env, mut store) = ctx.data_and_store_mut();
let cid = env.contract_id;
// Enforce function ACL
if let Err(e) = acl_allow(env, &[ContractSection::Deploy]) {
@@ -64,11 +64,15 @@ pub(crate) fn db_init(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32)
return darkfi_sdk::error::CALLER_ACCESS_DENIED
}
// Subtract used gas. Here we count the length read from the memory slice.
// TODO: There should probably be an additional fee to open a new sled tree.
env.subtract_gas(&mut store, ptr_len as u64);
// This takes lock of the blockchain overlay reference in the wasm env
let contracts = &env.blockchain.lock().unwrap().contracts;
// Create a mem slice of the wasm VM memory
let memory_view = env.memory_view(&ctx);
let memory_view = env.memory_view(&store);
let Ok(mem_slice) = ptr.slice(&memory_view, ptr_len) else {
error!(
target: "runtime::db::db_init",
@@ -131,7 +135,7 @@ pub(crate) fn db_init(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32)
}
// Nor can we allow another contract to initialize a db for someone else:
if cid != &read_cid {
if cid != read_cid {
error!(
target: "runtime::db::db_init",
"[WASM] [{}] db_init(): Unauthorized ContractId", cid,
@@ -194,9 +198,9 @@ pub(crate) fn db_init(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32)
/// Otherwise, returns an error value.
///
/// This function can be called from any [`ContractSection`].
pub(crate) fn db_lookup(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32) -> i64 {
let env = ctx.data();
let cid = &env.contract_id;
pub(crate) fn db_lookup(mut ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32) -> i64 {
let (env, mut store) = ctx.data_and_store_mut();
let cid = env.contract_id;
// Enforce function ACL
if let Err(e) = acl_allow(
@@ -215,8 +219,11 @@ pub(crate) fn db_lookup(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32
return darkfi_sdk::error::CALLER_ACCESS_DENIED
}
// Subtract used gas. Here we count the length read from the memory slice.
env.subtract_gas(&mut store, ptr_len as u64);
// Read memory location that contains the ContractId and DB name
let memory_view = env.memory_view(&ctx);
let memory_view = env.memory_view(&store);
let contracts = &env.blockchain.lock().unwrap().contracts;
let Ok(mem_slice) = ptr.slice(&memory_view, ptr_len) else {
@@ -318,9 +325,9 @@ pub(crate) fn db_lookup(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32
///
/// This function can be called only from the Deploy or Update [`ContractSection`].
/// Returns `SUCCESS` on success, otherwise returns an error value.
pub(crate) fn db_set(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32) -> i64 {
let env = ctx.data();
let cid = &env.contract_id;
pub(crate) fn db_set(mut ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32) -> i64 {
let (env, mut store) = ctx.data_and_store_mut();
let cid = env.contract_id;
if let Err(e) = acl_allow(env, &[ContractSection::Deploy, ContractSection::Update]) {
error!(
@@ -330,9 +337,11 @@ pub(crate) fn db_set(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32) -
return darkfi_sdk::error::CALLER_ACCESS_DENIED
}
// Ensure that it is possible to read from the memory that this function needs
let memory_view = env.memory_view(&ctx);
// Subtract used gas. Here we count the length hread from the memory slice.
env.subtract_gas(&mut store, ptr_len as u64);
// Ensure that it is possible to read from the memory that this function needs
let memory_view = env.memory_view(&store);
let Ok(mem_slice) = ptr.slice(&memory_view, ptr_len) else {
error!(
target: "runtime::db::db_set",
@@ -446,9 +455,9 @@ pub(crate) fn db_set(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32) -
///
/// This function can be called only from the Deploy or Update [`ContractSection`].
/// Returns `SUCCESS` on success, otherwise returns an error value.
pub(crate) fn db_del(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32) -> i64 {
let env = ctx.data();
let cid = &env.contract_id;
pub(crate) fn db_del(mut ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32) -> i64 {
let (env, mut store) = ctx.data_and_store_mut();
let cid = env.contract_id;
if let Err(e) = acl_allow(env, &[ContractSection::Deploy, ContractSection::Update]) {
error!(
@@ -458,8 +467,11 @@ pub(crate) fn db_del(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32) -
return darkfi_sdk::error::CALLER_ACCESS_DENIED
}
// Subtract used gas. Here we count the length of the looked-up key.
env.subtract_gas(&mut store, ptr_len as u64);
// Ensure that it is possible to read from the memory that this function needs
let memory_view = env.memory_view(&ctx);
let memory_view = env.memory_view(&store);
let Ok(mem_slice) = ptr.slice(&memory_view, ptr_len) else {
error!(
@@ -528,7 +540,7 @@ pub(crate) fn db_del(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32) -
let db_handle = &db_handles[db_handle_index];
// Validate that the DbHandle matches the contract ID
if db_handle.contract_id != env.contract_id {
if db_handle.contract_id != cid {
error!(
target: "runtime::db::db_del",
"[WASM] [{}] db_del(): Unauthorized to write to DbHandle", cid,
@@ -555,9 +567,9 @@ pub(crate) fn db_del(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32) -
///
/// On success, returns the length of the `objects` Vector in the environment.
/// Otherwise, returns an error code.
pub(crate) fn db_get(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32) -> i64 {
let env = ctx.data();
let cid = &env.contract_id;
pub(crate) fn db_get(mut ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32) -> i64 {
let (env, mut store) = ctx.data_and_store_mut();
let cid = env.contract_id;
if let Err(e) =
acl_allow(env, &[ContractSection::Deploy, ContractSection::Exec, ContractSection::Metadata])
@@ -569,9 +581,11 @@ pub(crate) fn db_get(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32) -
return darkfi_sdk::error::CALLER_ACCESS_DENIED
}
// Ensure that it is possible to read memory
let memory_view = env.memory_view(&ctx);
// Subtract used gas. Here we count the length of the looked-up key.
env.subtract_gas(&mut store, ptr_len as u64);
// Ensure that it is possible to read memory
let memory_view = env.memory_view(&store);
let Ok(mem_slice) = ptr.slice(&memory_view, ptr_len) else {
error!(
target: "runtime::db::db_get",
@@ -653,6 +667,7 @@ pub(crate) fn db_get(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32) -
return darkfi_sdk::error::DB_GET_FAILED
}
};
drop(db_handles);
// Return special error if the data is empty
let Some(return_data) = ret else {
@@ -667,6 +682,9 @@ pub(crate) fn db_get(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32) -
return darkfi_sdk::error::DATA_TOO_LARGE
}
// Subtract used gas. Here we count the length of the data read from db.
env.subtract_gas(&mut store, return_data.len() as u64);
// Copy the data (Vec<u8>) to the VM by pushing it to the objects Vector.
let mut objects = env.objects.borrow_mut();
if objects.len() == u32::MAX as usize {
@@ -681,11 +699,12 @@ pub(crate) fn db_get(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32) -
/// Check if a database contains a given key.
///
/// Returns `1` if the key is found. Returns `0` if the key is not found and there are no errors.
/// Returns `1` if the key is found.
/// Returns `0` if the key is not found and there are no errors.
/// Otherwise, returns an error code.
pub(crate) fn db_contains_key(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32) -> i64 {
let env = ctx.data();
let cid = &env.contract_id;
pub(crate) fn db_contains_key(mut ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32) -> i64 {
let (env, mut store) = ctx.data_and_store_mut();
let cid = env.contract_id;
if let Err(e) =
acl_allow(env, &[ContractSection::Deploy, ContractSection::Exec, ContractSection::Metadata])
@@ -697,9 +716,11 @@ pub(crate) fn db_contains_key(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_le
return darkfi_sdk::error::CALLER_ACCESS_DENIED
}
// Ensure memory is readable
let memory_view = env.memory_view(&ctx);
// Subtract used gas. Here we count the length of the looked-up key.
env.subtract_gas(&mut store, ptr_len as u64);
// Ensure memory is readable
let memory_view = env.memory_view(&store);
let Ok(mem_slice) = ptr.slice(&memory_view, ptr_len) else {
error!(
target: "runtime::db::db_contains_key",
@@ -784,8 +805,9 @@ pub(crate) fn db_contains_key(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_le
}
/// Given a zkas circuit, create a VerifyingKey and insert them both into the db.
/// This function can called only from the Deploy [`ContractSection`].
/// Returns `0` on success, otherwise returns a (negative) error code.
///
/// This function can only be called from the Deploy [`ContractSection`].
/// Returns `SUCCESS` on success, otherwise returns an error code.
pub(crate) fn zkas_db_set(mut ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, ptr_len: u32) -> i64 {
let (env, mut store) = ctx.data_and_store_mut();
let cid = env.contract_id;