Skip to content

Commit

Permalink
Remove final state root from batch proof input (#1449)
Browse files Browse the repository at this point in the history
  • Loading branch information
yaziciahmet authored Nov 11, 2024
1 parent 708502d commit 79a1bb5
Show file tree
Hide file tree
Showing 21 changed files with 205 additions and 118 deletions.
70 changes: 25 additions & 45 deletions crates/batch-prover/src/proving.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ use serde::de::DeserializeOwned;
use serde::Serialize;
use sov_db::ledger_db::BatchProverLedgerOps;
use sov_db::schema::types::{BatchNumber, StoredBatchProof, StoredBatchProofOutput};
use sov_modules_api::{BlobReaderTrait, SlotData, SpecId, Zkvm};
use sov_modules_api::{BatchProofCircuitOutputV2, BlobReaderTrait, SlotData, SpecId, Zkvm};
use sov_rollup_interface::da::{BlockHeaderTrait, DaNamespace, DaSpec, SequencerCommitment};
use sov_rollup_interface::fork::fork_from_block_number;
use sov_rollup_interface::rpc::SoftConfirmationStatus;
use sov_rollup_interface::services::da::DaService;
use sov_rollup_interface::zk::{BatchProofCircuitInput, BatchProofCircuitOutput, Proof, ZkvmHost};
use sov_rollup_interface::zk::{BatchProofCircuitInputV2, Proof, ZkvmHost};
use sov_stf_runner::ProverService;
use tokio::sync::Mutex;
use tracing::{debug, info};
Expand All @@ -38,7 +38,7 @@ pub(crate) async fn data_to_prove<Da, DB, StateRoot, Witness>(
) -> Result<
(
Vec<SequencerCommitment>,
Vec<BatchProofCircuitInput<'static, StateRoot, Witness, Da::Spec>>,
Vec<BatchProofCircuitInputV2<'static, StateRoot, Witness, Da::Spec>>,
),
L1ProcessingError,
>
Expand Down Expand Up @@ -119,8 +119,6 @@ where
for sequencer_commitments_range in ranges {
let first_l2_height_of_l1 =
sequencer_commitments[*sequencer_commitments_range.start()].l2_start_block_number;
let last_l2_height_of_l1 =
sequencer_commitments[*sequencer_commitments_range.end()].l2_end_block_number;
let (
state_transition_witnesses,
soft_confirmations,
Expand All @@ -144,43 +142,25 @@ where
L1ProcessingError::Other(format!("Error getting initial state root: {:?}", e))
})?
.expect("There should be a state root");
let initial_batch_hash = ledger
.get_soft_confirmation_by_number(&BatchNumber(first_l2_height_of_l1))
.map_err(|e| {
L1ProcessingError::Other(format!("Error getting initial batch hash: {:?}", e))
})?
.ok_or(L1ProcessingError::Other(format!(
"Could not find soft batch at height {}",
first_l2_height_of_l1
)))?
.prev_hash;

let final_state_root = ledger
.get_l2_state_root::<StateRoot>(last_l2_height_of_l1)
.map_err(|e| {
L1ProcessingError::Other(format!("Error getting final state root: {:?}", e))
})?
.expect("There should be a state root");

let input: BatchProofCircuitInput<StateRoot, Witness, Da::Spec> = BatchProofCircuitInput {
initial_state_root,
final_state_root,
prev_soft_confirmation_hash: initial_batch_hash,
da_data: da_data.clone(),
da_block_header_of_commitments: da_block_header_of_commitments.clone(),
inclusion_proof: inclusion_proof.clone(),
completeness_proof: completeness_proof.clone(),
soft_confirmations,
state_transition_witnesses,
da_block_headers_of_soft_confirmations,
preproven_commitments: preproven_commitments.to_vec(),
sequencer_commitments_range: (
*sequencer_commitments_range.start() as u32,
*sequencer_commitments_range.end() as u32,
),
sequencer_public_key: sequencer_pub_key.clone(),
sequencer_da_public_key: sequencer_da_pub_key.clone(),
};
let input: BatchProofCircuitInputV2<StateRoot, Witness, Da::Spec> =
BatchProofCircuitInputV2 {
initial_state_root,
da_data: da_data.clone(),
da_block_header_of_commitments: da_block_header_of_commitments.clone(),
inclusion_proof: inclusion_proof.clone(),
completeness_proof: completeness_proof.clone(),
soft_confirmations,
state_transition_witnesses,
da_block_headers_of_soft_confirmations,
preproven_commitments: preproven_commitments.to_vec(),
sequencer_commitments_range: (
*sequencer_commitments_range.start() as u32,
*sequencer_commitments_range.end() as u32,
),
sequencer_public_key: sequencer_pub_key.clone(),
sequencer_da_public_key: sequencer_da_pub_key.clone(),
};

batch_proof_circuit_inputs.push(input);
}
Expand All @@ -194,7 +174,7 @@ pub(crate) async fn prove_l1<Da, Ps, Vm, DB, StateRoot, Witness>(
code_commitments_by_spec: HashMap<SpecId, Vm::CodeCommitment>,
l1_block: Da::FilteredBlock,
sequencer_commitments: Vec<SequencerCommitment>,
inputs: Vec<BatchProofCircuitInput<'_, StateRoot, Witness, Da::Spec>>,
inputs: Vec<BatchProofCircuitInputV2<'_, StateRoot, Witness, Da::Spec>>,
) -> anyhow::Result<()>
where
Da: DaService,
Expand Down Expand Up @@ -247,7 +227,7 @@ where
}

