diff --git a/Cargo.lock b/Cargo.lock index 4638987fbe9..10d3ac08d2c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4206,11 +4206,13 @@ dependencies = [ "serde_json", "serde_with", "serde_yaml", + "sha3", "smart-default", "strum", "thiserror", "time", "tracing", + "wat", ] [[package]] diff --git a/core/crypto/src/signature.rs b/core/crypto/src/signature.rs index a9121131423..69176e42db9 100644 --- a/core/crypto/src/signature.rs +++ b/core/crypto/src/signature.rs @@ -156,6 +156,13 @@ impl PublicKey { Self::SECP256K1(_) => panic!(), } } + + pub fn unwrap_as_secp256k1(&self) -> &Secp256K1PublicKey { + match self { + Self::SECP256K1(key) => key, + Self::ED25519(_) => panic!(), + } + } } // This `Hash` implementation is safe since it retains the property diff --git a/core/crypto/src/test_utils.rs b/core/crypto/src/test_utils.rs index 07614c44d79..174b58b23d4 100644 --- a/core/crypto/src/test_utils.rs +++ b/core/crypto/src/test_utils.rs @@ -28,7 +28,10 @@ impl PublicKey { let keypair = ed25519_key_pair_from_seed(seed); PublicKey::ED25519(ED25519PublicKey(keypair.verifying_key().to_bytes())) } - _ => unimplemented!(), + KeyType::SECP256K1 => { + let secret_key = SecretKey::SECP256K1(secp256k1_secret_key_from_seed(seed)); + PublicKey::SECP256K1(secret_key.public_key().unwrap_as_secp256k1().clone()) + } } } } @@ -40,7 +43,7 @@ impl SecretKey { let keypair = ed25519_key_pair_from_seed(seed); SecretKey::ED25519(ED25519SecretKey(keypair.to_keypair_bytes())) } - _ => SecretKey::SECP256K1(secp256k1_secret_key_from_seed(seed)), + KeyType::SECP256K1 => SecretKey::SECP256K1(secp256k1_secret_key_from_seed(seed)), } } } diff --git a/core/primitives-core/src/parameter.rs b/core/primitives-core/src/parameter.rs index dcc35c4a21d..205b3e087e8 100644 --- a/core/primitives-core/src/parameter.rs +++ b/core/primitives-core/src/parameter.rs @@ -157,6 +157,7 @@ pub enum Parameter { AltBn128, FunctionCallWeight, VmKind, + EthImplicitAccounts, } #[derive( diff --git a/core/primitives-core/src/runtime/fees.rs b/core/primitives-core/src/runtime/fees.rs index a2b7bf5acd5..a13865ac891 100644 --- a/core/primitives-core/src/runtime/fees.rs +++ b/core/primitives-core/src/runtime/fees.rs @@ -203,24 +203,30 @@ impl StorageUsageConfig { } /// Helper functions for computing Transfer fees. -/// In case of implicit account creation they always include extra fees for the CreateAccount and +/// In case of implicit account creation they include extra fees for the CreateAccount and /// AddFullAccessKey (for NEAR-implicit account only) actions that are implicit. /// We can assume that no overflow will happen here. pub fn transfer_exec_fee( cfg: &RuntimeFeesConfig, implicit_account_creation_allowed: bool, + eth_implicit_accounts_enabled: bool, receiver_account_type: AccountType, ) -> Gas { let transfer_fee = cfg.fee(ActionCosts::transfer).exec_fee(); - match (implicit_account_creation_allowed, receiver_account_type) { + match (implicit_account_creation_allowed, eth_implicit_accounts_enabled, receiver_account_type) + { // Regular transfer to a named account. - (_, AccountType::NamedAccount) => transfer_fee, + (_, _, AccountType::NamedAccount) => transfer_fee, // No account will be created, just a regular transfer. - (false, _) => transfer_fee, - // Currently, no account is created on transfer to ETH-implicit account, just a regular transfer. - (true, AccountType::EthImplicitAccount) => transfer_fee, + (false, _, _) => transfer_fee, + // No account will be created, just a regular transfer. + (true, false, AccountType::EthImplicitAccount) => transfer_fee, + // Extra fee for the CreateAccount. + (true, true, AccountType::EthImplicitAccount) => { + transfer_fee + cfg.fee(ActionCosts::create_account).exec_fee() + } // Extra fees for the CreateAccount and AddFullAccessKey. - (true, AccountType::NearImplicitAccount) => { + (true, _, AccountType::NearImplicitAccount) => { transfer_fee + cfg.fee(ActionCosts::create_account).exec_fee() + cfg.fee(ActionCosts::add_full_access_key).exec_fee() @@ -232,18 +238,24 @@ pub fn transfer_send_fee( cfg: &RuntimeFeesConfig, sender_is_receiver: bool, implicit_account_creation_allowed: bool, + eth_implicit_accounts_enabled: bool, receiver_account_type: AccountType, ) -> Gas { let transfer_fee = cfg.fee(ActionCosts::transfer).send_fee(sender_is_receiver); - match (implicit_account_creation_allowed, receiver_account_type) { + match (implicit_account_creation_allowed, eth_implicit_accounts_enabled, receiver_account_type) + { // Regular transfer to a named account. - (_, AccountType::NamedAccount) => transfer_fee, + (_, _, AccountType::NamedAccount) => transfer_fee, // No account will be created, just a regular transfer. - (false, _) => transfer_fee, - // Currently, no account is created on transfer to ETH-implicit account, just a regular transfer. - (true, AccountType::EthImplicitAccount) => transfer_fee, + (false, _, _) => transfer_fee, + // No account will be created, just a regular transfer. + (true, false, AccountType::EthImplicitAccount) => transfer_fee, + // Extra fee for the CreateAccount. + (true, true, AccountType::EthImplicitAccount) => { + transfer_fee + cfg.fee(ActionCosts::create_account).send_fee(sender_is_receiver) + } // Extra fees for the CreateAccount and AddFullAccessKey. - (true, AccountType::NearImplicitAccount) => { + (true, _, AccountType::NearImplicitAccount) => { transfer_fee + cfg.fee(ActionCosts::create_account).send_fee(sender_is_receiver) + cfg.fee(ActionCosts::add_full_access_key).send_fee(sender_is_receiver) diff --git a/core/primitives-core/src/version.rs b/core/primitives-core/src/version.rs index 45c57cafd5f..be7bb1e3af5 100644 --- a/core/primitives-core/src/version.rs +++ b/core/primitives-core/src/version.rs @@ -128,6 +128,7 @@ pub enum ProtocolFeature { /// NEP: https://github.com/near/NEPs/pull/509 #[cfg(feature = "protocol_feature_chunk_validation")] ChunkValidation, + EthImplicitAccounts, } impl ProtocolFeature { @@ -183,6 +184,7 @@ impl ProtocolFeature { ProtocolFeature::SimpleNightshadeV2 => 135, #[cfg(feature = "protocol_feature_chunk_validation")] ProtocolFeature::ChunkValidation => 137, + ProtocolFeature::EthImplicitAccounts => 138, } } } diff --git a/core/primitives/Cargo.toml b/core/primitives/Cargo.toml index c56527abde8..b01f62bc353 100644 --- a/core/primitives/Cargo.toml +++ b/core/primitives/Cargo.toml @@ -33,12 +33,14 @@ serde.workspace = true serde_json.workspace = true serde_with.workspace = true serde_yaml.workspace = true +sha3.workspace = true smart-default.workspace = true stdx.workspace = true strum.workspace = true thiserror.workspace = true time.workspace = true tracing.workspace = true +wat.workspace = true near-crypto.workspace = true near-fmt.workspace = true diff --git a/core/primitives/res/runtime_configs/138.yaml b/core/primitives/res/runtime_configs/138.yaml new file mode 100644 index 00000000000..df593820025 --- /dev/null +++ b/core/primitives/res/runtime_configs/138.yaml @@ -0,0 +1 @@ +eth_implicit_accounts: { old: false, new: true } diff --git a/core/primitives/res/runtime_configs/parameters.snap b/core/primitives/res/runtime_configs/parameters.snap index 4a891b4dc7f..564d7a7e67b 100644 --- a/core/primitives/res/runtime_configs/parameters.snap +++ b/core/primitives/res/runtime_configs/parameters.snap @@ -172,4 +172,5 @@ ed25519_verify true alt_bn128 true function_call_weight true vm_kind NearVm +eth_implicit_accounts false diff --git a/core/primitives/res/runtime_configs/parameters.yaml b/core/primitives/res/runtime_configs/parameters.yaml index 64a166a6be4..7e63478bd88 100644 --- a/core/primitives/res/runtime_configs/parameters.yaml +++ b/core/primitives/res/runtime_configs/parameters.yaml @@ -207,3 +207,4 @@ ed25519_verify: false alt_bn128: false function_call_weight: false vm_kind: Wasmer0 +eth_implicit_accounts: false diff --git a/core/primitives/res/runtime_configs/parameters_testnet.yaml b/core/primitives/res/runtime_configs/parameters_testnet.yaml index 86cb7439858..32920158ab8 100644 --- a/core/primitives/res/runtime_configs/parameters_testnet.yaml +++ b/core/primitives/res/runtime_configs/parameters_testnet.yaml @@ -202,3 +202,4 @@ ed25519_verify: false alt_bn128: false function_call_weight: false vm_kind: Wasmer0 +eth_implicit_accounts: false diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index ba42d3c05cb..8b32fbbf8bd 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -486,9 +486,9 @@ pub enum ActionErrorKind { /// Error occurs when a new `ActionReceipt` created by the `FunctionCall` action fails /// receipt validation. NewReceiptValidationError(ReceiptValidationError), - /// Error occurs when a `CreateAccount` action is called on hex-characters - /// account of length 64. See implicit account creation NEP: - /// . + /// Error occurs when a `CreateAccount` action is called on a NEAR-implicit or ETH-implicit account. + /// See NEAR-implicit account creation NEP: . + /// Also, see ETH-implicit account creation NEP: . /// /// TODO(#8598): This error is named very poorly. A better name would be /// `OnlyNamedAccountCreationAllowed`. diff --git a/core/primitives/src/runtime/config_store.rs b/core/primitives/src/runtime/config_store.rs index b8c6e45d053..c31091c4412 100644 --- a/core/primitives/src/runtime/config_store.rs +++ b/core/primitives/src/runtime/config_store.rs @@ -38,6 +38,8 @@ static CONFIG_DIFFS: &[(ProtocolVersion, &str)] = &[ (63, include_config!("63.yaml")), (64, include_config!("64.yaml")), (129, include_config!("129.yaml")), + // Introduce ETH-implicit accounts. + (138, include_config!("138.yaml")), ]; /// Testnet parameters for versions <= 29, which (incorrectly) differed from mainnet parameters diff --git a/core/primitives/src/runtime/parameter_table.rs b/core/primitives/src/runtime/parameter_table.rs index d107badd176..f623e93704e 100644 --- a/core/primitives/src/runtime/parameter_table.rs +++ b/core/primitives/src/runtime/parameter_table.rs @@ -323,6 +323,7 @@ impl TryFrom<&ParameterTable> for RuntimeConfig { ed25519_verify: params.get(Parameter::Ed25519Verify)?, alt_bn128: params.get(Parameter::AltBn128)?, function_call_weight: params.get(Parameter::FunctionCallWeight)?, + eth_implicit_accounts: params.get(Parameter::EthImplicitAccounts)?, }, account_creation_config: AccountCreationConfig { min_allowed_top_level_account_length: params diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__0.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__0.json.snap index 5f5a4b09f38..31b7b727362 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__0.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__0.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": false, "alt_bn128": false, "function_call_weight": false, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 200000000000000, "max_stack_height": 16384, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__129.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__129.json.snap index bf99fcd66ff..5d760413d18 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__129.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__129.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": true, "alt_bn128": true, "function_call_weight": true, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 300000000000000, "max_stack_height": 262144, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__138.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__138.json.snap new file mode 100644 index 00000000000..b998df7b47e --- /dev/null +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__138.json.snap @@ -0,0 +1,218 @@ +--- +source: core/primitives/src/runtime/config_store.rs +expression: config_view +--- +{ + "storage_amount_per_byte": "10000000000000000000", + "transaction_costs": { + "action_receipt_creation_config": { + "send_sir": 108059500000, + "send_not_sir": 108059500000, + "execution": 108059500000 + }, + "data_receipt_creation_config": { + "base_cost": { + "send_sir": 36486732312, + "send_not_sir": 36486732312, + "execution": 36486732312 + }, + "cost_per_byte": { + "send_sir": 17212011, + "send_not_sir": 17212011, + "execution": 17212011 + } + }, + "action_creation_config": { + "create_account_cost": { + "send_sir": 3850000000000, + "send_not_sir": 3850000000000, + "execution": 3850000000000 + }, + "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": 64572944 + }, + "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 + }, + "delegate_cost": { + "send_sir": 200000000000, + "send_not_sir": 200000000000, + "execution": 200000000000 + } + }, + "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, + "ed25519_verify_base": 210000000000, + "ed25519_verify_byte": 9000000, + "ecrecover_base": 278821988457, + "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": 822756, + "vm_kind": "", + "disable_9393_fix": false, + "storage_get_mode": "FlatStorage", + "fix_contract_loading_cost": true, + "implicit_account_creation": true, + "math_extension": true, + "ed25519_verify": true, + "alt_bn128": true, + "function_call_weight": true, + "eth_implicit_accounts": true, + "limit_config": { + "max_gas_burnt": 300000000000000, + "max_stack_height": 262144, + "contract_prepare_version": 2, + "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": 2048, + "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": 1000000, + "account_id_validity_rules_version": 1 + } + }, + "account_creation_config": { + "min_allowed_top_level_account_length": 65, + "registrar_account_id": "registrar" + } +} diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__35.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__35.json.snap index 6132c476a6e..d5c77aa3010 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__35.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__35.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": false, "alt_bn128": false, "function_call_weight": false, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 200000000000000, "max_stack_height": 16384, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__42.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__42.json.snap index 2dc93e90514..fd15774958f 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__42.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__42.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": false, "alt_bn128": false, "function_call_weight": false, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 200000000000000, "max_stack_height": 16384, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__46.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__46.json.snap index 9687f0b7577..ace94190635 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__46.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__46.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": false, "alt_bn128": false, "function_call_weight": false, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 200000000000000, "max_stack_height": 16384, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__48.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__48.json.snap index 27599960fe4..6e77b1dcb42 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__48.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__48.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": false, "alt_bn128": false, "function_call_weight": false, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 200000000000000, "max_stack_height": 16384, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__49.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__49.json.snap index e3aa6a4aa48..d9f9c05c4f0 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__49.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__49.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": false, "alt_bn128": false, "function_call_weight": false, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 200000000000000, "max_stack_height": 16384, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__50.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__50.json.snap index 7c7f08fb7bf..30e3ea3bc08 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__50.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__50.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": false, "alt_bn128": false, "function_call_weight": false, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 200000000000000, "max_stack_height": 16384, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__52.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__52.json.snap index 4a5d601a029..70e87554f13 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__52.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__52.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": false, "alt_bn128": false, "function_call_weight": false, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 300000000000000, "max_stack_height": 16384, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__53.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__53.json.snap index b3241b79e9f..f76fe99f4f3 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__53.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__53.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": false, "alt_bn128": false, "function_call_weight": true, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 300000000000000, "max_stack_height": 16384, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__55.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__55.json.snap index e0a47a72d32..6cfea4bf5c1 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__55.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__55.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": false, "alt_bn128": true, "function_call_weight": true, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 300000000000000, "max_stack_height": 16384, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__57.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__57.json.snap index 6eef7b33564..ef3e4065ede 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__57.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__57.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": false, "alt_bn128": true, "function_call_weight": true, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 300000000000000, "max_stack_height": 16384, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__59.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__59.json.snap index be0582f2170..813372b4564 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__59.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__59.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": true, "alt_bn128": true, "function_call_weight": true, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 300000000000000, "max_stack_height": 16384, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__61.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__61.json.snap index 201276d778b..411a7b88c61 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__61.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__61.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": true, "alt_bn128": true, "function_call_weight": true, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 300000000000000, "max_stack_height": 16384, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__62.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__62.json.snap index 035ebbb2f76..d539911e534 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__62.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__62.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": true, "alt_bn128": true, "function_call_weight": true, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 300000000000000, "max_stack_height": 262144, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__63.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__63.json.snap index 420d0b9b2b2..d0fdf69c63f 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__63.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__63.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": true, "alt_bn128": true, "function_call_weight": true, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 300000000000000, "max_stack_height": 262144, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__64.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__64.json.snap index 49a7c8a045f..4e495a80e8f 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__64.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__64.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": true, "alt_bn128": true, "function_call_weight": true, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 300000000000000, "max_stack_height": 262144, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_0.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_0.json.snap index 5f5a4b09f38..31b7b727362 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_0.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_0.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": false, "alt_bn128": false, "function_call_weight": false, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 200000000000000, "max_stack_height": 16384, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_129.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_129.json.snap index bf99fcd66ff..5d760413d18 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_129.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_129.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": true, "alt_bn128": true, "function_call_weight": true, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 300000000000000, "max_stack_height": 262144, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_138.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_138.json.snap new file mode 100644 index 00000000000..b998df7b47e --- /dev/null +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_138.json.snap @@ -0,0 +1,218 @@ +--- +source: core/primitives/src/runtime/config_store.rs +expression: config_view +--- +{ + "storage_amount_per_byte": "10000000000000000000", + "transaction_costs": { + "action_receipt_creation_config": { + "send_sir": 108059500000, + "send_not_sir": 108059500000, + "execution": 108059500000 + }, + "data_receipt_creation_config": { + "base_cost": { + "send_sir": 36486732312, + "send_not_sir": 36486732312, + "execution": 36486732312 + }, + "cost_per_byte": { + "send_sir": 17212011, + "send_not_sir": 17212011, + "execution": 17212011 + } + }, + "action_creation_config": { + "create_account_cost": { + "send_sir": 3850000000000, + "send_not_sir": 3850000000000, + "execution": 3850000000000 + }, + "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": 64572944 + }, + "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 + }, + "delegate_cost": { + "send_sir": 200000000000, + "send_not_sir": 200000000000, + "execution": 200000000000 + } + }, + "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, + "ed25519_verify_base": 210000000000, + "ed25519_verify_byte": 9000000, + "ecrecover_base": 278821988457, + "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": 822756, + "vm_kind": "", + "disable_9393_fix": false, + "storage_get_mode": "FlatStorage", + "fix_contract_loading_cost": true, + "implicit_account_creation": true, + "math_extension": true, + "ed25519_verify": true, + "alt_bn128": true, + "function_call_weight": true, + "eth_implicit_accounts": true, + "limit_config": { + "max_gas_burnt": 300000000000000, + "max_stack_height": 262144, + "contract_prepare_version": 2, + "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": 2048, + "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": 1000000, + "account_id_validity_rules_version": 1 + } + }, + "account_creation_config": { + "min_allowed_top_level_account_length": 65, + "registrar_account_id": "registrar" + } +} diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_35.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_35.json.snap index 6132c476a6e..d5c77aa3010 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_35.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_35.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": false, "alt_bn128": false, "function_call_weight": false, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 200000000000000, "max_stack_height": 16384, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_42.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_42.json.snap index 2dc93e90514..fd15774958f 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_42.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_42.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": false, "alt_bn128": false, "function_call_weight": false, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 200000000000000, "max_stack_height": 16384, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_46.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_46.json.snap index 9687f0b7577..ace94190635 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_46.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_46.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": false, "alt_bn128": false, "function_call_weight": false, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 200000000000000, "max_stack_height": 16384, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_48.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_48.json.snap index 27599960fe4..6e77b1dcb42 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_48.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_48.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": false, "alt_bn128": false, "function_call_weight": false, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 200000000000000, "max_stack_height": 16384, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_49.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_49.json.snap index e3aa6a4aa48..d9f9c05c4f0 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_49.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_49.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": false, "alt_bn128": false, "function_call_weight": false, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 200000000000000, "max_stack_height": 16384, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_50.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_50.json.snap index 7c7f08fb7bf..30e3ea3bc08 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_50.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_50.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": false, "alt_bn128": false, "function_call_weight": false, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 200000000000000, "max_stack_height": 16384, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_52.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_52.json.snap index 4a5d601a029..70e87554f13 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_52.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_52.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": false, "alt_bn128": false, "function_call_weight": false, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 300000000000000, "max_stack_height": 16384, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_53.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_53.json.snap index b3241b79e9f..f76fe99f4f3 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_53.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_53.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": false, "alt_bn128": false, "function_call_weight": true, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 300000000000000, "max_stack_height": 16384, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_55.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_55.json.snap index e0a47a72d32..6cfea4bf5c1 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_55.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_55.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": false, "alt_bn128": true, "function_call_weight": true, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 300000000000000, "max_stack_height": 16384, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_57.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_57.json.snap index 6eef7b33564..ef3e4065ede 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_57.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_57.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": false, "alt_bn128": true, "function_call_weight": true, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 300000000000000, "max_stack_height": 16384, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_59.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_59.json.snap index be0582f2170..813372b4564 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_59.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_59.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": true, "alt_bn128": true, "function_call_weight": true, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 300000000000000, "max_stack_height": 16384, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_61.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_61.json.snap index 201276d778b..411a7b88c61 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_61.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_61.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": true, "alt_bn128": true, "function_call_weight": true, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 300000000000000, "max_stack_height": 16384, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_62.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_62.json.snap index 035ebbb2f76..d539911e534 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_62.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_62.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": true, "alt_bn128": true, "function_call_weight": true, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 300000000000000, "max_stack_height": 262144, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_63.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_63.json.snap index 420d0b9b2b2..d0fdf69c63f 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_63.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_63.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": true, "alt_bn128": true, "function_call_weight": true, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 300000000000000, "max_stack_height": 262144, diff --git a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_64.json.snap b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_64.json.snap index 49a7c8a045f..4e495a80e8f 100644 --- a/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_64.json.snap +++ b/core/primitives/src/runtime/snapshots/near_primitives__runtime__config_store__tests__testnet_64.json.snap @@ -181,6 +181,7 @@ expression: config_view "ed25519_verify": true, "alt_bn128": true, "function_call_weight": true, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 300000000000000, "max_stack_height": 262144, 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 index ce9564793ac..4fc91b441a4 100644 --- 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 @@ -181,6 +181,7 @@ expression: "&view" "ed25519_verify": true, "alt_bn128": true, "function_call_weight": true, + "eth_implicit_accounts": false, "limit_config": { "max_gas_burnt": 300000000000000, "max_stack_height": 262144, diff --git a/core/primitives/src/test_utils.rs b/core/primitives/src/test_utils.rs index 0aaf94ec599..959eb347e48 100644 --- a/core/primitives/src/test_utils.rs +++ b/core/primitives/src/test_utils.rs @@ -561,6 +561,11 @@ pub fn near_implicit_test_account_secret() -> SecretKey { "ed25519:5roj6k68kvZu3UEJFyXSfjdKGrodgZUfFLZFpzYXWtESNsLWhYrq3JGi4YpqeVKuw1m9R2TEHjfgWT1fjUqB1DNy".parse().unwrap() } +/// A fixed ETH-implicit account. +pub fn eth_implicit_test_account() -> AccountId { + "0x96791e923f8cf697ad9c3290f2c9059f0231b24c".parse().unwrap() +} + impl FinalExecutionOutcomeView { #[track_caller] /// Check transaction and all transitive receipts for success status. diff --git a/core/primitives/src/utils.rs b/core/primitives/src/utils.rs index c98e7dff0fb..b62f0a544b9 100644 --- a/core/primitives/src/utils.rs +++ b/core/primitives/src/utils.rs @@ -17,8 +17,9 @@ use crate::version::{ CREATE_RECEIPT_ID_SWITCH_TO_CURRENT_BLOCK_VERSION, }; -use near_crypto::ED25519PublicKey; -use near_primitives_core::account::id::AccountId; +use near_crypto::{ED25519PublicKey, Secp256K1PublicKey}; +use near_primitives_core::account::id::{AccountId, AccountType}; +use near_vm_runner::ContractCode; use std::mem::size_of; use std::ops::Deref; @@ -470,19 +471,44 @@ where Serializable(object) } -/// Derives `AccountId` from `PublicKey``. -/// If the key type is ED25519, returns hex-encoded copy of the key. +// TODO(eth-implicit) Replace this function (and wat dependency) with a real Wallet Contract implementation. +pub fn wallet_contract_placeholder() -> ContractCode { + let code = wat::parse_str(r#"(module (func (export "main")))"#); + ContractCode::new(code.unwrap().to_vec(), None) +} + +/// From `near-account-id` version `1.0.0-alpha.2`, `is_implicit` returns true for ETH-implicit accounts. +/// This function is a wrapper for `is_implicit` method so that we can easily differentiate its behavior +/// based on whether ETH-implicit accounts are enabled. +pub fn account_is_implicit(account_id: &AccountId, eth_implicit_accounts_enabled: bool) -> bool { + if eth_implicit_accounts_enabled { + account_id.get_account_type().is_implicit() + } else { + account_id.get_account_type() == AccountType::NearImplicitAccount + } +} + +/// Returns hex-encoded copy of the public key. +/// This is a NEAR-implicit account ID which can be controlled by the corresponding ED25519 private key. pub fn derive_near_implicit_account_id(public_key: &ED25519PublicKey) -> AccountId { hex::encode(public_key).parse().unwrap() } +/// Returns '0x' + keccak256(public_key)[12:32].hex(). +/// This is an ETH-implicit account ID which can be controlled by the corresponding Secp256K1 private key. +pub fn derive_eth_implicit_account_id(public_key: &Secp256K1PublicKey) -> AccountId { + use sha3::Digest; + let pk_hash = sha3::Keccak256::digest(&public_key); + format!("0x{}", hex::encode(&pk_hash[12..32])).parse().unwrap() +} + #[cfg(test)] mod tests { use super::*; use near_crypto::{KeyType, PublicKey}; #[test] - fn test_derive_account_id_from_ed25519_public_key() { + fn test_derive_near_implicit_account_id() { let public_key = PublicKey::from_seed(KeyType::ED25519, "test"); let expected: AccountId = "bb4dc639b212e075a751685b26bdcea5920a504181ff2910e8549742127092a0".parse().unwrap(); @@ -490,6 +516,14 @@ mod tests { assert_eq!(account_id, expected); } + #[test] + fn test_derive_eth_implicit_account_id() { + let public_key = PublicKey::from_seed(KeyType::SECP256K1, "test"); + let expected: AccountId = "0x96791e923f8cf697ad9c3290f2c9059f0231b24c".parse().unwrap(); + let account_id = derive_eth_implicit_account_id(public_key.unwrap_as_secp256k1()); + assert_eq!(account_id, expected); + } + #[test] fn test_num_chunk_producers() { for num_seats in 1..50 { diff --git a/core/primitives/src/views.rs b/core/primitives/src/views.rs index 580bed3c3d9..c19bbd94c66 100644 --- a/core/primitives/src/views.rs +++ b/core/primitives/src/views.rs @@ -2561,6 +2561,8 @@ pub struct VMConfigView { pub alt_bn128: bool, /// See [`VMConfig::function_call_weight`]. pub function_call_weight: bool, + /// See [`VMConfig::eth_implicit_accounts`]. + pub eth_implicit_accounts: bool, /// Describes limits for VM and Runtime. /// @@ -2585,6 +2587,7 @@ impl From for VMConfigView { alt_bn128: config.alt_bn128, function_call_weight: config.function_call_weight, vm_kind: config.vm_kind, + eth_implicit_accounts: config.eth_implicit_accounts, } } } @@ -2605,6 +2608,7 @@ impl From for near_vm_runner::logic::Config { alt_bn128: view.alt_bn128, function_call_weight: view.function_call_weight, vm_kind: view.vm_kind, + eth_implicit_accounts: view.eth_implicit_accounts, } } } diff --git a/integration-tests/src/tests/client/features/access_key_nonce_for_implicit_accounts.rs b/integration-tests/src/tests/client/features/access_key_nonce_for_implicit_accounts.rs index bb07c943c2b..6b0f6daaf17 100644 --- a/integration-tests/src/tests/client/features/access_key_nonce_for_implicit_accounts.rs +++ b/integration-tests/src/tests/client/features/access_key_nonce_for_implicit_accounts.rs @@ -12,14 +12,17 @@ use near_network::shards_manager::ShardsManagerRequestFromNetwork; use near_network::types::{NetworkRequests, PeerManagerMessageRequest}; use near_o11y::testonly::init_test_logger; use near_primitives::account::AccessKey; -use near_primitives::errors::InvalidTxError; +use near_primitives::checked_feature; +use near_primitives::errors::{InvalidAccessKeyError, InvalidTxError}; use near_primitives::runtime::config_store::RuntimeConfigStore; use near_primitives::shard_layout::ShardLayout; use near_primitives::sharding::ChunkHash; -use near_primitives::transaction::SignedTransaction; +use near_primitives::transaction::{Action, AddKeyAction, DeployContractAction, SignedTransaction}; use near_primitives::types::{AccountId, BlockHeight}; -use near_primitives::utils::derive_near_implicit_account_id; -use near_primitives::version::{ProtocolFeature, ProtocolVersion}; +use near_primitives::utils::{ + derive_eth_implicit_account_id, derive_near_implicit_account_id, wallet_contract_placeholder, +}; +use near_primitives::version::{ProtocolFeature, ProtocolVersion, PROTOCOL_VERSION}; use near_primitives::views::FinalExecutionStatus; use nearcore::config::GenesisExt; use nearcore::test_utils::TestEnvNightshadeSetupExt; @@ -113,13 +116,13 @@ fn test_transaction_hash_collision() { ); } -/// Helper for checking that duplicate transactions from implicit accounts are properly rejected. -/// It creates implicit account, deletes it and creates again, so that nonce of the access -/// key is updated. Then it tries to send tx from implicit account with invalid nonce, which +/// Helper for checking that duplicate transactions from NEAR-implicit accounts are properly rejected. +/// It creates NEAR-implicit account, deletes it and creates again, so that nonce of the access +/// key is updated. Then it tries to send tx from NEAR-implicit account with invalid nonce, which /// should fail since the protocol upgrade. -fn get_status_of_tx_hash_collision_for_implicit_account( +fn get_status_of_tx_hash_collision_for_near_implicit_account( protocol_version: ProtocolVersion, - implicit_account_signer: InMemorySigner, + near_implicit_account_signer: InMemorySigner, ) -> ProcessTxResponse { let epoch_length = 100; let mut genesis = Genesis::test(vec!["test0".parse().unwrap(), "test1".parse().unwrap()], 1); @@ -134,13 +137,13 @@ fn get_status_of_tx_hash_collision_for_implicit_account( let mut height = 1; let blocks_number = 5; let signer1 = InMemorySigner::from_seed("test1".parse().unwrap(), KeyType::ED25519, "test1"); - let implicit_account_id = implicit_account_signer.account_id.clone(); + let near_implicit_account_id = near_implicit_account_signer.account_id.clone(); - // Send money to implicit account, invoking its creation. + // Send money to NEAR-implicit account, invoking its creation. let send_money_tx = SignedTransaction::send_money( 1, "test1".parse().unwrap(), - implicit_account_id.clone(), + near_implicit_account_id.clone(), &signer1, deposit_for_account_creation, *genesis_block.hash(), @@ -148,24 +151,24 @@ fn get_status_of_tx_hash_collision_for_implicit_account( height = check_tx_processing(&mut env, send_money_tx, height, blocks_number); let block = env.clients[0].chain.get_block_by_height(height - 1).unwrap(); - // Delete implicit account. + // Delete NEAR-implicit account. let delete_account_tx = SignedTransaction::delete_account( // Because AccessKeyNonceRange is enabled, correctness of this nonce is guaranteed. (height - 1) * near_primitives::account::AccessKey::ACCESS_KEY_NONCE_RANGE_MULTIPLIER, - implicit_account_id.clone(), - implicit_account_id.clone(), + near_implicit_account_id.clone(), + near_implicit_account_id.clone(), "test0".parse().unwrap(), - &implicit_account_signer, + &near_implicit_account_signer, *block.hash(), ); height = check_tx_processing(&mut env, delete_account_tx, height, blocks_number); let block = env.clients[0].chain.get_block_by_height(height - 1).unwrap(); - // Send money to implicit account again, invoking its second creation. + // Send money to NEAR-implicit account again, invoking its second creation. let send_money_again_tx = SignedTransaction::send_money( 2, "test1".parse().unwrap(), - implicit_account_id.clone(), + near_implicit_account_id.clone(), &signer1, deposit_for_account_creation, *block.hash(), @@ -173,43 +176,45 @@ fn get_status_of_tx_hash_collision_for_implicit_account( height = check_tx_processing(&mut env, send_money_again_tx, height, blocks_number); let block = env.clients[0].chain.get_block_by_height(height - 1).unwrap(); - // Send money from implicit account with incorrect nonce. - let send_money_from_implicit_account_tx = SignedTransaction::send_money( + // Send money from NEAR-implicit account with incorrect nonce. + let send_money_from_near_implicit_account_tx = SignedTransaction::send_money( 1, - implicit_account_id.clone(), + near_implicit_account_id.clone(), "test0".parse().unwrap(), - &implicit_account_signer, + &near_implicit_account_signer, 100, *block.hash(), ); - let response = env.clients[0].process_tx(send_money_from_implicit_account_tx, false, false); + let response = + env.clients[0].process_tx(send_money_from_near_implicit_account_tx, false, false); - // Check that sending money from implicit account with correct nonce is still valid. - let send_money_from_implicit_account_tx = SignedTransaction::send_money( + // Check that sending money from NEAR-implicit account with correct nonce is still valid. + let send_money_from_near_implicit_account_tx = SignedTransaction::send_money( (height - 1) * AccessKey::ACCESS_KEY_NONCE_RANGE_MULTIPLIER, - implicit_account_id, + near_implicit_account_id, "test0".parse().unwrap(), - &implicit_account_signer, + &near_implicit_account_signer, 100, *block.hash(), ); - check_tx_processing(&mut env, send_money_from_implicit_account_tx, height, blocks_number); + check_tx_processing(&mut env, send_money_from_near_implicit_account_tx, height, blocks_number); response } /// Test that duplicate transactions from NEAR-implicit accounts are properly rejected. #[test] -fn test_transaction_hash_collision_for_implicit_account_fail() { +fn test_transaction_hash_collision_for_near_implicit_account_fail() { let protocol_version = ProtocolFeature::AccessKeyNonceForImplicitAccounts.protocol_version(); let secret_key = SecretKey::from_seed(KeyType::ED25519, "test"); - let implicit_account_id = - derive_near_implicit_account_id(secret_key.public_key().unwrap_as_ed25519()); - let implicit_account_signer = InMemorySigner::from_secret_key(implicit_account_id, secret_key); + let public_key = secret_key.public_key(); + let near_implicit_account_id = derive_near_implicit_account_id(public_key.unwrap_as_ed25519()); + let near_implicit_account_signer = + InMemorySigner::from_secret_key(near_implicit_account_id, secret_key); assert_matches!( - get_status_of_tx_hash_collision_for_implicit_account( + get_status_of_tx_hash_collision_for_near_implicit_account( protocol_version, - implicit_account_signer + near_implicit_account_signer ), ProcessTxResponse::InvalidTx(InvalidTxError::InvalidNonce { .. }) ); @@ -217,22 +222,122 @@ fn test_transaction_hash_collision_for_implicit_account_fail() { /// Test that duplicate transactions from NEAR-implicit accounts are not rejected until protocol upgrade. #[test] -fn test_transaction_hash_collision_for_implicit_account_ok() { +fn test_transaction_hash_collision_for_near_implicit_account_ok() { let protocol_version = ProtocolFeature::AccessKeyNonceForImplicitAccounts.protocol_version() - 1; let secret_key = SecretKey::from_seed(KeyType::ED25519, "test"); - let implicit_account_id = - derive_near_implicit_account_id(secret_key.public_key().unwrap_as_ed25519()); - let implicit_account_signer = InMemorySigner::from_secret_key(implicit_account_id, secret_key); + let public_key = secret_key.public_key(); + let near_implicit_account_id = derive_near_implicit_account_id(public_key.unwrap_as_ed25519()); + let near_implicit_account_signer = + InMemorySigner::from_secret_key(near_implicit_account_id, secret_key); assert_matches!( - get_status_of_tx_hash_collision_for_implicit_account( + get_status_of_tx_hash_collision_for_near_implicit_account( protocol_version, - implicit_account_signer + near_implicit_account_signer ), ProcessTxResponse::ValidTx ); } +/// Test that transactions from ETH-implicit accounts are rejected. +#[test] +fn test_transaction_from_eth_implicit_account_fail() { + if !checked_feature!("stable", EthImplicitAccounts, PROTOCOL_VERSION) { + return; + } + let genesis = Genesis::test(vec!["test0".parse().unwrap(), "test1".parse().unwrap()], 1); + let mut env = TestEnv::builder(ChainGenesis::test()) + .real_epoch_managers(&genesis.config) + .nightshade_runtimes(&genesis) + .build(); + let genesis_block = env.clients[0].chain.get_block_by_height(0).unwrap(); + let deposit_for_account_creation = 10u128.pow(23); + let mut height = 1; + let blocks_number = 5; + let signer1 = InMemorySigner::from_seed("test1".parse().unwrap(), KeyType::ED25519, "test1"); + + let secret_key = SecretKey::from_seed(KeyType::SECP256K1, "test"); + let public_key = secret_key.public_key(); + let eth_implicit_account_id = derive_eth_implicit_account_id(public_key.unwrap_as_secp256k1()); + let eth_implicit_account_signer = + InMemorySigner::from_secret_key(eth_implicit_account_id.clone(), secret_key); + + // Send money to ETH-implicit account, invoking its creation. + let send_money_tx = SignedTransaction::send_money( + 1, + "test1".parse().unwrap(), + eth_implicit_account_id.clone(), + &signer1, + deposit_for_account_creation, + *genesis_block.hash(), + ); + // Check for tx success status and get new block height. + height = check_tx_processing(&mut env, send_money_tx, height, blocks_number); + let block = env.clients[0].chain.get_block_by_height(height - 1).unwrap(); + + // Try to send money from ETH-implicit account using `(block_height - 1) * 1e6` as a nonce. + // That would be a good nonce for any access key, but the transaction should fail nonetheless because there is no access key. + let nonce = (height - 1) * AccessKey::ACCESS_KEY_NONCE_RANGE_MULTIPLIER; + let send_money_from_eth_implicit_account_tx = SignedTransaction::send_money( + nonce, + eth_implicit_account_id.clone(), + "test0".parse().unwrap(), + ð_implicit_account_signer, + 100, + *block.hash(), + ); + let response = env.clients[0].process_tx(send_money_from_eth_implicit_account_tx, false, false); + let expected_tx_error = ProcessTxResponse::InvalidTx(InvalidTxError::InvalidAccessKeyError( + InvalidAccessKeyError::AccessKeyNotFound { + account_id: eth_implicit_account_id.clone(), + public_key: public_key.clone(), + }, + )); + assert_eq!(response, expected_tx_error); + + // Try to delete ETH-implicit account. Should fail because there is no access key. + let delete_eth_implicit_account_tx = SignedTransaction::delete_account( + nonce, + eth_implicit_account_id.clone(), + eth_implicit_account_id.clone(), + "test0".parse().unwrap(), + ð_implicit_account_signer, + *block.hash(), + ); + let response = env.clients[0].process_tx(delete_eth_implicit_account_tx, false, false); + assert_eq!(response, expected_tx_error); + + // Try to add an access key to the ETH-implicit account. Should fail because there is no access key. + let add_access_key_to_eth_implicit_account_tx = SignedTransaction::from_actions( + nonce, + eth_implicit_account_id.clone(), + eth_implicit_account_id.clone(), + ð_implicit_account_signer, + vec![Action::AddKey(Box::new(AddKeyAction { + public_key, + access_key: AccessKey::full_access(), + }))], + *block.hash(), + ); + let response = + env.clients[0].process_tx(add_access_key_to_eth_implicit_account_tx, false, false); + assert_eq!(response, expected_tx_error); + + // Try to deploy the Wallet Contract again to the ETH-implicit account. Should fail because there is no access key. + let wallet_contract_code = wallet_contract_placeholder().code().to_vec(); + let add_access_key_to_eth_implicit_account_tx = SignedTransaction::from_actions( + nonce, + eth_implicit_account_id.clone(), + eth_implicit_account_id, + ð_implicit_account_signer, + vec![Action::DeployContract(DeployContractAction { code: wallet_contract_code })], + *block.hash(), + ); + let response = + env.clients[0].process_tx(add_access_key_to_eth_implicit_account_tx, false, false); + assert_eq!(response, expected_tx_error); +} + /// Test that chunks with transactions that have expired are considered invalid. #[test] fn test_chunk_transaction_validity() { diff --git a/integration-tests/src/tests/client/features/delegate_action.rs b/integration-tests/src/tests/client/features/delegate_action.rs index 503b6278541..5d90db2d7e8 100644 --- a/integration-tests/src/tests/client/features/delegate_action.rs +++ b/integration-tests/src/tests/client/features/delegate_action.rs @@ -12,18 +12,21 @@ use near_crypto::{KeyType, PublicKey, Signer}; use near_primitives::account::{ id::AccountType, AccessKey, AccessKeyPermission, FunctionCallPermission, }; +use near_primitives::checked_feature; use near_primitives::config::ActionCosts; use near_primitives::errors::{ ActionError, ActionErrorKind, ActionsValidationError, InvalidAccessKeyError, InvalidTxError, TxExecutionError, }; -use near_primitives::test_utils::{create_user_test_signer, near_implicit_test_account}; +use near_primitives::test_utils::{ + create_user_test_signer, eth_implicit_test_account, near_implicit_test_account, +}; use near_primitives::transaction::{ Action, AddKeyAction, CreateAccountAction, DeleteAccountAction, DeleteKeyAction, DeployContractAction, FunctionCallAction, StakeAction, TransferAction, }; use near_primitives::types::{AccountId, Balance}; -use near_primitives::version::{ProtocolFeature, ProtocolVersion}; +use near_primitives::version::{ProtocolFeature, ProtocolVersion, PROTOCOL_VERSION}; use near_primitives::views::{ AccessKeyPermissionView, ExecutionStatusView, FinalExecutionOutcomeView, FinalExecutionStatus, }; @@ -121,6 +124,7 @@ fn check_meta_tx_execution( receiver: AccountId, ) -> (FinalExecutionOutcomeView, i128, i128, i128) { let node_user = node.user(); + let protocol_version = node.genesis().config.protocol_version; assert_eq!( relayer, @@ -137,7 +141,13 @@ fn check_meta_tx_execution( .nonce; let user_pubk = match sender.get_account_type() { AccountType::NearImplicitAccount => PublicKey::from_near_implicit_account(&sender).unwrap(), - AccountType::EthImplicitAccount => PublicKey::from_seed(KeyType::ED25519, sender.as_ref()), + AccountType::EthImplicitAccount => { + if checked_feature!("stable", EthImplicitAccounts, protocol_version) { + panic!("ETH-implicit accounts must not have access key"); + } else { + PublicKey::from_seed(KeyType::ED25519, sender.as_ref()) + } + } AccountType::NamedAccount => PublicKey::from_seed(KeyType::ED25519, sender.as_ref()), }; let user_nonce_before = node_user.get_access_key(&sender, &user_pubk).unwrap().nonce; @@ -803,12 +813,22 @@ fn meta_tx_create_near_implicit_account_fails() { meta_tx_create_implicit_account_fails(near_implicit_test_account()); } +#[test] +fn meta_tx_create_eth_implicit_account_fails() { + if !checked_feature!("stable", EthImplicitAccounts, PROTOCOL_VERSION) { + return; + } + meta_tx_create_implicit_account_fails(eth_implicit_test_account()); +} + /// Try creating an implicit account with a meta tx transfer and use the account /// in the same meta transaction. /// /// This is expected to fail with `AccountDoesNotExist`, known limitation of NEP-366. -/// It only works with accounts that already exists because it needs to do a -/// nonce check against the access key, which can only exist if the account exists. +/// In case of NEAR-implicit accounts it only works with accounts that already exist +/// because it needs to do a nonce check against the access key, +/// which can only exist if the account exists. +/// In case of ETH-implicit accounts the access key does not exist anyway. fn meta_tx_create_and_use_implicit_account(new_account: AccountId) { let relayer = bob_account(); let sender = alice_account(); @@ -840,12 +860,24 @@ fn meta_tx_create_and_use_near_implicit_account() { meta_tx_create_and_use_implicit_account(near_implicit_test_account()); } -/// Creating an implicit account with a meta tx transfer and use the account in +#[test] +fn meta_tx_create_and_use_eth_implicit_account() { + if !checked_feature!("stable", EthImplicitAccounts, PROTOCOL_VERSION) { + return; + } + meta_tx_create_and_use_implicit_account(eth_implicit_test_account()); +} + +/// Creating an implicit account with a meta tx transfer and try using the account in /// a second meta transaction. /// /// Creation through a meta tx should work as normal, it's just that the relayer /// pays for the storage and the user could delete the account and cash in, /// hence this workflow is not ideal from all circumstances. +/// +/// Using the account should only work for NEAR-implicit accounts, +/// as ETH-implicit accounts do not have access keys +/// and they can only be used by calling associated smart contract. fn meta_tx_create_implicit_account(new_account: AccountId) { let relayer = bob_account(); let sender = alice_account(); @@ -860,8 +892,8 @@ fn meta_tx_create_implicit_account(new_account: AccountId) { let tx_cost = match new_account.get_account_type() { AccountType::NearImplicitAccount => fee_helper.create_account_transfer_full_key_cost(), - AccountType::EthImplicitAccount => panic!("must be near-implicit"), - AccountType::NamedAccount => panic!("must be near-implicit"), + AccountType::EthImplicitAccount => fee_helper.create_account_transfer_cost(), + AccountType::NamedAccount => panic!("must be implicit"), }; check_meta_tx_no_fn_call( &node, @@ -878,6 +910,13 @@ fn meta_tx_create_implicit_account(new_account: AccountId) { let balance = node.view_balance(&new_account).expect("failed looking up balance"); assert_eq!(balance, initial_amount); + if new_account.get_account_type() == AccountType::EthImplicitAccount { + // ETH-implicit account must not have access key added. + assert!(node.user().is_locked(&new_account).unwrap()); + // We will not attempt to make a transfer from this account. + return; + } + // Now test we can use this account in a meta transaction that sends back half the tokens to alice. let transfer_amount = initial_amount / 2; let actions = vec![Action::Transfer(TransferAction { deposit: transfer_amount })]; @@ -887,19 +926,22 @@ fn meta_tx_create_implicit_account(new_account: AccountId) { actions, tx_cost, transfer_amount, - new_account.clone(), + new_account, relayer, sender, ) .assert_success(); - - // balance of the new account should NOT change, the relayer pays for it! - // (note: relayer balance checks etc are done in the shared checker function) - let balance = node.view_balance(&new_account).expect("failed looking up balance"); - assert_eq!(balance, initial_amount); } #[test] fn meta_tx_create_near_implicit_account() { meta_tx_create_implicit_account(near_implicit_test_account()); } + +#[test] +fn meta_tx_create_eth_implicit_account() { + if !checked_feature!("stable", EthImplicitAccounts, PROTOCOL_VERSION) { + return; + } + meta_tx_create_implicit_account(eth_implicit_test_account()); +} diff --git a/integration-tests/src/tests/client/features/restrict_tla.rs b/integration-tests/src/tests/client/features/restrict_tla.rs index 250a2e42af1..b50675845ec 100644 --- a/integration-tests/src/tests/client/features/restrict_tla.rs +++ b/integration-tests/src/tests/client/features/restrict_tla.rs @@ -23,11 +23,11 @@ fn test_create_top_level_accounts() { .build(); // These accounts cannot be created because they are top level accounts that are not implicit. - // Note that implicit accounts have to be 64 characters long. + // Note that implicit accounts have to be 64 or 42 (if starts with '0x') characters long. let top_level_accounts = [ - "0x06012c8cf97bead5deae237070f9587f8e7a266d", - "0x5e97870f263700f46aa00d967821199b9bc5a120", - "0x0000000000000000000000000000000000000000", + "0x06012c8cf97bead5deae237070f9587f8e7a266da", + "0a5e97870f263700f46aa00d967821199b9bc5a120", + "0x000000000000000000000000000000000000000", "alice", "thisisaveryverylongtoplevelaccount", ]; diff --git a/integration-tests/src/tests/standard_cases/mod.rs b/integration-tests/src/tests/standard_cases/mod.rs index 4a47ec2c397..e358f8294a9 100644 --- a/integration-tests/src/tests/standard_cases/mod.rs +++ b/integration-tests/src/tests/standard_cases/mod.rs @@ -16,7 +16,7 @@ use near_primitives::errors::{ }; use near_primitives::hash::{hash, CryptoHash}; use near_primitives::types::{AccountId, Balance, TrieNodesCount}; -use near_primitives::utils::derive_near_implicit_account_id; +use near_primitives::utils::{derive_eth_implicit_account_id, derive_near_implicit_account_id}; use near_primitives::views::{ AccessKeyView, AccountView, ExecutionMetadataView, FinalExecutionOutcomeView, FinalExecutionStatus, @@ -336,12 +336,16 @@ pub fn transfer_tokens_implicit_account(node: impl Node, public_key: PublicKey) let root = node_user.get_state_root(); let tokens_used = 10u128.pow(25); let fee_helper = fee_helper(&node); - let receiver_id = derive_near_implicit_account_id(public_key.unwrap_as_ed25519()); + + let receiver_id = match public_key.key_type() { + KeyType::ED25519 => derive_near_implicit_account_id(public_key.unwrap_as_ed25519()), + KeyType::SECP256K1 => derive_eth_implicit_account_id(public_key.unwrap_as_secp256k1()), + }; let transfer_cost = match receiver_id.get_account_type() { AccountType::NearImplicitAccount => fee_helper.create_account_transfer_full_key_cost(), - AccountType::EthImplicitAccount => std::panic!("must be near-implicit"), - AccountType::NamedAccount => std::panic!("must be near-implicit"), + AccountType::EthImplicitAccount => fee_helper.create_account_transfer_cost(), + AccountType::NamedAccount => std::panic!("must be implicit"), }; let transaction_result = @@ -369,8 +373,11 @@ pub fn transfer_tokens_implicit_account(node: impl Node, public_key: PublicKey) AccountType::NearImplicitAccount => { assert_eq!(view_access_key.unwrap(), AccessKey::full_access().into()); } - AccountType::EthImplicitAccount => std::panic!("must be near-implicit"), - AccountType::NamedAccount => std::panic!("must be near-implicit"), + AccountType::EthImplicitAccount => { + // A transfer to ETH-implicit address does not create access key. + assert!(view_access_key.is_err()); + } + AccountType::NamedAccount => std::panic!("must be implicit"), } let transaction_result = @@ -401,31 +408,34 @@ pub fn trying_to_create_implicit_account(node: impl Node, public_key: PublicKey) let root = node_user.get_state_root(); let tokens_used = 10u128.pow(25); let fee_helper = fee_helper(&node); - let receiver_id = derive_near_implicit_account_id(public_key.unwrap_as_ed25519()); + + let receiver_id = match public_key.key_type() { + KeyType::ED25519 => derive_near_implicit_account_id(public_key.unwrap_as_ed25519()), + KeyType::SECP256K1 => derive_eth_implicit_account_id(public_key.unwrap_as_secp256k1()), + }; let transaction_result = node_user - .create_account( - account_id.clone(), - receiver_id.clone(), - node.signer().public_key(), - tokens_used, - ) + .create_account(account_id.clone(), receiver_id.clone(), public_key, tokens_used) .unwrap(); + let create_account_fee = fee_helper.cfg().fee(ActionCosts::create_account).send_fee(false); + let add_access_key_fee = fee_helper + .cfg() + .fee(near_primitives::config::ActionCosts::add_full_access_key) + .send_fee(false); + let cost = match receiver_id.get_account_type() { AccountType::NearImplicitAccount => { - let fail_cost = - fee_helper.create_account_transfer_full_key_cost_fail_on_create_account(); - let create_account_fee = - fee_helper.cfg().fee(ActionCosts::create_account).send_fee(false); - let add_access_key_fee = fee_helper - .cfg() - .fee(near_primitives::config::ActionCosts::add_full_access_key) - .send_fee(false); - fail_cost + fee_helper.gas_to_balance(create_account_fee + add_access_key_fee) + fee_helper.create_account_transfer_full_key_cost_fail_on_create_account() + + fee_helper.gas_to_balance(create_account_fee + add_access_key_fee) + } + AccountType::EthImplicitAccount => { + // This test uses `node_user.create_account` method that is normally used for NamedAccounts and should fail here. + fee_helper.create_account_transfer_full_key_cost_fail_on_create_account() + // We add this fee analogously to the NEAR-implicit match arm above (without `add_access_key_fee`). + + fee_helper.gas_to_balance(create_account_fee) } - AccountType::EthImplicitAccount => std::panic!("must be near-implicit"), - AccountType::NamedAccount => std::panic!("must be near-implicit"), + AccountType::NamedAccount => std::panic!("must be implicit"), }; assert_eq!( diff --git a/integration-tests/src/tests/standard_cases/runtime.rs b/integration-tests/src/tests/standard_cases/runtime.rs index c30551085f0..c939a0b0e14 100644 --- a/integration-tests/src/tests/standard_cases/runtime.rs +++ b/integration-tests/src/tests/standard_cases/runtime.rs @@ -1,7 +1,10 @@ use crate::node::RuntimeNode; use crate::tests::standard_cases::*; use near_chain_configs::Genesis; +use near_crypto::SecretKey; +use near_primitives::checked_feature; use near_primitives::state_record::StateRecord; +use near_primitives::version::PROTOCOL_VERSION; use nearcore::config::{GenesisExt, TESTING_INIT_BALANCE}; use testlib::runtime_utils::{add_test_contract, alice_account, bob_account}; @@ -120,6 +123,16 @@ fn test_transfer_tokens_near_implicit_account_runtime() { transfer_tokens_implicit_account(node, public_key); } +#[test] +fn test_transfer_tokens_eth_implicit_account_runtime() { + if !checked_feature!("stable", EthImplicitAccounts, PROTOCOL_VERSION) { + return; + } + let node = create_runtime_node(); + let secret_key = SecretKey::from_seed(KeyType::SECP256K1, "test"); + transfer_tokens_implicit_account(node, secret_key.public_key()); +} + #[test] fn test_trying_to_create_near_implicit_account_runtime() { let node = create_runtime_node(); @@ -127,6 +140,16 @@ fn test_trying_to_create_near_implicit_account_runtime() { trying_to_create_implicit_account(node, public_key); } +#[test] +fn test_trying_to_create_eth_implicit_account_runtime() { + if !checked_feature!("stable", EthImplicitAccounts, PROTOCOL_VERSION) { + return; + } + let node = create_runtime_node(); + let secret_key = SecretKey::from_seed(KeyType::SECP256K1, "test"); + trying_to_create_implicit_account(node, secret_key.public_key()); +} + #[test] fn test_smart_contract_reward_runtime() { let node = create_runtime_node(); diff --git a/integration-tests/src/user/mod.rs b/integration-tests/src/user/mod.rs index cc1da5b1a8f..0a3aa6bce4b 100644 --- a/integration-tests/src/user/mod.rs +++ b/integration-tests/src/user/mod.rs @@ -38,6 +38,9 @@ pub trait User { fn view_state(&self, account_id: &AccountId, prefix: &[u8]) -> Result; + /// Returns whether the account is locked (has no access keys). + fn is_locked(&self, account_id: &AccountId) -> Result; + fn view_call( &self, account_id: &AccountId, diff --git a/integration-tests/src/user/rpc_user.rs b/integration-tests/src/user/rpc_user.rs index 0e5e53c6cd2..1eb60f2bd9a 100644 --- a/integration-tests/src/user/rpc_user.rs +++ b/integration-tests/src/user/rpc_user.rs @@ -9,7 +9,7 @@ use near_crypto::{PublicKey, Signer}; use near_jsonrpc::client::{new_client, JsonRpcClient}; use near_jsonrpc_client::ChunkId; use near_jsonrpc_primitives::errors::ServerError; -use near_jsonrpc_primitives::types::query::{RpcQueryRequest, RpcQueryResponse}; +use near_jsonrpc_primitives::types::query::{QueryResponseKind, RpcQueryRequest, RpcQueryResponse}; use near_jsonrpc_primitives::types::transactions::{RpcTransactionStatusRequest, TransactionInfo}; use near_primitives::hash::CryptoHash; use near_primitives::receipt::Receipt; @@ -70,9 +70,7 @@ impl User for RpcUser { fn view_account(&self, account_id: &AccountId) -> Result { let query = QueryRequest::ViewAccount { account_id: account_id.clone() }; match self.query(query)?.kind { - near_jsonrpc_primitives::types::query::QueryResponseKind::ViewAccount(account_view) => { - Ok(account_view) - } + QueryResponseKind::ViewAccount(account_view) => Ok(account_view), _ => Err("Invalid type of response".into()), } } @@ -84,9 +82,15 @@ impl User for RpcUser { include_proof: false, }; match self.query(query)?.kind { - near_jsonrpc_primitives::types::query::QueryResponseKind::ViewState( - view_state_result, - ) => Ok(view_state_result), + QueryResponseKind::ViewState(view_state_result) => Ok(view_state_result), + _ => Err("Invalid type of response".into()), + } + } + + fn is_locked(&self, account_id: &AccountId) -> Result { + let query = QueryRequest::ViewAccessKeyList { account_id: account_id.clone() }; + match self.query(query)?.kind { + QueryResponseKind::AccessKeyList(access_keys) => Ok(access_keys.keys.is_empty()), _ => Err("Invalid type of response".into()), } } @@ -94,9 +98,7 @@ impl User for RpcUser { fn view_contract_code(&self, account_id: &AccountId) -> Result { let query = QueryRequest::ViewCode { account_id: account_id.clone() }; match self.query(query)?.kind { - near_jsonrpc_primitives::types::query::QueryResponseKind::ViewCode( - contract_code_view, - ) => Ok(contract_code_view), + QueryResponseKind::ViewCode(contract_code_view) => Ok(contract_code_view), _ => Err("Invalid type of response".into()), } } @@ -113,9 +115,7 @@ impl User for RpcUser { args: args.to_vec().into(), }; match self.query(query)?.kind { - near_jsonrpc_primitives::types::query::QueryResponseKind::CallResult(call_result) => { - Ok(call_result) - } + QueryResponseKind::CallResult(call_result) => Ok(call_result), _ => Err("Invalid type of response".into()), } } @@ -217,9 +217,7 @@ impl User for RpcUser { public_key: public_key.clone(), }; match self.query(query)?.kind { - near_jsonrpc_primitives::types::query::QueryResponseKind::AccessKey(access_key) => { - Ok(access_key) - } + QueryResponseKind::AccessKey(access_key) => Ok(access_key), _ => Err("Invalid type of response".into()), } } diff --git a/integration-tests/src/user/runtime_user.rs b/integration-tests/src/user/runtime_user.rs index 72f5c98d6c8..f450e64dc67 100644 --- a/integration-tests/src/user/runtime_user.rs +++ b/integration-tests/src/user/runtime_user.rs @@ -252,6 +252,14 @@ impl User for RuntimeUser { .map_err(|err| err.to_string()) } + fn is_locked(&self, account_id: &AccountId) -> Result { + let state_update = self.client.read().expect(POISONED_LOCK_ERR).get_state_update(); + self.trie_viewer + .view_access_keys(&state_update, account_id) + .map(|access_keys| access_keys.is_empty()) + .map_err(|err| err.to_string()) + } + fn view_call( &self, account_id: &AccountId, diff --git a/runtime/near-vm-runner/src/config.rs b/runtime/near-vm-runner/src/config.rs index 99ab03da55e..9182949880f 100644 --- a/runtime/near-vm-runner/src/config.rs +++ b/runtime/near-vm-runner/src/config.rs @@ -51,6 +51,9 @@ pub struct Config { /// Enable the `FunctionCallWeight` protocol feature. pub function_call_weight: bool, + /// Enable the `EthImplicitAccounts` protocol feature. + pub eth_implicit_accounts: bool, + /// Describes limits for VM and Runtime. pub limit_config: LimitConfig, } diff --git a/runtime/near-vm-runner/src/logic/logic.rs b/runtime/near-vm-runner/src/logic/logic.rs index e5b223b949c..5327a601710 100644 --- a/runtime/near-vm-runner/src/logic/logic.rs +++ b/runtime/near-vm-runner/src/logic/logic.rs @@ -1780,11 +1780,13 @@ impl<'a> VMLogic<'a> { self.fees_config, sir, self.config.implicit_account_creation, + self.config.eth_implicit_accounts, receiver_id.get_account_type(), ); let exec_fee = transfer_exec_fee( self.fees_config, self.config.implicit_account_creation, + self.config.eth_implicit_accounts, receiver_id.get_account_type(), ); let burn_gas = send_fee; diff --git a/runtime/near-vm-runner/src/tests.rs b/runtime/near-vm-runner/src/tests.rs index 346143d9ad9..b02d4ac802d 100644 --- a/runtime/near-vm-runner/src/tests.rs +++ b/runtime/near-vm-runner/src/tests.rs @@ -48,6 +48,7 @@ impl crate::logic::Config { ed25519_verify: config.ed25519_verify, alt_bn128: config.alt_bn128, function_call_weight: config.function_call_weight, + eth_implicit_accounts: config.eth_implicit_accounts, limit_config: crate::config::LimitConfig { max_gas_burnt: config.limit_config.max_gas_burnt, max_stack_height: config.limit_config.max_stack_height, diff --git a/runtime/runtime/src/actions.rs b/runtime/runtime/src/actions.rs index df4f6e6616e..7b4e63509b5 100644 --- a/runtime/runtime/src/actions.rs +++ b/runtime/runtime/src/actions.rs @@ -22,7 +22,9 @@ use near_primitives::transaction::{ }; use near_primitives::types::validator_stake::ValidatorStake; use near_primitives::types::{AccountId, BlockHeight, EpochInfoProvider, Gas, TrieCacheMode}; -use near_primitives::utils::create_random_seed; +use near_primitives::utils::{ + account_is_implicit, create_random_seed, wallet_contract_placeholder, +}; use near_primitives::version::{ ProtocolFeature, ProtocolVersion, DELETE_KEY_STORAGE_USAGE_PROTOCOL_VERSION, }; @@ -429,9 +431,10 @@ pub(crate) fn action_create_account( )); } -/// Can only be used for NEAR-implicit accounts. +/// Can only be used for implicit accounts. pub(crate) fn action_implicit_account_creation_transfer( state_update: &mut TrieUpdate, + apply_state: &ApplyState, fee_config: &RuntimeFeesConfig, account: &mut Option, actor_id: &mut AccountId, @@ -473,9 +476,38 @@ pub(crate) fn action_implicit_account_creation_transfer( } // Invariant: The `account_id` is implicit. // It holds because in the only calling site, we've checked the permissions before. - AccountType::EthImplicitAccount | AccountType::NamedAccount => { - panic!("must be near-implicit") + AccountType::EthImplicitAccount => { + if checked_feature!("stable", EthImplicitAccounts, current_protocol_version) { + // TODO(eth-implicit) Use real Wallet Contract. + let wallet_contract = wallet_contract_placeholder(); + let storage_usage = fee_config.storage_usage_config.num_bytes_account + + fee_config.storage_usage_config.num_extra_bytes_record + + wallet_contract.code().len() as u64; + + *account = + Some(Account::new(transfer.deposit, 0, *wallet_contract.hash(), storage_usage)); + + // TODO(eth-implicit) Store a reference to the `Wallet Contract` instead of literally deploying it. + set_code(state_update, account_id.clone(), &wallet_contract); + // Precompile the contract and store result (compiled code or error) in the database. + // Note, that contract compilation costs are already accounted in deploy cost using + // special logic in estimator (see get_runtime_config() function). + precompile_contract( + &wallet_contract, + &apply_state.config.wasm_config, + apply_state.cache.as_deref(), + ) + .ok(); + } else { + // This panic is unreachable as this is an implicit account creation transfer. + // `check_account_existence` would fail because in this protocol version `account_is_implicit` + // would return false for an account that is of the ETH-implicit type. + panic!("must be near-implicit"); + } } + // This panic is unreachable as this is an implicit account creation transfer. + // `check_account_existence` would fail because `account_is_implicit` would return false for a Named account. + AccountType::NamedAccount => panic!("must be implicit"), } } @@ -897,8 +929,7 @@ pub(crate) fn check_account_existence( } else { // TODO: this should be `config.implicit_account_creation`. if config.wasm_config.implicit_account_creation - // TODO(eth-implicit) Change back to is_implicit() when ETH-implicit accounts are supported. - && account_id.get_account_type() == AccountType::NearImplicitAccount + && account_is_implicit(account_id, config.wasm_config.eth_implicit_accounts) { // If the account doesn't exist and it's implicit, then you // should only be able to create it using single transfer action. @@ -920,8 +951,7 @@ pub(crate) fn check_account_existence( if account.is_none() { return if config.wasm_config.implicit_account_creation && is_the_only_action - // TODO(eth-implicit) Change back to is_implicit() when ETH-implicit accounts are supported. - && account_id.get_account_type() == AccountType::NearImplicitAccount + && account_is_implicit(account_id, config.wasm_config.eth_implicit_accounts) && !is_refund { // OK. It's implicit account creation. @@ -1375,7 +1405,7 @@ mod tests { &sender_id, &RuntimeConfig::test(), false, - 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 37d9e3627e5..2ace6a379ad 100644 --- a/runtime/runtime/src/config.rs +++ b/runtime/runtime/src/config.rs @@ -100,6 +100,7 @@ pub fn total_send_fees( fees, sender_is_receiver, config.wasm_config.implicit_account_creation, + config.wasm_config.eth_implicit_accounts, receiver_id.get_account_type(), ) } @@ -194,6 +195,7 @@ pub fn exec_fee(config: &RuntimeConfig, action: &Action, receiver_id: &AccountId transfer_exec_fee( fees, config.wasm_config.implicit_account_creation, + config.wasm_config.eth_implicit_accounts, receiver_id.get_account_type(), ) } diff --git a/runtime/runtime/src/lib.rs b/runtime/runtime/src/lib.rs index f63983fbcbb..737e7c2803f 100644 --- a/runtime/runtime/src/lib.rs +++ b/runtime/runtime/src/lib.rs @@ -382,6 +382,7 @@ impl Runtime { debug_assert!(!is_refund); action_implicit_account_creation_transfer( state_update, + apply_state, &apply_state.config.fees, account, actor_id, diff --git a/test-utils/testlib/src/fees_utils.rs b/test-utils/testlib/src/fees_utils.rs index ddd964946a5..e1a2d9a40eb 100644 --- a/test-utils/testlib/src/fees_utils.rs +++ b/test-utils/testlib/src/fees_utils.rs @@ -56,10 +56,24 @@ impl FeeHelper { exec_gas + send_gas } + pub fn create_account_transfer_fee(&self) -> Gas { + let exec_gas = self.cfg().fee(ActionCosts::new_action_receipt).exec_fee() + + self.cfg().fee(ActionCosts::create_account).exec_fee() + + self.cfg().fee(ActionCosts::transfer).exec_fee(); + let send_gas = self.cfg().fee(ActionCosts::new_action_receipt).send_fee(false) + + self.cfg().fee(ActionCosts::create_account).send_fee(false) + + self.cfg().fee(ActionCosts::transfer).send_fee(false); + exec_gas + send_gas + } + pub fn create_account_transfer_full_key_cost(&self) -> Balance { self.gas_to_balance(self.create_account_transfer_full_key_fee()) } + pub fn create_account_transfer_cost(&self) -> Balance { + self.gas_to_balance(self.create_account_transfer_fee()) + } + pub fn create_account_transfer_full_key_cost_no_reward(&self) -> Balance { let exec_gas = self.cfg().fee(ActionCosts::new_action_receipt).exec_fee() + self.cfg().fee(ActionCosts::create_account).exec_fee() @@ -118,10 +132,6 @@ impl FeeHelper { self.gas_to_balance(self.transfer_fee()) } - pub fn transfer_cost_64len_hex(&self) -> Balance { - self.create_account_transfer_full_key_cost() - } - pub fn stake_cost(&self) -> Balance { let exec_gas = self.cfg().fee(ActionCosts::new_action_receipt).exec_fee() + self.cfg().fee(ActionCosts::stake).exec_fee(); diff --git a/tools/mirror/src/key_mapping.rs b/tools/mirror/src/key_mapping.rs index 46932926ad5..fbedfbbe0d7 100644 --- a/tools/mirror/src/key_mapping.rs +++ b/tools/mirror/src/key_mapping.rs @@ -107,10 +107,11 @@ pub fn map_account( match account_id.get_account_type() { AccountType::NearImplicitAccount => { let public_key = - PublicKey::from_near_implicit_account(account_id).expect("must be near-implicit"); + PublicKey::from_near_implicit_account(account_id).expect("must be implicit"); let mapped_key = map_key(&public_key, secret); - derive_near_implicit_account_id(mapped_key.public_key().unwrap_as_ed25519()) + derive_near_implicit_account_id(&mapped_key.public_key().unwrap_as_ed25519()) } + // TODO(eth-implicit) map to a new ETH address AccountType::EthImplicitAccount => account_id.clone(), AccountType::NamedAccount => account_id.clone(), }