diff --git a/evm/src/cpu/kernel/asm/main.asm b/evm/src/cpu/kernel/asm/main.asm index e87b790cba..93503add18 100644 --- a/evm/src/cpu/kernel/asm/main.asm +++ b/evm/src/cpu/kernel/asm/main.asm @@ -7,9 +7,9 @@ global main: %jump(load_all_mpts) global hash_initial_tries: - %mpt_hash_state_trie %mstore_global_metadata(@GLOBAL_METADATA_STATE_TRIE_DIGEST_BEFORE) - %mpt_hash_txn_trie %mstore_global_metadata(@GLOBAL_METADATA_TXN_TRIE_DIGEST_BEFORE) - %mpt_hash_receipt_trie %mstore_global_metadata(@GLOBAL_METADATA_RECEIPT_TRIE_DIGEST_BEFORE) + %mpt_hash_state_trie %mload_global_metadata(@GLOBAL_METADATA_STATE_TRIE_DIGEST_BEFORE) %assert_eq + %mpt_hash_txn_trie %mload_global_metadata(@GLOBAL_METADATA_TXN_TRIE_DIGEST_BEFORE) %assert_eq + %mpt_hash_receipt_trie %mload_global_metadata(@GLOBAL_METADATA_RECEIPT_TRIE_DIGEST_BEFORE) %assert_eq global txn_loop: // If the prover has no more txns for us to process, halt. @@ -21,7 +21,7 @@ global txn_loop: %jump(route_txn) global hash_final_tries: - %mpt_hash_state_trie %mstore_global_metadata(@GLOBAL_METADATA_STATE_TRIE_DIGEST_AFTER) - %mpt_hash_txn_trie %mstore_global_metadata(@GLOBAL_METADATA_TXN_TRIE_DIGEST_AFTER) - %mpt_hash_receipt_trie %mstore_global_metadata(@GLOBAL_METADATA_RECEIPT_TRIE_DIGEST_AFTER) + %mpt_hash_state_trie %mload_global_metadata(@GLOBAL_METADATA_STATE_TRIE_DIGEST_AFTER) %assert_eq + %mpt_hash_txn_trie %mload_global_metadata(@GLOBAL_METADATA_TXN_TRIE_DIGEST_AFTER) %assert_eq + %mpt_hash_receipt_trie %mload_global_metadata(@GLOBAL_METADATA_RECEIPT_TRIE_DIGEST_AFTER) %assert_eq %jump(halt) diff --git a/evm/src/fixed_recursive_verifier.rs b/evm/src/fixed_recursive_verifier.rs index 8e3bfb628f..3ca1221345 100644 --- a/evm/src/fixed_recursive_verifier.rs +++ b/evm/src/fixed_recursive_verifier.rs @@ -38,7 +38,7 @@ use crate::keccak_sponge::keccak_sponge_stark::KeccakSpongeStark; use crate::logic::LogicStark; use crate::memory::memory_stark::MemoryStark; use crate::memory::segments::Segment; -use crate::memory::{NUM_CHANNELS, VALUE_LIMBS}; +use crate::memory::VALUE_LIMBS; use crate::permutation::{ get_grand_product_challenge_set_target, GrandProductChallenge, GrandProductChallengeSet, }; @@ -647,7 +647,7 @@ where prod = builder.mul(prod, combined); }); - // Add public values reads. + // Add trie roots writes. let trie_fields = [ ( GlobalMetadata::StateTrieRootDigestBefore, @@ -675,15 +675,10 @@ where ), ]; - let mut timestamp_target = builder.mul_const( - F::from_canonical_usize(NUM_CHANNELS), - public_values.cpu_trace_len, - ); - timestamp_target = builder.add_const(timestamp_target, F::ONE); trie_fields.map(|(field, targets)| { let row = builder.add_virtual_targets(13); // is_read - builder.connect(row[0], one); + builder.connect(row[0], zero); // context builder.connect(row[1], zero); // segment @@ -696,7 +691,7 @@ where builder.connect(row[4 + j], targets[j]); } // timestamp - builder.connect(row[12], timestamp_target); + builder.connect(row[12], one); let combined = challenge.combine_base_circuit(builder, &row); prod = builder.mul(prod, combined); @@ -909,10 +904,6 @@ where &public_values.block_metadata, ); - agg_inputs.set_target( - self.aggregation.public_values.cpu_trace_len, - F::from_canonical_usize(public_values.cpu_trace_len), - ); set_trie_roots_target( &mut agg_inputs, &self.aggregation.public_values.trie_roots_before, @@ -977,10 +968,6 @@ where &public_values.block_metadata, ); - block_inputs.set_target( - self.block.public_values.cpu_trace_len, - F::from_canonical_usize(public_values.cpu_trace_len), - ); set_trie_roots_target( &mut block_inputs, &self.block.public_values.trie_roots_before, diff --git a/evm/src/generation/mod.rs b/evm/src/generation/mod.rs index d011ec76c8..5beded4e9b 100644 --- a/evm/src/generation/mod.rs +++ b/evm/src/generation/mod.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use eth_trie_utils::partial_trie::HashedPartialTrie; +use eth_trie_utils::partial_trie::{HashedPartialTrie, PartialTrie}; use ethereum_types::{Address, BigEndianHash, H256, U256}; use plonky2::field::extension::Extendable; use plonky2::field::polynomial::PolynomialValues; @@ -22,7 +22,8 @@ use crate::generation::outputs::{get_outputs, GenerationOutputs}; use crate::generation::state::GenerationState; use crate::memory::segments::Segment; use crate::proof::{BlockMetadata, PublicValues, TrieRoots}; -use crate::witness::memory::{MemoryAddress, MemoryChannel, MemoryOp, MemoryOpKind}; +use crate::util::h2u; +use crate::witness::memory::{MemoryAddress, MemoryChannel}; use crate::witness::transition::transition; pub mod mpt; @@ -39,6 +40,8 @@ use crate::witness::util::mem_write_log; pub struct GenerationInputs { pub signed_txns: Vec>, pub tries: TrieInputs, + /// Expected trie roots after the transactions are executed. + pub trie_roots_after: TrieRoots, /// Mapping between smart contract code hashes and the contract byte code. /// All account smart contracts that are invoked will have an entry present. @@ -73,10 +76,13 @@ pub struct TrieInputs { pub storage_tries: Vec<(H256, HashedPartialTrie)>, } -fn apply_metadata_memops, const D: usize>( +fn apply_metadata_and_tries_memops, const D: usize>( state: &mut GenerationState, - metadata: &BlockMetadata, + inputs: &GenerationInputs, ) { + let metadata = &inputs.block_metadata; + let tries = &inputs.tries; + let trie_roots_after = &inputs.trie_roots_after; let fields = [ ( GlobalMetadata::BlockBeneficiary, @@ -88,67 +94,43 @@ fn apply_metadata_memops, const D: usize>( (GlobalMetadata::BlockGasLimit, metadata.block_gaslimit), (GlobalMetadata::BlockChainId, metadata.block_chain_id), (GlobalMetadata::BlockBaseFee, metadata.block_base_fee), - ]; - - let channel = MemoryChannel::GeneralPurpose(0); - let ops = fields.map(|(field, val)| { - mem_write_log( - channel, - MemoryAddress::new(0, Segment::GlobalMetadata, field as usize), - state, - val, - ) - }); - - state.memory.apply_ops(&ops); - state.traces.memory_ops.extend(ops); -} - -fn apply_trie_memops, const D: usize>( - state: &mut GenerationState, - trie_roots_before: &TrieRoots, - trie_roots_after: &TrieRoots, -) { - let fields = [ ( GlobalMetadata::StateTrieRootDigestBefore, - trie_roots_before.state_root, + h2u(tries.state_trie.hash()), ), ( GlobalMetadata::TransactionTrieRootDigestBefore, - trie_roots_before.transactions_root, + h2u(tries.transactions_trie.hash()), ), ( GlobalMetadata::ReceiptTrieRootDigestBefore, - trie_roots_before.receipts_root, + h2u(tries.receipts_trie.hash()), ), ( GlobalMetadata::StateTrieRootDigestAfter, - trie_roots_after.state_root, + h2u(trie_roots_after.state_root), ), ( GlobalMetadata::TransactionTrieRootDigestAfter, - trie_roots_after.transactions_root, + h2u(trie_roots_after.transactions_root), ), ( GlobalMetadata::ReceiptTrieRootDigestAfter, - trie_roots_after.receipts_root, + h2u(trie_roots_after.receipts_root), ), ]; let channel = MemoryChannel::GeneralPurpose(0); - - let ops = fields.map(|(field, hash)| { - let val = hash.into_uint(); - MemoryOp::new( + let ops = fields.map(|(field, val)| { + mem_write_log( channel, - state.traces.cpu.len(), MemoryAddress::new(0, Segment::GlobalMetadata, field as usize), - MemoryOpKind::Read, + state, val, ) }); + state.memory.apply_ops(&ops); state.traces.memory_ops.extend(ops); } @@ -164,7 +146,7 @@ pub fn generate_traces, const D: usize>( )> { let mut state = GenerationState::::new(inputs.clone(), &KERNEL.code); - apply_metadata_memops(&mut state, &inputs.block_metadata); + apply_metadata_and_tries_memops(&mut state, &inputs); generate_bootstrap_kernel::(&mut state); @@ -194,13 +176,10 @@ pub fn generate_traces, const D: usize>( receipts_root: H256::from_uint(&read_metadata(ReceiptTrieRootDigestAfter)), }; - apply_trie_memops(&mut state, &trie_roots_before, &trie_roots_after); - let public_values = PublicValues { trie_roots_before, trie_roots_after, block_metadata: inputs.block_metadata, - cpu_trace_len: state.traces.clock(), }; let tables = timed!( diff --git a/evm/src/proof.rs b/evm/src/proof.rs index 67fb0dc9eb..df4b93589a 100644 --- a/evm/src/proof.rs +++ b/evm/src/proof.rs @@ -53,7 +53,6 @@ pub struct PublicValues { pub trie_roots_before: TrieRoots, pub trie_roots_after: TrieRoots, pub block_metadata: BlockMetadata, - pub cpu_trace_len: usize, } #[derive(Debug, Clone, Default, Serialize, Deserialize)] @@ -81,7 +80,6 @@ pub struct PublicValuesTarget { pub trie_roots_before: TrieRootsTarget, pub trie_roots_after: TrieRootsTarget, pub block_metadata: BlockMetadataTarget, - pub cpu_trace_len: Target, } impl PublicValuesTarget { @@ -124,8 +122,6 @@ impl PublicValuesTarget { buffer.write_target(block_chain_id)?; buffer.write_target(block_base_fee)?; - buffer.write_target(self.cpu_trace_len)?; - Ok(()) } @@ -152,18 +148,15 @@ impl PublicValuesTarget { block_base_fee: buffer.read_target()?, }; - let cpu_trace_len = buffer.read_target()?; - Ok(Self { trie_roots_before, trie_roots_after, block_metadata, - cpu_trace_len, }) } pub fn from_public_inputs(pis: &[Target]) -> Self { - assert!(pis.len() > TrieRootsTarget::SIZE * 2 + BlockMetadataTarget::SIZE); + assert!(pis.len() > TrieRootsTarget::SIZE * 2 + BlockMetadataTarget::SIZE - 1); Self { trie_roots_before: TrieRootsTarget::from_public_inputs(&pis[0..TrieRootsTarget::SIZE]), trie_roots_after: TrieRootsTarget::from_public_inputs( @@ -173,7 +166,6 @@ impl PublicValuesTarget { &pis[TrieRootsTarget::SIZE * 2 ..TrieRootsTarget::SIZE * 2 + BlockMetadataTarget::SIZE], ), - cpu_trace_len: pis[TrieRootsTarget::SIZE * 2 + BlockMetadataTarget::SIZE], } } @@ -202,7 +194,6 @@ impl PublicValuesTarget { pv0.block_metadata, pv1.block_metadata, ), - cpu_trace_len: builder.select(condition, pv0.cpu_trace_len, pv1.cpu_trace_len), } } } diff --git a/evm/src/recursive_verifier.rs b/evm/src/recursive_verifier.rs index 4a8da740f6..c24c2518f0 100644 --- a/evm/src/recursive_verifier.rs +++ b/evm/src/recursive_verifier.rs @@ -516,12 +516,10 @@ pub(crate) fn add_virtual_public_values, const D: u let trie_roots_before = add_virtual_trie_roots(builder); let trie_roots_after = add_virtual_trie_roots(builder); let block_metadata = add_virtual_block_metadata(builder); - let cpu_trace_len = builder.add_virtual_public_input(); PublicValuesTarget { trie_roots_before, trie_roots_after, block_metadata, - cpu_trace_len, } } @@ -659,10 +657,6 @@ pub(crate) fn set_public_value_targets( &public_values_target.block_metadata, &public_values.block_metadata, ); - witness.set_target( - public_values_target.cpu_trace_len, - F::from_canonical_usize(public_values.cpu_trace_len), - ); } pub(crate) fn set_trie_roots_target( diff --git a/evm/src/util.rs b/evm/src/util.rs index 7c1ae12eea..a1bb7a1fc6 100644 --- a/evm/src/util.rs +++ b/evm/src/util.rs @@ -175,3 +175,7 @@ pub(crate) fn biguint_to_mem_vec(x: BigUint) -> Vec { } mem_vec } + +pub(crate) fn h2u(h: H256) -> U256 { + U256::from_big_endian(&h.0) +} diff --git a/evm/src/verifier.rs b/evm/src/verifier.rs index 1f026dc5a4..bd49345b53 100644 --- a/evm/src/verifier.rs +++ b/evm/src/verifier.rs @@ -1,7 +1,7 @@ use std::any::type_name; use anyhow::{ensure, Result}; -use ethereum_types::{BigEndianHash, U256}; +use ethereum_types::U256; use plonky2::field::extension::{Extendable, FieldExtension}; use plonky2::field::types::Field; use plonky2::fri::verifier::verify_fri_proof; @@ -21,12 +21,13 @@ use crate::keccak_sponge::keccak_sponge_stark::KeccakSpongeStark; use crate::logic::LogicStark; use crate::memory::memory_stark::MemoryStark; use crate::memory::segments::Segment; -use crate::memory::{NUM_CHANNELS, VALUE_LIMBS}; +use crate::memory::VALUE_LIMBS; use crate::permutation::{GrandProductChallenge, PermutationCheckVars}; use crate::proof::{ AllProof, AllProofChallenges, PublicValues, StarkOpeningSet, StarkProof, StarkProofChallenges, }; use crate::stark::Stark; +use crate::util::h2u; use crate::vanishing_poly::eval_vanishing_poly; use crate::vars::StarkEvaluationVars; @@ -118,11 +119,9 @@ where // Memory extra_looking_products.push(Vec::new()); - let cpu_trace_len = 1 << all_proof.stark_proofs[1].proof.recover_degree_bits(config); for c in 0..config.num_challenges { extra_looking_products[Table::Memory as usize].push(get_memory_extra_looking_products( &public_values, - cpu_trace_len, ctl_challenges.challenges[c], )); } @@ -137,10 +136,9 @@ where /// Computes the extra product to multiply to the looked value. It contains memory operations not in the CPU trace: /// - block metadata writes before kernel bootstrapping, -/// - public values reads at the end of the execution. +/// - trie roots writes before kernel bootstrapping. pub(crate) fn get_memory_extra_looking_products( public_values: &PublicValues, - cpu_trace_len: usize, challenge: GrandProductChallenge, ) -> F where @@ -148,8 +146,8 @@ where { let mut prod = F::ONE; - // Add metadata writes. - let block_fields = [ + // Add metadata and tries writes. + let fields = [ ( GlobalMetadata::BlockBeneficiary, U256::from_big_endian(&public_values.block_metadata.block_beneficiary.0), @@ -178,71 +176,50 @@ where GlobalMetadata::BlockBaseFee, public_values.block_metadata.block_base_fee, ), - ]; - let is_read = F::ZERO; - let context = F::ZERO; - let segment = F::from_canonical_u32(Segment::GlobalMetadata as u32); - let timestamp = F::ONE; - - block_fields.map(|(field, val)| { - let mut row = vec![F::ZERO; 13]; - row[0] = is_read; - row[1] = context; - row[2] = segment; - row[3] = F::from_canonical_usize(field as usize); - - for j in 0..VALUE_LIMBS { - row[j + 4] = F::from_canonical_u32((val >> (j * 32)).low_u32()); - } - row[12] = timestamp; - prod *= challenge.combine(row.iter()); - }); - - // Add public values reads. - let trie_fields = [ ( GlobalMetadata::StateTrieRootDigestBefore, - public_values.trie_roots_before.state_root, + h2u(public_values.trie_roots_before.state_root), ), ( GlobalMetadata::TransactionTrieRootDigestBefore, - public_values.trie_roots_before.transactions_root, + h2u(public_values.trie_roots_before.transactions_root), ), ( GlobalMetadata::ReceiptTrieRootDigestBefore, - public_values.trie_roots_before.receipts_root, + h2u(public_values.trie_roots_before.receipts_root), ), ( GlobalMetadata::StateTrieRootDigestAfter, - public_values.trie_roots_after.state_root, + h2u(public_values.trie_roots_after.state_root), ), ( GlobalMetadata::TransactionTrieRootDigestAfter, - public_values.trie_roots_after.transactions_root, + h2u(public_values.trie_roots_after.transactions_root), ), ( GlobalMetadata::ReceiptTrieRootDigestAfter, - public_values.trie_roots_after.receipts_root, + h2u(public_values.trie_roots_after.receipts_root), ), ]; - let is_read = F::ONE; - let timestamp = F::from_canonical_usize(cpu_trace_len * NUM_CHANNELS + 1); + let is_read = F::ZERO; + let context = F::ZERO; + let segment = F::from_canonical_u32(Segment::GlobalMetadata as u32); + let timestamp = F::ONE; - trie_fields.map(|(field, hash)| { + fields.map(|(field, val)| { let mut row = vec![F::ZERO; 13]; row[0] = is_read; row[1] = context; row[2] = segment; row[3] = F::from_canonical_usize(field as usize); - let val = hash.into_uint(); - for j in 0..VALUE_LIMBS { row[j + 4] = F::from_canonical_u32((val >> (j * 32)).low_u32()); } row[12] = timestamp; prod *= challenge.combine(row.iter()); }); + prod } diff --git a/evm/tests/add11_yml.rs b/evm/tests/add11_yml.rs index 86a4b9af0b..f9428381c4 100644 --- a/evm/tests/add11_yml.rs +++ b/evm/tests/add11_yml.rs @@ -14,7 +14,7 @@ use plonky2_evm::all_stark::AllStark; use plonky2_evm::config::StarkConfig; use plonky2_evm::generation::mpt::AccountRlp; use plonky2_evm::generation::{GenerationInputs, TrieInputs}; -use plonky2_evm::proof::BlockMetadata; +use plonky2_evm::proof::{BlockMetadata, TrieRoots}; use plonky2_evm::prover::prove; use plonky2_evm::verifier::verify_proof; use plonky2_evm::Node; @@ -91,9 +91,47 @@ fn add11_yml() -> anyhow::Result<()> { contract_code.insert(keccak(vec![]), vec![]); contract_code.insert(code_hash, code.to_vec()); + let expected_state_trie_after = { + let beneficiary_account_after = AccountRlp { + nonce: 1.into(), + ..AccountRlp::default() + }; + let sender_account_after = AccountRlp { + balance: 0xde0b6b3a75be550u64.into(), + nonce: 1.into(), + ..AccountRlp::default() + }; + let to_account_after = AccountRlp { + balance: 0xde0b6b3a76586a0u64.into(), + code_hash, + // Storage map: { 0 => 2 } + storage_root: HashedPartialTrie::from(Node::Leaf { + nibbles: Nibbles::from_h256_be(keccak([0u8; 32])), + value: vec![2], + }) + .hash(), + ..AccountRlp::default() + }; + + let mut expected_state_trie_after = HashedPartialTrie::from(Node::Empty); + expected_state_trie_after.insert( + beneficiary_nibbles, + rlp::encode(&beneficiary_account_after).to_vec(), + ); + expected_state_trie_after + .insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec()); + expected_state_trie_after.insert(to_nibbles, rlp::encode(&to_account_after).to_vec()); + expected_state_trie_after + }; + let trie_roots_after = TrieRoots { + state_root: expected_state_trie_after.hash(), + transactions_root: tries_before.transactions_trie.hash(), // TODO: Fix this when we have transactions trie. + receipts_root: tries_before.receipts_trie.hash(), // TODO: Fix this when we have receipts trie. + }; let inputs = GenerationInputs { signed_txns: vec![txn.to_vec()], tries: tries_before, + trie_roots_after, contract_code, block_metadata, addresses: vec![], @@ -103,40 +141,6 @@ fn add11_yml() -> anyhow::Result<()> { let proof = prove::(&all_stark, &config, inputs, &mut timing)?; timing.filter(Duration::from_millis(100)).print(); - let beneficiary_account_after = AccountRlp { - nonce: 1.into(), - ..AccountRlp::default() - }; - let sender_account_after = AccountRlp { - balance: 0xde0b6b3a75be550u64.into(), - nonce: 1.into(), - ..AccountRlp::default() - }; - let to_account_after = AccountRlp { - balance: 0xde0b6b3a76586a0u64.into(), - code_hash, - // Storage map: { 0 => 2 } - storage_root: HashedPartialTrie::from(Node::Leaf { - nibbles: Nibbles::from_h256_be(keccak([0u8; 32])), - value: vec![2], - }) - .hash(), - ..AccountRlp::default() - }; - - let mut expected_state_trie_after = HashedPartialTrie::from(Node::Empty); - expected_state_trie_after.insert( - beneficiary_nibbles, - rlp::encode(&beneficiary_account_after).to_vec(), - ); - expected_state_trie_after.insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec()); - expected_state_trie_after.insert(to_nibbles, rlp::encode(&to_account_after).to_vec()); - - assert_eq!( - proof.public_values.trie_roots_after.state_root, - expected_state_trie_after.hash() - ); - verify_proof(&all_stark, proof, &config) } diff --git a/evm/tests/basic_smart_contract.rs b/evm/tests/basic_smart_contract.rs index 4bbf6d1a33..5b2958dff5 100644 --- a/evm/tests/basic_smart_contract.rs +++ b/evm/tests/basic_smart_contract.rs @@ -15,7 +15,7 @@ use plonky2_evm::config::StarkConfig; use plonky2_evm::cpu::kernel::opcodes::{get_opcode, get_push_opcode}; use plonky2_evm::generation::mpt::AccountRlp; use plonky2_evm::generation::{GenerationInputs, TrieInputs}; -use plonky2_evm::proof::BlockMetadata; +use plonky2_evm::proof::{BlockMetadata, TrieRoots}; use plonky2_evm::prover::prove; use plonky2_evm::verifier::verify_proof; use plonky2_evm::Node; @@ -102,18 +102,6 @@ fn test_basic_smart_contract() -> anyhow::Result<()> { contract_code.insert(keccak(vec![]), vec![]); contract_code.insert(code_hash, code.to_vec()); - let inputs = GenerationInputs { - signed_txns: vec![txn.to_vec()], - tries: tries_before, - contract_code, - block_metadata, - addresses: vec![], - }; - - let mut timing = TimingTree::new("prove", log::Level::Debug); - let proof = prove::(&all_stark, &config, inputs, &mut timing)?; - timing.filter(Duration::from_millis(100)).print(); - let expected_state_trie_after: HashedPartialTrie = { let txdata_gas = 2 * 16; let gas_used = 21_000 + code_gas + txdata_gas; @@ -154,11 +142,23 @@ fn test_basic_smart_contract() -> anyhow::Result<()> { } } .into(); + let trie_roots_after = TrieRoots { + state_root: expected_state_trie_after.hash(), + transactions_root: tries_before.transactions_trie.hash(), // TODO: Fix this when we have transactions trie. + receipts_root: tries_before.receipts_trie.hash(), // TODO: Fix this when we have receipts trie. + }; + let inputs = GenerationInputs { + signed_txns: vec![txn.to_vec()], + tries: tries_before, + trie_roots_after, + contract_code, + block_metadata, + addresses: vec![], + }; - assert_eq!( - proof.public_values.trie_roots_after.state_root, - expected_state_trie_after.hash() - ); + let mut timing = TimingTree::new("prove", log::Level::Debug); + let proof = prove::(&all_stark, &config, inputs, &mut timing)?; + timing.filter(Duration::from_millis(100)).print(); verify_proof(&all_stark, proof, &config) } diff --git a/evm/tests/empty_txn_list.rs b/evm/tests/empty_txn_list.rs index eaed9ef02e..bc8d2bddc4 100644 --- a/evm/tests/empty_txn_list.rs +++ b/evm/tests/empty_txn_list.rs @@ -3,7 +3,7 @@ use std::marker::PhantomData; use std::time::Duration; use env_logger::{try_init_from_env, Env, DEFAULT_FILTER_ENV}; -use eth_trie_utils::partial_trie::HashedPartialTrie; +use eth_trie_utils::partial_trie::{HashedPartialTrie, PartialTrie}; use keccak_hash::keccak; use log::info; use plonky2::field::goldilocks_field::GoldilocksField; @@ -14,7 +14,7 @@ use plonky2_evm::all_stark::AllStark; use plonky2_evm::config::StarkConfig; use plonky2_evm::fixed_recursive_verifier::AllRecursiveCircuits; use plonky2_evm::generation::{GenerationInputs, TrieInputs}; -use plonky2_evm::proof::BlockMetadata; +use plonky2_evm::proof::{BlockMetadata, TrieRoots}; use plonky2_evm::Node; type F = GoldilocksField; @@ -40,6 +40,12 @@ fn test_empty_txn_list() -> anyhow::Result<()> { let mut contract_code = HashMap::new(); contract_code.insert(keccak(vec![]), vec![]); + // No transactions, so no trie roots change. + let trie_roots_after = TrieRoots { + state_root: state_trie.hash(), + transactions_root: transactions_trie.hash(), + receipts_root: receipts_trie.hash(), + }; let inputs = GenerationInputs { signed_txns: vec![], tries: TrieInputs { @@ -48,6 +54,7 @@ fn test_empty_txn_list() -> anyhow::Result<()> { receipts_trie, storage_tries, }, + trie_roots_after, contract_code, block_metadata, addresses: vec![], diff --git a/evm/tests/self_balance_gas_cost.rs b/evm/tests/self_balance_gas_cost.rs index d61a1953d7..4df0569125 100644 --- a/evm/tests/self_balance_gas_cost.rs +++ b/evm/tests/self_balance_gas_cost.rs @@ -15,7 +15,7 @@ use plonky2_evm::all_stark::AllStark; use plonky2_evm::config::StarkConfig; use plonky2_evm::generation::mpt::AccountRlp; use plonky2_evm::generation::{GenerationInputs, TrieInputs}; -use plonky2_evm::proof::BlockMetadata; +use plonky2_evm::proof::{BlockMetadata, TrieRoots}; use plonky2_evm::prover::prove; use plonky2_evm::verifier::verify_proof; use plonky2_evm::Node; @@ -87,9 +87,48 @@ fn self_balance_gas_cost() -> anyhow::Result<()> { contract_code.insert(keccak(vec![]), vec![]); contract_code.insert(code_hash, code.to_vec()); + let expected_state_trie_after = { + let beneficiary_account_after = AccountRlp::default(); + let sender_account_after = AccountRlp { + balance: 999999999999999568680u128.into(), + nonce: 1.into(), + ..AccountRlp::default() + }; + let to_account_after = AccountRlp { + code_hash, + // Storage map: { 1 => 5 } + storage_root: HashedPartialTrie::from(Node::Leaf { + // TODO: Could do keccak(pad32(1)) + nibbles: Nibbles::from_str( + "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6", + ) + .unwrap(), + value: vec![5], + }) + .hash(), + ..AccountRlp::default() + }; + + let mut expected_state_trie_after = HashedPartialTrie::from(Node::Empty); + expected_state_trie_after.insert( + beneficiary_nibbles, + rlp::encode(&beneficiary_account_after).to_vec(), + ); + expected_state_trie_after + .insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec()); + expected_state_trie_after.insert(to_nibbles, rlp::encode(&to_account_after).to_vec()); + expected_state_trie_after + }; + + let trie_roots_after = TrieRoots { + state_root: expected_state_trie_after.hash(), + transactions_root: tries_before.transactions_trie.hash(), // TODO: Fix this when we have transactions trie. + receipts_root: tries_before.receipts_trie.hash(), // TODO: Fix this when we have receipts trie. + }; let inputs = GenerationInputs { signed_txns: vec![txn.to_vec()], tries: tries_before, + trie_roots_after, contract_code, block_metadata, addresses: vec![], @@ -99,40 +138,6 @@ fn self_balance_gas_cost() -> anyhow::Result<()> { let proof = prove::(&all_stark, &config, inputs, &mut timing)?; timing.filter(Duration::from_millis(100)).print(); - let beneficiary_account_after = AccountRlp::default(); - let sender_account_after = AccountRlp { - balance: 999999999999999568680u128.into(), - nonce: 1.into(), - ..AccountRlp::default() - }; - let to_account_after = AccountRlp { - code_hash, - // Storage map: { 1 => 5 } - storage_root: HashedPartialTrie::from(Node::Leaf { - // TODO: Could do keccak(pad32(1)) - nibbles: Nibbles::from_str( - "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6", - ) - .unwrap(), - value: vec![5], - }) - .hash(), - ..AccountRlp::default() - }; - - let mut expected_state_trie_after = HashedPartialTrie::from(Node::Empty); - expected_state_trie_after.insert( - beneficiary_nibbles, - rlp::encode(&beneficiary_account_after).to_vec(), - ); - expected_state_trie_after.insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec()); - expected_state_trie_after.insert(to_nibbles, rlp::encode(&to_account_after).to_vec()); - - assert_eq!( - proof.public_values.trie_roots_after.state_root, - expected_state_trie_after.hash() - ); - verify_proof(&all_stark, proof, &config) } diff --git a/evm/tests/simple_transfer.rs b/evm/tests/simple_transfer.rs index ac0f88a534..80c6783da4 100644 --- a/evm/tests/simple_transfer.rs +++ b/evm/tests/simple_transfer.rs @@ -14,7 +14,7 @@ use plonky2_evm::all_stark::AllStark; use plonky2_evm::config::StarkConfig; use plonky2_evm::generation::mpt::AccountRlp; use plonky2_evm::generation::{GenerationInputs, TrieInputs}; -use plonky2_evm::proof::BlockMetadata; +use plonky2_evm::proof::{BlockMetadata, TrieRoots}; use plonky2_evm::prover::prove; use plonky2_evm::verifier::verify_proof; use plonky2_evm::Node; @@ -78,18 +78,6 @@ fn test_simple_transfer() -> anyhow::Result<()> { let mut contract_code = HashMap::new(); contract_code.insert(keccak(vec![]), vec![]); - let inputs = GenerationInputs { - signed_txns: vec![txn.to_vec()], - tries: tries_before, - contract_code, - block_metadata, - addresses: vec![], - }; - - let mut timing = TimingTree::new("prove", log::Level::Debug); - let proof = prove::(&all_stark, &config, inputs, &mut timing)?; - timing.filter(Duration::from_millis(100)).print(); - let expected_state_trie_after: HashedPartialTrie = { let txdata_gas = 2 * 16; let gas_used = 21_000 + txdata_gas; @@ -121,11 +109,23 @@ fn test_simple_transfer() -> anyhow::Result<()> { } .into() }; + let trie_roots_after = TrieRoots { + state_root: expected_state_trie_after.hash(), + transactions_root: tries_before.transactions_trie.hash(), // TODO: Fix this when we have transactions trie. + receipts_root: tries_before.receipts_trie.hash(), // TODO: Fix this when we have receipts trie. + }; + let inputs = GenerationInputs { + signed_txns: vec![txn.to_vec()], + tries: tries_before, + trie_roots_after, + contract_code, + block_metadata, + addresses: vec![], + }; - assert_eq!( - proof.public_values.trie_roots_after.state_root, - expected_state_trie_after.hash() - ); + let mut timing = TimingTree::new("prove", log::Level::Debug); + let proof = prove::(&all_stark, &config, inputs, &mut timing)?; + timing.filter(Duration::from_millis(100)).print(); verify_proof(&all_stark, proof, &config) }