pub(crate) fn state_transition_already_proven<StateRoot, Witness, Da>(
input: &BatchProofCircuitInput<StateRoot, Witness, Da::Spec>,
input: &BatchProofCircuitInputV2<StateRoot, Witness, Da::Spec>,
proofs: &Vec<StoredBatchProof>,
) -> bool
where
Expand All @@ -263,7 +243,6 @@ where
{
for proof in proofs {
if proof.proof_output.initial_state_root == input.initial_state_root.as_ref()
&& proof.proof_output.final_state_root == input.final_state_root.as_ref()
&& proof.proof_output.sequencer_commitments_range == input.sequencer_commitments_range
{
return true;
Expand Down Expand Up @@ -294,9 +273,10 @@ where

// l1_height => (tx_id, proof, circuit_output)
// save proof along with tx id to db, should be queryable by slot number or slot hash
// TODO: select output version based on spec
let circuit_output = Vm::extract_output::<
<Da as DaService>::Spec,
BatchProofCircuitOutput<<Da as DaService>::Spec, StateRoot>,
BatchProofCircuitOutputV2<<Da as DaService>::Spec, StateRoot>,
>(&proof)
.expect("Proof should be deserializable");

Expand Down
2 changes: 1 addition & 1 deletion crates/batch-prover/src/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ where

let receipt = soft_confirmation_result.soft_confirmation_receipt;

let next_state_root = soft_confirmation_result.state_root;
let next_state_root = soft_confirmation_result.state_root_transition.final_root;
// Check if post state root is the same as the one in the soft confirmation
if next_state_root.as_ref().to_vec() != soft_confirmation.state_root {
bail!("Post state root mismatch at height: {}", l2_height)
Expand Down
8 changes: 3 additions & 5 deletions crates/batch-prover/tests/prover_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use sov_db::rocks_db_config::RocksdbConfig;
use sov_mock_da::{MockAddress, MockBlockHeader, MockDaService, MockDaSpec, MockHash};
use sov_mock_zkvm::MockZkvm;
use sov_rollup_interface::da::Time;
use sov_rollup_interface::zk::BatchProofCircuitInput;
use sov_rollup_interface::zk::BatchProofCircuitInputV2;
use sov_stf_runner::mock::MockStf;
use sov_stf_runner::ProverService;

Expand Down Expand Up @@ -99,11 +99,9 @@ fn make_new_prover(thread_pool_size: usize, da_service: Arc<MockDaService>) -> T

fn make_transition_data(
header_hash: MockHash,
) -> BatchProofCircuitInput<'static, [u8; 0], Vec<u8>, MockDaSpec> {
BatchProofCircuitInput {
) -> BatchProofCircuitInputV2<'static, [u8; 0], Vec<u8>, MockDaSpec> {
BatchProofCircuitInputV2 {
initial_state_root: [],
final_state_root: [],
prev_soft_confirmation_hash: [0; 32],
inclusion_proof: [0; 32],
completeness_proof: (),
da_data: vec![],
Expand Down
15 changes: 5 additions & 10 deletions crates/citrea-stf/src/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ use std::marker::PhantomData;
use citrea_primitives::forks::FORKS;
use sov_rollup_interface::da::{BlockHeaderTrait, DaNamespace, DaVerifier};
use sov_rollup_interface::stf::{ApplySequencerCommitmentsOutput, StateTransitionFunction};
use sov_rollup_interface::zk::{BatchProofCircuitInput, BatchProofCircuitOutput, Zkvm, ZkvmGuest};
use sov_rollup_interface::zk::{
BatchProofCircuitInputV2, BatchProofCircuitOutputV2, Zkvm, ZkvmGuest,
};

/// Verifies a state transition
pub struct StateTransitionVerifier<ST, Da, Zk>
Expand Down Expand Up @@ -39,7 +41,7 @@ where
pre_state: Stf::PreState,
) -> Result<(), Da::Error> {
println!("Running sequencer commitments in DA slot");
let data: BatchProofCircuitInput<Stf::StateRoot, _, Da::Spec> = zkvm.read_from_host();
let data: BatchProofCircuitInputV2<Stf::StateRoot, _, Da::Spec> = zkvm.read_from_host();

if !data.da_block_header_of_commitments.verify_hash() {
panic!("Invalid hash of DA block header of commitments");
Expand Down Expand Up @@ -77,7 +79,6 @@ where
data.sequencer_public_key.as_ref(),
data.sequencer_da_public_key.as_ref(),
&data.initial_state_root,
data.prev_soft_confirmation_hash,
pre_state,
data.da_data,
data.sequencer_commitments_range,
Expand All @@ -89,16 +90,10 @@ where
);

println!("out of apply_soft_confirmations_from_sequencer_commitments");
assert_eq!(
final_state_root.as_ref(),
data.final_state_root.as_ref(),
"Invalid final state root"
);

let out: BatchProofCircuitOutput<Da::Spec, _> = BatchProofCircuitOutput {
let out: BatchProofCircuitOutputV2<Da::Spec, _> = BatchProofCircuitOutputV2 {
initial_state_root: data.initial_state_root,
final_state_root,
prev_soft_confirmation_hash: data.prev_soft_confirmation_hash,
final_soft_confirmation_hash,
state_diff,
da_slot_hash: data.da_block_header_of_commitments.hash(),
Expand Down
25 changes: 14 additions & 11 deletions crates/evm/src/evm/conversions.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
use citrea_primitives::forks::FORKS;
use reth_primitives::{
Bytes as RethBytes, SealedHeader, TransactionSigned, TransactionSignedEcRecovered,
TransactionSignedNoHash, KECCAK_EMPTY,
Bytes as RethBytes, TransactionSigned, TransactionSignedEcRecovered, TransactionSignedNoHash,
KECCAK_EMPTY,
};
use revm::primitives::{
AccountInfo as ReVmAccountInfo, BlobExcessGasAndPrice, BlockEnv, SpecId, TransactTo, TxEnv,
U256,
};
use sov_modules_api::fork::fork_from_block_number;
use revm::primitives::{AccountInfo as ReVmAccountInfo, SpecId, TransactTo, TxEnv, U256};

use super::primitive_types::{RlpEvmTransaction, TransactionSignedAndRecovered};
use super::AccountInfo;
use crate::citrea_spec_id_to_evm_spec_id;

impl From<AccountInfo> for ReVmAccountInfo {
fn from(info: AccountInfo) -> Self {
Expand Down Expand Up @@ -132,8 +126,17 @@ impl From<TransactionSignedAndRecovered> for TransactionSignedEcRecovered {
}
}

pub(crate) fn sealed_block_to_block_env(sealed_header: &SealedHeader) -> BlockEnv {
BlockEnv {
#[cfg(feature = "native")]
pub(crate) fn sealed_block_to_block_env(
sealed_header: &reth_primitives::SealedHeader,
) -> revm::primitives::BlockEnv {
use citrea_primitives::forks::FORKS;
use revm::primitives::BlobExcessGasAndPrice;
use sov_modules_api::fork::fork_from_block_number;

use crate::citrea_spec_id_to_evm_spec_id;

revm::primitives::BlockEnv {
number: U256::from(sealed_header.number),
coinbase: sealed_header.beneficiary,
timestamp: U256::from(sealed_header.timestamp),
Expand Down
4 changes: 2 additions & 2 deletions crates/evm/src/tests/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ pub(crate) fn commit(

let (cache_log, mut witness) = checkpoint.freeze();

let (root, authenticated_node_batch, _) = storage
let (state_root_transition, authenticated_node_batch, _) = storage
.compute_state_update(cache_log, &mut witness)
.expect("jellyfish merkle tree update must succeed");

Expand All @@ -111,7 +111,7 @@ pub(crate) fn commit(

storage.commit(&authenticated_node_batch, &accessory_log, &offchain_log);

root.0
state_root_transition.final_root.0
}

/// Loads the genesis configuration from the given path and pushes the accounts to the evm config
Expand Down
5 changes: 3 additions & 2 deletions crates/fullnode/src/da_block_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use sov_rollup_interface::fork::fork_from_block_number;
use sov_rollup_interface::rpc::SoftConfirmationStatus;
use sov_rollup_interface::services::da::{DaService, SlotData};
use sov_rollup_interface::spec::SpecId;
use sov_rollup_interface::zk::{BatchProofCircuitOutput, Proof, ZkvmHost};
use sov_rollup_interface::zk::{BatchProofCircuitOutputV2, Proof, ZkvmHost};
use tokio::select;
use tokio::sync::{mpsc, Mutex};
use tokio::time::{sleep, Duration};
Expand Down Expand Up @@ -298,9 +298,10 @@ where
);
tracing::debug!("ZK proof: {:?}", proof);

// TODO: select output version based on spec
let batch_proof_output = Vm::extract_output::<
<Da as DaService>::Spec,
BatchProofCircuitOutput<<Da as DaService>::Spec, StateRoot>,
BatchProofCircuitOutputV2<<Da as DaService>::Spec, StateRoot>,
>(&proof)
.expect("Proof should be deserializable");
if batch_proof_output.sequencer_da_public_key != self.sequencer_da_pub_key
Expand Down
2 changes: 1 addition & 1 deletion crates/fullnode/src/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ where

let receipt = soft_confirmation_result.soft_confirmation_receipt;

let next_state_root = soft_confirmation_result.state_root;
let next_state_root = soft_confirmation_result.state_root_transition.final_root;
// Check if post state root is the same as the one in the soft confirmation
if next_state_root.as_ref().to_vec() != soft_confirmation.state_root {
bail!("Post state root mismatch at height: {}", l2_height)
Expand Down
11 changes: 8 additions & 3 deletions crates/fullnode/tests/hash_stf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ impl HashStf {
ordered_writes: vec![(hash_key.to_cache_key(), Some(hash_value.into_cache_value()))],
};

let (jmt_root_hash, state_update, _) = storage
let (state_root_transition, state_update, _) = storage
.compute_state_update(ordered_reads_writes, witness)
.unwrap();

Expand All @@ -55,7 +55,13 @@ impl HashStf {

let mut root_hash = [0u8; 32];

for (i, &byte) in jmt_root_hash.as_ref().iter().enumerate().take(32) {
for (i, &byte) in state_root_transition
.final_root
.as_ref()
.iter()
.enumerate()
.take(32)
{
root_hash[i] = byte;
}

Expand Down Expand Up @@ -227,7 +233,6 @@ impl<Da: DaSpec> StateTransitionFunction<Da> for HashStf {
_sequencer_public_key: &[u8],
_sequencer_da_public_key: &[u8],
_initial_state_root: &Self::StateRoot,
_initial_batch_hash: [u8; 32],
_pre_state: Self::PreState,
_da_data: Vec<<Da as DaSpec>::BlobTransaction>,
_sequencer_commitments_range: (u32, u32),
Expand Down
5 changes: 3 additions & 2 deletions crates/light-client-prover/src/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use borsh::BorshDeserialize;
use sov_modules_api::BlobReaderTrait;
use sov_rollup_interface::da::{DaDataLightClient, DaNamespace, DaVerifier};
use sov_rollup_interface::zk::{
BatchProofCircuitOutput, BatchProofInfo, LightClientCircuitInput, LightClientCircuitOutput,
BatchProofCircuitOutputV2, BatchProofInfo, LightClientCircuitInput, LightClientCircuitOutput,
ZkvmGuest,
};

Expand Down Expand Up @@ -101,7 +101,8 @@ pub fn run_circuit<DaV: DaVerifier, G: ZkvmGuest>(
DaDataLightClient::Complete(proof) => {
let journal =
G::extract_raw_output(&proof).expect("DaData proofs must be valid");
let batch_proof_output: BatchProofCircuitOutput<DaV::Spec, [u8; 32]> =
// TODO: select output version based on the spec
let batch_proof_output: BatchProofCircuitOutputV2<DaV::Spec, [u8; 32]> =
match G::verify_and_extract_output(
&journal,
&batch_proof_method_id.into(),
Expand Down
5 changes: 2 additions & 3 deletions crates/light-client-prover/src/tests/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::collections::BTreeMap;
use sov_mock_da::{MockAddress, MockBlob, MockDaSpec, MockHash};
use sov_mock_zkvm::{MockCodeCommitment, MockJournal, MockProof};
use sov_rollup_interface::da::{BlobReaderTrait, DaDataLightClient};
use sov_rollup_interface::zk::{BatchProofCircuitOutput, LightClientCircuitOutput};
use sov_rollup_interface::zk::{BatchProofCircuitOutputV2, LightClientCircuitOutput};

pub(crate) fn create_mock_blob(
initial_state_root: [u8; 32],
Expand All @@ -13,10 +13,9 @@ pub(crate) fn create_mock_blob(
) -> MockBlob {
let batch_proof_method_id = MockCodeCommitment([2u8; 32]);

let bp = BatchProofCircuitOutput::<MockDaSpec, [u8; 32]> {
let bp = BatchProofCircuitOutputV2::<MockDaSpec, [u8; 32]> {
initial_state_root,
final_state_root,
prev_soft_confirmation_hash: [3; 32],
final_soft_confirmation_hash: [4; 32],
state_diff: BTreeMap::new(),
da_slot_hash: MockHash([5; 32]),
Expand Down
7 changes: 4 additions & 3 deletions crates/sequencer/src/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -492,19 +492,20 @@ where
prestate,
&mut signed_soft_confirmation,
);
let state_root_transition = soft_confirmation_result.state_root_transition;

let receipt = soft_confirmation_result.soft_confirmation_receipt;

if soft_confirmation_result.state_root.as_ref() == self.state_root.as_ref() {
if state_root_transition.final_root.as_ref() == self.state_root.as_ref() {
bail!("Max L2 blocks per L1 is reached for the current L1 block. State root is the same as before, skipping");
}

trace!(
"State root after applying slot: {:?}",
soft_confirmation_result.state_root
state_root_transition.final_root,
);

let next_state_root = soft_confirmation_result.state_root;
let next_state_root = state_root_transition.final_root;

self.storage_manager
.save_change_set_l2(l2_height, soft_confirmation_result.change_set)?;
Expand Down
Loading

0 comments on commit 79a1bb5

Please sign in to comment.