Skip to content

Commit

Permalink
nit PR fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
staffik committed Oct 31, 2023
1 parent b0d6ab4 commit cb1a914
Show file tree
Hide file tree
Showing 11 changed files with 94 additions and 60 deletions.
15 changes: 13 additions & 2 deletions core/account-id/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,22 @@ pub use errors::{ParseAccountError, ParseErrorKind};
#[derive(Eq, Ord, Hash, Clone, Debug, PartialEq, PartialOrd)]
pub struct AccountId(Box<str>);

/// Enum representing possible types of accounts.
#[derive(PartialEq)]
pub enum AccountType {
/// Any valid account, that is neither NEAR-implicit nor ETH-implicit.
NamedAccount,
/// An account with 64 characters long hexadecimal address.
NearImplicitAccount,
/// An account which address starts with '0x', followed by 40 hex characters.
EthImplicitAccount,
}

impl AccountType {
pub fn is_implicit(&self) -> bool {
match &self {
Self::NearImplicitAccount => true,
// TODO change to true later, see https://github.com/near/nearcore/issues/10018
// TODO(eth-implicit) change to true later, see https://github.com/near/nearcore/issues/10018
Self::EthImplicitAccount => false,
Self::NamedAccount => false,
}
Expand Down Expand Up @@ -150,7 +154,7 @@ impl AccountId {
.map_or(false, |s| !s.contains('.'))
}

/// Returns `true` if the `AccountId` is a 40 characters long hexadecimal prefixed with '0x'.
/// Returns `true` if the `AccountId` is '0x' followed by 40 hex characters (42 characters in total).
///
/// See [Implicit-Accounts](https://docs.near.org/docs/concepts/account#implicit-accounts).
///
Expand Down Expand Up @@ -475,7 +479,9 @@ mod tests {
"10-4.8-2",
"b-o_w_e-n",
"no_lols",
// NEAR-implicit account
"0123456789012345678901234567890123456789012345678901234567890123",
// ETH-implicit account
"0xb794f5ea0ba39494ce839613fffba74279579268",
// Valid, but can't be created
"near.a",
Expand Down Expand Up @@ -592,7 +598,9 @@ mod tests {
"alex-skidanov",
"b-o_w_e-n",
"no_lols",
// ETH-implicit account
"0xb794f5ea0ba39494ce839613fffba74279579268",
// NEAR-implicit account
"0123456789012345678901234567890123456789012345678901234567890123",
];
for account_id in ok_top_level_account_ids {
Expand Down Expand Up @@ -719,6 +727,7 @@ mod tests {
),
(
"b794f5ea0ba39494ce839613fffba74279579268",
// ETH-implicit account
"0xb794f5ea0ba39494ce839613fffba74279579268",
),
("aa", "ъ@aa"),
Expand Down Expand Up @@ -764,6 +773,7 @@ mod tests {
"fffff_ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
"00000000000000000000000000000000000000000000000000000000000000",
"0xb794f5ea0ba39494ce839613fffba74279579268",
];
for invalid_account_id in invalid_near_implicit_account_ids {
assert!(
Expand Down Expand Up @@ -805,6 +815,7 @@ mod tests {
"0xfffff_ffffffffffffffffffffffffffffffffff",
"0xoooooooooooooooooooooooooooooooooooooooo",
"0x00000000000000000000000000000000000000000",
"0000000000000000000000000000000000000000000000000000000000000000",
];
for invalid_account_id in invalid_eth_implicit_account_ids {
assert!(
Expand Down
50 changes: 36 additions & 14 deletions core/primitives-core/src/runtime/fees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,31 +208,53 @@ impl StorageUsageConfig {
/// We can assume that no overflow will happen here.
pub fn transfer_exec_fee(
cfg: &RuntimeFeesConfig,
is_receiver_implicit: bool,
implicit_account_creation_allowed: bool,
receiver_account_type: AccountType,
) -> Gas {
let mut result = cfg.fee(ActionCosts::transfer).exec_fee();
if is_receiver_implicit {
result += cfg.fee(ActionCosts::create_account).exec_fee();
if receiver_account_type == AccountType::NearImplicitAccount {
result += cfg.fee(ActionCosts::add_full_access_key).exec_fee();
let implicit_account_creation =
implicit_account_creation_allowed && receiver_account_type.is_implicit();
if !implicit_account_creation {
// No account will be created, just a regular transfer.
cfg.fee(ActionCosts::transfer).exec_fee()
} else {
match receiver_account_type {
// Extra fees for the CreateAccount and AddFullAccessKey.
AccountType::NearImplicitAccount => {
cfg.fee(ActionCosts::transfer).exec_fee()
+ cfg.fee(ActionCosts::create_account).exec_fee()
+ cfg.fee(ActionCosts::add_full_access_key).exec_fee()
}
// These arms are impossible, as we checked for `is_implicit` above.
AccountType::EthImplicitAccount | AccountType::NamedAccount => {
panic!("must be near-implicit")
}
}
}
result
}

pub fn transfer_send_fee(
cfg: &RuntimeFeesConfig,
sender_is_receiver: bool,
is_receiver_implicit: bool,
implicit_account_creation_allowed: bool,
receiver_account_type: AccountType,
) -> Gas {
let mut result = cfg.fee(ActionCosts::transfer).send_fee(sender_is_receiver);
if is_receiver_implicit {
result += cfg.fee(ActionCosts::create_account).send_fee(sender_is_receiver);
if receiver_account_type == AccountType::NearImplicitAccount {
result += cfg.fee(ActionCosts::add_full_access_key).send_fee(sender_is_receiver);
let implicit_account_creation =
implicit_account_creation_allowed && receiver_account_type.is_implicit();
if !implicit_account_creation {
// No account will be created, just a regular transfer.
cfg.fee(ActionCosts::transfer).send_fee(sender_is_receiver)
} else {
match receiver_account_type {
// Extra fees for the CreateAccount and AddFullAccessKey.
AccountType::NearImplicitAccount => {
cfg.fee(ActionCosts::transfer).send_fee(sender_is_receiver)
+ cfg.fee(ActionCosts::create_account).send_fee(sender_is_receiver)
+ cfg.fee(ActionCosts::add_full_access_key).send_fee(sender_is_receiver)
}
// These arms are impossible, as we checked for `is_implicit` above.
AccountType::EthImplicitAccount | AccountType::NamedAccount => {
panic!("must be near-implicit")
}
}
}
result
}
13 changes: 6 additions & 7 deletions core/primitives/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::version::{
CREATE_RECEIPT_ID_SWITCH_TO_CURRENT_BLOCK_VERSION,
};

use near_crypto::{KeyType, PublicKey};
use near_crypto::ED25519PublicKey;
use near_primitives_core::account::id::AccountId;

use std::mem::size_of;
Expand Down Expand Up @@ -471,23 +471,22 @@ where

/// Derives `AccountId` from `PublicKey``.
/// If the key type is ED25519, returns hex-encoded copy of the key.
pub fn derive_near_implicit_account_id(public_key: &PublicKey) -> AccountId {
match public_key.key_type() {
KeyType::ED25519 => hex::encode(public_key.key_data()).parse().unwrap(),
_ => unimplemented!(),
}
pub fn derive_near_implicit_account_id(public_key: &ED25519PublicKey) -> AccountId {
hex::encode(public_key).parse().unwrap()
}

#[cfg(test)]
mod tests {
use super::*;
use near_crypto::{KeyType, PublicKey};

#[test]
fn test_derive_account_id_from_ed25519_public_key() {
let public_key = PublicKey::from_seed(KeyType::ED25519, "test");
let expected: AccountId =
"bb4dc639b212e075a751685b26bdcea5920a504181ff2910e8549742127092a0".parse().unwrap();
assert_eq!(derive_near_implicit_account_id(&public_key), expected);
let account_id = derive_near_implicit_account_id(public_key.unwrap_as_ed25519());
assert_eq!(account_id, expected);
}

#[test]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,8 @@ fn get_status_of_tx_hash_collision_for_implicit_account(
fn test_transaction_hash_collision_for_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());
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);
assert_matches!(
get_status_of_tx_hash_collision_for_implicit_account(
Expand All @@ -220,7 +221,8 @@ fn test_transaction_hash_collision_for_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());
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);
assert_matches!(
get_status_of_tx_hash_collision_for_implicit_account(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -860,8 +860,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 implicit"),
AccountType::NamedAccount => panic!("must be implicit"),
AccountType::EthImplicitAccount => panic!("must be near-implicit"),
AccountType::NamedAccount => panic!("must be near-implicit"),
};
check_meta_tx_no_fn_call(
&node,
Expand Down
33 changes: 17 additions & 16 deletions integration-tests/src/tests/standard_cases/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,12 +336,12 @@ 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);
let receiver_id = derive_near_implicit_account_id(public_key.unwrap_as_ed25519());

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 implicit"),
AccountType::NamedAccount => std::panic!("must be implicit"),
AccountType::EthImplicitAccount => std::panic!("must be near-implicit"),
AccountType::NamedAccount => std::panic!("must be near-implicit"),
};

let transaction_result =
Expand Down Expand Up @@ -369,8 +369,8 @@ 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 implicit"),
AccountType::NamedAccount => std::panic!("must be implicit"),
AccountType::EthImplicitAccount => std::panic!("must be near-implicit"),
AccountType::NamedAccount => std::panic!("must be near-implicit"),
}

let transaction_result =
Expand Down Expand Up @@ -401,7 +401,7 @@ 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);
let receiver_id = derive_near_implicit_account_id(public_key.unwrap_as_ed25519());

let transaction_result = node_user
.create_account(
Expand All @@ -414,17 +414,18 @@ pub fn trying_to_create_implicit_account(node: impl Node, public_key: PublicKey)

let cost = match receiver_id.get_account_type() {
AccountType::NearImplicitAccount => {
fee_helper.create_account_transfer_full_key_cost_fail_on_create_account()
+ fee_helper.gas_to_balance(
fee_helper.cfg().fee(ActionCosts::create_account).send_fee(false)
+ fee_helper
.cfg()
.fee(near_primitives::config::ActionCosts::add_full_access_key)
.send_fee(false),
)
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)
}
AccountType::EthImplicitAccount => std::panic!("must be implicit"),
AccountType::NamedAccount => std::panic!("must be implicit"),
AccountType::EthImplicitAccount => std::panic!("must be near-implicit"),
AccountType::NamedAccount => std::panic!("must be near-implicit"),
};

assert_eq!(
Expand Down
6 changes: 2 additions & 4 deletions runtime/near-vm-runner/src/logic/logic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1773,17 +1773,15 @@ impl<'a> VMLogic<'a> {

let (receipt_idx, sir) = self.promise_idx_to_receipt_idx_with_sir(promise_idx)?;
let receiver_id = self.ext.get_receipt_receiver(receipt_idx);
let is_receiver_implicit =
self.config.implicit_account_creation && receiver_id.get_account_type().is_implicit();
let send_fee = transfer_send_fee(
self.fees_config,
sir,
is_receiver_implicit,
self.config.implicit_account_creation,
receiver_id.get_account_type(),
);
let exec_fee = transfer_exec_fee(
self.fees_config,
is_receiver_implicit,
self.config.implicit_account_creation,
receiver_id.get_account_type(),
);
let burn_gas = send_fee;
Expand Down
5 changes: 4 additions & 1 deletion runtime/runtime/src/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ pub(crate) fn action_create_account(
));
}

/// Can only be used for NEAR-implicit accounts.
pub(crate) fn action_implicit_account_creation_transfer(
state_update: &mut TrieUpdate,
fee_config: &RuntimeFeesConfig,
Expand Down Expand Up @@ -472,7 +473,9 @@ 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 implicit"),
AccountType::EthImplicitAccount | AccountType::NamedAccount => {
panic!("must be near-implicit")
}
}
}

Expand Down
16 changes: 7 additions & 9 deletions runtime/runtime/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,11 @@ pub fn total_send_fees(
}
Transfer(_) => {
// Account for implicit account creation
let receiver_account_type = receiver_id.get_account_type();
let is_receiver_implicit = config.wasm_config.implicit_account_creation
&& receiver_account_type.is_implicit();
transfer_send_fee(
fees,
sender_is_receiver,
is_receiver_implicit,
receiver_account_type,
config.wasm_config.implicit_account_creation,
receiver_id.get_account_type(),
)
}
Stake(_) => fees.fee(ActionCosts::stake).send_fee(sender_is_receiver),
Expand Down Expand Up @@ -194,10 +191,11 @@ pub fn exec_fee(config: &RuntimeConfig, action: &Action, receiver_id: &AccountId
}
Transfer(_) => {
// Account for implicit account creation
let receiver_account_type = receiver_id.get_account_type();
let is_receiver_implicit =
config.wasm_config.implicit_account_creation && receiver_account_type.is_implicit();
transfer_exec_fee(fees, is_receiver_implicit, receiver_account_type)
transfer_exec_fee(
fees,
config.wasm_config.implicit_account_creation,
receiver_id.get_account_type(),
)
}
Stake(_) => fees.fee(ActionCosts::stake).exec_fee(),
AddKey(add_key_action) => match &add_key_action.access_key.permission {
Expand Down
4 changes: 2 additions & 2 deletions tools/mirror/src/key_mapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ 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 implicit");
PublicKey::from_near_implicit_account(account_id).expect("must be near-implicit");
let mapped_key = map_key(&public_key, secret);
derive_near_implicit_account_id(&mapped_key.public_key())
derive_near_implicit_account_id(mapped_key.public_key().unwrap_as_ed25519())
}
AccountType::EthImplicitAccount => account_id.clone(),
AccountType::NamedAccount => account_id.clone(),
Expand Down
2 changes: 1 addition & 1 deletion tools/mirror/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1008,7 +1008,7 @@ impl<T: ChainAccess> TxMirror<T> {
{
let public_key =
PublicKey::from_near_implicit_account(&target_account)
.expect("must be implicit");
.expect("must be near-implicit");
nonce_updates.insert((target_account, public_key));
}
}
Expand Down

0 comments on commit cb1a914

Please sign in to comment.