use bitcoin::psbt::Psbt;
use bitcoin::sighash::EcdsaSighashType;
use bitcoin::{Amount, Transaction, Witness};
use ddk_dlc::secp256k1_zkp::{EcdsaAdaptorSignature, Secp256k1, SecretKey};
use ddk_messages::{
AcceptDlc, CetAdaptorSignatures, FundingSignature, FundingSignatures, OfferDlc, SignDlc,
};
use super::context::{self, context_from_messages};
use super::error::ContractError;
use super::psbt;
use super::types::{DlcInputSigningKey, Party, SignResult};
pub fn funding_signature_from_witness(witness: Witness) -> FundingSignature {
psbt::funding_signature_from_witness(witness)
}
pub fn funding_signatures_from_witnesses(witnesses: Vec<Witness>) -> FundingSignatures {
FundingSignatures {
funding_signatures: witnesses
.into_iter()
.map(psbt::funding_signature_from_witness)
.collect(),
}
}
pub fn sign_p2wpkh_funding_input(
funding_transaction: &Transaction,
input_index: usize,
prevout_value: Amount,
secret_key: &SecretKey,
) -> Result<FundingSignature, ContractError> {
let secp = Secp256k1::new();
let witness = ddk_dlc::util::get_witness_for_p2wpkh_input(
&secp,
secret_key,
funding_transaction,
input_index,
EcdsaSighashType::All,
prevout_value,
)?;
Ok(psbt::funding_signature_from_witness(witness))
}
pub fn create_cet_adaptor_signatures(
offer: &OfferDlc,
accept: &AcceptDlc,
funding_secret_key: &SecretKey,
) -> Result<Vec<EcdsaAdaptorSignature>, ContractError> {
let secp = Secp256k1::new();
let context = context_from_messages(offer, accept)?;
context::create_adaptor_signatures(
&secp,
&context,
funding_secret_key,
offer.get_total_collateral(),
)
}
pub fn verify_cet_adaptor_signatures(
offer: &OfferDlc,
accept: &AcceptDlc,
party: Party,
refund_signature: &ddk_dlc::secp256k1_zkp::ecdsa::Signature,
adaptor_signatures: &CetAdaptorSignatures,
) -> Result<(), ContractError> {
let secp = Secp256k1::new();
let context = context_from_messages(offer, accept)?;
let (funding_pubkey, error): (_, fn(String) -> ContractError) = match party {
Party::Offer => (offer.funding_pubkey, ContractError::InvalidSign),
Party::Accept => (accept.funding_pubkey, ContractError::InvalidAccept),
};
context::verify_counterparty_signatures(
&secp,
&context,
offer.get_total_collateral(),
funding_pubkey,
refund_signature,
adaptor_signatures,
error,
)
}
pub fn funding_signatures_from_psbt(
offer: &OfferDlc,
accept: &AcceptDlc,
party: Party,
psbt: &Psbt,
) -> Result<FundingSignatures, ContractError> {
psbt::ensure_matching_psbt(offer, accept, psbt)?;
psbt::extract_funding_signatures(offer, accept, party, psbt)
}
pub fn compute_contract_id(
offer: &OfferDlc,
accept: &AcceptDlc,
) -> Result<[u8; 32], ContractError> {
let context = context_from_messages(offer, accept)?;
Ok(context::contract_id_from_transactions(
&context.transactions,
&offer.temporary_contract_id,
))
}
pub fn sign_accept_with_funding_signatures(
offer: &OfferDlc,
accept: &AcceptDlc,
funding_secret_key: &SecretKey,
funding_signatures: FundingSignatures,
) -> Result<SignResult, ContractError> {
super::sign::sign_accept_internal(offer, accept, funding_secret_key, funding_signatures)
}
pub fn finalize_sign_with_funding_signatures(
offer: &OfferDlc,
accept: &AcceptDlc,
sign: &SignDlc,
funding_signatures: FundingSignatures,
) -> Result<Transaction, ContractError> {
super::finalize::finalize_sign_internal(offer, accept, sign, funding_signatures, &[])
}
pub fn finalize_sign_spliced_with_funding_signatures(
offer: &OfferDlc,
accept: &AcceptDlc,
sign: &SignDlc,
funding_signatures: FundingSignatures,
dlc_input_keys: &[DlcInputSigningKey],
) -> Result<Transaction, ContractError> {
super::finalize::finalize_sign_internal(offer, accept, sign, funding_signatures, dlc_input_keys)
}