#![allow(clippy::upper_case_acronyms)] use std::collections::HashMap; use std::time::Duration; use env_logger::{try_init_from_env, Env, DEFAULT_FILTER_ENV}; use eth_trie_utils::nibbles::Nibbles; use eth_trie_utils::partial_trie::{HashedPartialTrie, PartialTrie}; use ethereum_types::Address; use hex_literal::hex; use keccak_hash::keccak; use plonky2::field::goldilocks_field::GoldilocksField; use plonky2::plonk::config::PoseidonGoldilocksConfig; use plonky2::util::timing::TimingTree; 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::prover::prove; use plonky2_evm::verifier::verify_proof; use plonky2_evm::Node; type F = GoldilocksField; const D: usize = 2; type C = PoseidonGoldilocksConfig; /// The `add11_yml` test case from https://github.com/ethereum/tests #[test] fn add11_yml() -> anyhow::Result<()> { init_logger(); let all_stark = AllStark::::default(); let config = StarkConfig::standard_fast_config(); let beneficiary = hex!("2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"); let sender = hex!("a94f5374fce5edbc8e2a8697c15331677e6ebf0b"); let to = hex!("095e7baea6a6c7c4c2dfeb977efac326af552d87"); let beneficiary_state_key = keccak(beneficiary); let sender_state_key = keccak(sender); let to_state_key = keccak(to); let beneficiary_nibbles = Nibbles::from_bytes_be(beneficiary_state_key.as_bytes()).unwrap(); let sender_nibbles = Nibbles::from_bytes_be(sender_state_key.as_bytes()).unwrap(); let to_nibbles = Nibbles::from_bytes_be(to_state_key.as_bytes()).unwrap(); let code = [0x60, 0x01, 0x60, 0x01, 0x01, 0x60, 0x00, 0x55, 0x00]; let code_hash = keccak(code); let beneficiary_account_before = AccountRlp { nonce: 1.into(), ..AccountRlp::default() }; let sender_account_before = AccountRlp { balance: 0x0de0b6b3a7640000u64.into(), ..AccountRlp::default() }; let to_account_before = AccountRlp { balance: 0x0de0b6b3a7640000u64.into(), code_hash, ..AccountRlp::default() }; let mut state_trie_before = HashedPartialTrie::from(Node::Empty); state_trie_before.insert( beneficiary_nibbles, rlp::encode(&beneficiary_account_before).to_vec(), ); state_trie_before.insert(sender_nibbles, rlp::encode(&sender_account_before).to_vec()); state_trie_before.insert(to_nibbles, rlp::encode(&to_account_before).to_vec()); let tries_before = TrieInputs { state_trie: state_trie_before, transactions_trie: Node::Empty.into(), receipts_trie: Node::Empty.into(), storage_tries: vec![(Address::from_slice(&to), Node::Empty.into())], }; let txn = hex!("f863800a83061a8094095e7baea6a6c7c4c2dfeb977efac326af552d87830186a0801ba0ffb600e63115a7362e7811894a91d8ba4330e526f22121c994c4692035dfdfd5a06198379fcac8de3dbfac48b165df4bf88e2088f294b61efb9a65fe2281c76e16"); let block_metadata = BlockMetadata { block_beneficiary: Address::from(beneficiary), block_base_fee: 0xa.into(), ..BlockMetadata::default() }; let mut contract_code = HashMap::new(); 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 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) } fn init_logger() { let _ = try_init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "info")); }