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

Parse BatchProof/LightClient data from DA #1037

Merged
merged 16 commits into from
Sep 3, 2024
37 changes: 0 additions & 37 deletions bin/citrea/provers/risc0/guest-bitcoin/Cargo.lock

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

3 changes: 2 additions & 1 deletion crates/bitcoin-da/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ thiserror = { workspace = true }
tracing = { workspace = true, optional = true }

bitcoin = { workspace = true }
brotli = { workspace = true }
brotli = { workspace = true, optional = true }
futures.workspace = true
sha2 = { workspace = true }

Expand All @@ -36,6 +36,7 @@ bitcoincore-rpc = { workspace = true, optional = true }
[features]
default = []
native = [
"dep:brotli",
"dep:tokio",
"dep:pin-project",
"dep:tracing",
Expand Down
1 change: 0 additions & 1 deletion crates/bitcoin-da/src/helpers/compression.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::io::Write;

#[cfg(feature = "native")]
pub fn compress_blob(blob: &[u8]) -> Vec<u8> {
use brotli::CompressorWriter;
let mut writer = CompressorWriter::new(Vec::new(), 4096, 11, 22);
Expand Down
1 change: 1 addition & 0 deletions crates/bitcoin-da/src/helpers/merkle_tree.rs
kpp marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ impl BitcoinMerkleTree {
self.nodes[self.nodes.len() - 1][0]
}

#[cfg(feature = "native")]
pub fn get_idx_path(&self, index: u32) -> Vec<[u8; 32]> {
assert!(index < self.nodes[0].len() as u32, "Index out of bounds");
let mut path = vec![];
Expand Down
187 changes: 101 additions & 86 deletions crates/bitcoin-da/src/helpers/mod.rs
kpp marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,112 +1,127 @@
use core::num::NonZeroU16;

use sha2::{Digest, Sha256};

#[cfg(feature = "native")]
pub mod builders;
#[cfg(feature = "native")]
pub mod compression;
pub mod merkle_tree;
pub mod parsers;
#[cfg(test)]
pub mod test_utils;

/// Header - represents a header of a LightClient transaction
struct TransactionHeaderLightClient<'a> {
pub(crate) rollup_name: &'a [u8],
pub(crate) kind: TransactionKindLightClient,
}
#[cfg(feature = "native")]
mod light_client {
use core::num::NonZeroU16;

impl<'a> TransactionHeaderLightClient<'a> {
fn to_bytes(&self) -> Vec<u8> {
let kind = match self.kind {
TransactionKindLightClient::Complete => 0u16.to_le_bytes(),
TransactionKindLightClient::Chunked => 1u16.to_le_bytes(),
TransactionKindLightClient::ChunkedPart => 2u16.to_le_bytes(),
TransactionKindLightClient::Unknown(v) => v.get().to_le_bytes(),
};
let mut result = vec![];
result.extend_from_slice(&kind);
result.extend_from_slice(self.rollup_name);
result
/// Header - represents a header of a LightClient transaction
pub(crate) struct TransactionHeaderLightClient<'a> {
pub(crate) rollup_name: &'a [u8],
pub(crate) kind: TransactionKindLightClient,
}
fn from_bytes<'b: 'a>(bytes: &'b [u8]) -> Option<TransactionHeaderLightClient<'a>>
where
'a: 'b,
{
let (kind_slice, rollup_name) = bytes.split_at(2);
if kind_slice.len() != 2 {
return None;

impl<'a> TransactionHeaderLightClient<'a> {
pub(crate) fn to_bytes(&self) -> Vec<u8> {
let kind = match self.kind {
TransactionKindLightClient::Complete => 0u16.to_le_bytes(),
TransactionKindLightClient::Chunked => 1u16.to_le_bytes(),
TransactionKindLightClient::ChunkedPart => 2u16.to_le_bytes(),
TransactionKindLightClient::Unknown(v) => v.get().to_le_bytes(),
};
let mut result = vec![];
result.extend_from_slice(&kind);
result.extend_from_slice(self.rollup_name);
result
}
pub(crate) fn from_bytes<'b: 'a>(
bytes: &'b [u8],
) -> Option<TransactionHeaderLightClient<'a>>
where
'a: 'b,
{
let (kind_slice, rollup_name) = bytes.split_at(2);
if kind_slice.len() != 2 {
return None;
}
let mut kind_bytes = [0; 2];
kind_bytes.copy_from_slice(kind_slice);
let kind = match u16::from_le_bytes(kind_bytes) {
0 => TransactionKindLightClient::Complete,
1 => TransactionKindLightClient::Chunked,
2 => TransactionKindLightClient::ChunkedPart,
n => TransactionKindLightClient::Unknown(NonZeroU16::new(n).expect("Is not zero")),
};
Some(Self { rollup_name, kind })
}
let mut kind_bytes = [0; 2];
kind_bytes.copy_from_slice(kind_slice);
let kind = match u16::from_le_bytes(kind_bytes) {
0 => TransactionKindLightClient::Complete,
1 => TransactionKindLightClient::Chunked,
2 => TransactionKindLightClient::ChunkedPart,
n => TransactionKindLightClient::Unknown(NonZeroU16::new(n).expect("Is not zero")),
};
Some(Self { rollup_name, kind })
}
}

/// Header - represents a header of a BatchProof transaction
struct TransactionHeaderBatchProof<'a> {
pub(crate) rollup_name: &'a [u8],
pub(crate) kind: TransactionKindBatchProof,
/// Type represents a typed enum for LightClient kind
#[repr(u16)]
pub(crate) enum TransactionKindLightClient {
/// This type of transaction includes full body (< 400kb)
Complete = 0,
/// This type of transaction includes txids of chunks (>= 400kb)
Chunked = 1,
/// This type of transaction includes chunk parts of body (>= 400kb)
ChunkedPart = 2,
Unknown(NonZeroU16),
}
}

impl<'a> TransactionHeaderBatchProof<'a> {
fn to_bytes(&self) -> Vec<u8> {
let kind = match self.kind {
TransactionKindBatchProof::SequencerCommitment => 0u16.to_le_bytes(),
// TransactionKindBatchProof::ForcedTransaction => 1u16.to_le_bytes(),
TransactionKindBatchProof::Unknown(v) => v.get().to_le_bytes(),
};
let mut result = vec![];
result.extend_from_slice(&kind);
result.extend_from_slice(self.rollup_name);
result
mod batch_proof {
use core::num::NonZeroU16;

/// Header - represents a header of a BatchProof transaction
pub(crate) struct TransactionHeaderBatchProof<'a> {
pub(crate) rollup_name: &'a [u8],
pub(crate) kind: TransactionKindBatchProof,
}
fn from_bytes<'b: 'a>(bytes: &'b [u8]) -> Option<TransactionHeaderBatchProof<'a>>
where
'a: 'b,
{
let (kind_slice, rollup_name) = bytes.split_at(2);
if kind_slice.len() != 2 {
return None;

impl<'a> TransactionHeaderBatchProof<'a> {
#[cfg(feature = "native")]
pub(crate) fn to_bytes(&self) -> Vec<u8> {
let kind = match self.kind {
TransactionKindBatchProof::SequencerCommitment => 0u16.to_le_bytes(),
// TransactionKindBatchProof::ForcedTransaction => 1u16.to_le_bytes(),
TransactionKindBatchProof::Unknown(v) => v.get().to_le_bytes(),
};
let mut result = vec![];
result.extend_from_slice(&kind);
result.extend_from_slice(self.rollup_name);
result
}
pub(crate) fn from_bytes<'b: 'a>(bytes: &'b [u8]) -> Option<TransactionHeaderBatchProof<'a>>
where
'a: 'b,
{
let (kind_slice, rollup_name) = bytes.split_at(2);
if kind_slice.len() != 2 {
return None;
}
let mut kind_bytes = [0; 2];
kind_bytes.copy_from_slice(kind_slice);
let kind = match u16::from_le_bytes(kind_bytes) {
0 => TransactionKindBatchProof::SequencerCommitment,
// 1 => TransactionKindBatchProof::ForcedTransaction,
n => TransactionKindBatchProof::Unknown(NonZeroU16::new(n).expect("Is not zero")),
};
Some(Self { rollup_name, kind })
}
let mut kind_bytes = [0; 2];
kind_bytes.copy_from_slice(kind_slice);
let kind = match u16::from_le_bytes(kind_bytes) {
0 => TransactionKindBatchProof::SequencerCommitment,
// 1 => TransactionKindBatchProof::ForcedTransaction,
n => TransactionKindBatchProof::Unknown(NonZeroU16::new(n).expect("Is not zero")),
};
Some(Self { rollup_name, kind })
}
}

/// Type represents a typed enum for LightClient kind
#[repr(u16)]
enum TransactionKindLightClient {
/// This type of transaction includes full body (< 400kb)
Complete = 0,
/// This type of transaction includes txids of chunks (>= 400kb)
Chunked = 1,
/// This type of transaction includes chunk parts of body (>= 400kb)
ChunkedPart = 2,
Unknown(NonZeroU16),
/// Type represents a typed enum for BatchProof kind
#[repr(u16)]
pub(crate) enum TransactionKindBatchProof {
/// SequencerCommitment
SequencerCommitment = 0,
// /// ForcedTransaction
// ForcedTransaction = 1,
Unknown(NonZeroU16),
}
}

/// Type represents a typed enum for BatchProof kind
#[repr(u16)]
enum TransactionKindBatchProof {
/// SequencerCommitment
SequencerCommitment = 0,
// /// ForcedTransaction
// ForcedTransaction = 1,
Unknown(NonZeroU16),
}
use batch_proof::*;
#[cfg(feature = "native")]
use light_client::*;

pub fn calculate_double_sha256(input: &[u8]) -> [u8; 32] {
let mut hasher = Sha256::default();
Expand Down
Loading