From 4fdac73bc6fcfd6dfc4ee337d60115bfb9ea9207 Mon Sep 17 00:00:00 2001 From: johntaiko Date: Tue, 22 Aug 2023 01:43:42 +0000 Subject: [PATCH] feat: remove difficulty after eip-4399 aka POS --- .../src/circuit_input_builder/block.rs | 10 ++++--- bus-mapping/src/evm/opcodes/stackonlyop.rs | 6 ++-- eth-types/src/geth_types.rs | 8 +++--- geth-utils/gethutil/trace.go | 17 +++++------ mock/src/block.rs | 6 ++-- mock/src/lib.rs | 4 ++- testool/src/statetest/executor.rs | 4 +-- testool/src/statetest/json.rs | 10 ++++--- testool/src/statetest/spec.rs | 9 ++---- testool/src/statetest/yaml.rs | 8 ++++-- zkevm-circuits/src/pi_circuit.rs | 28 +++++++++++-------- zkevm-circuits/src/witness/block.rs | 22 ++++----------- 12 files changed, 63 insertions(+), 69 deletions(-) diff --git a/bus-mapping/src/circuit_input_builder/block.rs b/bus-mapping/src/circuit_input_builder/block.rs index 11bb587d4d..76958f9db8 100644 --- a/bus-mapping/src/circuit_input_builder/block.rs +++ b/bus-mapping/src/circuit_input_builder/block.rs @@ -8,7 +8,7 @@ use crate::{ operation::{OperationContainer, RWCounter}, Error, }; -use eth_types::{evm_unimplemented, Address, Word}; +use eth_types::{evm_unimplemented, Address, Hash, Word}; use std::collections::HashMap; /// Context of a [`Block`] which can mutate in a [`Transaction`]. @@ -69,8 +69,8 @@ pub struct Block { pub number: Word, /// difficulty pub timestamp: Word, - /// gas limit - pub difficulty: Word, + /// mix hash + pub mix_hash: Hash, /// base fee pub base_fee: Word, /// State root of the previous block @@ -126,7 +126,9 @@ impl Block { .low_u64() .into(), timestamp: eth_block.timestamp, - difficulty: eth_block.difficulty, + mix_hash: eth_block + .mix_hash + .ok_or(Error::EthTypeError(eth_types::Error::IncompleteBlock))?, base_fee: eth_block.base_fee_per_gas.unwrap_or_default(), prev_state_root, container: OperationContainer::new(), diff --git a/bus-mapping/src/evm/opcodes/stackonlyop.rs b/bus-mapping/src/evm/opcodes/stackonlyop.rs index 21ec6bdcfe..dc609a6099 100644 --- a/bus-mapping/src/evm/opcodes/stackonlyop.rs +++ b/bus-mapping/src/evm/opcodes/stackonlyop.rs @@ -54,12 +54,12 @@ mod stackonlyop_tests { bytecode, evm_types::{OpcodeId, StackAddress}, geth_types::GethData, - word, Bytecode, Word, + word, Bytecode, ToWord, Word, }; use itertools::Itertools; use mock::{ test_ctx::{helpers::*, TestContext}, - MOCK_BASEFEE, MOCK_DIFFICULTY, MOCK_GASLIMIT, + MOCK_BASEFEE, MOCK_GASLIMIT, MOCK_MIX_HASH, }; use pretty_assertions::assert_eq; use std::ops::{BitOr, BitXor}; @@ -375,7 +375,7 @@ mod stackonlyop_tests { STOP }, vec![], - vec![StackOp::new(1, StackAddress(1023), *MOCK_DIFFICULTY)], + vec![StackOp::new(1, StackAddress(1023), MOCK_MIX_HASH.to_word())], ); } diff --git a/eth-types/src/geth_types.rs b/eth-types/src/geth_types.rs index 86750a7599..7f6151514b 100644 --- a/eth-types/src/geth_types.rs +++ b/eth-types/src/geth_types.rs @@ -72,7 +72,7 @@ pub struct BlockConstants { /// U64 type is required to serialize into proper hex with 0x prefix pub number: U64, /// difficulty - pub difficulty: Word, + pub mix_hash: Hash, /// gas limit pub gas_limit: Word, /// base fee @@ -87,7 +87,7 @@ impl TryFrom<&Block> for BlockConstants { coinbase: block.author.ok_or(Error::IncompleteBlock)?, timestamp: block.timestamp, number: block.number.ok_or(Error::IncompleteBlock)?, - difficulty: block.difficulty, + mix_hash: block.mix_hash.ok_or(Error::IncompleteBlock)?, gas_limit: block.gas_limit, base_fee: block.base_fee_per_gas.ok_or(Error::IncompleteBlock)?, }) @@ -100,7 +100,7 @@ impl BlockConstants { coinbase: Address, timestamp: Word, number: U64, - difficulty: Word, + mix_hash: Hash, gas_limit: Word, base_fee: Word, ) -> BlockConstants { @@ -108,7 +108,7 @@ impl BlockConstants { coinbase, timestamp, number, - difficulty, + mix_hash, gas_limit, base_fee, } diff --git a/geth-utils/gethutil/trace.go b/geth-utils/gethutil/trace.go index 39cd78b894..5aa6f89bb6 100644 --- a/geth-utils/gethutil/trace.go +++ b/geth-utils/gethutil/trace.go @@ -83,12 +83,12 @@ func FormatLogs(logs []logger.StructLog) []StructLogRes { } type Block struct { - Coinbase common.Address `json:"coinbase"` - Timestamp *hexutil.Big `json:"timestamp"` - Number *hexutil.Big `json:"number"` - Difficulty *hexutil.Big `json:"difficulty"` - GasLimit *hexutil.Big `json:"gas_limit"` - BaseFee *hexutil.Big `json:"base_fee"` + Coinbase common.Address `json:"coinbase"` + Timestamp *hexutil.Big `json:"timestamp"` + Number *hexutil.Big `json:"number"` + GasLimit *hexutil.Big `json:"gas_limit"` + BaseFee *hexutil.Big `json:"base_fee"` + MixHash common.Hash `json:"mix_hash"` } type Account struct { @@ -186,8 +186,6 @@ func Trace(config TraceConfig) ([]*ExecutionResult, error) { return nil, fmt.Errorf("txs total gas: %d Exceeds block gas limit: %d", txsGasLimit, blockGasLimit) } - random := common.BigToHash(toBigInt(config.Block.Difficulty)) - blockCtx := vm.BlockContext{ CanTransfer: core.CanTransfer, Transfer: core.Transfer, @@ -202,10 +200,9 @@ func Trace(config TraceConfig) ([]*ExecutionResult, error) { Coinbase: config.Block.Coinbase, BlockNumber: toBigInt(config.Block.Number), Time: toBigInt(config.Block.Timestamp).Uint64(), - Difficulty: toBigInt(config.Block.Difficulty), BaseFee: toBigInt(config.Block.BaseFee), GasLimit: blockGasLimit, - Random: &random, + Random: &config.Block.MixHash, } // Setup state db with accounts from argument diff --git a/mock/src/block.rs b/mock/src/block.rs index 4123312933..ae0c778877 100644 --- a/mock/src/block.rs +++ b/mock/src/block.rs @@ -1,6 +1,6 @@ //! Mock Block definition and builder related methods. -use crate::{MockTransaction, MOCK_BASEFEE, MOCK_CHAIN_ID, MOCK_DIFFICULTY, MOCK_GASLIMIT}; +use crate::{MockTransaction, MOCK_BASEFEE, MOCK_CHAIN_ID, MOCK_GASLIMIT, MOCK_MIX_HASH}; use eth_types::{Address, Block, Bytes, Hash, Transaction, Word, H64, U64}; use ethers_core::types::{Bloom, OtherFields}; @@ -54,13 +54,13 @@ impl Default for MockBlock { extra_data: Bytes::default(), logs_bloom: None, timestamp: Word::from(123456789u64), - difficulty: *MOCK_DIFFICULTY, + mix_hash: *MOCK_MIX_HASH, total_difficulty: Word::zero(), + difficulty: Word::zero(), seal_fields: Vec::new(), uncles: Vec::new(), transactions: Vec::new(), size: Word::zero(), - mix_hash: Hash::zero(), nonce: H64::zero(), chain_id: *MOCK_CHAIN_ID, } diff --git a/mock/src/lib.rs b/mock/src/lib.rs index 7512272e34..e6c7ec7246 100644 --- a/mock/src/lib.rs +++ b/mock/src/lib.rs @@ -1,4 +1,6 @@ //! Mock types and functions to generate GethData used for tests +use std::str::FromStr; + use eth_types::{address, bytecode, bytecode::Bytecode, word, Address, Bytes, Hash, Word}; use ethers_signers::LocalWallet; use lazy_static::lazy_static; @@ -34,7 +36,7 @@ lazy_static! { /// Mock chain ID value pub static ref MOCK_CHAIN_ID: Word = Word::from(1338u64); /// Mock DIFFICULTY value - pub static ref MOCK_DIFFICULTY: Word = Word::from(0x200000u64); + pub static ref MOCK_MIX_HASH: Hash = Hash::from_str("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").unwrap(); /// Mock accounts loaded with ETH to use for test cases. pub static ref MOCK_ACCOUNTS: Vec
= vec![ address!("0x000000000000000000000000000000000cafe111"), diff --git a/testool/src/statetest/executor.rs b/testool/src/statetest/executor.rs index c2c365d8f1..d738de1fb5 100644 --- a/testool/src/statetest/executor.rs +++ b/testool/src/statetest/executor.rs @@ -131,7 +131,7 @@ fn into_traceconfig(st: StateTest) -> (String, TraceConfig, StateTestResult) { coinbase: st.env.current_coinbase, timestamp: U256::from(st.env.current_timestamp), number: U64::from(st.env.current_number), - difficulty: st.env.current_difficulty, + mix_hash: st.env.current_mix_hash, gas_limit: U256::from(st.env.current_gas_limit), base_fee: U256::one(), }, @@ -222,7 +222,7 @@ pub fn run_test( author: Some(trace_config.block_constants.coinbase), timestamp: trace_config.block_constants.timestamp, number: Some(U64::from(trace_config.block_constants.number.as_u64())), - difficulty: trace_config.block_constants.difficulty, + mix_hash: Some(trace_config.block_constants.mix_hash), gas_limit: trace_config.block_constants.gas_limit, base_fee_per_gas: Some(trace_config.block_constants.base_fee), transactions, diff --git a/testool/src/statetest/json.rs b/testool/src/statetest/json.rs index 0b89dc6c56..467222edd9 100644 --- a/testool/src/statetest/json.rs +++ b/testool/src/statetest/json.rs @@ -13,7 +13,7 @@ use std::collections::HashMap; #[serde(rename_all = "camelCase")] struct TestEnv { current_coinbase: String, - current_difficulty: String, + current_mix_hash: String, current_gas_limit: String, current_number: String, current_timestamp: String, @@ -192,7 +192,7 @@ impl<'a> JsonStateTestBuilder<'a> { fn parse_env(env: &TestEnv) -> Result { Ok(Env { current_coinbase: parse::parse_address(&env.current_coinbase)?, - current_difficulty: parse::parse_u256(&env.current_difficulty)?, + current_mix_hash: parse::parse_hash(&env.current_mix_hash)?, current_gas_limit: parse::parse_u64(&env.current_gas_limit)?, current_number: parse::parse_u64(&env.current_number)?, current_timestamp: parse::parse_u64(&env.current_timestamp)?, @@ -305,7 +305,7 @@ mod test { }, "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "0x20000", + "currentMixHash" : "0x20000", "currentGasLimit" : "0xFF112233445566", "currentNumber" : "1", "currentTimestamp" : "1000", @@ -371,7 +371,9 @@ mod test { id: "add11_d0_g0_v0".to_string(), env: Env { current_coinbase: Address::from_str("0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba")?, - current_difficulty: U256::from(131072u64), + current_mix_hash: H256::from_str( + "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + )?, current_gas_limit: 0xFF112233445566, current_number: 1, current_timestamp: 1000, diff --git a/testool/src/statetest/spec.rs b/testool/src/statetest/spec.rs index 10f61f4cbd..5045e24ced 100644 --- a/testool/src/statetest/spec.rs +++ b/testool/src/statetest/spec.rs @@ -6,7 +6,7 @@ use std::{collections::HashMap, str::FromStr}; #[derive(PartialEq, Eq, Debug, Clone)] pub struct Env { pub current_coinbase: Address, - pub current_difficulty: U256, + pub current_mix_hash: H256, pub current_gas_limit: u64, pub current_number: u64, pub current_timestamp: u64, @@ -90,10 +90,7 @@ impl std::fmt::Display for StateTest { } table.add_row(row!["coinbase", format!("{:?}", self.env.current_coinbase)]); - table.add_row(row![ - "difficulty", - format!("{}", self.env.current_difficulty) - ]); + table.add_row(row!["mix_hash", format!("{}", self.env.current_mix_hash)]); table.add_row(row!["number", format!("{}", self.env.current_number)]); table.add_row(row!["timestamp", format!("{}", self.env.current_timestamp)]); table.add_row(row!["prev_hash", format!("{:?}", self.env.previous_hash)]); @@ -262,7 +259,7 @@ impl StateTest { id: String::default(), env: Env { current_coinbase: *mock::MOCK_COINBASE, - current_difficulty: U256::default(), + current_mix_hash: H256::default(), current_gas_limit: 16000000, current_number: 1, current_timestamp: 1, diff --git a/testool/src/statetest/yaml.rs b/testool/src/statetest/yaml.rs index fadd4fc682..22fb507c95 100644 --- a/testool/src/statetest/yaml.rs +++ b/testool/src/statetest/yaml.rs @@ -204,7 +204,7 @@ impl<'a> YamlStateTestBuilder<'a> { fn parse_env(yaml: &Yaml) -> Result { Ok(Env { current_coinbase: Self::parse_address(&yaml["currentCoinbase"])?, - current_difficulty: Self::parse_u256(&yaml["currentDifficulty"])?, + current_mix_hash: Self::parse_hash(&yaml["currentMixHash"])?, current_gas_limit: Self::parse_u64(&yaml["currentGasLimit"])?, current_number: Self::parse_u64(&yaml["currentNumber"])?, current_timestamp: Self::parse_u64(&yaml["currentTimestamp"])?, @@ -436,7 +436,7 @@ mod test { arith: env: currentCoinbase: 2adc25665018aa1fe0e6bc666dac8fc2697ff9ba - currentDifficulty: 0x20000 + currentMixHash: 0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 currentGasLimit: {{ gas_limit }} currentNumber: 1 currentTimestamp: 1000 @@ -600,7 +600,9 @@ arith: id: "arith_d0_g0_v0".into(), env: Env { current_coinbase: address!("0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"), - current_difficulty: U256::from(0x20000u64), + current_mix_hash: H256::from_str( + "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + )?, current_number: 1, current_timestamp: 1000, current_gas_limit: 100000000, diff --git a/zkevm-circuits/src/pi_circuit.rs b/zkevm-circuits/src/pi_circuit.rs index c656ccc555..2e9edae155 100644 --- a/zkevm-circuits/src/pi_circuit.rs +++ b/zkevm-circuits/src/pi_circuit.rs @@ -45,7 +45,7 @@ pub struct BlockValues { gas_limit: u64, number: u64, timestamp: u64, - difficulty: Word, + mix_hash: H256, base_fee: Word, // NOTE: BaseFee was added by EIP-1559 and is ignored in legacy headers. chain_id: u64, history_hashes: Vec, @@ -125,7 +125,7 @@ impl PublicData { gas_limit: self.block_constants.gas_limit.as_u64(), number: self.block_constants.number.as_u64(), timestamp: self.block_constants.timestamp.as_u64(), - difficulty: self.block_constants.difficulty, + mix_hash: self.block_constants.mix_hash, base_fee: self.block_constants.base_fee, chain_id: self.chain_id.as_u64(), history_hashes, @@ -926,21 +926,23 @@ impl PiCircuitConfig { raw_pi_vals[offset] = timestamp; offset += 1; - // difficulty - let difficulty = rlc(block_values.difficulty.to_le_bytes(), randomness); + let mut mix_hash_bytes = block_values.mix_hash.to_fixed_bytes(); + mix_hash_bytes.reverse(); + // mix hash + let mix_hash = rlc(mix_hash_bytes, randomness); region.assign_advice( - || "difficulty", + || "mix_hash", self.block_table.value, offset, - || Value::known(difficulty), + || Value::known(mix_hash), )?; region.assign_advice( - || "difficulty", + || "mix_hash", self.raw_public_inputs, offset, - || Value::known(difficulty), + || Value::known(mix_hash), )?; - raw_pi_vals[offset] = difficulty; + raw_pi_vals[offset] = mix_hash; offset += 1; // base_fee @@ -1164,7 +1166,7 @@ impl SubCircuit for PiCircuit { coinbase: block.context.coinbase, timestamp: block.context.timestamp, number: block.context.number.as_u64().into(), - difficulty: block.context.difficulty, + mix_hash: block.context.mix_hash, gas_limit: block.context.gas_limit.into(), base_fee: block.context.base_fee, }, @@ -1487,8 +1489,10 @@ fn raw_public_inputs_col( // timestamp result[offset] = F::from(block.timestamp); offset += 1; - // difficulty - result[offset] = rlc(block.difficulty.to_le_bytes(), randomness); + // mix hash + let mut mix_hash_bytes = block.mix_hash.to_fixed_bytes(); + mix_hash_bytes.reverse(); + result[offset] = rlc(mix_hash_bytes, randomness); offset += 1; // base_fee result[offset] = rlc(block.base_fee.to_le_bytes(), randomness); diff --git a/zkevm-circuits/src/witness/block.rs b/zkevm-circuits/src/witness/block.rs index a2fbd1c7fc..bee18e10a3 100644 --- a/zkevm-circuits/src/witness/block.rs +++ b/zkevm-circuits/src/witness/block.rs @@ -185,10 +185,10 @@ pub struct BlockContext { pub number: Word, /// The timestamp of the block pub timestamp: Word, - /// The difficulty of the blcok - pub difficulty: Word, /// The mix hash of the block - pub mix_hash: Option, + // after eip-4399, the difficulty is always zero, we need to use the mix hash instead of + // difficulty. + pub mix_hash: H256, /// The base fee, the minimum amount of gas fee for a transaction pub base_fee: Word, /// The hash of previous blocks @@ -227,18 +227,7 @@ impl BlockContext { [ Value::known(F::from(BlockContextFieldTag::Difficulty as u64)), Value::known(F::ZERO), - { - if self.difficulty.is_zero() { - rlc_be_bytes( - &self.mix_hash.unwrap_or_default().to_fixed_bytes(), - randomness, - ) - } else { - randomness.map(|randomness| { - rlc::value(&self.difficulty.to_le_bytes(), randomness) - }) - } - }, + rlc_be_bytes(&self.mix_hash.to_fixed_bytes(), randomness), ], [ Value::known(F::from(BlockContextFieldTag::GasLimit as u64)), @@ -295,8 +284,7 @@ impl From<&circuit_input_builder::Block> for BlockContext { gas_limit: block.gas_limit, number: block.number, timestamp: block.timestamp, - difficulty: block.difficulty, - mix_hash: block.eth_block.mix_hash, + mix_hash: block.mix_hash, base_fee: block.base_fee, history_hashes: block.history_hashes.clone(), chain_id: block.chain_id,