move function from wallet to escrow_psbt.rs

This commit is contained in:
fbock
2024-08-05 13:33:56 +02:00
parent aba9dca686
commit b9aa271ab0
2 changed files with 93 additions and 99 deletions

View File

@ -119,10 +119,96 @@ pub fn build_escrow_transaction_output_descriptor(
}
// pub fn assemble_escrow_psbts(
// coordinator: &Coordinator,
// escrow_data: &EscrowPsbtConstructionData,
// coordinator_pk: &XOnlyPublicKey,
// ) -> Result<()> {
// panic!("Implement wallet.build_escrow_psbt()");
// Ok(())
// }
impl<D: bdk::database::BatchDatabase> CoordinatorWallet<D> {
pub async fn create_escrow_psbt(
&self,
db: &Arc<CoordinatorDB>,
taker_psbt_request: &OfferPsbtRequest,
) -> Result<EscrowPsbt> {
let trade_id = &taker_psbt_request.offer.offer_id_hex.clone();
let maker_psbt_input_data = db.fetch_maker_escrow_psbt_data(trade_id).await?;
let taker_psbt_input_data = EscrowPsbtConstructionData {
taproot_xonly_pubkey_hex: taker_psbt_request.trade_data.taproot_pubkey_hex.clone(),
escrow_input_utxos: csv_hex_to_bdk_input(
&taker_psbt_request.trade_data.bdk_psbt_inputs_hex_csv,
)?,
change_address: Address::from_str(
&taker_psbt_request.trade_data.client_change_address,
)?
.assume_checked(),
musig_pubkey_compressed_hex: taker_psbt_request.trade_data.musig_pubkey_hex.clone(),
};
let coordinator_escrow_pk = self.get_coordinator_taproot_pk().await?;
let escrow_output_descriptor = build_escrow_transaction_output_descriptor(
&maker_psbt_input_data,
&taker_psbt_input_data,
&coordinator_escrow_pk,
)?;
let escrow_coordinator_fee_address =
Address::from_str(&self.get_new_address().await?)?.assume_checked();
let (escrow_amount_maker_sat, escrow_amount_taker_sat, escrow_fee_sat_per_participant) = db
.get_escrow_tx_amounts(trade_id, self.coordinator_feerate)
.await?;
let (escrow_psbt, details) = {
// maybe we can generate a address/taproot pk directly from the descriptor without a new wallet?
let temp_wallet = Wallet::new(
&escrow_output_descriptor,
None,
bitcoin::Network::Regtest,
MemoryDatabase::new(),
)?;
let escrow_address = temp_wallet
.get_address(bdk::wallet::AddressIndex::New)?
.address;
// using absolute fee for now, in production we should come up with a way to determine the tx weight
// upfront and substract the fee from the change outputs
let tx_fee_abs = 10000;
let change_amount_maker = maker_psbt_input_data.input_sum()?
- (escrow_amount_maker_sat + escrow_fee_sat_per_participant + tx_fee_abs / 2);
let change_amount_taker = taker_psbt_input_data.input_sum()?
- (escrow_amount_taker_sat + escrow_fee_sat_per_participant + tx_fee_abs / 2);
let amount_escrow = escrow_amount_maker_sat + escrow_amount_taker_sat;
let mut builder = temp_wallet.build_tx();
builder
.manually_selected_only()
.add_recipient(escrow_address.script_pubkey(), amount_escrow)
.add_recipient(
escrow_coordinator_fee_address.script_pubkey(),
escrow_fee_sat_per_participant * 2,
)
.add_recipient(
maker_psbt_input_data.change_address.script_pubkey(),
change_amount_maker,
)
.add_recipient(
taker_psbt_input_data.change_address.script_pubkey(),
change_amount_taker,
)
.fee_absolute(tx_fee_abs);
for input in maker_psbt_input_data.escrow_input_utxos.iter() {
// satisfaction weight 66 bytes for schnorr sig + opcode + sighash for keyspend. This is a hack?
builder.add_foreign_utxo(input.utxo, input.psbt_input.clone(), 264)?;
}
for input in taker_psbt_input_data.escrow_input_utxos.iter() {
builder.add_foreign_utxo(input.utxo, input.psbt_input.clone(), 264)?;
}
builder.finish()?
};
Ok(EscrowPsbt {
escrow_psbt_hex: escrow_psbt.to_string(),
escrow_output_descriptor,
coordinator_xonly_escrow_pk: coordinator_escrow_pk.to_string(),
escrow_amount_maker_sat,
escrow_amount_taker_sat,
escrow_fee_sat_per_participant,
})
}
}

