Skip to content

Commit

Permalink
Proper Precompile Gas Consumption (polkadot-evm#337)
Browse files Browse the repository at this point in the history
* First pass at Modexp precompile gas calculation

* Incremental WIP adding modexp-eip2565.json tests

* Include Modexp in precompile set

* Working impl for ethereum test cases

* Cleanup

* Add Ethereum consensus tests in Modexp unit tests

* Return gas cost from Modexp::execute()

* Add (not very DRY) ethereum tests for Blake2 precompile

* Fixes for Blake2F precompile

* Implement EIP1108 gas costs for bn128 precompiles

* Make precompile consensus test generic

* Move test_precompile_consensus_tests to fp_evm

* Clean up precompile testdata

* Improve test_precompile_consensus_tests error handling

* Change ECRecover to return "" on error; add related tests

* Add clarifying comment

* Add sha256 and ripem160 precompile test vectors

* Add bn128 test vectors

* Remove non-existent mod declaration

* Implement Blake2 gas cost

* Remove ecrecover tests that expect bytes 33-63 to matter

* editorconfig

* Remove version specification from local crate references

* Remove modexp_eip2565 ts-tests (now redundant)

* Use 'core::cmp::max'

* Resolve compilation warnings

* Handle target_gas properly

* Revert from_ne_bytes -> from_le_bytes with comment about the logic

* Bump precompile versions

* Use 1.1.0 instead of 1.0.1 for new precompile versions

Co-authored-by: Wei Tang <[email protected]>

* Bump fp-evm to 1.0.1-dev

* Reflect new fp-evm version in crates which depend on it

* Remove unused log dependency in modexp precompile

* Move eth "consensus tests" utility to its own crate

* Modify remaining precompile tests to use pallet_evm_test_vector_support

* Leave primitives/evm/src/precompile.r untouched

* Add missing files

* Use 1.0.1-dev as version for pallet-evm-test-vector-support

* Chain 'std' for 'fp-evm'

* Specify paritytech/frontier as the repo in all Cargo.toml files

* Bump versions

* Bump fp-storage to 1.0.1-dev

* Bump fp-rpc to 1.0.1-dev

* Bump fc-consensus to 1.0.1-dev

Co-authored-by: Wei Tang <[email protected]>
  • Loading branch information
notlesh and sorpaas authored Apr 22, 2021
1 parent 0a6f4ba commit 961e992
Show file tree
Hide file tree
Showing 34 changed files with 650 additions and 135 deletions.
42 changes: 28 additions & 14 deletions Cargo.lock

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

4 changes: 2 additions & 2 deletions client/consensus/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "fc-consensus"
version = "1.0.0"
version = "1.0.1-dev"
authors = ["Parity Technologies <[email protected]>"]
description = "Frontier consensus for substrate"
edition = "2018"
Expand All @@ -17,7 +17,7 @@ sc-client-api = { version = "3.0.0", git = "https://github.com/paritytech/substr
sp-block-builder = { version = "3.0.0", git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
sp-inherents = { version = "3.0.0", git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
fp-consensus = { version = "1.0.0", path = "../../primitives/consensus" }
fp-rpc = { version = "1.0.0", path = "../../primitives/rpc" }
fp-rpc = { version = "1.0.1-dev", path = "../../primitives/rpc" }
fc-db = { version = "1.0.0", path = "../db" }
sp-consensus = { version = "0.9.0", git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
log = "0.4.8"
Expand Down
4 changes: 2 additions & 2 deletions client/mapping-sync/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ sp-blockchain = { version = "3.0.0", git = "https://github.com/paritytech/substr
sc-client-api = { version = "3.0.0", git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
sp-api = { version = "3.0.0", git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
fp-consensus = { version = "1.0.0", path = "../../primitives/consensus" }
fc-consensus = { version = "1.0.0", path = "../consensus" }
fc-consensus = { version = "1.0.1-dev", path = "../consensus" }
fc-db = { version = "1.0.0", path = "../db" }
fp-rpc = { version = "1.0.0", path = "../../primitives/rpc" }
fp-rpc = { version = "1.0.1-dev", path = "../../primitives/rpc" }
futures = { version = "0.3.1", features = ["compat"] }
futures-timer = "3.0.1"
log = "0.4.8"
10 changes: 5 additions & 5 deletions client/rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ jsonrpc-pubsub = "15.0.0"
log = "0.4.8"
ethereum-types = "0.11.0"
evm = "0.25.0"
fc-consensus = { version = "1.0.0", path = "../consensus" }
fc-consensus = { version = "1.0.1-dev", path = "../consensus" }
fc-db = { version = "1.0.0", path = "../db" }
fc-rpc-core = { version = "1.1.0-dev", path = "../rpc-core" }
fp-consensus = { version = "1.0.0", path = "../../primitives/consensus" }
fp-rpc = { version = "1.0.0", path = "../../primitives/rpc" }
fp-storage = { version = "1.0.0", path = "../../primitives/storage"}
fp-rpc = { version = "1.0.1-dev", path = "../../primitives/rpc" }
fp-storage = { version = "1.0.1-dev", path = "../../primitives/storage"}
sp-io = { version = "3.0.0", git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
sp-runtime = { version = "3.0.0", git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
sp-api = { version = "3.0.0", git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
Expand All @@ -30,8 +30,8 @@ sc-service = { version = "0.9.0", git = "https://github.com/paritytech/substrate
sc-client-api = { version = "3.0.0", git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
sc-rpc = { version = "3.0.0", git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
sc-network = { version = "0.9.0", git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
pallet-evm = { version = "3.0.0", path = "../../frame/evm" }
fp-evm = { version = "1.0.0", path = "../../primitives/evm" }
pallet-evm = { version = "3.0.1-dev", path = "../../frame/evm" }
fp-evm = { version = "1.0.1-dev", path = "../../primitives/evm" }
pallet-ethereum = { version = "1.0.1-dev", path = "../../frame/ethereum" }
ethereum = { version = "0.7.1", features = ["with-codec"] }
codec = { package = "parity-scale-codec", version = "2.0.0" }
Expand Down
8 changes: 4 additions & 4 deletions frame/ethereum/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,20 @@ frame-support = { version = "3.0.0", default-features = false, git = "https://gi
frame-system = { version = "3.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
pallet-balances = { version = "3.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
pallet-timestamp = { version = "3.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
pallet-evm = { version = "3.0.0", default-features = false, path = "../evm" }
pallet-evm = { version = "3.0.1-dev", default-features = false, path = "../evm" }
sp-runtime = { version = "3.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
sp-std = { version = "3.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
sp-io = { version = "3.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
fp-evm = { version = "1.0.0", default-features = false, path = "../../primitives/evm" }
fp-evm = { version = "1.0.1-dev", default-features = false, path = "../../primitives/evm" }
evm = { version = "0.25.0", features = ["with-codec"], default-features = false }
ethereum = { version = "0.7.1", default-features = false, features = ["with-codec"] }
ethereum-types = { version = "0.11", default-features = false }
rlp = { version = "0.5", default-features = false }
sha3 = { version = "0.8", default-features = false }
libsecp256k1 = { version = "0.3", default-features = false }
fp-consensus = { version = "1.0.0", path = "../../primitives/consensus", default-features = false }
fp-rpc = { version = "1.0.0", path = "../../primitives/rpc", default-features = false }
fp-storage = { version = "1.0.0", path = "../../primitives/storage", default-features = false}
fp-rpc = { version = "1.0.1-dev", path = "../../primitives/rpc", default-features = false }
fp-storage = { version = "1.0.1-dev", path = "../../primitives/storage", default-features = false}

[dev-dependencies]
sp-core = { version = "3.0.0", git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
Expand Down
6 changes: 3 additions & 3 deletions frame/evm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
[package]
name = "pallet-evm"
version = "3.0.0"
version = "3.0.1-dev"
authors = ["Parity Technologies <[email protected]>"]
edition = "2018"
license = "Apache-2.0"
homepage = "https://substrate.dev"
repository = "https://github.com/paritytech/substrate/"
repository = "https://github.com/paritytech/frontier/"
description = "FRAME EVM contracts pallet"
readme = "README.md"

Expand All @@ -23,7 +23,7 @@ sp-core = { version = "3.0.0", default-features = false, git = "https://github.c
sp-runtime = { version = "3.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
sp-std = { version = "3.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
sp-io = { version = "3.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
fp-evm = { version = "1.0.0", default-features = false, path = "../../primitives/evm" }
fp-evm = { version = "1.0.1-dev", default-features = false, path = "../../primitives/evm" }
primitive-types = { version = "0.9.0", default-features = false, features = ["rlp", "byteorder"] }
rlp = { version = "0.5", default-features = false }
evm = { version = "0.25.0", default-features = false, features = ["with-codec"] }
Expand Down
9 changes: 6 additions & 3 deletions frame/evm/precompile/blake2/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
[package]
name = "pallet-evm-precompile-blake2"
version = "1.0.0"
version = "1.1.0-dev"
authors = ["Parity Technologies <[email protected]>"]
edition = "2018"
license = "Apache-2.0"
homepage = "https://substrate.dev"
repository = "https://github.com/paritytech/substrate/"
repository = "https://github.com/paritytech/frontier/"
description = "BLAKE2 precompiles for EVM pallet."

[dependencies]
sp-core = { version = "3.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
sp-io = { version = "3.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
fp-evm = { version = "1.0.0", default-features = false, path = "../../../../primitives/evm" }
fp-evm = { version = "1.0.1-dev", default-features = false, path = "../../../../primitives/evm" }
evm = { version = "0.25.0", default-features = false, features = ["with-codec"] }

[dev-dependencies]
pallet-evm-test-vector-support = { version = "1.0.0-dev", path = "../../test-vector-support" }

[features]
default = ["std"]
std = [
Expand Down
48 changes: 36 additions & 12 deletions frame/evm/precompile/blake2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,24 @@ mod eip_152;

use alloc::vec::Vec;
use core::mem::size_of;
use fp_evm::LinearCostPrecompile;
use evm::{ExitSucceed, ExitError};
use fp_evm::Precompile;
use evm::{ExitSucceed, ExitError, Context};

pub struct Blake2F;

impl LinearCostPrecompile for Blake2F {
const BASE: u64 = 15;
const WORD: u64 = 3;
impl Blake2F {
const GAS_COST_PER_ROUND: u64 = 1; // https://eips.ethereum.org/EIPS/eip-152#gas-costs-and-benchmarks
}

impl Precompile for Blake2F {

/// Format of `input`:
/// [4 bytes for rounds][64 bytes for h][128 bytes for m][8 bytes for t_0][8 bytes for t_1][1 byte for f]
fn execute(
input: &[u8],
_: u64,
) -> core::result::Result<(ExitSucceed, Vec<u8>), ExitError> {
target_gas: Option<u64>,
_context: &Context,
) -> core::result::Result<(ExitSucceed, Vec<u8>, u64), ExitError> {
const BLAKE2_F_ARG_LEN: usize = 213;

if input.len() != BLAKE2_F_ARG_LEN {
Expand All @@ -46,15 +49,24 @@ impl LinearCostPrecompile for Blake2F {

let mut rounds_buf: [u8; 4] = [0; 4];
rounds_buf.copy_from_slice(&input[0..4]);
let rounds: u32 = u32::from_le_bytes(rounds_buf);
let rounds: u32 = u32::from_be_bytes(rounds_buf);

let gas_cost: u64 = (rounds as u64) * Blake2F::GAS_COST_PER_ROUND;
if let Some(gas_left) = target_gas {
if gas_left < gas_cost {
return Err(ExitError::OutOfGas);
}
}

// we use from_le_bytes below to effectively swap byte order to LE if architecture is BE

let mut h_buf: [u8; 64] = [0; 64];
h_buf.copy_from_slice(&input[4..48]);
h_buf.copy_from_slice(&input[4..68]);
let mut h = [0u64; 8];
let mut ctr = 0;
for state_word in &mut h {
let mut temp: [u8; 8] = Default::default();
temp.copy_from_slice(&h_buf[(ctr + 8)..(ctr + 1) * 8]);
temp.copy_from_slice(&h_buf[(ctr * 8)..(ctr + 1) * 8]);
*state_word = u64::from_le_bytes(temp).into();
ctr += 1;
}
Expand All @@ -65,7 +77,7 @@ impl LinearCostPrecompile for Blake2F {
ctr = 0;
for msg_word in &mut m {
let mut temp: [u8; 8] = Default::default();
temp.copy_from_slice(&m_buf[(ctr + 8)..(ctr + 1) * 8]);
temp.copy_from_slice(&m_buf[(ctr * 8)..(ctr + 1) * 8]);
*msg_word = u64::from_le_bytes(temp).into();
ctr += 1;
}
Expand All @@ -90,6 +102,18 @@ impl LinearCostPrecompile for Blake2F {
output_buf[i * 8..(i + 1) * 8].copy_from_slice(&state_word.to_le_bytes());
}

Ok((ExitSucceed::Returned, output_buf.to_vec()))
Ok((ExitSucceed::Returned, output_buf.to_vec(), gas_cost))
}
}

#[cfg(test)]
mod tests {
use super::*;
use pallet_evm_test_vector_support::test_precompile_test_vectors;

#[test]
fn process_consensus_tests() -> std::result::Result<(), String> {
test_precompile_test_vectors::<Blake2F>("../testdata/blake2F.json")?;
Ok(())
}
}
7 changes: 5 additions & 2 deletions frame/evm/precompile/bn128/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ authors = ["Parity Technologies <[email protected]>"]
edition = "2018"
license = "Apache-2.0"
homepage = "https://substrate.dev"
repository = "https://github.com/paritytech/substrate/"
repository = "https://github.com/paritytech/frontier/"
description = "BN128 precompiles for EVM pallet."

[dependencies]
sp-core = { version = "3.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
sp-io = { version = "3.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "frontier" }
fp-evm = { version = "1.0.0", default-features = false, path = "../../../../primitives/evm" }
fp-evm = { version = "1.0.1-dev", default-features = false, path = "../../../../primitives/evm" }
evm = { version = "0.25.0", default-features = false, features = ["with-codec"] }
bn = { package = "substrate-bn", version = "0.6", default-features = false }

[dev-dependencies]
pallet-evm-test-vector-support = { version = "1.0.0-dev", path = "../../test-vector-support" }

[features]
default = ["std"]
std = [
Expand Down
Loading

0 comments on commit 961e992

Please sign in to comment.