mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-03 06:13:07 +00:00
Interpreter GenerationInputs (#1455)
* Add initialization with GenerationInputs to the interpreter * Add new_with_generation_inputs_and_kernel * Apply comments
This commit is contained in:
parent
3b1ed824f5
commit
b05e84ddf8
@ -5,7 +5,8 @@ use std::collections::HashMap;
|
||||
use std::ops::Range;
|
||||
|
||||
use anyhow::bail;
|
||||
use ethereum_types::{U256, U512};
|
||||
use eth_trie_utils::partial_trie::PartialTrie;
|
||||
use ethereum_types::{BigEndianHash, H160, H256, U256, U512};
|
||||
use keccak_hash::keccak;
|
||||
use plonky2::field::goldilocks_field::GoldilocksField;
|
||||
|
||||
@ -16,11 +17,13 @@ use crate::cpu::kernel::constants::global_metadata::GlobalMetadata;
|
||||
use crate::cpu::kernel::constants::txn_fields::NormalizedTxnField;
|
||||
use crate::cpu::stack::MAX_USER_STACK_SIZE;
|
||||
use crate::extension_tower::BN_BASE;
|
||||
use crate::generation::mpt::load_all_mpts;
|
||||
use crate::generation::prover_input::ProverInputFn;
|
||||
use crate::generation::state::GenerationState;
|
||||
use crate::generation::rlp::all_rlp_prover_inputs_reversed;
|
||||
use crate::generation::state::{all_withdrawals_prover_inputs_reversed, GenerationState};
|
||||
use crate::generation::GenerationInputs;
|
||||
use crate::memory::segments::{Segment, SEGMENT_SCALING_FACTOR};
|
||||
use crate::util::u256_to_usize;
|
||||
use crate::util::{h2u, u256_to_usize};
|
||||
use crate::witness::errors::{ProgramError, ProverInputError};
|
||||
use crate::witness::gas::gas_to_charge;
|
||||
use crate::witness::memory::{MemoryAddress, MemoryContextState, MemorySegmentState, MemoryState};
|
||||
@ -150,6 +153,18 @@ impl<'a> Interpreter<'a> {
|
||||
result
|
||||
}
|
||||
|
||||
/// Returns an instance of `Interpreter` given `GenerationInputs`, and assuming we are
|
||||
/// initializing with the `KERNEL` code.
|
||||
pub(crate) fn new_with_generation_inputs_and_kernel(
|
||||
initial_offset: usize,
|
||||
initial_stack: Vec<U256>,
|
||||
inputs: GenerationInputs,
|
||||
) -> Self {
|
||||
let mut result = Self::new_with_kernel(initial_offset, initial_stack);
|
||||
result.initialize_interpreter_state_with_kernel(inputs);
|
||||
result
|
||||
}
|
||||
|
||||
pub(crate) fn new(
|
||||
code: &'a [u8],
|
||||
initial_offset: usize,
|
||||
@ -181,6 +196,136 @@ impl<'a> Interpreter<'a> {
|
||||
result
|
||||
}
|
||||
|
||||
/// Initializes the interpreter state given `GenerationInputs`, using the KERNEL code.
|
||||
pub(crate) fn initialize_interpreter_state_with_kernel(&mut self, inputs: GenerationInputs) {
|
||||
self.initialize_interpreter_state(inputs, KERNEL.code_hash, KERNEL.code.len());
|
||||
}
|
||||
|
||||
/// Initializes the interpreter state given `GenerationInputs`.
|
||||
pub(crate) fn initialize_interpreter_state(
|
||||
&mut self,
|
||||
inputs: GenerationInputs,
|
||||
kernel_hash: H256,
|
||||
kernel_code_len: usize,
|
||||
) {
|
||||
let tries = &inputs.tries;
|
||||
|
||||
// Set state's inputs.
|
||||
self.generation_state.inputs = inputs.clone();
|
||||
|
||||
// Initialize the MPT's pointers.
|
||||
let (trie_root_ptrs, trie_data) =
|
||||
load_all_mpts(tries).expect("Invalid MPT data for preinitialization");
|
||||
let trie_roots_after = &inputs.trie_roots_after;
|
||||
self.generation_state.trie_root_ptrs = trie_root_ptrs;
|
||||
|
||||
// Initialize the `TrieData` segment.
|
||||
for (i, data) in trie_data.iter().enumerate() {
|
||||
let trie_addr = MemoryAddress::new(0, Segment::TrieData, i);
|
||||
self.generation_state.memory.set(trie_addr, data.into());
|
||||
}
|
||||
|
||||
// Update the RLP and withdrawal prover inputs.
|
||||
let rlp_prover_inputs =
|
||||
all_rlp_prover_inputs_reversed(inputs.clone().signed_txn.as_ref().unwrap_or(&vec![]));
|
||||
let withdrawal_prover_inputs = all_withdrawals_prover_inputs_reversed(&inputs.withdrawals);
|
||||
self.generation_state.rlp_prover_inputs = rlp_prover_inputs;
|
||||
self.generation_state.withdrawal_prover_inputs = withdrawal_prover_inputs;
|
||||
|
||||
// Set `GlobalMetadata` values.
|
||||
let metadata = &inputs.block_metadata;
|
||||
let global_metadata_to_set = [
|
||||
(
|
||||
GlobalMetadata::BlockBeneficiary,
|
||||
U256::from_big_endian(&metadata.block_beneficiary.0),
|
||||
),
|
||||
(GlobalMetadata::BlockTimestamp, metadata.block_timestamp),
|
||||
(GlobalMetadata::BlockNumber, metadata.block_number),
|
||||
(GlobalMetadata::BlockDifficulty, metadata.block_difficulty),
|
||||
(
|
||||
GlobalMetadata::BlockRandom,
|
||||
metadata.block_random.into_uint(),
|
||||
),
|
||||
(GlobalMetadata::BlockGasLimit, metadata.block_gaslimit),
|
||||
(GlobalMetadata::BlockChainId, metadata.block_chain_id),
|
||||
(GlobalMetadata::BlockBaseFee, metadata.block_base_fee),
|
||||
(
|
||||
GlobalMetadata::BlockCurrentHash,
|
||||
h2u(inputs.block_hashes.cur_hash),
|
||||
),
|
||||
(GlobalMetadata::BlockGasUsed, metadata.block_gas_used),
|
||||
(GlobalMetadata::BlockGasUsedBefore, inputs.gas_used_before),
|
||||
(GlobalMetadata::BlockGasUsedAfter, inputs.gas_used_after),
|
||||
(GlobalMetadata::TxnNumberBefore, inputs.txn_number_before),
|
||||
(
|
||||
GlobalMetadata::TxnNumberAfter,
|
||||
inputs.txn_number_before + if inputs.signed_txn.is_some() { 1 } else { 0 },
|
||||
),
|
||||
(
|
||||
GlobalMetadata::StateTrieRootDigestBefore,
|
||||
h2u(tries.state_trie.hash()),
|
||||
),
|
||||
(
|
||||
GlobalMetadata::TransactionTrieRootDigestBefore,
|
||||
h2u(tries.transactions_trie.hash()),
|
||||
),
|
||||
(
|
||||
GlobalMetadata::ReceiptTrieRootDigestBefore,
|
||||
h2u(tries.receipts_trie.hash()),
|
||||
),
|
||||
(
|
||||
GlobalMetadata::StateTrieRootDigestAfter,
|
||||
h2u(trie_roots_after.state_root),
|
||||
),
|
||||
(
|
||||
GlobalMetadata::TransactionTrieRootDigestAfter,
|
||||
h2u(trie_roots_after.transactions_root),
|
||||
),
|
||||
(
|
||||
GlobalMetadata::ReceiptTrieRootDigestAfter,
|
||||
h2u(trie_roots_after.receipts_root),
|
||||
),
|
||||
(GlobalMetadata::KernelHash, h2u(kernel_hash)),
|
||||
(GlobalMetadata::KernelLen, kernel_code_len.into()),
|
||||
];
|
||||
|
||||
self.set_global_metadata_multi_fields(&global_metadata_to_set);
|
||||
|
||||
// Set final block bloom values.
|
||||
let final_block_bloom_fields = (0..8)
|
||||
.map(|i| {
|
||||
(
|
||||
MemoryAddress::new_u256s(
|
||||
U256::zero(),
|
||||
(Segment::GlobalBlockBloom.unscale()).into(),
|
||||
i.into(),
|
||||
)
|
||||
.unwrap(),
|
||||
metadata.block_bloom[i],
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
self.set_memory_multi_addresses(&final_block_bloom_fields);
|
||||
|
||||
// Set previous block hash.
|
||||
let block_hashes_fields = (0..256)
|
||||
.map(|i| {
|
||||
(
|
||||
MemoryAddress::new_u256s(
|
||||
U256::zero(),
|
||||
(Segment::BlockHashes.unscale()).into(),
|
||||
i.into(),
|
||||
)
|
||||
.unwrap(),
|
||||
h2u(inputs.block_hashes.prev_hashes[i]),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
self.set_memory_multi_addresses(&block_hashes_fields);
|
||||
}
|
||||
|
||||
fn checkpoint(&self) -> InterpreterCheckpoint {
|
||||
let registers = InterpreterRegistersState {
|
||||
kernel_mode: self.is_kernel(),
|
||||
|
||||
@ -4,7 +4,7 @@ use std::str::FromStr;
|
||||
use anyhow::{anyhow, Result};
|
||||
use eth_trie_utils::nibbles::Nibbles;
|
||||
use eth_trie_utils::partial_trie::{HashedPartialTrie, Node, PartialTrie};
|
||||
use ethereum_types::{Address, H256, U256};
|
||||
use ethereum_types::{Address, BigEndianHash, H256, U256};
|
||||
use hex_literal::hex;
|
||||
use keccak_hash::keccak;
|
||||
|
||||
@ -17,56 +17,9 @@ use crate::generation::mpt::{AccountRlp, LegacyReceiptRlp};
|
||||
use crate::generation::rlp::all_rlp_prover_inputs_reversed;
|
||||
use crate::generation::TrieInputs;
|
||||
use crate::memory::segments::{Segment, SEGMENT_SCALING_FACTOR};
|
||||
use crate::proof::TrieRoots;
|
||||
use crate::proof::{BlockHashes, BlockMetadata, TrieRoots};
|
||||
use crate::util::h2u;
|
||||
|
||||
// Stolen from `tests/mpt/insert.rs`
|
||||
// Prepare the interpreter by loading the initial MPTs and
|
||||
// by setting all `GlobalMetadata` and necessary code into memory.
|
||||
fn prepare_interpreter(
|
||||
interpreter: &mut Interpreter,
|
||||
trie_inputs: TrieInputs,
|
||||
transaction: &[u8],
|
||||
contract_code: HashMap<H256, Vec<u8>>,
|
||||
) {
|
||||
initialize_mpts(interpreter, &trie_inputs);
|
||||
assert_eq!(interpreter.stack(), vec![]);
|
||||
|
||||
// Set necessary `GlobalMetadata`.
|
||||
let global_metadata_to_set = [
|
||||
(
|
||||
GlobalMetadata::StateTrieRootDigestBefore,
|
||||
h2u(trie_inputs.state_trie.hash()),
|
||||
),
|
||||
(
|
||||
GlobalMetadata::TransactionTrieRootDigestBefore,
|
||||
h2u(trie_inputs.transactions_trie.hash()),
|
||||
),
|
||||
(
|
||||
GlobalMetadata::ReceiptTrieRootDigestBefore,
|
||||
h2u(trie_inputs.receipts_trie.hash()),
|
||||
),
|
||||
(GlobalMetadata::TxnNumberAfter, 1.into()),
|
||||
(GlobalMetadata::BlockGasUsedAfter, 0xa868u64.into()),
|
||||
(GlobalMetadata::BlockGasLimit, 1_000_000.into()),
|
||||
(GlobalMetadata::BlockBaseFee, 10.into()),
|
||||
(
|
||||
GlobalMetadata::BlockBeneficiary,
|
||||
U256::from_big_endian(
|
||||
&Address::from(hex!("2adc25665018aa1fe0e6bc666dac8fc2697ff9ba")).0,
|
||||
),
|
||||
),
|
||||
];
|
||||
|
||||
interpreter.set_global_metadata_multi_fields(&global_metadata_to_set);
|
||||
|
||||
// Set contract code and transaction.
|
||||
interpreter.generation_state.inputs.contract_code = contract_code;
|
||||
|
||||
interpreter.generation_state.inputs.signed_txn = Some(transaction.to_vec());
|
||||
let rlp_prover_inputs = all_rlp_prover_inputs_reversed(transaction);
|
||||
interpreter.generation_state.rlp_prover_inputs = rlp_prover_inputs;
|
||||
}
|
||||
use crate::GenerationInputs;
|
||||
|
||||
#[test]
|
||||
fn test_add11_yml() {
|
||||
@ -120,10 +73,8 @@ fn test_add11_yml() {
|
||||
|
||||
let txn = hex!("f863800a83061a8094095e7baea6a6c7c4c2dfeb977efac326af552d87830186a0801ba0ffb600e63115a7362e7811894a91d8ba4330e526f22121c994c4692035dfdfd5a06198379fcac8de3dbfac48b165df4bf88e2088f294b61efb9a65fe2281c76e16");
|
||||
|
||||
let initial_stack = vec![];
|
||||
let mut interpreter = Interpreter::new_with_kernel(0, initial_stack);
|
||||
let gas_used = 0xa868u64.into();
|
||||
|
||||
prepare_interpreter(&mut interpreter, tries_before.clone(), &txn, contract_code);
|
||||
let expected_state_trie_after = {
|
||||
let beneficiary_account_after = AccountRlp {
|
||||
nonce: 1.into(),
|
||||
@ -158,7 +109,7 @@ fn test_add11_yml() {
|
||||
};
|
||||
let receipt_0 = LegacyReceiptRlp {
|
||||
status: true,
|
||||
cum_gas_used: 0xa868u64.into(),
|
||||
cum_gas_used: gas_used,
|
||||
bloom: vec![0; 256].into(),
|
||||
logs: vec![],
|
||||
};
|
||||
@ -179,24 +130,41 @@ fn test_add11_yml() {
|
||||
receipts_root: receipts_trie.hash(),
|
||||
};
|
||||
|
||||
// Set trie roots after the transaction was executed.
|
||||
let metadata_to_set = [
|
||||
(
|
||||
GlobalMetadata::StateTrieRootDigestAfter,
|
||||
h2u(trie_roots_after.state_root),
|
||||
),
|
||||
(
|
||||
GlobalMetadata::TransactionTrieRootDigestAfter,
|
||||
h2u(trie_roots_after.transactions_root),
|
||||
),
|
||||
(
|
||||
GlobalMetadata::ReceiptTrieRootDigestAfter,
|
||||
h2u(trie_roots_after.receipts_root),
|
||||
),
|
||||
];
|
||||
interpreter.set_global_metadata_multi_fields(&metadata_to_set);
|
||||
let block_metadata = BlockMetadata {
|
||||
block_beneficiary: Address::from(beneficiary),
|
||||
block_timestamp: 0x03e8.into(),
|
||||
block_number: 1.into(),
|
||||
block_difficulty: 0x020000.into(),
|
||||
block_random: H256::from_uint(&0x020000.into()),
|
||||
block_gaslimit: 0xff112233u32.into(),
|
||||
block_chain_id: 1.into(),
|
||||
block_base_fee: 0xa.into(),
|
||||
block_gas_used: gas_used,
|
||||
block_bloom: [0.into(); 8],
|
||||
};
|
||||
|
||||
let route_txn_label = KERNEL.global_labels["hash_initial_tries"];
|
||||
let tries_inputs = GenerationInputs {
|
||||
signed_txn: Some(txn.to_vec()),
|
||||
withdrawals: vec![],
|
||||
tries: tries_before,
|
||||
trie_roots_after,
|
||||
contract_code: contract_code.clone(),
|
||||
block_metadata,
|
||||
checkpoint_state_trie_root: HashedPartialTrie::from(Node::Empty).hash(),
|
||||
txn_number_before: 0.into(),
|
||||
gas_used_before: 0.into(),
|
||||
gas_used_after: gas_used,
|
||||
block_hashes: BlockHashes {
|
||||
prev_hashes: vec![H256::default(); 256],
|
||||
cur_hash: H256::default(),
|
||||
},
|
||||
};
|
||||
|
||||
let initial_stack = vec![];
|
||||
let mut interpreter =
|
||||
Interpreter::new_with_generation_inputs_and_kernel(0, initial_stack, tries_inputs);
|
||||
|
||||
let route_txn_label = KERNEL.global_labels["main"];
|
||||
// Switch context and initialize memory with the data we need for the tests.
|
||||
interpreter.generation_state.registers.program_counter = route_txn_label;
|
||||
interpreter.set_context_metadata_field(0, ContextMetadata::GasLimit, 1_000_000.into());
|
||||
@ -259,10 +227,6 @@ fn test_add11_yml_with_exception() {
|
||||
let txn_gas_limit = 400_000;
|
||||
let gas_price = 10;
|
||||
|
||||
let initial_stack = vec![];
|
||||
let mut interpreter = Interpreter::new_with_kernel(0, initial_stack);
|
||||
|
||||
prepare_interpreter(&mut interpreter, tries_before.clone(), &txn, contract_code);
|
||||
// Here, since the transaction fails, it consumes its gas limit, and does nothing else.
|
||||
let expected_state_trie_after = {
|
||||
let beneficiary_account_after = beneficiary_account_before;
|
||||
@ -308,26 +272,41 @@ fn test_add11_yml_with_exception() {
|
||||
receipts_root: receipts_trie.hash(),
|
||||
};
|
||||
|
||||
// Set trie roots after the transaction was executed.
|
||||
let metadata_to_set = [
|
||||
(
|
||||
GlobalMetadata::StateTrieRootDigestAfter,
|
||||
h2u(trie_roots_after.state_root),
|
||||
),
|
||||
(
|
||||
GlobalMetadata::TransactionTrieRootDigestAfter,
|
||||
h2u(trie_roots_after.transactions_root),
|
||||
),
|
||||
(
|
||||
GlobalMetadata::ReceiptTrieRootDigestAfter,
|
||||
h2u(trie_roots_after.receipts_root),
|
||||
),
|
||||
// The gas used in this case is the transaction gas limit
|
||||
(GlobalMetadata::BlockGasUsedAfter, txn_gas_limit.into()),
|
||||
];
|
||||
interpreter.set_global_metadata_multi_fields(&metadata_to_set);
|
||||
let block_metadata = BlockMetadata {
|
||||
block_beneficiary: Address::from(beneficiary),
|
||||
block_timestamp: 0x03e8.into(),
|
||||
block_number: 1.into(),
|
||||
block_difficulty: 0x020000.into(),
|
||||
block_random: H256::from_uint(&0x020000.into()),
|
||||
block_gaslimit: 0xff112233u32.into(),
|
||||
block_chain_id: 1.into(),
|
||||
block_base_fee: 0xa.into(),
|
||||
block_gas_used: txn_gas_limit.into(),
|
||||
block_bloom: [0.into(); 8],
|
||||
};
|
||||
|
||||
let route_txn_label = KERNEL.global_labels["hash_initial_tries"];
|
||||
let tries_inputs = GenerationInputs {
|
||||
signed_txn: Some(txn.to_vec()),
|
||||
withdrawals: vec![],
|
||||
tries: tries_before,
|
||||
trie_roots_after,
|
||||
contract_code: contract_code.clone(),
|
||||
block_metadata,
|
||||
checkpoint_state_trie_root: HashedPartialTrie::from(Node::Empty).hash(),
|
||||
txn_number_before: 0.into(),
|
||||
gas_used_before: 0.into(),
|
||||
gas_used_after: txn_gas_limit.into(),
|
||||
block_hashes: BlockHashes {
|
||||
prev_hashes: vec![H256::default(); 256],
|
||||
cur_hash: H256::default(),
|
||||
},
|
||||
};
|
||||
|
||||
let initial_stack = vec![];
|
||||
let mut interpreter =
|
||||
Interpreter::new_with_generation_inputs_and_kernel(0, initial_stack, tries_inputs);
|
||||
|
||||
let route_txn_label = KERNEL.global_labels["main"];
|
||||
// Switch context and initialize memory with the data we need for the tests.
|
||||
interpreter.generation_state.registers.program_counter = route_txn_label;
|
||||
interpreter.set_context_metadata_field(0, ContextMetadata::GasLimit, 1_000_000.into());
|
||||
|
||||
@ -169,7 +169,7 @@ impl<F: Field> GenerationState<F> {
|
||||
|
||||
/// Withdrawals prover input array is of the form `[addr0, amount0, ..., addrN, amountN, U256::MAX, U256::MAX]`.
|
||||
/// Returns the reversed array.
|
||||
fn all_withdrawals_prover_inputs_reversed(withdrawals: &[(Address, U256)]) -> Vec<U256> {
|
||||
pub(crate) fn all_withdrawals_prover_inputs_reversed(withdrawals: &[(Address, U256)]) -> Vec<U256> {
|
||||
let mut withdrawal_prover_inputs = withdrawals
|
||||
.iter()
|
||||
.flat_map(|w| [U256::from((w.0).0.as_slice()), w.1])
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user