Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
e593f21
chore: use Descriptor instead of XOnlyPublicKey
sistemd Nov 26, 2025
11a61b5
chore: rename reimbursement_key to operator_descriptor
sistemd Nov 26, 2025
0b79b19
chore: remove redundant doc comment
sistemd Nov 26, 2025
26699a5
refactor: use generate_locking_script where possible
sistemd Nov 26, 2025
c8f3032
test: cover the error case as well
sistemd Nov 26, 2025
bdba1a8
chore: use XOnlyPublicKey on stake tx data
sistemd Nov 26, 2025
3f2e909
chore: use XOnlyPublicKey in ConnectorStake
sistemd Nov 26, 2025
b19eab6
chore: remove unneeded regression and ignore regressions
sistemd Nov 27, 2025
2978fa9
refactor: generate_address can actually be removed
sistemd Nov 27, 2025
c6c949b
chore: switch back to operator_descriptor in RpcDisproveData
sistemd Nov 27, 2025
105a45f
chore: error handling
sistemd Nov 27, 2025
ed0d874
refactor: generate_locking_script
sistemd Nov 28, 2025
2f48fa8
refactor: avoid unnecessary error handling
sistemd Nov 28, 2025
db4c684
chore: fixme comment
sistemd Nov 28, 2025
cc1aab0
fix: doc comment
sistemd Dec 1, 2025
dc21c40
fix: doc comments for functions which no longer return errors
sistemd Dec 1, 2025
e6933c0
fix: don't return unnecessary errors
sistemd Dec 1, 2025
0a2d8c4
chore: fmt
sistemd Dec 1, 2025
95d7397
chore: StakeChainErr variant instead of unexpected
sistemd Dec 2, 2025
e4fb934
chore: very small rename
sistemd Dec 2, 2025
9441fc1
chore: no Clone for StakeChainErr
sistemd Dec 2, 2025
3d9683b
fix: remove needless conversion
sistemd Dec 2, 2025
dfa34e9
fix: remove needless error handling
sistemd Dec 2, 2025
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -312,3 +312,6 @@ certs
*.hex

.obsidian

