Skip to content

Commit

Permalink
pass WriteOpts to WASM host fns
Browse files Browse the repository at this point in the history
  • Loading branch information
brentstone committed Jan 15, 2024
1 parent a1143ab commit b7b1921
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 36 deletions.
58 changes: 35 additions & 23 deletions core/src/ledger/storage/write_log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,26 +208,24 @@ impl WriteLog {
}
}

/// Write a key and a value and return the gas cost and the size difference
/// Fails with [`Error::UpdateVpOfNewAccount`] when attempting to update a
/// validity predicate of a new account that's not yet committed to storage.
/// Fails with [`Error::UpdateTemporaryValue`] when attempting to update a
/// Write a key and a value, with write options, and return the gas cost and
/// the size difference. Fails with [`Error::UpdateVpOfNewAccount`] when
/// attempting to update a validity predicate of a new account that's
/// not yet committed to storage. Fails with
/// [`Error::UpdateTemporaryValue`] when attempting to update a
/// temporary value.
pub fn write(
pub fn write_with_opts(
&mut self,
key: &storage::Key,
value: Vec<u8>,
// action: WriteActions,
action: WriteOpts,
) -> Result<(u64, i64)> {
let len = value.len();
let gas = key.len() + len;
let size_diff = match self.tx_write_log.insert(
key.clone(),
StorageModification::Write {
value,
action: WriteOpts::ALL,
},
) {
let size_diff = match self
.tx_write_log
.insert(key.clone(), StorageModification::Write { value, action })
{
Some(prev) => match prev {
StorageModification::Write {
ref value,
Expand All @@ -248,6 +246,16 @@ impl WriteLog {
Ok((gas as u64 * STORAGE_WRITE_GAS_PER_BYTE, size_diff))
}

/// Write a key and value using all write options, and return the gas cost
/// and size difference
pub fn write(
&mut self,
key: &storage::Key,
value: Vec<u8>,
) -> Result<(u64, i64)> {
self.write_with_opts(key, value, WriteOpts::ALL)
}

/// Write a key and a value.
/// Fails with [`Error::UpdateVpOfNewAccount`] when attempting to update a
/// validity predicate of a new account that's not yet committed to storage.
Expand Down Expand Up @@ -317,24 +325,22 @@ impl WriteLog {
Ok((gas as u64 * MEMORY_ACCESS_GAS_PER_BYTE, size_diff))
}

/// Delete a key and its value, and return the gas cost and the size
/// difference.
/// Delete a key and its value, with write options, and return the gas cost
/// and the size difference.
/// Fails with [`Error::DeleteVp`] for a validity predicate key, which are
/// not possible to delete.
pub fn delete(
pub fn delete_with_opts(
&mut self,
key: &storage::Key,
// action: WriteActions,
action: WriteOpts,
) -> Result<(u64, i64)> {
if key.is_validity_predicate().is_some() {
return Err(Error::DeleteVp);
}
let size_diff = match self.tx_write_log.insert(
key.clone(),
StorageModification::Delete {
action: WriteOpts::ALL,
},
) {
let size_diff = match self
.tx_write_log
.insert(key.clone(), StorageModification::Delete { action })
{
Some(prev) => match prev {
StorageModification::Write {
ref value,
Expand All @@ -354,6 +360,12 @@ impl WriteLog {
Ok((gas as u64 * STORAGE_WRITE_GAS_PER_BYTE, -size_diff))
}

/// Delete a key and its value, with all write options, and return the gas
/// cost and the size difference.
pub fn delete(&mut self, key: &storage::Key) -> Result<(u64, i64)> {
self.delete_with_opts(key, WriteOpts::ALL)
}

/// Delete a key and its value.
/// Fails with [`Error::DeleteVp`] for a validity predicate key, which are
/// not possible to delete.
Expand Down
14 changes: 12 additions & 2 deletions shared/src/vm/host_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ pub enum TxRuntimeError {
MissingTxData,
#[error("IBC: {0}")]
Ibc(#[from] namada_core::ledger::ibc::Error),
#[error("Invalid Write Options")]
InvalidWriteOptions,
}

type TxResult<T> = std::result::Result<T, TxRuntimeError>;
Expand Down Expand Up @@ -817,6 +819,7 @@ pub fn tx_write<MEM, DB, H, CA>(
key_len: u64,
val_ptr: u64,
val_len: u64,
write_opts: u8,
) -> TxResult<()>
where
MEM: VmMemory,
Expand Down Expand Up @@ -844,9 +847,12 @@ where

check_address_existence(env, &key)?;

let write_opts = WriteOpts::from_bits(write_opts)
.ok_or_else(|| TxRuntimeError::InvalidWriteOptions)?;

let write_log = unsafe { env.ctx.write_log.get() };
let (gas, _size_diff) = write_log
.write(&key, value)
.write_with_opts(&key, value, write_opts)
.map_err(TxRuntimeError::StorageModificationError)?;
tx_charge_gas(env, gas)
}
Expand Down Expand Up @@ -950,6 +956,7 @@ pub fn tx_delete<MEM, DB, H, CA>(
env: &TxVmEnv<MEM, DB, H, CA>,
key_ptr: u64,
key_len: u64,
write_opts: u8,
) -> TxResult<()>
where
MEM: VmMemory,
Expand All @@ -970,9 +977,12 @@ where
return Err(TxRuntimeError::CannotDeleteVp);
}

let write_opts = WriteOpts::from_bits(write_opts)
.ok_or_else(|| TxRuntimeError::InvalidWriteOptions)?;

let write_log = unsafe { env.ctx.write_log.get() };
let (gas, _size_diff) = write_log
.delete(&key)
.delete_with_opts(&key, write_opts)
.map_err(TxRuntimeError::StorageModificationError)?;
tx_charge_gas(env, gas)
}
Expand Down
5 changes: 3 additions & 2 deletions tests/src/vm_host_env/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -472,15 +472,16 @@ mod native_tx_host_env {
key_ptr: u64,
key_len: u64,
val_ptr: u64,
val_len: u64
val_len: u64,
write_opts: u8
));
native_host_fn!(tx_write_temp(
key_ptr: u64,
key_len: u64,
val_ptr: u64,
val_len: u64
));
native_host_fn!(tx_delete(key_ptr: u64, key_len: u64));
native_host_fn!(tx_delete(key_ptr: u64, key_len: u64, write_opts: u8));
native_host_fn!(tx_iter_prefix(prefix_ptr: u64, prefix_len: u64) -> u64);
native_host_fn!(tx_iter_next(iter_id: u64) -> i64);
native_host_fn!(tx_insert_verifier(addr_ptr: u64, addr_len: u64));
Expand Down
22 changes: 14 additions & 8 deletions tx_prelude/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ impl StorageWrite for Ctx {
&mut self,
key: &storage::Key,
val: impl AsRef<[u8]>,
_action: WriteOpts,
action: WriteOpts,
) -> storage_api::Result<()> {
let key = key.to_string();
// TODO: do certain write actions need to be considered here??
Expand All @@ -238,24 +238,30 @@ impl StorageWrite for Ctx {
key.len() as _,
val.as_ref().as_ptr() as _,
val.as_ref().len() as _,
action.bits() as _,
)
};
Ok(())
}

fn delete(&mut self, key: &storage::Key) -> storage_api::Result<()> {
let key = key.to_string();
unsafe { namada_tx_delete(key.as_ptr() as _, key.len() as _) };
Ok(())
self.delete_with_opts(key, WriteOpts::ALL)
}

// TODO: is this the correct thing to do here?
fn delete_with_opts(
&mut self,
_key: &storage::Key,
_action: WriteOpts,
key: &storage::Key,
action: WriteOpts,
) -> storage_api::Result<()> {
unimplemented!()
let key = key.to_string();
unsafe {
namada_tx_delete(
key.as_ptr() as _,
key.len() as _,
action.bits() as _,
)
};
Ok(())
}
}

Expand Down
3 changes: 2 additions & 1 deletion vm_env/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub mod tx {
key_len: u64,
val_ptr: u64,
val_len: u64,
write_opts: u8,
);

// Write a temporary key/value
Expand All @@ -45,7 +46,7 @@ pub mod tx {
);

// Delete the given key and its value
pub fn namada_tx_delete(key_ptr: u64, key_len: u64);
pub fn namada_tx_delete(key_ptr: u64, key_len: u64, write_opts: u8);

// Get an ID of a data iterator with key prefix, ordered by storage
// keys.
Expand Down

0 comments on commit b7b1921

Please sign in to comment.