Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgradeable batch proof method id lists in light client circuit #1630

Merged
merged 29 commits into from
Dec 25, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
4e04def
Add DaDataLightClient::BatchProverMethodId transaction
kpp Dec 19, 2024
4ba8ca9
Rename BatchProverMethodId -> BatchProofMethodId
kpp Dec 24, 2024
fd18cbd
Merge branch 'nightly' into kpp/light_client_method_msg
kpp Dec 24, 2024
134f499
Take METHOD_ID_UPGRADE_AUTHORITY from env
kpp Dec 24, 2024
d76156e
Merge branch 'nightly' into kpp/light_client_method_msg
eyusufatik Dec 24, 2024
9004b5f
implement method id upgrades for light client circuit
eyusufatik Dec 24, 2024
c727cd6
Lint
yaziciahmet Dec 24, 2024
14e32bc
Rename DaData to DaTxRequest
yaziciahmet Dec 25, 2024
86d3511
Implemented batch proof method id tx sending
yaziciahmet Dec 25, 2024
f18b011
Use type0 for method id tx
yaziciahmet Dec 25, 2024
3def078
Merge branch 'nightly' into kpp/light_client_method_msg
yaziciahmet Dec 25, 2024
04a43d3
Improve error handling in lcp circuit
yaziciahmet Dec 25, 2024
89494d3
Make method id tx data readable from guest
yaziciahmet Dec 25, 2024
9935337
Added e2e test
yaziciahmet Dec 25, 2024
434df7c
Make testcase default
yaziciahmet Dec 25, 2024
ae6634b
Test one more da block to ensure same method ids are being used
yaziciahmet Dec 25, 2024
71a7e33
Lint
yaziciahmet Dec 25, 2024
0703908
Remove print
yaziciahmet Dec 25, 2024
530770e
Lint
yaziciahmet Dec 25, 2024
92642c0
Fix test
yaziciahmet Dec 25, 2024
341f51d
Separate batch proof method id tx as type 2
yaziciahmet Dec 25, 2024
18e1c56
fix method id tx comments and rename field
eyusufatik Dec 25, 2024
0ca4387
update method id append test in bitcoin-e2e with different method id
eyusufatik Dec 25, 2024
d02cfa2
Add method id tx to crate tests
yaziciahmet Dec 25, 2024
7dc7ce8
Merge branch 'nightly' into kpp/light_client_method_msg
yaziciahmet Dec 25, 2024
88b7beb
Rename da tests
yaziciahmet Dec 25, 2024
cc0eb10
Fix verifier test
yaziciahmet Dec 25, 2024
62c6781
Fix bitcoin verifier test
yaziciahmet Dec 25, 2024
267b23b
Remove TODO comment
yaziciahmet Dec 25, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ byteorder = { version = "1.5.0", default-features = false }
bytes = { version = "1.2.1", default-features = false }
chrono = { version = "0.4.37", default-features = false }
clap = { version = "4.4.10", features = ["derive"] }
const-hex = "1.12"
crypto-bigint = { version = "0.5.5" }
digest = { version = "0.10.6", default-features = false, features = ["alloc"] }
derive_more = { version = "0.99.11", default-features = false }
Expand Down
4 changes: 4 additions & 0 deletions crates/bitcoin-da/src/helpers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ enum TransactionKindLightClient {
Chunked = 1,
/// This type of transaction includes chunk parts of body (>= 400kb)
ChunkedPart = 2,
/// This type of transaction includes a new batch proof method_id
BatchProofMethodId = 3,
Unknown(NonZeroU16),
}

