Skip to content

Commit

Permalink
Feat(Engine): Introduce pausability for precompiles and the concept o…
Browse files Browse the repository at this point in the history
…f permissions for such action.

Permissions are hardcoded for a single NEAR account.
  • Loading branch information
RomanHodulak committed Sep 2, 2022
1 parent 20062d6 commit 5381d5e
Show file tree
Hide file tree
Showing 24 changed files with 661 additions and 80 deletions.
25 changes: 25 additions & 0 deletions Cargo.lock

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

15 changes: 9 additions & 6 deletions engine-precompiles/src/alt_bn256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,11 @@ fn read_point(input: &[u8], pos: usize) -> Result<bn::G1, ExitError> {
})
}

pub(super) struct Bn256Add<HF: HardFork>(PhantomData<HF>);
#[derive(Default)]
pub struct Bn256Add<HF: HardFork>(PhantomData<HF>);

impl<HF: HardFork> Bn256Add<HF> {
pub(super) const ADDRESS: Address = super::make_address(0, 6);
pub const ADDRESS: Address = super::make_address(0, 6);

pub fn new() -> Self {
Self(Default::default())
Expand Down Expand Up @@ -269,10 +270,11 @@ impl Precompile for Bn256Add<Istanbul> {
}
}

pub(super) struct Bn256Mul<HF: HardFork>(PhantomData<HF>);
#[derive(Default)]
pub struct Bn256Mul<HF: HardFork>(PhantomData<HF>);

impl<HF: HardFork> Bn256Mul<HF> {
pub(super) const ADDRESS: Address = super::make_address(0, 7);
pub const ADDRESS: Address = super::make_address(0, 7);

pub fn new() -> Self {
Self(Default::default())
Expand Down Expand Up @@ -374,10 +376,11 @@ impl Precompile for Bn256Mul<Istanbul> {
}
}

pub(super) struct Bn256Pair<HF: HardFork>(PhantomData<HF>);
#[derive(Default)]
pub struct Bn256Pair<HF: HardFork>(PhantomData<HF>);

impl<HF: HardFork> Bn256Pair<HF> {
pub(super) const ADDRESS: Address = super::make_address(0, 8);
pub const ADDRESS: Address = super::make_address(0, 8);

pub fn new() -> Self {
Self(Default::default())
Expand Down
4 changes: 2 additions & 2 deletions engine-precompiles/src/blake2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,10 @@ fn f(mut h: [u64; 8], m: [u64; 16], t: [u64; 2], f: bool, rounds: u32) -> Vec<u8
result
}

pub(super) struct Blake2F;
pub struct Blake2F;

impl Blake2F {
pub(super) const ADDRESS: Address = crate::make_address(0, 9);
pub const ADDRESS: Address = crate::make_address(0, 9);
}

impl Precompile for Blake2F {
Expand Down
4 changes: 2 additions & 2 deletions engine-precompiles/src/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ mod consts {
pub struct SHA256;

impl SHA256 {
pub(super) const ADDRESS: Address = super::make_address(0, 2);
pub const ADDRESS: Address = super::make_address(0, 2);
}

impl Precompile for SHA256 {
Expand Down Expand Up @@ -91,7 +91,7 @@ impl Precompile for SHA256 {
pub struct RIPEMD160;

impl RIPEMD160 {
pub(super) const ADDRESS: Address = super::make_address(0, 3);
pub const ADDRESS: Address = super::make_address(0, 3);

#[cfg(not(feature = "contract"))]
fn internal_impl(input: &[u8]) -> [u8; 20] {
Expand Down
2 changes: 1 addition & 1 deletion engine-precompiles/src/identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ mod consts {
pub struct Identity;

impl Identity {
pub(super) const ADDRESS: Address = super::make_address(0, 4);
pub const ADDRESS: Address = super::make_address(0, 4);
}

impl Precompile for Identity {
Expand Down
19 changes: 17 additions & 2 deletions engine-precompiles/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ use crate::xcc::CrossContractCall;
use aurora_engine_sdk::env::Env;
use aurora_engine_sdk::io::IO;
use aurora_engine_sdk::promise::ReadOnlyPromiseHandler;
use aurora_engine_types::{account_id::AccountId, types::Address, vec, BTreeMap, Box};
use aurora_engine_types::{account_id::AccountId, types::Address, vec, BTreeMap, BTreeSet, Box};
use evm::backend::Log;
use evm::executor::{
self,
stack::{PrecompileFailure, PrecompileHandle},
};
use evm::{Context, ExitError, ExitSucceed};
use evm::{Context, ExitError, ExitFatal, ExitSucceed};
use promise_result::PromiseResult;
use xcc::cross_contract_call;

Expand Down Expand Up @@ -112,6 +112,13 @@ impl HardFork for Berlin {}

pub struct Precompiles<'a, I, E, H> {
pub all_precompiles: prelude::BTreeMap<Address, AllPrecompiles<'a, I, E, H>>,
pub paused_precompiles: prelude::BTreeSet<Address>,
}

impl<'a, I, E, H> Precompiles<'a, I, E, H> {
fn is_paused(&self, address: prelude::H160) -> bool {
self.paused_precompiles.contains(&Address::new(address))
}
}

impl<'a, I: IO + Copy, E: Env, H: ReadOnlyPromiseHandler> executor::stack::PrecompileSet
Expand All @@ -123,6 +130,12 @@ impl<'a, I: IO + Copy, E: Env, H: ReadOnlyPromiseHandler> executor::stack::Preco
) -> Option<Result<executor::stack::PrecompileOutput, PrecompileFailure>> {
let address = handle.code_address();

if self.is_paused(address) {
return Some(Err(PrecompileFailure::Fatal {
exit_status: ExitFatal::Other(prelude::Cow::Borrowed("ERR_PAUSED")),
}));
}

let result = match self.all_precompiles.get(&Address::new(address))? {
AllPrecompiles::ExitToNear(p) => process_precompile(p, handle),
AllPrecompiles::ExitToEthereum(p) => process_precompile(p, handle),
Expand All @@ -132,6 +145,7 @@ impl<'a, I: IO + Copy, E: Env, H: ReadOnlyPromiseHandler> executor::stack::Preco
AllPrecompiles::CrossContractCall(p) => process_handle_based_precompile(p, handle),
AllPrecompiles::Generic(p) => process_precompile(p.as_ref(), handle),
};

Some(result.and_then(|output| post_process(output, handle)))
}

Expand Down Expand Up @@ -354,6 +368,7 @@ impl<'a, I: IO + Copy, E: Env, H: ReadOnlyPromiseHandler> Precompiles<'a, I, E,

Self {
all_precompiles: generic_precompiles,
paused_precompiles: BTreeSet::new(),
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions engine-precompiles/src/modexp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ use crate::{
use evm::{Context, ExitError};
use num::{BigUint, Integer};

pub(super) struct ModExp<HF: HardFork>(PhantomData<HF>);
#[derive(Default)]
pub struct ModExp<HF: HardFork>(PhantomData<HF>);

impl<HF: HardFork> ModExp<HF> {
pub(super) const ADDRESS: Address = super::make_address(0, 5);
pub const ADDRESS: Address = super::make_address(0, 5);

pub fn new() -> Self {
Self(Default::default())
Expand Down
2 changes: 1 addition & 1 deletion engine-precompiles/src/secp256k1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ fn internal_impl(hash: H256, signature: &[u8]) -> Result<Address, ExitError> {
pub struct ECRecover;

impl ECRecover {
pub(super) const ADDRESS: Address = super::make_address(0, 1);
pub const ADDRESS: Address = super::make_address(0, 1);
}

impl Precompile for ECRecover {
Expand Down
19 changes: 19 additions & 0 deletions engine-standalone-storage/src/sync/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use aurora_engine::pausables::PausedPrecompilesKeeper;
use aurora_engine::{connector, engine, parameters::SubmitResult, xcc};
use aurora_engine_sdk::env::{self, Env, DEFAULT_PREPAID_GAS};
use aurora_engine_types::{
Expand Down Expand Up @@ -388,6 +389,24 @@ fn non_submit_execute<'db>(
TransactionKind::Unknown => None,
// Not handled in this function; is handled by the general `execute_transaction` function
TransactionKind::Submit(_) => unreachable!(),
TransactionKind::PausePrecompiles(args) => {
let precompiles_to_pause = args.paused_mask;

let mut pauser = engine::get_pauser(&io).expect("Unable to read precompiles pauser");
pauser.pause_precompiles(precompiles_to_pause);
engine::set_pauser(&mut io, pauser);

None
}
TransactionKind::ResumePrecompiles(args) => {
let precompiles_to_pause = args.paused_mask;

let mut pauser = engine::get_pauser(&io).expect("Unable to read precompiles pauser");
pauser.resume_precompiles(precompiles_to_pause);
engine::set_pauser(&mut io, pauser);

None
}
};

Ok(result)
Expand Down
17 changes: 17 additions & 0 deletions engine-standalone-storage/src/sync/types.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::Storage;
use aurora_engine::parameters;
use aurora_engine::parameters::PausePrecompilesCallArgs;
use aurora_engine::xcc::AddressVersionUpdateArgs;
use aurora_engine_transactions::{EthTransactionKind, NormalizedEthTransaction};
use aurora_engine_types::account_id::AccountId;
Expand Down Expand Up @@ -77,6 +78,10 @@ pub enum TransactionKind {
Submit(EthTransactionKind),
/// Ethereum transaction triggered by a NEAR account
Call(parameters::CallArgs),
/// Administrative method that makes a subset of precompiles paused
PausePrecompiles(PausePrecompilesCallArgs),
/// Administrative method that resumes previously paused subset of precompiles
ResumePrecompiles(PausePrecompilesCallArgs),
/// Input here represents the EVM code used to create the new contract
Deploy(Vec<u8>),
/// New bridged token
Expand Down Expand Up @@ -332,6 +337,8 @@ impl TransactionKind {
Self::no_evm_execution("factory_set_wnear_address")
}
TransactionKind::Unknown => Self::no_evm_execution("unknown"),
Self::PausePrecompiles(_) => Self::no_evm_execution("pause_precompiles"),
Self::ResumePrecompiles(_) => Self::no_evm_execution("resume_precompiles"),
}
}

Expand Down Expand Up @@ -494,6 +501,8 @@ enum BorshableTransactionKind<'a> {
FactoryUpdate(Cow<'a, Vec<u8>>),
FactoryUpdateAddressVersion(Cow<'a, AddressVersionUpdateArgs>),
FactorySetWNearAddress(types::Address),
PausePrecompiles(Cow<'a, parameters::PausePrecompilesCallArgs>),
ResumePrecompiles(Cow<'a, parameters::PausePrecompilesCallArgs>),
Unknown,
}

Expand Down Expand Up @@ -533,6 +542,8 @@ impl<'a> From<&'a TransactionKind> for BorshableTransactionKind<'a> {
Self::FactorySetWNearAddress(*address)
}
TransactionKind::Unknown => Self::Unknown,
TransactionKind::PausePrecompiles(x) => Self::PausePrecompiles(Cow::Borrowed(x)),
TransactionKind::ResumePrecompiles(x) => Self::ResumePrecompiles(Cow::Borrowed(x)),
}
}
}
Expand Down Expand Up @@ -584,6 +595,12 @@ impl<'a> TryFrom<BorshableTransactionKind<'a>> for TransactionKind {
Ok(Self::FactorySetWNearAddress(address))
}
BorshableTransactionKind::Unknown => Ok(Self::Unknown),
BorshableTransactionKind::PausePrecompiles(x) => {
Ok(Self::PausePrecompiles(x.into_owned()))
}
BorshableTransactionKind::ResumePrecompiles(x) => {
Ok(Self::ResumePrecompiles(x.into_owned()))
}
}
}
}
3 changes: 2 additions & 1 deletion engine-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,14 @@ rlp = { version = "0.5.0", default-features = false }
base64 = "0.13.0"
bstr = "0.2"
byte-slice-cast = { version = "1.0", default-features = false }
ethabi = "17.1"
ethabi = "17.1"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
hex = { version = "0.4.3", default-features = false }
near-sdk = { git = "https://github.com/aurora-is-near/near-sdk-rs.git", rev = "7a3fa3fbff84b712050370d840297df38c925d2d" }
near-sdk-sim = { git = "https://github.com/aurora-is-near/near-sdk-rs.git", rev = "7a3fa3fbff84b712050370d840297df38c925d2d" }
near-crypto = { git = "https://github.com/birchmd/nearcore.git", rev = "980bc48dc02878fea1e0dbc5812ae7de49f12dda" }
near-vm-errors = { git = "https://github.com/birchmd/nearcore.git", rev = "980bc48dc02878fea1e0dbc5812ae7de49f12dda" }
near-vm-runner = { git = "https://github.com/birchmd/nearcore.git", rev = "980bc48dc02878fea1e0dbc5812ae7de49f12dda", default-features = false, features = [ "wasmer2_vm", "protocol_feature_alt_bn128" ] }
near-vm-logic = { git = "https://github.com/birchmd/nearcore.git", rev = "980bc48dc02878fea1e0dbc5812ae7de49f12dda", default-features = false, features = [ "protocol_feature_alt_bn128" ] }
near-primitives-core = { git = "https://github.com/birchmd/nearcore.git", rev = "980bc48dc02878fea1e0dbc5812ae7de49f12dda", features = [ "protocol_feature_alt_bn128" ] }
Expand Down
10 changes: 8 additions & 2 deletions engine-tests/src/test_utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ pub fn origin() -> String {
pub(crate) const SUBMIT: &str = "submit";
pub(crate) const CALL: &str = "call";
pub(crate) const DEPLOY_ERC20: &str = "deploy_erc20_token";
pub(crate) const PAUSE_PRECOMPILES: &str = "pause_precompiles";
pub(crate) const RESUME_PRECOMPILES: &str = "resume_precompiles";

pub(crate) mod erc20;
pub(crate) mod exit_precompile;
Expand Down Expand Up @@ -223,7 +225,11 @@ impl AuroraRunner {

if let Some(standalone_runner) = &mut self.standalone_runner {
if maybe_error.is_none()
&& (method_name == SUBMIT || method_name == CALL || method_name == DEPLOY_ERC20)
&& (method_name == SUBMIT
|| method_name == CALL
|| method_name == DEPLOY_ERC20
|| method_name == PAUSE_PRECOMPILES
|| method_name == RESUME_PRECOMPILES)
{
standalone_runner
.submit_raw(method_name, &self.context, &self.promise_results)
Expand Down Expand Up @@ -582,7 +588,7 @@ impl Default for AuroraRunner {

/// Wrapper around `ProfileData` to still include the wasm gas usage
/// (which was removed in https://github.com/near/nearcore/pull/4438).
#[derive(Default, Clone)]
#[derive(Debug, Default, Clone)]
pub(crate) struct ExecutionProfile {
pub host_breakdown: ProfileData,
wasm_gas: u64,
Expand Down
Loading

0 comments on commit 5381d5e

Please sign in to comment.