diff --git a/core/account-id/src/lib.rs b/core/account-id/src/lib.rs index 00c32bceab0..196232f03b8 100644 --- a/core/account-id/src/lib.rs +++ b/core/account-id/src/lib.rs @@ -104,24 +104,6 @@ impl AccountId { !self.is_system() && !self.contains('.') } - /// Returns `true` if the account id can be viewed as an Ethereum address directly - /// - /// See [Ethereum account](https://ethereum.org/en/developers/docs/accounts/) for more details. - /// - /// ## Examples - /// ``` - /// use near_account_id::AccountId; - /// - /// let eth_addr: AccountId = "0x06012c8cf97bead5deae237070f9587f8e7a266d".parse().unwrap(); - /// assert!(eth_addr.is_ethereum_address()); - /// - /// let non_eth_addr: AccountId = "0x".parse().unwrap(); - /// assert!(!non_eth_addr.is_ethereum_address()); - /// ``` - pub fn is_ethereum_address(&self) -> bool { - self.starts_with("0x") && self.len() == 42 - } - /// Returns `true` if the `AccountId` is a direct sub-account of the provided parent account. /// /// See [Subaccounts](https://docs.near.org/docs/concepts/account#subaccounts). @@ -738,28 +720,6 @@ mod tests { } } - #[test] - fn test_is_ethereum_address() { - let valid_ethereum_addresses = &[ - "0x06012c8cf97bead5deae237070f9587f8e7a266d", - "0x5e97870f263700f46aa00d967821199b9bc5a120", - "0x0000000000000000000000000000000000000000", - ]; - for account_id in valid_ethereum_addresses { - assert!(account_id.parse::().unwrap().is_ethereum_address()); - } - - let non_ethereum_addresses = &[ - "alice.near", - "near", - "0x", - "20782e20662e64666420482123494b6b6c677573646b6c66676a646b6c736667", - ]; - for account_id in non_ethereum_addresses { - assert!(!account_id.parse::().unwrap().is_ethereum_address()); - } - } - #[test] #[cfg(feature = "arbitrary")] fn test_arbitrary() { diff --git a/core/primitives-core/Cargo.toml b/core/primitives-core/Cargo.toml index 65e6b7af9c6..fde0b49fcf7 100644 --- a/core/primitives-core/Cargo.toml +++ b/core/primitives-core/Cargo.toml @@ -37,7 +37,7 @@ protocol_feature_fix_contract_loading_cost = [] protocol_feature_reject_blocks_with_outdated_protocol_version = [] protocol_feature_simple_nightshade_v2 = [] protocol_feature_block_header_v4 = [] -protocol_feature_ethereum_address = [] +protocol_feature_restrict_tla = [] nightly = [ "nightly_protocol", @@ -46,8 +46,7 @@ nightly = [ "protocol_feature_fix_staking_threshold", "protocol_feature_reject_blocks_with_outdated_protocol_version", "protocol_feature_simple_nightshade_v2", - "protocol_feature_ethereum_address", + "protocol_feature_restrict_tla", ] -nightly_protocol = [ -] +nightly_protocol = [] diff --git a/core/primitives-core/src/version.rs b/core/primitives-core/src/version.rs index d287cf32214..10d035b961f 100644 --- a/core/primitives-core/src/version.rs +++ b/core/primitives-core/src/version.rs @@ -124,8 +124,8 @@ pub enum ProtocolFeature { SimpleNightshadeV2, #[cfg(feature = "protocol_feature_block_header_v4")] BlockHeaderV4, - #[cfg(feature = "protocol_feature_ethereum_address")] - EthereumAddress, + #[cfg(feature = "protocol_feature_restrict_tla")] + RestrictTLA, } impl ProtocolFeature { @@ -180,8 +180,8 @@ impl ProtocolFeature { ProtocolFeature::SimpleNightshadeV2 => 135, #[cfg(feature = "protocol_feature_block_header_v4")] ProtocolFeature::BlockHeaderV4 => 138, - #[cfg(feature = "protocol_feature_ethereum_address")] - ProtocolFeature::EthereumAddress => 139, + #[cfg(feature = "protocol_feature_restrict_tla")] + ProtocolFeature::RestrictTLA => 139, } } } diff --git a/core/primitives/Cargo.toml b/core/primitives/Cargo.toml index f7d6c82e33a..99c7d1dba1d 100644 --- a/core/primitives/Cargo.toml +++ b/core/primitives/Cargo.toml @@ -59,12 +59,12 @@ protocol_feature_simple_nightshade_v2 = [ protocol_feature_block_header_v4 = [ "near-primitives-core/protocol_feature_block_header_v4", ] -protocol_feature_ethereum_address = [ - "near-primitives-core/protocol_feature_ethereum_address", +protocol_feature_restrict_tla = [ + "near-primitives-core/protocol_feature_restrict_tla", ] nightly = [ "nightly_protocol", - "protocol_feature_ethereum_address", + "protocol_feature_restrict_tla", "protocol_feature_block_header_v4", "protocol_feature_fix_contract_loading_cost", "protocol_feature_fix_staking_threshold", diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index aa003e3a780..89c67d7755f 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -82,9 +82,7 @@ protocol_feature_reject_blocks_with_outdated_protocol_version = [ protocol_feature_simple_nightshade_v2 = [ "near-primitives/protocol_feature_simple_nightshade_v2", ] -protocol_feature_ethereum_address = [ - "nearcore/protocol_feature_ethereum_address", -] +protocol_feature_restrict_tla = ["nearcore/protocol_feature_restrict_tla"] nightly = [ "nightly_protocol", diff --git a/integration-tests/src/tests/standard_cases/mod.rs b/integration-tests/src/tests/standard_cases/mod.rs index 7dd513f6ff1..4cda0de72aa 100644 --- a/integration-tests/src/tests/standard_cases/mod.rs +++ b/integration-tests/src/tests/standard_cases/mod.rs @@ -665,16 +665,18 @@ pub fn test_create_account_failure_already_exists(node: impl Node) { ); } -pub fn test_create_ethereum_address(node: impl Node) { +pub fn test_create_top_level_account(node: impl Node) { let account_id = &node.account_id().unwrap(); let node_user = node.user(); - let valid_ethereum_addresses = [ + let top_level_accounts = [ "0x06012c8cf97bead5deae237070f9587f8e7a266d", "0x5e97870f263700f46aa00d967821199b9bc5a120", "0x0000000000000000000000000000000000000000", + "alice", + "thisisaveryverylongtoplevelaccount" ]; - for (_, address) in valid_ethereum_addresses.iter().enumerate() { - let new_account_id = address.parse::().unwrap(); + for (_, id) in top_level_accounts.iter().enumerate() { + let new_account_id = id.parse::().unwrap(); let transaction_result = node_user .create_account(account_id.clone(), new_account_id.clone(), node.signer().public_key(), 0) .unwrap(); diff --git a/integration-tests/src/tests/standard_cases/runtime.rs b/integration-tests/src/tests/standard_cases/runtime.rs index 7cd067a1081..becfe588e52 100644 --- a/integration-tests/src/tests/standard_cases/runtime.rs +++ b/integration-tests/src/tests/standard_cases/runtime.rs @@ -346,9 +346,8 @@ fn test_storage_read_write_costs_runtime() { } #[test] -#[cfg(feature = "protocol_feature_ethereum_address")] -fn test_create_ethereum_address_runtime() { +#[cfg(feature = "protocol_feature_restrict_tla")] +fn test_create_top_level_account_runtime() { let node = create_runtime_node(); - let runtime_config = node.client.as_ref().read().unwrap().runtime_config.clone(); - test_create_ethereum_address(node); + test_create_top_level_account(node); } diff --git a/nearcore/Cargo.toml b/nearcore/Cargo.toml index d2867cd768c..5c4b3b3cf6d 100644 --- a/nearcore/Cargo.toml +++ b/nearcore/Cargo.toml @@ -116,15 +116,15 @@ protocol_feature_fix_contract_loading_cost = [ protocol_feature_simple_nightshade_v2 = [ "near-primitives/protocol_feature_simple_nightshade_v2", ] -protocol_feature_ethereum_address = [ - "near-primitives/protocol_feature_ethereum_address", - "node-runtime/protocol_feature_ethereum_address", +protocol_feature_restrict_tla = [ + "near-primitives/protocol_feature_restrict_tla", + "node-runtime/protocol_feature_restrict_tla", ] serialize_all_state_changes = ["near-store/serialize_all_state_changes"] nightly = [ "nightly_protocol", - "protocol_feature_ethereum_address", + "protocol_feature_restrict_tla", "protocol_feature_fix_contract_loading_cost", "protocol_feature_fix_staking_threshold", "protocol_feature_simple_nightshade_v2", diff --git a/runtime/runtime/Cargo.toml b/runtime/runtime/Cargo.toml index 91392738c7c..5d343c17dd4 100644 --- a/runtime/runtime/Cargo.toml +++ b/runtime/runtime/Cargo.toml @@ -31,7 +31,9 @@ near-store.workspace = true near-vm-runner.workspace = true [features] -protocol_feature_ethereum_address = ["near-primitives/protocol_feature_ethereum_address"] +protocol_feature_restrict_tla = [ + "near-primitives/protocol_feature_restrict_tla", +] nightly = [ "nightly_protocol", "near-chain-configs/nightly", @@ -39,7 +41,7 @@ nightly = [ "near-primitives/nightly", "near-store/nightly", "near-vm-runner/nightly", - "protocol_feature_ethereum_address", + "protocol_feature_restrict_tla", ] default = [] nightly_protocol = [ @@ -48,7 +50,7 @@ nightly_protocol = [ "near-primitives/nightly_protocol", "near-store/nightly_protocol", "near-vm-runner/nightly_protocol", - "protocol_feature_ethereum_address", + "protocol_feature_restrict_tla", ] no_cpu_compatibility_checks = ["near-vm-runner/no_cpu_compatibility_checks"] diff --git a/runtime/runtime/src/actions.rs b/runtime/runtime/src/actions.rs index 969fda045cc..dadcb2a12ab 100644 --- a/runtime/runtime/src/actions.rs +++ b/runtime/runtime/src/actions.rs @@ -385,9 +385,21 @@ pub(crate) fn action_create_account( current_protocol_version: ProtocolVersion, ) { if account_id.is_top_level() { - if account_id.len() < account_creation_config.min_allowed_top_level_account_length as usize - && predecessor_id != &account_creation_config.registrar_account_id - { + let old_condition_for_error = account_id.len() + < account_creation_config.min_allowed_top_level_account_length as usize + && predecessor_id != &account_creation_config.registrar_account_id; + let new_condition_for_error = !account_id.is_implicit() + && predecessor_id != &account_creation_config.registrar_account_id; + let is_error = if checked_feature!( + "protocol_feature_restrict_tla", + RestrictTLA, + current_protocol_version + ) { + new_condition_for_error + } else { + old_condition_for_error + }; + if is_error { // A short top-level account ID can only be created registrar account. result.result = Err(ActionErrorKind::CreateAccountOnlyByRegistrar { account_id: account_id.clone(), @@ -396,25 +408,6 @@ pub(crate) fn action_create_account( } .into()); return; - } else if checked_feature!( - "protocol_feature_ethereum_address", - EthereumAddress, - current_protocol_version - ) { - if account_id.is_ethereum_address() - && predecessor_id != &account_creation_config.registrar_account_id - { - // An Ethereum address can only be created by the registrar account - result.result = Err(ActionErrorKind::CreateAccountOnlyByRegistrar { - account_id: account_id.clone(), - registrar_account_id: account_creation_config.registrar_account_id.clone(), - predecessor_id: predecessor_id.clone(), - } - .into()); - return; - } - } else { - // OK: Valid top-level Account ID } } else if !account_id.is_sub_account_of(predecessor_id) { // The sub-account can only be created by its root account. E.g. `alice.near` only by `near` @@ -1021,6 +1014,7 @@ mod tests { } #[test] + #[cfg(not(feature = "protocol_feature_restrict_tla"))] fn test_create_account_valid_top_level_long() { let account_id = "bob_near_long_name".parse().unwrap(); let predecessor_id = "alice.near".parse().unwrap(); @@ -1063,6 +1057,7 @@ mod tests { } #[test] + #[cfg(not(feature = "protocol_feature_restrict_tla"))] fn test_create_account_invalid_short_top_level() { let account_id = "bob".parse::().unwrap(); let predecessor_id = "near".parse::().unwrap(); @@ -1082,6 +1077,7 @@ mod tests { } #[test] + #[cfg(not(feature = "protocol_feature_restrict_tla"))] fn test_create_account_valid_short_top_level_len_allowed() { let account_id = "bob".parse().unwrap(); let predecessor_id = "near".parse().unwrap(); @@ -1090,25 +1086,34 @@ mod tests { } #[test] - #[cfg(feature = "protocol_feature_ethereum_address")] - fn test_create_ethereum_address() { - let account_id: AccountId = "0x32400084c286cf3e17e7b677ea9583e60a000324".parse().unwrap(); - let predecessor_id: AccountId = "near".parse().unwrap(); - let action_result = test_action_create_account(account_id.clone(), predecessor_id.clone(), 32); - assert_eq!( - action_result.result, - Err(ActionError { - index: None, - kind: ActionErrorKind::CreateAccountOnlyByRegistrar { - account_id: account_id.clone(), - registrar_account_id: "registrar".parse().unwrap(), - predecessor_id: predecessor_id, - }, - }) - ); - let registrar_account_id: AccountId = "registrar".parse().unwrap(); - let action_result = test_action_create_account(account_id, registrar_account_id, 32); - assert!(action_result.result.is_ok()); + #[cfg(feature = "protocol_feature_restrict_tla")] + fn test_create_top_level_account_restriction() { + let account_ids = [ + "0x32400084c286cf3e17e7b677ea9583e60a000324", + "thisisaveryverylongtoplevelaccount", + "32400084c286cf3e17e7b677ea9583e60a000324", + "000000000000000000000000000000000000000000000000000000000000000" + ]; + for id in &account_ids { + let account_id: AccountId = id.parse().unwrap(); + let predecessor_id: AccountId = "near".parse().unwrap(); + let action_result = + test_action_create_account(account_id.clone(), predecessor_id.clone(), 32); + assert_eq!( + action_result.result, + Err(ActionError { + index: None, + kind: ActionErrorKind::CreateAccountOnlyByRegistrar { + account_id: account_id.clone(), + registrar_account_id: "registrar".parse().unwrap(), + predecessor_id: predecessor_id, + }, + }) + ); + let registrar_account_id: AccountId = "registrar".parse().unwrap(); + let action_result = test_action_create_account(account_id, registrar_account_id, 32); + assert!(action_result.result.is_ok()); + } } fn test_delete_large_account(