Skip to content

Commit

Permalink
feat: refactor rlp circuit and tx circuit to support more tx types (p…
Browse files Browse the repository at this point in the history
…rivacy-scaling-explorations#528)

* wip

* wip 22

* wip 3

* wip 4

* wip 5

* wip 6

* wip 7

* wip 8

* wip 9

* wip 10

* wip 11

* wip 12

* wip 13

* wip 14

* wip 15

* wip 16

* wip 17

* wip 18

* wip 19

* add macros

* addressing some comments

* rewrite constraint (part 1)

* reduce condition degree

* rewrite constraint (part 2)

* rewrite constraint (part 3)

* rewrite constraint (part 4)

* rewrite constraint (part 5)

* add docs

* docs

* data table assignments

* add witness gen part 1

* add more fields for supporting pre-eip155 tx

* add witness gen part 2

* add witness gen part 3

* finish gen_sm_witness

* pass eip1559 rlp witness test

* refactor

* add pre-eip155 test case

* add unit test in rlp_circuit_fsm

* pass pre-eip155 tx unit test in rlp circuit

* fix constraint errors part 1

* fix witness gen bug

* update unit test

* fix constraint errors (part 2)

* add eip155 tx test

* make witness gen more precise

* update data table checks

* fix clippy errors

* fix clippy

* fix clippy

* fmt

* update sm checks

* reduce degree to 9

* add eip1559 test and add constraints on DecodeTagStart -> End

* finish padding

* move away RLP internal tables from table.rs

* remove old rlp circuit

* re-organize tests in rlp_circuit_fsm into its own dir

* clean

* clean

* disable tx circuit

* fmt

* clippy

* fix typo

* fix a bug in keccak circuit's min_num_rows_block

* move q_enable to RlpTable

* finish rom of l1_msg_hash

* add sm init checks

* remove old RlpTable

* fix typos and refine comments

* bug-fix: use max_length to select b to accumulate bytes' value

* update tx_data_gas_cost calc rule

* clean

* ignore tx_l1_fee unit tests in evm_circuit

* refactor tx_circuit

* add empty row

* turn on the tx_circuit

* fix clippy errors

* fmt

* fix

* assign padding_tx in rlp circuit

* clean

* pass pre-eip155 tx test

* clippy and add constraints on sig.v

* ignore null signature

* add ChainID

* dep: use scroll tech's fork of ethers-rs

* refactor

* add l1 msg tx test in rlp circuit

* pass l1 msg unit test in tx circuit

* finish

* update Cargo.lock

* fix

* refactor: move is_zero to util/

* add doc

---------

Co-authored-by: Rohit Narurkar <rohit.narurkar@protonmail.com>
  • Loading branch information
kunxian-xia and roynalnaruto authored Jun 8, 2023
1 parent 801a048 commit 79caaf4
Show file tree
Hide file tree
Showing 37 changed files with 4,852 additions and 4,303 deletions.
25 changes: 16 additions & 9 deletions Cargo.lock

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

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ members = [
"testool"
]

[patch.crates-io]
ethers-core = { git = "https://github.com/scroll-tech/ethers-rs.git", branch = "v0.17.0" }
ethers-etherscan = { git = "https://github.com/scroll-tech/ethers-rs.git", branch = "v0.17.0" }
[patch."https://github.com/privacy-scaling-explorations/halo2.git"]
halo2_proofs = { git = "https://github.com/scroll-tech/halo2.git", branch = "v0.4" }
[patch."https://github.com/privacy-scaling-explorations/poseidon.git"]
Expand Down
45 changes: 18 additions & 27 deletions bus-mapping/src/circuit_input_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use eth_types::{
};
use ethers_core::{
k256::ecdsa::SigningKey,
types::{Bytes, NameOrAddress, Signature, TransactionRequest},
types::{Bytes, Signature, TransactionRequest},
};
use ethers_providers::JsonRpcClient;
pub use execution::{
Expand Down Expand Up @@ -62,6 +62,8 @@ pub struct CircuitsParams {
pub max_txs: usize,
/// Maximum number of bytes from all txs calldata in the Tx Circuit
pub max_calldata: usize,
/// Maximum number of rows that the RLP Circuit can have
pub max_rlp_rows: usize,
/// Max amount of rows that the CopyCircuit can have.
pub max_copy_rows: usize,
/// Maximum number of inner blocks in a batch
Expand Down Expand Up @@ -103,6 +105,7 @@ impl Default for CircuitsParams {
max_bytecode: 512,
max_evm_rows: 0,
max_keccak_rows: 0,
max_rlp_rows: 1000,
}
}
}
Expand Down Expand Up @@ -740,27 +743,7 @@ pub fn keccak_inputs_tx_circuit(

let hash_datas = txs
.iter()
.map(|tx| {
let sig = Signature {
r: tx.r,
s: tx.s,
v: tx.v,
};
let mut tx: TransactionRequest = tx.into();
if tx.to.is_some() {
let to = tx.to.clone().unwrap();
match to {
NameOrAddress::Name(_) => {}
NameOrAddress::Address(addr) => {
// the rlp of zero addr is 0x80
if addr == Address::zero() {
tx.to = None;
}
}
}
}
tx.rlp_signed(&sig).to_vec()
})
.map(|tx| tx.rlp_bytes.clone())
.collect::<Vec<Vec<u8>>>();
let dummy_hash_data = {
// dummy tx is a legacy tx.
Expand All @@ -774,14 +757,23 @@ pub fn keccak_inputs_tx_circuit(
.iter()
.enumerate()
.filter(|(i, tx)| {
if tx.v == 0 && tx.r.is_zero() && tx.s.is_zero() {
warn!("tx {} is not signed, skipping tx circuit keccak input", i);
if !tx.tx_type.is_l1_msg() && 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
);
false
} else {
true
}
})
.map(|(_, tx)| tx.sign_data(chain_id))
.map(|(_, tx)| {
if tx.tx_type.is_l1_msg() {
Ok(SignData::default())
} else {
tx.sign_data()
}
})
.try_collect()?;
// Keccak inputs from SignVerify Chip
let sign_verify_inputs = keccak_inputs_sign_verify(&sign_datas);
Expand All @@ -795,8 +787,7 @@ pub fn keccak_inputs_tx_circuit(
dummy_tx.rlp().to_vec()
};
inputs.push(dummy_sign_input);
// NOTE: We don't verify the Tx Hash in the circuit yet, so we don't have more
// hash inputs.

Ok(inputs)
}

Expand Down
41 changes: 30 additions & 11 deletions bus-mapping/src/circuit_input_builder/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ use std::collections::BTreeMap;

use eth_types::{
evm_types::{gas_utils::tx_data_gas_cost, Memory},
geth_types, Address, GethExecTrace, Signature, Word, H256,
geth_types,
geth_types::{get_rlp_unsigned, TxType},
Address, GethExecTrace, Signature, Word, H256,
};
use ethers_core::{types::TransactionRequest, utils::get_contract_address};
use ethers_core::utils::get_contract_address;

use crate::{
l2_predeployed::l1_gas_price_oracle,
Expand Down Expand Up @@ -191,6 +193,8 @@ impl TransactionContext {
pub struct Transaction {
/// ..
pub block_num: u64,
/// Type
pub tx_type: TxType,
/// Nonce
pub nonce: u64,
/// Hash
Expand All @@ -199,6 +203,10 @@ pub struct Transaction {
pub gas: u64,
/// Gas price
pub gas_price: Word,
/// Gas fee cap
pub gas_fee_cap: Word,
/// Gas tip cap
pub gas_tip_cap: Word,
/// From / Caller Address
pub from: Address,
/// To / Callee Address
Expand All @@ -211,6 +219,10 @@ pub struct Transaction {
pub chain_id: u64,
/// Signature
pub signature: Signature,
/// RLP bytes
pub rlp_bytes: Vec<u8>,
/// RLP bytes for signing
pub rlp_unsigned_bytes: Vec<u8>,
/// Current values of L1 fee
pub l1_fee: TxL1Fee,
/// Committed values of L1 fee
Expand All @@ -235,24 +247,24 @@ impl From<&Transaction> for geth_types::Transaction {
v: tx.signature.v,
r: tx.signature.r,
s: tx.signature.s,
gas_fee_cap: tx.gas_fee_cap,
gas_tip_cap: tx.gas_tip_cap,
rlp_unsigned_bytes: tx.rlp_unsigned_bytes.clone(),
rlp_bytes: tx.rlp_bytes.clone(),
..Default::default()
}
}
}

impl From<&Transaction> for TransactionRequest {
fn from(tx: &Transaction) -> TransactionRequest {
(&Into::<geth_types::Transaction>::into(tx)).into()
}
}

impl Transaction {
/// Create a dummy Transaction with zero values
pub fn dummy() -> Self {
Self {
nonce: 0,
gas: 0,
gas_price: Word::zero(),
gas_fee_cap: Word::zero(),
gas_tip_cap: Word::zero(),
from: Address::zero(),
to: Address::zero(),
value: Word::zero(),
Expand All @@ -263,10 +275,13 @@ impl Transaction {
s: Word::zero(),
v: 0,
},
rlp_bytes: vec![],
rlp_unsigned_bytes: vec![],
calls: Vec::new(),
steps: Vec::new(),
block_num: Default::default(),
hash: Default::default(),
tx_type: Default::default(),
l1_fee: Default::default(),
l1_fee_committed: Default::default(),
}
Expand Down Expand Up @@ -352,9 +367,14 @@ impl Transaction {
Ok(Self {
block_num: eth_tx.block_number.unwrap().as_u64(),
hash: eth_tx.hash,
tx_type: TxType::get_tx_type(eth_tx),
rlp_bytes: eth_tx.rlp().to_vec(),
rlp_unsigned_bytes: get_rlp_unsigned(eth_tx),
nonce: eth_tx.nonce.as_u64(),
gas: eth_tx.gas.as_u64(),
gas_price: eth_tx.gas_price.unwrap_or_default(),
gas_fee_cap: eth_tx.max_fee_per_gas.unwrap_or_default(),
gas_tip_cap: eth_tx.max_priority_fee_per_gas.unwrap_or_default(),
from: eth_tx.from,
to: eth_tx.to.unwrap_or_default(),
value: eth_tx.value,
Expand Down Expand Up @@ -419,8 +439,7 @@ impl Transaction {

/// Calculate L1 fee of this transaction.
pub fn l1_fee(&self) -> u64 {
let tx_data_gas_cost =
tx_data_gas_cost(&Into::<TransactionRequest>::into(self).rlp_unsigned());
let tx_data_gas_cost = tx_data_gas_cost(&self.rlp_bytes);

self.l1_fee.tx_l1_fee(tx_data_gas_cost).0
}
Expand All @@ -441,7 +460,7 @@ impl TxL1Fee {
/// Calculate L1 fee and remainder of transaction.
pub fn tx_l1_fee(&self, tx_data_gas_cost: u64) -> (u64, u64) {
// <https://github.com/scroll-tech/go-ethereum/blob/49192260a177f1b63fc5ea3b872fb904f396260c/rollup/fees/rollup_fee.go#L118>
let tx_l1_gas = tx_data_gas_cost + 1088 + self.fee_overhead;
let tx_l1_gas = tx_data_gas_cost + self.fee_overhead;
let tx_l1_fee = self.fee_scalar as u128 * self.base_fee as u128 * tx_l1_gas as u128;

(
Expand Down
1 change: 1 addition & 0 deletions circuit-benchmarks/src/super_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ mod tests {
max_evm_rows: 0,
max_inner_blocks: MAX_INNER_BLOCKS,
max_keccak_rows: 0,
max_rlp_rows: 256,
};
let (_, circuit, instance, _) =
SuperCircuit::<_, MAX_TXS, MAX_CALLDATA, MAX_INNER_BLOCKS, 0x100>::build(
Expand Down
1 change: 1 addition & 0 deletions circuit-benchmarks/src/tx_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ mod tests {
max_keccak_rows: 0, // FIXME: can this be none?
max_exp_steps: 100_000,
max_evm_rows: 4_000_000,
max_rlp_rows: 4_000_000,
};
let cli = BuilderClient::new(cli, params).await.unwrap();
let (builder, _) = cli.gen_inputs(block_num).await.unwrap();
Expand Down
Loading

0 comments on commit 79caaf4

Please sign in to comment.