mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-02 13:53:07 +00:00
150 lines
5.2 KiB
Rust
150 lines
5.2 KiB
Rust
#![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, U256};
|
|
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;
|
|
|
|
/// Test a simple token transfer to a new address.
|
|
#[test]
|
|
fn test_simple_transfer() -> anyhow::Result<()> {
|
|
init_logger();
|
|
|
|
let all_stark = AllStark::<F, D>::default();
|
|
let config = StarkConfig::standard_fast_config();
|
|
|
|
let beneficiary = hex!("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
|
|
let sender = hex!("2c7536e3605d9c16a7a3d7b1898e529396a65c23");
|
|
let to = hex!("a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0");
|
|
|
|
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 beneficiary_account_before = AccountRlp::default();
|
|
let sender_account_before = AccountRlp {
|
|
nonce: 5.into(),
|
|
balance: eth_to_wei(100_000.into()),
|
|
storage_root: HashedPartialTrie::from(Node::Empty).hash(),
|
|
code_hash: keccak([]),
|
|
};
|
|
let to_account_before = AccountRlp::default();
|
|
|
|
let state_trie_before = Node::Leaf {
|
|
nibbles: sender_nibbles,
|
|
value: rlp::encode(&sender_account_before).to_vec(),
|
|
}
|
|
.into();
|
|
let tries_before = TrieInputs {
|
|
state_trie: state_trie_before,
|
|
transactions_trie: HashedPartialTrie::from(Node::Empty),
|
|
receipts_trie: HashedPartialTrie::from(Node::Empty),
|
|
storage_tries: vec![],
|
|
};
|
|
|
|
// Generated using a little py-evm script.
|
|
let txn = hex!("f861050a8255f094a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0648242421ba02c89eb757d9deeb1f5b3859a9d4d679951ef610ac47ad4608dc142beb1b7e313a05af7e9fbab825455d36c36c7f4cfcafbeafa9a77bdff936b52afb36d4fe4bcdd");
|
|
let value = U256::from(100u32);
|
|
|
|
let block_metadata = BlockMetadata {
|
|
block_beneficiary: Address::from(beneficiary),
|
|
..BlockMetadata::default()
|
|
};
|
|
|
|
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::<F, C, D>(&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;
|
|
|
|
let beneficiary_account_after = AccountRlp {
|
|
balance: beneficiary_account_before.balance + gas_used * 10,
|
|
..beneficiary_account_before
|
|
};
|
|
let sender_account_after = AccountRlp {
|
|
balance: sender_account_before.balance - value - gas_used * 10,
|
|
nonce: sender_account_before.nonce + 1,
|
|
..sender_account_before
|
|
};
|
|
let to_account_after = AccountRlp {
|
|
balance: value,
|
|
..to_account_before
|
|
};
|
|
|
|
let mut children = core::array::from_fn(|_| Node::Empty.into());
|
|
children[beneficiary_nibbles.get_nibble(0) as usize] = Node::Leaf {
|
|
nibbles: beneficiary_nibbles.truncate_n_nibbles_front(1),
|
|
value: rlp::encode(&beneficiary_account_after).to_vec(),
|
|
}
|
|
.into();
|
|
children[sender_nibbles.get_nibble(0) as usize] = Node::Leaf {
|
|
nibbles: sender_nibbles.truncate_n_nibbles_front(1),
|
|
value: rlp::encode(&sender_account_after).to_vec(),
|
|
}
|
|
.into();
|
|
children[to_nibbles.get_nibble(0) as usize] = Node::Leaf {
|
|
nibbles: to_nibbles.truncate_n_nibbles_front(1),
|
|
value: rlp::encode(&to_account_after).to_vec(),
|
|
}
|
|
.into();
|
|
Node::Branch {
|
|
children,
|
|
value: vec![],
|
|
}
|
|
.into()
|
|
};
|
|
|
|
assert_eq!(
|
|
proof.public_values.trie_roots_after.state_root,
|
|
expected_state_trie_after.hash()
|
|
);
|
|
|
|
verify_proof(&all_stark, proof, &config)
|
|
}
|
|
|
|
fn eth_to_wei(eth: U256) -> U256 {
|
|
// 1 ether = 10^18 wei.
|
|
eth * U256::from(10).pow(18.into())
|
|
}
|
|
|
|
fn init_logger() {
|
|
let _ = try_init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "info"));
|
|
}
|