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 f61f68a commit 7cb592f
Show file tree
Hide file tree
Showing 19 changed files with 246 additions and 153 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,10 +37,12 @@ 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",
"protocol_feature_chunk_validation",
"protocol_feature_eth_implicit",
"protocol_feature_fix_contract_loading_cost",
"protocol_feature_fix_staking_threshold",
"protocol_feature_reject_blocks_with_outdated_protocol_version",
Expand Down
12 changes: 10 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,12 @@ 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")]
{
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,10 +51,12 @@ 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",
"protocol_feature_chunk_validation",
"protocol_feature_eth_implicit",
"protocol_feature_fix_contract_loading_cost",
"protocol_feature_fix_staking_threshold",
"protocol_feature_reject_blocks_with_outdated_protocol_version",
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,9 +80,13 @@ 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_eth_implicit",
"protocol_feature_fix_contract_loading_cost",
"protocol_feature_reject_blocks_with_outdated_protocol_version",
"protocol_feature_simple_nightshade_v2",
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 @@ -417,9 +419,9 @@ fn test_transaction_eth_implicit_account_invalid_pk() {

// Now we send money from ETH-implicit account using correct signing key.
// As this is the first valid transaction from that account, no access key has been added yet,
// so using 0 nonce should pass (we should not use 0 nonce in real transaction).
// so using nonce=1 should pass (however, we should use `block_height - 1) * 1e6` in a real transaction).
let send_money_from_implicit_account_tx = SignedTransaction::send_money(
0,
1,
implicit_account_id,
"test0".parse().unwrap(),
&implicit_account_signer,
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
58 changes: 41 additions & 17 deletions integration-tests/src/tests/client/features/delegate_action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,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 +110,29 @@ 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")]
{
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,17 +180,23 @@ 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),
Err(_) => {
#[cfg(feature = "protocol_feature_eth_implicit")]
assert!(sender.get_account_type() == AccountType::EthImplicitAccount);

#[cfg(not(feature = "protocol_feature_eth_implicit"))]
panic!("Sender account must have access key");
}
}

let sender_after = node_user.view_balance(&sender).unwrap_or(0);
Expand Down Expand Up @@ -829,6 +850,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 +893,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 +975,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
20 changes: 14 additions & 6 deletions integration-tests/src/user/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ use futures::{future::LocalBoxFuture, FutureExt};

use near_crypto::{PublicKey, Signer};
use near_jsonrpc_primitives::errors::ServerError;
use near_primitives::account::{id::AccountType, AccessKey};
#[cfg(feature = "protocol_feature_eth_implicit")]
use near_primitives::account::id::AccountType;
use near_primitives::account::AccessKey;
use near_primitives::action::delegate::{DelegateAction, NonDelegateAction, SignedDelegateAction};
use near_primitives::hash::CryptoHash;
use near_primitives::receipt::Receipt;
Expand Down Expand Up @@ -266,11 +268,17 @@ pub trait User {

let user_nonce = match access_key {
Ok(access_key) => access_key.nonce,
Err(_) => match signer_id.get_account_type() {
// Zero nonce is for tests only. In real setting we should use `(block_height - 1) * 1e6`.
AccountType::EthImplicitAccount => 0,
_ => panic!("failed reading user's nonce for access key"),
},
Err(_) => {
#[cfg(not(feature = "protocol_feature_eth_implicit"))]
panic!("failed reading user's nonce for access key");

#[cfg(feature = "protocol_feature_eth_implicit")]
match signer_id.get_account_type() {
// Zero nonce is for tests only. In real setting we should use `(block_height - 1) * 1e6`.
AccountType::EthImplicitAccount => 0,
_ => panic!("failed reading user's nonce for access key"),
}
}
};

let delegate_action = DelegateAction {
Expand Down
4 changes: 4 additions & 0 deletions nearcore/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,17 @@ 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"
]

serialize_all_state_changes = ["near-store/serialize_all_state_changes"]
nightly = [
"nightly_protocol",
"protocol_feature_eth_implicit",
"protocol_feature_fix_contract_loading_cost",
"protocol_feature_fix_staking_threshold",
"protocol_feature_simple_nightshade_v2",
Expand Down
2 changes: 2 additions & 0 deletions neard/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,13 @@ 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_eth_implicit",
"protocol_feature_fix_staking_threshold",
"protocol_feature_simple_nightshade_v2",
"serialize_all_state_changes",
Expand Down
Loading

0 comments on commit 7cb592f

Please sign in to comment.