From b82cfb10bebaf4b2b8f075d81b4e6970c00e1212 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Chuda=C5=9B?= Date: Tue, 28 Jan 2025 13:29:29 +0000 Subject: [PATCH 1/4] Remove NEP-491 --- chain/chain/src/test_utils/kv_runtime.rs | 2 - chain/rosetta-rpc/Cargo.toml | 2 - chain/rosetta-rpc/src/adapters/mod.rs | 58 -- chain/rosetta-rpc/src/lib.rs | 12 +- core/chain-configs/Cargo.toml | 2 - core/chain-configs/src/genesis_validate.rs | 22 +- core/chain-configs/src/test_genesis.rs | 11 +- core/chain-configs/src/test_utils.rs | 2 +- core/primitives-core/Cargo.toml | 2 - core/primitives-core/src/account.rs | 144 +--- core/primitives-core/src/version.rs | 6 - core/primitives/Cargo.toml | 4 - core/primitives/src/action/mod.rs | 31 - core/primitives/src/errors.rs | 5 - core/primitives/src/test_utils.rs | 2 +- core/primitives/src/transaction.rs | 2 - core/primitives/src/views.rs | 34 +- .../genesis-csv-to-json/src/csv_parser.rs | 10 +- genesis-tools/genesis-populate/src/lib.rs | 2 - integration-tests/Cargo.toml | 4 - .../src/tests/client/features.rs | 2 - .../client/features/nonrefundable_transfer.rs | 681 ------------------ .../client/features/stateless_validation.rs | 9 +- .../src/tests/runtime/state_viewer.rs | 4 +- nearcore/Cargo.toml | 4 - neard/Cargo.toml | 2 - runtime/runtime/Cargo.toml | 2 - runtime/runtime/src/actions.rs | 87 +-- runtime/runtime/src/config.rs | 23 - runtime/runtime/src/lib.rs | 55 +- runtime/runtime/src/pipelining.rs | 2 - runtime/runtime/src/verifier.rs | 24 - .../runtime/tests/runtime_group_tools/mod.rs | 9 +- test-utils/testlib/src/runtime_utils.rs | 5 +- tools/amend-genesis/src/lib.rs | 51 +- tools/fork-network/src/cli.rs | 2 - tools/state-viewer/Cargo.toml | 4 - tools/state-viewer/src/contract_accounts.rs | 8 - 38 files changed, 44 insertions(+), 1287 deletions(-) delete mode 100644 integration-tests/src/tests/client/features/nonrefundable_transfer.rs diff --git a/chain/chain/src/test_utils/kv_runtime.rs b/chain/chain/src/test_utils/kv_runtime.rs index 47e10c8f9c9..ffd35f1a9c5 100644 --- a/chain/chain/src/test_utils/kv_runtime.rs +++ b/chain/chain/src/test_utils/kv_runtime.rs @@ -1303,10 +1303,8 @@ impl RuntimeAdapter for KeyValueRuntime { |state| *state.amounts.get(account_id).unwrap_or(&0), ), 0, - 0, CryptoHash::default(), 0, - PROTOCOL_VERSION, ) .into(), ), diff --git a/chain/rosetta-rpc/Cargo.toml b/chain/rosetta-rpc/Cargo.toml index d63f7599a57..da66e8378c9 100644 --- a/chain/rosetta-rpc/Cargo.toml +++ b/chain/rosetta-rpc/Cargo.toml @@ -44,7 +44,6 @@ near-actix-test-utils.workspace = true near-time.workspace = true [features] -protocol_feature_nonrefundable_transfer_nep491 = [] nightly_protocol = [ "near-actix-test-utils/nightly_protocol", "near-chain-configs/nightly_protocol", @@ -67,5 +66,4 @@ nightly = [ "near-primitives/nightly", "nightly_protocol", "node-runtime/nightly", - "protocol_feature_nonrefundable_transfer_nep491", ] diff --git a/chain/rosetta-rpc/src/adapters/mod.rs b/chain/rosetta-rpc/src/adapters/mod.rs index d54e4f46b10..709224917e7 100644 --- a/chain/rosetta-rpc/src/adapters/mod.rs +++ b/chain/rosetta-rpc/src/adapters/mod.rs @@ -352,23 +352,6 @@ impl From for Vec { ); } - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - // Non-refundable transfer deposit is burnt for permanent storage bytes on the receiving account. - near_primitives::transaction::Action::NonrefundableStorageTransfer(action) => { - let transfer_amount = crate::models::Amount::from_yoctonear(action.deposit); - - let sender_transfer_operation_id = - crate::models::OperationIdentifier::new(&operations); - operations.push( - validated_operations::TransferOperation { - account: sender_account_identifier.clone(), - amount: -transfer_amount.clone(), - predecessor_id: Some(sender_account_identifier.clone()), - } - .into_operation(sender_transfer_operation_id.clone()), - ); - } - near_primitives::transaction::Action::Stake(action) => { operations.push( validated_operations::StakeOperation { @@ -884,8 +867,6 @@ mod tests { amount: 5000000000000000000, code_hash: near_primitives::hash::CryptoHash::default(), locked: 400000000000000000000000000000, - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - permanent_storage_bytes: 0, storage_paid_at: 0, storage_usage: 200000, }, @@ -901,8 +882,6 @@ mod tests { amount: 4000000000000000000, code_hash: near_primitives::hash::CryptoHash::default(), locked: 400000000000000000000000000000, - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - permanent_storage_bytes: 0, storage_paid_at: 0, storage_usage: 200000, }, @@ -916,8 +895,6 @@ mod tests { amount: 7000000000000000000, code_hash: near_primitives::hash::CryptoHash::default(), locked: 400000000000000000000000000000, - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - permanent_storage_bytes: 0, storage_paid_at: 0, storage_usage: 200000, }, @@ -933,8 +910,6 @@ mod tests { amount: 8000000000000000000, code_hash: near_primitives::hash::CryptoHash::default(), locked: 400000000000000000000000000000, - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - permanent_storage_bytes: 0, storage_paid_at: 0, storage_usage: 200000, }, @@ -948,8 +923,6 @@ mod tests { amount: 4000000000000000000, code_hash: near_primitives::hash::CryptoHash::default(), locked: 400000000000000000000000000000, - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - permanent_storage_bytes: 0, storage_paid_at: 0, storage_usage: 200000, }, @@ -960,8 +933,6 @@ mod tests { amount: 6000000000000000000, code_hash: near_primitives::hash::CryptoHash::default(), locked: 400000000000000000000000000000, - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - permanent_storage_bytes: 0, storage_paid_at: 0, storage_usage: 200000, }, @@ -1592,33 +1563,4 @@ mod tests { Err(crate::errors::ErrorKind::InvalidInput(_)) )); } - - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - #[test] - fn test_convert_nonrefundable_storage_transfer_action() { - let deposit = near_primitives::types::Balance::MAX - 1; - let nonrefundable_transfer_actions = vec![ - near_primitives::transaction::NonrefundableStorageTransferAction { deposit }.into(), - ]; - let near_nonrefundable_transfer_actions = NearActions { - sender_account_id: "sender.near".parse().unwrap(), - receiver_account_id: "receiver.near".parse().unwrap(), - actions: nonrefundable_transfer_actions, - }; - let nonrefundable_transfer_operations_converted: Vec = - near_nonrefundable_transfer_actions.into(); - assert_eq!(nonrefundable_transfer_operations_converted.len(), 1); - assert_eq!( - nonrefundable_transfer_operations_converted[0].type_, - crate::models::OperationType::Transfer - ); - assert_eq!( - nonrefundable_transfer_operations_converted[0].account, - "sender.near".parse().unwrap() - ); - assert_eq!( - nonrefundable_transfer_operations_converted[0].amount, - Some(-crate::models::Amount::from_yoctonear(deposit)) - ); - } } diff --git a/chain/rosetta-rpc/src/lib.rs b/chain/rosetta-rpc/src/lib.rs index 1942fef7179..2ff0fec70e1 100644 --- a/chain/rosetta-rpc/src/lib.rs +++ b/chain/rosetta-rpc/src/lib.rs @@ -17,7 +17,7 @@ pub use config::RosettaRpcConfig; use near_chain_configs::Genesis; use near_client::{ClientActor, ViewClientActor}; use near_o11y::WithSpanContextExt; -use near_primitives::{borsh::BorshDeserialize, version::PROTOCOL_VERSION}; +use near_primitives::borsh::BorshDeserialize; mod adapters; mod config; @@ -369,15 +369,7 @@ async fn account_balance( Err(crate::errors::ErrorKind::NotFound(_)) => ( block.header.hash, block.header.height, - near_primitives::account::Account::new( - 0, - 0, - 0, - Default::default(), - 0, - PROTOCOL_VERSION, - ) - .into(), + near_primitives::account::Account::new(0, 0, Default::default(), 0).into(), ), Err(err) => return Err(err.into()), }; diff --git a/core/chain-configs/Cargo.toml b/core/chain-configs/Cargo.toml index cb9d585ffb4..890a220e06f 100644 --- a/core/chain-configs/Cargo.toml +++ b/core/chain-configs/Cargo.toml @@ -32,7 +32,6 @@ near-primitives.workspace = true near-config-utils.workspace = true [features] -protocol_feature_nonrefundable_transfer_nep491 = [] nightly_protocol = [ "near-o11y/nightly_protocol", "near-parameters/nightly_protocol", @@ -43,7 +42,6 @@ nightly = [ "near-parameters/nightly", "near-primitives/nightly", "nightly_protocol", - "protocol_feature_nonrefundable_transfer_nep491", ] test_genesis = ["near-primitives/rand", "near-primitives/test_utils"] test_utils = ["near-primitives/rand"] diff --git a/core/chain-configs/src/genesis_validate.rs b/core/chain-configs/src/genesis_validate.rs index b2cb11803d6..b2674cbbae2 100644 --- a/core/chain-configs/src/genesis_validate.rs +++ b/core/chain-configs/src/genesis_validate.rs @@ -200,31 +200,11 @@ mod test { use near_crypto::{KeyType, PublicKey}; use near_primitives::account::{AccessKey, Account}; use near_primitives::types::AccountInfo; - use near_primitives::version::PROTOCOL_VERSION; const VALID_ED25519_RISTRETTO_KEY: &str = "ed25519:KuTCtARNzxZQ3YvXDeLjx83FDqxv2SdQTSbiq876zR7"; fn create_account() -> Account { - Account::new(100, 10, 0, Default::default(), 0, PROTOCOL_VERSION) - } - - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - #[test] - fn test_total_supply_does_not_depend_on_permanent_storage_bytes() { - let mut config = GenesisConfig::default(); - config.epoch_length = 42; - config.total_supply = 110; - config.validators = vec![AccountInfo { - account_id: "test".parse().unwrap(), - public_key: VALID_ED25519_RISTRETTO_KEY.parse().unwrap(), - amount: 10, - }]; - let records = GenesisRecords(vec![StateRecord::Account { - account_id: "test".parse().unwrap(), - account: Account::new(100, 10, 1, Default::default(), 0, PROTOCOL_VERSION), - }]); - let genesis = &Genesis::new(config, records).unwrap(); - validate_genesis(genesis).unwrap(); + Account::new(100, 10, Default::default(), 0) } #[test] diff --git a/core/chain-configs/src/test_genesis.rs b/core/chain-configs/src/test_genesis.rs index 42cbcc9c76a..93044a35370 100644 --- a/core/chain-configs/src/test_genesis.rs +++ b/core/chain-configs/src/test_genesis.rs @@ -447,10 +447,8 @@ impl TestGenesisBuilder { account: Account::new( user_account.balance, validator_stake.remove(&user_account.account_id).unwrap_or(0), - 0, CryptoHash::default(), 0, - self.protocol_version, ), }); for access_key in &user_account.access_keys { @@ -467,14 +465,7 @@ impl TestGenesisBuilder { for (account_id, balance) in validator_stake { records.push(StateRecord::Account { account_id, - account: Account::new( - 0, - balance, - 0, - CryptoHash::default(), - 0, - self.protocol_version, - ), + account: Account::new(0, balance, CryptoHash::default(), 0), }); } diff --git a/core/chain-configs/src/test_utils.rs b/core/chain-configs/src/test_utils.rs index dd18ef7bb56..aca9b93a047 100644 --- a/core/chain-configs/src/test_utils.rs +++ b/core/chain-configs/src/test_utils.rs @@ -185,7 +185,7 @@ pub fn add_account_with_key( ) { records.push(StateRecord::Account { account_id: account_id.clone(), - account: Account::new(amount, staked, 0, code_hash, 0, PROTOCOL_VERSION), + account: Account::new(amount, staked, code_hash, 0), }); records.push(StateRecord::AccessKey { account_id, diff --git a/core/primitives-core/Cargo.toml b/core/primitives-core/Cargo.toml index 532cd3d9736..be13270c2e7 100644 --- a/core/primitives-core/Cargo.toml +++ b/core/primitives-core/Cargo.toml @@ -35,12 +35,10 @@ expect-test.workspace = true [features] default = [] protocol_feature_fix_contract_loading_cost = [] -protocol_feature_nonrefundable_transfer_nep491 = [] nightly = [ "nightly_protocol", "protocol_feature_fix_contract_loading_cost", - "protocol_feature_nonrefundable_transfer_nep491", ] nightly_protocol = [ diff --git a/core/primitives-core/src/account.rs b/core/primitives-core/src/account.rs index 33f750a51d3..1b668d62c52 100644 --- a/core/primitives-core/src/account.rs +++ b/core/primitives-core/src/account.rs @@ -1,7 +1,6 @@ -use crate::checked_feature; use crate::hash::CryptoHash; use crate::serialize::dec_format; -use crate::types::{Balance, Nonce, ProtocolVersion, StorageUsage}; +use crate::types::{Balance, Nonce, StorageUsage}; use borsh::{BorshDeserialize, BorshSerialize}; pub use near_account_id as id; use near_schema_checker_lib::ProtocolSchema; @@ -62,19 +61,7 @@ pub struct AccountV1 { storage_usage: StorageUsage, } -impl AccountV1 { - fn to_v2(&self, permanent_storage_bytes: StorageUsage) -> AccountV2 { - AccountV2 { - amount: self.amount, - locked: self.locked, - code_hash: self.code_hash, - storage_usage: self.storage_usage, - permanent_storage_bytes, - } - } -} - -/// V2 introduces permanent_storage_bytes +// TODO(global-contract): add new field #[derive( BorshSerialize, BorshDeserialize, @@ -95,8 +82,6 @@ pub struct AccountV2 { code_hash: CryptoHash, /// Storage used by the given account, includes account id, this struct, access keys and other data. storage_usage: StorageUsage, - /// Permanent storage allowance, additional to what storage staking gives. - permanent_storage_bytes: StorageUsage, } impl Account { @@ -108,32 +93,13 @@ impl Account { /// differentiate AccountVersion V1 from newer versions. const SERIALIZATION_SENTINEL: u128 = u128::MAX; - // TODO(nonrefundable) Consider using consider some additional new types - // or a different way to write down constructor (e.g. builder pattern.) pub fn new( amount: Balance, locked: Balance, - permanent_storage_bytes: StorageUsage, code_hash: CryptoHash, storage_usage: StorageUsage, - protocol_version: ProtocolVersion, ) -> Self { - if permanent_storage_bytes > 0 { - assert!(checked_feature!( - "protocol_feature_nonrefundable_transfer_nep491", - NonrefundableStorage, - protocol_version - )); - Self::V2(AccountV2 { - amount, - locked, - permanent_storage_bytes, - code_hash, - storage_usage, - }) - } else { - Self::V1(AccountV1 { amount, locked, code_hash, storage_usage }) - } + Self::V1(AccountV1 { amount, locked, code_hash, storage_usage }) } #[inline] @@ -144,14 +110,6 @@ impl Account { } } - #[inline] - pub fn permanent_storage_bytes(&self) -> StorageUsage { - match self { - Self::V1(_) => 0, - Self::V2(account) => account.permanent_storage_bytes, - } - } - #[inline] pub fn locked(&self) -> Balance { match self { @@ -192,16 +150,6 @@ impl Account { } } - #[inline] - pub fn set_permanent_storage_bytes(&mut self, permanent_storage_bytes: StorageUsage) { - match self { - Self::V1(v1) => { - *self = Account::V2(v1.to_v2(permanent_storage_bytes)); - } - Self::V2(v2) => v2.permanent_storage_bytes = permanent_storage_bytes, - } - } - #[inline] pub fn set_locked(&mut self, locked: Balance) { match self { @@ -235,8 +183,6 @@ struct SerdeAccount { amount: Balance, #[serde(with = "dec_format")] locked: Balance, - #[serde(with = "dec_format", default, skip_serializing_if = "Option::is_none")] - permanent_storage_bytes: Option, code_hash: CryptoHash, storage_usage: StorageUsage, /// Version of Account in re migrations and similar. @@ -251,33 +197,18 @@ impl<'de> serde::Deserialize<'de> for Account { { let account_data = SerdeAccount::deserialize(deserializer)?; match account_data.version { - AccountVersion::V1 => { - if account_data.permanent_storage_bytes.is_some() { - return Err(serde::de::Error::custom( - "permanent storage bytes should not be set for V1 account", - )); - } - Ok(Account::V1(AccountV1 { - amount: account_data.amount, - locked: account_data.locked, - code_hash: account_data.code_hash, - storage_usage: account_data.storage_usage, - })) - } - AccountVersion::V2 => { - let Some(permanent_storage_bytes) = account_data.permanent_storage_bytes else { - return Err(serde::de::Error::custom( - "permanent storage bytes is missing for V2", - )); - }; - Ok(Account::V2(AccountV2 { - amount: account_data.amount, - locked: account_data.locked, - permanent_storage_bytes, - code_hash: account_data.code_hash, - storage_usage: account_data.storage_usage, - })) - } + AccountVersion::V1 => Ok(Account::V1(AccountV1 { + amount: account_data.amount, + locked: account_data.locked, + code_hash: account_data.code_hash, + storage_usage: account_data.storage_usage, + })), + AccountVersion::V2 => Ok(Account::V2(AccountV2 { + amount: account_data.amount, + locked: account_data.locked, + code_hash: account_data.code_hash, + storage_usage: account_data.storage_usage, + })), } } } @@ -288,14 +219,9 @@ impl serde::Serialize for Account { S: serde::Serializer, { let version = self.version(); - let permanent_storage_bytes = match version { - AccountVersion::V1 => None, - AccountVersion::V2 => Some(self.permanent_storage_bytes()), - }; let repr = SerdeAccount { amount: self.amount(), locked: self.locked(), - permanent_storage_bytes, code_hash: self.code_hash(), storage_usage: self.storage_usage(), version, @@ -445,23 +371,8 @@ pub struct FunctionCallPermission { #[cfg(test)] mod tests { - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - use crate::version::ProtocolFeature; - use super::*; - #[test] - #[should_panic] - fn test_v1_account_cannot_have_permanent_storage_bytes() { - #[cfg(not(feature = "protocol_feature_nonrefundable_transfer_nep491"))] - let protocol_version = crate::version::PROTOCOL_VERSION; - - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - let protocol_version = ProtocolFeature::NonrefundableStorage.protocol_version() - 1; - - Account::new(0, 0, 1, CryptoHash::default(), 0, protocol_version); - } - #[test] fn test_v1_account_serde_serialization() { let old_account = AccountV1 { @@ -475,7 +386,6 @@ mod tests { let expected_serde_repr = SerdeAccount { amount: old_account.amount, locked: old_account.locked, - permanent_storage_bytes: None, code_hash: old_account.code_hash, storage_usage: old_account.storage_usage, version: AccountVersion::V1, @@ -515,7 +425,6 @@ mod tests { let account_v2 = AccountV2 { amount: 10_000_000, locked: 100_000, - permanent_storage_bytes: 2000, code_hash: CryptoHash::hash_bytes(&[42]), storage_usage: 1000, }; @@ -525,7 +434,6 @@ mod tests { let expected_serde_repr = SerdeAccount { amount: account_v2.amount, locked: account_v2.locked, - permanent_storage_bytes: Some(account_v2.permanent_storage_bytes), code_hash: account_v2.code_hash, storage_usage: account_v2.storage_usage, version: AccountVersion::V2, @@ -537,33 +445,11 @@ mod tests { assert_eq!(deserialized_account, account); } - /// It is impossible to construct V1 account with permanent_storage_bytes greater than 0. - /// So the situation in this test is theoretical. - /// - /// Serialization of V1 account with permanent_storage_bytes amount greater than 0 would pass without an error, - /// but an error would be raised on deserialization of such invalid data. - #[test] - fn test_account_v2_serde_serialization_invalid_data() { - let account = SerdeAccount { - amount: 10_000_000, - locked: 100_000, - permanent_storage_bytes: Some(1), - code_hash: CryptoHash::default(), - storage_usage: 1000, - version: AccountVersion::V1, - }; - let serialized_account = serde_json::to_string(&account).unwrap(); - let deserialization_result: Result = - serde_json::from_str(&serialized_account); - assert!(deserialization_result.is_err()); - } - #[test] fn test_account_v2_borsh_serialization() { let account_v2 = AccountV2 { amount: 10_000_000, locked: 100_000, - permanent_storage_bytes: 2000, code_hash: CryptoHash::hash_bytes(&[42]), storage_usage: 1000, }; diff --git a/core/primitives-core/src/version.rs b/core/primitives-core/src/version.rs index 2424339da5f..17e914148ed 100644 --- a/core/primitives-core/src/version.rs +++ b/core/primitives-core/src/version.rs @@ -129,10 +129,6 @@ pub enum ProtocolFeature { FixContractLoadingCost, /// Enables rejection of blocks with outdated protocol versions. RejectBlocksWithOutdatedProtocolVersions, - /// Allows creating an account with a non refundable balance to cover storage costs. - /// NEP: - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - NonrefundableStorage, // NEP: https://github.com/near/NEPs/pull/488 BLS12381, RestrictTla, @@ -271,8 +267,6 @@ impl ProtocolFeature { // Nightly features: #[cfg(feature = "protocol_feature_fix_contract_loading_cost")] ProtocolFeature::FixContractLoadingCost => 129, - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - ProtocolFeature::NonrefundableStorage => 140, // TODO(#11201): When stabilizing this feature in mainnet, also remove the temporary code // that always enables this for mocknet (see config_mocknet function). ProtocolFeature::ShuffleShardAssignments => 143, diff --git a/core/primitives/Cargo.toml b/core/primitives/Cargo.toml index fafa05204e6..2c87f3f3792 100644 --- a/core/primitives/Cargo.toml +++ b/core/primitives/Cargo.toml @@ -64,9 +64,6 @@ clock = ["near-time/clock", "near-time/serde"] protocol_feature_fix_contract_loading_cost = [ "near-primitives-core/protocol_feature_fix_contract_loading_cost", ] -protocol_feature_nonrefundable_transfer_nep491 = [ - "near-primitives-core/protocol_feature_nonrefundable_transfer_nep491", -] nightly = [ "near-fmt/nightly", @@ -75,7 +72,6 @@ nightly = [ "near-primitives/nightly", "nightly_protocol", "protocol_feature_fix_contract_loading_cost", - "protocol_feature_nonrefundable_transfer_nep491", ] nightly_protocol = [ diff --git a/core/primitives/src/action/mod.rs b/core/primitives/src/action/mod.rs index 7c3a0ddef90..78e2fce8946 100644 --- a/core/primitives/src/action/mod.rs +++ b/core/primitives/src/action/mod.rs @@ -261,23 +261,6 @@ pub struct TransferAction { pub deposit: Balance, } -#[derive( - BorshSerialize, - BorshDeserialize, - PartialEq, - Eq, - Clone, - Debug, - serde::Serialize, - serde::Deserialize, - ProtocolSchema, -)] -#[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] -pub struct NonrefundableStorageTransferAction { - #[serde(with = "dec_format")] - pub deposit: Balance, -} - #[derive( BorshSerialize, BorshDeserialize, @@ -306,11 +289,6 @@ pub enum Action { Delegate(Box), DeployGlobalContract(DeployGlobalContractAction), UseGlobalContract(Box), - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - /// Makes a non-refundable transfer for storage allowance. - /// Only possible during new account creation. - /// For implicit account creation, it has to be the only action in the receipt. - NonrefundableStorageTransfer(NonrefundableStorageTransferAction), } const _: () = assert!( @@ -332,8 +310,6 @@ impl Action { match self { Action::FunctionCall(a) => a.deposit, Action::Transfer(a) => a.deposit, - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - Action::NonrefundableStorageTransfer(a) => a.deposit, _ => 0, } } @@ -369,13 +345,6 @@ impl From for Action { } } -#[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] -impl From for Action { - fn from(nonrefundable_transfer_action: NonrefundableStorageTransferAction) -> Self { - Self::NonrefundableStorageTransfer(nonrefundable_transfer_action) - } -} - impl From for Action { fn from(stake_action: StakeAction) -> Self { Self::Stake(Box::new(stake_action)) diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index 1b322036ad4..7e43f2bb525 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -591,8 +591,6 @@ pub enum ActionErrorKind { DelegateActionInvalidNonce { delegate_nonce: Nonce, ak_nonce: Nonce }, /// DelegateAction nonce is larger than the upper bound given by the block height DelegateActionNonceTooLarge { delegate_nonce: Nonce, upper_bound: Nonce }, - /// Non-refundable storage transfer to an existing account is not allowed according to NEP-491. - NonRefundableTransferToExistingAccount { account_id: AccountId }, } impl From for ActionError { @@ -933,9 +931,6 @@ impl Display for ActionErrorKind { ActionErrorKind::DelegateActionAccessKeyError(access_key_error) => Display::fmt(&access_key_error, f), ActionErrorKind::DelegateActionInvalidNonce { delegate_nonce, ak_nonce } => write!(f, "DelegateAction nonce {} must be larger than nonce of the used access key {}", delegate_nonce, ak_nonce), ActionErrorKind::DelegateActionNonceTooLarge { delegate_nonce, upper_bound } => write!(f, "DelegateAction nonce {} must be smaller than the access key nonce upper bound {}", delegate_nonce, upper_bound), - ActionErrorKind::NonRefundableTransferToExistingAccount { account_id} => { - write!(f, "Can't make non-refundable storage transfer to {} because it already exists", account_id) - } } } } diff --git a/core/primitives/src/test_utils.rs b/core/primitives/src/test_utils.rs index d31cfd5003f..dd86e8f7c33 100644 --- a/core/primitives/src/test_utils.rs +++ b/core/primitives/src/test_utils.rs @@ -26,7 +26,7 @@ use std::collections::HashMap; use std::sync::Arc; pub fn account_new(amount: Balance, code_hash: CryptoHash) -> Account { - Account::new(amount, 0, 0, code_hash, std::mem::size_of::() as u64, PROTOCOL_VERSION) + Account::new(amount, 0, code_hash, std::mem::size_of::() as u64) } impl Transaction { diff --git a/core/primitives/src/transaction.rs b/core/primitives/src/transaction.rs index 261d1a5660b..54707c11697 100644 --- a/core/primitives/src/transaction.rs +++ b/core/primitives/src/transaction.rs @@ -1,5 +1,3 @@ -#[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] -pub use crate::action::NonrefundableStorageTransferAction; pub use crate::action::{ Action, AddKeyAction, CreateAccountAction, DeleteAccountAction, DeleteKeyAction, DeployContractAction, FunctionCallAction, StakeAction, TransferAction, diff --git a/core/primitives/src/views.rs b/core/primitives/src/views.rs index 05a68f772d5..e60be033c0d 100644 --- a/core/primitives/src/views.rs +++ b/core/primitives/src/views.rs @@ -26,8 +26,6 @@ use crate::sharding::{ ShardChunkHeaderInnerV3, ShardChunkHeaderV3, }; use crate::stateless_validation::chunk_endorsements_bitmap::ChunkEndorsementsBitmap; -#[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] -use crate::transaction::NonrefundableStorageTransferAction; use crate::transaction::{ Action, AddKeyAction, CreateAccountAction, DeleteAccountAction, DeleteKeyAction, DeployContractAction, ExecutionMetadata, ExecutionOutcome, ExecutionOutcomeWithIdAndProof, @@ -47,7 +45,6 @@ use near_fmt::{AbbrBytes, Slice}; use near_parameters::config::CongestionControlConfig; use near_parameters::view::CongestionControlConfigView; use near_parameters::{ActionCosts, ExtCosts}; -use near_primitives_core::version::PROTOCOL_VERSION; use near_schema_checker_lib::ProtocolSchema; use near_time::Utc; use serde_with::base64::Base64; @@ -66,9 +63,6 @@ pub struct AccountView { pub amount: Balance, #[serde(with = "dec_format")] pub locked: Balance, - #[serde(with = "dec_format")] - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - pub permanent_storage_bytes: StorageUsage, pub code_hash: CryptoHash, pub storage_usage: StorageUsage, /// TODO(2271): deprecated. @@ -91,8 +85,6 @@ impl From<&Account> for AccountView { AccountView { amount: account.amount(), locked: account.locked(), - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - permanent_storage_bytes: account.permanent_storage_bytes(), code_hash: account.code_hash(), storage_usage: account.storage_usage(), storage_paid_at: 0, @@ -108,18 +100,7 @@ impl From for AccountView { impl From<&AccountView> for Account { fn from(view: &AccountView) -> Self { - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - let permanent_storage_bytes = view.permanent_storage_bytes; - #[cfg(not(feature = "protocol_feature_nonrefundable_transfer_nep491"))] - let permanent_storage_bytes = 0; - Account::new( - view.amount, - view.locked, - permanent_storage_bytes, - view.code_hash, - view.storage_usage, - PROTOCOL_VERSION, - ) + Account::new(view.amount, view.locked, view.code_hash, view.storage_usage) } } @@ -1151,11 +1132,6 @@ pub enum ActionView { #[serde(with = "dec_format")] deposit: Balance, }, - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - NonrefundableStorageTransfer { - #[serde(with = "dec_format")] - deposit: Balance, - }, Stake { #[serde(with = "dec_format")] stake: Balance, @@ -1206,10 +1182,6 @@ impl From for ActionView { deposit: action.deposit, }, Action::Transfer(action) => ActionView::Transfer { deposit: action.deposit }, - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - Action::NonrefundableStorageTransfer(action) => { - ActionView::NonrefundableStorageTransfer { deposit: action.deposit } - } Action::Stake(action) => { ActionView::Stake { stake: action.stake, public_key: action.public_key } } @@ -1264,10 +1236,6 @@ impl TryFrom for Action { })) } ActionView::Transfer { deposit } => Action::Transfer(TransferAction { deposit }), - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - ActionView::NonrefundableStorageTransfer { deposit } => { - Action::NonrefundableStorageTransfer(NonrefundableStorageTransferAction { deposit }) - } ActionView::Stake { stake, public_key } => { Action::Stake(Box::new(StakeAction { stake, public_key })) } diff --git a/genesis-tools/genesis-csv-to-json/src/csv_parser.rs b/genesis-tools/genesis-csv-to-json/src/csv_parser.rs index e717877b162..73f752f0d9b 100644 --- a/genesis-tools/genesis-csv-to-json/src/csv_parser.rs +++ b/genesis-tools/genesis-csv-to-json/src/csv_parser.rs @@ -11,7 +11,6 @@ use near_primitives::receipt::{ActionReceipt, Receipt, ReceiptEnum}; use near_primitives::state_record::StateRecord; use near_primitives::transaction::{Action, FunctionCallAction}; use near_primitives::types::{AccountId, AccountInfo, Balance, Gas}; -use near_primitives::version::PROTOCOL_VERSION; use std::fs::File; use std::io::Read; use std::path::PathBuf; @@ -189,14 +188,7 @@ fn account_records(row: &Row, gas_price: Balance) -> Vec { let mut res = vec![StateRecord::Account { account_id: row.account_id.clone(), - account: Account::new( - row.amount, - row.validator_stake, - 0, - smart_contract_hash, - 0, - PROTOCOL_VERSION, - ), + account: Account::new(row.amount, row.validator_stake, smart_contract_hash, 0), }]; // Add restricted access keys. diff --git a/genesis-tools/genesis-populate/src/lib.rs b/genesis-tools/genesis-populate/src/lib.rs index e66f2780d78..c87bda5c31e 100644 --- a/genesis-tools/genesis-populate/src/lib.rs +++ b/genesis-tools/genesis-populate/src/lib.rs @@ -341,10 +341,8 @@ impl GenesisBuilder { let account = Account::new( testing_init_balance, testing_init_stake, - 0, self.additional_accounts_code_hash, 0, - self.genesis.config.protocol_version, ); set_account(&mut state_update, account_id.clone(), &account); let account_record = StateRecord::Account { account_id: account_id.clone(), account }; diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index 6357538f8b4..49a84f668d3 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -94,9 +94,6 @@ test_features = [ protocol_feature_fix_contract_loading_cost = [ "nearcore/protocol_feature_fix_contract_loading_cost", ] -protocol_feature_nonrefundable_transfer_nep491 = [ - "near-primitives/protocol_feature_nonrefundable_transfer_nep491", -] nightly = [ "near-actix-test-utils/nightly", @@ -125,7 +122,6 @@ nightly = [ "nightly_protocol", "node-runtime/nightly", "protocol_feature_fix_contract_loading_cost", - "protocol_feature_nonrefundable_transfer_nep491", "testlib/nightly", ] nightly_protocol = [ diff --git a/integration-tests/src/tests/client/features.rs b/integration-tests/src/tests/client/features.rs index 78e60389fc1..e49c74aeb59 100644 --- a/integration-tests/src/tests/client/features.rs +++ b/integration-tests/src/tests/client/features.rs @@ -17,8 +17,6 @@ mod increase_storage_compute_cost; mod limit_contract_functions_number; mod lower_storage_key_limit; mod nearvm; -#[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] -mod nonrefundable_transfer; mod orphan_chunk_state_witness; mod restore_receipts_after_fix_apply_chunks; mod restrict_tla; diff --git a/integration-tests/src/tests/client/features/nonrefundable_transfer.rs b/integration-tests/src/tests/client/features/nonrefundable_transfer.rs deleted file mode 100644 index 932ce35b7c9..00000000000 --- a/integration-tests/src/tests/client/features/nonrefundable_transfer.rs +++ /dev/null @@ -1,681 +0,0 @@ -//! Non-refundable transfers during account creation allow to sponsor an -//! accounts storage staking balance without that someone being able to run off -//! with the money. -//! -//! This feature introduces the NonrefundableStorageTransfer action. -//! -//! NEP: https://github.com/near/NEPs/pull/491 - -use near_chain_configs::Genesis; -use near_chain_configs::NEAR_BASE; -use near_client::test_utils::TestEnv; -use near_crypto::{InMemorySigner, KeyType, PublicKey, Signer}; -use near_parameters::RuntimeConfigStore; -use near_primitives::errors::{ - ActionError, ActionErrorKind, ActionsValidationError, InvalidTxError, TxExecutionError, -}; -use near_primitives::transaction::{ - Action, AddKeyAction, CreateAccountAction, DeleteAccountAction, DeployContractAction, - NonrefundableStorageTransferAction, SignedTransaction, TransferAction, -}; -use near_primitives::types::StorageUsage; -use near_primitives::types::{AccountId, Balance}; -use near_primitives::utils::{derive_eth_implicit_account_id, derive_near_implicit_account_id}; -use near_primitives::version::{ProtocolFeature, ProtocolVersion}; -use near_primitives::views::{ - ExecutionStatusView, FinalExecutionOutcomeView, QueryRequest, QueryResponseKind, -}; -use near_primitives_core::account::{AccessKey, AccessKeyPermission}; -use nearcore::test_utils::TestEnvNightshadeSetupExt; -use testlib::fees_utils::FeeHelper; - -use crate::node::RuntimeNode; - -#[derive(Clone, Debug)] -struct Transfers { - /// Regular transfer amount (if any). - regular_amount: Balance, - /// Non-refundable transfer amount (if any). - nonrefundable_amount: Balance, - /// Whether non-refundable transfer action should be first in the receipt. - nonrefundable_transfer_first: bool, -} - -/// Different `Transfers` configurations, where we only test cases where non-refundable transfer happens. -const TEST_CASES: [Transfers; 3] = [ - Transfers { regular_amount: 0, nonrefundable_amount: 1, nonrefundable_transfer_first: true }, - Transfers { regular_amount: 1, nonrefundable_amount: 1, nonrefundable_transfer_first: true }, - Transfers { regular_amount: 1, nonrefundable_amount: 1, nonrefundable_transfer_first: false }, -]; - -/// Contract size that does not fit within Zero-balance account limit. -const TEST_CONTRACT_SIZE: usize = 1500; - -struct TransferConfig { - /// Describes transfers configuration we are interested in. - transfers: Transfers, - /// True if the receipt should create account. - account_creation: bool, - /// Differentiates between named and implicit account creation, if `account_creation` is true. - implicit_account_creation: bool, - /// Whether the last action in the receipt should deploy a contract. - deploy_contract: bool, -} - -/// Default sender to use in tests of this module. -fn sender() -> AccountId { - "test0".parse().unwrap() -} - -/// Default receiver to use in tests of this module. -fn receiver() -> AccountId { - "test1".parse().unwrap() -} - -fn new_account_id(index: usize) -> AccountId { - format!("subaccount{}.test0", index).parse().unwrap() -} - -/// Default signer (corresponding to the default sender) to use in tests of this module. -fn signer() -> Signer { - InMemorySigner::test_signer(&sender()) -} - -/// Creates a test environment using given protocol version (if some). -fn setup_env_with_protocol_version(protocol_version: Option) -> TestEnv { - let mut genesis = Genesis::test(vec![sender(), receiver()], 1); - if let Some(protocol_version) = protocol_version { - genesis.config.protocol_version = protocol_version; - } - // Must match the config store used by the `fee_helper()`. - let store = RuntimeConfigStore::new(None); - TestEnv::builder(&genesis.config) - .nightshade_runtimes_with_runtime_config_store(&genesis, vec![store; 2]) - .build() -} - -/// Creates a test environment using default protocol version. -fn setup_env() -> TestEnv { - setup_env_with_protocol_version(None) -} - -fn fee_helper() -> FeeHelper { - let node = RuntimeNode::new(&sender()); - crate::tests::standard_cases::fee_helper(&node) -} - -fn get_nonce(env: &mut TestEnv, signer: &Signer) -> u64 { - let request = QueryRequest::ViewAccessKey { - account_id: signer.get_account_id(), - public_key: signer.public_key(), - }; - match env.query_view(request).unwrap().kind { - QueryResponseKind::AccessKey(view) => view.nonce, - _ => panic!("wrong query response"), - } -} - -fn account_exists(env: &mut TestEnv, account_id: AccountId) -> bool { - let request = QueryRequest::ViewAccount { account_id }; - env.query_view(request).is_ok() -} - -fn get_total_supply(env: &TestEnv) -> Balance { - let tip = env.clients[0].chain.head().unwrap(); - let block_info = env.clients[0].chain.get_block_header(&tip.last_block_hash).unwrap(); - block_info.total_supply() -} - -fn execute_transaction_from_actions( - env: &mut TestEnv, - actions: Vec, - signer: &Signer, - receiver: AccountId, -) -> Result { - let tip = env.clients[0].chain.head().unwrap(); - let nonce = get_nonce(env, signer); - let tx = SignedTransaction::from_actions( - nonce + 1, - signer.get_account_id(), - receiver, - &signer, - actions, - tip.last_block_hash, - 0, - ); - let tx_result = env.execute_tx(tx); - let height = env.clients[0].chain.head().unwrap().height; - for i in 0..2 { - env.produce_block(0, height + 1 + i); - } - tx_result -} - -/// Submits a transfer (regular, non-refundable, or both). -/// Can possibly create an account or deploy a contract, depending on the `config`. -/// -/// This methods checks that the balance is subtracted from the sender and added -/// to the receiver, if the status was ok. No checks are done on an error. -fn exec_transfers( - env: &mut TestEnv, - signer: Signer, - receiver: AccountId, - config: TransferConfig, -) -> Result { - let sender_pre_balance = env.query_balance(sender()); - let (receiver_before_amount, receiver_before_permanent_storage_bytes) = - if config.account_creation { - (0, 0) - } else { - let receiver_before = env.query_account(receiver.clone()); - (receiver_before.amount, receiver_before.permanent_storage_bytes) - }; - - let mut actions = vec![]; - - if config.account_creation && !config.implicit_account_creation { - actions.push(Action::CreateAccount(CreateAccountAction {})); - actions.push(Action::AddKey(Box::new(AddKeyAction { - public_key: PublicKey::from_seed(KeyType::ED25519, receiver.as_str()), - access_key: AccessKey { nonce: 0, permission: AccessKeyPermission::FullAccess }, - }))); - } - - if config.transfers.nonrefundable_transfer_first && config.transfers.nonrefundable_amount > 0 { - actions.push(Action::NonrefundableStorageTransfer(NonrefundableStorageTransferAction { - deposit: config.transfers.nonrefundable_amount, - })); - } - if config.transfers.regular_amount > 0 { - actions.push(Action::Transfer(TransferAction { deposit: config.transfers.regular_amount })); - } - if !config.transfers.nonrefundable_transfer_first && config.transfers.nonrefundable_amount > 0 { - actions.push(Action::NonrefundableStorageTransfer(NonrefundableStorageTransferAction { - deposit: config.transfers.nonrefundable_amount, - })); - } - - if config.deploy_contract { - let contract = near_test_contracts::sized_contract(TEST_CONTRACT_SIZE); - actions.push(Action::DeployContract(DeployContractAction { code: contract.to_vec() })) - } - - let tx_result = execute_transaction_from_actions(env, actions, &signer, receiver.clone()); - - let outcome = match &tx_result { - Ok(outcome) => outcome, - _ => { - return tx_result; - } - }; - - if !matches!(outcome.status, near_primitives::views::FinalExecutionStatus::SuccessValue(_)) { - return tx_result; - } - - let gas_cost = outcome.tokens_burnt(); - assert_eq!( - sender_pre_balance - - config.transfers.regular_amount - - config.transfers.nonrefundable_amount - - gas_cost, - env.query_balance(sender()) - ); - - let receiver_expected_amount_after = receiver_before_amount + config.transfers.regular_amount; - let receiver_expected_permanent_storage_bytes_after = receiver_before_permanent_storage_bytes - + (config.transfers.nonrefundable_amount / fee_helper().rt_cfg.storage_amount_per_byte()) - as StorageUsage; - let receiver_after = env.query_account(receiver); - assert_eq!(receiver_after.amount, receiver_expected_amount_after); - assert_eq!( - receiver_after.permanent_storage_bytes, - receiver_expected_permanent_storage_bytes_after - ); - - tx_result -} - -fn regular_transfer( - env: &mut TestEnv, - signer: Signer, - receiver: AccountId, - amount: Balance, -) -> Result { - exec_transfers( - env, - signer, - receiver, - TransferConfig { - transfers: Transfers { - regular_amount: amount, - nonrefundable_amount: 0, - nonrefundable_transfer_first: false, - }, - account_creation: false, - implicit_account_creation: false, - deploy_contract: false, - }, - ) -} - -fn delete_account( - env: &mut TestEnv, - signer: &Signer, - beneficiary_id: AccountId, -) -> Result { - let actions = vec![Action::DeleteAccount(DeleteAccountAction { beneficiary_id })]; - execute_transaction_from_actions(env, actions, &signer, signer.get_account_id()) -} - -/// Can delete account with permanent storage bytes. -#[test] -fn deleting_account_with_permanent_storage_bytes() { - let mut env = setup_env(); - let new_account_id = new_account_id(0); - let new_account = InMemorySigner::test_signer(&new_account_id); - let regular_amount = 10u128.pow(20); - let nonrefundable_amount = NEAR_BASE; - // Create account with permanent storage bytes. - // Send some NEAR (refundable) so that the new account is able to pay the gas for its deletion in the next transaction. - // Deploy a contract that does not fit within Zero-balance account limit. - let create_account_tx_result = exec_transfers( - &mut env, - signer(), - new_account_id.clone(), - TransferConfig { - transfers: Transfers { - regular_amount, - nonrefundable_amount, - nonrefundable_transfer_first: true, - }, - account_creation: true, - implicit_account_creation: false, - deploy_contract: true, - }, - ); - create_account_tx_result.unwrap().assert_success(); - - // Delete the new account (that has permanent storage bytes worth 1 NEAR). - let beneficiary_id = receiver(); - let beneficiary_before = env.query_account(beneficiary_id.clone()); - let delete_account_tx_result = delete_account(&mut env, &new_account, beneficiary_id.clone()); - delete_account_tx_result.unwrap().assert_success(); - assert!(!account_exists(&mut env, new_account_id)); - - // Check that the beneficiary account received the remaining balance from the deleted account but nothing more. - // Especially, check that the permanent storage bytes of the beneficiary account were not affected. - let beneficiary_after = env.query_account(beneficiary_id); - assert_eq!( - beneficiary_after.amount, - beneficiary_before.amount + regular_amount - fee_helper().prepaid_delete_account_cost() - ); - assert_eq!( - beneficiary_after.permanent_storage_bytes, - beneficiary_before.permanent_storage_bytes - ); -} - -/// Permanent storage bytes cannot be transferred. -#[test] -fn permanent_storage_bytes_cannot_be_transferred() { - let mut env = setup_env(); - let new_account_id = new_account_id(0); - let new_account = InMemorySigner::test_signer(&new_account_id); - // The `new_account` is created with permanent storage bytes worth 1 NEAR. - let create_account_tx_result = exec_transfers( - &mut env, - signer(), - new_account_id.clone(), - TransferConfig { - transfers: Transfers { - regular_amount: 0, - nonrefundable_amount: NEAR_BASE, - nonrefundable_transfer_first: true, - }, - account_creation: true, - implicit_account_creation: false, - deploy_contract: false, - }, - ); - create_account_tx_result.unwrap().assert_success(); - - // Although `new_account` has permanent storage bytes worth 1 NEAR, it cannot make neither refundable nor non-refundable transfer of 1 yoctoNEAR. - for nonrefundable in [false, true] { - let transfer_tx_result = exec_transfers( - &mut env, - new_account.clone(), - receiver(), - TransferConfig { - transfers: Transfers { - regular_amount: if nonrefundable { 0 } else { 1 }, - nonrefundable_amount: if nonrefundable { 1 } else { 0 }, - nonrefundable_transfer_first: true, - }, - account_creation: false, - implicit_account_creation: false, - deploy_contract: false, - }, - ); - match transfer_tx_result { - Err(InvalidTxError::NotEnoughBalance { signer_id, balance, .. }) => { - assert_eq!(signer_id, new_account_id); - assert_eq!(balance, 0); - } - _ => panic!("Expected NotEnoughBalance error"), - } - } -} - -fn calculate_named_account_storage_usage(contract_size: usize) -> u64 { - let account_id = new_account_id(0); - let mut account_storage_usage = fee_helper().cfg().storage_usage_config.num_bytes_account; - account_storage_usage += fee_helper().cfg().storage_usage_config.num_extra_bytes_record; - account_storage_usage += - PublicKey::from_seed(KeyType::ED25519, account_id.as_str()).len() as u64; - account_storage_usage += borsh::object_length(&AccessKey::full_access()).unwrap() as u64; - account_storage_usage + contract_size as u64 -} - -/// Permanent storage bytes allows to have account with zero balance and more than 1kB of state. -#[test] -fn permanent_storage_bytes_allows_1kb_state_with_zero_balance() { - assert!(fee_helper().rt_cfg.storage_amount_per_byte() > 0); - let mut env = setup_env(); - let new_account_id = new_account_id(0); - let storage_bytes_required = calculate_named_account_storage_usage(TEST_CONTRACT_SIZE) as u128; - let nonrefundable_amount_required = - storage_bytes_required * fee_helper().rt_cfg.storage_amount_per_byte(); - let tx_result = exec_transfers( - &mut env, - signer(), - new_account_id, - TransferConfig { - transfers: Transfers { - regular_amount: 0, - nonrefundable_amount: nonrefundable_amount_required, - nonrefundable_transfer_first: true, - }, - account_creation: true, - implicit_account_creation: false, - deploy_contract: true, - }, - ); - tx_result.unwrap().assert_success(); -} - -/// 1 yoctonear less than required to pay for necessary permanent storage bytes. -#[test] -fn insufficient_nonrefundable_transfer_amount() { - let mut env = setup_env(); - let new_account_id = new_account_id(0); - let storage_bytes_required = calculate_named_account_storage_usage(TEST_CONTRACT_SIZE) as u128; - let nonrefundable_amount_required = - storage_bytes_required * fee_helper().rt_cfg.storage_amount_per_byte(); - let tx_result = exec_transfers( - &mut env, - signer(), - new_account_id.clone(), - TransferConfig { - transfers: Transfers { - regular_amount: 0, - // We subtract 1 yoctonear here. - nonrefundable_amount: nonrefundable_amount_required - 1, - nonrefundable_transfer_first: true, - }, - account_creation: true, - implicit_account_creation: false, - deploy_contract: true, - }, - ); - let status = &tx_result.unwrap().receipts_outcome[0].outcome.status; - assert!(matches!( - status, - ExecutionStatusView::Failure(TxExecutionError::ActionError( - ActionError { kind: ActionErrorKind::LackBalanceForState { account_id, .. }, .. } - )) if *account_id == new_account_id - )); -} - -/// Test that both storage staking and permanent storage bytes are taken into account for storage allowance. -/// Test that further transfer is prohibited because it would make the storage stake too low. -#[test] -fn storage_staking_and_permanent_storage_bytes_taken_into_account() { - let mut env = setup_env(); - let new_account_id = new_account_id(0); - let new_account = InMemorySigner::test_signer(&new_account_id); - let storage_bytes_required = calculate_named_account_storage_usage(TEST_CONTRACT_SIZE) as u128; - // Just third of the required storage bytes will be covered by permanent storage bytes. - let permanent_storage_bytes = storage_bytes_required / 3; - let nonrefundable_amount = - permanent_storage_bytes * fee_helper().rt_cfg.storage_amount_per_byte(); - // Remaining storage allowance will be provided by storage staking. - let storage_stake = (storage_bytes_required - permanent_storage_bytes) - * fee_helper().rt_cfg.storage_amount_per_byte(); - let tx_result = exec_transfers( - &mut env, - signer(), - new_account_id.clone(), - TransferConfig { - transfers: Transfers { - regular_amount: storage_stake, - nonrefundable_amount, - nonrefundable_transfer_first: false, - }, - account_creation: true, - implicit_account_creation: false, - deploy_contract: true, - }, - ); - tx_result.unwrap().assert_success(); - - // Now we attempt to make a transfer of 1 yoctonear that would result in insufficient balance for state. - let tx_result = regular_transfer(&mut env, new_account, receiver(), 1); - assert!(matches!( - tx_result, - Err(InvalidTxError::LackBalanceForState { signer_id, .. }) if *signer_id == new_account_id - )); -} - -/// Non-refundable transfer amount is burnt. -#[test] -fn non_refundable_transfer_amount_is_burnt() { - let mut env = setup_env(); - let total_supply_before = get_total_supply(&env); - let new_account_id = new_account_id(0); - let nonrefundable_amount = 42 * NEAR_BASE; - let tx_result = exec_transfers( - &mut env, - signer(), - new_account_id, - TransferConfig { - transfers: Transfers { - regular_amount: 0, - nonrefundable_amount, - nonrefundable_transfer_first: true, - }, - account_creation: true, - implicit_account_creation: false, - deploy_contract: false, - }, - ); - tx_result.unwrap().assert_success(); - let total_supply_after = get_total_supply(&env); - let transaction_fee = fee_helper().create_account_transfer_full_key_cost(); - assert_eq!(total_supply_after, total_supply_before - transaction_fee - nonrefundable_amount); -} - -/// Non-refundable amount is burnt even if the receiver is both created and deleted in the single action receipt. -#[test] -fn create_account_nonrefundable_delete_account() { - let mut env = setup_env(); - let mut actions = vec![]; - let new_account_id = new_account_id(0); - let nonrefundable_amount = 42 * NEAR_BASE; - - actions.push(Action::CreateAccount(CreateAccountAction {})); - actions.push(Action::AddKey(Box::new(AddKeyAction { - public_key: PublicKey::from_seed(KeyType::ED25519, new_account_id.as_str()), - access_key: AccessKey { nonce: 0, permission: AccessKeyPermission::FullAccess }, - }))); - actions.push(Action::NonrefundableStorageTransfer(NonrefundableStorageTransferAction { - deposit: nonrefundable_amount, - })); - actions.push(Action::DeleteAccount(DeleteAccountAction { beneficiary_id: sender() })); - - let total_supply_before = get_total_supply(&env); - let tx_result = execute_transaction_from_actions(&mut env, actions, &signer(), new_account_id); - tx_result.unwrap().assert_success(); - // We create and delete account within a single action receipt, thus we remove duplicate `new_action_receipt_cost` from this calculation. - let transaction_fee = fee_helper().create_account_transfer_full_key_cost() - + fee_helper().prepaid_delete_account_cost() - - fee_helper().new_action_receipt_cost(); - let total_supply_after = get_total_supply(&env); - assert_eq!(total_supply_after, total_supply_before - transaction_fee - nonrefundable_amount); -} - -/// Non-refundable transfer successfully adds permanent storage bytes when creating named account. -#[test] -fn non_refundable_transfer_create_named_account() { - for (index, transfers) in TEST_CASES.iter().enumerate() { - let new_account_id = new_account_id(index); - let tx_result = exec_transfers( - &mut setup_env(), - signer(), - new_account_id, - TransferConfig { - transfers: transfers.clone(), - account_creation: true, - implicit_account_creation: false, - deploy_contract: false, - }, - ); - tx_result.unwrap().assert_success(); - } -} - -/// Non-refundable transfer successfully adds permanent storage bytes when creating NEAR-implicit account. -#[test] -fn non_refundable_transfer_create_near_implicit_account() { - for (index, transfers) in TEST_CASES.iter().enumerate() { - let public_key = - PublicKey::from_seed(KeyType::ED25519, &format!("near{}", index).to_string()); - let new_account_id = derive_near_implicit_account_id(public_key.unwrap_as_ed25519()); - let tx_result = exec_transfers( - &mut setup_env(), - signer(), - new_account_id.clone(), - TransferConfig { - transfers: transfers.clone(), - account_creation: true, - implicit_account_creation: true, - deploy_contract: false, - }, - ); - if transfers.regular_amount == 0 { - tx_result.unwrap().assert_success(); - } else { - // Non-refundable transfer must be the only action in an implicit account creation transaction. - let status = &tx_result.unwrap().receipts_outcome[0].outcome.status; - assert!(matches!( - status, - ExecutionStatusView::Failure(TxExecutionError::ActionError( - ActionError { kind: ActionErrorKind::AccountDoesNotExist { account_id }, .. } - )) if *account_id == new_account_id, - )); - } - } -} - -/// Non-refundable transfer successfully adds permanent storage bytes when creating ETH-implicit account. -#[test] -fn non_refundable_transfer_create_eth_implicit_account() { - for (index, transfers) in TEST_CASES.iter().enumerate() { - let public_key = - PublicKey::from_seed(KeyType::SECP256K1, &format!("eth{}", index).to_string()); - let new_account_id = derive_eth_implicit_account_id(public_key.unwrap_as_secp256k1()); - let tx_result = exec_transfers( - &mut setup_env(), - signer(), - new_account_id.clone(), - TransferConfig { - transfers: transfers.clone(), - account_creation: true, - implicit_account_creation: true, - deploy_contract: false, - }, - ); - if transfers.regular_amount == 0 { - tx_result.unwrap().assert_success(); - } else { - // Non-refundable transfer must be the only action in an implicit account creation transaction. - let status = &tx_result.unwrap().receipts_outcome[0].outcome.status; - assert!(matches!( - status, - ExecutionStatusView::Failure(TxExecutionError::ActionError( - ActionError { kind: ActionErrorKind::AccountDoesNotExist { account_id }, .. } - )) if *account_id == new_account_id, - )); - } - } -} - -/// Non-refundable transfer is rejected on existing account. -#[test] -fn reject_non_refundable_transfer_existing_account() { - for transfers in TEST_CASES { - let tx_result = exec_transfers( - &mut setup_env(), - signer(), - receiver(), - TransferConfig { - transfers, - account_creation: false, - implicit_account_creation: false, - deploy_contract: false, - }, - ); - let status = &tx_result.unwrap().receipts_outcome[0].outcome.status; - assert!(matches!( - status, - ExecutionStatusView::Failure(TxExecutionError::ActionError( - ActionError { kind: ActionErrorKind::NonRefundableTransferToExistingAccount { account_id }, .. } - )) if *account_id == receiver(), - )); - } -} - -/// During the protocol upgrade phase, before the voting completes, we must not -/// include non-refundable transfer actions on the chain. -/// -/// The correct way to handle it is to reject transaction before they even get -/// into the transaction pool. Hence, we check that an `InvalidTxError` error is -/// returned for older protocol versions. -#[test] -fn reject_non_refundable_transfer_in_older_versions() { - let mut env = setup_env_with_protocol_version(Some( - ProtocolFeature::NonrefundableStorage.protocol_version() - 1, - )); - for transfers in TEST_CASES { - let tx_result = exec_transfers( - &mut env, - signer(), - receiver(), - TransferConfig { - transfers, - account_creation: false, - implicit_account_creation: false, - deploy_contract: false, - }, - ); - assert_eq!( - tx_result, - Err(InvalidTxError::ActionsValidation( - ActionsValidationError::UnsupportedProtocolFeature { - protocol_feature: "NonrefundableStorage".to_string(), - version: ProtocolFeature::NonrefundableStorage.protocol_version() - } - )) - ); - } -} diff --git a/integration-tests/src/tests/client/features/stateless_validation.rs b/integration-tests/src/tests/client/features/stateless_validation.rs index 07a024f5f06..7f90b4723cb 100644 --- a/integration-tests/src/tests/client/features/stateless_validation.rs +++ b/integration-tests/src/tests/client/features/stateless_validation.rs @@ -110,14 +110,7 @@ fn run_chunk_validation_test( let staked = if i < num_validators { validator_stake } else { 0 }; records.push(StateRecord::Account { account_id: account.clone(), - account: Account::new( - initial_balance, - staked, - 0, - CryptoHash::default(), - 0, - genesis_protocol_version, - ), + account: Account::new(initial_balance, staked, CryptoHash::default(), 0), }); records.push(StateRecord::AccessKey { account_id: account.clone(), diff --git a/integration-tests/src/tests/runtime/state_viewer.rs b/integration-tests/src/tests/runtime/state_viewer.rs index 7984cfe0841..85472b5dba6 100644 --- a/integration-tests/src/tests/runtime/state_viewer.rs +++ b/integration-tests/src/tests/runtime/state_viewer.rs @@ -363,7 +363,7 @@ fn test_view_state_too_large() { set_account( &mut state_update, alice_account(), - &Account::new(0, 0, 0, CryptoHash::default(), 50_001, PROTOCOL_VERSION), + &Account::new(0, 0, CryptoHash::default(), 50_001), ); let trie_viewer = TrieViewer::new(Some(50_000), None); let result = trie_viewer.view_state(&state_update, &alice_account(), b"", false); @@ -378,7 +378,7 @@ fn test_view_state_with_large_contract() { set_account( &mut state_update, alice_account(), - &Account::new(0, 0, 0, sha256(&contract_code), 50_001, PROTOCOL_VERSION), + &Account::new(0, 0, sha256(&contract_code), 50_001), ); state_update.set(TrieKey::ContractCode { account_id: alice_account() }, contract_code); let trie_viewer = TrieViewer::new(Some(50_000), None); diff --git a/nearcore/Cargo.toml b/nearcore/Cargo.toml index 931f63bdd7f..a10bc0d504d 100644 --- a/nearcore/Cargo.toml +++ b/nearcore/Cargo.toml @@ -110,9 +110,6 @@ json_rpc = ["near-jsonrpc", "near-jsonrpc-primitives"] protocol_feature_fix_contract_loading_cost = [ "near-vm-runner/protocol_feature_fix_contract_loading_cost", ] -protocol_feature_nonrefundable_transfer_nep491 = [ - "near-primitives/protocol_feature_nonrefundable_transfer_nep491", -] nightly = [ "near-actix-test-utils/nightly", @@ -139,7 +136,6 @@ nightly = [ "nightly_protocol", "node-runtime/nightly", "protocol_feature_fix_contract_loading_cost", - "protocol_feature_nonrefundable_transfer_nep491", "testlib/nightly", ] nightly_protocol = [ diff --git a/neard/Cargo.toml b/neard/Cargo.toml index ee501594bac..ae1ef6c1c70 100644 --- a/neard/Cargo.toml +++ b/neard/Cargo.toml @@ -70,7 +70,6 @@ test_features = ["nearcore/test_features"] expensive_tests = ["nearcore/expensive_tests"] rosetta_rpc = ["nearcore/rosetta_rpc"] json_rpc = ["nearcore/json_rpc"] -protocol_feature_nonrefundable_transfer_nep491 = ["near-state-viewer/protocol_feature_nonrefundable_transfer_nep491"] nightly = [ "near-chain-configs/nightly", @@ -90,7 +89,6 @@ nightly = [ "near-undo-block/nightly", "nearcore/nightly", "nightly_protocol", - "protocol_feature_nonrefundable_transfer_nep491", ] nightly_protocol = [ "near-chain-configs/nightly_protocol", diff --git a/runtime/runtime/Cargo.toml b/runtime/runtime/Cargo.toml index 91aa6aadb1a..0dc80d01b83 100644 --- a/runtime/runtime/Cargo.toml +++ b/runtime/runtime/Cargo.toml @@ -47,7 +47,6 @@ nightly = [ "near-vm-runner/nightly", "near-wallet-contract/nightly", "nightly_protocol", - "protocol_feature_nonrefundable_transfer_nep491", "testlib/nightly", ] nightly_protocol = [ @@ -61,7 +60,6 @@ nightly_protocol = [ "near-wallet-contract/nightly_protocol", "testlib/nightly_protocol", ] -protocol_feature_nonrefundable_transfer_nep491 = [] no_cpu_compatibility_checks = ["near-vm-runner/no_cpu_compatibility_checks"] sandbox = ["near-o11y/sandbox", "near-vm-runner/sandbox"] test_features = [ diff --git a/runtime/runtime/src/actions.rs b/runtime/runtime/src/actions.rs index c21cad8ab16..08e205b077f 100644 --- a/runtime/runtime/src/actions.rs +++ b/runtime/runtime/src/actions.rs @@ -439,25 +439,6 @@ pub(crate) fn action_transfer(account: &mut Account, deposit: Balance) -> Result Ok(()) } -#[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] -pub(crate) fn action_nonrefundable_storage_transfer( - account: &mut Account, - deposit: Balance, - storage_amount_per_byte: Balance, -) -> Result<(), StorageError> { - let permanent_storage_bytes = (deposit / storage_amount_per_byte) as StorageUsage; - account.set_permanent_storage_bytes( - account.permanent_storage_bytes().checked_add(permanent_storage_bytes).ok_or_else( - || { - StorageError::StorageInconsistentState( - "permanent_storage_bytes integer overflow".to_string(), - ) - }, - )?, - ); - Ok(()) -} - pub(crate) fn action_create_account( fee_config: &RuntimeFeesConfig, account_creation_config: &AccountCreationConfig, @@ -466,7 +447,6 @@ pub(crate) fn action_create_account( account_id: &AccountId, predecessor_id: &AccountId, result: &mut ActionResult, - protocol_version: ProtocolVersion, ) { if account_id.is_top_level() { if account_id.len() < account_creation_config.min_allowed_top_level_account_length as usize @@ -497,12 +477,10 @@ pub(crate) fn action_create_account( *actor_id = account_id.clone(); *account = Some(Account::new( - 0, 0, 0, CryptoHash::default(), fee_config.storage_usage_config.num_bytes_account, - protocol_version, )); } @@ -517,19 +495,9 @@ pub(crate) fn action_implicit_account_creation_transfer( deposit: Balance, block_height: BlockHeight, current_protocol_version: ProtocolVersion, - nonrefundable_storage_transfer: bool, epoch_info_provider: &dyn EpochInfoProvider, ) { *actor_id = account_id.clone(); - - let (amount, permanent_storage_bytes) = if nonrefundable_storage_transfer { - let permanent_storage_bytes = - (deposit / apply_state.config.storage_amount_per_byte()) as StorageUsage; - (0, permanent_storage_bytes) - } else { - (deposit, 0) - }; - match account_id.get_account_type() { AccountType::NearImplicitAccount => { let mut access_key = AccessKey::full_access(); @@ -548,15 +516,13 @@ pub(crate) fn action_implicit_account_creation_transfer( let public_key = PublicKey::from_near_implicit_account(account_id).unwrap(); *account = Some(Account::new( - amount, + deposit, 0, - permanent_storage_bytes, CryptoHash::default(), fee_config.storage_usage_config.num_bytes_account + public_key.len() as u64 + borsh::object_length(&access_key).unwrap() as u64 + fee_config.storage_usage_config.num_extra_bytes_record, - current_protocol_version, )); set_access_key(state_update, account_id.clone(), public_key, &access_key); @@ -577,14 +543,7 @@ pub(crate) fn action_implicit_account_creation_transfer( + fee_config.storage_usage_config.num_extra_bytes_record; let contract_hash = *magic_bytes.hash(); - *account = Some(Account::new( - amount, - 0, - permanent_storage_bytes, - contract_hash, - storage_usage, - current_protocol_version, - )); + *account = Some(Account::new(deposit, 0, contract_hash, storage_usage)); state_update.set_code(account_id.clone(), &magic_bytes); // Precompile Wallet Contract and store result (compiled code or error) in the database. @@ -1078,8 +1037,6 @@ pub(crate) fn check_actor_permissions( } Action::CreateAccount(_) | Action::FunctionCall(_) | Action::Transfer(_) => (), Action::Delegate(_) => (), - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - Action::NonrefundableStorageTransfer(_) => (), }; Ok(()) } @@ -1090,11 +1047,6 @@ pub(crate) fn check_account_existence( account_id: &AccountId, config: &RuntimeConfig, implicit_account_creation_eligible: bool, - #[cfg_attr( - not(feature = "protocol_feature_nonrefundable_transfer_nep491"), - allow(unused_variables) - )] - receipt_starts_with_create_account: bool, ) -> Result<(), ActionError> { match action { Action::CreateAccount(_) => { @@ -1133,30 +1085,6 @@ pub(crate) fn check_account_existence( ); } } - // TODO(nonrefundable) Merge with arm above on stabilization. - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - Action::NonrefundableStorageTransfer(_) => { - if account.is_none() { - return check_transfer_to_nonexisting_account( - config, - account_id, - implicit_account_creation_eligible, - ); - } else if !receipt_starts_with_create_account { - // If the account already existed before the current receipt, - // non-refundable transfer is not allowed. But for named - // accounts, it could be that the account was created in this - // receipt which is allowed. Checking for the first action of - // the receipt being a `CreateAccount` action serves this - // purpose. - // For implicit accounts creation with non-refundable storage - // we require that this is the only action in the receipt. - return Err(ActionErrorKind::NonRefundableTransferToExistingAccount { - account_id: account_id.clone(), - } - .into()); - } - } Action::DeployContract(_) | Action::FunctionCall(_) | Action::Stake(_) @@ -1231,7 +1159,6 @@ mod tests { use near_primitives::runtime::migration_data::MigrationFlags; use near_primitives::transaction::CreateAccountAction; use near_primitives::types::{EpochId, StateChangeCause}; - use near_primitives_core::version::PROTOCOL_VERSION; use near_store::set_account; use near_store::test_utils::TestTriesBuilder; use std::sync::Arc; @@ -1255,7 +1182,6 @@ mod tests { &account_id, &predecessor_id, &mut action_result, - PROTOCOL_VERSION, ); if action_result.result.is_ok() { assert!(account.is_some()); @@ -1341,8 +1267,7 @@ mod tests { storage_usage: u64, state_update: &mut TrieUpdate, ) -> ActionResult { - let mut account = - Some(Account::new(100, 0, 0, *code_hash, storage_usage, PROTOCOL_VERSION)); + let mut account = Some(Account::new(100, 0, *code_hash, storage_usage)); let mut actor_id = account_id.clone(); let mut action_result = ActionResult::default(); let receipt = Receipt::new_balance_refund( @@ -1392,8 +1317,7 @@ mod tests { tries.new_trie_update(ShardUId::single_shard(), CryptoHash::default()); let account_id = "alice".parse::().unwrap(); let deploy_action = DeployContractAction { code: [0; 10_000].to_vec() }; - let mut account = - Account::new(100, 0, 0, CryptoHash::default(), storage_usage, PROTOCOL_VERSION); + let mut account = Account::new(100, 0, CryptoHash::default(), storage_usage); let apply_state = create_apply_state(0); let res = action_deploy_contract( &mut state_update, @@ -1503,7 +1427,7 @@ mod tests { let tries = TestTriesBuilder::new().build(); let mut state_update = tries.new_trie_update(ShardUId::single_shard(), CryptoHash::default()); - let account = Account::new(100, 0, 0, CryptoHash::default(), 100, PROTOCOL_VERSION); + let account = Account::new(100, 0, CryptoHash::default(), 100); set_account(&mut state_update, account_id.clone(), &account); set_access_key(&mut state_update, account_id.clone(), public_key.clone(), access_key); @@ -1659,7 +1583,6 @@ mod tests { &sender_id, &RuntimeConfig::test(), false, - false, ), Err(ActionErrorKind::AccountDoesNotExist { account_id: sender_id.clone() }.into()) ); diff --git a/runtime/runtime/src/config.rs b/runtime/runtime/src/config.rs index 11cbf568a14..afe238ae732 100644 --- a/runtime/runtime/src/config.rs +++ b/runtime/runtime/src/config.rs @@ -104,19 +104,6 @@ pub fn total_send_fees( receiver_id.get_account_type(), ) } - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - // TODO(nonrefundable) Before stabilizing, consider using separate gas cost parameters - // for non-refundable and regular transfers. - NonrefundableStorageTransfer(_) => { - // Account for implicit account creation - transfer_send_fee( - fees, - sender_is_receiver, - config.wasm_config.implicit_account_creation, - config.wasm_config.eth_implicit_accounts, - receiver_id.get_account_type(), - ) - } Stake(_) => fees.fee(ActionCosts::stake).send_fee(sender_is_receiver), AddKey(add_key_action) => match &add_key_action.access_key.permission { AccessKeyPermission::FunctionCall(call_perm) => { @@ -216,16 +203,6 @@ pub fn exec_fee(config: &RuntimeConfig, action: &Action, receiver_id: &AccountId receiver_id.get_account_type(), ) } - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - NonrefundableStorageTransfer(_) => { - // Account for implicit account creation - transfer_exec_fee( - fees, - config.wasm_config.implicit_account_creation, - config.wasm_config.eth_implicit_accounts, - receiver_id.get_account_type(), - ) - } Stake(_) => fees.fee(ActionCosts::stake).exec_fee(), AddKey(add_key_action) => match &add_key_action.access_key.permission { AccessKeyPermission::FunctionCall(call_perm) => { diff --git a/runtime/runtime/src/lib.rs b/runtime/runtime/src/lib.rs index debb8bc8e29..c51e953e195 100644 --- a/runtime/runtime/src/lib.rs +++ b/runtime/runtime/src/lib.rs @@ -36,8 +36,6 @@ use near_primitives::runtime::migration_data::{MigrationData, MigrationFlags}; use near_primitives::sandbox::state_patch::SandboxStatePatch; use near_primitives::state_record::StateRecord; use near_primitives::stateless_validation::contract_distribution::ContractUpdates; -#[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] -use near_primitives::transaction::NonrefundableStorageTransferAction; use near_primitives::transaction::{ Action, ExecutionMetadata, ExecutionOutcome, ExecutionOutcomeWithId, ExecutionStatus, LogEntry, SignedTransaction, TransferAction, @@ -440,8 +438,6 @@ impl Runtime { let is_the_only_action = actions.len() == 1; let implicit_account_creation_eligible = is_the_only_action && !is_refund; - let receipt_starts_with_create_account = - matches!(actions.get(0), Some(Action::CreateAccount(_))); // Account validation if let Err(e) = check_account_existence( action, @@ -449,7 +445,6 @@ impl Runtime { account_id, &apply_state.config, implicit_account_creation_eligible, - receipt_starts_with_create_account, ) { result.result = Err(e); return Ok(result); @@ -470,7 +465,6 @@ impl Runtime { receipt.receiver_id(), receipt.predecessor_id(), &mut result, - apply_state.current_protocol_version, ); } Action::DeployContract(deploy_contract) => { @@ -522,24 +516,6 @@ impl Runtime { action_transfer_or_implicit_account_creation( account, *deposit, - false, - is_refund, - action_receipt, - receipt, - state_update, - apply_state, - actor_id, - epoch_info_provider, - )?; - } - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - Action::NonrefundableStorageTransfer(NonrefundableStorageTransferAction { - deposit, - }) => { - action_transfer_or_implicit_account_creation( - account, - *deposit, - true, is_refund, action_receipt, receipt, @@ -667,8 +643,6 @@ impl Runtime { result.gas_burnt = exec_fees; // TODO(#8806): Support compute costs for actions. For now they match burnt gas. result.compute_usage = exec_fees; - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - let mut nonrefundable_amount_burnt: Balance = 0; // Executing actions one by one for (action_index, action) in action_receipt.actions.iter().enumerate() { @@ -713,14 +687,6 @@ impl Runtime { res.index = Some(action_index as u64); break; } - - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - if let Action::NonrefundableStorageTransfer(NonrefundableStorageTransferAction { - deposit, - }) = action - { - nonrefundable_amount_burnt = safe_add_balance(nonrefundable_amount_burnt, *deposit)? - } } // Going to check balance covers account's storage. @@ -803,13 +769,6 @@ impl Runtime { state_update.rollback(); } }; - // If the receipt was successfully applied, we update `other_burnt_amount` statistic with the non-refundable amount burnt. - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - if result.result.is_ok() { - stats.other_burnt_amount = - safe_add_balance(stats.other_burnt_amount, nonrefundable_amount_burnt)?; - } - // If the receipt is a refund, then we consider it free without burnt gas. let gas_burnt: Gas = if receipt.predecessor_id().is_system() { 0 } else { result.gas_burnt }; @@ -2288,7 +2247,6 @@ impl ApplyState { fn action_transfer_or_implicit_account_creation( account: &mut Option, deposit: u128, - nonrefundable: bool, is_refund: bool, action_receipt: &ActionReceipt, receipt: &Receipt, @@ -2298,17 +2256,7 @@ fn action_transfer_or_implicit_account_creation( epoch_info_provider: &dyn EpochInfoProvider, ) -> Result<(), RuntimeError> { Ok(if let Some(account) = account.as_mut() { - if nonrefundable { - assert!(cfg!(feature = "protocol_feature_nonrefundable_transfer_nep491")); - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - action_nonrefundable_storage_transfer( - account, - deposit, - apply_state.config.storage_amount_per_byte(), - )?; - } else { - action_transfer(account, deposit)?; - } + action_transfer(account, deposit)?; // Check if this is a gas refund, then try to refund the access key allowance. if is_refund && &action_receipt.signer_id == receipt.receiver_id() { try_refund_allowance( @@ -2332,7 +2280,6 @@ fn action_transfer_or_implicit_account_creation( deposit, apply_state.block_height, apply_state.current_protocol_version, - nonrefundable, epoch_info_provider, ); }) diff --git a/runtime/runtime/src/pipelining.rs b/runtime/runtime/src/pipelining.rs index 0f2cb2d5f73..80a17521581 100644 --- a/runtime/runtime/src/pipelining.rs +++ b/runtime/runtime/src/pipelining.rs @@ -191,8 +191,6 @@ impl ReceiptPreparationPipeline { | Action::DeleteKey(_) | Action::DeleteAccount(_) | Action::DeployGlobalContract(_) => {} - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - Action::NonrefundableStorageTransfer(_) => {} } } return any_function_calls; diff --git a/runtime/runtime/src/verifier.rs b/runtime/runtime/src/verifier.rs index 1e19ff54985..0901320e1fa 100644 --- a/runtime/runtime/src/verifier.rs +++ b/runtime/runtime/src/verifier.rs @@ -45,12 +45,7 @@ pub fn check_storage_stake( runtime_config: &RuntimeConfig, current_protocol_version: ProtocolVersion, ) -> Result<(), StorageStakingError> { - #[cfg(not(feature = "protocol_feature_nonrefundable_transfer_nep491"))] let billable_storage_bytes = account.storage_usage(); - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - let billable_storage_bytes = - account.storage_usage().saturating_sub(account.permanent_storage_bytes()); - let required_amount = Balance::from(billable_storage_bytes) .checked_mul(runtime_config.storage_amount_per_byte()) .ok_or_else(|| { @@ -442,10 +437,6 @@ pub fn validate_action( } Action::FunctionCall(a) => validate_function_call_action(limit_config, a), Action::Transfer(_) => Ok(()), - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - Action::NonrefundableStorageTransfer(_) => { - check_feature_enabled(ProtocolFeature::NonrefundableStorage, current_protocol_version) - } Action::Stake(a) => validate_stake_action(a), Action::AddKey(a) => validate_add_key_action(limit_config, a), Action::DeleteKey(_) => Ok(()), @@ -600,21 +591,6 @@ fn validate_delete_action(action: &DeleteAccountAction) -> Result<(), ActionsVal Ok(()) } -#[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] -fn check_feature_enabled( - feature: ProtocolFeature, - current_protocol_version: ProtocolVersion, -) -> Result<(), ActionsValidationError> { - if feature.protocol_version() <= current_protocol_version { - Ok(()) - } else { - Err(ActionsValidationError::UnsupportedProtocolFeature { - protocol_feature: format!("{feature:?}"), - version: feature.protocol_version(), - }) - } -} - fn truncate_string(s: &str, limit: usize) -> String { for i in (0..=limit).rev() { if let Some(s) = s.get(..i) { diff --git a/runtime/runtime/tests/runtime_group_tools/mod.rs b/runtime/runtime/tests/runtime_group_tools/mod.rs index 7bfdfc4d3af..b5056dd6683 100644 --- a/runtime/runtime/tests/runtime_group_tools/mod.rs +++ b/runtime/runtime/tests/runtime_group_tools/mod.rs @@ -267,14 +267,7 @@ impl RuntimeGroup { if (i as u64) < num_existing_accounts { state_records.push(StateRecord::Account { account_id: account_id.clone(), - account: Account::new( - TESTING_INIT_BALANCE, - TESTING_INIT_STAKE, - 0, - code_hash, - 0, - PROTOCOL_VERSION, - ), + account: Account::new(TESTING_INIT_BALANCE, TESTING_INIT_STAKE, code_hash, 0), }); state_records.push(StateRecord::AccessKey { account_id: account_id.clone(), diff --git a/test-utils/testlib/src/runtime_utils.rs b/test-utils/testlib/src/runtime_utils.rs index 7dcc5153d2f..eafbf8396be 100644 --- a/test-utils/testlib/src/runtime_utils.rs +++ b/test-utils/testlib/src/runtime_utils.rs @@ -4,7 +4,6 @@ use near_primitives::account::{AccessKey, Account}; use near_primitives::hash::hash; use near_primitives::state_record::StateRecord; use near_primitives::types::{AccountId, Balance}; -use near_primitives::version::PROTOCOL_VERSION; pub fn alice_account() -> AccountId { "alice.near".parse().unwrap() @@ -47,7 +46,7 @@ pub fn add_contract(genesis: &mut Genesis, account_id: &AccountId, code: Vec if !is_account_record_found { records.push(StateRecord::Account { account_id: account_id.clone(), - account: Account::new(0, 0, 0, hash, 0, PROTOCOL_VERSION), + account: Account::new(0, 0, hash, 0), }); } records.push(StateRecord::Contract { account_id: account_id.clone(), code }); @@ -64,7 +63,7 @@ pub fn add_account_with_access_key( let records = genesis.force_read_records().as_mut(); records.push(StateRecord::Account { account_id: account_id.clone(), - account: Account::new(balance, 0, 0, Default::default(), 0, PROTOCOL_VERSION), + account: Account::new(balance, 0, Default::default(), 0), }); records.push(StateRecord::AccessKey { account_id, public_key, access_key }); } diff --git a/tools/amend-genesis/src/lib.rs b/tools/amend-genesis/src/lib.rs index c5b9a8b04ce..8909bfce517 100644 --- a/tools/amend-genesis/src/lib.rs +++ b/tools/amend-genesis/src/lib.rs @@ -5,12 +5,11 @@ use near_crypto::PublicKey; use near_primitives::hash::CryptoHash; use near_primitives::shard_layout::ShardLayout; use near_primitives::state_record::StateRecord; -use near_primitives::types::{AccountId, AccountInfo, StorageUsage}; +use near_primitives::types::{AccountId, AccountInfo}; use near_primitives::utils; use near_primitives::version::ProtocolVersion; use near_primitives_core::account::{AccessKey, Account}; use near_primitives_core::types::{Balance, BlockHeightDelta, NumBlocks, NumSeats, NumShards}; -use near_primitives_core::version::PROTOCOL_VERSION; use num_rational::Rational32; use serde::ser::{SerializeSeq, Serializer}; use std::collections::{hash_map, HashMap}; @@ -48,40 +47,22 @@ fn set_total_balance(dst: &mut Account, src: &Account) { } impl AccountRecords { - fn new( - amount: Balance, - locked: Balance, - permanent_storage_bytes: StorageUsage, - num_bytes_account: u64, - ) -> Self { + fn new(amount: Balance, locked: Balance, num_bytes_account: u64) -> Self { let mut ret = Self::default(); - ret.set_account(amount, locked, permanent_storage_bytes, num_bytes_account); + ret.set_account(amount, locked, num_bytes_account); ret } fn new_validator(stake: Balance, num_bytes_account: u64) -> Self { let mut ret = Self::default(); - ret.set_account(0, stake, 0, num_bytes_account); + ret.set_account(0, stake, num_bytes_account); ret.amount_needed = true; ret } - fn set_account( - &mut self, - amount: Balance, - locked: Balance, - permanent_storage_bytes: StorageUsage, - num_bytes_account: u64, - ) { + fn set_account(&mut self, amount: Balance, locked: Balance, num_bytes_account: u64) { assert!(self.account.is_none()); - let account = Account::new( - amount, - locked, - permanent_storage_bytes, - CryptoHash::default(), - num_bytes_account, - PROTOCOL_VERSION, - ); + let account = Account::new(amount, locked, CryptoHash::default(), num_bytes_account); self.account = Some(account); } @@ -200,7 +181,6 @@ fn parse_extra_records( let r = AccountRecords::new( account.amount(), account.locked(), - account.permanent_storage_bytes(), num_bytes_account, ); e.insert(r); @@ -214,12 +194,7 @@ fn parse_extra_records( &account_id )); } - r.set_account( - account.amount(), - account.locked(), - account.permanent_storage_bytes(), - num_bytes_account, - ); + r.set_account(account.amount(), account.locked(), num_bytes_account); } } } @@ -483,16 +458,8 @@ mod test { fn parse(&self) -> StateRecord { match &self { Self::Account { account_id, amount, locked, storage_usage } => { - // `permanent_storage_bytes` can be implemented if this is required in state records. - let permanent_storage_bytes = 0; - let account = Account::new( - *amount, - *locked, - permanent_storage_bytes, - CryptoHash::default(), - *storage_usage, - PROTOCOL_VERSION, - ); + let account = + Account::new(*amount, *locked, CryptoHash::default(), *storage_usage); StateRecord::Account { account_id: account_id.parse().unwrap(), account } } Self::AccessKey { account_id, public_key } => StateRecord::AccessKey { diff --git a/tools/fork-network/src/cli.rs b/tools/fork-network/src/cli.rs index 9fdc107da9c..cc7139f8a5b 100644 --- a/tools/fork-network/src/cli.rs +++ b/tools/fork-network/src/cli.rs @@ -852,10 +852,8 @@ impl ForkNetworkCommand { Account::new( liquid_balance, validator_account.amount, - 0, CryptoHash::default(), storage_bytes, - PROTOCOL_VERSION, ), )?; storage_mutator.set_access_key( diff --git a/tools/state-viewer/Cargo.toml b/tools/state-viewer/Cargo.toml index 58b76941ed3..56831237d08 100644 --- a/tools/state-viewer/Cargo.toml +++ b/tools/state-viewer/Cargo.toml @@ -64,9 +64,6 @@ sandbox = [ "near-o11y/sandbox", "node-runtime/sandbox", ] -protocol_feature_nonrefundable_transfer_nep491 = [ - "near-primitives/protocol_feature_nonrefundable_transfer_nep491", -] nightly = [ "near-chain-configs/nightly", @@ -82,7 +79,6 @@ nightly = [ "nearcore/nightly", "nightly_protocol", "node-runtime/nightly", - "protocol_feature_nonrefundable_transfer_nep491", "testlib/nightly", ] nightly_protocol = [ diff --git a/tools/state-viewer/src/contract_accounts.rs b/tools/state-viewer/src/contract_accounts.rs index 3f55a18170e..165e9c5ca8a 100644 --- a/tools/state-viewer/src/contract_accounts.rs +++ b/tools/state-viewer/src/contract_accounts.rs @@ -128,8 +128,6 @@ pub(crate) enum ActionType { DeployContract, FunctionCall, Transfer, - #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] - NonrefundableStorageTransfer, Stake, AddKey, DeleteKey, @@ -339,12 +337,6 @@ fn try_find_actions_spawned_by_receipt( Action::DeployContract(_) => ActionType::DeployContract, Action::FunctionCall(_) => ActionType::FunctionCall, Action::Transfer(_) => ActionType::Transfer, - #[cfg( - feature = "protocol_feature_nonrefundable_transfer_nep491" - )] - Action::NonrefundableStorageTransfer(_) => { - ActionType::NonrefundableStorageTransfer - } Action::Stake(_) => ActionType::Stake, Action::AddKey(_) => ActionType::AddKey, Action::DeleteKey(_) => ActionType::DeleteKey, From 2dc5fda30ed21ce840c80c505b2b55ebccf3a233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Chuda=C5=9B?= Date: Tue, 28 Jan 2025 13:54:39 +0000 Subject: [PATCH 2/4] nit --- runtime/runtime/src/balance_checker.rs | 4 +--- test-utils/testlib/src/fees_utils.rs | 6 ------ 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/runtime/runtime/src/balance_checker.rs b/runtime/runtime/src/balance_checker.rs index aeec8117a1a..5202cca85d6 100644 --- a/runtime/runtime/src/balance_checker.rs +++ b/runtime/runtime/src/balance_checker.rs @@ -607,7 +607,6 @@ mod tests { let mut initial_state = tries.new_trie_update(ShardUId::single_shard(), root); // We use `u128::MAX - 1`, because `u128::MAX` is used as a sentinel value for accounts version 2 or higher. - // See NEP-491 for more details: https://github.com/near/NEPs/pull/491. let alice = account_new(u128::MAX - 1, hash(&[])); let bob = account_new(2u128, hash(&[])); @@ -636,8 +635,7 @@ mod tests { } /// This tests shows what would happen if the total balance becomes u128::MAX - /// which is also the sentinel value use to distinguish between accounts version 1 and 2 or higher - /// See NEP-491 for more details: https://github.com/near/NEPs/pull/491. + /// which is also the sentinel value use to distinguish between accounts version 1 and 2 or higher. #[test] fn test_total_balance_u128_max() { let tries = TestTriesBuilder::new().build(); diff --git a/test-utils/testlib/src/fees_utils.rs b/test-utils/testlib/src/fees_utils.rs index 65a434a68fd..ab5e9bd626b 100644 --- a/test-utils/testlib/src/fees_utils.rs +++ b/test-utils/testlib/src/fees_utils.rs @@ -34,12 +34,6 @@ impl FeeHelper { self.gas_to_balance(gas_reward) } - pub fn new_action_receipt_cost(&self) -> Balance { - let exec_gas = self.cfg().fee(ActionCosts::new_action_receipt).exec_fee(); - let send_gas = self.cfg().fee(ActionCosts::new_action_receipt).send_fee(false); - self.gas_to_balance(exec_gas + send_gas) - } - pub fn create_account_cost(&self) -> Balance { let exec_gas = self.cfg().fee(ActionCosts::new_action_receipt).exec_fee() + self.cfg().fee(ActionCosts::create_account).exec_fee(); From 9774cc03091435c49ad2458371014213ab5a98ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Chuda=C5=9B?= Date: Thu, 30 Jan 2025 10:26:44 +0000 Subject: [PATCH 3/4] restore deadth code --- core/primitives-core/src/account.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/core/primitives-core/src/account.rs b/core/primitives-core/src/account.rs index 1b668d62c52..045113427da 100644 --- a/core/primitives-core/src/account.rs +++ b/core/primitives-core/src/account.rs @@ -61,6 +61,18 @@ pub struct AccountV1 { storage_usage: StorageUsage, } +#[allow(dead_code)] +impl AccountV1 { + fn to_v2(&self) -> AccountV2 { + AccountV2 { + amount: self.amount, + locked: self.locked, + code_hash: self.code_hash, + storage_usage: self.storage_usage, + } + } +} + // TODO(global-contract): add new field #[derive( BorshSerialize, From 9ef6c3d91e389e7020e0f82d171caa883364b97b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Chuda=C5=9B?= Date: Thu, 30 Jan 2025 12:12:04 +0000 Subject: [PATCH 4/4] schema check --- .../res/protocol_schema.toml | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tools/protocol-schema-check/res/protocol_schema.toml b/tools/protocol-schema-check/res/protocol_schema.toml index c01b93be816..2a0471983a9 100644 --- a/tools/protocol-schema-check/res/protocol_schema.toml +++ b/tools/protocol-schema-check/res/protocol_schema.toml @@ -1,13 +1,13 @@ AccessKey = 433079403 AccessKeyPermission = 885623561 -Account = 4069344376 +Account = 1842241023 AccountV1 = 3570440720 -AccountV2 = 1741861562 +AccountV2 = 337859929 AccountVersion = 3672019478 Action = 708080604 ActionCosts = 3115555891 -ActionError = 4217425219 -ActionErrorKind = 1632922469 +ActionError = 3315176969 +ActionErrorKind = 853762542 ActionReceipt = 882261823 ActionsValidationError = 1053886215 AddKeyAction = 356099649 @@ -128,11 +128,11 @@ EpochSyncProofLastEpochData = 2620439209 EpochSyncProofV1 = 3403222461 EpochValidatorInfo = 1082066685 ExecutionMetadata = 3853243413 -ExecutionOutcome = 2925419955 -ExecutionOutcomeWithId = 1289816961 -ExecutionOutcomeWithIdAndProof = 3179626578 -ExecutionOutcomeWithProof = 2219338929 -ExecutionStatus = 3681865123 +ExecutionOutcome = 1389616391 +ExecutionOutcomeWithId = 3435887297 +ExecutionOutcomeWithIdAndProof = 3467933830 +ExecutionOutcomeWithProof = 3452427190 +ExecutionStatus = 1674342960 ExtCosts = 1172935704 FetchingStateStatus = 2204896805 FlatStateChanges = 2811133731 @@ -225,8 +225,8 @@ RoutedMessageBody = 2711205418 RoutingTableUpdate = 2987752645 Secp256K1PublicKey = 4117078281 Secp256K1Signature = 3687154735 -SerdeAccount = 399208377 -ServerError = 2338793369 +SerdeAccount = 4024521980 +ServerError = 3111148975 ShardChunk = 1084327441 ShardChunkHeader = 2471921769 ShardChunkHeaderInner = 4085026561 @@ -286,7 +286,7 @@ TrieKey = 544589632 TrieQueueIndices = 2601394796 TrieRefcountAddition = 2117109883 TrieRefcountSubtraction = 2150368599 -TxExecutionError = 214948980 +TxExecutionError = 1525511446 UseGlobalContractAction = 4227348133 VMKind = 2110212047 ValidatorKickoutReason = 2362237969