use crate::types::Gas;
use core::fmt;
use serde::{Deserialize, Serialize};
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
#[derive(Clone, Copy, Debug, Hash, Serialize, Deserialize)]
pub enum VMKind {
Wasmer,
Wasmtime,
}
impl Default for VMKind {
#[cfg(feature = "wasmer_default")]
fn default() -> Self {
VMKind::Wasmer
}
#[cfg(feature = "wasmtime_default")]
fn default() -> Self {
VMKind::Wasmtime
}
#[cfg(all(not(feature = "wasmer_default"), not(feature = "wasmtime_default")))]
fn default() -> Self {
VMKind::Wasmer
}
}
#[derive(Clone, Debug, Hash, Serialize, Deserialize, PartialEq, Eq)]
pub struct VMConfig {
pub ext_costs: ExtCostsConfig,
pub grow_mem_cost: u32,
pub regular_op_cost: u32,
pub limit_config: VMLimitConfig,
}
#[derive(Debug, Serialize, Deserialize, Clone, Hash, PartialEq, Eq)]
pub struct VMLimitConfig {
pub max_gas_burnt: Gas,
pub max_gas_burnt_view: Gas,
pub max_stack_height: u32,
pub initial_memory_pages: u32,
pub max_memory_pages: u32,
pub registers_memory_limit: u64,
pub max_register_size: u64,
pub max_number_registers: u64,
pub max_number_logs: u64,
pub max_total_log_length: u64,
pub max_total_prepaid_gas: Gas,
pub max_actions_per_receipt: u64,
pub max_number_bytes_method_names: u64,
pub max_length_method_name: u64,
pub max_arguments_length: u64,
pub max_length_returned_data: u64,
pub max_contract_size: u64,
pub max_length_storage_key: u64,
pub max_length_storage_value: u64,
pub max_promises_per_function_call_action: u64,
pub max_number_input_data_dependencies: u64,
}
impl Default for VMConfig {
fn default() -> VMConfig {
VMConfig {
ext_costs: ExtCostsConfig::default(),
grow_mem_cost: 1,
regular_op_cost: 3856371,
limit_config: VMLimitConfig::default(),
}
}
}
impl VMConfig {
pub fn non_crypto_hash(&self) -> u64 {
let mut s = DefaultHasher::new();
self.hash(&mut s);
s.finish()
}
pub fn free() -> Self {
Self {
ext_costs: ExtCostsConfig::free(),
grow_mem_cost: 0,
regular_op_cost: 0,
limit_config: VMLimitConfig {
max_gas_burnt: std::u64::MAX,
max_gas_burnt_view: std::u64::MAX,
..Default::default()
},
}
}
}
impl Default for VMLimitConfig {
fn default() -> Self {
Self {
max_gas_burnt: 2 * 10u64.pow(14),
max_gas_burnt_view: 2 * 10u64.pow(14),
max_stack_height: 16 * 1024,
initial_memory_pages: 2u32.pow(10),
max_memory_pages: 2u32.pow(11),
registers_memory_limit: 2u64.pow(30),
max_register_size: 2u64.pow(20) * 100,
max_number_registers: 100,
max_number_logs: 100,
max_total_log_length: 16 * 1024,
max_total_prepaid_gas: 300 * 10u64.pow(12),
max_actions_per_receipt: 100,
max_number_bytes_method_names: 2000,
max_length_method_name: 256,
max_arguments_length: 4 * 2u64.pow(20),
max_length_returned_data: 4 * 2u64.pow(20),
max_contract_size: 4 * 2u64.pow(20),
max_length_storage_key: 4 * 2u64.pow(20),
max_length_storage_value: 4 * 2u64.pow(20),
max_promises_per_function_call_action: 1024,
max_number_input_data_dependencies: 128,
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone, Hash, PartialEq, Eq)]
pub struct ExtCostsConfig {
pub base: Gas,
pub contract_compile_base: Gas,
pub contract_compile_bytes: Gas,
pub read_memory_base: Gas,
pub read_memory_byte: Gas,
pub write_memory_base: Gas,
pub write_memory_byte: Gas,
pub read_register_base: Gas,
pub read_register_byte: Gas,
pub write_register_base: Gas,
pub write_register_byte: Gas,
pub utf8_decoding_base: Gas,
pub utf8_decoding_byte: Gas,
pub utf16_decoding_base: Gas,
pub utf16_decoding_byte: Gas,
pub sha256_base: Gas,
pub sha256_byte: Gas,
pub keccak256_base: Gas,
pub keccak256_byte: Gas,
pub keccak512_base: Gas,
pub keccak512_byte: Gas,
pub log_base: Gas,
pub log_byte: Gas,
pub storage_write_base: Gas,
pub storage_write_key_byte: Gas,
pub storage_write_value_byte: Gas,
pub storage_write_evicted_byte: Gas,
pub storage_read_base: Gas,
pub storage_read_key_byte: Gas,
pub storage_read_value_byte: Gas,
pub storage_remove_base: Gas,
pub storage_remove_key_byte: Gas,
pub storage_remove_ret_value_byte: Gas,
pub storage_has_key_base: Gas,
pub storage_has_key_byte: Gas,
pub storage_iter_create_prefix_base: Gas,
pub storage_iter_create_prefix_byte: Gas,
pub storage_iter_create_range_base: Gas,
pub storage_iter_create_from_byte: Gas,
pub storage_iter_create_to_byte: Gas,
pub storage_iter_next_base: Gas,
pub storage_iter_next_key_byte: Gas,
pub storage_iter_next_value_byte: Gas,
pub touching_trie_node: Gas,
pub promise_and_base: Gas,
pub promise_and_per_promise: Gas,
pub promise_return: Gas,
pub validator_stake_base: Gas,
pub validator_total_stake_base: Gas,
}
const SAFETY_MULTIPLIER: u64 = 3;
impl Default for ExtCostsConfig {
fn default() -> ExtCostsConfig {
ExtCostsConfig {
base: SAFETY_MULTIPLIER * 88256037,
contract_compile_base: SAFETY_MULTIPLIER * 11815321,
contract_compile_bytes: SAFETY_MULTIPLIER * 72250,
read_memory_base: SAFETY_MULTIPLIER * 869954400,
read_memory_byte: SAFETY_MULTIPLIER * 1267111,
write_memory_base: SAFETY_MULTIPLIER * 934598287,
write_memory_byte: SAFETY_MULTIPLIER * 907924,
read_register_base: SAFETY_MULTIPLIER * 839055062,
read_register_byte: SAFETY_MULTIPLIER * 32854,
write_register_base: SAFETY_MULTIPLIER * 955174162,
write_register_byte: SAFETY_MULTIPLIER * 1267188,
utf8_decoding_base: SAFETY_MULTIPLIER * 1037259687,
utf8_decoding_byte: SAFETY_MULTIPLIER * 97193493,
utf16_decoding_base: SAFETY_MULTIPLIER * 1181104350,
utf16_decoding_byte: SAFETY_MULTIPLIER * 54525831,
sha256_base: SAFETY_MULTIPLIER * 1513656750,
sha256_byte: SAFETY_MULTIPLIER * 8039117,
keccak256_base: SAFETY_MULTIPLIER * 1959830425,
keccak256_byte: SAFETY_MULTIPLIER * 7157035,
keccak512_base: SAFETY_MULTIPLIER * 1937129412,
keccak512_byte: SAFETY_MULTIPLIER * 12216567,
log_base: SAFETY_MULTIPLIER * 1181104350,
log_byte: SAFETY_MULTIPLIER * 4399597,
storage_write_base: SAFETY_MULTIPLIER * 21398912000,
storage_write_key_byte: SAFETY_MULTIPLIER * 23494289,
storage_write_value_byte: SAFETY_MULTIPLIER * 10339513,
storage_write_evicted_byte: SAFETY_MULTIPLIER * 10705769,
storage_read_base: SAFETY_MULTIPLIER * 18785615250,
storage_read_key_byte: SAFETY_MULTIPLIER * 10317511,
storage_read_value_byte: SAFETY_MULTIPLIER * 1870335,
storage_remove_base: SAFETY_MULTIPLIER * 17824343500,
storage_remove_key_byte: SAFETY_MULTIPLIER * 12740128,
storage_remove_ret_value_byte: SAFETY_MULTIPLIER * 3843852,
storage_has_key_base: SAFETY_MULTIPLIER * 18013298875,
storage_has_key_byte: SAFETY_MULTIPLIER * 10263615,
storage_iter_create_prefix_base: SAFETY_MULTIPLIER * 0,
storage_iter_create_prefix_byte: SAFETY_MULTIPLIER * 0,
storage_iter_create_range_base: SAFETY_MULTIPLIER * 0,
storage_iter_create_from_byte: SAFETY_MULTIPLIER * 0,
storage_iter_create_to_byte: SAFETY_MULTIPLIER * 0,
storage_iter_next_base: SAFETY_MULTIPLIER * 0,
storage_iter_next_key_byte: SAFETY_MULTIPLIER * 0,
storage_iter_next_value_byte: SAFETY_MULTIPLIER * 0,
touching_trie_node: SAFETY_MULTIPLIER * 5367318642,
promise_and_base: SAFETY_MULTIPLIER * 488337800,
promise_and_per_promise: SAFETY_MULTIPLIER * 1817392,
promise_return: SAFETY_MULTIPLIER * 186717462,
validator_stake_base: SAFETY_MULTIPLIER * 303944908800,
validator_total_stake_base: SAFETY_MULTIPLIER * 303944908800,
}
}
}
impl ExtCostsConfig {
fn free() -> ExtCostsConfig {
ExtCostsConfig {
base: 0,
contract_compile_base: 0,
contract_compile_bytes: 0,
read_memory_base: 0,
read_memory_byte: 0,
write_memory_base: 0,
write_memory_byte: 0,
read_register_base: 0,
read_register_byte: 0,
write_register_base: 0,
write_register_byte: 0,
utf8_decoding_base: 0,
utf8_decoding_byte: 0,
utf16_decoding_base: 0,
utf16_decoding_byte: 0,
sha256_base: 0,
sha256_byte: 0,
keccak256_base: 0,
keccak256_byte: 0,
keccak512_base: 0,
keccak512_byte: 0,
log_base: 0,
log_byte: 0,
storage_write_base: 0,
storage_write_key_byte: 0,
storage_write_value_byte: 0,
storage_write_evicted_byte: 0,
storage_read_base: 0,
storage_read_key_byte: 0,
storage_read_value_byte: 0,
storage_remove_base: 0,
storage_remove_key_byte: 0,
storage_remove_ret_value_byte: 0,
storage_has_key_base: 0,
storage_has_key_byte: 0,
storage_iter_create_prefix_base: 0,
storage_iter_create_prefix_byte: 0,
storage_iter_create_range_base: 0,
storage_iter_create_from_byte: 0,
storage_iter_create_to_byte: 0,
storage_iter_next_base: 0,
storage_iter_next_key_byte: 0,
storage_iter_next_value_byte: 0,
touching_trie_node: 0,
promise_and_base: 0,
promise_and_per_promise: 0,
promise_return: 0,
validator_stake_base: 0,
validator_total_stake_base: 0,
}
}
}
#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug, PartialOrd, Ord)]
#[allow(non_camel_case_types)]
pub enum ExtCosts {
base,
contract_compile_base,
contract_compile_bytes,
read_memory_base,
read_memory_byte,
write_memory_base,
write_memory_byte,
read_register_base,
read_register_byte,
write_register_base,
write_register_byte,
utf8_decoding_base,
utf8_decoding_byte,
utf16_decoding_base,
utf16_decoding_byte,
sha256_base,
sha256_byte,
keccak256_base,
keccak256_byte,
keccak512_base,
keccak512_byte,
log_base,
log_byte,
storage_write_base,
storage_write_key_byte,
storage_write_value_byte,
storage_write_evicted_byte,
storage_read_base,
storage_read_key_byte,
storage_read_value_byte,
storage_remove_base,
storage_remove_key_byte,
storage_remove_ret_value_byte,
storage_has_key_base,
storage_has_key_byte,
storage_iter_create_prefix_base,
storage_iter_create_prefix_byte,
storage_iter_create_range_base,
storage_iter_create_from_byte,
storage_iter_create_to_byte,
storage_iter_next_base,
storage_iter_next_key_byte,
storage_iter_next_value_byte,
touching_trie_node,
promise_and_base,
promise_and_per_promise,
promise_return,
validator_stake_base,
validator_total_stake_base,
}
#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug, PartialOrd, Ord)]
#[allow(non_camel_case_types)]
pub enum ActionCosts {
create_account,
delete_account,
deploy_contract,
function_call,
transfer,
stake,
add_key,
delete_key,
value_return,
new_receipt,
}
impl fmt::Display for ActionCosts {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", ActionCosts::name_of(*self as usize))
}
}
impl ActionCosts {
pub const fn count() -> usize {
ActionCosts::new_receipt as usize + 1
}
pub fn name_of(index: usize) -> &'static str {
vec![
"create_account",
"delete_account",
"deploy_contract",
"function_call",
"transfer",
"stake",
"add_key",
"delete_key",
"value_return",
"new_receipt",
][index]
}
}
impl fmt::Display for ExtCosts {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", ExtCosts::name_of(*self as usize))
}
}
impl ExtCosts {
pub fn value(self, config: &ExtCostsConfig) -> Gas {
use ExtCosts::*;
match self {
base => config.base,
contract_compile_base => config.contract_compile_base,
contract_compile_bytes => config.contract_compile_bytes,
read_memory_base => config.read_memory_base,
read_memory_byte => config.read_memory_byte,
write_memory_base => config.write_memory_base,
write_memory_byte => config.write_memory_byte,
read_register_base => config.read_register_base,
read_register_byte => config.read_register_byte,
write_register_base => config.write_register_base,
write_register_byte => config.write_register_byte,
utf8_decoding_base => config.utf8_decoding_base,
utf8_decoding_byte => config.utf8_decoding_byte,
utf16_decoding_base => config.utf16_decoding_base,
utf16_decoding_byte => config.utf16_decoding_byte,
sha256_base => config.sha256_base,
sha256_byte => config.sha256_byte,
keccak256_base => config.keccak256_base,
keccak256_byte => config.keccak256_byte,
keccak512_base => config.keccak512_base,
keccak512_byte => config.keccak512_byte,
log_base => config.log_base,
log_byte => config.log_byte,
storage_write_base => config.storage_write_base,
storage_write_key_byte => config.storage_write_key_byte,
storage_write_value_byte => config.storage_write_value_byte,
storage_write_evicted_byte => config.storage_write_evicted_byte,
storage_read_base => config.storage_read_base,
storage_read_key_byte => config.storage_read_key_byte,
storage_read_value_byte => config.storage_read_value_byte,
storage_remove_base => config.storage_remove_base,
storage_remove_key_byte => config.storage_remove_key_byte,
storage_remove_ret_value_byte => config.storage_remove_ret_value_byte,
storage_has_key_base => config.storage_has_key_base,
storage_has_key_byte => config.storage_has_key_byte,
storage_iter_create_prefix_base => config.storage_iter_create_prefix_base,
storage_iter_create_prefix_byte => config.storage_iter_create_prefix_byte,
storage_iter_create_range_base => config.storage_iter_create_range_base,
storage_iter_create_from_byte => config.storage_iter_create_from_byte,
storage_iter_create_to_byte => config.storage_iter_create_to_byte,
storage_iter_next_base => config.storage_iter_next_base,
storage_iter_next_key_byte => config.storage_iter_next_key_byte,
storage_iter_next_value_byte => config.storage_iter_next_value_byte,
touching_trie_node => config.touching_trie_node,
promise_and_base => config.promise_and_base,
promise_and_per_promise => config.promise_and_per_promise,
promise_return => config.promise_return,
validator_stake_base => config.validator_stake_base,
validator_total_stake_base => config.validator_total_stake_base,
}
}
pub const fn count() -> usize {
ExtCosts::validator_total_stake_base as usize + 1
}
pub fn name_of(index: usize) -> &'static str {
vec![
"base",
"contract_compile_base",
"contract_compile_bytes",
"read_memory_base",
"read_memory_byte",
"write_memory_base",
"write_memory_byte",
"read_register_base",
"read_register_byte",
"write_register_base",
"write_register_byte",
"utf8_decoding_base",
"utf8_decoding_byte",
"utf16_decoding_base",
"utf16_decoding_byte",
"sha256_base",
"sha256_byte",
"keccak256_base",
"keccak256_byte",
"keccak512_base",
"keccak512_byte",
"log_base",
"log_byte",
"storage_write_base",
"storage_write_key_byte",
"storage_write_value_byte",
"storage_write_evicted_byte",
"storage_read_base",
"storage_read_key_byte",
"storage_read_value_byte",
"storage_remove_base",
"storage_remove_key_byte",
"storage_remove_ret_value_byte",
"storage_has_key_base",
"storage_has_key_byte",
"storage_iter_create_prefix_base",
"storage_iter_create_prefix_byte",
"storage_iter_create_range_base",
"storage_iter_create_from_byte",
"storage_iter_create_to_byte",
"storage_iter_next_base",
"storage_iter_next_key_byte",
"storage_iter_next_value_byte",
"touching_trie_node",
"promise_and_base",
"promise_and_per_promise",
"promise_return",
"validator_stake_base",
"validator_total_stake_base",
][index]
}
}