From b133a43a3a0f70ad32c23a107e4192ce02ebcd49 Mon Sep 17 00:00:00 2001 From: Jakob Meier Date: Wed, 11 Jan 2023 15:51:40 +0100 Subject: [PATCH] feat: gas profile by parameter (#8148) This resolves #8033, completing the gas profile by parameter effort. The main achievement here is that we can now look at gas profiles and know exactly for which parameter it has been spent. Code wise, the old `enum Cost` used in profiles only is finally gone. The tricky parts in this PR are to make sure that old profiles stored on DB are still understood and presented correctly in RPC calls. --- CHANGELOG.md | 2 + Cargo.lock | 1 + core/primitives-core/Cargo.toml | 2 + core/primitives-core/src/config.rs | 155 +++---- core/primitives-core/src/profile.rs | 412 +++++++++--------- .../primitives-core/src/profile/profile_v2.rs | 265 +++++++++++ ..._profile_v2__test__profile_data_debug.snap | 78 ++++ ..._profile_v1__test__profile_data_debug.snap | 78 ++++ ...re__profile__test__profile_data_debug.snap | 83 ++++ ...__views__tests__exec_metadata_v1_view.snap | 8 + ...__views__tests__exec_metadata_v2_view.snap | 359 +++++++++++++++ ...__views__tests__exec_metadata_v3_view.snap | 374 ++++++++++++++++ ...es__views__tests__runtime_config_view.snap | 201 +++++++++ core/primitives/src/transaction.rs | 11 +- core/primitives/src/views.rs | 210 ++++++--- .../client/features/chunk_nodes_cache.rs | 3 +- ...__sanity_checks__receipts_gas_profile.snap | 34 +- ..._checks__receipts_gas_profile_nightly.snap | 34 +- runtime/near-vm-logic/src/gas_counter.rs | 6 +- runtime/near-vm-logic/src/logic.rs | 6 +- runtime/runtime/src/lib.rs | 6 +- 21 files changed, 1955 insertions(+), 373 deletions(-) create mode 100644 core/primitives-core/src/profile/profile_v2.rs create mode 100644 core/primitives-core/src/profile/snapshots/near_primitives_core__profile__profile_v2__test__profile_data_debug.snap create mode 100644 core/primitives-core/src/snapshots/near_primitives_core__profile__profile_v1__test__profile_data_debug.snap create mode 100644 core/primitives-core/src/snapshots/near_primitives_core__profile__test__profile_data_debug.snap create mode 100644 core/primitives/src/snapshots/near_primitives__views__tests__exec_metadata_v1_view.snap create mode 100644 core/primitives/src/snapshots/near_primitives__views__tests__exec_metadata_v2_view.snap create mode 100644 core/primitives/src/snapshots/near_primitives__views__tests__exec_metadata_v3_view.snap create mode 100644 core/primitives/src/snapshots/near_primitives__views__tests__runtime_config_view.snap diff --git a/CHANGELOG.md b/CHANGELOG.md index d2d9154825e..19ba761f9b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,8 @@ `opentelemetry-otlp`: [#7563](https://github.com/near/nearcore/pull/7563). * Tracing of requests across processes: [#8004](https://github.com/near/nearcore/pull/8004). +* Gas profiles as displayed in the `EXPERIMENTAL_tx_status` are now more + detailed and give the gas cost per parameter. ## 1.30.0 diff --git a/Cargo.lock b/Cargo.lock index c7eb02b9f46..d46aba46137 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3506,6 +3506,7 @@ dependencies = [ "bs58", "derive_more", "enum-map", + "insta", "near-account-id", "num-rational", "serde", diff --git a/core/primitives-core/Cargo.toml b/core/primitives-core/Cargo.toml index 2c3bd756710..617391b1602 100644 --- a/core/primitives-core/Cargo.toml +++ b/core/primitives-core/Cargo.toml @@ -30,7 +30,9 @@ near-account-id = { path = "../account-id", features = ["arbitrary"] } [dev-dependencies] serde_json.workspace = true +insta.workspace = true [features] default = [] protocol_feature_ed25519_verify = [] +nightly = ["protocol_feature_ed25519_verify"] diff --git a/core/primitives-core/src/config.rs b/core/primitives-core/src/config.rs index 17d794bf380..7e230769592 100644 --- a/core/primitives-core/src/config.rs +++ b/core/primitives-core/src/config.rs @@ -359,6 +359,9 @@ impl ExtCostsConfig { } /// Strongly-typed representation of the fees for counting. +/// +/// Do not change the enum discriminants here, they are used for borsh +/// (de-)serialization. #[derive( Copy, Clone, @@ -374,69 +377,69 @@ impl ExtCostsConfig { )] #[allow(non_camel_case_types)] pub enum ExtCosts { - base, - contract_loading_base, - contract_loading_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, - ripemd160_base, - ripemd160_block, + base = 0, + contract_loading_base = 1, + contract_loading_bytes = 2, + read_memory_base = 3, + read_memory_byte = 4, + write_memory_base = 5, + write_memory_byte = 6, + read_register_base = 7, + read_register_byte = 8, + write_register_base = 9, + write_register_byte = 10, + utf8_decoding_base = 11, + utf8_decoding_byte = 12, + utf16_decoding_base = 13, + utf16_decoding_byte = 14, + sha256_base = 15, + sha256_byte = 16, + keccak256_base = 17, + keccak256_byte = 18, + keccak512_base = 19, + keccak512_byte = 20, + ripemd160_base = 21, + ripemd160_block = 22, + ecrecover_base = 23, + log_base = 24, + log_byte = 25, + storage_write_base = 26, + storage_write_key_byte = 27, + storage_write_value_byte = 28, + storage_write_evicted_byte = 29, + storage_read_base = 30, + storage_read_key_byte = 31, + storage_read_value_byte = 32, + storage_remove_base = 33, + storage_remove_key_byte = 34, + storage_remove_ret_value_byte = 35, + storage_has_key_base = 36, + storage_has_key_byte = 37, + storage_iter_create_prefix_base = 38, + storage_iter_create_prefix_byte = 39, + storage_iter_create_range_base = 40, + storage_iter_create_from_byte = 41, + storage_iter_create_to_byte = 42, + storage_iter_next_base = 43, + storage_iter_next_key_byte = 44, + storage_iter_next_value_byte = 45, + touching_trie_node = 46, + read_cached_trie_node = 47, + promise_and_base = 48, + promise_and_per_promise = 49, + promise_return = 50, + validator_stake_base = 51, + validator_total_stake_base = 52, + alt_bn128_g1_multiexp_base = 53, + alt_bn128_g1_multiexp_element = 54, + alt_bn128_pairing_check_base = 55, + alt_bn128_pairing_check_element = 56, + alt_bn128_g1_sum_base = 57, + alt_bn128_g1_sum_element = 58, #[cfg(feature = "protocol_feature_ed25519_verify")] - ed25519_verify_base, + ed25519_verify_base = 59, #[cfg(feature = "protocol_feature_ed25519_verify")] - ed25519_verify_byte, - ecrecover_base, - 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, - read_cached_trie_node, - promise_and_base, - promise_and_per_promise, - promise_return, - validator_stake_base, - validator_total_stake_base, - alt_bn128_g1_multiexp_base, - alt_bn128_g1_multiexp_element, - alt_bn128_pairing_check_base, - alt_bn128_pairing_check_element, - alt_bn128_g1_sum_base, - alt_bn128_g1_sum_element, + ed25519_verify_byte = 60, } // Type of an action, used in fees logic. @@ -455,21 +458,21 @@ pub enum ExtCosts { )] #[allow(non_camel_case_types)] pub enum ActionCosts { - create_account, - delete_account, - deploy_contract_base, - deploy_contract_byte, - function_call_base, - function_call_byte, - transfer, - stake, - add_full_access_key, - add_function_call_key_base, - add_function_call_key_byte, - delete_key, - new_action_receipt, - new_data_receipt_base, - new_data_receipt_byte, + create_account = 0, + delete_account = 1, + deploy_contract_base = 2, + deploy_contract_byte = 3, + function_call_base = 4, + function_call_byte = 5, + transfer = 6, + stake = 7, + add_full_access_key = 8, + add_function_call_key_base = 9, + add_function_call_key_byte = 10, + delete_key = 11, + new_action_receipt = 12, + new_data_receipt_base = 13, + new_data_receipt_byte = 14, } impl ExtCosts { diff --git a/core/primitives-core/src/profile.rs b/core/primitives-core/src/profile.rs index 2cf232ad80c..cd0bb3d1a48 100644 --- a/core/primitives-core/src/profile.rs +++ b/core/primitives-core/src/profile.rs @@ -1,88 +1,76 @@ +pub use profile_v2::ProfileDataV2; + use crate::config::{ActionCosts, ExtCosts}; +use crate::types::Gas; use borsh::{BorshDeserialize, BorshSerialize}; +use enum_map::{enum_map, Enum, EnumMap}; use std::fmt; -use std::ops::{Index, IndexMut}; use strum::IntoEnumIterator; -/// Serialization format to store profiles in the database. -/// -/// This is not part of the protocol but archival nodes still rely on this not -/// changing to answer old tx-status requests with a gas profile. -#[derive(Clone, PartialEq, Eq)] -pub struct DataArray(Box<[u64; Self::LEN]>); - -impl DataArray { - pub const LEN: usize = if cfg!(feature = "protocol_feature_ed25519_verify") { 72 } else { 70 }; -} - -impl Index for DataArray { - type Output = u64; - - fn index(&self, index: usize) -> &Self::Output { - &self.0[index] - } -} - -impl IndexMut for DataArray { - fn index_mut(&mut self, index: usize) -> &mut Self::Output { - &mut self.0[index] - } -} - -impl BorshDeserialize for DataArray { - fn deserialize(buf: &mut &[u8]) -> Result { - let data_vec: Vec = BorshDeserialize::deserialize(buf)?; - let mut data_array = [0; Self::LEN]; - let len = Self::LEN.min(data_vec.len()); - data_array[0..len].copy_from_slice(&data_vec[0..len]); - Ok(Self(Box::new(data_array))) - } -} - -impl BorshSerialize for DataArray { - fn serialize(&self, writer: &mut W) -> Result<(), std::io::Error> { - let v: Vec<_> = self.0.as_ref().to_vec(); - BorshSerialize::serialize(&v, writer) - } -} +mod profile_v2; /// Profile of gas consumption. -/// When add new cost, the new cost should also be append to profile_index -#[derive(Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] -pub struct ProfileData { - data: DataArray, +#[derive(Clone, PartialEq, Eq)] +pub struct ProfileDataV3 { + /// Gas spent on sending or executing actions. + actions_profile: EnumMap, + /// Non-action gas spent outside the WASM VM while executing a contract. + wasm_ext_profile: EnumMap, + /// Gas spent on execution inside the WASM VM. + wasm_gas: Gas, } -impl Default for ProfileData { - fn default() -> ProfileData { - ProfileData::new() +impl Default for ProfileDataV3 { + fn default() -> ProfileDataV3 { + ProfileDataV3::new() } } -impl ProfileData { +impl ProfileDataV3 { #[inline] pub fn new() -> Self { - let costs = DataArray(Box::new([0; DataArray::LEN])); - ProfileData { data: costs } + Self { + actions_profile: enum_map! { _ => 0 }, + wasm_ext_profile: enum_map! { _ => 0 }, + wasm_gas: 0, + } + } + + /// Test instance with unique numbers in each field. + pub fn test() -> Self { + let mut profile_data = ProfileDataV3::default(); + for (i, cost) in ExtCosts::iter().enumerate() { + profile_data.add_ext_cost(cost, i as Gas); + } + for (i, cost) in ActionCosts::iter().enumerate() { + profile_data.add_action_cost(cost, i as Gas + 1000); + } + profile_data } #[inline] - pub fn merge(&mut self, other: &ProfileData) { - for i in 0..DataArray::LEN { - self.data[i] = self.data[i].saturating_add(other.data[i]); + pub fn merge(&mut self, other: &ProfileDataV3) { + for ((_, gas), (_, other_gas)) in + self.actions_profile.iter_mut().zip(other.actions_profile.iter()) + { + *gas = gas.saturating_add(*other_gas); + } + for ((_, gas), (_, other_gas)) in + self.wasm_ext_profile.iter_mut().zip(other.wasm_ext_profile.iter()) + { + *gas = gas.saturating_add(*other_gas); } + self.wasm_gas = self.wasm_gas.saturating_add(other.wasm_gas); } #[inline] pub fn add_action_cost(&mut self, action: ActionCosts, value: u64) { - self[Cost::ActionCost { action_cost_kind: action }] = - self[Cost::ActionCost { action_cost_kind: action }].saturating_add(value); + self.actions_profile[action] = self.actions_profile[action].saturating_add(value); } #[inline] pub fn add_ext_cost(&mut self, ext: ExtCosts, value: u64) { - self[Cost::ExtCost { ext_cost_kind: ext }] = - self[Cost::ExtCost { ext_cost_kind: ext }].saturating_add(value); + self.wasm_ext_profile[ext] = self.wasm_ext_profile[ext].saturating_add(value); } /// WasmInstruction is the only cost we don't explicitly account for. @@ -94,37 +82,100 @@ impl ProfileData { /// with the help on the VM side, so we don't want to have profiling logic /// there both for simplicity and efficiency reasons. pub fn compute_wasm_instruction_cost(&mut self, total_gas_burnt: u64) { - self[Cost::WasmInstruction] = + self.wasm_gas = total_gas_burnt.saturating_sub(self.action_gas()).saturating_sub(self.host_gas()); } - fn get_action_cost(&self, action: ActionCosts) -> u64 { - self[Cost::ActionCost { action_cost_kind: action }] + pub fn get_action_cost(&self, action: ActionCosts) -> u64 { + self.actions_profile[action] } pub fn get_ext_cost(&self, ext: ExtCosts) -> u64 { - self[Cost::ExtCost { ext_cost_kind: ext }] + self.wasm_ext_profile[ext] + } + + pub fn get_wasm_cost(&self) -> u64 { + self.wasm_gas } fn host_gas(&self) -> u64 { - ExtCosts::iter().map(|a| self.get_ext_cost(a)).fold(0, u64::saturating_add) + self.wasm_ext_profile.as_slice().iter().copied().fold(0, u64::saturating_add) } pub fn action_gas(&self) -> u64 { - // TODO(#8033): Temporary hack to work around multiple action costs - // mapping to the same profile entry. Can be removed as soon as inner - // tracking of profile is tracked by parameter or when the profile is - // more detail, which ever happens first. - let mut indices: Vec<_> = ActionCosts::iter() - .map(|action_cost_kind| Cost::ActionCost { action_cost_kind }.profile_index()) - .collect(); - indices.sort_unstable(); - indices.dedup(); - indices.into_iter().map(|i| self.data[i]).fold(0, u64::saturating_add) + self.actions_profile.as_slice().iter().copied().fold(0, u64::saturating_add) } } -impl fmt::Debug for ProfileData { +impl BorshDeserialize for ProfileDataV3 { + fn deserialize(buf: &mut &[u8]) -> Result { + let actions_array: Vec = BorshDeserialize::deserialize(buf)?; + let ext_array: Vec = BorshDeserialize::deserialize(buf)?; + let wasm_gas: u64 = BorshDeserialize::deserialize(buf)?; + + // Mapping raw arrays to enum maps. + // The enum map could be smaller or larger than the raw array. + // Extra values in the array that are unknown to the current binary will + // be ignored. Missing values are filled with 0. + let actions_profile = enum_map! { + cost => actions_array.get(borsh_action_index(cost)).copied().unwrap_or(0) + }; + let wasm_ext_profile = enum_map! { + cost => ext_array.get(borsh_ext_index(cost)).copied().unwrap_or(0) + }; + + Ok(Self { actions_profile, wasm_ext_profile, wasm_gas }) + } +} + +impl BorshSerialize for ProfileDataV3 { + fn serialize(&self, writer: &mut W) -> Result<(), std::io::Error> { + let mut actions_costs: Vec = vec![0u64; ActionCosts::LENGTH]; + for (cost, gas) in self.actions_profile.iter() { + actions_costs[borsh_action_index(cost)] = *gas; + } + BorshSerialize::serialize(&actions_costs, writer)?; + + let mut ext_costs: Vec = vec![0u64; ExtCosts::LENGTH]; + for (cost, gas) in self.wasm_ext_profile.iter() { + ext_costs[borsh_ext_index(cost)] = *gas; + } + BorshSerialize::serialize(&ext_costs, writer)?; + + let wasm_cost: u64 = self.wasm_gas; + BorshSerialize::serialize(&wasm_cost, writer) + } +} + +/// Fixed index of an action cost for borsh (de)serialization. +/// +/// We use borsh to store profiles on the DB and borsh is quite fragile with +/// changes. This mapping is to decouple the Rust enum from the borsh +/// representation. The enum can be changed freely but here in the mapping we +/// can only append more values at the end. +/// +/// TODO: Consider changing this to a different format (e.g. protobuf) because +/// canonical representation is not required here. +const fn borsh_action_index(action: ActionCosts) -> usize { + // actual indices are defined on the enum variants + action as usize +} + +/// Fixed index of an ext cost for borsh (de)serialization. +/// +/// We use borsh to store profiles on the DB and borsh is quite fragile with +/// changes. This mapping is to decouple the Rust enum from the borsh +/// representation. The enum can be changed freely but here in the mapping we +/// can only append more values at the end. +/// +/// TODO: Consider changing this to a different format (e.g. protobuf) because +/// canonical representation is not required here. +const fn borsh_ext_index(ext: ExtCosts) -> usize { + // actual indices are defined on the enum variants + ext as usize +} + +impl fmt::Debug for ProfileDataV3 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use num_rational::Ratio; let host_gas = self.host_gas(); @@ -157,146 +208,30 @@ impl fmt::Debug for ProfileData { } } -#[derive(Clone, Copy, Debug)] -pub enum Cost { - ActionCost { action_cost_kind: ActionCosts }, - ExtCost { ext_cost_kind: ExtCosts }, - WasmInstruction, -} - -impl Cost { - pub fn iter() -> impl Iterator { - let actions = - ActionCosts::iter().map(|action_cost_kind| Cost::ActionCost { action_cost_kind }); - let ext = ExtCosts::iter().map(|ext_cost_kind| Cost::ExtCost { ext_cost_kind }); - let op = std::iter::once(Cost::WasmInstruction); - actions.chain(ext).chain(op) - } - - /// Entry in DataArray inside the gas profile. - /// - /// Entries can be shared by multiple costs. - /// - /// TODO: Remove after completing all of #8033. - pub fn profile_index(self) -> usize { - // make sure to increase `DataArray::LEN` when adding a new index - match self { - Cost::ActionCost { action_cost_kind: ActionCosts::create_account } => 0, - Cost::ActionCost { action_cost_kind: ActionCosts::delete_account } => 1, - Cost::ActionCost { action_cost_kind: ActionCosts::deploy_contract_base } => 2, - Cost::ActionCost { action_cost_kind: ActionCosts::deploy_contract_byte } => 2, - Cost::ActionCost { action_cost_kind: ActionCosts::function_call_base } => 3, - Cost::ActionCost { action_cost_kind: ActionCosts::function_call_byte } => 3, - Cost::ActionCost { action_cost_kind: ActionCosts::transfer } => 4, - Cost::ActionCost { action_cost_kind: ActionCosts::stake } => 5, - Cost::ActionCost { action_cost_kind: ActionCosts::add_full_access_key } => 6, - Cost::ActionCost { action_cost_kind: ActionCosts::add_function_call_key_base } => 6, - Cost::ActionCost { action_cost_kind: ActionCosts::add_function_call_key_byte } => 6, - Cost::ActionCost { action_cost_kind: ActionCosts::delete_key } => 7, - Cost::ActionCost { action_cost_kind: ActionCosts::new_data_receipt_byte } => 8, - Cost::ActionCost { action_cost_kind: ActionCosts::new_action_receipt } => 9, - Cost::ActionCost { action_cost_kind: ActionCosts::new_data_receipt_base } => 9, - Cost::ExtCost { ext_cost_kind: ExtCosts::base } => 10, - Cost::ExtCost { ext_cost_kind: ExtCosts::contract_loading_base } => 11, - Cost::ExtCost { ext_cost_kind: ExtCosts::contract_loading_bytes } => 12, - Cost::ExtCost { ext_cost_kind: ExtCosts::read_memory_base } => 13, - Cost::ExtCost { ext_cost_kind: ExtCosts::read_memory_byte } => 14, - Cost::ExtCost { ext_cost_kind: ExtCosts::write_memory_base } => 15, - Cost::ExtCost { ext_cost_kind: ExtCosts::write_memory_byte } => 16, - Cost::ExtCost { ext_cost_kind: ExtCosts::read_register_base } => 17, - Cost::ExtCost { ext_cost_kind: ExtCosts::read_register_byte } => 18, - Cost::ExtCost { ext_cost_kind: ExtCosts::write_register_base } => 19, - Cost::ExtCost { ext_cost_kind: ExtCosts::write_register_byte } => 20, - Cost::ExtCost { ext_cost_kind: ExtCosts::utf8_decoding_base } => 21, - Cost::ExtCost { ext_cost_kind: ExtCosts::utf8_decoding_byte } => 22, - Cost::ExtCost { ext_cost_kind: ExtCosts::utf16_decoding_base } => 23, - Cost::ExtCost { ext_cost_kind: ExtCosts::utf16_decoding_byte } => 24, - Cost::ExtCost { ext_cost_kind: ExtCosts::sha256_base } => 25, - Cost::ExtCost { ext_cost_kind: ExtCosts::sha256_byte } => 26, - Cost::ExtCost { ext_cost_kind: ExtCosts::keccak256_base } => 27, - Cost::ExtCost { ext_cost_kind: ExtCosts::keccak256_byte } => 28, - Cost::ExtCost { ext_cost_kind: ExtCosts::keccak512_base } => 29, - Cost::ExtCost { ext_cost_kind: ExtCosts::keccak512_byte } => 30, - Cost::ExtCost { ext_cost_kind: ExtCosts::ripemd160_base } => 31, - Cost::ExtCost { ext_cost_kind: ExtCosts::ripemd160_block } => 32, - Cost::ExtCost { ext_cost_kind: ExtCosts::ecrecover_base } => 33, - Cost::ExtCost { ext_cost_kind: ExtCosts::log_base } => 34, - Cost::ExtCost { ext_cost_kind: ExtCosts::log_byte } => 35, - Cost::ExtCost { ext_cost_kind: ExtCosts::storage_write_base } => 36, - Cost::ExtCost { ext_cost_kind: ExtCosts::storage_write_key_byte } => 37, - Cost::ExtCost { ext_cost_kind: ExtCosts::storage_write_value_byte } => 38, - Cost::ExtCost { ext_cost_kind: ExtCosts::storage_write_evicted_byte } => 39, - Cost::ExtCost { ext_cost_kind: ExtCosts::storage_read_base } => 40, - Cost::ExtCost { ext_cost_kind: ExtCosts::storage_read_key_byte } => 41, - Cost::ExtCost { ext_cost_kind: ExtCosts::storage_read_value_byte } => 42, - Cost::ExtCost { ext_cost_kind: ExtCosts::storage_remove_base } => 43, - Cost::ExtCost { ext_cost_kind: ExtCosts::storage_remove_key_byte } => 44, - Cost::ExtCost { ext_cost_kind: ExtCosts::storage_remove_ret_value_byte } => 45, - Cost::ExtCost { ext_cost_kind: ExtCosts::storage_has_key_base } => 46, - Cost::ExtCost { ext_cost_kind: ExtCosts::storage_has_key_byte } => 47, - Cost::ExtCost { ext_cost_kind: ExtCosts::storage_iter_create_prefix_base } => 48, - Cost::ExtCost { ext_cost_kind: ExtCosts::storage_iter_create_prefix_byte } => 49, - Cost::ExtCost { ext_cost_kind: ExtCosts::storage_iter_create_range_base } => 50, - Cost::ExtCost { ext_cost_kind: ExtCosts::storage_iter_create_from_byte } => 51, - Cost::ExtCost { ext_cost_kind: ExtCosts::storage_iter_create_to_byte } => 52, - Cost::ExtCost { ext_cost_kind: ExtCosts::storage_iter_next_base } => 53, - Cost::ExtCost { ext_cost_kind: ExtCosts::storage_iter_next_key_byte } => 54, - Cost::ExtCost { ext_cost_kind: ExtCosts::storage_iter_next_value_byte } => 55, - Cost::ExtCost { ext_cost_kind: ExtCosts::touching_trie_node } => 56, - Cost::ExtCost { ext_cost_kind: ExtCosts::promise_and_base } => 57, - Cost::ExtCost { ext_cost_kind: ExtCosts::promise_and_per_promise } => 58, - Cost::ExtCost { ext_cost_kind: ExtCosts::promise_return } => 59, - Cost::ExtCost { ext_cost_kind: ExtCosts::validator_stake_base } => 60, - Cost::ExtCost { ext_cost_kind: ExtCosts::validator_total_stake_base } => 61, - Cost::WasmInstruction => 62, - Cost::ExtCost { ext_cost_kind: ExtCosts::read_cached_trie_node } => 63, - Cost::ExtCost { ext_cost_kind: ExtCosts::alt_bn128_g1_multiexp_base } => 64, - Cost::ExtCost { ext_cost_kind: ExtCosts::alt_bn128_g1_multiexp_element } => 65, - Cost::ExtCost { ext_cost_kind: ExtCosts::alt_bn128_pairing_check_base } => 66, - Cost::ExtCost { ext_cost_kind: ExtCosts::alt_bn128_pairing_check_element } => 67, - Cost::ExtCost { ext_cost_kind: ExtCosts::alt_bn128_g1_sum_base } => 68, - Cost::ExtCost { ext_cost_kind: ExtCosts::alt_bn128_g1_sum_element } => 69, - #[cfg(feature = "protocol_feature_ed25519_verify")] - Cost::ExtCost { ext_cost_kind: ExtCosts::ed25519_verify_base } => 70, - #[cfg(feature = "protocol_feature_ed25519_verify")] - Cost::ExtCost { ext_cost_kind: ExtCosts::ed25519_verify_byte } => 71, - } - } -} - -impl Index for ProfileData { - type Output = u64; - - fn index(&self, index: Cost) -> &Self::Output { - &self.data[index.profile_index()] - } -} - -impl IndexMut for ProfileData { - fn index_mut(&mut self, index: Cost) -> &mut Self::Output { - &mut self.data[index.profile_index()] - } -} - +/// Tests for ProfileDataV3 #[cfg(test)] mod test { use super::*; #[test] + #[cfg(not(feature = "nightly"))] fn test_profile_data_debug() { - let profile_data = ProfileData::new(); - println!("{:#?}", &profile_data); + let profile_data = ProfileDataV3::test(); + // we don't care about exact formatting, but the numbers should not change unexpectedly + let pretty_debug_str = format!("{profile_data:#?}"); + insta::assert_snapshot!(pretty_debug_str); } #[test] fn test_profile_data_debug_no_data() { - let profile_data = ProfileData::new(); + let profile_data = ProfileDataV3::default(); + // we don't care about exact formatting, but at least it should not panic println!("{:#?}", &profile_data); } #[test] fn test_no_panic_on_overflow() { - let mut profile_data = ProfileData::new(); + let mut profile_data = ProfileDataV3::default(); profile_data.add_action_cost(ActionCosts::add_full_access_key, u64::MAX); profile_data.add_action_cost(ActionCosts::add_full_access_key, u64::MAX); @@ -306,11 +241,11 @@ mod test { #[test] fn test_merge() { - let mut profile_data = ProfileData::new(); + let mut profile_data = ProfileDataV3::default(); profile_data.add_action_cost(ActionCosts::add_full_access_key, 111); profile_data.add_ext_cost(ExtCosts::storage_read_base, 11); - let mut profile_data2 = ProfileData::new(); + let mut profile_data2 = ProfileDataV3::default(); profile_data2.add_action_cost(ActionCosts::add_full_access_key, 222); profile_data2.add_ext_cost(ExtCosts::storage_read_base, 22); @@ -320,10 +255,73 @@ mod test { } #[test] - fn test_profile_len() { - let mut indices: Vec<_> = Cost::iter().map(|i| i.profile_index()).collect(); - indices.sort(); - indices.dedup(); - assert_eq!(indices.len(), DataArray::LEN); + fn test_borsh_ser_deser() { + let mut profile_data = ProfileDataV3::default(); + for (i, cost) in ExtCosts::iter().enumerate() { + profile_data.add_ext_cost(cost, i as Gas); + } + for (i, cost) in ActionCosts::iter().enumerate() { + profile_data.add_action_cost(cost, i as Gas + 1000); + } + let buf = profile_data.try_to_vec().expect("failed serializing a normal profile"); + + let restored: ProfileDataV3 = BorshDeserialize::deserialize(&mut buf.as_slice()) + .expect("failed deserializing a normal profile"); + + assert_eq!(profile_data, restored); + } + + #[test] + fn test_borsh_incomplete_profile() { + let action_profile = vec![50u64, 60]; + let ext_profile = vec![100u64, 200]; + let wasm_cost = 99u64; + let input = manually_encode_profile_v2(action_profile, ext_profile, wasm_cost); + + let profile: ProfileDataV3 = BorshDeserialize::deserialize(&mut input.as_slice()) + .expect("should be able to parse a profile with less entries"); + + assert_eq!(50, profile.get_action_cost(ActionCosts::create_account)); + assert_eq!(60, profile.get_action_cost(ActionCosts::delete_account)); + assert_eq!(0, profile.get_action_cost(ActionCosts::deploy_contract_base)); + + assert_eq!(100, profile.get_ext_cost(ExtCosts::base)); + assert_eq!(200, profile.get_ext_cost(ExtCosts::contract_loading_base)); + assert_eq!(0, profile.get_ext_cost(ExtCosts::contract_loading_bytes)); + } + + #[test] + fn test_borsh_larger_profile_than_current() { + let action_profile = vec![1234u64; ActionCosts::LENGTH + 5]; + let ext_profile = vec![5678u64; ExtCosts::LENGTH + 10]; + let wasm_cost = 90u64; + let input = manually_encode_profile_v2(action_profile, ext_profile, wasm_cost); + + let profile: ProfileDataV3 = BorshDeserialize::deserialize(&mut input.as_slice()).expect( + "should be able to parse a profile with more entries than the current version has", + ); + + for action in ActionCosts::iter() { + assert_eq!(1234, profile.get_action_cost(action), "{action:?}"); + } + + for ext in ExtCosts::iter() { + assert_eq!(5678, profile.get_ext_cost(ext), "{ext:?}"); + } + + assert_eq!(90, profile.wasm_gas); + } + + #[track_caller] + fn manually_encode_profile_v2( + action_profile: Vec, + ext_profile: Vec, + wasm_cost: u64, + ) -> Vec { + let mut input = vec![]; + BorshSerialize::serialize(&action_profile, &mut input).unwrap(); + BorshSerialize::serialize(&ext_profile, &mut input).unwrap(); + BorshSerialize::serialize(&wasm_cost, &mut input).unwrap(); + input } } diff --git a/core/primitives-core/src/profile/profile_v2.rs b/core/primitives-core/src/profile/profile_v2.rs new file mode 100644 index 00000000000..e0086cf55c0 --- /dev/null +++ b/core/primitives-core/src/profile/profile_v2.rs @@ -0,0 +1,265 @@ +use crate::config::{ActionCosts, ExtCosts}; +use crate::types::Gas; +use borsh::{BorshDeserialize, BorshSerialize}; +use std::fmt; +use std::ops::Index; +use strum::IntoEnumIterator; + +/// Deprecated serialization format to store profiles in the database. +/// +/// There is no ProfileDataV1 because meta data V1 did no have profiles. +/// Counting thus starts with 2 to match the meta data version numbers. +/// +/// This is not part of the protocol but archival nodes still rely on this not +/// changing to answer old tx-status requests with a gas profile. +/// +/// It used to store an array that manually mapped `enum Cost` to gas +/// numbers. Now `ProfileDataV2` and `Cost` are deprecated. But to lookup +/// old gas profiles from the DB, we need to keep the code around. +#[derive(Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] +pub struct ProfileDataV2 { + data: DataArray, +} + +#[derive(Clone, PartialEq, Eq)] +struct DataArray(Box<[u64; Self::LEN]>); + +impl DataArray { + const LEN: usize = if cfg!(feature = "protocol_feature_ed25519_verify") { 72 } else { 70 }; +} + +impl ProfileDataV2 { + pub fn get_ext_cost(&self, ext: ExtCosts) -> u64 { + self[ext] + } + + pub fn get_wasm_cost(&self) -> u64 { + // ProfileV2Cost::WasmInstruction => 62, + self.data[62] + } + + fn host_gas(&self) -> u64 { + ExtCosts::iter().map(|a| self.get_ext_cost(a)).fold(0, u64::saturating_add) + } + + /// List action cost in the old way, which conflated several action parameters into one. + /// + /// This is used to display old gas profiles on the RPC API and in debug output. + pub fn legacy_action_costs(&self) -> Vec<(&'static str, Gas)> { + vec![ + ("CREATE_ACCOUNT", self.data[0]), + ("DELETE_ACCOUNT", self.data[1]), + ("DEPLOY_CONTRACT", self.data[2]), // contains per byte and base cost + ("FUNCTION_CALL", self.data[3]), // contains per byte and base cost + ("TRANSFER", self.data[4]), + ("STAKE", self.data[5]), + ("ADD_KEY", self.data[6]), // contains base + per byte cost for function call keys and full access keys + ("DELETE_KEY", self.data[7]), + ("NEW_DATA_RECEIPT_BYTE", self.data[8]), // contains the per-byte cost for sending back a data dependency + ("NEW_RECEIPT", self.data[9]), // contains base cost for data receipts and action receipts + ] + } + + pub fn action_gas(&self) -> u64 { + self.legacy_action_costs().iter().map(|(_name, cost)| *cost).fold(0, u64::saturating_add) + } + + /// Test instance with unique numbers in each field. + pub fn test() -> Self { + let mut profile_data = ProfileDataV2::default(); + let num_legacy_actions = 10; + for i in 0..num_legacy_actions { + profile_data.data.0[i] = i as Gas + 1000; + } + for i in num_legacy_actions..DataArray::LEN { + profile_data.data.0[i] = (i - num_legacy_actions) as Gas; + } + profile_data + } +} + +impl fmt::Debug for ProfileDataV2 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use num_rational::Ratio; + let host_gas = self.host_gas(); + let action_gas = self.action_gas(); + + writeln!(f, "------------------------------")?; + writeln!(f, "Action gas: {}", action_gas)?; + writeln!(f, "------ Host functions --------")?; + for cost in ExtCosts::iter() { + let d = self.get_ext_cost(cost); + if d != 0 { + writeln!( + f, + "{} -> {} [{}% host]", + cost, + d, + Ratio::new(d * 100, core::cmp::max(host_gas, 1)).to_integer(), + )?; + } + } + writeln!(f, "------ Actions --------")?; + for (cost, gas) in self.legacy_action_costs() { + if gas != 0 { + writeln!(f, "{} -> {}", cost.to_ascii_lowercase(), gas)?; + } + } + writeln!(f, "------------------------------")?; + Ok(()) + } +} + +impl Index for DataArray { + type Output = u64; + + fn index(&self, index: usize) -> &Self::Output { + &self.0[index] + } +} + +impl Index for ProfileDataV2 { + type Output = u64; + + fn index(&self, cost: ActionCosts) -> &Self::Output { + let index = match cost { + ActionCosts::create_account => 0, + ActionCosts::delete_account => 1, + ActionCosts::deploy_contract_base => 2, + ActionCosts::deploy_contract_byte => 2, + ActionCosts::function_call_base => 3, + ActionCosts::function_call_byte => 3, + ActionCosts::transfer => 4, + ActionCosts::stake => 5, + ActionCosts::add_full_access_key => 6, + ActionCosts::add_function_call_key_base => 6, + ActionCosts::add_function_call_key_byte => 6, + ActionCosts::delete_key => 7, + ActionCosts::new_data_receipt_byte => 8, + ActionCosts::new_action_receipt => 9, + ActionCosts::new_data_receipt_base => 9, + // new costs added after profile v1 was deprecated don't have this entry + #[allow(unreachable_patterns)] + _ => return &0, + }; + &self.data[index] + } +} + +impl Index for ProfileDataV2 { + type Output = u64; + + fn index(&self, cost: ExtCosts) -> &Self::Output { + let index = match cost { + ExtCosts::base => 10, + ExtCosts::contract_loading_base => 11, + ExtCosts::contract_loading_bytes => 12, + ExtCosts::read_memory_base => 13, + ExtCosts::read_memory_byte => 14, + ExtCosts::write_memory_base => 15, + ExtCosts::write_memory_byte => 16, + ExtCosts::read_register_base => 17, + ExtCosts::read_register_byte => 18, + ExtCosts::write_register_base => 19, + ExtCosts::write_register_byte => 20, + ExtCosts::utf8_decoding_base => 21, + ExtCosts::utf8_decoding_byte => 22, + ExtCosts::utf16_decoding_base => 23, + ExtCosts::utf16_decoding_byte => 24, + ExtCosts::sha256_base => 25, + ExtCosts::sha256_byte => 26, + ExtCosts::keccak256_base => 27, + ExtCosts::keccak256_byte => 28, + ExtCosts::keccak512_base => 29, + ExtCosts::keccak512_byte => 30, + ExtCosts::ripemd160_base => 31, + ExtCosts::ripemd160_block => 32, + ExtCosts::ecrecover_base => 33, + ExtCosts::log_base => 34, + ExtCosts::log_byte => 35, + ExtCosts::storage_write_base => 36, + ExtCosts::storage_write_key_byte => 37, + ExtCosts::storage_write_value_byte => 38, + ExtCosts::storage_write_evicted_byte => 39, + ExtCosts::storage_read_base => 40, + ExtCosts::storage_read_key_byte => 41, + ExtCosts::storage_read_value_byte => 42, + ExtCosts::storage_remove_base => 43, + ExtCosts::storage_remove_key_byte => 44, + ExtCosts::storage_remove_ret_value_byte => 45, + ExtCosts::storage_has_key_base => 46, + ExtCosts::storage_has_key_byte => 47, + ExtCosts::storage_iter_create_prefix_base => 48, + ExtCosts::storage_iter_create_prefix_byte => 49, + ExtCosts::storage_iter_create_range_base => 50, + ExtCosts::storage_iter_create_from_byte => 51, + ExtCosts::storage_iter_create_to_byte => 52, + ExtCosts::storage_iter_next_base => 53, + ExtCosts::storage_iter_next_key_byte => 54, + ExtCosts::storage_iter_next_value_byte => 55, + ExtCosts::touching_trie_node => 56, + ExtCosts::promise_and_base => 57, + ExtCosts::promise_and_per_promise => 58, + ExtCosts::promise_return => 59, + ExtCosts::validator_stake_base => 60, + ExtCosts::validator_total_stake_base => 61, + ExtCosts::read_cached_trie_node => 63, + ExtCosts::alt_bn128_g1_multiexp_base => 64, + ExtCosts::alt_bn128_g1_multiexp_element => 65, + ExtCosts::alt_bn128_pairing_check_base => 66, + ExtCosts::alt_bn128_pairing_check_element => 67, + ExtCosts::alt_bn128_g1_sum_base => 68, + ExtCosts::alt_bn128_g1_sum_element => 69, + // new costs added after profile v1 was deprecated don't have this entry + #[allow(unreachable_patterns)] + _ => return &0, + }; + &self.data[index] + } +} + +impl BorshDeserialize for DataArray { + fn deserialize(buf: &mut &[u8]) -> Result { + let data_vec: Vec = BorshDeserialize::deserialize(buf)?; + let mut data_array = [0; Self::LEN]; + let len = Self::LEN.min(data_vec.len()); + data_array[0..len].copy_from_slice(&data_vec[0..len]); + Ok(Self(Box::new(data_array))) + } +} + +impl BorshSerialize for DataArray { + fn serialize(&self, writer: &mut W) -> Result<(), std::io::Error> { + let v: Vec<_> = self.0.as_ref().to_vec(); + BorshSerialize::serialize(&v, writer) + } +} + +impl Default for ProfileDataV2 { + fn default() -> Self { + let costs = DataArray(Box::new([0; DataArray::LEN])); + ProfileDataV2 { data: costs } + } +} + +/// Tests for ProfileDataV2 +#[cfg(test)] +mod test { + use super::*; + + #[test] + #[cfg(not(feature = "nightly"))] + fn test_profile_data_debug() { + let profile_data = ProfileDataV2::test(); + // we don't care about exact formatting, but the numbers should not change unexpectedly + let pretty_debug_str = format!("{profile_data:#?}"); + insta::assert_snapshot!(pretty_debug_str); + } + + #[test] + fn test_profile_data_debug_no_data() { + let profile_data = ProfileDataV2::default(); + // we don't care about exact formatting, but at least it should not panic + println!("{:#?}", &profile_data); + } +} diff --git a/core/primitives-core/src/profile/snapshots/near_primitives_core__profile__profile_v2__test__profile_data_debug.snap b/core/primitives-core/src/profile/snapshots/near_primitives_core__profile__profile_v2__test__profile_data_debug.snap new file mode 100644 index 00000000000..00442a71dd8 --- /dev/null +++ b/core/primitives-core/src/profile/snapshots/near_primitives_core__profile__profile_v2__test__profile_data_debug.snap @@ -0,0 +1,78 @@ +--- +source: core/primitives-core/src/profile/profile_v2.rs +expression: pretty_debug_str +--- +------------------------------ +Action gas: 10045 +------ Host functions -------- +contract_loading_base -> 1 [0% host] +contract_loading_bytes -> 2 [0% host] +read_memory_base -> 3 [0% host] +read_memory_byte -> 4 [0% host] +write_memory_base -> 5 [0% host] +write_memory_byte -> 6 [0% host] +read_register_base -> 7 [0% host] +read_register_byte -> 8 [0% host] +write_register_base -> 9 [0% host] +write_register_byte -> 10 [0% host] +utf8_decoding_base -> 11 [0% host] +utf8_decoding_byte -> 12 [0% host] +utf16_decoding_base -> 13 [0% host] +utf16_decoding_byte -> 14 [0% host] +sha256_base -> 15 [0% host] +sha256_byte -> 16 [0% host] +keccak256_base -> 17 [0% host] +keccak256_byte -> 18 [1% host] +keccak512_base -> 19 [1% host] +keccak512_byte -> 20 [1% host] +ripemd160_base -> 21 [1% host] +ripemd160_block -> 22 [1% host] +ecrecover_base -> 23 [1% host] +log_base -> 24 [1% host] +log_byte -> 25 [1% host] +storage_write_base -> 26 [1% host] +storage_write_key_byte -> 27 [1% host] +storage_write_value_byte -> 28 [1% host] +storage_write_evicted_byte -> 29 [1% host] +storage_read_base -> 30 [1% host] +storage_read_key_byte -> 31 [1% host] +storage_read_value_byte -> 32 [1% host] +storage_remove_base -> 33 [1% host] +storage_remove_key_byte -> 34 [1% host] +storage_remove_ret_value_byte -> 35 [2% host] +storage_has_key_base -> 36 [2% host] +storage_has_key_byte -> 37 [2% host] +storage_iter_create_prefix_base -> 38 [2% host] +storage_iter_create_prefix_byte -> 39 [2% host] +storage_iter_create_range_base -> 40 [2% host] +storage_iter_create_from_byte -> 41 [2% host] +storage_iter_create_to_byte -> 42 [2% host] +storage_iter_next_base -> 43 [2% host] +storage_iter_next_key_byte -> 44 [2% host] +storage_iter_next_value_byte -> 45 [2% host] +touching_trie_node -> 46 [2% host] +read_cached_trie_node -> 53 [3% host] +promise_and_base -> 47 [2% host] +promise_and_per_promise -> 48 [2% host] +promise_return -> 49 [2% host] +validator_stake_base -> 50 [2% host] +validator_total_stake_base -> 51 [2% host] +alt_bn128_g1_multiexp_base -> 54 [3% host] +alt_bn128_g1_multiexp_element -> 55 [3% host] +alt_bn128_pairing_check_base -> 56 [3% host] +alt_bn128_pairing_check_element -> 57 [3% host] +alt_bn128_g1_sum_base -> 58 [3% host] +alt_bn128_g1_sum_element -> 59 [3% host] +------ Actions -------- +create_account -> 1000 +delete_account -> 1001 +deploy_contract -> 1002 +function_call -> 1003 +transfer -> 1004 +stake -> 1005 +add_key -> 1006 +delete_key -> 1007 +new_data_receipt_byte -> 1008 +new_receipt -> 1009 +------------------------------ + diff --git a/core/primitives-core/src/snapshots/near_primitives_core__profile__profile_v1__test__profile_data_debug.snap b/core/primitives-core/src/snapshots/near_primitives_core__profile__profile_v1__test__profile_data_debug.snap new file mode 100644 index 00000000000..115c4212678 --- /dev/null +++ b/core/primitives-core/src/snapshots/near_primitives_core__profile__profile_v1__test__profile_data_debug.snap @@ -0,0 +1,78 @@ +--- +source: core/primitives-core/src/profile.rs +expression: pretty_debug_str +--- +------------------------------ +Action gas: 10045 +------ Host functions -------- +contract_loading_base -> 1 [0% host] +contract_loading_bytes -> 2 [0% host] +read_memory_base -> 3 [0% host] +read_memory_byte -> 4 [0% host] +write_memory_base -> 5 [0% host] +write_memory_byte -> 6 [0% host] +read_register_base -> 7 [0% host] +read_register_byte -> 8 [0% host] +write_register_base -> 9 [0% host] +write_register_byte -> 10 [0% host] +utf8_decoding_base -> 11 [0% host] +utf8_decoding_byte -> 12 [0% host] +utf16_decoding_base -> 13 [0% host] +utf16_decoding_byte -> 14 [0% host] +sha256_base -> 15 [0% host] +sha256_byte -> 16 [0% host] +keccak256_base -> 17 [0% host] +keccak256_byte -> 18 [1% host] +keccak512_base -> 19 [1% host] +keccak512_byte -> 20 [1% host] +ripemd160_base -> 21 [1% host] +ripemd160_block -> 22 [1% host] +ecrecover_base -> 23 [1% host] +log_base -> 24 [1% host] +log_byte -> 25 [1% host] +storage_write_base -> 26 [1% host] +storage_write_key_byte -> 27 [1% host] +storage_write_value_byte -> 28 [1% host] +storage_write_evicted_byte -> 29 [1% host] +storage_read_base -> 30 [1% host] +storage_read_key_byte -> 31 [1% host] +storage_read_value_byte -> 32 [1% host] +storage_remove_base -> 33 [1% host] +storage_remove_key_byte -> 34 [1% host] +storage_remove_ret_value_byte -> 35 [2% host] +storage_has_key_base -> 36 [2% host] +storage_has_key_byte -> 37 [2% host] +storage_iter_create_prefix_base -> 38 [2% host] +storage_iter_create_prefix_byte -> 39 [2% host] +storage_iter_create_range_base -> 40 [2% host] +storage_iter_create_from_byte -> 41 [2% host] +storage_iter_create_to_byte -> 42 [2% host] +storage_iter_next_base -> 43 [2% host] +storage_iter_next_key_byte -> 44 [2% host] +storage_iter_next_value_byte -> 45 [2% host] +touching_trie_node -> 46 [2% host] +read_cached_trie_node -> 53 [3% host] +promise_and_base -> 47 [2% host] +promise_and_per_promise -> 48 [2% host] +promise_return -> 49 [2% host] +validator_stake_base -> 50 [2% host] +validator_total_stake_base -> 51 [2% host] +alt_bn128_g1_multiexp_base -> 54 [3% host] +alt_bn128_g1_multiexp_element -> 55 [3% host] +alt_bn128_pairing_check_base -> 56 [3% host] +alt_bn128_pairing_check_element -> 57 [3% host] +alt_bn128_g1_sum_base -> 58 [3% host] +alt_bn128_g1_sum_element -> 59 [3% host] +------ Actions -------- +create_account -> 1000 +delete_account -> 1001 +deploy_contract -> 1002 +function_call -> 1003 +transfer -> 1004 +stake -> 1005 +add_key -> 1006 +delete_key -> 1007 +new_data_receipt_byte -> 1008 +new_receipt -> 1009 +------------------------------ + diff --git a/core/primitives-core/src/snapshots/near_primitives_core__profile__test__profile_data_debug.snap b/core/primitives-core/src/snapshots/near_primitives_core__profile__test__profile_data_debug.snap new file mode 100644 index 00000000000..ce0a8fd6bc5 --- /dev/null +++ b/core/primitives-core/src/snapshots/near_primitives_core__profile__test__profile_data_debug.snap @@ -0,0 +1,83 @@ +--- +source: core/primitives-core/src/profile.rs +expression: pretty_debug_str +--- +------------------------------ +Action gas: 15105 +------ Host functions -------- +contract_loading_base -> 1 [0% host] +contract_loading_bytes -> 2 [0% host] +read_memory_base -> 3 [0% host] +read_memory_byte -> 4 [0% host] +write_memory_base -> 5 [0% host] +write_memory_byte -> 6 [0% host] +read_register_base -> 7 [0% host] +read_register_byte -> 8 [0% host] +write_register_base -> 9 [0% host] +write_register_byte -> 10 [0% host] +utf8_decoding_base -> 11 [0% host] +utf8_decoding_byte -> 12 [0% host] +utf16_decoding_base -> 13 [0% host] +utf16_decoding_byte -> 14 [0% host] +sha256_base -> 15 [0% host] +sha256_byte -> 16 [0% host] +keccak256_base -> 17 [0% host] +keccak256_byte -> 18 [1% host] +keccak512_base -> 19 [1% host] +keccak512_byte -> 20 [1% host] +ripemd160_base -> 21 [1% host] +ripemd160_block -> 22 [1% host] +ecrecover_base -> 23 [1% host] +log_base -> 24 [1% host] +log_byte -> 25 [1% host] +storage_write_base -> 26 [1% host] +storage_write_key_byte -> 27 [1% host] +storage_write_value_byte -> 28 [1% host] +storage_write_evicted_byte -> 29 [1% host] +storage_read_base -> 30 [1% host] +storage_read_key_byte -> 31 [1% host] +storage_read_value_byte -> 32 [1% host] +storage_remove_base -> 33 [1% host] +storage_remove_key_byte -> 34 [1% host] +storage_remove_ret_value_byte -> 35 [2% host] +storage_has_key_base -> 36 [2% host] +storage_has_key_byte -> 37 [2% host] +storage_iter_create_prefix_base -> 38 [2% host] +storage_iter_create_prefix_byte -> 39 [2% host] +storage_iter_create_range_base -> 40 [2% host] +storage_iter_create_from_byte -> 41 [2% host] +storage_iter_create_to_byte -> 42 [2% host] +storage_iter_next_base -> 43 [2% host] +storage_iter_next_key_byte -> 44 [2% host] +storage_iter_next_value_byte -> 45 [2% host] +touching_trie_node -> 46 [2% host] +read_cached_trie_node -> 47 [2% host] +promise_and_base -> 48 [2% host] +promise_and_per_promise -> 49 [2% host] +promise_return -> 50 [2% host] +validator_stake_base -> 51 [2% host] +validator_total_stake_base -> 52 [3% host] +alt_bn128_g1_multiexp_base -> 53 [3% host] +alt_bn128_g1_multiexp_element -> 54 [3% host] +alt_bn128_pairing_check_base -> 55 [3% host] +alt_bn128_pairing_check_element -> 56 [3% host] +alt_bn128_g1_sum_base -> 57 [3% host] +alt_bn128_g1_sum_element -> 58 [3% host] +------ Actions -------- +create_account -> 1000 +delete_account -> 1001 +deploy_contract_base -> 1002 +deploy_contract_byte -> 1003 +function_call_base -> 1004 +function_call_byte -> 1005 +transfer -> 1006 +stake -> 1007 +add_full_access_key -> 1008 +add_function_call_key_base -> 1009 +add_function_call_key_byte -> 1010 +delete_key -> 1011 +new_action_receipt -> 1012 +new_data_receipt_base -> 1013 +new_data_receipt_byte -> 1014 +------------------------------ + diff --git a/core/primitives/src/snapshots/near_primitives__views__tests__exec_metadata_v1_view.snap b/core/primitives/src/snapshots/near_primitives__views__tests__exec_metadata_v1_view.snap new file mode 100644 index 00000000000..38bc34efcdf --- /dev/null +++ b/core/primitives/src/snapshots/near_primitives__views__tests__exec_metadata_v1_view.snap @@ -0,0 +1,8 @@ +--- +source: core/primitives/src/views.rs +expression: view +--- +{ + "version": 1, + "gas_profile": null +} diff --git a/core/primitives/src/snapshots/near_primitives__views__tests__exec_metadata_v2_view.snap b/core/primitives/src/snapshots/near_primitives__views__tests__exec_metadata_v2_view.snap new file mode 100644 index 00000000000..e88d8d8ce0a --- /dev/null +++ b/core/primitives/src/snapshots/near_primitives__views__tests__exec_metadata_v2_view.snap @@ -0,0 +1,359 @@ +--- +source: core/primitives/src/views.rs +expression: view +--- +{ + "version": 2, + "gas_profile": [ + { + "cost_category": "ACTION_COST", + "cost": "ADD_KEY", + "gas_used": "1006" + }, + { + "cost_category": "ACTION_COST", + "cost": "CREATE_ACCOUNT", + "gas_used": "1000" + }, + { + "cost_category": "ACTION_COST", + "cost": "DELETE_ACCOUNT", + "gas_used": "1001" + }, + { + "cost_category": "ACTION_COST", + "cost": "DELETE_KEY", + "gas_used": "1007" + }, + { + "cost_category": "ACTION_COST", + "cost": "DEPLOY_CONTRACT", + "gas_used": "1002" + }, + { + "cost_category": "ACTION_COST", + "cost": "FUNCTION_CALL", + "gas_used": "1003" + }, + { + "cost_category": "ACTION_COST", + "cost": "NEW_DATA_RECEIPT_BYTE", + "gas_used": "1008" + }, + { + "cost_category": "ACTION_COST", + "cost": "NEW_RECEIPT", + "gas_used": "1009" + }, + { + "cost_category": "ACTION_COST", + "cost": "STAKE", + "gas_used": "1005" + }, + { + "cost_category": "ACTION_COST", + "cost": "TRANSFER", + "gas_used": "1004" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "ALT_BN128_G1_MULTIEXP_BASE", + "gas_used": "54" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "ALT_BN128_G1_MULTIEXP_ELEMENT", + "gas_used": "55" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "ALT_BN128_G1_SUM_BASE", + "gas_used": "58" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "ALT_BN128_G1_SUM_ELEMENT", + "gas_used": "59" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "ALT_BN128_PAIRING_CHECK_BASE", + "gas_used": "56" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "ALT_BN128_PAIRING_CHECK_ELEMENT", + "gas_used": "57" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "BASE", + "gas_used": "0" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "CONTRACT_LOADING_BASE", + "gas_used": "1" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "CONTRACT_LOADING_BYTES", + "gas_used": "2" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "ECRECOVER_BASE", + "gas_used": "23" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "KECCAK256_BASE", + "gas_used": "17" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "KECCAK256_BYTE", + "gas_used": "18" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "KECCAK512_BASE", + "gas_used": "19" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "KECCAK512_BYTE", + "gas_used": "20" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "LOG_BASE", + "gas_used": "24" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "LOG_BYTE", + "gas_used": "25" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "PROMISE_AND_BASE", + "gas_used": "47" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "PROMISE_AND_PER_PROMISE", + "gas_used": "48" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "PROMISE_RETURN", + "gas_used": "49" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "READ_CACHED_TRIE_NODE", + "gas_used": "53" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "READ_MEMORY_BASE", + "gas_used": "3" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "READ_MEMORY_BYTE", + "gas_used": "4" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "READ_REGISTER_BASE", + "gas_used": "7" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "READ_REGISTER_BYTE", + "gas_used": "8" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "RIPEMD160_BASE", + "gas_used": "21" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "RIPEMD160_BLOCK", + "gas_used": "22" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "SHA256_BASE", + "gas_used": "15" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "SHA256_BYTE", + "gas_used": "16" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_HAS_KEY_BASE", + "gas_used": "36" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_HAS_KEY_BYTE", + "gas_used": "37" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_ITER_CREATE_FROM_BYTE", + "gas_used": "41" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_ITER_CREATE_PREFIX_BASE", + "gas_used": "38" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_ITER_CREATE_PREFIX_BYTE", + "gas_used": "39" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_ITER_CREATE_RANGE_BASE", + "gas_used": "40" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_ITER_CREATE_TO_BYTE", + "gas_used": "42" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_ITER_NEXT_BASE", + "gas_used": "43" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_ITER_NEXT_KEY_BYTE", + "gas_used": "44" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_ITER_NEXT_VALUE_BYTE", + "gas_used": "45" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_READ_BASE", + "gas_used": "30" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_READ_KEY_BYTE", + "gas_used": "31" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_READ_VALUE_BYTE", + "gas_used": "32" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_REMOVE_BASE", + "gas_used": "33" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_REMOVE_KEY_BYTE", + "gas_used": "34" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_REMOVE_RET_VALUE_BYTE", + "gas_used": "35" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_WRITE_BASE", + "gas_used": "26" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_WRITE_EVICTED_BYTE", + "gas_used": "29" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_WRITE_KEY_BYTE", + "gas_used": "27" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_WRITE_VALUE_BYTE", + "gas_used": "28" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "TOUCHING_TRIE_NODE", + "gas_used": "46" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "UTF16_DECODING_BASE", + "gas_used": "13" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "UTF16_DECODING_BYTE", + "gas_used": "14" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "UTF8_DECODING_BASE", + "gas_used": "11" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "UTF8_DECODING_BYTE", + "gas_used": "12" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "VALIDATOR_STAKE_BASE", + "gas_used": "50" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "VALIDATOR_TOTAL_STAKE_BASE", + "gas_used": "51" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "WASM_INSTRUCTION", + "gas_used": "52" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "WRITE_MEMORY_BASE", + "gas_used": "5" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "WRITE_MEMORY_BYTE", + "gas_used": "6" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "WRITE_REGISTER_BASE", + "gas_used": "9" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "WRITE_REGISTER_BYTE", + "gas_used": "10" + } + ] +} diff --git a/core/primitives/src/snapshots/near_primitives__views__tests__exec_metadata_v3_view.snap b/core/primitives/src/snapshots/near_primitives__views__tests__exec_metadata_v3_view.snap new file mode 100644 index 00000000000..a9d3e193f14 --- /dev/null +++ b/core/primitives/src/snapshots/near_primitives__views__tests__exec_metadata_v3_view.snap @@ -0,0 +1,374 @@ +--- +source: core/primitives/src/views.rs +expression: view +--- +{ + "version": 3, + "gas_profile": [ + { + "cost_category": "ACTION_COST", + "cost": "ADD_FULL_ACCESS_KEY", + "gas_used": "1008" + }, + { + "cost_category": "ACTION_COST", + "cost": "ADD_FUNCTION_CALL_KEY_BASE", + "gas_used": "1009" + }, + { + "cost_category": "ACTION_COST", + "cost": "ADD_FUNCTION_CALL_KEY_BYTE", + "gas_used": "1010" + }, + { + "cost_category": "ACTION_COST", + "cost": "CREATE_ACCOUNT", + "gas_used": "1000" + }, + { + "cost_category": "ACTION_COST", + "cost": "DELETE_ACCOUNT", + "gas_used": "1001" + }, + { + "cost_category": "ACTION_COST", + "cost": "DELETE_KEY", + "gas_used": "1011" + }, + { + "cost_category": "ACTION_COST", + "cost": "DEPLOY_CONTRACT_BASE", + "gas_used": "1002" + }, + { + "cost_category": "ACTION_COST", + "cost": "DEPLOY_CONTRACT_BYTE", + "gas_used": "1003" + }, + { + "cost_category": "ACTION_COST", + "cost": "FUNCTION_CALL_BASE", + "gas_used": "1004" + }, + { + "cost_category": "ACTION_COST", + "cost": "FUNCTION_CALL_BYTE", + "gas_used": "1005" + }, + { + "cost_category": "ACTION_COST", + "cost": "NEW_ACTION_RECEIPT", + "gas_used": "1012" + }, + { + "cost_category": "ACTION_COST", + "cost": "NEW_DATA_RECEIPT_BASE", + "gas_used": "1013" + }, + { + "cost_category": "ACTION_COST", + "cost": "NEW_DATA_RECEIPT_BYTE", + "gas_used": "1014" + }, + { + "cost_category": "ACTION_COST", + "cost": "STAKE", + "gas_used": "1007" + }, + { + "cost_category": "ACTION_COST", + "cost": "TRANSFER", + "gas_used": "1006" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "ALT_BN128_G1_MULTIEXP_BASE", + "gas_used": "53" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "ALT_BN128_G1_MULTIEXP_ELEMENT", + "gas_used": "54" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "ALT_BN128_G1_SUM_BASE", + "gas_used": "57" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "ALT_BN128_G1_SUM_ELEMENT", + "gas_used": "58" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "ALT_BN128_PAIRING_CHECK_BASE", + "gas_used": "55" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "ALT_BN128_PAIRING_CHECK_ELEMENT", + "gas_used": "56" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "CONTRACT_LOADING_BASE", + "gas_used": "1" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "CONTRACT_LOADING_BYTES", + "gas_used": "2" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "ECRECOVER_BASE", + "gas_used": "23" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "KECCAK256_BASE", + "gas_used": "17" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "KECCAK256_BYTE", + "gas_used": "18" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "KECCAK512_BASE", + "gas_used": "19" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "KECCAK512_BYTE", + "gas_used": "20" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "LOG_BASE", + "gas_used": "24" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "LOG_BYTE", + "gas_used": "25" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "PROMISE_AND_BASE", + "gas_used": "48" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "PROMISE_AND_PER_PROMISE", + "gas_used": "49" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "PROMISE_RETURN", + "gas_used": "50" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "READ_CACHED_TRIE_NODE", + "gas_used": "47" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "READ_MEMORY_BASE", + "gas_used": "3" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "READ_MEMORY_BYTE", + "gas_used": "4" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "READ_REGISTER_BASE", + "gas_used": "7" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "READ_REGISTER_BYTE", + "gas_used": "8" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "RIPEMD160_BASE", + "gas_used": "21" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "RIPEMD160_BLOCK", + "gas_used": "22" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "SHA256_BASE", + "gas_used": "15" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "SHA256_BYTE", + "gas_used": "16" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_HAS_KEY_BASE", + "gas_used": "36" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_HAS_KEY_BYTE", + "gas_used": "37" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_ITER_CREATE_FROM_BYTE", + "gas_used": "41" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_ITER_CREATE_PREFIX_BASE", + "gas_used": "38" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_ITER_CREATE_PREFIX_BYTE", + "gas_used": "39" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_ITER_CREATE_RANGE_BASE", + "gas_used": "40" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_ITER_CREATE_TO_BYTE", + "gas_used": "42" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_ITER_NEXT_BASE", + "gas_used": "43" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_ITER_NEXT_KEY_BYTE", + "gas_used": "44" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_ITER_NEXT_VALUE_BYTE", + "gas_used": "45" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_READ_BASE", + "gas_used": "30" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_READ_KEY_BYTE", + "gas_used": "31" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_READ_VALUE_BYTE", + "gas_used": "32" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_REMOVE_BASE", + "gas_used": "33" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_REMOVE_KEY_BYTE", + "gas_used": "34" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_REMOVE_RET_VALUE_BYTE", + "gas_used": "35" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_WRITE_BASE", + "gas_used": "26" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_WRITE_EVICTED_BYTE", + "gas_used": "29" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_WRITE_KEY_BYTE", + "gas_used": "27" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "STORAGE_WRITE_VALUE_BYTE", + "gas_used": "28" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "TOUCHING_TRIE_NODE", + "gas_used": "46" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "UTF16_DECODING_BASE", + "gas_used": "13" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "UTF16_DECODING_BYTE", + "gas_used": "14" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "UTF8_DECODING_BASE", + "gas_used": "11" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "UTF8_DECODING_BYTE", + "gas_used": "12" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "VALIDATOR_STAKE_BASE", + "gas_used": "51" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "VALIDATOR_TOTAL_STAKE_BASE", + "gas_used": "52" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "WRITE_MEMORY_BASE", + "gas_used": "5" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "WRITE_MEMORY_BYTE", + "gas_used": "6" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "WRITE_REGISTER_BASE", + "gas_used": "9" + }, + { + "cost_category": "WASM_HOST_COST", + "cost": "WRITE_REGISTER_BYTE", + "gas_used": "10" + } + ] +} diff --git a/core/primitives/src/snapshots/near_primitives__views__tests__runtime_config_view.snap b/core/primitives/src/snapshots/near_primitives__views__tests__runtime_config_view.snap new file mode 100644 index 00000000000..ba2ca5ad713 --- /dev/null +++ b/core/primitives/src/snapshots/near_primitives__views__tests__runtime_config_view.snap @@ -0,0 +1,201 @@ +--- +source: core/primitives/src/views.rs +expression: "&view" +--- +{ + "storage_amount_per_byte": "90900000000000000000", + "transaction_costs": { + "action_receipt_creation_config": { + "send_sir": 108059500000, + "send_not_sir": 108059500000, + "execution": 108059500000 + }, + "data_receipt_creation_config": { + "base_cost": { + "send_sir": 4697339419375, + "send_not_sir": 4697339419375, + "execution": 4697339419375 + }, + "cost_per_byte": { + "send_sir": 59357464, + "send_not_sir": 59357464, + "execution": 59357464 + } + }, + "action_creation_config": { + "create_account_cost": { + "send_sir": 99607375000, + "send_not_sir": 99607375000, + "execution": 99607375000 + }, + "deploy_contract_cost": { + "send_sir": 184765750000, + "send_not_sir": 184765750000, + "execution": 184765750000 + }, + "deploy_contract_cost_per_byte": { + "send_sir": 6812999, + "send_not_sir": 6812999, + "execution": 6812999 + }, + "function_call_cost": { + "send_sir": 2319861500000, + "send_not_sir": 2319861500000, + "execution": 2319861500000 + }, + "function_call_cost_per_byte": { + "send_sir": 2235934, + "send_not_sir": 2235934, + "execution": 2235934 + }, + "transfer_cost": { + "send_sir": 115123062500, + "send_not_sir": 115123062500, + "execution": 115123062500 + }, + "stake_cost": { + "send_sir": 141715687500, + "send_not_sir": 141715687500, + "execution": 102217625000 + }, + "add_key_cost": { + "full_access_cost": { + "send_sir": 101765125000, + "send_not_sir": 101765125000, + "execution": 101765125000 + }, + "function_call_cost": { + "send_sir": 102217625000, + "send_not_sir": 102217625000, + "execution": 102217625000 + }, + "function_call_cost_per_byte": { + "send_sir": 1925331, + "send_not_sir": 1925331, + "execution": 1925331 + } + }, + "delete_key_cost": { + "send_sir": 94946625000, + "send_not_sir": 94946625000, + "execution": 94946625000 + }, + "delete_account_cost": { + "send_sir": 147489000000, + "send_not_sir": 147489000000, + "execution": 147489000000 + } + }, + "storage_usage_config": { + "num_bytes_account": 100, + "num_extra_bytes_record": 40 + }, + "burnt_gas_reward": [ + 3, + 10 + ], + "pessimistic_gas_price_inflation_ratio": [ + 103, + 100 + ] + }, + "wasm_config": { + "ext_costs": { + "base": 264768111, + "contract_loading_base": 35445963, + "contract_loading_bytes": 216750, + "read_memory_base": 2609863200, + "read_memory_byte": 3801333, + "write_memory_base": 2803794861, + "write_memory_byte": 2723772, + "read_register_base": 2517165186, + "read_register_byte": 98562, + "write_register_base": 2865522486, + "write_register_byte": 3801564, + "utf8_decoding_base": 3111779061, + "utf8_decoding_byte": 291580479, + "utf16_decoding_base": 3543313050, + "utf16_decoding_byte": 163577493, + "sha256_base": 4540970250, + "sha256_byte": 24117351, + "keccak256_base": 5879491275, + "keccak256_byte": 21471105, + "keccak512_base": 5811388236, + "keccak512_byte": 36649701, + "ripemd160_base": 853675086, + "ripemd160_block": 680107584, + "ecrecover_base": 3365369625000, + "log_base": 3543313050, + "log_byte": 13198791, + "storage_write_base": 64196736000, + "storage_write_key_byte": 70482867, + "storage_write_value_byte": 31018539, + "storage_write_evicted_byte": 32117307, + "storage_read_base": 56356845750, + "storage_read_key_byte": 30952533, + "storage_read_value_byte": 5611005, + "storage_remove_base": 53473030500, + "storage_remove_key_byte": 38220384, + "storage_remove_ret_value_byte": 11531556, + "storage_has_key_base": 54039896625, + "storage_has_key_byte": 30790845, + "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": 16101955926, + "read_cached_trie_node": 2280000000, + "promise_and_base": 1465013400, + "promise_and_per_promise": 5452176, + "promise_return": 560152386, + "validator_stake_base": 911834726400, + "validator_total_stake_base": 911834726400, + "contract_compile_base": 0, + "contract_compile_bytes": 0, + "alt_bn128_g1_multiexp_base": 713000000000, + "alt_bn128_g1_multiexp_element": 320000000000, + "alt_bn128_g1_sum_base": 3000000000, + "alt_bn128_g1_sum_element": 5000000000, + "alt_bn128_pairing_check_base": 9686000000000, + "alt_bn128_pairing_check_element": 5102000000000 + }, + "grow_mem_cost": 1, + "regular_op_cost": 3856371, + "limit_config": { + "max_gas_burnt": 200000000000000, + "max_stack_height": 16384, + "stack_limiter_version": 1, + "initial_memory_pages": 1024, + "max_memory_pages": 2048, + "registers_memory_limit": 1073741824, + "max_register_size": 104857600, + "max_number_registers": 100, + "max_number_logs": 100, + "max_total_log_length": 16384, + "max_total_prepaid_gas": 300000000000000, + "max_actions_per_receipt": 100, + "max_number_bytes_method_names": 2000, + "max_length_method_name": 256, + "max_arguments_length": 4194304, + "max_length_returned_data": 4194304, + "max_contract_size": 4194304, + "max_transaction_size": 4194304, + "max_length_storage_key": 4194304, + "max_length_storage_value": 4194304, + "max_promises_per_function_call_action": 1024, + "max_number_input_data_dependencies": 128, + "max_functions_number_per_contract": 10000, + "wasmer2_stack_limit": 204800, + "max_locals_per_contract": 1048576, + "account_id_validity_rules_version": 1 + } + }, + "account_creation_config": { + "min_allowed_top_level_account_length": 0, + "registrar_account_id": "registrar" + } +} diff --git a/core/primitives/src/transaction.rs b/core/primitives/src/transaction.rs index 46f82880ef4..40f32a32d4d 100644 --- a/core/primitives/src/transaction.rs +++ b/core/primitives/src/transaction.rs @@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize}; use near_crypto::{PublicKey, Signature}; use near_o11y::pretty; -use near_primitives_core::profile::ProfileData; +use near_primitives_core::profile::{ProfileDataV2, ProfileDataV3}; use crate::account::AccessKey; use crate::errors::TxExecutionError; @@ -366,11 +366,12 @@ pub struct ExecutionOutcome { #[derive(BorshSerialize, BorshDeserialize, PartialEq, Clone, Eq, Debug)] pub enum ExecutionMetadata { - // V1: Empty Metadata + /// V1: Empty Metadata V1, - - // V2: With ProfileData - V2(ProfileData), + /// V2: With ProfileData by legacy `Cost` enum + V2(ProfileDataV2), + // V3: With ProfileData by gas parameters + V3(ProfileDataV3), } impl Default for ExecutionMetadata { diff --git a/core/primitives/src/views.rs b/core/primitives/src/views.rs index a1b4652e491..ccac1d4f5c7 100644 --- a/core/primitives/src/views.rs +++ b/core/primitives/src/views.rs @@ -17,6 +17,7 @@ use serde::{Deserialize, Serialize}; use near_crypto::{PublicKey, Signature}; use near_o11y::pretty; +use strum::IntoEnumIterator; use crate::account::{AccessKey, AccessKeyPermission, Account, FunctionCallPermission}; use crate::block::{Block, BlockHeader, Tip}; @@ -30,7 +31,6 @@ use crate::errors::TxExecutionError; use crate::hash::{hash, CryptoHash}; use crate::merkle::{combine_hash, MerklePath}; use crate::network::PeerId; -use crate::profile::Cost; use crate::receipt::{ActionReceipt, DataReceipt, DataReceiver, Receipt, ReceiptEnum}; use crate::runtime::config::RuntimeConfig; use crate::serialize::{base64_format, dec_format, option_base64_format}; @@ -1266,73 +1266,102 @@ impl Default for ExecutionMetadataView { impl From for ExecutionMetadataView { fn from(metadata: ExecutionMetadata) -> Self { - let gas_profile = match metadata { + let version = match metadata { + ExecutionMetadata::V1 => 1, + ExecutionMetadata::V2(_) => 2, + ExecutionMetadata::V3(_) => 3, + }; + let mut gas_profile = match metadata { ExecutionMetadata::V1 => None, ExecutionMetadata::V2(profile_data) => { - let mut costs: Vec<_> = - Cost::iter() - .filter(|&cost| profile_data[cost] > 0) - .map(|cost| CostGasUsed { - cost_category: match cost { - Cost::ActionCost { .. } => "ACTION_COST", - Cost::ExtCost { .. } => "WASM_HOST_COST", - Cost::WasmInstruction => "WASM_HOST_COST", - } - .to_string(), - cost: match cost { - // preserve old behavior that conflated some action - // costs for profile (duplicates are removed afterwards) - Cost::ActionCost { - action_cost_kind: - ActionCosts::deploy_contract_base - | ActionCosts::deploy_contract_byte, - } => "DEPLOY_CONTRACT".to_owned(), - Cost::ActionCost { - action_cost_kind: - ActionCosts::function_call_base - | ActionCosts::function_call_byte, - } => "FUNCTION_CALL".to_owned(), - Cost::ActionCost { - action_cost_kind: - ActionCosts::add_full_access_key - | ActionCosts::add_function_call_key_base - | ActionCosts::add_function_call_key_byte, - } => "ADD_KEY".to_owned(), - Cost::ActionCost { - action_cost_kind: - ActionCosts::new_action_receipt - | ActionCosts::new_data_receipt_base, - } => "NEW_RECEIPT".to_owned(), - // other costs have always been mapped one-to-one - Cost::ActionCost { action_cost_kind: action_cost } => { - format!("{:?}", action_cost).to_ascii_uppercase() - } - Cost::ExtCost { ext_cost_kind: ext_cost } => { - format!("{:?}", ext_cost).to_ascii_uppercase() - } - Cost::WasmInstruction => "WASM_INSTRUCTION".to_string(), - }, - gas_used: profile_data[cost], - }) - .collect(); + // Add actions, wasm op, and ext costs in groups. + + // actions should use the old format, since `ActionCosts` + // includes more detailed entries than were present in the old + // profile + let mut costs: Vec = profile_data + .legacy_action_costs() + .into_iter() + .filter(|&(_, gas)| gas > 0) + .map(|(name, gas)| CostGasUsed::action(name.to_string(), gas)) + .collect(); + + // wasm op is a single cost, for historical reasons it is inaccurately displayed as "wasm host" + costs.push(CostGasUsed::wasm_host( + "WASM_INSTRUCTION".to_string(), + profile_data.get_wasm_cost(), + )); + + // ext costs are 1-to-1, except for those added later which we will display as 0 + for ext_cost in ExtCosts::iter() { + costs.push(CostGasUsed::wasm_host( + format!("{:?}", ext_cost).to_ascii_uppercase(), + profile_data.get_ext_cost(ext_cost), + )); + } - // The order doesn't really matter, but the default one is just - // historical, which is especially unintuitive, so let's sort - // lexicographically. - // - // Can't `sort_by_key` here because lifetime inference in - // closures is limited. - costs.sort_by(|lhs, rhs| { - lhs.cost_category.cmp(&rhs.cost_category).then(lhs.cost.cmp(&rhs.cost)) - }); + Some(costs) + } + ExecutionMetadata::V3(profile) => { + // Add actions, wasm op, and ext costs in groups. + // actions costs are 1-to-1 + let mut costs: Vec = ActionCosts::iter() + .flat_map(|cost| { + let gas_used = profile.get_action_cost(cost); + (gas_used > 0).then(|| { + CostGasUsed::action( + format!("{:?}", cost).to_ascii_uppercase(), + gas_used, + ) + }) + }) + .collect(); + + // wasm op is a single cost, for historical reasons it is inaccurately displayed as "wasm host" + let wasm_gas_used = profile.get_wasm_cost(); + if wasm_gas_used > 0 { + costs.push(CostGasUsed::wasm_host( + "WASM_INSTRUCTION".to_string(), + wasm_gas_used, + )); + } - // need to remove duplicate entries due to cost conflation - costs.dedup(); + // ext costs are 1-to-1 + for ext_cost in ExtCosts::iter() { + let gas_used = profile.get_ext_cost(ext_cost); + if gas_used > 0 { + costs.push(CostGasUsed::wasm_host( + format!("{:?}", ext_cost).to_ascii_uppercase(), + gas_used, + )); + } + } Some(costs) } }; - ExecutionMetadataView { version: 1, gas_profile } + if let Some(ref mut costs) = gas_profile { + // The order doesn't really matter, but the default one is just + // historical, which is especially unintuitive, so let's sort + // lexicographically. + // + // Can't `sort_by_key` here because lifetime inference in + // closures is limited. + costs.sort_by(|lhs, rhs| { + lhs.cost_category.cmp(&rhs.cost_category).then_with(|| lhs.cost.cmp(&rhs.cost)) + }); + } + ExecutionMetadataView { version, gas_profile } + } +} + +impl CostGasUsed { + pub fn action(cost: String, gas_used: Gas) -> Self { + Self { cost_category: "ACTION_COST".to_string(), cost, gas_used } + } + + pub fn wasm_host(cost: String, gas_used: Gas) -> Self { + Self { cost_category: "WASM_HOST_COST".to_string(), cost, gas_used } } } @@ -2166,7 +2195,7 @@ impl From for RuntimeConfigView { } } -// reverse direction: rosetta adapter uses this, also we use to test that all fields are present in view (TODO) +// reverse direction: rosetta adapter uses this, also we use to test that all fields are present in view impl From for RuntimeConfig { fn from(config: RuntimeConfigView) -> Self { Self { @@ -2569,3 +2598,62 @@ impl From for near_primitives_core::config::ExtCostsConfig { Self { costs } } } + +#[cfg(test)] +mod tests { + #[cfg(not(feature = "nightly"))] + use super::ExecutionMetadataView; + use super::RuntimeConfigView; + use crate::runtime::config::RuntimeConfig; + #[cfg(not(feature = "nightly"))] + use crate::transaction::ExecutionMetadata; + #[cfg(not(feature = "nightly"))] + use near_primitives_core::profile::{ProfileDataV2, ProfileDataV3}; + + /// The JSON representation used in RPC responses must not remove or rename + /// fields, only adding fields is allowed or we risk breaking clients. + #[test] + #[cfg(not(feature = "nightly"))] + fn test_runtime_config_view() { + let config = RuntimeConfig::test(); + let view = RuntimeConfigView::from(config); + insta::assert_json_snapshot!(&view); + } + + /// A `RuntimeConfigView` must contain all info to reconstruct a `RuntimeConfig`. + #[test] + fn test_runtime_config_view_is_complete() { + let config = RuntimeConfig::test(); + let view = RuntimeConfigView::from(config.clone()); + let reconstructed_config = RuntimeConfig::from(view); + + assert_eq!(config, reconstructed_config); + } + + /// `ExecutionMetadataView` with profile V1 displayed on the RPC should not change. + #[test] + #[cfg(not(feature = "nightly"))] + fn test_exec_metadata_v1_view() { + let metadata = ExecutionMetadata::V1; + let view = ExecutionMetadataView::from(metadata); + insta::assert_json_snapshot!(view); + } + + /// `ExecutionMetadataView` with profile V2 displayed on the RPC should not change. + #[test] + #[cfg(not(feature = "nightly"))] + fn test_exec_metadata_v2_view() { + let metadata = ExecutionMetadata::V2(ProfileDataV2::test()); + let view = ExecutionMetadataView::from(metadata); + insta::assert_json_snapshot!(view); + } + + /// `ExecutionMetadataView` with profile V3 displayed on the RPC should not change. + #[test] + #[cfg(not(feature = "nightly"))] + fn test_exec_metadata_v3_view() { + let metadata = ExecutionMetadata::V3(ProfileDataV3::test()); + let view = ExecutionMetadataView::from(metadata); + insta::assert_json_snapshot!(view); + } +} diff --git a/integration-tests/src/tests/client/features/chunk_nodes_cache.rs b/integration-tests/src/tests/client/features/chunk_nodes_cache.rs index 19a8998c75b..b3ddd536019 100644 --- a/integration-tests/src/tests/client/features/chunk_nodes_cache.rs +++ b/integration-tests/src/tests/client/features/chunk_nodes_cache.rs @@ -133,7 +133,8 @@ fn compare_node_counts() { let metadata = receipt_execution_outcome.outcome_with_id.outcome.metadata; match metadata { ExecutionMetadata::V1 => panic!("ExecutionMetadata cannot be empty"), - ExecutionMetadata::V2(profile_data) => TrieNodesCount { + ExecutionMetadata::V2(_profile_data) => panic!("expected newest ExecutionMetadata"), + ExecutionMetadata::V3(profile_data) => TrieNodesCount { db_reads: { let cost = profile_data.get_ext_cost(ExtCosts::touching_trie_node); assert_eq!(cost % touching_trie_node_cost, 0); diff --git a/integration-tests/src/tests/runtime/snapshots/integration_tests__tests__runtime__sanity_checks__receipts_gas_profile.snap b/integration-tests/src/tests/runtime/snapshots/integration_tests__tests__runtime__sanity_checks__receipts_gas_profile.snap index 516c8ba19a0..23dc32f5334 100644 --- a/integration-tests/src/tests/runtime/snapshots/integration_tests__tests__runtime__sanity_checks__receipts_gas_profile.snap +++ b/integration-tests/src/tests/runtime/snapshots/integration_tests__tests__runtime__sanity_checks__receipts_gas_profile.snap @@ -6,8 +6,18 @@ expression: receipts_gas_profile [ CostGasUsed { cost_category: "ACTION_COST", - cost: "ADD_KEY", - gas_used: 203992376655, + cost: "ADD_FULL_ACCESS_KEY", + gas_used: 101765125000, + }, + CostGasUsed { + cost_category: "ACTION_COST", + cost: "ADD_FUNCTION_CALL_KEY_BASE", + gas_used: 102217625000, + }, + CostGasUsed { + cost_category: "ACTION_COST", + cost: "ADD_FUNCTION_CALL_KEY_BYTE", + gas_used: 9626655, }, CostGasUsed { cost_category: "ACTION_COST", @@ -26,17 +36,27 @@ expression: receipts_gas_profile }, CostGasUsed { cost_category: "ACTION_COST", - cost: "DEPLOY_CONTRACT", - gas_used: 184997391966, + cost: "DEPLOY_CONTRACT_BASE", + gas_used: 184765750000, + }, + CostGasUsed { + cost_category: "ACTION_COST", + cost: "DEPLOY_CONTRACT_BYTE", + gas_used: 231641966, + }, + CostGasUsed { + cost_category: "ACTION_COST", + cost: "FUNCTION_CALL_BASE", + gas_used: 20878753500000, }, CostGasUsed { cost_category: "ACTION_COST", - cost: "FUNCTION_CALL", - gas_used: 20878961441862, + cost: "FUNCTION_CALL_BYTE", + gas_used: 207941862, }, CostGasUsed { cost_category: "ACTION_COST", - cost: "NEW_RECEIPT", + cost: "NEW_ACTION_RECEIPT", gas_used: 1480548358496, }, CostGasUsed { diff --git a/integration-tests/src/tests/runtime/snapshots/integration_tests__tests__runtime__sanity_checks__receipts_gas_profile_nightly.snap b/integration-tests/src/tests/runtime/snapshots/integration_tests__tests__runtime__sanity_checks__receipts_gas_profile_nightly.snap index 516c8ba19a0..23dc32f5334 100644 --- a/integration-tests/src/tests/runtime/snapshots/integration_tests__tests__runtime__sanity_checks__receipts_gas_profile_nightly.snap +++ b/integration-tests/src/tests/runtime/snapshots/integration_tests__tests__runtime__sanity_checks__receipts_gas_profile_nightly.snap @@ -6,8 +6,18 @@ expression: receipts_gas_profile [ CostGasUsed { cost_category: "ACTION_COST", - cost: "ADD_KEY", - gas_used: 203992376655, + cost: "ADD_FULL_ACCESS_KEY", + gas_used: 101765125000, + }, + CostGasUsed { + cost_category: "ACTION_COST", + cost: "ADD_FUNCTION_CALL_KEY_BASE", + gas_used: 102217625000, + }, + CostGasUsed { + cost_category: "ACTION_COST", + cost: "ADD_FUNCTION_CALL_KEY_BYTE", + gas_used: 9626655, }, CostGasUsed { cost_category: "ACTION_COST", @@ -26,17 +36,27 @@ expression: receipts_gas_profile }, CostGasUsed { cost_category: "ACTION_COST", - cost: "DEPLOY_CONTRACT", - gas_used: 184997391966, + cost: "DEPLOY_CONTRACT_BASE", + gas_used: 184765750000, + }, + CostGasUsed { + cost_category: "ACTION_COST", + cost: "DEPLOY_CONTRACT_BYTE", + gas_used: 231641966, + }, + CostGasUsed { + cost_category: "ACTION_COST", + cost: "FUNCTION_CALL_BASE", + gas_used: 20878753500000, }, CostGasUsed { cost_category: "ACTION_COST", - cost: "FUNCTION_CALL", - gas_used: 20878961441862, + cost: "FUNCTION_CALL_BYTE", + gas_used: 207941862, }, CostGasUsed { cost_category: "ACTION_COST", - cost: "NEW_RECEIPT", + cost: "NEW_ACTION_RECEIPT", gas_used: 1480548358496, }, CostGasUsed { diff --git a/runtime/near-vm-logic/src/gas_counter.rs b/runtime/near-vm-logic/src/gas_counter.rs index ed54520863d..c1c08468554 100644 --- a/runtime/near-vm-logic/src/gas_counter.rs +++ b/runtime/near-vm-logic/src/gas_counter.rs @@ -4,7 +4,7 @@ use near_primitives_core::config::ExtCosts::read_cached_trie_node; use near_primitives_core::config::ExtCosts::touching_trie_node; use near_primitives_core::{ config::{ActionCosts, ExtCosts, ExtCostsConfig}, - profile::ProfileData, + profile::ProfileDataV3, types::Gas, }; use std::collections::HashMap; @@ -58,7 +58,7 @@ pub struct GasCounter { /// FIXME(nagisa): why do we store a copy both here and in the VMLogic??? ext_costs_config: ExtCostsConfig, /// Where to store profile data, if needed. - profile: ProfileData, + profile: ProfileDataV3, } impl GasCounter { @@ -274,7 +274,7 @@ impl GasCounter { self.prepaid_gas - self.used_gas() } - pub fn profile_data(&self) -> ProfileData { + pub fn profile_data(&self) -> ProfileDataV3 { self.profile.clone() } } diff --git a/runtime/near-vm-logic/src/logic.rs b/runtime/near-vm-logic/src/logic.rs index c9bbb587e7a..2fe169a702b 100644 --- a/runtime/near-vm-logic/src/logic.rs +++ b/runtime/near-vm-logic/src/logic.rs @@ -9,11 +9,11 @@ use byteorder::ByteOrder; use near_crypto::Secp256K1Signature; use near_primitives::checked_feature; use near_primitives::config::ViewConfig; +use near_primitives::profile::ProfileDataV3; use near_primitives::runtime::fees::RuntimeFeesConfig; use near_primitives::version::is_implicit_account_creation_enabled; use near_primitives_core::config::ExtCosts::*; use near_primitives_core::config::{ActionCosts, ExtCosts, VMConfig}; -use near_primitives_core::profile::ProfileData; use near_primitives_core::runtime::fees::{transfer_exec_fee, transfer_send_fee}; use near_primitives_core::types::{ AccountId, Balance, EpochHeight, Gas, ProtocolVersion, StorageUsage, @@ -2863,7 +2863,7 @@ pub struct VMOutcome { pub used_gas: Gas, pub logs: Vec, /// Data collected from making a contract call - pub profile: ProfileData, + pub profile: ProfileDataV3, pub action_receipts: Vec<(AccountId, ReceiptMetadata)>, pub aborted: Option, } @@ -2895,7 +2895,7 @@ impl VMOutcome { burnt_gas: 0, used_gas: 0, logs: Vec::new(), - profile: ProfileData::default(), + profile: ProfileDataV3::default(), action_receipts: Vec::new(), aborted: Some(error), } diff --git a/runtime/runtime/src/lib.rs b/runtime/runtime/src/lib.rs index c7edaf6ac59..65d98141074 100644 --- a/runtime/runtime/src/lib.rs +++ b/runtime/runtime/src/lib.rs @@ -11,7 +11,7 @@ pub use near_crypto; use near_crypto::PublicKey; pub use near_primitives; use near_primitives::contract::ContractCode; -use near_primitives::profile::ProfileData; +use near_primitives::profile::ProfileDataV3; pub use near_primitives::runtime::apply_state::ApplyState; use near_primitives::runtime::fees::RuntimeFeesConfig; use near_primitives::runtime::get_insufficient_storage_stake; @@ -134,7 +134,7 @@ pub struct ActionResult { pub logs: Vec, pub new_receipts: Vec, pub validator_proposals: Vec, - pub profile: ProfileData, + pub profile: ProfileDataV3, } impl ActionResult { @@ -732,7 +732,7 @@ impl Runtime { gas_burnt: result.gas_burnt, tokens_burnt, executor_id: account_id.clone(), - metadata: ExecutionMetadata::V2(result.profile), + metadata: ExecutionMetadata::V3(result.profile), }, }) }