Skip to content

Commit

Permalink
Enable valid MockTx generation & move it's generation to mock crate (p…
Browse files Browse the repository at this point in the history
…rivacy-scaling-explorations#701)

* feat: Enable valid MockTx generation

In order to be able to generate Tx objects with full customization
possibilities and, at the same time, have consistent Txs with the
correct hash and signatures, it was required an upgrade on the
`MockTransaction` structure to allow for that.

This includes the following:
- Addition of `AddrOrWallet` enum to keep backwards compatibility and
  allow for simple Tx generations for Opcode testing purposes with just
  addresses or more complex cases where a Wallet is required so that the
  Tx can be correctly signed.
- Refactor of the `MockTransaction` struct making some fields optional
  to preserve the compatibility with all other tests.
- Refactor of the `MockTransaction::build` function to compute the
  signature and tx_hash only when it has not been specified and it is
  possible.

This resolves privacy-scaling-explorations#677 bringing back the generation of Mock structures for
testing to the mock crate and removing it from any other workspace
member.

* chore: Add docs for AddrOrWallet assoc methods

* change: Replace Tx generations with rand_tx for MockTransaction

* chore: Add ethers{signers,core} to mock deps

* Update Cargo.lock

* fix: hash & signature computation on build

The computation of the hash and the signature params has to be done only
if these params haven't been set already. This fixes it.

Also, include & export 3 `MockTransaction`s correctly signed & hashed so
that can be easily used by tests as it happens with the `MockAccount`s
for example.

* add: `MockWallet`s exported via mock crate

* chore: Add rand_chacha & rand to deps

* change: Update tests & benches to use mock's new methods

* update: Cargo.lock

* add: Conversion method from TxResponse and GethTransaction

* fix: Fix sigdata params setting order in build fn

* change: Use mock structs in tests instead of building them

* fix: Clippy suggestions

* fix: Do rlp for TransactionRequest instead of Transaction

* fix: Remove unnecessary clone

* fix: Complete the usage of From/Into for Transaction

* fix: Address review comments

* fix: Apply 2nd review round suggestions

* feat: Enable valid MockTx generation

In order to be able to generate Tx objects with full customization
possibilities and, at the same time, have consistent Txs with the
correct hash and signatures, it was required an upgrade on the
`MockTransaction` structure to allow for that.

This includes the following:
- Addition of `AddrOrWallet` enum to keep backwards compatibility and
  allow for simple Tx generations for Opcode testing purposes with just
  addresses or more complex cases where a Wallet is required so that the
  Tx can be correctly signed.
- Refactor of the `MockTransaction` struct making some fields optional
  to preserve the compatibility with all other tests.
- Refactor of the `MockTransaction::build` function to compute the
  signature and tx_hash only when it has not been specified and it is
  possible.

This resolves privacy-scaling-explorations#677 bringing back the generation of Mock structures for
testing to the mock crate and removing it from any other workspace
member.

* chore: Add docs for AddrOrWallet assoc methods

* change: Replace Tx generations with rand_tx for MockTransaction

* chore: Add ethers{signers,core} to mock deps

* Update Cargo.lock

* fix: hash & signature computation on build

The computation of the hash and the signature params has to be done only
if these params haven't been set already. This fixes it.

Also, include & export 3 `MockTransaction`s correctly signed & hashed so
that can be easily used by tests as it happens with the `MockAccount`s
for example.

* add: `MockWallet`s exported via mock crate

* chore: Add rand_chacha & rand to deps

* change: Update tests & benches to use mock's new methods

* update: Cargo.lock

* add: Conversion method from TxResponse and GethTransaction

* fix: Fix sigdata params setting order in build fn

* change: Use mock structs in tests instead of building them

* fix: Clippy suggestions

* fix: Do rlp for TransactionRequest instead of Transaction

* fix: Remove unnecessary clone

* fix: Complete the usage of From/Into for Transaction

* fix: Address review comments

* fix: Apply 2nd review round suggestions

* fix: Support SigData with all params set in MockTransaction::build
  • Loading branch information
CPerezz authored Aug 23, 2022
1 parent c840a66 commit ff687f3
Show file tree
Hide file tree
Showing 11 changed files with 278 additions and 133 deletions.
5 changes: 4 additions & 1 deletion Cargo.lock

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