Expand All @@ -26,6 +28,7 @@ impl TransactionKindLightClient {
TransactionKindLightClient::Complete => 0u16.to_le_bytes().to_vec(),
TransactionKindLightClient::Chunked => 1u16.to_le_bytes().to_vec(),
TransactionKindLightClient::ChunkedPart => 2u16.to_le_bytes().to_vec(),
TransactionKindLightClient::BatchProofMethodId => 3u16.to_le_bytes().to_vec(),
TransactionKindLightClient::Unknown(v) => v.get().to_le_bytes().to_vec(),
}
}
Expand All @@ -39,6 +42,7 @@ impl TransactionKindLightClient {
0 => Some(TransactionKindLightClient::Complete),
1 => Some(TransactionKindLightClient::Chunked),
2 => Some(TransactionKindLightClient::ChunkedPart),
3 => Some(TransactionKindLightClient::BatchProofMethodId),
n => Some(TransactionKindLightClient::Unknown(
NonZeroU16::new(n).expect("Is not zero"),
)),
Expand Down
72 changes: 70 additions & 2 deletions crates/bitcoin-da/src/helpers/parsers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ pub enum ParsedLightClientTransaction {
Aggregate(ParsedAggregate),
/// Kind 2
Chunk(ParsedChunk),
/// Kind 3
BatchProverMethodId(ParsedBatchProverMethodId),
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -54,6 +56,13 @@ pub struct ParsedSequencerCommitment {
pub public_key: Vec<u8>,
}

#[derive(Debug, Clone)]
pub struct ParsedBatchProverMethodId {
pub body: Vec<u8>,
pub signature: Vec<u8>,
pub public_key: Vec<u8>,
}

/// To verify the signature of the inscription and get the hash of the body
pub trait VerifyParsed {
fn public_key(&self) -> &[u8];
Expand Down Expand Up @@ -118,6 +127,18 @@ impl VerifyParsed for ParsedSequencerCommitment {
}
}

impl VerifyParsed for ParsedBatchProverMethodId {
fn public_key(&self) -> &[u8] {
&self.public_key
}
fn signature(&self) -> &[u8] {
&self.signature
}
fn body(&self) -> &[u8] {
&self.body
}
}

#[derive(Error, Debug, Clone, PartialEq)]
pub enum ParserError {
#[error("Invalid header length")]
Expand Down Expand Up @@ -196,6 +217,10 @@ fn parse_relevant_lightclient(
TransactionKindLightClient::ChunkedPart => {
light_client::parse_type_2_body(instructions).map(ParsedLightClientTransaction::Chunk)
}
TransactionKindLightClient::BatchProofMethodId => {
light_client::parse_type_3_body(instructions)
.map(ParsedLightClientTransaction::BatchProverMethodId)
}
TransactionKindLightClient::Unknown(n) => Err(ParserError::InvalidHeaderType(n)),
}
}
Expand Down Expand Up @@ -262,8 +287,8 @@ mod light_client {
use bitcoin::script::Instruction::{Op, PushBytes};

use super::{
read_instr, read_opcode, read_push_bytes, ParsedAggregate, ParsedChunk, ParsedComplete,
ParserError,
read_instr, read_opcode, read_push_bytes, ParsedAggregate, ParsedBatchProverMethodId,
ParsedChunk, ParsedComplete, ParserError,
};

// Parse transaction body of Type0
Expand Down Expand Up @@ -417,6 +442,49 @@ mod light_client {

Ok(ParsedChunk { body })
}

// Parse transaction body of Type3
pub(super) fn parse_type_3_body(
instructions: &mut dyn Iterator<Item = Result<Instruction<'_>, ParserError>>,
) -> Result<ParsedBatchProverMethodId, ParserError> {
let op_false = read_push_bytes(instructions)?;
if !op_false.is_empty() {
// OP_FALSE = OP_PUSHBYTES_0
return Err(ParserError::UnexpectedOpcode);
}

if OP_IF != read_opcode(instructions)? {
return Err(ParserError::UnexpectedOpcode);
}

let signature = read_push_bytes(instructions)?;
let public_key = read_push_bytes(instructions)?;
let body = read_push_bytes(instructions)?;

if OP_ENDIF != read_opcode(instructions)? {
return Err(ParserError::UnexpectedOpcode);
}

// Nonce
let _nonce = read_push_bytes(instructions)?;
if OP_NIP != read_opcode(instructions)? {
return Err(ParserError::UnexpectedOpcode);
}
// END of transaction
if instructions.next().is_some() {
return Err(ParserError::UnexpectedOpcode);
}

let signature = signature.as_bytes().to_vec();
let public_key = public_key.as_bytes().to_vec();
let body = body.as_bytes().to_vec();

Ok(ParsedBatchProverMethodId {
body,
signature,
public_key,
})
}
}

mod batch_proof {
Expand Down
17 changes: 16 additions & 1 deletion crates/bitcoin-da/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,9 @@ impl DaService for BitcoinService {
ParsedLightClientTransaction::Chunk(_chunk) => {
// we ignore them for now
}
ParsedLightClientTransaction::BatchProverMethodId(_) => {
// ignore because these are not proofs
}
}
}
}
Expand Down Expand Up @@ -827,7 +830,8 @@ impl DaService for BitcoinService {
body.extend(chunk);
}
ParsedLightClientTransaction::Complete(_)
| ParsedLightClientTransaction::Aggregate(_) => {
| ParsedLightClientTransaction::Aggregate(_)
| ParsedLightClientTransaction::BatchProverMethodId(_) => {
error!("{}:{}: Expected chunk, got other tx kind", tx_id, chunk_id);
continue 'aggregate;
}
Expand Down Expand Up @@ -994,6 +998,17 @@ impl DaService for BitcoinService {
ParsedLightClientTransaction::Chunk(_) => {
// ignore
}
ParsedLightClientTransaction::BatchProverMethodId(method_id) => {
if let Some(hash) = method_id.get_sig_verified_hash() {
let relevant_tx = BlobWithSender::new(
method_id.body,
method_id.public_key,
hash,
);

relevant_txs.push(relevant_tx);
}
}
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions crates/bitcoin-da/src/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,16 @@ impl DaVerifier for BitcoinVerifier {
ParsedLightClientTransaction::Chunk(_chunk) => {
// ignore
}
ParsedLightClientTransaction::BatchProverMethodId(method_id) => {
if let Some(blob_content) =
verified_blob_content(&method_id, &mut blobs_iter)?
{
// assert tx content is not modified
if blob_content != method_id.body {
return Err(ValidationError::BlobContentWasModified);
}
}
}
}
}
}
Expand Down
27 changes: 25 additions & 2 deletions crates/light-client-prover/src/circuit.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use borsh::BorshDeserialize;
use sov_modules_api::BlobReaderTrait;
use sov_rollup_interface::da::{DaDataLightClient, DaNamespace, DaVerifier};
use sov_rollup_interface::da::{BatchProofMethodId, DaDataLightClient, DaNamespace, DaVerifier};
use sov_rollup_interface::zk::{
BatchProofCircuitOutput, BatchProofInfo, LightClientCircuitInput, LightClientCircuitOutput,
OldBatchProofCircuitOutput, ZkvmGuest,
Expand All @@ -25,6 +25,7 @@ pub fn run_circuit<DaV: DaVerifier, G: ZkvmGuest>(
l2_genesis_root: [u8; 32],
initial_batch_proof_method_ids: InitialBatchProofMethodIds,
batch_prover_da_public_key: &[u8],
method_id_upgrade_authority_da_public_key: &[u8],
network: Network,
) -> Result<LightClientCircuitOutput, LightClientVerificationError> {
// Extract previous light client proof output
Expand All @@ -45,7 +46,7 @@ pub fn run_circuit<DaV: DaVerifier, G: ZkvmGuest>(
None
};

let batch_proof_method_ids = previous_light_client_proof_output
let mut batch_proof_method_ids = previous_light_client_proof_output
.as_ref()
.map_or(initial_batch_proof_method_ids, |o| {
o.batch_proof_method_ids.clone()
Expand Down Expand Up @@ -176,6 +177,28 @@ pub fn run_circuit<DaV: DaVerifier, G: ZkvmGuest>(
}
DaDataLightClient::Aggregate(_) => todo!(),
DaDataLightClient::Chunk(_) => todo!(),
DaDataLightClient::BatchProofMethodId(_) => {} // if coming from batch prover, ignore
}
}
} else if blob.sender().as_ref() == method_id_upgrade_authority_da_public_key {
let data = DaDataLightClient::try_from_slice(blob.verified_data());

if let Ok(data) = data {
match data {
DaDataLightClient::BatchProofMethodId(BatchProofMethodId {
method_id,
l2_block_number,
}) => {
let last_activation_height = batch_proof_method_ids
.last()
.expect("Should be at least one")
.0;

if l2_block_number > last_activation_height {
batch_proof_method_ids.push((l2_block_number, method_id));
}
}
_ => {} // ignore other types of data
}
}
}
Expand Down
Loading
Loading