Skip to content

Commit

Permalink
Wrap changes in protocol_feature
Browse files Browse the repository at this point in the history
  • Loading branch information
staffik committed Nov 8, 2023
1 parent 32cbe4a commit d10bfc5
Show file tree
Hide file tree
Showing 18 changed files with 220 additions and 141 deletions.
2 changes: 2 additions & 0 deletions core/primitives-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ protocol_feature_fix_contract_loading_cost = []
protocol_feature_reject_blocks_with_outdated_protocol_version = []
protocol_feature_simple_nightshade_v2 = []
protocol_feature_chunk_validation = []
protocol_feature_eth_implicit = []

nightly = [
"nightly_protocol",
Expand All @@ -45,6 +46,7 @@ nightly = [
"protocol_feature_fix_staking_threshold",
"protocol_feature_reject_blocks_with_outdated_protocol_version",
"protocol_feature_simple_nightshade_v2",
"protocol_feature_eth_implicit",
]

nightly_protocol = [
Expand Down
11 changes: 9 additions & 2 deletions core/primitives-core/src/runtime/fees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,10 @@ pub fn transfer_exec_fee(
(false, _) => transfer_fee,
// Extra fee for the CreateAccount.
(true, AccountType::EthImplicitAccount) => {
transfer_fee + cfg.fee(ActionCosts::create_account).exec_fee()
#[cfg(feature = "protocol_feature_eth_implicit")]
return transfer_fee + cfg.fee(ActionCosts::create_account).exec_fee();
#[cfg(not(feature = "protocol_feature_eth_implicit"))]
transfer_fee
}
// Extra fees for the CreateAccount and AddFullAccessKey.
(true, AccountType::NearImplicitAccount) => {
Expand All @@ -244,7 +247,11 @@ pub fn transfer_send_fee(
(false, _) => transfer_fee,
// Extra fee for the CreateAccount.
(true, AccountType::EthImplicitAccount) => {
transfer_fee + cfg.fee(ActionCosts::create_account).send_fee(sender_is_receiver)
#[cfg(feature = "protocol_feature_eth_implicit")]
return transfer_fee
+ cfg.fee(ActionCosts::create_account).send_fee(sender_is_receiver);
#[cfg(not(feature = "protocol_feature_eth_implicit"))]
transfer_fee
}
// Extra fees for the CreateAccount and AddFullAccessKey.
(true, AccountType::NearImplicitAccount) => {
Expand Down
6 changes: 5 additions & 1 deletion core/primitives-core/src/version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ pub enum ProtocolFeature {
/// NEP: https://github.com/near/NEPs/pull/509
#[cfg(feature = "protocol_feature_chunk_validation")]
ChunkValidation,
#[cfg(feature = "protocol_feature_eth_implicit")]
EthImplicit,
}

impl ProtocolFeature {
Expand Down Expand Up @@ -189,6 +191,8 @@ impl ProtocolFeature {
ProtocolFeature::PostStateRoot => 136,
#[cfg(feature = "protocol_feature_chunk_validation")]
ProtocolFeature::ChunkValidation => 137,
#[cfg(feature = "protocol_feature_eth_implicit")]
ProtocolFeature::EthImplicit => 138,
}
}
}
Expand All @@ -201,7 +205,7 @@ const STABLE_PROTOCOL_VERSION: ProtocolVersion = 64;
/// Largest protocol version supported by the current binary.
pub const PROTOCOL_VERSION: ProtocolVersion = if cfg!(feature = "nightly_protocol") {
// On nightly, pick big enough version to support all features.
139
140
} else {
// Enable all stable features.
STABLE_PROTOCOL_VERSION
Expand Down
2 changes: 2 additions & 0 deletions core/primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ protocol_feature_fix_staking_threshold = ["near-primitives-core/protocol_feature
protocol_feature_fix_contract_loading_cost = ["near-primitives-core/protocol_feature_fix_contract_loading_cost"]
protocol_feature_reject_blocks_with_outdated_protocol_version = ["near-primitives-core/protocol_feature_reject_blocks_with_outdated_protocol_version"]
protocol_feature_simple_nightshade_v2 = ["near-primitives-core/protocol_feature_simple_nightshade_v2"]
protocol_feature_eth_implicit = ["near-primitives-core/protocol_feature_eth_implicit"]
protocol_feature_chunk_validation = []
nightly = [
"nightly_protocol",
Expand All @@ -59,6 +60,7 @@ nightly = [
"protocol_feature_fix_staking_threshold",
"protocol_feature_reject_blocks_with_outdated_protocol_version",
"protocol_feature_simple_nightshade_v2",
"protocol_feature_eth_implicit",
"near-fmt/nightly",
"near-primitives-core/nightly",
"near-vm-runner/nightly",
Expand Down
13 changes: 8 additions & 5 deletions core/primitives/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -557,12 +557,13 @@ pub fn create_test_signer(account_name: &str) -> InMemoryValidatorSigner {
pub fn create_user_test_signer(account_name: &AccountIdRef) -> InMemorySigner {
let account_id = account_name.to_owned();
if account_id == near_implicit_test_account() {
InMemorySigner::from_secret_key(account_id, near_implicit_test_account_secret())
} else if account_id == eth_implicit_test_account() {
InMemorySigner::from_secret_key(account_id, eth_implicit_test_account_secret())
} else {
InMemorySigner::from_seed(account_id, KeyType::ED25519, account_name.as_str())
return InMemorySigner::from_secret_key(account_id, near_implicit_test_account_secret());
}
#[cfg(feature = "protocol_feature_eth_implicit")]
if account_id == eth_implicit_test_account() {
return InMemorySigner::from_secret_key(account_id, eth_implicit_test_account_secret());
}
InMemorySigner::from_seed(account_id, KeyType::ED25519, account_name.as_str())
}

/// A fixed NEAR-implicit account for which tests can know the private key.
Expand All @@ -576,11 +577,13 @@ pub fn near_implicit_test_account_secret() -> SecretKey {
}

/// A fixed ETH-implicit account for which tests can know the private key.
#[cfg(feature = "protocol_feature_eth_implicit")]
pub fn eth_implicit_test_account() -> AccountId {
"0x96791e923f8cf697ad9c3290f2c9059f0231b24c".parse().unwrap()
}

/// Private key for the fixed ETH-implicit test account.
#[cfg(feature = "protocol_feature_eth_implicit")]
pub fn eth_implicit_test_account_secret() -> SecretKey {
"secp256k1:X4ETFKtQkSGVoZEnkn7bZ3LyajJaK2b3eweXaKmynGx".parse().unwrap()
}
Expand Down
12 changes: 12 additions & 0 deletions core/primitives/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ use crate::version::{

use near_crypto::{KeyType, PublicKey};
use near_primitives_core::account::id::AccountId;
#[cfg(not(feature = "protocol_feature_eth_implicit"))]
use near_primitives_core::account::id::AccountType;

use std::mem::size_of;
use std::ops::Deref;
Expand Down Expand Up @@ -469,6 +471,16 @@ where
Serializable(object)
}

/// 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 the protocol version.
pub fn account_is_implicit(account_id: &AccountId) -> bool {
#[cfg(feature = "protocol_feature_eth_implicit")]
return account_id.get_account_type().is_implicit();
#[cfg(not(feature = "protocol_feature_eth_implicit"))]
return account_id.get_account_type() == AccountType::NearImplicitAccount;
}

/// Derives `AccountId` from `PublicKey`.
/// If the key type is ED25519, returns hex-encoded copy of the key.
/// If the key type is SECP256K1, returns '0x' + keccak256(public_key)[12:32].hex().
Expand Down
4 changes: 4 additions & 0 deletions integration-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,16 @@ protocol_feature_reject_blocks_with_outdated_protocol_version = [
protocol_feature_simple_nightshade_v2 = [
"near-primitives/protocol_feature_simple_nightshade_v2",
]
protocol_feature_eth_implicit = [
"near-primitives/protocol_feature_eth_implicit",
]

nightly = [
"nightly_protocol",
"protocol_feature_fix_contract_loading_cost",
"protocol_feature_reject_blocks_with_outdated_protocol_version",
"protocol_feature_simple_nightshade_v2",
"protocol_feature_eth_implicit",
"near-actix-test-utils/nightly",
"near-async/nightly",
"near-chain-configs/nightly",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ fn get_status_of_tx_hash_collision_for_implicit_account(
/// Test that duplicate transactions from ETH-implicit account can be properly rejected
/// if we set nonce to `(block_height - 1) * 1e6` for transactions that results in
/// access key being added to the ETH-implicit account.
#[cfg(feature = "protocol_feature_eth_implicit")]
#[test]
fn test_transaction_eth_implicit_account() {
let epoch_length = 10;
Expand Down Expand Up @@ -337,6 +338,7 @@ fn test_transaction_eth_implicit_account() {
}

/// Test that the signer is correctly verified for transactions done from an ETH-implicit account.
#[cfg(feature = "protocol_feature_eth_implicit")]
#[test]
fn test_transaction_eth_implicit_account_invalid_pk() {
let epoch_length = 10;
Expand Down Expand Up @@ -465,6 +467,7 @@ fn test_transaction_hash_collision_for_near_implicit_account_ok() {
/// Test that duplicate transactions from ETH-implicit accounts are not rejected before and after protocol upgrade.
/// It is responsibility of the transaction signer to choose nonce equal to `(block_height - 1) * 1e6` in case the transaction
/// results in adding a new key to an ETH-implicit account (see https://github.com/near/NEPs/issues/498#issuecomment-1782881395).
#[cfg(feature = "protocol_feature_eth_implicit")]
#[test]
fn test_transaction_hash_collision_for_eth_implicit_account_ok() {
let protocol_version =
Expand Down
50 changes: 34 additions & 16 deletions integration-tests/src/tests/client/features/delegate_action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
//! NEP: https://github.com/near/NEPs/pull/366
//! This is the module for its integration tests.
use core::panic;

use crate::node::{Node, RuntimeNode};
use crate::tests::standard_cases::fee_helper;
use near_chain::ChainGenesis;
Expand All @@ -17,10 +19,9 @@ use near_primitives::errors::{
ActionError, ActionErrorKind, ActionsValidationError, InvalidAccessKeyError, InvalidTxError,
TxExecutionError,
};
use near_primitives::test_utils::{
create_user_test_signer, eth_implicit_test_account, eth_implicit_test_account_secret,
near_implicit_test_account,
};
use near_primitives::test_utils::{create_user_test_signer, near_implicit_test_account};
#[cfg(feature = "protocol_feature_eth_implicit")]
use near_primitives::test_utils::{eth_implicit_test_account, eth_implicit_test_account_secret};
use near_primitives::transaction::{
Action, AddKeyAction, CreateAccountAction, DeleteAccountAction, DeleteKeyAction,
DeployContractAction, FunctionCallAction, StakeAction, TransferAction,
Expand Down Expand Up @@ -111,6 +112,27 @@ fn reject_valid_meta_tx_in_older_versions() {
);
}

/// For NEAR-implicit accounts, returns the corresponding implicit public key.
/// For Named accounts, generates a public key using the account ID as the seed.
///
/// In case of ETH-implicit account, the ETH-implicit address shall be derived from the public key.
/// Thus, we cannot derive the public key from ETH-implicit address and the caller must
/// explicitly provide the Secp256K1 `public_key` matching the sender address.
fn derive_public_key_from_sender(sender: &AccountId, public_key: Option<PublicKey>) -> PublicKey {
match sender.get_account_type() {
AccountType::NearImplicitAccount => PublicKey::from_near_implicit_account(&sender).unwrap(),
AccountType::EthImplicitAccount => {
// We require that tests sending transactions from ETH-implicit accounts must provide the public key.
#[cfg(feature = "protocol_feature_eth_implicit")]
return public_key.unwrap();

#[cfg(not(feature = "protocol_feature_eth_implicit"))]
PublicKey::from_seed(KeyType::ED25519, sender.as_ref())
}
AccountType::NamedAccount => PublicKey::from_seed(KeyType::ED25519, sender.as_ref()),
}
}

/// Take a list of actions and execute them as a meta transaction, check
/// everything executes successfully, return balance differences for the sender,
/// relayer, and receiver.
Expand Down Expand Up @@ -141,16 +163,9 @@ fn check_meta_tx_execution(
.unwrap()
.nonce;

let user_pubk = match sender.get_account_type() {
AccountType::NearImplicitAccount => PublicKey::from_near_implicit_account(&sender).unwrap(),
// We require that tests sending transactions from ETH-implicit accounts provide the public key.
// It is because we can't infer public key from ETH-implicit account ID, and we need
// the public key from which the ETH-implicit sender address was derived.
AccountType::EthImplicitAccount => public_key.unwrap(),
AccountType::NamedAccount => PublicKey::from_seed(KeyType::ED25519, sender.as_ref()),
};
let user_pubk = derive_public_key_from_sender(&sender, public_key);

let user_nonce_before = node_user.get_access_key(&sender, &user_pubk);
let access_key_before = node_user.get_access_key(&sender, &user_pubk);

let tx_result =
node_user.meta_tx(sender.clone(), receiver.clone(), relayer.clone(), actions).unwrap();
Expand All @@ -165,14 +180,14 @@ fn check_meta_tx_execution(
.nonce;
assert_eq!(relayer_nonce, relayer_nonce_before + 1);

match user_nonce_before {
Ok(user_nonce_before) => {
match access_key_before {
Ok(access_key_before) => {
// user key must be checked for existence (to test DeleteKey action)
if let Ok(user_nonce) = node_user
.get_access_key(&sender, &PublicKey::from_seed(KeyType::ED25519, sender.as_ref()))
.map(|key| key.nonce)
{
assert_eq!(user_nonce, user_nonce_before.nonce + 1);
assert_eq!(user_nonce, access_key_before.nonce + 1);
}
}
Err(_) => assert!(sender.get_account_type() == AccountType::EthImplicitAccount),
Expand Down Expand Up @@ -829,6 +844,7 @@ fn meta_tx_create_near_implicit_account_fails() {
meta_tx_create_implicit_account_fails(near_implicit_test_account());
}

#[cfg(feature = "protocol_feature_eth_implicit")]
#[test]
fn meta_tx_create_eth_implicit_account_fails() {
meta_tx_create_implicit_account_fails(eth_implicit_test_account());
Expand Down Expand Up @@ -871,6 +887,7 @@ fn meta_tx_create_and_use_near_implicit_account() {
meta_tx_create_and_use_implicit_account(near_implicit_test_account());
}

#[cfg(feature = "protocol_feature_eth_implicit")]
#[test]
fn meta_tx_create_and_use_eth_implicit_account() {
meta_tx_create_and_use_implicit_account(eth_implicit_test_account());
Expand Down Expand Up @@ -952,6 +969,7 @@ fn meta_tx_create_near_implicit_account() {
meta_tx_create_implicit_account(near_implicit_test_account(), None);
}

#[cfg(feature = "protocol_feature_eth_implicit")]
#[test]
fn meta_tx_create_eth_implicit_account() {
let secret_key = eth_implicit_test_account_secret();
Expand Down
3 changes: 3 additions & 0 deletions integration-tests/src/tests/standard_cases/runtime.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::node::RuntimeNode;
use crate::tests::standard_cases::*;
use near_chain_configs::Genesis;
#[cfg(feature = "protocol_feature_eth_implicit")]
use near_crypto::SecretKey;
use near_primitives::state_record::StateRecord;
use nearcore::config::{GenesisExt, TESTING_INIT_BALANCE};
Expand Down Expand Up @@ -121,6 +122,7 @@ fn test_transfer_tokens_near_implicit_account_runtime() {
transfer_tokens_implicit_account(node, public_key);
}

#[cfg(feature = "protocol_feature_eth_implicit")]
#[test]
fn test_transfer_tokens_eth_implicit_account_runtime() {
let node = create_runtime_node();
Expand All @@ -135,6 +137,7 @@ fn test_trying_to_create_near_implicit_account_runtime() {
trying_to_create_implicit_account(node, public_key);
}

#[cfg(feature = "protocol_feature_eth_implicit")]
#[test]
fn test_trying_to_create_eth_implicit_account_runtime() {
let node = create_runtime_node();
Expand Down
4 changes: 4 additions & 0 deletions nearcore/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ protocol_feature_fix_contract_loading_cost = [
protocol_feature_simple_nightshade_v2 = [
"near-primitives/protocol_feature_simple_nightshade_v2",
]
protocol_feature_eth_implicit = [
"near-primitives/protocol_feature_eth_implicit",
]
new_epoch_sync = [
"near-client/new_epoch_sync"
]
Expand All @@ -125,6 +128,7 @@ nightly = [
"protocol_feature_fix_contract_loading_cost",
"protocol_feature_fix_staking_threshold",
"protocol_feature_simple_nightshade_v2",
"protocol_feature_eth_implicit",
"serialize_all_state_changes",
"near-async/nightly",
"near-chain-configs/nightly",
Expand Down
2 changes: 2 additions & 0 deletions neard/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,15 @@ rosetta_rpc = ["nearcore/rosetta_rpc"]
json_rpc = ["nearcore/json_rpc"]
protocol_feature_fix_staking_threshold = ["nearcore/protocol_feature_fix_staking_threshold"]
protocol_feature_simple_nightshade_v2 = ["nearcore/protocol_feature_simple_nightshade_v2"]
protocol_feature_eth_implicit = ["nearcore/protocol_feature_eth_implicit"]
serialize_all_state_changes = ["nearcore/serialize_all_state_changes"]
new_epoch_sync = ["nearcore/new_epoch_sync"]

nightly = [
"nightly_protocol",
"protocol_feature_fix_staking_threshold",
"protocol_feature_simple_nightshade_v2",
"protocol_feature_eth_implicit",
"serialize_all_state_changes",
"near-chain-configs/nightly",
"near-client/nightly",
Expand Down
5 changes: 5 additions & 0 deletions runtime/runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,13 @@ near-store.workspace = true
near-vm-runner.workspace = true

[features]
protocol_feature_eth_implicit = [
"near-primitives/protocol_feature_eth_implicit",
]

nightly = [
"nightly_protocol",
"protocol_feature_eth_implicit",
"near-chain-configs/nightly",
"near-o11y/nightly",
"near-primitives-core/nightly",
Expand Down
Loading

0 comments on commit d10bfc5

Please sign in to comment.