# local regressions
**/proptest-regressions/*
2 changes: 2 additions & 0 deletions Cargo.lock

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

17 changes: 8 additions & 9 deletions bin/alpen-bridge/src/rpc_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -773,25 +773,25 @@ impl StrataBridgeDaApiServer for BridgeRpc {
.get(&claim_txid)
.map(|sigs| sigs.challenge);

let reimbursement_key = contract
let reimbursement_descriptor = contract
.0
.state
.state
.graph_input(claim_txid)
.map(|input| input.operator_pubkey);
.map(|input| input.operator_descriptor.clone());

match (challenge_sig, reimbursement_key) {
(Some(challenge_sig), Some(reimbursement_key)) => {
Some((challenge_sig, reimbursement_key))
match (challenge_sig, reimbursement_descriptor) {
(Some(challenge_sig), Some(reimbursement_descriptor)) => {
Some((challenge_sig, reimbursement_descriptor))
}
_ => None, // No challenge transaction available for this claim
}
})
.map(|(challenge_sig, reimbursement_key)| {
.map(|(challenge_sig, operator_descriptor)| {
let challenge_input = ChallengeTxInput {
claim_outpoint: OutPoint::new(claim_txid, CHALLENGE_VOUT),
challenge_amt: self.params.tx_graph.challenge_cost,
operator_pubkey: reimbursement_key,
operator_descriptor,
network: self.params.network,
};

Expand All @@ -814,7 +814,6 @@ impl StrataBridgeDaApiServer for BridgeRpc {
ChallengeTx::new(challenge_input, challenge_connector)
.finalize_presigned(ConnectorC1Path::Challenge(challenge_sig))
});

Ok(challenge_tx)
}

Expand Down Expand Up @@ -854,7 +853,7 @@ impl StrataBridgeDaApiServer for BridgeRpc {
deposit_txid: contract.0.deposit_txid,
stake_outpoint: OutPoint::new(graph_summary.stake_txid, STAKE_VOUT),
stake_hash: graph_input.stake_hash,
operator_pubkey: graph_input.operator_pubkey,
operator_descriptor: graph_input.operator_descriptor.clone(),
wots_public_keys: graph_input.wots_public_keys.clone(),
n_of_n_sig,
})
Expand Down
7 changes: 5 additions & 2 deletions bin/dev-cli/src/handlers/disprove.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use strata_bridge_connectors::{
};
use strata_bridge_primitives::{
constants::NUM_ASSERT_DATA_TX,
types::descriptor_to_x_only_pubkey,
wots::{self, Groth16Sigs, Wots256Sig},
};
use strata_bridge_proof_protocol::BridgeProofPublicOutput;
Expand Down Expand Up @@ -100,7 +101,7 @@ pub(crate) async fn handle_disprove(args: cli::DisproveArgs) -> anyhow::Result<(
post_assert_txid,
deposit_txid,
stake_outpoint,
operator_pubkey,
operator_descriptor,
stake_hash,
wots_public_keys,
n_of_n_sig,
Expand Down Expand Up @@ -141,7 +142,9 @@ pub(crate) async fn handle_disprove(args: cli::DisproveArgs) -> anyhow::Result<(

let connector_stake = ConnectorStake::new(
agg_pubkey,
operator_pubkey,
descriptor_to_x_only_pubkey(&operator_descriptor).map_err(|e| {
anyhow!("could not extract x-only pubkey from operator descriptor: {e}")
})?,
stake_hash,
params.stake_chain_delta,
params.network,
Expand Down
1 change: 1 addition & 0 deletions crates/connectors/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ strata-bridge-proof-snark.workspace = true
ark-serialize.workspace = true
bincode.workspace = true
bitcoin.workspace = true
bitcoin-bosd.workspace = true
bitcoin-script.workspace = true
bitvm.workspace = true
secp256k1.workspace = true
Expand Down
40 changes: 15 additions & 25 deletions crates/connectors/src/connector_cpfp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,52 +2,42 @@
//!
//! Reference: <https://bitcoinops.org/en/topics/cpfp/>

use bitcoin::{key::TapTweak, psbt::Input, Address, Network, ScriptBuf};
use secp256k1::{schnorr, XOnlyPublicKey};
use bitcoin::{psbt::Input, Network, ScriptBuf};
use bitcoin_bosd::Descriptor;
use secp256k1::schnorr;
use strata_bridge_primitives::scripts::taproot::finalize_input;

/// Connector for adding outputs to a transaction for CPFP.
///
/// It creates a taproot locking script with a public key that is assumed to be tweaked and expects
/// a schnorr signature to finalize the input.
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone)]
pub struct ConnectorCpfp {
/// The bitcoin network for which to generate output addresses.
network: Network,

/// The public key used to create the child transaction in CPFP.
public_key: XOnlyPublicKey,
/// The locking script for the child transaction in CPFP.
locking_script: ScriptBuf,
}

impl ConnectorCpfp {
/// Constructs a new CPFP connector.
pub const fn new(public_key: XOnlyPublicKey, network: Network) -> Self {
pub fn new(descriptor: Descriptor, network: Network) -> Self {
let locking_script = descriptor.to_script();
Self {
network,
public_key,
locking_script,
}
}

/// Returns the public key used to create the child transaction in CPFP.
pub const fn public_key(&self) -> XOnlyPublicKey {
self.public_key
}

/// Returns the bitcoin network for which to generate output addresses.
pub const fn network(&self) -> Network {
self.network
}

/// Generates a taproot address for the child transaction.
///
/// This taproot address uses a key-spend path with the public key of the connector.
pub fn generate_taproot_address(&self) -> bitcoin::Address {
Address::p2tr_tweaked(self.public_key.dangerous_assume_tweaked(), self.network)
}

/// Generates the locking script for the child transaction.
pub fn generate_locking_script(&self) -> ScriptBuf {
self.generate_taproot_address().script_pubkey()
pub fn locking_script(&self) -> ScriptBuf {
self.locking_script.clone()
}

/// Finalizes the connector using a schnorr signature.
Expand Down Expand Up @@ -104,7 +94,7 @@ mod tests {

let keypair = generate_keypair();
let xonly_pubkey = keypair.x_only_public_key().0;
let connector = ConnectorCpfp::new(xonly_pubkey, network);
let connector = ConnectorCpfp::new(xonly_pubkey.into(), network);

let output_address =
Address::p2tr_tweaked(xonly_pubkey.dangerous_assume_tweaked(), network);
Expand All @@ -125,7 +115,7 @@ mod tests {
let starting_tx_ins = create_tx_ins([utxo]);
let starting_tx_outs = create_tx_outs([
(
connector.generate_taproot_address().script_pubkey(),
connector.locking_script(),
Amount::from_sat(0), // set amount later
),
(wallet_addr.script_pubkey(), unspent.amount),
Expand Down Expand Up @@ -171,7 +161,7 @@ mod tests {
let parent_tx_outs = vec![TxOut {
value: signed_starting_tx.output[input_utxo_vout].value, /* same output as input (0
* fees) */
script_pubkey: connector.generate_taproot_address().script_pubkey(),
script_pubkey: connector.locking_script(),
}];
let mut parent_tx = create_tx(parent_tx_ins, parent_tx_outs);
parent_tx.version = Version(3);
Expand Down Expand Up @@ -213,7 +203,7 @@ mod tests {

let funding_tx_ins = create_tx_ins([utxo]);
let funding_tx_outs = create_tx_outs([
(connector.generate_taproot_address().script_pubkey(), FEES),
(connector.locking_script(), FEES),
(wallet_addr.script_pubkey(), unspent.amount - FEES - FEES),
]);
let funding_tx = create_tx(funding_tx_ins, funding_tx_outs);
Expand Down
4 changes: 2 additions & 2 deletions crates/connectors/src/connector_s.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ use crate::stake_path::StakeSpendPath;
/// preimage to the [`ConnectorStake`]. It is required that the preimage be securely derived and
/// never reused under any circumstances
// TODO: This should replace the `ConnectorS` struct above.
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone)]
pub struct ConnectorStake {
/// The N-of-N aggregated public key for the operator set.
n_of_n_agg_pubkey: XOnlyPublicKey,

/// The operator's public key.
/// The operator's pubkey.
operator_pubkey: XOnlyPublicKey,

/// The hash of the `k`th stake preimage.
Expand Down
Loading
Loading