Skip to content

Commit

Permalink
feat: add consolidated block hashes across checkpoints (#551)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nashtare authored Sep 12, 2024
1 parent 5bb3a6a commit 4ef831b
Show file tree
Hide file tree
Showing 49 changed files with 1,607 additions and 580 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion evm_arithmetization/benches/fibonacci_25m_gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ use keccak_hash::keccak;
use mpt_trie::nibbles::Nibbles;
use mpt_trie::partial_trie::{HashedPartialTrie, PartialTrie};
use plonky2::field::goldilocks_field::GoldilocksField;
use plonky2::field::types::Field;
use plonky2::hash::hash_types::NUM_HASH_OUT_ELTS;

type F = GoldilocksField;

Expand All @@ -50,7 +52,7 @@ fn criterion_benchmark(c: &mut Criterion) {
simulate_execution::<F>(inputs).unwrap();
}

fn prepare_setup() -> anyhow::Result<GenerationInputs> {
fn prepare_setup() -> anyhow::Result<GenerationInputs<F>> {
let sender = hex!("8943545177806ED17B9F23F0a21ee5948eCaa776");
let to = hex!("159271B89fea49aF29DFaf8b4eCE7D042D5d6f07");

Expand Down Expand Up @@ -181,6 +183,7 @@ fn prepare_setup() -> anyhow::Result<GenerationInputs> {
checkpoint_state_trie_root: H256(hex!(
"fe07ff6d1ab215df17884b89112ccf2373597285a56c5902150313ad1a53ee57"
)),
checkpoint_consolidated_hash: [F::ZERO; NUM_HASH_OUT_ELTS],
ger_data: None,
block_metadata,
txn_number_before: 0.into(),
Expand Down
4 changes: 2 additions & 2 deletions evm_arithmetization/src/cpu/kernel/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ impl<F: RichField> Interpreter<F> {
pub(crate) fn new_with_generation_inputs(
initial_offset: usize,
initial_stack: Vec<U256>,
inputs: &GenerationInputs,
inputs: &GenerationInputs<F>,
max_cpu_len_log: Option<usize>,
) -> Self {
debug_inputs(inputs);
Expand Down Expand Up @@ -216,7 +216,7 @@ impl<F: RichField> Interpreter<F> {
}

/// Initializes the interpreter state given `GenerationInputs`.
pub(crate) fn initialize_interpreter_state(&mut self, inputs: &GenerationInputs) {
pub(crate) fn initialize_interpreter_state(&mut self, inputs: &GenerationInputs<F>) {
// Initialize registers.
let registers_before = RegistersState::new();
self.generation_state.registers = RegistersState {
Expand Down
6 changes: 5 additions & 1 deletion evm_arithmetization/src/cpu/kernel/tests/add11.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ use keccak_hash::keccak;
use mpt_trie::nibbles::Nibbles;
use mpt_trie::partial_trie::{HashedPartialTrie, Node, PartialTrie};
use plonky2::field::goldilocks_field::GoldilocksField as F;
use plonky2::field::types::Field;
use plonky2::hash::hash_types::NUM_HASH_OUT_ELTS;

use crate::cpu::kernel::aggregator::KERNEL;
use crate::cpu::kernel::interpreter::Interpreter;
Expand Down Expand Up @@ -174,7 +176,7 @@ fn test_add11_yml() {
receipts_root: receipts_trie.hash(),
};

let inputs = GenerationInputs {
let inputs = GenerationInputs::<F> {
signed_txns: vec![txn.to_vec()],
burn_addr: None,
withdrawals: vec![],
Expand All @@ -184,6 +186,7 @@ fn test_add11_yml() {
contract_code: contract_code.clone(),
block_metadata,
checkpoint_state_trie_root: HashedPartialTrie::from(Node::Empty).hash(),
checkpoint_consolidated_hash: [F::ZERO; NUM_HASH_OUT_ELTS],
txn_number_before: 0.into(),
gas_used_before: 0.into(),
gas_used_after: gas_used,
Expand Down Expand Up @@ -360,6 +363,7 @@ fn test_add11_yml_with_exception() {
contract_code: contract_code.clone(),
block_metadata,
checkpoint_state_trie_root: HashedPartialTrie::from(Node::Empty).hash(),
checkpoint_consolidated_hash: [F::ZERO; NUM_HASH_OUT_ELTS],
txn_number_before: 0.into(),
gas_used_before: 0.into(),
gas_used_after: txn_gas_limit.into(),
Expand Down
5 changes: 4 additions & 1 deletion evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use ethereum_types::U256;
use keccak_hash::{keccak, H256};
use mpt_trie::partial_trie::{HashedPartialTrie, PartialTrie};
use plonky2::field::goldilocks_field::GoldilocksField as F;
use plonky2::field::types::Field;
use plonky2::hash::hash_types::NUM_HASH_OUT_ELTS;

use crate::cpu::kernel::{aggregator::KERNEL, interpreter::Interpreter};
use crate::generation::{
Expand Down Expand Up @@ -76,7 +78,7 @@ fn test_init_exc_stop() {
receipts_root: receipts_trie.hash(),
};

let inputs = GenerationInputs {
let inputs = GenerationInputs::<F> {
signed_txns: vec![],
burn_addr: None,
withdrawals: vec![],
Expand All @@ -89,6 +91,7 @@ fn test_init_exc_stop() {
trie_roots_after,
contract_code,
checkpoint_state_trie_root: HashedPartialTrie::from(Node::Empty).hash(),
checkpoint_consolidated_hash: [F::ZERO; NUM_HASH_OUT_ELTS],
block_metadata,
txn_number_before: 0.into(),
gas_used_before: 0.into(),
Expand Down
63 changes: 40 additions & 23 deletions evm_arithmetization/src/fixed_recursive_verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ where
{
pub is_dummy: bool,
pub proof_with_pis: ProofWithPublicInputs<F, C, D>,
pub public_values: PublicValues,
pub public_values: PublicValues<F>,
}

/// Contains all recursive circuits used in the system. For each STARK and each
Expand Down Expand Up @@ -1347,9 +1347,6 @@ where
let parent_block_proof = builder.add_virtual_proof_with_pis(&expected_common_data);
let agg_root_proof = builder.add_virtual_proof_with_pis(&agg.circuit.common);

// Connect block hashes
Self::connect_block_hashes(&mut builder, &parent_block_proof, &agg_root_proof);

let parent_pv = PublicValuesTarget::from_public_inputs(&parent_block_proof.public_inputs);
let agg_pv = PublicValuesTarget::from_public_inputs(&agg_root_proof.public_inputs);

Expand Down Expand Up @@ -1555,7 +1552,7 @@ where
// This also enforces that the initial state trie root that will be stored in
// these `FinalPublicValues` actually matches the known checkpoint state trie
// root.
final_pv.connect_parent(&mut builder, &parent_pv);
final_pv.connect_parent::<F, C, D>(&mut builder, &parent_pv);

let block_verifier_data = builder.constant_verifier_data(&block.circuit.verifier_only);

Expand Down Expand Up @@ -1672,13 +1669,11 @@ where
/// Connect the 256 block hashes between two blocks
fn connect_block_hashes(
builder: &mut CircuitBuilder<F, D>,
lhs: &ProofWithPublicInputsTarget<D>,
rhs: &ProofWithPublicInputsTarget<D>,
lhs_public_values: &PublicValuesTarget,
rhs_public_values: &PublicValuesTarget,
) {
let lhs_public_values = PublicValuesTarget::from_public_inputs(&lhs.public_inputs);
let rhs_public_values = PublicValuesTarget::from_public_inputs(&rhs.public_inputs);
for i in 0..255 {
for j in 0..8 {
for j in 0..TARGET_HASH_SIZE {
builder.connect(
lhs_public_values.block_hashes.prev_hashes[8 * (i + 1) + j],
rhs_public_values.block_hashes.prev_hashes[8 * i + j],
Expand All @@ -1687,7 +1682,7 @@ where
}
let expected_hash = lhs_public_values.block_hashes.cur_hash;
let prev_block_hash = &rhs_public_values.block_hashes.prev_hashes[255 * 8..256 * 8];
for i in 0..expected_hash.len() {
for i in 0..TARGET_HASH_SIZE {
builder.connect(expected_hash[i], prev_block_hash[i]);
}
}
Expand Down Expand Up @@ -1736,6 +1731,9 @@ where
// Check that the checkpoint block has the predetermined state trie root in
// `ExtraBlockData`.
Self::connect_checkpoint_block(builder, rhs, has_not_parent_block);

// Connect block hashes
Self::connect_block_hashes(builder, lhs, rhs);
}

fn connect_checkpoint_block(
Expand All @@ -1755,6 +1753,18 @@ where
constr = builder.mul(has_not_parent_block, constr);
builder.assert_zero(constr);
}

let consolidated_hash = builder
.hash_n_to_hash_no_pad::<C::InnerHasher>(x.block_hashes.prev_hashes.to_vec())
.elements;

for i in 0..NUM_HASH_OUT_ELTS {
builder.conditional_assert_eq(
has_not_parent_block,
x.extra_block_data.checkpoint_consolidated_hash[i],
consolidated_hash[i],
)
}
}

fn connect_final_block_values_to_intermediary(
Expand Down Expand Up @@ -1818,7 +1828,7 @@ where
&self,
all_stark: &AllStark<F, D>,
config: &StarkConfig,
generation_inputs: TrimmedGenerationInputs,
generation_inputs: TrimmedGenerationInputs<F>,
segment_data: &mut GenerationSegmentData,
timing: &mut TimingTree,
abort_signal: Option<Arc<AtomicBool>>,
Expand Down Expand Up @@ -1893,7 +1903,7 @@ where
&self,
all_stark: &AllStark<F, D>,
config: &StarkConfig,
generation_inputs: GenerationInputs,
generation_inputs: GenerationInputs<F>,
max_cpu_len_log: usize,
timing: &mut TimingTree,
abort_signal: Option<Arc<AtomicBool>>,
Expand Down Expand Up @@ -1985,7 +1995,7 @@ where
all_proof: AllProof<F, C, D>,
table_circuits: &[(RecursiveCircuitsForTableSize<F, C, D>, u8); NUM_TABLES],
abort_signal: Option<Arc<AtomicBool>>,
) -> anyhow::Result<(ProofWithPublicInputs<F, C, D>, PublicValues)> {
) -> anyhow::Result<(ProofWithPublicInputs<F, C, D>, PublicValues<F>)> {
let mut root_inputs = PartialWitness::new();

for table in 0..NUM_TABLES {
Expand Down Expand Up @@ -2106,6 +2116,9 @@ where
checkpoint_state_trie_root: lhs_public_values
.extra_block_data
.checkpoint_state_trie_root,
checkpoint_consolidated_hash: lhs_public_values
.extra_block_data
.checkpoint_consolidated_hash,
txn_number_before: lhs_public_values.extra_block_data.txn_number_before,
txn_number_after: real_public_values.extra_block_data.txn_number_after,
gas_used_before: lhs_public_values.extra_block_data.gas_used_before,
Expand Down Expand Up @@ -2175,11 +2188,11 @@ where
&self,
lhs_is_agg: bool,
lhs_proof: &ProofWithPublicInputs<F, C, D>,
lhs_public_values: PublicValues,
lhs_public_values: PublicValues<F>,
rhs_is_agg: bool,
rhs_proof: &ProofWithPublicInputs<F, C, D>,
rhs_public_values: PublicValues,
) -> anyhow::Result<(ProofWithPublicInputs<F, C, D>, PublicValues)> {
rhs_public_values: PublicValues<F>,
) -> anyhow::Result<(ProofWithPublicInputs<F, C, D>, PublicValues<F>)> {
let mut txn_inputs = PartialWitness::new();

Self::set_dummy_if_necessary(
Expand Down Expand Up @@ -2290,8 +2303,8 @@ where
&self,
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)> {
public_values: PublicValues<F>,
) -> anyhow::Result<(ProofWithPublicInputs<F, C, D>, PublicValues<F>)> {
let mut block_inputs = PartialWitness::new();

block_inputs.set_bool_target(
Expand Down Expand Up @@ -2387,14 +2400,14 @@ where
+ TrieRootsTarget::SIZE * 2
+ BlockMetadataTarget::SIZE
+ BlockHashesTarget::SIZE
- 8;

- 16;
for i in 0..public_values.block_hashes.prev_hashes.len() - 1 {
let targets = h256_limbs::<F>(public_values.block_hashes.prev_hashes[i]);
for j in 0..8 {
nonzero_pis.insert(block_hashes_keys.start + 8 * (i + 1) + j, targets[j]);
}
}

let block_hashes_current_start = burn_addr_offset
+ TrieRootsTarget::SIZE * 2
+ BlockMetadataTarget::SIZE
Expand Down Expand Up @@ -2474,11 +2487,15 @@ where
/// This method outputs a tuple of [`ProofWithPublicInputs<F, C, D>`] and
/// associated [`FinalPublicValues`]. Only the proof with public inputs is
/// necessary for a verifier to assert correctness of the computation.
#[allow(clippy::type_complexity)]
pub fn prove_block_wrapper(
&self,
block_proof: &ProofWithPublicInputs<F, C, D>,
public_values: PublicValues,
) -> anyhow::Result<(ProofWithPublicInputs<F, C, D>, FinalPublicValues)> {
public_values: PublicValues<F>,
) -> anyhow::Result<(
ProofWithPublicInputs<F, C, D>,
FinalPublicValues<F, C::InnerHasher>,
)> {
let mut block_wrapper_inputs = PartialWitness::new();

block_wrapper_inputs
Expand Down
Loading

0 comments on commit 4ef831b

Please sign in to comment.