27 changes: 4 additions & 23 deletions circuit-benchmarks/src/tx_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ mod tests {
use crate::bench_params::DEGREE;
use ark_std::{end_timer, start_timer};
use env_logger::Env;
use eth_types::{address, geth_types::Transaction, word, Bytes};
use group::{Curve, Group};
use halo2_proofs::arithmetic::{BaseExt, CurveAffine};
use halo2_proofs::plonk::{create_proof, keygen_pk, keygen_vk, verify_proof, SingleVerifier};
Expand All @@ -15,7 +14,7 @@ mod tests {
transcript::{Blake2bRead, Blake2bWrite, Challenge255},
};
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;
use rand_chacha::ChaCha20Rng;
use secp256k1::Secp256k1Affine;
use std::marker::PhantomData;
use zkevm_circuits::tx_circuit::{
Expand All @@ -33,31 +32,13 @@ mod tests {
const MAX_TXS: usize = 2_usize.pow(DEGREE as u32) / ROWS_PER_TX;
const MAX_CALLDATA: usize = 1024;

let mut rng = XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06,
0xbc, 0xe5,
]);
let mut rng = ChaCha20Rng::seed_from_u64(42);

let aux_generator =
<Secp256k1Affine as CurveAffine>::CurveExt::random(&mut rng).to_affine();
let chain_id: u64 = 1337;

// Transaction generated with `zkevm-circuits/src/tx_circuit.rs:rand_tx` using
// `rng = ChaCha20Rng::seed_from_u64(42)`
let txs = vec![Transaction {
from: address!("0x5f9b7e36af4ff81688f712fb738bbbc1b7348aae"),
to: Some(address!("0x701653d7ae8ddaa5c8cee1ee056849f271827926")),
nonce: word!("0x3"),
gas_limit: word!("0x7a120"),
value: word!("0x3e8"),
gas_price: word!("0x4d2"),
gas_fee_cap: word!("0x0"),
gas_tip_cap: word!("0x0"),
call_data: Bytes::from(b"hello"),
access_list: None,
v: 2710,
r: word!("0xaf180d27f90b2b20808bc7670ce0aca862bc2b5fa39c195ab7b1a96225ee14d7"),
s: word!("0x61159fa4664b698ea7d518526c96cd94cf4d8adf418000754be106a3a133f866"),
}];
let txs = vec![mock::CORRECT_MOCK_TXS[0].clone().into()];

let randomness = Fr::from(0xcafeu64);
let mut instance: Vec<Vec<Fr>> = (1..POW_RAND_SIZE + 1)
Expand Down
41 changes: 37 additions & 4 deletions eth-types/src/geth_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,30 @@ pub struct Transaction {
pub s: Word,
}

impl Transaction {
/// Create Self from a web3 transaction
pub fn from_eth_tx(tx: &crate::Transaction) -> Self {
Self {
impl From<&Transaction> for crate::Transaction {
fn from(tx: &Transaction) -> crate::Transaction {
crate::Transaction {
from: tx.from,
to: tx.to,
nonce: tx.nonce,
gas: tx.gas_limit,
value: tx.value,
gas_price: Some(tx.gas_price),
max_priority_fee_per_gas: Some(tx.gas_fee_cap),
max_fee_per_gas: Some(tx.gas_tip_cap),
input: tx.call_data.clone(),
access_list: tx.access_list.clone(),
v: tx.v.into(),
r: tx.r,
s: tx.s,
..Default::default()
}
}
}

impl From<&crate::Transaction> for Transaction {
fn from(tx: &crate::Transaction) -> Transaction {
Transaction {
from: tx.from,
to: tx.to,
nonce: tx.nonce,
Expand All @@ -145,6 +165,19 @@ impl Transaction {
}
}

impl From<Transaction> for ethers_core::types::TransactionRequest {
fn from(tx: Transaction) -> ethers_core::types::TransactionRequest {
TransactionRequest::new()
.from(tx.from)
.to(tx.to.unwrap())
.nonce(tx.nonce)
.value(tx.value)
.data(tx.call_data.clone())
.gas(tx.gas_limit)
.gas_price(tx.gas_price)
}
}

/// GethData is a type that contains all the information of a Ethereum block
#[derive(Debug, Clone)]
pub struct GethData {
Expand Down
2 changes: 1 addition & 1 deletion integration-tests/tests/circuits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ async fn test_tx_circuit_block(block_num: u64) {
let txs: Vec<_> = eth_block
.transactions
.iter()
.map(geth_types::Transaction::from_eth_tx)
.map(geth_types::Transaction::from)
.collect();

let mut rng = ChaCha20Rng::seed_from_u64(2);
Expand Down
4 changes: 4 additions & 0 deletions mock/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,7 @@ external-tracer = { path = "../external-tracer" }
lazy_static = "1.4"
ethbloom = "0.11.1"
itertools = "0.10.3"
ethers-signers = "0.6"
ethers-core = "0.6"
rand_chacha = "0.3"
rand = "0.8"
16 changes: 15 additions & 1 deletion mock/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
//! Mock types and functions to generate GethData used for tests
use eth_types::{address, Address, Word};
use ethers_signers::LocalWallet;
use lazy_static::lazy_static;
use rand::SeedableRng;
use rand_chacha::ChaCha20Rng;
mod account;
mod block;
pub mod test_ctx;
Expand All @@ -10,7 +13,7 @@ mod transaction;
pub(crate) use account::MockAccount;
pub(crate) use block::MockBlock;
pub use test_ctx::TestContext;
pub(crate) use transaction::MockTransaction;
pub use transaction::{AddrOrWallet, MockTransaction, CORRECT_MOCK_TXS};

lazy_static! {
/// Mock coinbase value
Expand All @@ -28,12 +31,23 @@ lazy_static! {
address!("0x000000000000000000000000000000000cafe444"),
address!("0x000000000000000000000000000000000cafe555"),
];
/// Mock wallets used to generate correctly signed and hashed Transactions.
pub static ref MOCK_WALLETS: Vec<LocalWallet> = {
let mut rng = ChaCha20Rng::seed_from_u64(2u64);
vec![
LocalWallet::new(&mut rng),
LocalWallet::new(&mut rng),
LocalWallet::new(&mut rng),
]
};
}

/// Generate a [`Word`] which corresponds to a certain amount of ETH.
pub fn eth(x: u64) -> Word {
Word::from(x) * Word::from(10u64.pow(18))
}

/// Express an amount of ETH in GWei.
pub fn gwei(x: u64) -> Word {
Word::from(x) * Word::from(10u64.pow(9))
}
2 changes: 1 addition & 1 deletion mock/src/test_ctx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ fn gen_geth_traces<const NACC: usize, const NTX: usize>(
transactions: block
.transactions
.iter()
.map(eth_types::geth_types::Transaction::from_eth_tx)
.map(eth_types::geth_types::Transaction::from)
.collect(),
logger_config,
};
Expand Down
Loading

0 comments on commit ff687f3

Please sign in to comment.