Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support external account provider #75

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions frame/ethereum/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ impl AddressMapping<AccountId32> for HashedAddressMapping {
}

impl pallet_evm::Config for Test {
type AccountProvider = pallet_evm::NativeSystemAccountProvider<Self>;
type FeeCalculator = FixedGasPrice;
type GasWeightMapping = pallet_evm::FixedGasWeightMapping<Self>;
type WeightPerGas = WeightPerGas;
Expand Down
4 changes: 2 additions & 2 deletions frame/evm/precompile/dispatch/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ impl<T, DispatchValidator, DecodeLimit> Precompile for Dispatch<T, DispatchValid
where
T: pallet_evm::Config,
T::RuntimeCall: Dispatchable<PostInfo = PostDispatchInfo> + GetDispatchInfo + Decode,
<T::RuntimeCall as Dispatchable>::RuntimeOrigin: From<Option<T::AccountId>>,
DispatchValidator: DispatchValidateT<T::AccountId, T::RuntimeCall>,
<T::RuntimeCall as Dispatchable>::RuntimeOrigin: From<Option<<<T as pallet_evm::Config>::AccountProvider as pallet_evm::AccountProvider>::AccountId>>,
DispatchValidator: DispatchValidateT<<<T as pallet_evm::Config>::AccountProvider as pallet_evm::AccountProvider>::AccountId, T::RuntimeCall>,
DecodeLimit: Get<u32>,
{
fn execute(handle: &mut impl PrecompileHandle) -> PrecompileResult {
Expand Down
5 changes: 3 additions & 2 deletions frame/evm/precompile/dispatch/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,15 @@ parameter_types! {
pub WeightPerGas: Weight = Weight::from_parts(20_000, 0);
}
impl pallet_evm::Config for Test {
type AccountProvider = pallet_evm::NativeSystemAccountProvider<Self>;
type FeeCalculator = FixedGasPrice;
type GasWeightMapping = pallet_evm::FixedGasWeightMapping<Self>;
type WeightPerGas = WeightPerGas;

type BlockHashMapping = pallet_evm::SubstrateBlockHashMapping<Self>;
type CallOrigin = EnsureAddressRoot<Self::AccountId>;
type CallOrigin = EnsureAddressRoot<<Self::AccountProvider as pallet_evm::AccountProvider>::AccountId>;

type WithdrawOrigin = EnsureAddressNever<Self::AccountId>;
type WithdrawOrigin = EnsureAddressNever<<Self::AccountProvider as pallet_evm::AccountProvider>::AccountId>;
type AddressMapping = IdentityAddressMapping;
type Currency = Balances;

Expand Down
63 changes: 45 additions & 18 deletions frame/evm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ use sp_std::{cmp::min, collections::btree_map::BTreeMap, vec::Vec};
use fp_account::AccountId20;
use fp_evm::GenesisAccount;
pub use fp_evm::{
Account, CallInfo, CreateInfo, ExecutionInfoV2 as ExecutionInfo, FeeCalculator,
Account, AccountProvider, CallInfo, CreateInfo, ExecutionInfoV2 as ExecutionInfo, FeeCalculator,
IsPrecompileResult, LinearCostPrecompile, Log, Precompile, PrecompileFailure, PrecompileHandle,
PrecompileOutput, PrecompileResult, PrecompileSet, TransactionValidationError, Vicinity,
};
Expand All @@ -120,6 +120,9 @@ pub mod pallet {

#[pallet::config]
pub trait Config: frame_system::Config {
/// Account info provider.
type AccountProvider: AccountProvider;

/// Calculator for current gas price.
type FeeCalculator: FeeCalculator;

Expand All @@ -135,12 +138,12 @@ pub mod pallet {
/// Allow the origin to call on behalf of given address.
type CallOrigin: EnsureAddressOrigin<Self::RuntimeOrigin>;
/// Allow the origin to withdraw on behalf of given address.
type WithdrawOrigin: EnsureAddressOrigin<Self::RuntimeOrigin, Success = Self::AccountId>;
type WithdrawOrigin: EnsureAddressOrigin<Self::RuntimeOrigin, Success = <Self::AccountProvider as AccountProvider>::AccountId>;

/// Mapping from address to account id.
type AddressMapping: AddressMapping<Self::AccountId>;
type AddressMapping: AddressMapping<<Self::AccountProvider as AccountProvider>::AccountId>;
/// Currency type for withdraw and balance storage.
type Currency: Currency<Self::AccountId> + Inspect<Self::AccountId>;
type Currency: Currency<<Self::AccountProvider as AccountProvider>::AccountId> + Inspect<<Self::AccountProvider as AccountProvider>::AccountId>;

/// The overarching event type.
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
Expand Down Expand Up @@ -537,7 +540,7 @@ pub mod pallet {
MAX_ACCOUNT_NONCE,
UniqueSaturatedInto::<usize>::unique_saturated_into(account.nonce),
) {
frame_system::Pallet::<T>::inc_account_nonce(&account_id);
T::AccountProvider::inc_account_nonce(&account_id);
}

T::Currency::deposit_creating(&account_id, account.balance.unique_saturated_into());
Expand Down Expand Up @@ -568,11 +571,11 @@ pub mod pallet {

/// Type alias for currency balance.
pub type BalanceOf<T> =
<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
<<T as Config>::Currency as Currency<<<T as Config>::AccountProvider as AccountProvider>::AccountId>>::Balance;

/// Type alias for negative imbalance during fees
type NegativeImbalanceOf<C, T> =
<C as Currency<<T as frame_system::Config>::AccountId>>::NegativeImbalance;
<C as Currency<<<T as Config>::AccountProvider as AccountProvider>::AccountId>>::NegativeImbalance;

#[derive(
Debug,
Expand Down Expand Up @@ -802,7 +805,7 @@ impl<T: Config> Pallet<T> {
// In theory, we can always have pre-EIP161 contracts, so we
// make sure the account nonce is at least one.
let account_id = T::AddressMapping::into_account_id(*address);
frame_system::Pallet::<T>::inc_account_nonce(&account_id);
T::AccountProvider::inc_account_nonce(&account_id);
}

<AccountCodes<T>>::remove(address);
Expand All @@ -825,7 +828,7 @@ impl<T: Config> Pallet<T> {

if !<AccountCodes<T>>::contains_key(address) {
let account_id = T::AddressMapping::into_account_id(address);
let _ = frame_system::Pallet::<T>::inc_sufficients(&account_id);
T::AccountProvider::create_account(&account_id);
}

// Update metadata.
Expand Down Expand Up @@ -866,7 +869,7 @@ impl<T: Config> Pallet<T> {
pub fn account_basic(address: &H160) -> (Account, frame_support::weights::Weight) {
let account_id = T::AddressMapping::into_account_id(*address);

let nonce = frame_system::Pallet::<T>::account_nonce(&account_id);
let nonce = T::AccountProvider::account_nonce(&account_id);
// keepalive `true` takes into account ExistentialDeposit as part of what's considered liquid balance.
let balance =
T::Currency::reducible_balance(&account_id, Preservation::Preserve, Fortitude::Polite);
Expand Down Expand Up @@ -923,17 +926,17 @@ pub struct EVMCurrencyAdapter<C, OU>(sp_std::marker::PhantomData<(C, OU)>);
impl<T, C, OU> OnChargeEVMTransaction<T> for EVMCurrencyAdapter<C, OU>
where
T: Config,
C: Currency<<T as frame_system::Config>::AccountId>,
C: Currency<<<T as Config>::AccountProvider as AccountProvider>::AccountId>,
C::PositiveImbalance: Imbalance<
<C as Currency<<T as frame_system::Config>::AccountId>>::Balance,
<C as Currency<<<T as Config>::AccountProvider as AccountProvider>::AccountId>>::Balance,
Opposite = C::NegativeImbalance,
>,
C::NegativeImbalance: Imbalance<
<C as Currency<<T as frame_system::Config>::AccountId>>::Balance,
<C as Currency<<<T as Config>::AccountProvider as AccountProvider>::AccountId>>::Balance,
Opposite = C::PositiveImbalance,
>,
OU: OnUnbalanced<NegativeImbalanceOf<C, T>>,
U256: UniqueSaturatedInto<<C as Currency<<T as frame_system::Config>::AccountId>>::Balance>,
U256: UniqueSaturatedInto<<C as Currency<<<T as Config>::AccountProvider as AccountProvider>::AccountId>>::Balance>,
{
// Kept type as Option to satisfy bound of Default
type LiquidityInfo = Option<NegativeImbalanceOf<C, T>>;
Expand Down Expand Up @@ -1017,10 +1020,10 @@ where
impl<T> OnChargeEVMTransaction<T> for ()
where
T: Config,
<T::Currency as Currency<<T as frame_system::Config>::AccountId>>::PositiveImbalance:
Imbalance<<T::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance, Opposite = <T::Currency as Currency<<T as frame_system::Config>::AccountId>>::NegativeImbalance>,
<T::Currency as Currency<<T as frame_system::Config>::AccountId>>::NegativeImbalance:
Imbalance<<T::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance, Opposite = <T::Currency as Currency<<T as frame_system::Config>::AccountId>>::PositiveImbalance>,
<T::Currency as Currency<<<T as Config>::AccountProvider as AccountProvider>::AccountId>>::PositiveImbalance:
Imbalance<<T::Currency as Currency<<<T as Config>::AccountProvider as AccountProvider>::AccountId>>::Balance, Opposite = <T::Currency as Currency<<<T as Config>::AccountProvider as AccountProvider>::AccountId>>::NegativeImbalance>,
<T::Currency as Currency<<<T as Config>::AccountProvider as AccountProvider>::AccountId>>::NegativeImbalance:
Imbalance<<T::Currency as Currency<<<T as Config>::AccountProvider as AccountProvider>::AccountId>>::Balance, Opposite = <T::Currency as Currency<<<T as Config>::AccountProvider as AccountProvider>::AccountId>>::PositiveImbalance>,
U256: UniqueSaturatedInto<BalanceOf<T>>,

{
Expand Down Expand Up @@ -1064,3 +1067,27 @@ impl<T> OnCreate<T> for Tuple {
)*)
}
}

/// Native system account provider that `frame_system` provides.
pub struct NativeSystemAccountProvider<T>(sp_std::marker::PhantomData<T>);

impl<T: frame_system::Config> AccountProvider for NativeSystemAccountProvider<T> {
type AccountId = T::AccountId;
type Nonce = T::Nonce;

fn account_nonce(who: &Self::AccountId) -> Self::Nonce {
frame_system::Pallet::<T>::account_nonce(&who)
}

fn inc_account_nonce(who: &Self::AccountId) {
frame_system::Pallet::<T>::inc_account_nonce(&who)
}

fn create_account(who: &Self::AccountId) {
let _ = frame_system::Pallet::<T>::inc_sufficients(&who);
}
fn remove_account(who: &Self::AccountId) {
let _ = frame_system::Pallet::<T>::dec_sufficients(&who);
}
}

5 changes: 3 additions & 2 deletions frame/evm/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,14 +130,15 @@ parameter_types! {
pub MockPrecompiles: MockPrecompileSet = MockPrecompileSet;
}
impl crate::Config for Test {
type AccountProvider = crate::NativeSystemAccountProvider<Self>;
type FeeCalculator = FixedGasPrice;
type GasWeightMapping = crate::FixedGasWeightMapping<Self>;
type WeightPerGas = WeightPerGas;

type BlockHashMapping = crate::SubstrateBlockHashMapping<Self>;
type CallOrigin = EnsureAddressRoot<Self::AccountId>;
type CallOrigin = EnsureAddressRoot<<Self::AccountProvider as crate::AccountProvider>::AccountId>;

type WithdrawOrigin = EnsureAddressNever<Self::AccountId>;
type WithdrawOrigin = EnsureAddressNever<<Self::AccountProvider as crate::AccountProvider>::AccountId>;
type AddressMapping = IdentityAddressMapping;
type Currency = Balances;

Expand Down
4 changes: 2 additions & 2 deletions frame/evm/src/runner/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ use fp_evm::{
use crate::{
runner::Runner as RunnerT, AccountCodes, AccountCodesMetadata, AccountStorages, AddressMapping,
BalanceOf, BlockHashMapping, Config, Error, Event, FeeCalculator, OnChargeEVMTransaction,
OnCreate, Pallet, RunnerError,
OnCreate, Pallet, RunnerError, AccountProvider,
};

#[cfg(feature = "forbid-evm-reentrancy")]
Expand Down Expand Up @@ -843,7 +843,7 @@ where

fn inc_nonce(&mut self, address: H160) -> Result<(), ExitError> {
let account_id = T::AddressMapping::into_account_id(address);
frame_system::Pallet::<T>::inc_account_nonce(&account_id);
T::AccountProvider::inc_account_nonce(&account_id);
Ok(())
}

Expand Down
2 changes: 1 addition & 1 deletion precompiles/src/precompile_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1086,7 +1086,7 @@ impl<R: pallet_evm::Config, P: PrecompileSetFragment> PrecompileSetBuilder<R, P>
}

/// Return the list of addresses contained in this PrecompileSet.
pub fn used_addresses() -> impl Iterator<Item = R::AccountId> {
pub fn used_addresses() -> impl Iterator<Item = <R::AccountProvider as pallet_evm::AccountProvider>::AccountId> {
Self::new()
.inner
.used_addresses()
Expand Down
41 changes: 41 additions & 0 deletions primitives/evm/src/account_provider.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//! Custom account provider logic.

use sp_runtime::traits::AtLeast32Bit;

/// The account provider interface abstraction layer.
///
/// Expose account related logic that `pallet_evm` required to control accounts existence
/// in the network and their transactions uniqueness. By default, the pallet operates native
/// system accounts records that `frame_system` provides.
///
/// The interface allow any custom account provider logic to be used instead of
/// just using `frame_system` account provider. The accounts records should store nonce value
/// for each account at least.
pub trait AccountProvider {
/// The account identifier type.
///
/// Represent the account itself in accounts records.
type AccountId;
/// Nonce type.
///
/// The number that helps to ensure that each transaction in the network is unique
/// for particular account.
type Nonce: AtLeast32Bit;

/// Creates a new account in accounts records.
///
/// The account associated with new created address EVM.
fn create_account(who: &Self::AccountId);
/// Removes an account from accounts records.
///
/// The account associated with removed address from EVM.
fn remove_account(who: &Self::AccountId);
/// Return current account nonce value.
///
/// Used to represent account basic information in EVM format.
fn account_nonce(who: &Self::AccountId) -> Self::Nonce;
/// Increment a particular account's nonce value.
///
/// Incremented with each new transaction submitted by the account.
fn inc_account_nonce(who: &Self::AccountId);
}
2 changes: 2 additions & 0 deletions primitives/evm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![deny(unused_crate_dependencies)]

mod account_provider;
mod precompile;
mod validation;

Expand All @@ -36,6 +37,7 @@ pub use evm::{
};

pub use self::{
account_provider::AccountProvider,
precompile::{
Context, ExitError, ExitRevert, ExitSucceed, IsPrecompileResult, LinearCostPrecompile,
Precompile, PrecompileFailure, PrecompileHandle, PrecompileOutput, PrecompileResult,
Expand Down
1 change: 1 addition & 0 deletions template/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ parameter_types! {
}

impl pallet_evm::Config for Runtime {
type AccountProvider = pallet_evm::NativeSystemAccountProvider<Self>;
type FeeCalculator = BaseFee;
type GasWeightMapping = pallet_evm::FixedGasWeightMapping<Self>;
type WeightPerGas = WeightPerGas;
Expand Down