Skip to content

Commit

Permalink
Sign list of tx of aggregates tx instead of body
Browse files Browse the repository at this point in the history
  • Loading branch information
kpp committed Aug 16, 2024
1 parent 1466f38 commit 2752c2d
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 68 deletions.
72 changes: 43 additions & 29 deletions crates/bitcoin-da/src/helpers/builders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,8 +332,7 @@ impl fmt::Debug for TxWithId {
pub fn create_zkproof_transactions(
rollup_name: &str,
body: Vec<u8>,
signature: Vec<u8>,
signer_public_key: Vec<u8>,
da_private_key: &SecretKey,
prev_utxo: Option<UTXO>,
utxos: Vec<UTXO>,
recipient: Address,
Expand All @@ -347,8 +346,7 @@ pub fn create_zkproof_transactions(
create_inscription_type_0(
rollup_name.as_bytes(),
body,
signature,
signer_public_key,
da_private_key,
prev_utxo,
utxos,
recipient,
Expand All @@ -362,8 +360,7 @@ pub fn create_zkproof_transactions(
create_inscription_type_1(
rollup_name.as_bytes(),
body,
signature,
signer_public_key,
da_private_key,
prev_utxo,
utxos,
recipient,
Expand All @@ -384,8 +381,7 @@ pub fn create_zkproof_transactions(
pub fn create_seqcommitment_transactions(
rollup_name: &str,
body: Vec<u8>,
signature: Vec<u8>,
signer_public_key: Vec<u8>,
da_private_key: &SecretKey,
prev_utxo: Option<UTXO>,
utxos: Vec<UTXO>,
recipient: Address,
Expand All @@ -398,8 +394,7 @@ pub fn create_seqcommitment_transactions(
create_batchproof_type_0(
rollup_name.as_bytes(),
body,
signature,
signer_public_key,
da_private_key,
prev_utxo,
utxos,
recipient,
Expand Down Expand Up @@ -461,8 +456,7 @@ impl TxListWithReveal for BatchProvingTxs {
pub fn create_inscription_type_0(
rollup_name: &[u8],
body: Vec<u8>,
signature: Vec<u8>,
signer_public_key: Vec<u8>,
da_private_key: &SecretKey,
prev_utxo: Option<UTXO>,
utxos: Vec<UTXO>,
recipient: Address,
Expand All @@ -483,6 +477,10 @@ pub fn create_inscription_type_0(
};
let header_bytes = header.to_bytes();

// sign the body for authentication of the sequencer
let (signature, signer_public_key) =
sign_blob_with_private_key(&body, &da_private_key).expect("Sequencer sign the body");

// start creating inscription content
let mut reveal_script_builder = script::Builder::new()
.push_x_only_key(&public_key)
Expand Down Expand Up @@ -656,8 +654,7 @@ pub fn create_inscription_type_0(
pub fn create_inscription_type_1(
rollup_name: &[u8],
body: Vec<u8>,
signature: Vec<u8>,
signer_public_key: Vec<u8>,
da_private_key: &SecretKey,
mut prev_utxo: Option<UTXO>,
mut utxos: Vec<UTXO>,
recipient: Address,
Expand Down Expand Up @@ -838,6 +835,17 @@ pub fn create_inscription_type_1(
}
}

let reveal_tx_ids: Vec<_> = reveal_chunks
.iter()
.map(|tx| tx.compute_txid().to_byte_array())
.collect();

// To sign the list of tx ids we assume they form a contigious list of bytes
let reveal_body: Vec<u8> = reveal_tx_ids.iter().copied().flatten().collect();
// sign the body for authentication of the sequencer
let (signature, signer_public_key) =
sign_blob_with_private_key(&reveal_body, &da_private_key).expect("Sequencer sign the body");

let header = TransactionHeaderLightClient {
rollup_name,
kind: TransactionKindLightClient::Chunked,
Expand All @@ -856,8 +864,8 @@ pub fn create_inscription_type_1(
PushBytesBuf::try_from(signer_public_key).expect("Cannot push sequencer public key"),
);
// push txids
for tx in &reveal_chunks {
reveal_script_builder = reveal_script_builder.push_slice(tx.compute_txid().as_byte_array());
for id in reveal_tx_ids {
reveal_script_builder = reveal_script_builder.push_slice(id);
}
// push end if
reveal_script_builder = reveal_script_builder.push_opcode(OP_ENDIF);
Expand Down Expand Up @@ -1017,8 +1025,7 @@ pub fn create_inscription_type_1(
pub fn create_batchproof_type_0(
rollup_name: &[u8],
body: Vec<u8>,
signature: Vec<u8>,
signer_public_key: Vec<u8>,
da_private_key: &SecretKey,
prev_utxo: Option<UTXO>,
utxos: Vec<UTXO>,
recipient: Address,
Expand All @@ -1043,6 +1050,10 @@ pub fn create_batchproof_type_0(
};
let header_bytes = header.to_bytes();

// sign the body for authentication of the sequencer
let (signature, signer_public_key) =
sign_blob_with_private_key(&body, &da_private_key).expect("Sequencer sign the body");

// start creating inscription content
let reveal_script_builder = script::Builder::new()
.push_x_only_key(&public_key)
Expand Down Expand Up @@ -1215,10 +1226,12 @@ mod tests {
use bitcoin::hashes::Hash;
use bitcoin::secp256k1::constants::SCHNORR_SIGNATURE_SIZE;
use bitcoin::secp256k1::schnorr::Signature;
use bitcoin::secp256k1::SecretKey;
use bitcoin::taproot::ControlBlock;
use bitcoin::{Address, Amount, ScriptBuf, TxOut, Txid};

use super::LightClientTxs;
use crate::helpers::builders::sign_blob_with_private_key;
use crate::helpers::compression::{compress_blob, decompress_blob};
use crate::helpers::parsers::{parse_transaction, ParsedLightClientTransaction};
use crate::spec::utxo::UTXO;
Expand Down Expand Up @@ -1250,11 +1263,9 @@ mod tests {
}

#[allow(clippy::type_complexity)]
fn get_mock_data() -> (&'static str, Vec<u8>, Vec<u8>, Vec<u8>, Address, Vec<UTXO>) {
fn get_mock_data() -> (&'static str, Vec<u8>, Address, Vec<UTXO>) {
let rollup_name = "test_rollup";
let body = vec![100; 1000];
let signature = vec![100; 64];
let signer_public_key = vec![100; 33];
let address =
Address::from_str("bc1pp8qru0ve43rw9xffmdd8pvveths3cx6a5t6mcr0xfn9cpxx2k24qf70xq9")
.unwrap()
Expand Down Expand Up @@ -1320,16 +1331,14 @@ mod tests {
(
rollup_name,
body,
signature,
signer_public_key,
address,
utxos,
)
}

#[test]
fn choose_utxos() {
let (_, _, _, _, _, utxos) = get_mock_data();
let (_, _, _, utxos) = get_mock_data();

let (chosen_utxos, sum, leftover_utxos) =
super::choose_utxos(None, &utxos, 105_000).unwrap();
Expand Down Expand Up @@ -1372,7 +1381,7 @@ mod tests {

#[test]
fn build_commit_transaction() {
let (_, _, _, _, address, utxos) = get_mock_data();
let (_, _, address, utxos) = get_mock_data();

let recipient =
Address::from_str("bc1p2e37kuhnsdc5zvc8zlj2hn6awv3ruavak6ayc8jvpyvus59j3mwqwdt0zc")
Expand Down Expand Up @@ -1609,7 +1618,7 @@ mod tests {

#[test]
fn build_reveal_transaction() {
let (_, _, _, _, address, utxos) = get_mock_data();
let (_, _, address, utxos) = get_mock_data();

let utxo = utxos.first().unwrap();
let script = ScriptBuf::from_hex("62a58f2674fd840b6144bea2e63ebd35c16d7fd40252a2f28b2a01a648df356343e47976d7906a0e688bf5e134b6fd21bd365c016b57b1ace85cf30bf1206e27").unwrap();
Expand Down Expand Up @@ -1686,14 +1695,19 @@ mod tests {
}
#[test]
fn create_inscription_transactions() {
let (rollup_name, body, signature, signer_public_key, address, utxos) = get_mock_data();
let (rollup_name, body, address, utxos) = get_mock_data();

let da_private_key = SecretKey::from_slice(&[0xcd; 32]).expect("32 bytes, within curve order");

// sign the body for authentication of the sequencer
let (signature, signer_public_key) =
sign_blob_with_private_key(&body, &da_private_key).expect("Sequencer sign the body");

let tx_prefix = &[0u8];
let LightClientTxs::Complete { commit, reveal } = super::create_zkproof_transactions(
rollup_name,
body.clone(),
signature.clone(),
signer_public_key.clone(),
&da_private_key,
None,
utxos.clone(),
address.clone(),
Expand Down
92 changes: 62 additions & 30 deletions crates/bitcoin-da/src/helpers/parsers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub struct ParsedComplete {

#[derive(Debug, Clone)]
pub struct ParsedAggregate {
pub txids: Vec<Txid>,
pub body: Vec<u8>,
pub signature: Vec<u8>,
pub public_key: Vec<u8>,
}
Expand All @@ -58,12 +58,17 @@ pub struct ParsedSequencerCommitment {
pub public_key: Vec<u8>,
}

impl ParsedComplete {
/// To verify the signature of the inscription and get the hash of the body
pub(crate) trait VerifyParsed {
fn public_key(&self) -> &[u8];
fn signature(&self) -> &[u8];
fn body(&self) -> &[u8];

/// Verifies the signature of the inscription and returns the hash of the body
pub fn get_sig_verified_hash(&self) -> Option<[u8; 32]> {
let public_key = secp256k1::PublicKey::from_slice(&self.public_key);
let signature = ecdsa::Signature::from_compact(&self.signature);
let hash = calculate_double_sha256(&self.body);
fn get_sig_verified_hash(&self) -> Option<[u8; 32]> {
let public_key = secp256k1::PublicKey::from_slice(self.public_key());
let signature = ecdsa::Signature::from_compact(self.signature());
let hash = calculate_double_sha256(self.body());
let message = Message::from_digest_slice(&hash).unwrap(); // cannot fail

let secp = Secp256k1::new();
Expand All @@ -81,26 +86,45 @@ impl ParsedComplete {
}
}

impl ParsedSequencerCommitment {
/// Verifies the signature of the sequencer commitment and returns the hash of the body
pub fn get_sig_verified_hash(&self) -> Option<[u8; 32]> {
let public_key = secp256k1::PublicKey::from_slice(&self.public_key);
let signature = ecdsa::Signature::from_compact(&self.signature);
let hash = calculate_double_sha256(&self.body);
let message = Message::from_digest_slice(&hash).unwrap(); // cannot fail
impl VerifyParsed for ParsedComplete {
fn public_key(&self) -> &[u8] {
&self.public_key
}
fn signature(&self) -> &[u8] {
&self.signature
}
fn body(&self) -> &[u8] {
&self.body
}
}

let secp = Secp256k1::new();
impl VerifyParsed for ParsedAggregate {
fn public_key(&self) -> &[u8] {
&self.public_key
}
fn signature(&self) -> &[u8] {
&self.signature
}
fn body(&self) -> &[u8] {
&self.body
}
}

if public_key.is_ok()
&& signature.is_ok()
&& secp
.verify_ecdsa(&message, &signature.unwrap(), &public_key.unwrap())
.is_ok()
{
Some(hash)
} else {
None
}
impl VerifyParsed for ParsedSequencerCommitment {
fn public_key(&self) -> &[u8] {
&self.public_key
}
fn signature(&self) -> &[u8] {
&self.signature
}
fn body(&self) -> &[u8] {
&self.body
}
}

impl ParsedAggregate {
pub fn txids(&self) -> Result<Vec<Txid>, bitcoin::hashes::FromSliceError> {
self.body.chunks_exact(32).into_iter().map(Txid::from_slice).collect()
}
}

Expand Down Expand Up @@ -340,15 +364,17 @@ mod light_client {
let signature = read_push_bytes(instructions)?;
let public_key = read_push_bytes(instructions)?;

let mut txids = vec![];
let mut chunks = vec![];

loop {
let instr = read_instr(instructions)?;
match instr {
PushBytes(chunk) => match Txid::from_slice(chunk.as_bytes()) {
Ok(id) => txids.push(id),
Err(_) => return Err(ParserError::UnexpectedOpcode),
},
PushBytes(chunk) => {
if chunk.len() != 32 {
return Err(ParserError::UnexpectedOpcode);
}
chunks.push(chunk)
}
Op(OP_ENDIF) => break,
Op(_) => return Err(ParserError::UnexpectedOpcode),
}
Expand All @@ -364,11 +390,17 @@ mod light_client {
return Err(ParserError::UnexpectedOpcode);
}

let body_size: usize = 32 * chunks.len();
let mut body = Vec::with_capacity(body_size);
for chunk in chunks {
body.extend_from_slice(chunk.as_bytes());
}

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

Ok(ParsedAggregate {
txids,
body,
signature,
public_key,
})
Expand Down
14 changes: 6 additions & 8 deletions crates/bitcoin-da/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use crate::helpers::builders::{
};
use crate::helpers::compression::{compress_blob, decompress_blob};
use crate::helpers::merkle_tree::BitcoinMerkleTree;
use crate::helpers::parsers::{parse_batch_proof_transaction, ParsedBatchProofTransaction};
use crate::helpers::parsers::{parse_batch_proof_transaction, ParsedBatchProofTransaction, VerifyParsed};
use crate::helpers::{calculate_double_sha256, merkle_tree};
use crate::spec::blob::BlobWithSender;
use crate::spec::block::BitcoinBlock;
Expand Down Expand Up @@ -353,18 +353,17 @@ impl BitcoinService {
.require_network(network)
.context("Invalid network for address")?;

// sign the blob for authentication of the sequencer
let (signature, public_key) =
sign_blob_with_private_key(&blob, &da_private_key).expect("Sequencer sign the blob");
// // sign the blob for authentication of the sequencer
// let (signature, public_key) =
// sign_blob_with_private_key(&blob, &da_private_key).expect("Sequencer sign the blob");

match da_data {
DaData::ZKProof(_) => {
// create inscribe transactions
let inscription_txs = create_zkproof_transactions(
&rollup_name,
blob,
signature,
public_key,
&da_private_key,
prev_utxo,
utxos,
address,
Expand Down Expand Up @@ -452,8 +451,7 @@ impl BitcoinService {
let inscription_txs = create_seqcommitment_transactions(
&rollup_name,
blob,
signature,
public_key,
&da_private_key,
prev_utxo,
utxos,
address,
Expand Down
Loading

0 comments on commit 2752c2d

Please sign in to comment.