Skip to content

Commit

Permalink
Save bitvm setup (#438)
Browse files Browse the repository at this point in the history
* Winternitz derivation path improvment

* Operator winternitz generation with correct intermediate variables

* Precalculate length of all intermediate variables in lazy static

* Minor Fix

* Seperate taproot builder for further use

* WIP precalculating bitvm setups

* Fmt

* Save setupts to the db

* Use stored BitVM setups when signing

* put segments within a block

* Add disprove scripts

* resolve comments

* fix winternitz_derivation_path_to_vec test

* Fix prevouts loop on assert end tx

* Fix test

* Fix tests, reduce setup counts

* Fix last_mini_assert_txid calculation

* Fix tests and atacan's comments

* Remove unwrap

* Rename taproot builder

---------

Co-authored-by: Mehmet Efe Akça <[email protected]>
Co-authored-by: atacann <[email protected]>
  • Loading branch information
3 people authored Jan 21, 2025
1 parent 824d538 commit 803a96c
Show file tree
Hide file tree
Showing 13 changed files with 412 additions and 148 deletions.
37 changes: 16 additions & 21 deletions core/src/actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub enum TxType {

/// Derivation path specification for Winternitz one time public key generation.
#[derive(Debug, Clone, Copy)]
pub struct WinternitzDerivationPath {
pub struct WinternitzDerivationPath<'a> {
pub message_length: u32,
pub log_d: u32,
pub tx_type: TxType,
Expand All @@ -35,9 +35,9 @@ pub struct WinternitzDerivationPath {
pub watchtower_idx: Option<u32>,
pub time_tx_idx: Option<u32>,
pub kickoff_idx: Option<u32>,
pub intermediate_step_idx: Option<u32>,
pub intermediate_step_name: Option<&'a str>,
}
impl WinternitzDerivationPath {
impl<'a> WinternitzDerivationPath<'a> {
fn to_vec(self) -> Vec<u8> {
let index = match self.index {
None => 0,
Expand All @@ -59,9 +59,9 @@ impl WinternitzDerivationPath {
None => 0,
Some(i) => i + 1,
};
let intermediate_step_idx = match self.intermediate_step_idx {
None => 0,
Some(i) => i + 1,
let intermediate_step_name = match self.intermediate_step_name {
None => vec![],
Some(name) => name.as_bytes().to_vec(),
};

[
Expand All @@ -72,14 +72,14 @@ impl WinternitzDerivationPath {
watchtower_idx.to_be_bytes(),
time_tx_idx.to_be_bytes(),
kickoff_idx.to_be_bytes(),
intermediate_step_idx.to_be_bytes(),
]
.concat(),
intermediate_step_name,
]
.concat()
}
}
impl Default for WinternitzDerivationPath {
impl Default for WinternitzDerivationPath<'_> {
fn default() -> Self {
Self {
message_length: Default::default(),
Expand All @@ -90,7 +90,7 @@ impl Default for WinternitzDerivationPath {
watchtower_idx: Default::default(),
time_tx_idx: Default::default(),
kickoff_idx: Default::default(),
intermediate_step_idx: Default::default(),
intermediate_step_name: Default::default(),
}
}
}
Expand Down Expand Up @@ -314,7 +314,7 @@ impl Actor {
/// Returns derivied Winternitz secret key from given path.
fn get_derived_winternitz_sk(
&self,
path: WinternitzDerivationPath,
path: WinternitzDerivationPath<'_>,
) -> Result<winternitz::SecretKey, BridgeError> {
let wsk = self
.winternitz_secret_key
Expand All @@ -325,7 +325,7 @@ impl Actor {
/// Generates a Winternitz public key for the given path.
pub fn derive_winternitz_pk(
&self,
path: WinternitzDerivationPath,
path: WinternitzDerivationPath<'_>,
) -> Result<winternitz::PublicKey, BridgeError> {
let winternitz_params = winternitz::Parameters::new(path.message_length, path.log_d);

Expand All @@ -338,7 +338,7 @@ impl Actor {
/// Signs given data with Winternitz signature.
pub fn sign_winternitz_signature(
&self,
path: WinternitzDerivationPath,
path: WinternitzDerivationPath<'_>,
data: Vec<u8>,
) -> Result<Witness, BridgeError> {
let winternitz = Winternitz::<BinarysearchVerifier, StraightforwardConverter>::new();
Expand Down Expand Up @@ -517,7 +517,6 @@ mod tests {
vec![0; 4],
vec![0; 4],
vec![0; 4],
vec![0; 4]
]
.concat()
);
Expand All @@ -532,7 +531,6 @@ mod tests {
vec![0; 4],
vec![0; 4],
vec![0; 4],
vec![0; 4]
]
.concat()
);
Expand All @@ -547,7 +545,6 @@ mod tests {
vec![0; 4],
vec![0; 4],
vec![0; 4],
vec![0; 4]
]
.concat()
);
Expand All @@ -562,7 +559,6 @@ mod tests {
3u32.to_be_bytes().to_vec(),
vec![0; 4],
vec![0; 4],
vec![0; 4]
]
.concat()
);
Expand All @@ -577,7 +573,6 @@ mod tests {
3u32.to_be_bytes().to_vec(),
4u32.to_be_bytes().to_vec(),
vec![0; 4],
vec![0; 4]
]
.concat()
);
Expand All @@ -592,12 +587,11 @@ mod tests {
3u32.to_be_bytes().to_vec(),
4u32.to_be_bytes().to_vec(),
5u32.to_be_bytes().to_vec(),
vec![0; 4]
]
.concat()
);

params.intermediate_step_idx = Some(5);
params.intermediate_step_name = Some("step5");
assert_eq!(
params.to_vec(),
[
Expand All @@ -607,7 +601,7 @@ mod tests {
3u32.to_be_bytes().to_vec(),
4u32.to_be_bytes().to_vec(),
5u32.to_be_bytes().to_vec(),
6u32.to_be_bytes().to_vec()
"step5".as_bytes().to_vec()
]
.concat()
);
Expand Down Expand Up @@ -648,7 +642,8 @@ mod tests {

let params = WinternitzDerivationPath::default();
let expected_pk = vec![[
43, 217, 118, 91, 99, 62, 82, 3, 214, 248, 73, 185, 20, 141, 201, 23, 110, 104, 74, 42,
47, 247, 126, 209, 93, 128, 238, 60, 31, 80, 198, 136, 26, 126, 131, 194, 209, 85, 180,
145,
]];
assert_eq!(actor.derive_winternitz_pk(params).unwrap(), expected_pk);
}
Expand Down
36 changes: 20 additions & 16 deletions core/src/builder/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,32 @@ use crate::builder;
use crate::utils::SECP;
use crate::{utils, EVMAddress};
use bitcoin::address::NetworkUnchecked;
use bitcoin::hashes::Hash;
use bitcoin::Amount;
use bitcoin::{
secp256k1::XOnlyPublicKey,
taproot::{TaprootBuilder, TaprootSpendInfo},
Address, ScriptBuf,
};

pub fn taproot_builder_with_scripts(scripts: &[ScriptBuf]) -> TaprootBuilder {
let n = scripts.len();
if n == 0 {
TaprootBuilder::new()
} else if n > 1 {
let m: u8 = ((n - 1).ilog2() + 1) as u8; // m = ceil(log(n))
let k = 2_usize.pow(m.into()) - n;
(0..n).fold(TaprootBuilder::new(), |acc, i| {
acc.add_leaf(m - ((i >= n - k) as u8), scripts[i].clone())
.unwrap()
})
} else {
TaprootBuilder::new()
.add_leaf(0, scripts[0].clone())
.unwrap()
}
}

/// Creates a taproot address with either key path spend or script spend path
/// addresses. This depends on given arguments.
///
Expand All @@ -36,22 +55,7 @@ pub fn create_taproot_address(
internal_key: Option<XOnlyPublicKey>,
network: bitcoin::Network,
) -> (Address, TaprootSpendInfo) {
let n = scripts.len();

let taproot_builder = if n == 0 {
TaprootBuilder::new()
} else if n > 1 {
let m: u8 = ((n - 1).ilog2() + 1) as u8; // m = ceil(log(n))
let k = 2_usize.pow(m.into()) - n;
(0..n).fold(TaprootBuilder::new(), |acc, i| {
acc.add_leaf(m - ((i >= n - k) as u8), scripts[i].clone())
.unwrap()
})
} else {
TaprootBuilder::new()
.add_leaf(0, scripts[0].clone())
.unwrap()
};
let taproot_builder = taproot_builder_with_scripts(scripts);

let tree_info = match internal_key {
Some(xonly_pk) => taproot_builder.finalize(&SECP, xonly_pk).unwrap(),
Expand Down
14 changes: 7 additions & 7 deletions core/src/builder/sighash.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::builder::transaction::TxHandler;
use crate::config::BridgeConfig;
use crate::constants::NUM_INTERMEDIATE_STEPS;
use crate::constants::{NUM_INTERMEDIATE_STEPS, PARALLEL_ASSERT_TX_CHAIN_SIZE};
use crate::errors::BridgeError;
use crate::{builder, database::Database, EVMAddress};
use async_stream::try_stream;
Expand Down Expand Up @@ -259,25 +259,25 @@ pub fn create_nofn_sighash_stream(
)?;
}

let intermediate_wots =
vec![vec![vec![[0u8; 20]; 48]; NUM_INTERMEDIATE_STEPS]; config.num_time_txs]; // TODO: Fetch from db
let (assert_tx_addrs, root_hash, public_input_wots) = db.get_bitvm_setup(None, operator_idx as i32, time_tx_idx as i32, kickoff_idx as i32).await?.ok_or(BridgeError::BitvmSetupNotFound(operator_idx as i32, time_tx_idx as i32, kickoff_idx as i32))?;
let assert_begin_txhandler = builder::transaction::create_assert_begin_txhandler(
&kickoff_txhandler,
nofn_xonly_pk,
intermediate_wots[time_tx_idx].clone(),
&assert_tx_addrs,
network,
);

let mut assert_end_txhandler = builder::transaction::create_assert_end_txhandler(
&kickoff_txhandler,
&assert_begin_txhandler,
&assert_tx_addrs,
&root_hash,
nofn_xonly_pk,
*operator_xonly_pk,
public_input_wots,
network,
);
yield convert_tx_to_pubkey_spend(
&mut assert_end_txhandler,
NUM_INTERMEDIATE_STEPS,
PARALLEL_ASSERT_TX_CHAIN_SIZE,
None,
)?;

Expand Down
Loading

0 comments on commit 803a96c

Please sign in to comment.