Skip to content
This repository was archived by the owner on Apr 18, 2025. It is now read-only.

Commit 90b591c

Browse files
authored
feat: update pi circuit to be compatible with the latest bridge contract (#544)
* feat: refactor pi circuit to latest (wip) * do not include parent_hash in block table * pi circuit tests reorg * move constants to params * use copy constraints to enforce pi fields' validity * add rpi_padding related constraints * update dummy_tx to be pre-eip155 tx * finish rpi padding constraints * update keccak inputs for pi circuit * update (chain_id, hi, lo) instance into bytes * fmt * chain_id is u64 now * copy chain_id from pi to tx table
1 parent 3432f28 commit 90b591c

File tree

12 files changed

+939
-1050
lines changed

12 files changed

+939
-1050
lines changed

bus-mapping/src/circuit_input_builder.rs

Lines changed: 38 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -587,19 +587,18 @@ pub fn keccak_inputs(block: &Block, code_db: &CodeDB) -> Result<Vec<Vec<u8>>, Er
587587
let mut keccak_inputs = Vec::new();
588588
// Tx Circuit
589589
let txs: Vec<geth_types::Transaction> = block.txs.iter().map(|tx| tx.into()).collect();
590-
keccak_inputs.extend_from_slice(&keccak_inputs_tx_circuit(&txs, block.chain_id())?);
590+
keccak_inputs.extend_from_slice(&keccak_inputs_tx_circuit(&txs)?);
591591
log::debug!(
592592
"keccak total len after txs: {}",
593593
keccak_inputs.iter().map(|i| i.len()).sum::<usize>()
594594
);
595595
// PI circuit
596-
keccak_inputs.push(keccak_inputs_pi_circuit(
597-
block.chain_id(),
596+
keccak_inputs.extend(keccak_inputs_pi_circuit(
597+
block.chain_id,
598598
block.prev_state_root,
599599
block.withdraw_root,
600600
&block.headers,
601601
block.txs(),
602-
block.circuits_params.max_txs,
603602
));
604603
// Bytecode Circuit
605604
for _bytecode in code_db.0.values() {
@@ -645,10 +644,10 @@ pub fn keccak_inputs_sign_verify(sigs: &[SignData]) -> Vec<Vec<u8>> {
645644
inputs
646645
}
647646

648-
/// Generate a dummy tx in which
649-
/// (nonce=0, gas=0, gas_price=0, to=0, value=0, data="", chain_id)
647+
/// Generate a dummy pre-eip155 tx in which
648+
/// (nonce=0, gas=0, gas_price=0, to=0, value=0, data="")
650649
/// using the dummy private key = 1
651-
pub fn get_dummy_tx(chain_id: u64) -> (TransactionRequest, Signature) {
650+
pub fn get_dummy_tx() -> (TransactionRequest, Signature) {
652651
let mut sk_be_scalar = [0u8; 32];
653652
sk_be_scalar[31] = 1_u8;
654653

@@ -661,22 +660,28 @@ pub fn get_dummy_tx(chain_id: u64) -> (TransactionRequest, Signature) {
661660
.gas_price(U256::zero())
662661
.to(Address::zero())
663662
.value(U256::zero())
664-
.data(Bytes::default())
665-
.chain_id(chain_id);
663+
.data(Bytes::default());
664+
let sighash: H256 = keccak256(tx.rlp_unsigned()).into();
666665

667666
// FIXME: need to check if this is deterministic which means sig is fixed.
668-
let sig = wallet.sign_transaction_sync(&tx.clone().into());
667+
let sig = wallet.sign_hash(sighash);
668+
assert_eq!(sig.v, 28);
669669

670670
(tx, sig)
671671
}
672672

673673
/// Get the tx hash of the dummy tx (nonce=0, gas=0, gas_price=0, to=0, value=0,
674-
/// data="") for any chain_id
675-
pub fn get_dummy_tx_hash(chain_id: u64) -> H256 {
676-
let (tx, sig) = get_dummy_tx(chain_id);
674+
/// data="")
675+
pub fn get_dummy_tx_hash() -> H256 {
676+
let (tx, sig) = get_dummy_tx();
677677

678678
let tx_hash = keccak256(tx.rlp_signed(&sig));
679679

680+
assert_eq!(
681+
hex::encode(tx_hash),
682+
"137c41d53f2e633af81c75e938f6ccf7298ad6d2fa698b19a50545c1ae5b2b85"
683+
);
684+
680685
H256(tx_hash)
681686
}
682687

@@ -686,59 +691,43 @@ fn keccak_inputs_pi_circuit(
686691
withdraw_trie_root: Word,
687692
block_headers: &BTreeMap<u64, BlockHead>,
688693
transactions: &[Transaction],
689-
max_txs: usize,
690-
) -> Vec<u8> {
691-
let dummy_tx_hash = get_dummy_tx_hash(chain_id);
692-
693-
let result = iter::empty()
694-
// state roots
695-
.chain(prev_state_root.to_be_bytes())
696-
.chain(
697-
block_headers
698-
.last_key_value()
699-
.map(|(_, blk)| blk.eth_block.state_root)
700-
.unwrap_or(H256(prev_state_root.to_be_bytes()))
701-
.to_fixed_bytes(),
702-
)
703-
// withdraw trie root
704-
.chain(withdraw_trie_root.to_be_bytes())
694+
) -> Vec<Vec<u8>> {
695+
let data_bytes = iter::empty()
705696
.chain(block_headers.iter().flat_map(|(block_num, block)| {
706697
let num_txs = transactions
707698
.iter()
708699
.filter(|tx| tx.block_num == *block_num)
709700
.count() as u16;
710-
let parent_hash = block.eth_block.parent_hash;
711-
let block_hash = block.eth_block.hash.unwrap_or(H256::zero());
712-
let num_l1_msgs = 0_u16; // 0 for now
713701

714702
iter::empty()
715703
// Block Values
716-
.chain(block_hash.to_fixed_bytes())
717-
.chain(parent_hash.to_fixed_bytes()) // parent hash
718704
.chain(block.number.as_u64().to_be_bytes())
719705
.chain(block.timestamp.as_u64().to_be_bytes())
720706
.chain(block.base_fee.to_be_bytes())
721707
.chain(block.gas_limit.to_be_bytes())
722708
.chain(num_txs.to_be_bytes())
723-
.chain(num_l1_msgs.to_be_bytes())
724709
}))
725710
// Tx Hashes
726711
.chain(transactions.iter().flat_map(|tx| tx.hash.to_fixed_bytes()))
727-
.chain(
728-
(0..(max_txs - transactions.len()))
729-
.into_iter()
730-
.flat_map(|_| dummy_tx_hash.to_fixed_bytes()),
731-
)
712+
.collect::<Vec<u8>>();
713+
let data_hash = H256(keccak256(&data_bytes));
714+
let after_state_root = block_headers
715+
.last_key_value()
716+
.map(|(_, blk)| blk.eth_block.state_root)
717+
.unwrap_or(H256(prev_state_root.to_be_bytes()));
718+
let pi_bytes = iter::empty()
719+
.chain(chain_id.to_be_bytes())
720+
.chain(prev_state_root.to_be_bytes())
721+
.chain(after_state_root.to_fixed_bytes())
722+
.chain(withdraw_trie_root.to_be_bytes())
723+
.chain(data_hash.to_fixed_bytes())
732724
.collect::<Vec<u8>>();
733725

734-
result
726+
vec![data_bytes, pi_bytes]
735727
}
736728

737729
/// Generate the keccak inputs required by the Tx Circuit from the transactions.
738-
pub fn keccak_inputs_tx_circuit(
739-
txs: &[geth_types::Transaction],
740-
chain_id: u64,
741-
) -> Result<Vec<Vec<u8>>, Error> {
730+
pub fn keccak_inputs_tx_circuit(txs: &[geth_types::Transaction]) -> Result<Vec<Vec<u8>>, Error> {
742731
let mut inputs = Vec::new();
743732

744733
let hash_datas = txs
@@ -747,7 +736,7 @@ pub fn keccak_inputs_tx_circuit(
747736
.collect::<Vec<Vec<u8>>>();
748737
let dummy_hash_data = {
749738
// dummy tx is a legacy tx.
750-
let (dummy_tx, dummy_sig) = get_dummy_tx(chain_id);
739+
let (dummy_tx, dummy_sig) = get_dummy_tx();
751740
dummy_tx.rlp_signed(&dummy_sig).to_vec()
752741
};
753742
inputs.extend_from_slice(&hash_datas);
@@ -783,8 +772,9 @@ pub fn keccak_inputs_tx_circuit(
783772
// one that we use in get_dummy_tx, so we only need to include the tx sign
784773
// hash of the dummy tx.
785774
let dummy_sign_input = {
786-
let (dummy_tx, _) = get_dummy_tx(chain_id);
787-
dummy_tx.rlp().to_vec()
775+
let (dummy_tx, _) = get_dummy_tx();
776+
// dummy tx is of type pre-eip155
777+
dummy_tx.rlp_unsigned().to_vec()
788778
};
789779
inputs.push(dummy_sign_input);
790780

circuit-benchmarks/src/pi_circuit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ mod tests {
2525
use rand::SeedableRng;
2626
use rand_xorshift::XorShiftRng;
2727
use zkevm_circuits::{
28-
pi_circuit::{PiCircuit, PiTestCircuit},
28+
pi_circuit::{dev::PiTestCircuit, PiCircuit},
2929
util::SubCircuit,
3030
witness::{block_convert, Block},
3131
};

zkevm-circuits/src/evm_circuit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ impl<F: Field> Circuit<F> for EvmCircuit<F> {
457457
.dev_load(&mut layouter, block.bytecodes.values(), &challenges)?;
458458
config
459459
.block_table
460-
.dev_load(&mut layouter, &block.context, &block.txs, 1, &challenges)?;
460+
.dev_load(&mut layouter, &block.context, &block.txs, &challenges)?;
461461
config
462462
.copy_table
463463
.dev_load(&mut layouter, block, &challenges)?;

0 commit comments

Comments
 (0)