Skip to content

Commit

Permalink
Add AccountType enum
Browse files Browse the repository at this point in the history
  • Loading branch information
staffik committed Oct 23, 2023
1 parent 3e47bf0 commit 7f138a4
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 29 deletions.
25 changes: 18 additions & 7 deletions core/account-id/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ pub use errors::{ParseAccountError, ParseErrorKind};
#[derive(Eq, Ord, Hash, Clone, Debug, PartialEq, PartialOrd)]
pub struct AccountId(Box<str>);

pub enum AccountType {
NamedAccount,
NearImplicitAccount,
EthImplicitAccount,
}

impl AccountId {
/// Shortest valid length for a NEAR Account ID.
pub const MIN_LEN: usize = 2;
Expand Down Expand Up @@ -127,7 +133,7 @@ impl AccountId {
/// assert!(!alice_app.is_sub_account_of(&near_tla));
/// ```
pub fn is_sub_account_of(&self, parent: &AccountId) -> bool {
// TODO must be !self.is_ximplicit() ?
// TODO what if this account type is EthImplicitAccount ?
self.strip_suffix(parent.as_str())
.and_then(|s| s.strip_suffix('.'))
.map_or(false, |s| !s.contains('.'))
Expand All @@ -144,14 +150,14 @@ impl AccountId {
/// use near_account_id::AccountId;
///
/// let alice: AccountId = "alice.near".parse().unwrap();
/// assert!(!alice.is_eth());
/// assert!(!alice.is_eth_implicit());
///
/// let rando = "b794f5eA0ba39494ce839613FFfba74279579268"
/// .parse::<AccountId>()
/// .unwrap();
/// assert!(rando.is_eth());
/// assert!(rando.is_eth_implicit());
/// ```
pub fn is_eth(&self) -> bool {
pub fn is_eth_implicit(&self) -> bool {
self.len() == 40
&& self.as_bytes().iter().all(|b| matches!(b, b'a'..=b'f' | b'A'..=b'F' | b'0'..=b'9'))
}
Expand All @@ -177,9 +183,14 @@ impl AccountId {
self.len() == 64 && self.as_bytes().iter().all(|b| matches!(b, b'a'..=b'f' | b'0'..=b'9'))
}

/// Returns `true` if this `AccountId` is either NEAR implicit address or ETH-format address.
pub fn is_ximplicit(&self) -> bool {
self.is_near_implicit() || self.is_eth()
pub fn get_account_type(&self) -> AccountType {
if self.is_eth_implicit() {
return AccountType::EthImplicitAccount;
}
if self.is_near_implicit() {
return AccountType::NearImplicitAccount;
}
AccountType::NamedAccount
}

/// Returns `true` if this `AccountId` is the system account.
Expand Down
8 changes: 4 additions & 4 deletions core/primitives-core/src/runtime/fees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,12 +208,12 @@ impl StorageUsageConfig {
pub fn transfer_exec_fee(
cfg: &RuntimeFeesConfig,
is_receiver_implicit: bool,
is_receiver_eth: bool,
is_receiver_eth_implictit: bool,
) -> Gas {
let mut result = cfg.fee(ActionCosts::transfer).exec_fee();
if is_receiver_implicit {
result += cfg.fee(ActionCosts::create_account).exec_fee();
if !is_receiver_eth {
if !is_receiver_eth_implictit {
result += cfg.fee(ActionCosts::add_full_access_key).exec_fee();
}
}
Expand All @@ -224,12 +224,12 @@ pub fn transfer_send_fee(
cfg: &RuntimeFeesConfig,
sender_is_receiver: bool,
is_receiver_implicit: bool,
is_receiver_eth: bool,
is_receiver_eth_implictit: bool,
) -> 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 !is_receiver_eth {
if !is_receiver_eth_implictit {
result += cfg.fee(ActionCosts::add_full_access_key).send_fee(sender_is_receiver);
}
}
Expand Down
11 changes: 7 additions & 4 deletions runtime/near-vm-runner/src/logic/logic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use super::{StorageGetMode, ValuePtr};
use crate::config::Config;
use crate::ProfileDataV3;
use near_crypto::Secp256K1Signature;
use near_primitives_core::account::id::AccountType;
use near_primitives_core::config::ExtCosts::*;
use near_primitives_core::config::ViewConfig;
use near_primitives_core::config::{ActionCosts, ExtCosts};
Expand Down Expand Up @@ -1773,12 +1774,14 @@ 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.is_ximplicit();
let is_receiver_implicit = match receiver_id.get_account_type() {
AccountType::NearImplicitAccount | AccountType::EthImplicitAccount => self.config.implicit_account_creation,
AccountType::NamedAccount => false,
};
let send_fee =
transfer_send_fee(self.fees_config, sir, is_receiver_implicit, receiver_id.is_eth());
transfer_send_fee(self.fees_config, sir, is_receiver_implicit, receiver_id.is_eth_implicit());
let exec_fee =
transfer_exec_fee(self.fees_config, is_receiver_implicit, receiver_id.is_eth());
transfer_exec_fee(self.fees_config, is_receiver_implicit, receiver_id.is_eth_implicit());
let burn_gas = send_fee;
let use_gas = burn_gas.checked_add(exec_fee).ok_or(HostError::IntegerOverflow)?;
self.gas_counter.pay_action_accumulated(burn_gas, use_gas, ActionCosts::transfer)?;
Expand Down
13 changes: 11 additions & 2 deletions runtime/runtime/src/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use near_primitives::utils::create_random_seed;
use near_primitives::version::{
ProtocolFeature, ProtocolVersion, DELETE_KEY_STORAGE_USAGE_PROTOCOL_VERSION,
};
use near_primitives_core::account::id::AccountType;
use near_primitives_core::config::ActionCosts;
use near_store::{
get_access_key, get_code, remove_access_key, remove_account, set_access_key, set_code,
Expand Down Expand Up @@ -884,8 +885,12 @@ pub(crate) fn check_account_existence(
}
.into());
} else {
let is_implicit = match account_id.get_account_type() {
AccountType::NearImplicitAccount | AccountType::EthImplicitAccount => true,
AccountType::NamedAccount => false,
};
// TODO: this should be `config.implicit_account_creation`.
if config.wasm_config.implicit_account_creation && account_id.is_ximplicit() {
if config.wasm_config.implicit_account_creation && is_implicit {
// If the account doesn't exist and it's implicit, then you
// should only be able to create it using single transfer action.
// Because you should not be able to add another access key to the account in
Expand All @@ -904,9 +909,13 @@ pub(crate) fn check_account_existence(
}
Action::Transfer(_) => {
if account.is_none() {
let is_implicit = match account_id.get_account_type() {
AccountType::NearImplicitAccount | AccountType::EthImplicitAccount => true,
AccountType::NamedAccount => false,
};
return if config.wasm_config.implicit_account_creation
&& is_the_only_action
&& account_id.is_ximplicit()
&& is_implicit
&& !is_refund
{
// OK. It's implicit account creation.
Expand Down
17 changes: 11 additions & 6 deletions runtime/runtime/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use near_primitives::account::AccessKeyPermission;
use near_primitives::errors::IntegerOverflowError;
use near_primitives_core::account::id::AccountType;
use near_primitives_core::config::ActionCosts;
use num_bigint::BigUint;
use num_traits::cast::ToPrimitive;
Expand Down Expand Up @@ -96,13 +97,15 @@ pub fn total_send_fees(
}
Transfer(_) => {
// Account for implicit account creation
let is_receiver_implicit =
config.wasm_config.implicit_account_creation && receiver_id.is_ximplicit();
let is_receiver_implicit = match receiver_id.get_account_type() {
AccountType::NearImplicitAccount | AccountType::EthImplicitAccount => config.wasm_config.implicit_account_creation,
AccountType::NamedAccount => false,
};
transfer_send_fee(
fees,
sender_is_receiver,
is_receiver_implicit,
receiver_id.is_eth(),
receiver_id.is_eth_implicit(),
)
}
Stake(_) => fees.fee(ActionCosts::stake).send_fee(sender_is_receiver),
Expand Down Expand Up @@ -193,9 +196,11 @@ pub fn exec_fee(config: &RuntimeConfig, action: &Action, receiver_id: &AccountId
}
Transfer(_) => {
// Account for implicit account creation
let is_receiver_implicit =
config.wasm_config.implicit_account_creation && receiver_id.is_ximplicit();
transfer_exec_fee(fees, is_receiver_implicit, receiver_id.is_eth())
let is_receiver_implicit = match receiver_id.get_account_type() {
AccountType::NearImplicitAccount | AccountType::EthImplicitAccount => config.wasm_config.implicit_account_creation,
AccountType::NamedAccount => false,
};
transfer_exec_fee(fees, is_receiver_implicit, receiver_id.is_eth_implicit())
}
Stake(_) => fees.fee(ActionCosts::stake).exec_fee(),
AddKey(add_key_action) => match &add_key_action.access_key.permission {
Expand Down
10 changes: 6 additions & 4 deletions tools/mirror/src/genesis.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use near_primitives::state_record::StateRecord;
use near_primitives_core::account::{AccessKey, AccessKeyPermission};
use near_primitives_core::account::{AccessKey, AccessKeyPermission, id::AccountType};
use serde::ser::{SerializeSeq, Serializer};
use std::collections::HashSet;
use std::fs::File;
Expand Down Expand Up @@ -35,9 +35,11 @@ pub fn map_records<P: AsRef<Path>>(
public_key: replacement.public_key(),
access_key: access_key.clone(),
};
if !account_id.is_ximplicit()
&& access_key.permission == AccessKeyPermission::FullAccess
{
let is_implicit = match account_id.get_account_type() {
AccountType::NearImplicitAccount | AccountType::EthImplicitAccount => true,
AccountType::NamedAccount => false,
};
if !is_implicit && access_key.permission == AccessKeyPermission::FullAccess {
has_full_key.insert(account_id.clone());
}
// TODO: would be nice for stream_records_from_file() to let you return early on error so
Expand Down
8 changes: 6 additions & 2 deletions tools/mirror/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use near_primitives::views::{
ExecutionOutcomeWithIdView, ExecutionStatusView, QueryRequest, QueryResponseKind,
SignedTransactionView,
};
use near_primitives_core::account::{AccessKey, AccessKeyPermission};
use near_primitives_core::account::{AccessKey, AccessKeyPermission, id::AccountType};
use near_primitives_core::types::{Nonce, ShardId};
use nearcore::config::NearConfig;
use rocksdb::DB;
Expand Down Expand Up @@ -989,7 +989,11 @@ impl<T: ChainAccess> TxMirror<T> {
actions.push(Action::DeleteKey(Box::new(DeleteKeyAction { public_key })));
}
Action::Transfer(_) => {
if tx.receiver_id().is_ximplicit() && source_actions.len() == 1 {
let is_receiver_implicit = match tx.receiver_id().get_account_type() {
AccountType::NearImplicitAccount | AccountType::EthImplicitAccount => true,
AccountType::NamedAccount => false,
};
if is_receiver_implicit && source_actions.len() == 1 {
let target_account =
crate::key_mapping::map_account(tx.receiver_id(), self.secret.as_ref());
if !account_exists(&self.target_view_client, &target_account)
Expand Down

0 comments on commit 7f138a4

Please sign in to comment.