Skip to content

Commit

Permalink
builder: Add initial crate.
Browse files Browse the repository at this point in the history
  • Loading branch information
ceyhunsen committed Oct 1, 2024
1 parent c94d9da commit c61c806
Show file tree
Hide file tree
Showing 16 changed files with 276 additions and 257 deletions.
4 changes: 2 additions & 2 deletions core/src/actor.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::builder::transaction::TxHandler;
use crate::errors::BridgeError;
use crate::transaction_builder::TxHandler;
use crate::utils;
use bitcoin::sighash::SighashCache;
use bitcoin::taproot::LeafVersion;
Expand Down Expand Up @@ -217,7 +217,7 @@ impl Actor {
#[cfg(test)]
mod tests {
use super::Actor;
use crate::transaction_builder::TxHandler;
use crate::builder::transaction::TxHandler;
use bitcoin::{
absolute::Height, transaction::Version, Amount, Network, OutPoint, Transaction, TxIn, TxOut,
};
Expand Down
14 changes: 7 additions & 7 deletions core/src/aggregator.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use crate::{
actor::Actor,
builder,
config::BridgeConfig,
errors::BridgeError,
musig2::{
aggregate_nonces, aggregate_partial_signatures, AggregateFromPublicKeys, MuSigAggNonce,
MuSigPartialSignature, MuSigPubNonce,
},
traits::rpc::AggregatorServer,
transaction_builder,
utils::handle_taproot_witness_new,
ByteArray32, ByteArray66, EVMAddress, UTXO,
};
Expand Down Expand Up @@ -56,7 +56,7 @@ impl Aggregator {
agg_nonce: &MuSigAggNonce,
partial_sigs: Vec<MuSigPartialSignature>,
) -> Result<[u8; 64], BridgeError> {
let mut tx = transaction_builder::create_slash_or_take_tx(
let mut tx = builder::transaction::create_slash_or_take_tx(
deposit_outpoint,
kickoff_utxo,
operator_xonly_pk,
Expand Down Expand Up @@ -102,7 +102,7 @@ impl Aggregator {
agg_nonce: &MuSigAggNonce,
partial_sigs: Vec<MuSigPartialSignature>,
) -> Result<[u8; 64], BridgeError> {
let move_tx = transaction_builder::create_move_tx(
let move_tx = builder::transaction::create_move_tx(
deposit_outpoint,
self.nofn_xonly_pk,
self.config.bridge_amount_sats,
Expand All @@ -112,7 +112,7 @@ impl Aggregator {
txid: move_tx.compute_txid(),
vout: 0,
};
let slash_or_take_tx_handler = transaction_builder::create_slash_or_take_tx(
let slash_or_take_tx_handler = builder::transaction::create_slash_or_take_tx(
deposit_outpoint,
kickoff_utxo,
*operator_xonly_pk,
Expand All @@ -135,7 +135,7 @@ impl Aggregator {
// serde_json::to_string(&slash_or_take_utxo)?
// );

let mut tx_handler = transaction_builder::create_operator_takes_tx(
let mut tx_handler = builder::transaction::create_operator_takes_tx(
bridge_fund_outpoint,
slash_or_take_utxo,
*operator_xonly_pk,
Expand Down Expand Up @@ -175,7 +175,7 @@ impl Aggregator {
agg_nonce: &MuSigAggNonce,
partial_sigs: Vec<MuSigPartialSignature>,
) -> Result<[u8; 64], BridgeError> {
let mut tx = transaction_builder::create_move_tx_handler(
let mut tx = builder::transaction::create_move_tx_handler(
deposit_outpoint,
evm_address,
recovery_taproot_address,
Expand Down Expand Up @@ -300,7 +300,7 @@ impl Aggregator {

let move_tx_sig = secp256k1::schnorr::Signature::from_slice(&agg_move_tx_final_sig)?;

let mut move_tx_handler = transaction_builder::create_move_tx_handler(
let mut move_tx_handler = builder::transaction::create_move_tx_handler(
deposit_outpoint,
evm_address,
&recovery_taproot_address,
Expand Down
152 changes: 152 additions & 0 deletions core/src/builder/address.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
use crate::builder;
use crate::{utils, EVMAddress};
use bitcoin::address::NetworkUnchecked;
use bitcoin::{
taproot::{TaprootBuilder, TaprootSpendInfo},
Address, ScriptBuf,
};
use secp256k1::XOnlyPublicKey;

/// Creates a taproot address with either key path spend or script spend path
/// addresses. This depends on given arguments.
///
/// # Arguments
///
/// - `scripts`: If empty, script will be key path spend
/// - `internal_key`: If not given, will be defaulted to an unspendable x-only public key
/// - `network`: Bitcoin network
///
/// # Returns
///
/// - [`Address`]: Generated taproot address
/// - [`TaprootSpendInfo`]: Taproot spending information
///
/// # Panics
///
/// Will panic if some of the operations have invalid paramaters.
pub fn create_taproot_address(
scripts: &[ScriptBuf],
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 tree_info = match internal_key {
Some(xonly_pk) => taproot_builder.finalize(&utils::SECP, xonly_pk).unwrap(),
None => taproot_builder
.finalize(&utils::SECP, *utils::UNSPENDABLE_XONLY_PUBKEY)
.unwrap(),
};

let taproot_address = match internal_key {
Some(xonly_pk) => Address::p2tr(&utils::SECP, xonly_pk, tree_info.merkle_root(), network),
None => Address::p2tr(
&utils::SECP,
*utils::UNSPENDABLE_XONLY_PUBKEY,
tree_info.merkle_root(),
network,
),
};

(taproot_address, tree_info)
}

/// Generates a deposit address for the user. Funds can be spend by N-of-N or
/// user can take after specified time.
///
/// # Parameters
///
/// - `nofn_xonly_pk`: N-of-N x-only public key of the depositor
/// - `recovery_taproot_address`: User's x-only public key that can be used to
/// take funds after some time
/// - `user_evm_address`: User's EVM address.
/// - `amount`: Amount to deposit (in sats)
/// - `network`: Bitcoin network to work on
/// - `user_takes_after`: User can take the funds back, after this amounts of
/// blocks have passed
///
/// # Returns
///
/// - [`Address`]: Deposit taproot Bitcoin address
/// - [`TaprootSpendInfo`]: Deposit address's taproot spending information
///
/// # Panics
///
/// Panics if given parameters are malformed.
pub fn generate_deposit_address(
nofn_xonly_pk: XOnlyPublicKey,
recovery_taproot_address: &Address<NetworkUnchecked>,
user_evm_address: EVMAddress,
amount: u64,
network: bitcoin::Network,
user_takes_after: u32,
) -> (Address, TaprootSpendInfo) {
let deposit_script =
builder::script::create_deposit_script(nofn_xonly_pk, user_evm_address, amount);

let recovery_script_pubkey = recovery_taproot_address
.clone()
.assume_checked()
.script_pubkey();
let recovery_extracted_xonly_pk =
XOnlyPublicKey::from_slice(&recovery_script_pubkey.as_bytes()[2..34]).unwrap();

let script_timelock = builder::script::generate_relative_timelock_script(
recovery_extracted_xonly_pk,
user_takes_after,
);

create_taproot_address(&[deposit_script, script_timelock], None, network)
}

/// Shorthand function for creating a MuSig2 taproot address: No scripts and
/// `nofn_xonly_pk` as the internal key.
///
/// # Returns
///
/// See [`create_taproot_address`].
///
/// - [`Address`]: MuSig2 taproot Bitcoin address
/// - [`TaprootSpendInfo`]: MuSig2 address's taproot spending information
pub fn create_musig2_address(
nofn_xonly_pk: XOnlyPublicKey,
network: bitcoin::Network,
) -> (Address, TaprootSpendInfo) {
create_taproot_address(&[], Some(nofn_xonly_pk), network)
}

/// Creates a kickoff taproot address with multisig script.
///
/// # Returns
///
/// See [`create_taproot_address`].
///
/// - [`Address`]: Kickoff taproot Bitcoin address
/// - [`TaprootSpendInfo`]: Kickoff address's taproot spending information
pub fn create_kickoff_address(
nofn_xonly_pk: XOnlyPublicKey,
operator_xonly_pk: XOnlyPublicKey,
network: bitcoin::Network,
) -> (Address, TaprootSpendInfo) {
let musig2_and_operator_script = builder::script::create_musig2_and_operator_multisig_script(
nofn_xonly_pk,
operator_xonly_pk,
);

create_taproot_address(&[musig2_and_operator_script], None, network)
}
3 changes: 3 additions & 0 deletions core/src/builder/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod address;
pub mod script;
pub mod transaction;
File renamed without changes.
Loading

0 comments on commit c61c806

Please sign in to comment.