use std::{collections::BTreeSet, convert::TryFrom};
use wasmi::{Externals, RuntimeArgs, RuntimeValue, Trap};
use casper_types::{
account,
account::AccountHash,
api_error,
bytesrepr::{self, ToBytes},
contracts::{EntryPoints, NamedKeys},
ContractHash, ContractPackageHash, ContractVersion, Group, Key, URef, U512,
};
use super::{args::Args, scoped_instrumenter::ScopedInstrumenter, Error, Runtime};
use crate::{
core::resolvers::v1_function_index::FunctionIndex,
shared::{gas::Gas, host_function_costs::Cost, stored_value::StoredValue},
storage::global_state::StateReader,
};
impl<'a, R> Externals for Runtime<'a, R>
where
R: StateReader<Key, StoredValue>,
R::Error: Into<Error>,
{
fn invoke_index(
&mut self,
index: usize,
args: RuntimeArgs,
) -> Result<Option<RuntimeValue>, Trap> {
let func = FunctionIndex::try_from(index).expect("unknown function index");
let mut scoped_instrumenter = ScopedInstrumenter::new(func);
let host_function_costs = self
.protocol_data()
.wasm_config()
.take_host_function_costs();
match func {
FunctionIndex::ReadFuncIndex => {
let (key_ptr, key_size, output_size_ptr) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.read_value,
[key_ptr, key_size, output_size_ptr],
)?;
let ret = self.read(key_ptr, key_size, output_size_ptr)?;
Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
}
FunctionIndex::ReadLocalFuncIndex => {
let (key_ptr, key_size, output_size_ptr) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.read_value_local,
[key_ptr, key_size, output_size_ptr],
)?;
scoped_instrumenter.add_property("key_size", key_size);
let ret = self.read_local(key_ptr, key_size, output_size_ptr)?;
Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
}
FunctionIndex::LoadNamedKeysFuncIndex => {
let (total_keys_ptr, result_size_ptr) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.load_named_keys,
[total_keys_ptr, result_size_ptr],
)?;
let ret = self.load_named_keys(
total_keys_ptr,
result_size_ptr,
&mut scoped_instrumenter,
)?;
Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
}
FunctionIndex::WriteFuncIndex => {
let (key_ptr, key_size, value_ptr, value_size) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.write,
[key_ptr, key_size, value_ptr, value_size],
)?;
scoped_instrumenter.add_property("value_size", value_size);
self.write(key_ptr, key_size, value_ptr, value_size)?;
Ok(None)
}
FunctionIndex::WriteLocalFuncIndex => {
let (key_bytes_ptr, key_bytes_size, value_ptr, value_size) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.write_local,
[key_bytes_ptr, key_bytes_size, value_ptr, value_size],
)?;
scoped_instrumenter.add_property("key_bytes_size", key_bytes_size);
scoped_instrumenter.add_property("value_size", value_size);
self.write_local(key_bytes_ptr, key_bytes_size, value_ptr, value_size)?;
Ok(None)
}
FunctionIndex::AddFuncIndex => {
let (key_ptr, key_size, value_ptr, value_size) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.add,
[key_ptr, key_size, value_ptr, value_size],
)?;
self.add(key_ptr, key_size, value_ptr, value_size)?;
Ok(None)
}
FunctionIndex::NewFuncIndex => {
let (uref_ptr, value_ptr, value_size) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.new_uref,
[uref_ptr, value_ptr, value_size],
)?;
scoped_instrumenter.add_property("value_size", value_size);
self.new_uref(uref_ptr, value_ptr, value_size)?;
Ok(None)
}
FunctionIndex::RetFuncIndex => {
let (value_ptr, value_size) = Args::parse(args)?;
self.charge_host_function_call(&host_function_costs.ret, [value_ptr, value_size])?;
scoped_instrumenter.add_property("value_size", value_size);
Err(self.ret(value_ptr, value_size as usize, &mut scoped_instrumenter))
}
FunctionIndex::GetKeyFuncIndex => {
let (name_ptr, name_size, output_ptr, output_size, bytes_written) =
Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.get_key,
[name_ptr, name_size, output_ptr, output_size, bytes_written],
)?;
scoped_instrumenter.add_property("name_size", name_size);
let ret = self.load_key(
name_ptr,
name_size,
output_ptr,
output_size as usize,
bytes_written,
)?;
Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
}
FunctionIndex::HasKeyFuncIndex => {
let (name_ptr, name_size) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.has_key,
[name_ptr, name_size],
)?;
scoped_instrumenter.add_property("name_size", name_size);
let result = self.has_key(name_ptr, name_size)?;
Ok(Some(RuntimeValue::I32(result)))
}
FunctionIndex::PutKeyFuncIndex => {
let (name_ptr, name_size, key_ptr, key_size) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.put_key,
[name_ptr, name_size, key_ptr, key_size],
)?;
scoped_instrumenter.add_property("name_size", name_size);
self.put_key(name_ptr, name_size, key_ptr, key_size)?;
Ok(None)
}
FunctionIndex::RemoveKeyFuncIndex => {
let (name_ptr, name_size) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.remove_key,
[name_ptr, name_size],
)?;
scoped_instrumenter.add_property("name_size", name_size);
self.remove_key(name_ptr, name_size)?;
Ok(None)
}
FunctionIndex::GetCallerIndex => {
let output_size = Args::parse(args)?;
self.charge_host_function_call(&host_function_costs.get_caller, [output_size])?;
let ret = self.get_caller(output_size)?;
Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
}
FunctionIndex::GetBlocktimeIndex => {
let dest_ptr = Args::parse(args)?;
self.charge_host_function_call(&host_function_costs.get_blocktime, [dest_ptr])?;
self.get_blocktime(dest_ptr)?;
Ok(None)
}
FunctionIndex::GasFuncIndex => {
let gas_arg: u32 = Args::parse(args)?;
self.gas(Gas::new(gas_arg.into()))?;
Ok(None)
}
FunctionIndex::IsValidURefFnIndex => {
let (uref_ptr, uref_size) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.is_valid_uref,
[uref_ptr, uref_size],
)?;
Ok(Some(RuntimeValue::I32(i32::from(
self.is_valid_uref(uref_ptr, uref_size)?,
))))
}
FunctionIndex::RevertFuncIndex => {
let status = Args::parse(args)?;
self.charge_host_function_call(&host_function_costs.revert, [status])?;
Err(self.revert(status))
}
FunctionIndex::AddAssociatedKeyFuncIndex => {
let (account_hash_ptr, account_hash_size, weight_value) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.add_associated_key,
[account_hash_ptr, account_hash_size, weight_value as Cost],
)?;
let value = self.add_associated_key(
account_hash_ptr,
account_hash_size as usize,
weight_value,
)?;
Ok(Some(RuntimeValue::I32(value)))
}
FunctionIndex::RemoveAssociatedKeyFuncIndex => {
let (account_hash_ptr, account_hash_size) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.remove_associated_key,
[account_hash_ptr, account_hash_size],
)?;
let value =
self.remove_associated_key(account_hash_ptr, account_hash_size as usize)?;
Ok(Some(RuntimeValue::I32(value)))
}
FunctionIndex::UpdateAssociatedKeyFuncIndex => {
let (account_hash_ptr, account_hash_size, weight_value) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.update_associated_key,
[account_hash_ptr, account_hash_size, weight_value as Cost],
)?;
let value = self.update_associated_key(
account_hash_ptr,
account_hash_size as usize,
weight_value,
)?;
Ok(Some(RuntimeValue::I32(value)))
}
FunctionIndex::SetActionThresholdFuncIndex => {
let (action_type_value, threshold_value) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.set_action_threshold,
[action_type_value, threshold_value as Cost],
)?;
let value = self.set_action_threshold(action_type_value, threshold_value)?;
Ok(Some(RuntimeValue::I32(value)))
}
FunctionIndex::CreatePurseIndex => {
let (dest_ptr, dest_size) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.create_purse,
[dest_ptr, dest_size],
)?;
let purse = self.create_purse()?;
let purse_bytes = purse.into_bytes().map_err(Error::BytesRepr)?;
assert_eq!(dest_size, purse_bytes.len() as u32);
self.memory
.set(dest_ptr, &purse_bytes)
.map_err(|e| Error::Interpreter(e.into()))?;
Ok(Some(RuntimeValue::I32(0)))
}
FunctionIndex::TransferToAccountIndex => {
let (key_ptr, key_size, amount_ptr, amount_size, id_ptr, id_size, result_ptr) =
Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.transfer_to_account,
[
key_ptr,
key_size,
amount_ptr,
amount_size,
id_ptr,
id_size,
result_ptr,
],
)?;
let account_hash: AccountHash = {
let bytes = self.bytes_from_mem(key_ptr, key_size as usize)?;
bytesrepr::deserialize(bytes).map_err(Error::BytesRepr)?
};
let amount: U512 = {
let bytes = self.bytes_from_mem(amount_ptr, amount_size as usize)?;
bytesrepr::deserialize(bytes).map_err(Error::BytesRepr)?
};
let id: Option<u64> = {
let bytes = self.bytes_from_mem(id_ptr, id_size as usize)?;
bytesrepr::deserialize(bytes).map_err(Error::BytesRepr)?
};
let ret = match self.transfer_to_account(account_hash, amount, id)? {
Ok(transferred_to) => {
let result_value: u32 = transferred_to as u32;
let result_value_bytes = result_value.to_le_bytes();
self.memory
.set(result_ptr, &result_value_bytes)
.map_err(|error| Error::Interpreter(error.into()))?;
Ok(())
}
Err(api_error) => Err(api_error),
};
Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
}
FunctionIndex::TransferFromPurseToAccountIndex => {
let (
source_ptr,
source_size,
key_ptr,
key_size,
amount_ptr,
amount_size,
id_ptr,
id_size,
result_ptr,
) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.transfer_from_purse_to_account,
[
source_ptr,
source_size,
key_ptr,
key_size,
amount_ptr,
amount_size,
id_ptr,
id_size,
result_ptr,
],
)?;
let source_purse = {
let bytes = self.bytes_from_mem(source_ptr, source_size as usize)?;
bytesrepr::deserialize(bytes).map_err(Error::BytesRepr)?
};
let account_hash: AccountHash = {
let bytes = self.bytes_from_mem(key_ptr, key_size as usize)?;
bytesrepr::deserialize(bytes).map_err(Error::BytesRepr)?
};
let amount: U512 = {
let bytes = self.bytes_from_mem(amount_ptr, amount_size as usize)?;
bytesrepr::deserialize(bytes).map_err(Error::BytesRepr)?
};
let id: Option<u64> = {
let bytes = self.bytes_from_mem(id_ptr, id_size as usize)?;
bytesrepr::deserialize(bytes).map_err(Error::BytesRepr)?
};
let ret = match self.transfer_from_purse_to_account(
source_purse,
account_hash,
amount,
id,
)? {
Ok(transferred_to) => {
let result_value: u32 = transferred_to as u32;
let result_value_bytes = result_value.to_le_bytes();
self.memory
.set(result_ptr, &result_value_bytes)
.map_err(|error| Error::Interpreter(error.into()))?;
Ok(())
}
Err(api_error) => Err(api_error),
};
Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
}
FunctionIndex::TransferFromPurseToPurseIndex => {
let (
source_ptr,
source_size,
target_ptr,
target_size,
amount_ptr,
amount_size,
id_ptr,
id_size,
) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.transfer_from_purse_to_purse,
[
source_ptr,
source_size,
target_ptr,
target_size,
amount_ptr,
amount_size,
id_ptr,
id_size,
],
)?;
let ret = self.transfer_from_purse_to_purse(
source_ptr,
source_size,
target_ptr,
target_size,
amount_ptr,
amount_size,
id_ptr,
id_size,
)?;
Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
}
FunctionIndex::GetBalanceIndex => {
let (ptr, ptr_size, output_size_ptr) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.get_balance,
[ptr, ptr_size, output_size_ptr],
)?;
let ret = self.get_balance_host_buffer(ptr, ptr_size as usize, output_size_ptr)?;
Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
}
FunctionIndex::GetPhaseIndex => {
let dest_ptr = Args::parse(args)?;
self.charge_host_function_call(&host_function_costs.get_phase, [dest_ptr])?;
self.get_phase(dest_ptr)?;
Ok(None)
}
FunctionIndex::GetSystemContractIndex => {
let (system_contract_index, dest_ptr, dest_size) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.get_system_contract,
[system_contract_index, dest_ptr, dest_size],
)?;
let ret = self.get_system_contract(system_contract_index, dest_ptr, dest_size)?;
Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
}
FunctionIndex::GetMainPurseIndex => {
let dest_ptr = Args::parse(args)?;
self.charge_host_function_call(&host_function_costs.get_main_purse, [dest_ptr])?;
self.get_main_purse(dest_ptr)?;
Ok(None)
}
FunctionIndex::ReadHostBufferIndex => {
let (dest_ptr, dest_size, bytes_written_ptr) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.read_host_buffer,
[dest_ptr, dest_size, bytes_written_ptr],
)?;
scoped_instrumenter.add_property("dest_size", dest_size);
let ret = self.read_host_buffer(dest_ptr, dest_size as usize, bytes_written_ptr)?;
Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
}
FunctionIndex::CreateContractPackageAtHash => {
let (hash_dest_ptr, access_dest_ptr) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.create_contract_package_at_hash,
[hash_dest_ptr, access_dest_ptr],
)?;
let (hash_addr, access_addr) = self.create_contract_package_at_hash()?;
self.function_address(hash_addr, hash_dest_ptr)?;
self.function_address(access_addr, access_dest_ptr)?;
Ok(None)
}
FunctionIndex::CreateContractUserGroup => {
let (
package_key_ptr,
package_key_size,
label_ptr,
label_size,
num_new_urefs,
existing_urefs_ptr,
existing_urefs_size,
output_size_ptr,
) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.create_contract_user_group,
[
package_key_ptr,
package_key_size,
label_ptr,
label_size,
num_new_urefs,
existing_urefs_ptr,
existing_urefs_size,
output_size_ptr,
],
)?;
scoped_instrumenter
.add_property("existing_urefs_size", existing_urefs_size.to_string());
scoped_instrumenter.add_property("label_size", label_size.to_string());
let contract_package_hash: ContractPackageHash =
self.t_from_mem(package_key_ptr, package_key_size)?;
let label: String = self.t_from_mem(label_ptr, label_size)?;
let existing_urefs: BTreeSet<URef> =
self.t_from_mem(existing_urefs_ptr, existing_urefs_size)?;
let ret = self.create_contract_user_group(
contract_package_hash,
label,
num_new_urefs,
existing_urefs,
output_size_ptr,
)?;
Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
}
FunctionIndex::AddContractVersion => {
let (
contract_package_hash_ptr,
contract_package_hash_size,
version_ptr,
entry_points_ptr,
entry_points_size,
named_keys_ptr,
named_keys_size,
output_ptr,
output_size,
bytes_written_ptr,
) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.add_contract_version,
[
contract_package_hash_ptr,
contract_package_hash_size,
version_ptr,
entry_points_ptr,
entry_points_size,
named_keys_ptr,
named_keys_size,
output_ptr,
output_size,
bytes_written_ptr,
],
)?;
scoped_instrumenter
.add_property("entry_points_size", entry_points_size.to_string());
scoped_instrumenter.add_property("named_keys_size", named_keys_size.to_string());
let contract_package_hash: ContractPackageHash =
self.t_from_mem(contract_package_hash_ptr, contract_package_hash_size)?;
let entry_points: EntryPoints =
self.t_from_mem(entry_points_ptr, entry_points_size)?;
let named_keys: NamedKeys = self.t_from_mem(named_keys_ptr, named_keys_size)?;
let ret = self.add_contract_version(
contract_package_hash,
entry_points,
named_keys,
output_ptr,
output_size as usize,
bytes_written_ptr,
version_ptr,
)?;
Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
}
FunctionIndex::DisableContractVersion => {
let (package_key_ptr, package_key_size, contract_hash_ptr, contract_hash_size) =
Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.disable_contract_version,
[
package_key_ptr,
package_key_size,
contract_hash_ptr,
contract_hash_size,
],
)?;
let contract_package_hash = self.t_from_mem(package_key_ptr, package_key_size)?;
let contract_hash = self.t_from_mem(contract_hash_ptr, contract_hash_size)?;
let result = self.disable_contract_version(contract_package_hash, contract_hash)?;
Ok(Some(RuntimeValue::I32(api_error::i32_from(result))))
}
FunctionIndex::CallContractFuncIndex => {
let (
contract_hash_ptr,
contract_hash_size,
entry_point_name_ptr,
entry_point_name_size,
args_ptr,
args_size,
result_size_ptr,
) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.call_contract,
[
contract_hash_ptr,
contract_hash_size,
entry_point_name_ptr,
entry_point_name_size,
args_ptr,
args_size,
result_size_ptr,
],
)?;
scoped_instrumenter
.add_property("entry_point_name_size", entry_point_name_size.to_string());
scoped_instrumenter.add_property("args_size", args_size.to_string());
let contract_hash: ContractHash =
self.t_from_mem(contract_hash_ptr, contract_hash_size)?;
let entry_point_name: String =
self.t_from_mem(entry_point_name_ptr, entry_point_name_size)?;
let args_bytes: Vec<u8> = {
let args_size: u32 = args_size;
self.bytes_from_mem(args_ptr, args_size as usize)?
};
let ret = self.call_contract_host_buffer(
contract_hash,
&entry_point_name,
args_bytes,
result_size_ptr,
&mut scoped_instrumenter,
)?;
Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
}
FunctionIndex::CallVersionedContract => {
let (
contract_package_hash_ptr,
contract_package_hash_size,
contract_version_ptr,
contract_package_size,
entry_point_name_ptr,
entry_point_name_size,
args_ptr,
args_size,
result_size_ptr,
) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.call_versioned_contract,
[
contract_package_hash_ptr,
contract_package_hash_size,
contract_version_ptr,
contract_package_size,
entry_point_name_ptr,
entry_point_name_size,
args_ptr,
args_size,
result_size_ptr,
],
)?;
scoped_instrumenter
.add_property("entry_point_name_size", entry_point_name_size.to_string());
scoped_instrumenter.add_property("args_size", args_size.to_string());
let contract_package_hash: ContractPackageHash =
self.t_from_mem(contract_package_hash_ptr, contract_package_hash_size)?;
let contract_version: Option<ContractVersion> =
self.t_from_mem(contract_version_ptr, contract_package_size)?;
let entry_point_name: String =
self.t_from_mem(entry_point_name_ptr, entry_point_name_size)?;
let args_bytes: Vec<u8> = {
let args_size: u32 = args_size;
self.bytes_from_mem(args_ptr, args_size as usize)?
};
let ret = self.call_versioned_contract_host_buffer(
contract_package_hash,
contract_version,
entry_point_name,
args_bytes,
result_size_ptr,
&mut scoped_instrumenter,
)?;
Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
}
#[cfg(feature = "test-support")]
FunctionIndex::PrintIndex => {
let (text_ptr, text_size) = Args::parse(args)?;
self.charge_host_function_call(&host_function_costs.print, [text_ptr, text_size])?;
scoped_instrumenter.add_property("text_size", text_size);
self.print(text_ptr, text_size)?;
Ok(None)
}
FunctionIndex::GetRuntimeArgsizeIndex => {
let (name_ptr, name_size, size_ptr) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.get_named_arg_size,
[name_ptr, name_size, size_ptr],
)?;
scoped_instrumenter.add_property("name_size", name_size.to_string());
let ret = self.get_named_arg_size(name_ptr, name_size as usize, size_ptr)?;
Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
}
FunctionIndex::GetRuntimeArgIndex => {
let (name_ptr, name_size, dest_ptr, dest_size) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.get_named_arg,
[name_ptr, name_size, dest_ptr, dest_size],
)?;
scoped_instrumenter.add_property("name_size", name_size.to_string());
scoped_instrumenter.add_property("dest_size", dest_size.to_string());
let ret =
self.get_named_arg(name_ptr, name_size as usize, dest_ptr, dest_size as usize)?;
Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
}
FunctionIndex::RemoveContractUserGroupIndex => {
let (package_key_ptr, package_key_size, label_ptr, label_size) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.remove_contract_user_group,
[package_key_ptr, package_key_size, label_ptr, label_size],
)?;
scoped_instrumenter.add_property("label_size", label_size.to_string());
let package_key = self.t_from_mem(package_key_ptr, package_key_size)?;
let label: Group = self.t_from_mem(label_ptr, label_size)?;
let ret = self.remove_contract_user_group(package_key, label)?;
Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
}
FunctionIndex::ExtendContractUserGroupURefsIndex => {
let (package_ptr, package_size, label_ptr, label_size, value_size_ptr) =
Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.provision_contract_user_group_uref,
[
package_ptr,
package_size,
label_ptr,
label_size,
value_size_ptr,
],
)?;
scoped_instrumenter.add_property("label_size", label_size.to_string());
let ret = self.provision_contract_user_group_uref(
package_ptr,
package_size,
label_ptr,
label_size,
value_size_ptr,
)?;
Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
}
FunctionIndex::RemoveContractUserGroupURefsIndex => {
let (package_ptr, package_size, label_ptr, label_size, urefs_ptr, urefs_size) =
Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.remove_contract_user_group_urefs,
[
package_ptr,
package_size,
label_ptr,
label_size,
urefs_ptr,
urefs_size,
],
)?;
scoped_instrumenter.add_property("label_size", label_size.to_string());
scoped_instrumenter.add_property("urefs_size", urefs_size.to_string());
let ret = self.remove_contract_user_group_urefs(
package_ptr,
package_size,
label_ptr,
label_size,
urefs_ptr,
urefs_size,
)?;
Ok(Some(RuntimeValue::I32(api_error::i32_from(ret))))
}
FunctionIndex::Blake2b => {
let (in_ptr, in_size, out_ptr, out_size) = Args::parse(args)?;
self.charge_host_function_call(
&host_function_costs.blake2b,
[in_ptr, in_size, out_ptr, out_size],
)?;
scoped_instrumenter.add_property("in_size", in_size.to_string());
scoped_instrumenter.add_property("out_size", out_size.to_string());
let input: Vec<u8> = self.bytes_from_mem(in_ptr, in_size as usize)?;
let digest = account::blake2b(&input);
if digest.len() != out_size as usize {
let err_value = u32::from(api_error::ApiError::BufferTooSmall) as i32;
return Ok(Some(RuntimeValue::I32(err_value)));
}
self.memory
.set(out_ptr, &digest)
.map_err(|error| Error::Interpreter(error.into()))?;
Ok(Some(RuntimeValue::I32(0)))
}
FunctionIndex::RecordTransfer => {
let (
source_ptr,
source_size,
target_ptr,
target_size,
amount_ptr,
amount_size,
id_ptr,
id_size,
): (u32, u32, u32, u32, u32, u32, u32, u32) = Args::parse(args)?;
scoped_instrumenter.add_property("source_size", source_size.to_string());
scoped_instrumenter.add_property("target_size", target_size.to_string());
scoped_instrumenter.add_property("amount_size", amount_size.to_string());
scoped_instrumenter.add_property("id_size", id_size.to_string());
let source: URef = self.t_from_mem(source_ptr, source_size)?;
let target: URef = self.t_from_mem(target_ptr, target_size)?;
let amount: U512 = self.t_from_mem(amount_ptr, amount_size)?;
let id: Option<u64> = self.t_from_mem(id_ptr, id_size)?;
self.record_transfer(source, target, amount, id)?;
Ok(Some(RuntimeValue::I32(0)))
}
}
}
}