Skip to content

Commit

Permalink
Hex serialize LightClientProofResponse fields (#1709)
Browse files Browse the repository at this point in the history
  • Loading branch information
exeokan authored Jan 16, 2025
1 parent 7cb58b5 commit 9dd9b41
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 55 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

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

89 changes: 56 additions & 33 deletions bin/citrea/tests/bitcoin_e2e/light_client_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use rand::{thread_rng, Rng};
use risc0_zkvm::{FakeReceipt, InnerReceipt, MaybePruned, Receipt, ReceiptClaim};
use sov_ledger_rpc::LedgerRpcClient;
use sov_rollup_interface::da::{BatchProofMethodId, DaTxRequest};
use sov_rollup_interface::rpc::BatchProofMethodIdRpcResponse;
use sov_rollup_interface::zk::BatchProofCircuitOutput;

use super::batch_prover_test::wait_for_zkproofs;
Expand Down Expand Up @@ -598,14 +599,18 @@ impl TestCase for LightClientBatchProofMethodIdUpdateTest {
assert_eq!(
lcp_output.batch_proof_method_ids,
vec![
(
0,
BatchProofMethodIdRpcResponse::new(
U64::from(0),
[
1129196088, 155917133, 2638897170, 1970178024, 1745057535, 2098237452,
402126456, 572125060
]
.into()
),
(100, citrea_risc0_batch_proof::BATCH_PROOF_BITCOIN_ID)
BatchProofMethodIdRpcResponse::new(
U64::from(100),
citrea_risc0_batch_proof::BATCH_PROOF_BITCOIN_ID.into()
)
],
);

Expand Down Expand Up @@ -647,14 +652,18 @@ impl TestCase for LightClientBatchProofMethodIdUpdateTest {
assert_eq!(
lcp_output.batch_proof_method_ids,
vec![
(
0,
BatchProofMethodIdRpcResponse::new(
U64::from(0),
[
1129196088, 155917133, 2638897170, 1970178024, 1745057535, 2098237452,
402126456, 572125060
],
]
.into(),
),
BatchProofMethodIdRpcResponse::new(
U64::from(100),
citrea_risc0_batch_proof::BATCH_PROOF_BITCOIN_ID.into()
),
(100, citrea_risc0_batch_proof::BATCH_PROOF_BITCOIN_ID),
]
);

Expand All @@ -669,15 +678,22 @@ impl TestCase for LightClientBatchProofMethodIdUpdateTest {
assert_eq!(
lcp_output.batch_proof_method_ids,
vec![
(
0,
BatchProofMethodIdRpcResponse::new(
U64::from(0),
[
1129196088, 155917133, 2638897170, 1970178024, 1745057535, 2098237452,
402126456, 572125060
],
]
.into(),
),
(100, citrea_risc0_batch_proof::BATCH_PROOF_BITCOIN_ID),
(200, new_batch_proof_method_id)
BatchProofMethodIdRpcResponse::new(
U64::from(100),
citrea_risc0_batch_proof::BATCH_PROOF_BITCOIN_ID.into()
),
BatchProofMethodIdRpcResponse::new(
U64::from(200),
new_batch_proof_method_id.into()
)
]
);

Expand All @@ -700,15 +716,22 @@ impl TestCase for LightClientBatchProofMethodIdUpdateTest {
assert_eq!(
lcp_output.batch_proof_method_ids,
vec![
(
0,
BatchProofMethodIdRpcResponse::new(
U64::from(0),
[
1129196088, 155917133, 2638897170, 1970178024, 1745057535, 2098237452,
402126456, 572125060
],
]
.into(),
),
BatchProofMethodIdRpcResponse::new(
U64::from(100),
citrea_risc0_batch_proof::BATCH_PROOF_BITCOIN_ID.into()
),
(100, citrea_risc0_batch_proof::BATCH_PROOF_BITCOIN_ID),
(200, new_batch_proof_method_id)
BatchProofMethodIdRpcResponse::new(
U64::from(200),
new_batch_proof_method_id.into()
)
]
);

Expand Down Expand Up @@ -816,13 +839,13 @@ impl TestCase for LightClientUnverifiableBatchProofTest {
let method_ids = lcp_output.batch_proof_method_ids;
let genesis_state_root = lcp_output.state_root;

let fork1_height = method_ids[1].0;
let fork1_height: u64 = method_ids[1].height.to();

let verifiable_batch_proof = create_serialized_fake_receipt_batch_proof(
genesis_state_root,
[1u8; 32],
fork1_height + 1,
method_ids[1].1,
method_ids[1].method_id.into(),
None,
false,
);
Expand All @@ -835,7 +858,7 @@ impl TestCase for LightClientUnverifiableBatchProofTest {
[2u8; 32],
[3u8; 32],
fork1_height * 3,
method_ids[1].1,
method_ids[1].method_id.into(),
None,
false,
);
Expand All @@ -849,7 +872,7 @@ impl TestCase for LightClientUnverifiableBatchProofTest {
[3u8; 32],
[5u8; 32],
fork1_height * 4,
method_ids[1].1,
method_ids[1].method_id.into(),
None,
true,
);
Expand All @@ -862,7 +885,7 @@ impl TestCase for LightClientUnverifiableBatchProofTest {
[1u8; 32],
[2u8; 32],
fork1_height * 2,
method_ids[1].1,
method_ids[1].method_id.into(),
None,
false,
);
Expand Down Expand Up @@ -911,7 +934,7 @@ impl TestCase for LightClientUnverifiableBatchProofTest {

// The unverifiable batch proof and malformed journal batch proof should not have updated the state root or the last l2 height
assert_eq!(lcp_output.state_root, [3u8; 32]);
assert_eq!(lcp_output.last_l2_height, fork1_height * 3);
assert_eq!(lcp_output.last_l2_height, U64::from(fork1_height * 3));
assert!(lcp_output.unchained_batch_proofs_info.is_empty());

Ok(())
Expand Down Expand Up @@ -1025,7 +1048,7 @@ impl TestCase for VerifyChunkedTxsInLightClient {
let method_ids = lcp_output.batch_proof_method_ids;
let genesis_state_root = lcp_output.state_root;

let fork1_height = method_ids[1].0;
let fork1_height: u64 = method_ids[1].height.to();

// Even though the state diff is 100kb the proof will be 200kb because the fake receipt claim also has the journal
// But the compressed size will go down to 100kb
Expand All @@ -1036,7 +1059,7 @@ impl TestCase for VerifyChunkedTxsInLightClient {
genesis_state_root,
[1u8; 32],
fork1_height + 1,
method_ids[1].1,
method_ids[1].method_id.into(),
Some(state_diff_100kb.clone()),
false,
);
Expand Down Expand Up @@ -1074,7 +1097,7 @@ impl TestCase for VerifyChunkedTxsInLightClient {

// The batch proof should have updated the state root and the last l2 height
assert_eq!(lcp_output.state_root, [1u8; 32]);
assert_eq!(lcp_output.last_l2_height, fork1_height + 1);
assert_eq!(lcp_output.last_l2_height, U64::from(fork1_height + 1));
assert!(lcp_output.unchained_batch_proofs_info.is_empty());

// Now generate another proof but this time:
Expand All @@ -1089,7 +1112,7 @@ impl TestCase for VerifyChunkedTxsInLightClient {
[1u8; 32],
[2u8; 32],
fork1_height * 2,
method_ids[1].1,
method_ids[1].method_id.into(),
Some(state_diff_130kb),
false,
);
Expand Down Expand Up @@ -1159,10 +1182,10 @@ impl TestCase for VerifyChunkedTxsInLightClient {

// The batch proof should not have updated the state root and the last l2 height because these are only the chunks
assert_eq!(lcp_output.state_root, [1u8; 32]);
assert_eq!(lcp_output.last_l2_height, fork1_height + 1);
assert_eq!(lcp_output.last_l2_height, U64::from(fork1_height + 1));
assert!(lcp_output.unchained_batch_proofs_info.is_empty());
// There are two chunks so the size should be 2
assert_eq!(lcp_output.mmr_guest.size, 2);
assert_eq!(lcp_output.mmr_guest.size, U64::from(2));

let lcp_last_chunks = light_client_prover
.client
Expand All @@ -1174,10 +1197,10 @@ impl TestCase for VerifyChunkedTxsInLightClient {

// The batch proof should not have updated the state root and the last l2 height because these are only the chunks
assert_eq!(lcp_output.state_root, [1u8; 32]);
assert_eq!(lcp_output.last_l2_height, fork1_height + 1);
assert_eq!(lcp_output.last_l2_height, U64::from(fork1_height + 1));
assert!(lcp_output.unchained_batch_proofs_info.is_empty());
// There are now four chunks in total so the size should be 4
assert_eq!(lcp_output.mmr_guest.size, 4);
assert_eq!(lcp_output.mmr_guest.size, U64::from(4));

// Expect light client prover to have generated light client proof
let lcp_aggregate = light_client_prover
Expand All @@ -1190,7 +1213,7 @@ impl TestCase for VerifyChunkedTxsInLightClient {

// The batch proof should have updated the state root and the last l2 height
assert_eq!(lcp_output.state_root, [2u8; 32]);
assert_eq!(lcp_output.last_l2_height, fork1_height * 2);
assert_eq!(lcp_output.last_l2_height, U64::from(fork1_height * 2));
assert!(lcp_output.unchained_batch_proofs_info.is_empty());

let random_method_id = [1u32; 8];
Expand Down Expand Up @@ -1236,7 +1259,7 @@ impl TestCase for VerifyChunkedTxsInLightClient {
// The batch proof should NOT have updated the state root and the last l2 height
// Because it is not verified
assert_eq!(lcp_output.state_root, [2u8; 32]);
assert_eq!(lcp_output.last_l2_height, fork1_height * 2);
assert_eq!(lcp_output.last_l2_height, U64::from(fork1_height * 2));
// Also should not leave unchained outputs
assert!(lcp_output.unchained_batch_proofs_info.is_empty());

Expand Down
1 change: 1 addition & 0 deletions crates/sovereign-sdk/full-node/db/sov-db/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ sov-rollup-interface = { path = "../../../rollup-interface", features = ["native
sov-schema-db = { path = "../sov-schema-db" }

# External
alloy-primitives = { workspace = true, features=["serde"] }
anyhow = { workspace = true, default-features = true }
bincode = { workspace = true }
borsh = { workspace = true, default-features = true, features = ["bytes", "rc"] }
Expand Down
42 changes: 30 additions & 12 deletions crates/sovereign-sdk/full-node/db/sov-db/src/schema/types.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use std::fmt::Debug;
use std::sync::Arc;

use alloy_primitives::{U32, U64};
use borsh::{BorshDeserialize, BorshSerialize};
use sov_rollup_interface::da::LatestDaState;
use sov_rollup_interface::mmr::MMRGuest;
use sov_rollup_interface::rpc::{
BatchProofOutputRpcResponse, BatchProofResponse, HexTx, LatestDaStateRpcResponse,
LightClientProofOutputRpcResponse, LightClientProofResponse, SoftConfirmationResponse,
VerifiedBatchProofResponse,
BatchProofMethodIdRpcResponse, BatchProofOutputRpcResponse, BatchProofResponse, HexTx,
LatestDaStateRpcResponse, LightClientProofOutputRpcResponse, LightClientProofResponse,
SoftConfirmationResponse, VerifiedBatchProofResponse,
};
use sov_rollup_interface::soft_confirmation::SignedSoftConfirmation;
use sov_rollup_interface::zk::{
Expand Down Expand Up @@ -103,19 +104,36 @@ impl From<StoredLightClientProofOutput> for LightClientProofOutputRpcResponse {
fn from(value: StoredLightClientProofOutput) -> Self {
Self {
state_root: value.state_root,
light_client_proof_method_id: value.light_client_proof_method_id,
light_client_proof_method_id: value.light_client_proof_method_id.into(),
latest_da_state: LatestDaStateRpcResponse {
block_hash: value.latest_da_state.block_hash,
block_height: value.latest_da_state.block_height,
block_height: U64::from(value.latest_da_state.block_height),
total_work: value.latest_da_state.total_work,
current_target_bits: value.latest_da_state.current_target_bits,
epoch_start_time: value.latest_da_state.epoch_start_time,
prev_11_timestamps: value.latest_da_state.prev_11_timestamps,
current_target_bits: U32::from(value.latest_da_state.current_target_bits),
epoch_start_time: U32::from(value.latest_da_state.epoch_start_time),
prev_11_timestamps: value
.latest_da_state
.prev_11_timestamps
.into_iter()
.map(U32::from)
.collect::<Vec<_>>()
.try_into()
.expect("should have 11 elements"),
},
unchained_batch_proofs_info: value.unchained_batch_proofs_info,
last_l2_height: value.last_l2_height,
batch_proof_method_ids: value.batch_proof_method_ids,
mmr_guest: value.mmr_guest,
unchained_batch_proofs_info: value
.unchained_batch_proofs_info
.into_iter()
.map(Into::into)
.collect(),
last_l2_height: U64::from(value.last_l2_height),
batch_proof_method_ids: value
.batch_proof_method_ids
.into_iter()
.map(|(height, method_id)| {
BatchProofMethodIdRpcResponse::new(U64::from(height), method_id.into())
})
.collect(),
mmr_guest: value.mmr_guest.into(),
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion crates/sovereign-sdk/rollup-interface/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ resolver = "2"
[dependencies]
anyhow = { workspace = true }
async-trait = { workspace = true }
alloy-primitives = { workspace = true, features=["serde"], optional = true}
borsh = { workspace = true }
bytes = { workspace = true, optional = true, default-features = true }
digest = { workspace = true }
Expand All @@ -29,13 +30,14 @@ thiserror = { workspace = true, optional = true }
# TODO: Remove tokio when https://github.com/Sovereign-Labs/sovereign-sdk/issues/1161 is resolved
tokio = { workspace = true, optional = true }
tracing = { workspace = true, optional = true }
risc0-zkp = { workspace = true, optional = true }

[dev-dependencies]
serde_json = { workspace = true }

[features]
default = ["std"]
native = ["std", "tokio", "futures", "tracing"]
native = ["alloy-primitives", "std", "tokio", "futures", "tracing", "risc0-zkp"]
testing = []
std = [
"anyhow/default",
Expand Down
Loading

0 comments on commit 9dd9b41

Please sign in to comment.