Skip to content

Commit

Permalink
pallet-evm: add support for tuple-based precompile declarations (#6681)
Browse files Browse the repository at this point in the history
* pallet-evm: add support for tuple-based precompile declarations

* Add missing license header

* Switch to use impl_for_tuples

* Remove unnecessary impl for ()
  • Loading branch information
goldoneen committed Jul 27, 2020
1 parent b07e24b commit 506c806
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 24 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ primitive-types = { version = "0.7.0", default-features = false, features = ["rl
rlp = { version = "0.4", default-features = false }
evm = { version = "0.17", default-features = false }
sha3 = { version = "0.8", default-features = false }
impl-trait-for-tuples = "0.1"

[features]
default = ["std"]
Expand Down
26 changes: 2 additions & 24 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@
#![cfg_attr(not(feature = "std"), no_std)]

mod backend;
mod precompiles;
mod tests;

pub use crate::precompiles::{Precompile, Precompiles};
pub use crate::backend::{Account, Log, Vicinity, Backend};

use sp_std::vec::Vec;
Expand Down Expand Up @@ -175,30 +177,6 @@ impl<H: Hasher<Out=H256>> AddressMapping<AccountId32> for HashedAddressMapping<H
}
}

/// Custom precompiles to be used by EVM engine.
pub trait Precompiles {
/// Try to execute the code address as precompile. If the code address is not
/// a precompile or the precompile is not yet available, return `None`.
/// Otherwise, calculate the amount of gas needed with given `input` and
/// `target_gas`. Return `Some(Ok(status, output, gas_used))` if the execution
/// is successful. Otherwise return `Some(Err(_))`.
fn execute(
address: H160,
input: &[u8],
target_gas: Option<usize>
) -> Option<core::result::Result<(ExitSucceed, Vec<u8>, usize), ExitError>>;
}

impl Precompiles for () {
fn execute(
_address: H160,
_input: &[u8],
_target_gas: Option<usize>
) -> Option<core::result::Result<(ExitSucceed, Vec<u8>, usize), ExitError>> {
None
}
}

/// Substrate system chain ID.
pub struct SystemChainId;

Expand Down
69 changes: 69 additions & 0 deletions src/precompiles.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// This file is part of Substrate.

// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use sp_std::vec::Vec;
use sp_core::H160;
use evm::{ExitError, ExitSucceed};
use impl_trait_for_tuples::impl_for_tuples;

/// Custom precompiles to be used by EVM engine.
pub trait Precompiles {
/// Try to execute the code address as precompile. If the code address is not
/// a precompile or the precompile is not yet available, return `None`.
/// Otherwise, calculate the amount of gas needed with given `input` and
/// `target_gas`. Return `Some(Ok(status, output, gas_used))` if the execution
/// is successful. Otherwise return `Some(Err(_))`.
fn execute(
address: H160,
input: &[u8],
target_gas: Option<usize>,
) -> Option<core::result::Result<(ExitSucceed, Vec<u8>, usize), ExitError>>;
}

/// One single precompile used by EVM engine.
pub trait Precompile {
/// Try to execute the precompile. Calculate the amount of gas needed with given `input` and
/// `target_gas`. Return `Ok(status, output, gas_used)` if the execution is
/// successful. Otherwise return `Err(_)`.
fn execute(
input: &[u8],
target_gas: Option<usize>,
) -> core::result::Result<(ExitSucceed, Vec<u8>, usize), ExitError>;
}

#[impl_for_tuples(16)]
#[tuple_types_no_default_trait_bound]
impl Precompiles for Tuple {
for_tuples!( where #( Tuple: Precompile )* );

fn execute(
address: H160,
input: &[u8],
target_gas: Option<usize>,
) -> Option<core::result::Result<(ExitSucceed, Vec<u8>, usize), ExitError>> {
let mut index = 0;

for_tuples!( #(
index += 1;
if address == H160::from_low_u64_be(index) {
return Some(Tuple::execute(input, target_gas))
}
)* );

None
}
}

0 comments on commit 506c806

Please sign in to comment.