Skip to content

Commit

Permalink
Precompiles uses StorageMap; add struct PrecompileLabel; add_precompi…
Browse files Browse the repository at this point in the history
…le + remove_precompile dispatchables
  • Loading branch information
bernardoaraujor committed Mar 9, 2023
1 parent 71e440d commit 584f5a2
Show file tree
Hide file tree
Showing 10 changed files with 218 additions and 34 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions frame/evm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ repository = { workspace = true }
targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
serde = { workspace = true, default-features = false }
environmental = { workspace = true, optional = true }
evm = { workspace = true, features = ["with-codec"] }
hex = { version = "0.4.3", default-features = false, features = ["alloc"] }
Expand Down Expand Up @@ -40,6 +41,7 @@ pallet-evm-precompile-simple = { workspace = true }
[features]
default = ["std"]
std = [
"serde/std",
"environmental?/std",
"evm/std",
"evm/with-serde",
Expand Down
1 change: 1 addition & 0 deletions frame/evm/precompile/dispatch/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ impl pallet_evm::Config for Test {
type OnChargeTransaction = ();
type OnCreate = ();
type FindAuthor = FindAuthorTruncated;
type PrecompileModifierOrigin = frame_system::EnsureRoot<Self::AccountId>;
}

pub(crate) struct MockHandle {
Expand Down
68 changes: 56 additions & 12 deletions frame/evm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ use frame_support::{
};
use frame_system::RawOrigin;
use impl_trait_for_tuples::impl_for_tuples;
use scale_codec::{Decode, Encode};
use scale_info::TypeInfo;
use sp_core::{Hasher, H160, H256, U256};
use sp_runtime::{
traits::{BadOrigin, Saturating, UniqueSaturatedInto, Zero},
Expand Down Expand Up @@ -155,6 +157,9 @@ pub mod pallet {
/// Find author for the current block.
type FindAuthor: FindAuthor<H160>;

/// Origin allowed to modify Precompiles
type PrecompileModifierOrigin: EnsureOrigin<Self::RuntimeOrigin>;

/// EVM config used in the module.
fn config() -> &'static EvmConfig {
&LONDON_CONFIG
Expand Down Expand Up @@ -404,6 +409,37 @@ pub mod pallet {
pays_fee: Pays::No,
})
}

/// Add a precompile to storage
#[pallet::call_index(4)]
#[pallet::weight(T::DbWeight::get().reads_writes(0, 1))]
pub fn add_precompile(
origin: OriginFor<T>,
address: H160,
label: PrecompileLabel,
) -> DispatchResult {
T::PrecompileModifierOrigin::ensure_origin(origin)?;

Self::do_add_precompile(&address, label);

Ok(())
}

/// Remove a precompile from storage
#[pallet::call_index(5)]
#[pallet::weight(T::DbWeight::get().reads_writes(0, 1))]
pub fn remove_precompile(
origin: OriginFor<T>,
address: H160,
) -> DispatchResult {
T::PrecompileModifierOrigin::ensure_origin(origin)?;

ensure!(Precompiles::<T>::contains_key(address), Error::<T>::PrecompileDoesNotExist);

Self::do_remove_precompile(&address);

Ok(())
}
}

#[pallet::event]
Expand Down Expand Up @@ -445,6 +481,8 @@ pub mod pallet {
Reentrancy,
/// EIP-3607,
TransactionMustComeFromEOA,
/// Precompile does not exist in storage
PrecompileDoesNotExist,
}

impl<T> From<InvalidEvmTransactionError> for Error<T> {
Expand All @@ -467,7 +505,7 @@ pub mod pallet {
#[cfg_attr(feature = "std", derive(Default))]
pub struct GenesisConfig {
pub accounts: std::collections::BTreeMap<H160, GenesisAccount>,
pub precompiles: Vec<(Vec<u8>, H160)>,
pub precompiles: Vec<(H160, PrecompileLabel)>,
}

#[pallet::genesis_build]
Expand Down Expand Up @@ -499,8 +537,8 @@ pub mod pallet {
}
}

for (label, address) in &self.precompiles {
Pallet::<T>::add_precompile(label, address);
for (address, label) in &self.precompiles {
Pallet::<T>::do_add_precompile(address, label.clone());
}
}
}
Expand All @@ -515,15 +553,21 @@ pub mod pallet {
StorageDoubleMap<_, Blake2_128Concat, H160, Blake2_128Concat, H256, H256, ValueQuery>;

/// Allows for precompiles to have arbitrary addresses, potentially more than one.
/// `k1`: precompile label, e.g.: `b"Sha3FIPS256".to_vec()`
/// `k2`: precompile address
///
/// `key`: precompile `H160` address
/// `value`: precompile label, e.g.: `PrecompileLabel { label: b"Sha3FIPS256".to_vec() }`

/// Please note that adding a new precompile label here is not enough to guarantee its execution
/// It is also required to list the new label on the implementation of `PrecompileSet::execute()`
/// It is also required to list new labels on the implementation of `PrecompileSet::execute()`
#[pallet::storage]
#[pallet::getter(fn precompiles)]
pub type Precompiles<T: Config> =
StorageDoubleMap<_, Blake2_128Concat, Vec<u8>, Blake2_128Concat, H160, (), OptionQuery>;
StorageMap<_, Blake2_128Concat, H160, PrecompileLabel, ValueQuery>;
}

#[derive(Decode, Encode, Default, TypeInfo, Clone, PartialEq, Debug)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
pub struct PrecompileLabel {
pub label: Vec<u8>,
}

/// Type alias for currency balance.
Expand Down Expand Up @@ -688,13 +732,13 @@ static LONDON_CONFIG: EvmConfig = EvmConfig::london();

impl<T: Config> Pallet<T> {
/// Add a precompile to storage
pub fn add_precompile(label: &Vec<u8>, address: &H160) {
Precompiles::<T>::set(label, address, Some(()));
pub fn do_add_precompile(address: &H160, label: PrecompileLabel) {
Precompiles::<T>::set(address, label);
}

/// Remove a precompile from storage
pub fn remove_precompile(label: &Vec<u8>, address: &H160) {
Precompiles::<T>::remove(label, address);
pub fn do_remove_precompile(address: &H160) {
Precompiles::<T>::remove(address);
}

/// Check whether an account is empty.
Expand Down
1 change: 1 addition & 0 deletions frame/evm/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ impl crate::Config for Test {
type OnChargeTransaction = ();
type OnCreate = ();
type FindAuthor = FindAuthorTruncated;
type PrecompileModifierOrigin = frame_system::EnsureRoot<Self::AccountId>;
}

/// Exemple PrecompileSet with only Identity precompile.
Expand Down
25 changes: 25 additions & 0 deletions frame/evm/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -620,3 +620,28 @@ fn eip3607_transaction_from_precompile_should_fail() {
}
});
}

#[test]
fn precompile_storage_works() {
new_test_ext().execute_with(|| {
let origin = RuntimeOrigin::root();
let address = H160::from_low_u64_be(1);

let mut read_precompile = EVM::precompiles(address);
assert_eq!(read_precompile, PrecompileLabel::default());

let label = PrecompileLabel {
label: b"ECRecover".to_vec(),
};

assert_ok!(EVM::add_precompile(origin.clone(), address, label.clone()));

read_precompile = EVM::precompiles(address);
assert_eq!(read_precompile, label);

assert_ok!(EVM::remove_precompile(origin, address));

read_precompile = EVM::precompiles(address);
assert_eq!(read_precompile, PrecompileLabel::default());
});
}
1 change: 1 addition & 0 deletions template/node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ frame-system = { workspace = true }
pallet-transaction-payment = { workspace = true }

# Frontier
pallet-evm = { workspace = true }
fc-cli = { workspace = true }
fc-consensus = { workspace = true }
fc-db = { workspace = true }
Expand Down
51 changes: 44 additions & 7 deletions template/node/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ use frontier_template_runtime::{
AccountId, EnableManualSeal, GenesisConfig, Signature, WASM_BINARY,
};

use pallet_evm::PrecompileLabel;

// The URL for the telemetry server.
// const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/";

Expand Down Expand Up @@ -252,14 +254,49 @@ fn testnet_genesis(
},
precompiles: vec![
// Ethereum precompiles :
(b"ECRecover".to_vec(), H160::from_low_u64_be(1)),
(b"Sha256".to_vec(), H160::from_low_u64_be(2)),
(b"Ripemd160".to_vec(), H160::from_low_u64_be(3)),
(b"Identity".to_vec(), H160::from_low_u64_be(4)),
(b"Modexp".to_vec(), H160::from_low_u64_be(5)),
(
H160::from_low_u64_be(1),
PrecompileLabel {
label: b"ECRecover".to_vec(),
},
),
(
H160::from_low_u64_be(2),
PrecompileLabel {
label: b"Sha256".to_vec(),
},
),
(
H160::from_low_u64_be(3),
PrecompileLabel {
label: b"Ripemd160".to_vec(),
},
),
(
H160::from_low_u64_be(4),
PrecompileLabel {
label: b"Identity".to_vec(),
},
),
(
H160::from_low_u64_be(5),
PrecompileLabel {
label: b"Modexp".to_vec(),
},
),
// Non-Frontier specific nor Ethereum precompiles :
(b"Sha3FIPS256".to_vec(), H160::from_low_u64_be(1024)),
(b"Sha3FIPS256".to_vec(), H160::from_low_u64_be(1025)),
(
H160::from_low_u64_be(1024),
PrecompileLabel {
label: b"Sha3FIPS256".to_vec(),
},
),
(
H160::from_low_u64_be(1025),
PrecompileLabel {
label: b"Sha3FIPS256".to_vec(),
},
),
],
},
ethereum: Default::default(),
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 @@ -343,6 +343,7 @@ impl pallet_evm::Config for Runtime {
type OnChargeTransaction = ();
type OnCreate = ();
type FindAuthor = FindAuthorTruncated<Aura>;
type PrecompileModifierOrigin = frame_system::EnsureRoot<Self::AccountId>;
}

parameter_types! {
Expand Down
Loading

0 comments on commit 584f5a2

Please sign in to comment.