2023-03-16 13:32:34 -07:00
|
|
|
use std::collections::HashMap;
|
|
|
|
|
|
2023-03-20 21:40:58 -07:00
|
|
|
use ethereum_types::{Address, BigEndianHash, H160, H256, U256};
|
2023-03-16 13:32:34 -07:00
|
|
|
use keccak_hash::keccak;
|
2022-06-15 09:33:52 -07:00
|
|
|
use plonky2::field::types::Field;
|
|
|
|
|
|
2023-03-16 13:32:34 -07:00
|
|
|
use crate::cpu::kernel::aggregator::KERNEL;
|
2023-04-24 09:07:00 +02:00
|
|
|
use crate::cpu::kernel::constants::context_metadata::ContextMetadata;
|
2022-09-22 20:09:48 -07:00
|
|
|
use crate::generation::mpt::all_mpt_prover_inputs_reversed;
|
2022-09-29 23:09:32 -07:00
|
|
|
use crate::generation::rlp::all_rlp_prover_inputs_reversed;
|
2022-09-18 09:45:31 -07:00
|
|
|
use crate::generation::GenerationInputs;
|
2023-04-24 09:07:00 +02:00
|
|
|
use crate::memory::segments::Segment;
|
2023-09-26 11:13:57 -04:00
|
|
|
use crate::util::u256_to_usize;
|
|
|
|
|
use crate::witness::errors::ProgramError;
|
2023-04-24 09:07:00 +02:00
|
|
|
use crate::witness::memory::{MemoryAddress, MemoryState};
|
2022-11-30 12:55:41 -08:00
|
|
|
use crate::witness::state::RegistersState;
|
2022-12-01 11:15:51 -08:00
|
|
|
use crate::witness::traces::{TraceCheckpoint, Traces};
|
2023-03-16 13:32:34 -07:00
|
|
|
use crate::witness::util::stack_peek;
|
2022-12-01 11:15:51 -08:00
|
|
|
|
|
|
|
|
pub(crate) struct GenerationStateCheckpoint {
|
|
|
|
|
pub(crate) registers: RegistersState,
|
|
|
|
|
pub(crate) traces: TraceCheckpoint,
|
|
|
|
|
}
|
2022-06-15 09:33:52 -07:00
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub(crate) struct GenerationState<F: Field> {
|
2022-09-18 09:45:31 -07:00
|
|
|
pub(crate) inputs: GenerationInputs,
|
2022-11-30 12:55:41 -08:00
|
|
|
pub(crate) registers: RegistersState,
|
2022-07-16 09:14:51 -07:00
|
|
|
pub(crate) memory: MemoryState,
|
2022-11-30 12:55:41 -08:00
|
|
|
pub(crate) traces: Traces<F>,
|
2022-06-15 09:33:52 -07:00
|
|
|
|
2022-11-30 12:55:41 -08:00
|
|
|
pub(crate) next_txn_index: usize,
|
2022-09-18 09:45:31 -07:00
|
|
|
|
|
|
|
|
/// Prover inputs containing MPT data, in reverse order so that the next input can be obtained
|
|
|
|
|
/// via `pop()`.
|
|
|
|
|
pub(crate) mpt_prover_inputs: Vec<U256>,
|
2022-09-29 23:09:32 -07:00
|
|
|
|
|
|
|
|
/// Prover inputs containing RLP data, in reverse order so that the next input can be obtained
|
|
|
|
|
/// via `pop()`.
|
|
|
|
|
pub(crate) rlp_prover_inputs: Vec<U256>,
|
2023-03-16 13:32:34 -07:00
|
|
|
|
|
|
|
|
/// The state trie only stores state keys, which are hashes of addresses, but sometimes it is
|
|
|
|
|
/// useful to see the actual addresses for debugging. Here we store the mapping for all known
|
|
|
|
|
/// addresses.
|
|
|
|
|
pub(crate) state_key_to_address: HashMap<H256, Address>,
|
2023-03-16 15:10:49 -07:00
|
|
|
|
2023-03-21 16:03:54 -07:00
|
|
|
/// Prover inputs containing the result of a MODMUL operation, in little-endian order (so that
|
|
|
|
|
/// inputs are obtained in big-endian order via `pop()`). Contains both the remainder and the
|
|
|
|
|
/// quotient, in that order.
|
|
|
|
|
pub(crate) bignum_modmul_result_limbs: Vec<U256>,
|
2022-06-15 09:33:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<F: Field> GenerationState<F> {
|
2023-09-26 11:13:57 -04:00
|
|
|
pub(crate) fn new(inputs: GenerationInputs, kernel_code: &[u8]) -> Result<Self, ProgramError> {
|
2023-02-25 07:59:51 -08:00
|
|
|
log::debug!("Input signed_txns: {:?}", &inputs.signed_txns);
|
|
|
|
|
log::debug!("Input state_trie: {:?}", &inputs.tries.state_trie);
|
|
|
|
|
log::debug!(
|
|
|
|
|
"Input transactions_trie: {:?}",
|
|
|
|
|
&inputs.tries.transactions_trie
|
|
|
|
|
);
|
|
|
|
|
log::debug!("Input receipts_trie: {:?}", &inputs.tries.receipts_trie);
|
|
|
|
|
log::debug!("Input storage_tries: {:?}", &inputs.tries.storage_tries);
|
|
|
|
|
log::debug!("Input contract_code: {:?}", &inputs.contract_code);
|
2023-09-26 11:13:57 -04:00
|
|
|
let mpt_prover_inputs = all_mpt_prover_inputs_reversed(&inputs.tries)?;
|
2022-09-29 23:09:32 -07:00
|
|
|
let rlp_prover_inputs = all_rlp_prover_inputs_reversed(&inputs.signed_txns);
|
2023-03-21 16:03:54 -07:00
|
|
|
let bignum_modmul_result_limbs = Vec::new();
|
2022-09-18 09:45:31 -07:00
|
|
|
|
2023-09-26 11:13:57 -04:00
|
|
|
Ok(Self {
|
2022-09-18 09:45:31 -07:00
|
|
|
inputs,
|
2022-11-30 12:55:41 -08:00
|
|
|
registers: Default::default(),
|
2022-12-01 11:15:51 -08:00
|
|
|
memory: MemoryState::new(kernel_code),
|
2022-11-30 12:55:41 -08:00
|
|
|
traces: Traces::default(),
|
|
|
|
|
next_txn_index: 0,
|
2022-09-18 09:45:31 -07:00
|
|
|
mpt_prover_inputs,
|
2022-09-29 23:09:32 -07:00
|
|
|
rlp_prover_inputs,
|
2023-03-16 13:32:34 -07:00
|
|
|
state_key_to_address: HashMap::new(),
|
2023-03-21 16:03:54 -07:00
|
|
|
bignum_modmul_result_limbs,
|
2023-09-26 11:13:57 -04:00
|
|
|
})
|
2022-09-18 09:45:31 -07:00
|
|
|
}
|
|
|
|
|
|
2023-03-16 13:32:34 -07:00
|
|
|
/// Updates `program_counter`, and potentially adds some extra handling if we're jumping to a
|
|
|
|
|
/// special location.
|
2023-09-26 11:13:57 -04:00
|
|
|
pub fn jump_to(&mut self, dst: usize) -> Result<(), ProgramError> {
|
2023-03-16 13:32:34 -07:00
|
|
|
self.registers.program_counter = dst;
|
|
|
|
|
if dst == KERNEL.global_labels["observe_new_address"] {
|
2023-09-26 11:13:57 -04:00
|
|
|
let tip_u256 = stack_peek(self, 0)?;
|
2023-03-20 21:40:58 -07:00
|
|
|
let tip_h256 = H256::from_uint(&tip_u256);
|
|
|
|
|
let tip_h160 = H160::from(tip_h256);
|
|
|
|
|
self.observe_address(tip_h160);
|
2023-04-24 09:07:00 +02:00
|
|
|
} else if dst == KERNEL.global_labels["observe_new_contract"] {
|
2023-09-26 11:13:57 -04:00
|
|
|
let tip_u256 = stack_peek(self, 0)?;
|
2023-04-24 09:07:00 +02:00
|
|
|
let tip_h256 = H256::from_uint(&tip_u256);
|
2023-09-26 11:13:57 -04:00
|
|
|
self.observe_contract(tip_h256)?;
|
2023-03-16 13:32:34 -07:00
|
|
|
}
|
2023-09-26 11:13:57 -04:00
|
|
|
|
|
|
|
|
Ok(())
|
2023-03-16 13:32:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Observe the given address, so that we will be able to recognize the associated state key.
|
|
|
|
|
/// This is just for debugging purposes.
|
|
|
|
|
pub fn observe_address(&mut self, address: Address) {
|
|
|
|
|
let state_key = keccak(address.0);
|
|
|
|
|
self.state_key_to_address.insert(state_key, address);
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-24 09:07:00 +02:00
|
|
|
/// Observe the given code hash and store the associated code.
|
|
|
|
|
/// When called, the code corresponding to `codehash` should be stored in the return data.
|
2023-09-26 11:13:57 -04:00
|
|
|
pub fn observe_contract(&mut self, codehash: H256) -> Result<(), ProgramError> {
|
2023-04-24 09:07:00 +02:00
|
|
|
if self.inputs.contract_code.contains_key(&codehash) {
|
2023-09-26 11:13:57 -04:00
|
|
|
return Ok(()); // Return early if the code hash has already been observed.
|
2023-04-24 09:07:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let ctx = self.registers.context;
|
|
|
|
|
let returndata_size_addr = MemoryAddress::new(
|
|
|
|
|
ctx,
|
|
|
|
|
Segment::ContextMetadata,
|
|
|
|
|
ContextMetadata::ReturndataSize as usize,
|
|
|
|
|
);
|
2023-09-26 11:13:57 -04:00
|
|
|
let returndata_size = u256_to_usize(self.memory.get(returndata_size_addr))?;
|
2023-04-24 09:07:00 +02:00
|
|
|
let code = self.memory.contexts[ctx].segments[Segment::Returndata as usize].content
|
|
|
|
|
[..returndata_size]
|
|
|
|
|
.iter()
|
2023-09-12 19:23:16 -04:00
|
|
|
.map(|x| x.low_u32() as u8)
|
2023-04-24 09:07:00 +02:00
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
debug_assert_eq!(keccak(&code), codehash);
|
|
|
|
|
|
|
|
|
|
self.inputs.contract_code.insert(codehash, code);
|
2023-09-26 11:13:57 -04:00
|
|
|
|
|
|
|
|
Ok(())
|
2023-04-24 09:07:00 +02:00
|
|
|
}
|
|
|
|
|
|
2022-12-01 11:15:51 -08:00
|
|
|
pub fn checkpoint(&self) -> GenerationStateCheckpoint {
|
|
|
|
|
GenerationStateCheckpoint {
|
|
|
|
|
registers: self.registers,
|
|
|
|
|
traces: self.traces.checkpoint(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn rollback(&mut self, checkpoint: GenerationStateCheckpoint) {
|
|
|
|
|
self.registers = checkpoint.registers;
|
|
|
|
|
self.traces.rollback(checkpoint.traces);
|
|
|
|
|
}
|
2023-03-15 11:23:29 -07:00
|
|
|
|
|
|
|
|
pub(crate) fn stack(&self) -> Vec<U256> {
|
2023-03-19 14:13:42 -07:00
|
|
|
const MAX_TO_SHOW: usize = 10;
|
|
|
|
|
(0..self.registers.stack_len.min(MAX_TO_SHOW))
|
2023-03-15 11:23:29 -07:00
|
|
|
.map(|i| stack_peek(self, i).unwrap())
|
|
|
|
|
.collect()
|
|
|
|
|
}
|
2022-06-15 09:33:52 -07:00
|
|
|
}
|