Skip to content

Commit cb39117

Browse files
authored
fix(eip4844): Pass eth tests, additional conditions added. (#735)
* fix(eip4844): Pass eth tests, add condition to env. * Add BlobVersionNotSupported error
1 parent 36e71fc commit cb39117

File tree

7 files changed

+58
-17
lines changed

7 files changed

+58
-17
lines changed

bins/revme/src/statetest/runner.rs

-6
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,6 @@ fn skip_test(path: &Path) -> bool {
100100
| "loopMul.json"
101101
| "CALLBlake2f_MaxRounds.json"
102102
| "shiftCombinations.json"
103-
104-
// TODO: These EIP-4844 all have exception specified.
105-
| "emptyBlobhashList.json" // '>=Cancun': TR_EMPTYBLOB
106-
| "wrongBlobhashVersion.json" // '>=Cancun': TR_BLOBVERSION_INVALID
107-
| "createBlobhashTx.json" // '>=Cancun': TR_BLOBCREATE
108-
| "blobhashListBounds7.json" // ">=Cancun": "TR_BLOBLIST_OVERSIZE"
109103
) || path_str.contains("stEOF")
110104
}
111105

crates/precompile/src/kzg_point_evaluation.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ use sha2::{Digest, Sha256};
55

66
pub const POINT_EVALUATION: PrecompileAddress = PrecompileAddress(ADDRESS, Precompile::Env(run));
77

8-
const ADDRESS: B160 = crate::u64_to_b160(0x0A);
9-
const GAS_COST: u64 = 50_000;
10-
const VERSIONED_HASH_VERSION_KZG: u8 = 0x01;
8+
pub const ADDRESS: B160 = crate::u64_to_b160(0x0A);
9+
pub const GAS_COST: u64 = 50_000;
10+
pub const VERSIONED_HASH_VERSION_KZG: u8 = 0x01;
1111

1212
/// `U256(FIELD_ELEMENTS_PER_BLOB).to_be_bytes() ++ BLS_MODULUS.to_bytes32()`
1313
const RETURN_VALUE: &[u8; 64] = &hex!(

crates/precompile/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ mod bn128;
88
mod hash;
99
mod identity;
1010
#[cfg(feature = "std")]
11-
mod kzg_point_evaluation;
11+
pub mod kzg_point_evaluation;
1212
mod modexp;
1313
mod secp256k1;
1414

crates/primitives/src/constants.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,19 @@ pub const MAX_INITCODE_SIZE: usize = 2 * MAX_CODE_SIZE;
2121
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]);
2222

2323
// EIP-4844 constants
24-
/// Maximum consumable blob gas for data blobs per block.
25-
pub const MAX_BLOB_GAS_PER_BLOCK: u64 = 6 * GAS_PER_BLOB;
26-
/// Target consumable blob gas for data blobs per block (for 1559-like pricing).
27-
pub const TARGET_BLOB_GAS_PER_BLOCK: u64 = 3 * GAS_PER_BLOB;
2824
/// Gas consumption of a single data blob (== blob byte size).
2925
pub const GAS_PER_BLOB: u64 = 1 << 17;
26+
/// Target number of the blob per block.
27+
pub const TARGET_BLOB_NUMBER_PER_BLOCK: u64 = 3;
28+
/// Max number of blobs per block
29+
pub const MAX_BLOB_NUMBER_PER_BLOCK: u64 = 2 * TARGET_BLOB_NUMBER_PER_BLOCK;
30+
/// Maximum consumable blob gas for data blobs per block.
31+
pub const MAX_BLOB_GAS_PER_BLOCK: u64 = MAX_BLOB_NUMBER_PER_BLOCK * GAS_PER_BLOB;
32+
/// Target consumable blob gas for data blobs per block (for 1559-like pricing).
33+
pub const TARGET_BLOB_GAS_PER_BLOCK: u64 = TARGET_BLOB_NUMBER_PER_BLOCK * GAS_PER_BLOB;
3034
/// Minimum gas price for data blobs.
3135
pub const MIN_BLOB_GASPRICE: u64 = 1;
3236
/// Controls the maximum rate of change for blob gas price.
3337
pub const BLOB_GASPRICE_UPDATE_FRACTION: u64 = 3338477;
38+
/// First version of the blob.
39+
pub const VERSIONED_HASH_VERSION_KZG: u8 = 0x01;

crates/primitives/src/env.rs