View File

@ -244,98 +244,6 @@ impl<D: bdk::database::BatchDatabase> CoordinatorWallet<D> {
Ok(())
}
pub async fn create_escrow_psbt(
&self,
db: &Arc<CoordinatorDB>,
taker_psbt_request: &OfferPsbtRequest,
) -> Result<EscrowPsbt> {
let trade_id = &taker_psbt_request.offer.offer_id_hex.clone();
let maker_psbt_input_data = db.fetch_maker_escrow_psbt_data(trade_id).await?;
let taker_psbt_input_data = EscrowPsbtConstructionData {
taproot_xonly_pubkey_hex: taker_psbt_request.trade_data.taproot_pubkey_hex.clone(),
escrow_input_utxos: csv_hex_to_bdk_input(
&taker_psbt_request.trade_data.bdk_psbt_inputs_hex_csv,
)?,
change_address: Address::from_str(
&taker_psbt_request.trade_data.client_change_address,
)?
.assume_checked(),
musig_pubkey_compressed_hex: taker_psbt_request.trade_data.musig_pubkey_hex.clone(),
};
let coordinator_escrow_pk = self.get_coordinator_taproot_pk().await?;
let escrow_output_descriptor = build_escrow_transaction_output_descriptor(
&maker_psbt_input_data,
&taker_psbt_input_data,
&coordinator_escrow_pk,
)?;
let escrow_coordinator_fee_address =
Address::from_str(&self.get_new_address().await?)?.assume_checked();
let (escrow_amount_maker_sat, escrow_amount_taker_sat, escrow_fee_sat_per_participant) = db
.get_escrow_tx_amounts(trade_id, self.coordinator_feerate)
.await?;
let (escrow_psbt, details) = {
// maybe we can generate a address/taproot pk directly from the descriptor without a new wallet?
let temp_wallet = Wallet::new(
&escrow_output_descriptor,
None,
bitcoin::Network::Regtest,
MemoryDatabase::new(),
)?;
let escrow_address = temp_wallet
.get_address(bdk::wallet::AddressIndex::New)?
.address;
// using absolute fee for now, in production we should come up with a way to determine the tx weight
// upfront and substract the fee from the change outputs
let tx_fee_abs = 10000;
let change_amount_maker = maker_psbt_input_data.input_sum()?
- (escrow_amount_maker_sat + escrow_fee_sat_per_participant + tx_fee_abs / 2);
let change_amount_taker = taker_psbt_input_data.input_sum()?
- (escrow_amount_taker_sat + escrow_fee_sat_per_participant + tx_fee_abs / 2);
let amount_escrow = escrow_amount_maker_sat + escrow_amount_taker_sat;
let mut builder = temp_wallet.build_tx();
builder
.manually_selected_only()
.add_recipient(escrow_address.script_pubkey(), amount_escrow)
.add_recipient(
escrow_coordinator_fee_address.script_pubkey(),
escrow_fee_sat_per_participant * 2,
)
.add_recipient(
maker_psbt_input_data.change_address.script_pubkey(),
change_amount_maker,
)
.add_recipient(
taker_psbt_input_data.change_address.script_pubkey(),
change_amount_taker,
)
.fee_absolute(tx_fee_abs);
for input in maker_psbt_input_data.escrow_input_utxos.iter() {
// satisfaction weight 66 bytes for schnorr sig + opcode + sighash for keyspend. This is a hack?
builder.add_foreign_utxo(input.utxo, input.psbt_input.clone(), 264)?;
}
for input in taker_psbt_input_data.escrow_input_utxos.iter() {
builder.add_foreign_utxo(input.utxo, input.psbt_input.clone(), 264)?;
}
builder.finish()?
};
Ok(EscrowPsbt {
escrow_psbt_hex: escrow_psbt.to_string(),
escrow_output_descriptor,
coordinator_xonly_escrow_pk: coordinator_escrow_pk.to_string(),
escrow_amount_maker_sat,
escrow_amount_taker_sat,
escrow_fee_sat_per_participant,
})
}
pub async fn get_coordinator_taproot_pk(&self) -> Result<XOnlyPublicKey> {
let wallet = self.wallet.lock().await;
let address = wallet.get_address(bdk::wallet::AddressIndex::New)?;