Skip to content

Commit

Permalink
wip: add tx circuit l1 block hashes update
Browse files Browse the repository at this point in the history
  • Loading branch information
lastminutedev committed Dec 8, 2023
1 parent 1c34a61 commit 4453825
Show file tree
Hide file tree
Showing 26 changed files with 546 additions and 93 deletions.
2 changes: 2 additions & 0 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 bus-mapping/src/circuit_input_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -933,7 +933,7 @@ pub fn keccak_inputs_tx_circuit(txs: &[geth_types::Transaction]) -> Result<Vec<V
.iter()
.enumerate()
.filter(|(i, tx)| {
if !tx.tx_type.is_l1_msg() && tx.v == 0 && tx.r.is_zero() && tx.s.is_zero() {
if !tx.tx_type.is_l1_custom_tx() && tx.v == 0 && tx.r.is_zero() && tx.s.is_zero() {
warn!(
"tx {} is not signed and is not L1Msg, skipping tx circuit keccak input",
i
Expand All @@ -944,7 +944,7 @@ pub fn keccak_inputs_tx_circuit(txs: &[geth_types::Transaction]) -> Result<Vec<V
}
})
.map(|(_, tx)| {
if tx.tx_type.is_l1_msg() {
if tx.tx_type.is_l1_custom_tx() {
Ok(SignData::default())
} else {
tx.sign_data()
Expand Down
12 changes: 6 additions & 6 deletions bus-mapping/src/evm/opcodes/begin_end_tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub fn gen_begin_tx_steps(state: &mut CircuitInputStateRef) -> Result<ExecStep,

let caller_address = call.caller_address;

if state.tx.tx_type.is_l1_msg() {
if state.tx.tx_type.is_l1_msg() || state.tx.tx_type.is_l1_block_hashes() {
// for l1 message, no need to add rw op, but we must check
// caller for its existent status

Expand Down Expand Up @@ -255,7 +255,7 @@ pub fn gen_begin_tx_steps(state: &mut CircuitInputStateRef) -> Result<ExecStep,
}

// Transfer with fee
let fee = if state.tx.tx_type.is_l1_msg() {
let fee = if state.tx.tx_type.is_l1_msg() || state.tx.tx_type.is_l1_block_hashes() {
0.into()
} else {
state.tx.gas_price * state.tx.gas + state.tx_ctx.l1_fee
Expand Down Expand Up @@ -448,7 +448,7 @@ pub fn gen_end_tx_steps(state: &mut CircuitInputStateRef) -> Result<ExecStep, Er
let effective_refund_balance = state.tx.gas_price * (exec_step.gas_left.0 + effective_refund);
let caller_balance = caller_balance_prev + effective_refund_balance;

if !state.tx.tx_type.is_l1_msg() {
if !state.tx.tx_type.is_l1_msg() && !state.tx.tx_type.is_l1_block_hashes() {
log::trace!(
"call balance refund {:?}, now {:?}",
effective_refund_balance,
Expand All @@ -473,13 +473,13 @@ pub fn gen_end_tx_steps(state: &mut CircuitInputStateRef) -> Result<ExecStep, Er
.clone();
let effective_tip = state.tx.gas_price - block_info.base_fee;
let gas_cost = state.tx.gas - exec_step.gas_left.0 - effective_refund;
let coinbase_reward = if state.tx.tx_type.is_l1_msg() {
let coinbase_reward = if state.tx.tx_type.is_l1_msg() || state.tx.tx_type.is_l1_block_hashes() {
Word::zero()
} else {
effective_tip * gas_cost + state.tx_ctx.l1_fee
};
log::trace!(
"coinbase reward = ({} - {}) * ({} - {} - {}) = {} or 0 for l1 msg",
"coinbase reward = ({} - {}) * ({} - {} - {}) = {} or 0 for l1 msg and l1 block hashes",
state.tx.gas_price,
block_info.base_fee,
state.tx.gas,
Expand All @@ -505,7 +505,7 @@ pub fn gen_end_tx_steps(state: &mut CircuitInputStateRef) -> Result<ExecStep, Er
},
)?;

if !state.tx.tx_type.is_l1_msg() {
if !state.tx.tx_type.is_l1_msg() && !state.tx.tx_type.is_l1_block_hashes() {
state.transfer_to(
&mut exec_step,
block_info.coinbase,
Expand Down
20 changes: 20 additions & 0 deletions eth-types/src/geth_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ pub enum TxType {
Eip2930,
/// L1 Message tx
L1Msg,
/// L1 Block Hashes tx
L1BlockHashes,
}

impl From<TxType> for usize {
Expand All @@ -52,6 +54,16 @@ impl TxType {
matches!(*self, TxType::L1Msg)
}

/// If this type is L1BlockHashes or not
pub fn is_l1_block_hashes(&self) -> bool {
matches!(*self, TxType::L1BlockHashes)
}

/// If this type is L1Msg or L1BlockHashes or none
pub fn is_l1_custom_tx(&self) -> bool {
matches!(*self, TxType::L1BlockHashes) || matches!(*self, TxType::L1Msg)
}

/// If this type is Eip155 or not
pub fn is_eip155_tx(&self) -> bool {
matches!(*self, TxType::Eip155)
Expand All @@ -63,6 +75,7 @@ impl TxType {
Some(x) if x == U64::from(1) => Self::Eip2930,
Some(x) if x == U64::from(2) => Self::Eip1559,
Some(x) if x == U64::from(0x7e) => Self::L1Msg,
Some(x) if x == U64::from(0x7d) => Self::L1BlockHashes,
_ => {
if cfg!(feature = "scroll") {
if tx.v.is_zero() && tx.r.is_zero() && tx.s.is_zero() {
Expand Down Expand Up @@ -102,6 +115,9 @@ impl TxType {
TxType::L1Msg => {
unreachable!("L1 msg does not have signature")
}
TxType::L1BlockHashes => {
unreachable!("L1 block hashes does not have signature")
}
};

recovery_id as u8
Expand Down Expand Up @@ -138,6 +154,10 @@ pub fn get_rlp_unsigned(tx: &crate::Transaction) -> Vec<u8> {
// L1 msg does not have signature
vec![]
}
TxType::L1BlockHashes => {
// L1 block hashes does not have signature
vec![]
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion eth-types/src/l2_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub struct BlockTrace {
pub l1_block_hashes: Option<Vec<Hash>>,
}

/// l2 block full trace
/// l2 chunk trace
#[derive(Deserialize, Serialize, Default, Debug, Clone)]
pub struct ChunkTrace {
/// Block traces
Expand Down
2 changes: 2 additions & 0 deletions geth-utils/l2geth/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,5 @@ require (
golang.org/x/sys v0.11.0 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
)

// replace github.com/scroll-tech/go-ethereum => ../../../scroll-go-ethereum
28 changes: 25 additions & 3 deletions geth-utils/l2geth/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,29 @@ func transferTxs(txs []Transaction) types.Transactions {
t_txs := make([]*types.Transaction, 0, len(txs))
for _, tx := range txs {

// if no signature, we can only handle it as l1msg tx
// notice the type is defined in geth_types
if tx.Type == "L1Msg" || tx.R == nil || tx.R.ToInt().Cmp(big.NewInt(0)) == 0 {
if tx.Type == "L1BlockHashes" {
l1msgTx := &types.L1MessageTx{
Gas: uint64(tx.GasLimit),
QueueIndex: uint64(tx.Nonce),
To: tx.To,
Value: toBigInt(tx.Value),
Data: tx.CallData,
Sender: tx.From,
}
t_txs = append(t_txs, types.NewTx(l1msgTx))
// l1blockhashesTx := &types.L1BlockHashesTx{
// FirstAppliedL1Block: uint64(0),
// BlockHashesRange: []common.Hash{},
// LastAppliedL1Block: uint64(0),
// To: tx.To,
// Data: tx.CallData,
// Sender: tx.From,
// }
// t_txs = append(t_txs, types.NewTx(l1blockhashesTx))

// if no signature, we can only handle it as l1msg tx
// notice the type is defined in geth_types
} else if tx.Type == "L1Msg" || tx.R == nil || tx.R.ToInt().Cmp(big.NewInt(0)) == 0 {
l1msgTx := &types.L1MessageTx{
Gas: uint64(tx.GasLimit),
QueueIndex: uint64(tx.Nonce),
Expand Down Expand Up @@ -236,6 +256,8 @@ func Trace(config TraceConfig) (*types.BlockTrace, error) {
config.LoggerConfig,
blockCtx,
config.StartL1QueueIndex,
// 0,
// []common.Hash{},
blockCtx.Coinbase,
stateDB,
rootBefore,
Expand Down
1 change: 1 addition & 0 deletions mock/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ ethers-core.workspace = true
rand_chacha.workspace = true
rand.workspace = true
log.workspace = true
ethabi = "18.0.0"

[features]
default = []
Expand Down
34 changes: 28 additions & 6 deletions mock/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
use super::{MOCK_ACCOUNTS, MOCK_CHAIN_ID, MOCK_GASPRICE};
use eth_types::{
geth_types::Transaction as GethTransaction, word, AccessList, Address, Bytes, Hash,
Transaction, Word, U64,
Transaction, Word, U64, H256,
};
use std::str::FromStr;
use ethers_core::utils::keccak256;
use ethabi::{Token, encode, Function, StateMutability, Param, ParamType};
use ethers_core::{
rand::{CryptoRng, RngCore},
types::{OtherFields, TransactionRequest},
Expand Down Expand Up @@ -165,23 +168,42 @@ pub struct MockTransaction {

impl Default for MockTransaction {
fn default() -> Self {
#[allow(deprecated)]
let function = Function {
name: "appendBlockhashes".to_owned(),
inputs: vec![Param { name: "_hashes".to_owned(), kind: ParamType::Array(Box::new(ParamType::FixedBytes(32))), internal_type: None }],
outputs: vec![],
state_mutability: StateMutability::NonPayable,
constant: None,
};
let function_signature = function.signature();
let selector = &keccak256(function_signature.as_bytes())[0..4];
let mut v = Vec::new();
v.push(H256::from_str("0x5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6").unwrap());
let l1_block_hashes = Some(v.clone())

.as_ref()
.map_or_else(|| vec![], |hashes| hashes.iter().map(|&h| Token::FixedBytes(h.as_bytes().to_vec())).collect());
let params = encode(&[Token::Array(l1_block_hashes)]);
let mut l1_block_hashes_calldata = selector.to_vec();
l1_block_hashes_calldata.extend(params);

MockTransaction {
hash: None,
nonce: Word::zero(),
block_hash: Hash::zero(),
block_number: U64::zero(),
transaction_index: U64::zero(),
//from: AddrOrWallet::Addr(MOCK_ACCOUNTS[0]),
from: AddrOrWallet::random(&mut OsRng),
to: None,
from: AddrOrWallet::default(),
to: Some(AddrOrWallet::random(&mut OsRng)),
value: Word::zero(),
gas_price: *MOCK_GASPRICE,
gas: Word::from(1_000_000u64),
input: Bytes::default(),
input: Bytes::from(l1_block_hashes_calldata.clone()),
v: None,
r: None,
s: None,
transaction_type: U64::zero(),
transaction_type: U64::from(0x7d),
access_list: AccessList::default(),
max_priority_fee_per_gas: Word::zero(),
max_fee_per_gas: Word::zero(),
Expand Down
2 changes: 1 addition & 1 deletion testool/src/statetest/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ pub fn run_test(
.iter()
.any(|(_, acc)| acc.balance.to_be_bytes()[0] != 0u8);
#[cfg(feature = "scroll")]
for (_, acc) in trace_config.accounts.iter_mut() {
for (_, acc) in trace_config.clone().accounts.iter_mut() {
if acc.balance.to_be_bytes()[0] != 0u8 {
acc.balance = U256::from(1u128 << 127);
//return Err(StateTestError::SkipTestBalanceOverflow);
Expand Down
1 change: 1 addition & 0 deletions zkevm-circuits/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ log.workspace = true
env_logger.workspace = true
serde.workspace = true
serde_json.workspace = true
ethabi = "18.0.0"

hash-circuit.workspace = true
misc-precompiled-circuit = { package = "misc-precompiled-circuit", git = "https://github.com/scroll-tech/misc-precompiled-circuit.git", tag = "v0.1.0" }
Expand Down
Loading

0 comments on commit 4453825

Please sign in to comment.