+33-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::{
22
alloc::vec::Vec, calc_blob_fee, Account, EVMError, InvalidTransaction, Spec, SpecId, B160,
3-
B256, GAS_PER_BLOB, KECCAK_EMPTY, MAX_INITCODE_SIZE, U256,
3+
B256, GAS_PER_BLOB, KECCAK_EMPTY, MAX_BLOB_NUMBER_PER_BLOCK, MAX_INITCODE_SIZE, U256,
4+
VERSIONED_HASH_VERSION_KZG,
45
};
56
use bytes::Bytes;
67
use core::cmp::{min, Ordering};
@@ -107,7 +108,8 @@ pub struct TxEnv {
107108
/// [EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559
108109
pub gas_priority_fee: Option<U256>,
109110

110-
/// The list of blob versioned hashes.
111+
/// The list of blob versioned hashes. Per EIP there should be at least
112+
/// one blob present if [`Self::max_fee_per_blob_gas`] is `Some`.
111113
///
112114
/// Incorporated as part of the Cancun upgrade via [EIP-4844].
113115
///
@@ -458,11 +460,40 @@ impl Env {
458460
// - For CANCUN and later, check that the gas price is not more than the tx max
459461
// - For before CANCUN, check that `blob_hashes` and `max_fee_per_blob_gas` are empty / not set
460462
if SPEC::enabled(SpecId::CANCUN) {
463+
// Presence of max_fee_per_blob_gas means that this is blob transaction.
461464
if let Some(max) = self.tx.max_fee_per_blob_gas {
465+
// ensure that the user was willing to at least pay the current blob gasprice
462466
let price = self.block.get_blob_gasprice().expect("already checked");
463467
if U256::from(price) > max {
464468
return Err(InvalidTransaction::BlobGasPriceGreaterThanMax);
465469
}
470+
471+
// there must be at least one blob
472+
// assert len(tx.blob_versioned_hashes) > 0
473+
if self.tx.blob_hashes.is_empty() {
474+
return Err(InvalidTransaction::EmptyBlobs);
475+
}
476+
477+
// The field `to` deviates slightly from the semantics with the exception
478+
// that it MUST NOT be nil and therefore must always represent
479+
// a 20-byte address. This means that blob transactions cannot
480+
// have the form of a create transaction.
481+
if self.tx.transact_to.is_create() {
482+
return Err(InvalidTransaction::BlobCreateTransaction);
483+
}
484+
485+
// all versioned blob hashes must start with VERSIONED_HASH_VERSION_KZG
486+
for blob in self.tx.blob_hashes.iter() {
487+
if blob[0] != VERSIONED_HASH_VERSION_KZG {
488+
return Err(InvalidTransaction::BlobVersionNotSupported);
489+
}
490+
}
491+
492+
// ensure the total blob gas spent is at most equal to the limit
493+
// assert blob_gas_used <= MAX_BLOB_GAS_PER_BLOCK
494+
if self.tx.blob_hashes.len() > MAX_BLOB_NUMBER_PER_BLOCK as usize {
495+
return Err(InvalidTransaction::TooManyBlobs);
496+
}
466497
}
467498
} else {
468499
if !self.tx.blob_hashes.is_empty() {

crates/primitives/src/result.rs

+10
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ pub enum InvalidTransaction {
179179
},
180180
/// EIP-3860: Limit and meter initcode
181181
CreateInitcodeSizeLimit,
182+
/// Transaction chain id does not match the config chain id.
182183
InvalidChainId,
183184
/// Access list is not supported for blocks before the Berlin hardfork.
184185
AccessListNotSupported,
@@ -188,6 +189,15 @@ pub enum InvalidTransaction {
188189
BlobVersionedHashesNotSupported,
189190
/// Block `blob_gas_price` is greater than tx-specified `max_fee_per_blob_gas` after Cancun.
190191
BlobGasPriceGreaterThanMax,
192+
/// There should be at least one blob in Blob transaction.
193+
EmptyBlobs,
194+
/// Blob transaction can't be a create transaction.
195+
/// `to` must be present
196+
BlobCreateTransaction,
197+
/// Transaction has more then [`crate::MAX_BLOB_NUMBER_PER_BLOCK`] blobs
198+
TooManyBlobs,
199+
/// Blob transaction contains a versioned hash with an incorrect version
200+
BlobVersionNotSupported,
191201
}
192202

193203
/// Reason a transaction successfully completed.

crates/revm/src/evm_impl.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> Transact<DB::Error>
106106
&env.tx.access_list,
107107
);
108108

109-
// Additonal check to see if limit is big enought to cover initial gas.
109+
// Additional check to see if limit is big enough to cover initial gas.
110110
if initial_gas_spend > env.tx.gas_limit {
111111
return Err(InvalidTransaction::CallGasCostMoreThanGasLimit.into());
112112
}

0 commit comments

Comments
 (0)