Skip to content

Commit

Permalink
feat(continuations): trim public values at block proof level (#235)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nashtare authored May 22, 2024
1 parent 9a8db99 commit 824bb0e
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 94 deletions.
18 changes: 8 additions & 10 deletions evm_arithmetization/src/fixed_recursive_verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ use crate::get_challenges::observe_public_values_target;
use crate::memory::segments::Segment;
use crate::proof::{
AllProof, BlockHashesTarget, BlockMetadataTarget, ExtraBlockData, ExtraBlockDataTarget,
MemCapTarget, PublicValues, PublicValuesTarget, RegistersDataTarget, TrieRoots,
TrieRootsTarget,
FinalPublicValues, MemCapTarget, PublicValues, PublicValuesTarget, RegistersDataTarget,
TrieRoots, TrieRootsTarget, TARGET_HASH_SIZE,
};
use crate::prover::{check_abort_signal, generate_all_data_segments, prove, GenerationSegmentData};
use crate::recursive_verifier::{
Expand Down Expand Up @@ -1855,7 +1855,7 @@ where
opt_parent_block_proof: Option<&ProofWithPublicInputs<F, C, D>>,
agg_root_proof: &ProofWithPublicInputs<F, C, D>,
public_values: PublicValues,
) -> anyhow::Result<(ProofWithPublicInputs<F, C, D>, PublicValues)> {
) -> anyhow::Result<(ProofWithPublicInputs<F, C, D>, FinalPublicValues)> {
let mut block_inputs = PartialWitness::new();

block_inputs.set_bool_target(
Expand All @@ -1881,21 +1881,19 @@ where
let mut nonzero_pis = HashMap::new();

// Initialize the checkpoint block roots before, and state root after.
let state_trie_root_before_keys = 0..TrieRootsTarget::HASH_SIZE;
let state_trie_root_before_keys = 0..TARGET_HASH_SIZE;
for (key, &value) in state_trie_root_before_keys
.zip_eq(&h256_limbs::<F>(public_values.trie_roots_before.state_root))
{
nonzero_pis.insert(key, value);
}
let txn_trie_root_before_keys =
TrieRootsTarget::HASH_SIZE..TrieRootsTarget::HASH_SIZE * 2;
let txn_trie_root_before_keys = TARGET_HASH_SIZE..TARGET_HASH_SIZE * 2;
for (key, &value) in txn_trie_root_before_keys.clone().zip_eq(&h256_limbs::<F>(
public_values.trie_roots_before.transactions_root,
)) {
nonzero_pis.insert(key, value);
}
let receipts_trie_root_before_keys =
TrieRootsTarget::HASH_SIZE * 2..TrieRootsTarget::HASH_SIZE * 3;
let receipts_trie_root_before_keys = TARGET_HASH_SIZE * 2..TARGET_HASH_SIZE * 3;
for (key, &value) in receipts_trie_root_before_keys
.clone()
.zip_eq(&h256_limbs::<F>(
Expand All @@ -1905,7 +1903,7 @@ where
nonzero_pis.insert(key, value);
}
let state_trie_root_after_keys =
TrieRootsTarget::SIZE..TrieRootsTarget::SIZE + TrieRootsTarget::HASH_SIZE;
TrieRootsTarget::SIZE..TrieRootsTarget::SIZE + TARGET_HASH_SIZE;
for (key, &value) in state_trie_root_after_keys
.zip_eq(&h256_limbs::<F>(public_values.trie_roots_before.state_root))
{
Expand Down Expand Up @@ -1987,7 +1985,7 @@ where
})?;

let block_proof = self.block.circuit.prove(block_inputs)?;
Ok((block_proof, block_public_values))
Ok((block_proof, block_public_values.into()))
}

pub fn verify_block(&self, block_proof: &ProofWithPublicInputs<F, C, D>) -> anyhow::Result<()> {
Expand Down
194 changes: 116 additions & 78 deletions evm_arithmetization/src/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,77 +78,38 @@ impl PublicValues {
- 1
);

let trie_roots_before = TrieRoots::from_public_inputs(&pis[0..TrieRootsTarget::SIZE]);
let mut offset = 0;
let trie_roots_before =
TrieRoots::from_public_inputs(&pis[offset..offset + TrieRootsTarget::SIZE]);
offset += TrieRootsTarget::SIZE;
let trie_roots_after =
TrieRoots::from_public_inputs(&pis[TrieRootsTarget::SIZE..TrieRootsTarget::SIZE * 2]);
let block_metadata = BlockMetadata::from_public_inputs(
&pis[TrieRootsTarget::SIZE * 2..TrieRootsTarget::SIZE * 2 + BlockMetadataTarget::SIZE],
);
let block_hashes = BlockHashes::from_public_inputs(
&pis[TrieRootsTarget::SIZE * 2 + BlockMetadataTarget::SIZE
..TrieRootsTarget::SIZE * 2 + BlockMetadataTarget::SIZE + BlockHashesTarget::SIZE],
);
let extra_block_data = ExtraBlockData::from_public_inputs(
&pis[TrieRootsTarget::SIZE * 2 + BlockMetadataTarget::SIZE + BlockHashesTarget::SIZE
..TrieRootsTarget::SIZE * 2
+ BlockMetadataTarget::SIZE
+ BlockHashesTarget::SIZE
+ ExtraBlockDataTarget::SIZE],
);
let registers_before = RegistersData::from_public_inputs(
&pis[TrieRootsTarget::SIZE * 2
+ BlockMetadataTarget::SIZE
+ BlockHashesTarget::SIZE
+ ExtraBlockDataTarget::SIZE
..TrieRootsTarget::SIZE * 2
+ BlockMetadataTarget::SIZE
+ BlockHashesTarget::SIZE
+ ExtraBlockDataTarget::SIZE
+ RegistersDataTarget::SIZE],
);
let registers_after = RegistersData::from_public_inputs(
&pis[TrieRootsTarget::SIZE * 2
+ BlockMetadataTarget::SIZE
+ BlockHashesTarget::SIZE
+ ExtraBlockDataTarget::SIZE
+ RegistersDataTarget::SIZE
..TrieRootsTarget::SIZE * 2
+ BlockMetadataTarget::SIZE
+ BlockHashesTarget::SIZE
+ ExtraBlockDataTarget::SIZE
+ RegistersDataTarget::SIZE * 2],
);

TrieRoots::from_public_inputs(&pis[offset..offset + TrieRootsTarget::SIZE]);
offset += TrieRootsTarget::SIZE;
let block_metadata =
BlockMetadata::from_public_inputs(&pis[offset..offset + BlockMetadataTarget::SIZE]);
offset += BlockMetadataTarget::SIZE;
let block_hashes =
BlockHashes::from_public_inputs(&pis[offset..offset + BlockHashesTarget::SIZE]);
offset += BlockHashesTarget::SIZE;
let extra_block_data =
ExtraBlockData::from_public_inputs(&pis[offset..offset + ExtraBlockDataTarget::SIZE]);
offset += ExtraBlockDataTarget::SIZE;
let registers_before =
RegistersData::from_public_inputs(&pis[offset..offset + RegistersDataTarget::SIZE]);
offset += RegistersDataTarget::SIZE;
let registers_after =
RegistersData::from_public_inputs(&pis[offset..offset + RegistersDataTarget::SIZE]);
offset += RegistersDataTarget::SIZE;
let mem_before = MemCap::from_public_inputs(
&pis[TrieRootsTarget::SIZE * 2
+ BlockMetadataTarget::SIZE
+ BlockHashesTarget::SIZE
+ ExtraBlockDataTarget::SIZE
+ RegistersDataTarget::SIZE * 2
..TrieRootsTarget::SIZE * 2
+ BlockMetadataTarget::SIZE
+ BlockHashesTarget::SIZE
+ ExtraBlockDataTarget::SIZE
+ RegistersDataTarget::SIZE * 2
+ len_mem_cap * NUM_HASH_OUT_ELTS],
&pis[offset..offset + len_mem_cap * NUM_HASH_OUT_ELTS],
len_mem_cap,
);
offset += len_mem_cap * NUM_HASH_OUT_ELTS;
let mem_after = MemCap::from_public_inputs(
&pis[TrieRootsTarget::SIZE * 2
+ BlockMetadataTarget::SIZE
+ BlockHashesTarget::SIZE
+ ExtraBlockDataTarget::SIZE
+ RegistersDataTarget::SIZE * 2
+ len_mem_cap * NUM_HASH_OUT_ELTS
..TrieRootsTarget::SIZE * 2
+ BlockMetadataTarget::SIZE
+ BlockHashesTarget::SIZE
+ ExtraBlockDataTarget::SIZE
+ RegistersDataTarget::SIZE * 2
+ 2 * len_mem_cap * NUM_HASH_OUT_ELTS],
&pis[offset..offset + len_mem_cap * NUM_HASH_OUT_ELTS],
len_mem_cap,
);
// There are 3 elements per address, + 1 U256 for the memory value.

Self {
trie_roots_before,
trie_roots_after,
Expand All @@ -163,6 +124,72 @@ impl PublicValues {
}
}

/// Memory values which are public.
#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, Serialize)]
pub struct FinalPublicValues {
/// Trie hashes before the execution of the local state transition
pub trie_roots_before: TrieRoots,
/// Trie hashes after the execution of the local state transition.
pub trie_roots_after: TrieRoots,
/// Block metadata: it remains unchanged within a block.
pub block_metadata: BlockMetadata,
/// 256 previous block hashes and current block's hash.
pub block_hashes: BlockHashes,
/// Extra block data that is specific to the current proof.
pub extra_block_data: ExtraBlockData,
}

impl FinalPublicValues {
/// Extracts final public values from the given public inputs of a proof.
/// Public values are always the first public inputs added to the circuit,
/// so we can start extracting at index 0.
pub fn from_public_inputs<F: RichField>(pis: &[F]) -> Self {
assert!(
pis.len()
> TrieRootsTarget::SIZE * 2
+ BlockMetadataTarget::SIZE
+ BlockHashesTarget::SIZE
+ ExtraBlockDataTarget::SIZE
);

let mut offset = 0;
let trie_roots_before =
TrieRoots::from_public_inputs(&pis[offset..offset + TrieRootsTarget::SIZE]);
offset += TrieRootsTarget::SIZE;
let trie_roots_after =
TrieRoots::from_public_inputs(&pis[offset..offset + TrieRootsTarget::SIZE]);
offset += TrieRootsTarget::SIZE;
let block_metadata =
BlockMetadata::from_public_inputs(&pis[offset..offset + BlockMetadataTarget::SIZE]);
offset += BlockMetadataTarget::SIZE;
let block_hashes =
BlockHashes::from_public_inputs(&pis[offset..offset + BlockHashesTarget::SIZE]);
offset += BlockHashesTarget::SIZE;
let extra_block_data =
ExtraBlockData::from_public_inputs(&pis[offset..offset + ExtraBlockDataTarget::SIZE]);

Self {
trie_roots_before,
trie_roots_after,
block_metadata,
block_hashes,
extra_block_data,
}
}
}

impl From<PublicValues> for FinalPublicValues {
fn from(value: PublicValues) -> Self {
Self {
trie_roots_before: value.trie_roots_before,
trie_roots_after: value.trie_roots_after,
block_metadata: value.block_metadata,
block_hashes: value.block_hashes,
extra_block_data: value.extra_block_data,
}
}
}

/// Trie hashes.
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct TrieRoots {
Expand All @@ -178,9 +205,9 @@ impl TrieRoots {
pub fn from_public_inputs<F: RichField>(pis: &[F]) -> Self {
assert!(pis.len() == TrieRootsTarget::SIZE);

let state_root = get_h256(&pis[0..8]);
let transactions_root = get_h256(&pis[8..16]);
let receipts_root = get_h256(&pis[16..24]);
let state_root = get_h256(&pis[0..TARGET_HASH_SIZE]);
let transactions_root = get_h256(&pis[TARGET_HASH_SIZE..2 * TARGET_HASH_SIZE]);
let receipts_root = get_h256(&pis[2 * TARGET_HASH_SIZE..3 * TARGET_HASH_SIZE]);

Self {
state_root,
Expand Down Expand Up @@ -221,7 +248,9 @@ impl BlockHashes {
pub fn from_public_inputs<F: RichField>(pis: &[F]) -> Self {
assert!(pis.len() == BlockHashesTarget::SIZE);

let prev_hashes: [H256; 256] = core::array::from_fn(|i| get_h256(&pis[8 * i..8 + 8 * i]));
let prev_hashes: [H256; 256] = core::array::from_fn(|i| {
get_h256(&pis[TARGET_HASH_SIZE * i..TARGET_HASH_SIZE * (i + 1)])
});
let cur_hash = get_h256(&pis[2048..2056]);

Self {
Expand Down Expand Up @@ -271,7 +300,11 @@ impl BlockMetadata {
let block_base_fee =
(pis[18].to_canonical_u64() + (pis[19].to_canonical_u64() << 32)).into();
let block_gas_used = pis[20].to_canonical_u64().into();
let block_bloom = core::array::from_fn(|i| h2u(get_h256(&pis[21 + 8 * i..29 + 8 * i])));
let block_bloom = core::array::from_fn(|i| {
h2u(get_h256(
&pis[21 + TARGET_HASH_SIZE * i..21 + TARGET_HASH_SIZE * (i + 1)],
))
});

Self {
block_beneficiary,
Expand Down Expand Up @@ -757,25 +790,30 @@ impl PublicValuesTarget {
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
pub struct TrieRootsTarget {
/// Targets for the state trie hash.
pub(crate) state_root: [Target; 8],
pub(crate) state_root: [Target; TARGET_HASH_SIZE],
/// Targets for the transactions trie hash.
pub(crate) transactions_root: [Target; 8],
pub(crate) transactions_root: [Target; TARGET_HASH_SIZE],
/// Targets for the receipts trie hash.
pub(crate) receipts_root: [Target; 8],
pub(crate) receipts_root: [Target; TARGET_HASH_SIZE],
}

/// Number of `Target`s required for hashes.
pub(crate) const TARGET_HASH_SIZE: usize = 8;

impl TrieRootsTarget {
/// Number of `Target`s required for all trie hashes.
pub(crate) const HASH_SIZE: usize = 8;
pub(crate) const SIZE: usize = Self::HASH_SIZE * 3;
pub(crate) const SIZE: usize = TARGET_HASH_SIZE * 3;

/// Extracts trie hash `Target`s for all tries from the provided public
/// input `Target`s. The provided `pis` should start with the trie
/// hashes.
pub(crate) fn from_public_inputs(pis: &[Target]) -> Self {
let state_root = pis[0..8].try_into().unwrap();
let transactions_root = pis[8..16].try_into().unwrap();
let receipts_root = pis[16..24].try_into().unwrap();
let state_root = pis[0..TARGET_HASH_SIZE].try_into().unwrap();
let transactions_root = pis[TARGET_HASH_SIZE..2 * TARGET_HASH_SIZE]
.try_into()
.unwrap();
let receipts_root = pis[2 * TARGET_HASH_SIZE..3 * TARGET_HASH_SIZE]
.try_into()
.unwrap();

Self {
state_root,
Expand Down
11 changes: 5 additions & 6 deletions evm_arithmetization/tests/empty_txn_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ use env_logger::{try_init_from_env, Env, DEFAULT_FILTER_ENV};
use ethereum_types::{BigEndianHash, H256};
use evm_arithmetization::fixed_recursive_verifier::ProverOutputData;
use evm_arithmetization::generation::{GenerationInputs, TrieInputs};
use evm_arithmetization::proof::{BlockHashes, BlockMetadata, PublicValues, TrieRoots};
use evm_arithmetization::proof::{
BlockHashes, BlockMetadata, FinalPublicValues, PublicValues, TrieRoots,
};
use evm_arithmetization::{AllRecursiveCircuits, AllStark, Node, StarkConfig};
use keccak_hash::keccak;
use log::info;
Expand Down Expand Up @@ -236,11 +238,8 @@ fn test_empty_txn_list() -> anyhow::Result<()> {
all_circuits.prove_block(None, &txn_proof, txn_public_values)?;
all_circuits.verify_block(&block_proof)?;

// Test retrieved public values from the proof public inputs.
let retrieved_public_values = PublicValues::from_public_inputs(
&block_proof.public_inputs,
block_public_values.mem_before.mem_cap.len(),
);
// Test retrieved final public values from the proof public inputs.
let retrieved_public_values = FinalPublicValues::from_public_inputs(&block_proof.public_inputs);
assert_eq!(retrieved_public_values, block_public_values);

// Get the verifier associated to these preprocessed circuits, and have it
Expand Down

0 comments on commit 824bb0e

Please sign in to comment.