From 0cb70cba145b8c9fc6781585e6cd410ab6c626db Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 20 Sep 2023 16:00:23 +0200 Subject: [PATCH 1/2] fix(eip4844): Pass eth tests, add condition to env. --- bins/revme/src/statetest/runner.rs | 6 ---- crates/precompile/src/kzg_point_evaluation.rs | 6 ++-- crates/precompile/src/lib.rs | 2 +- crates/primitives/src/constants.rs | 14 +++++--- crates/primitives/src/env.rs | 35 +++++++++++++++++-- crates/primitives/src/result.rs | 8 +++++ crates/revm/src/evm_impl.rs | 2 +- 7 files changed, 56 insertions(+), 17 deletions(-) diff --git a/bins/revme/src/statetest/runner.rs b/bins/revme/src/statetest/runner.rs index 5ab8fc119a..93f666378c 100644 --- a/bins/revme/src/statetest/runner.rs +++ b/bins/revme/src/statetest/runner.rs @@ -100,12 +100,6 @@ fn skip_test(path: &Path) -> bool { | "loopMul.json" | "CALLBlake2f_MaxRounds.json" | "shiftCombinations.json" - - // TODO: These EIP-4844 all have exception specified. - | "emptyBlobhashList.json" // '>=Cancun': TR_EMPTYBLOB - | "wrongBlobhashVersion.json" // '>=Cancun': TR_BLOBVERSION_INVALID - | "createBlobhashTx.json" // '>=Cancun': TR_BLOBCREATE - | "blobhashListBounds7.json" // ">=Cancun": "TR_BLOBLIST_OVERSIZE" ) || path_str.contains("stEOF") } diff --git a/crates/precompile/src/kzg_point_evaluation.rs b/crates/precompile/src/kzg_point_evaluation.rs index ec85ac3d94..b4968c9bc9 100644 --- a/crates/precompile/src/kzg_point_evaluation.rs +++ b/crates/precompile/src/kzg_point_evaluation.rs @@ -5,9 +5,9 @@ use sha2::{Digest, Sha256}; pub const POINT_EVALUATION: PrecompileAddress = PrecompileAddress(ADDRESS, Precompile::Env(run)); -const ADDRESS: B160 = crate::u64_to_b160(0x0A); -const GAS_COST: u64 = 50_000; -const VERSIONED_HASH_VERSION_KZG: u8 = 0x01; +pub const ADDRESS: B160 = crate::u64_to_b160(0x0A); +pub const GAS_COST: u64 = 50_000; +pub const VERSIONED_HASH_VERSION_KZG: u8 = 0x01; /// `U256(FIELD_ELEMENTS_PER_BLOB).to_be_bytes() ++ BLS_MODULUS.to_bytes32()` const RETURN_VALUE: &[u8; 64] = &hex!( diff --git a/crates/precompile/src/lib.rs b/crates/precompile/src/lib.rs index c7c161026b..46f4c1bb96 100644 --- a/crates/precompile/src/lib.rs +++ b/crates/precompile/src/lib.rs @@ -8,7 +8,7 @@ mod bn128; mod hash; mod identity; #[cfg(feature = "std")] -mod kzg_point_evaluation; +pub mod kzg_point_evaluation; mod modexp; mod secp256k1; diff --git a/crates/primitives/src/constants.rs b/crates/primitives/src/constants.rs index 7776b18d04..4e5664747c 100644 --- a/crates/primitives/src/constants.rs +++ b/crates/primitives/src/constants.rs @@ -21,13 +21,19 @@ pub const MAX_INITCODE_SIZE: usize = 2 * MAX_CODE_SIZE; pub const PRECOMPILE3: B160 = B160([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3]); // EIP-4844 constants -/// Maximum consumable blob gas for data blobs per block. -pub const MAX_BLOB_GAS_PER_BLOCK: u64 = 6 * GAS_PER_BLOB; -/// Target consumable blob gas for data blobs per block (for 1559-like pricing). -pub const TARGET_BLOB_GAS_PER_BLOCK: u64 = 3 * GAS_PER_BLOB; /// Gas consumption of a single data blob (== blob byte size). pub const GAS_PER_BLOB: u64 = 1 << 17; +/// Target number of the blob per block. +pub const TARGET_BLOB_NUMBER_PER_BLOCK: u64 = 3; +/// Max number of blobs per block +pub const MAX_BLOB_NUMBER_PER_BLOCK: u64 = 2 * TARGET_BLOB_NUMBER_PER_BLOCK; +/// Maximum consumable blob gas for data blobs per block. +pub const MAX_BLOB_GAS_PER_BLOCK: u64 = MAX_BLOB_NUMBER_PER_BLOCK * GAS_PER_BLOB; +/// Target consumable blob gas for data blobs per block (for 1559-like pricing). +pub const TARGET_BLOB_GAS_PER_BLOCK: u64 = TARGET_BLOB_NUMBER_PER_BLOCK * GAS_PER_BLOB; /// Minimum gas price for data blobs. pub const MIN_BLOB_GASPRICE: u64 = 1; /// Controls the maximum rate of change for blob gas price. pub const BLOB_GASPRICE_UPDATE_FRACTION: u64 = 3338477; +/// First version of the blob. +pub const VERSIONED_HASH_VERSION_KZG: u8 = 0x01; diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index 71096b1b98..883d490dce 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -1,6 +1,7 @@ use crate::{ alloc::vec::Vec, calc_blob_fee, Account, EVMError, InvalidTransaction, Spec, SpecId, B160, - B256, GAS_PER_BLOB, KECCAK_EMPTY, MAX_INITCODE_SIZE, U256, + B256, GAS_PER_BLOB, KECCAK_EMPTY, MAX_BLOB_NUMBER_PER_BLOCK, MAX_INITCODE_SIZE, U256, + VERSIONED_HASH_VERSION_KZG, }; use bytes::Bytes; use core::cmp::{min, Ordering}; @@ -107,7 +108,8 @@ pub struct TxEnv { /// [EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559 pub gas_priority_fee: Option, - /// The list of blob versioned hashes. + /// The list of blob versioned hashes. Per EIP there should be at least + /// one blob present if [`Self::max_fee_per_blob_gas`] is `Some`. /// /// Incorporated as part of the Cancun upgrade via [EIP-4844]. /// @@ -458,11 +460,40 @@ impl Env { // - For CANCUN and later, check that the gas price is not more than the tx max // - For before CANCUN, check that `blob_hashes` and `max_fee_per_blob_gas` are empty / not set if SPEC::enabled(SpecId::CANCUN) { + // Presence of max_fee_per_blob_gas means that this is blob transaction. if let Some(max) = self.tx.max_fee_per_blob_gas { + // ensure that the user was willing to at least pay the current blob gasprice let price = self.block.get_blob_gasprice().expect("already checked"); if U256::from(price) > max { return Err(InvalidTransaction::BlobGasPriceGreaterThanMax); } + + // there must be at least one blob + // assert len(tx.blob_versioned_hashes) > 0 + if self.tx.blob_hashes.is_empty() { + return Err(InvalidTransaction::EmptyBlobs); + } + + // The field `to` deviates slightly from the semantics with the exception + // that it MUST NOT be nil and therefore must always represent + // a 20-byte address. This means that blob transactions cannot + // have the form of a create transaction. + if self.tx.transact_to.is_create() { + return Err(InvalidTransaction::BlobCreateTransaction); + } + + // all versioned blob hashes must start with VERSIONED_HASH_VERSION_KZG + for blob in self.tx.blob_hashes.iter() { + if blob[0] != VERSIONED_HASH_VERSION_KZG { + return Err(InvalidTransaction::BlobVersionedHashesNotSupported); + } + } + + // ensure the total blob gas spent is at most equal to the limit + // assert blob_gas_used <= MAX_BLOB_GAS_PER_BLOCK + if self.tx.blob_hashes.len() > MAX_BLOB_NUMBER_PER_BLOCK as usize { + return Err(InvalidTransaction::TooManyBlobs); + } } } else { if !self.tx.blob_hashes.is_empty() { diff --git a/crates/primitives/src/result.rs b/crates/primitives/src/result.rs index 4e5c1d93f6..60d0affa9c 100644 --- a/crates/primitives/src/result.rs +++ b/crates/primitives/src/result.rs @@ -179,6 +179,7 @@ pub enum InvalidTransaction { }, /// EIP-3860: Limit and meter initcode CreateInitcodeSizeLimit, + /// Transaction chain id does not match the config chain id. InvalidChainId, /// Access list is not supported for blocks before the Berlin hardfork. AccessListNotSupported, @@ -188,6 +189,13 @@ pub enum InvalidTransaction { BlobVersionedHashesNotSupported, /// Block `blob_gas_price` is greater than tx-specified `max_fee_per_blob_gas` after Cancun. BlobGasPriceGreaterThanMax, + /// There should be at least one blob in Blob transaction. + EmptyBlobs, + /// Blob transaction can't be a create transaction. + /// `to` must be present + BlobCreateTransaction, + /// Transaction has more then [`crate::MAX_BLOB_NUMBER_PER_BLOCK`] blobs + TooManyBlobs, } /// Reason a transaction successfully completed. diff --git a/crates/revm/src/evm_impl.rs b/crates/revm/src/evm_impl.rs index 8ea2728612..cb10edc6b4 100644 --- a/crates/revm/src/evm_impl.rs +++ b/crates/revm/src/evm_impl.rs @@ -106,7 +106,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> Transact &env.tx.access_list, ); - // Additonal check to see if limit is big enought to cover initial gas. + // Additional check to see if limit is big enough to cover initial gas. if initial_gas_spend > env.tx.gas_limit { return Err(InvalidTransaction::CallGasCostMoreThanGasLimit.into()); } From 753dfbad4413deaad9c9fcffd0dc09b4de443b64 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 20 Sep 2023 21:12:34 +0200 Subject: [PATCH 2/2] Add BlobVersionNotSupported error --- crates/primitives/src/env.rs | 2 +- crates/primitives/src/result.rs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index 883d490dce..e765db4faf 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -485,7 +485,7 @@ impl Env { // all versioned blob hashes must start with VERSIONED_HASH_VERSION_KZG for blob in self.tx.blob_hashes.iter() { if blob[0] != VERSIONED_HASH_VERSION_KZG { - return Err(InvalidTransaction::BlobVersionedHashesNotSupported); + return Err(InvalidTransaction::BlobVersionNotSupported); } } diff --git a/crates/primitives/src/result.rs b/crates/primitives/src/result.rs index 60d0affa9c..553982ab39 100644 --- a/crates/primitives/src/result.rs +++ b/crates/primitives/src/result.rs @@ -196,6 +196,8 @@ pub enum InvalidTransaction { BlobCreateTransaction, /// Transaction has more then [`crate::MAX_BLOB_NUMBER_PER_BLOCK`] blobs TooManyBlobs, + /// Blob transaction contains a versioned hash with an incorrect version + BlobVersionNotSupported, } /// Reason a transaction successfully completed.