change escrow output logic

This commit is contained in:
fbock
2024-07-25 16:11:18 +02:00
parent c03c2d5e1f
commit f704289940
7 changed files with 57 additions and 56 deletions

View File

@ -62,7 +62,8 @@ pub struct PublicOffers {
#[derive(Serialize, Debug, Deserialize)] #[derive(Serialize, Debug, Deserialize)]
pub struct OfferTakenResponse { pub struct OfferTakenResponse {
pub trade_psbt_hex_to_sign: String, pub escrow_output_descriptor: String,
pub escrow_tx_fee_address: String,
} }
// request to receive the escrow psbt to sign for the specified offer to take it // request to receive the escrow psbt to sign for the specified offer to take it

View File

@ -133,11 +133,11 @@ pub async fn handle_taker_bond(
} }
debug!("\nTaker bond validation successful"); debug!("\nTaker bond validation successful");
let escrow_psbt_data = match wallet let escrow_output_data = match wallet
.assemble_escrow_psbt(database, &payload.offer.offer_id_hex) .get_escrow_psbt_outputs(database, &payload.offer.offer_id_hex)
.await .await
{ {
Ok(escrow_psbt_data) => escrow_psbt_data, Ok(escrow_output_data) => escrow_output_data,
Err(e) => { Err(e) => {
return Err(BondError::CoordinatorError(e.to_string())); return Err(BondError::CoordinatorError(e.to_string()));
} }
@ -146,10 +146,9 @@ pub async fn handle_taker_bond(
if let Err(e) = database if let Err(e) = database
.add_taker_info_and_move_table( .add_taker_info_and_move_table(
payload, payload,
&escrow_psbt_data.escrow_psbt_hex_maker, &escrow_output_data.escrow_output_descriptor,
&escrow_psbt_data.escrow_psbt_hex_taker, &escrow_output_data.escrow_tx_fee_address,
escrow_psbt_data.escrow_psbt_txid, &escrow_output_data.coordinator_xonly_escrow_pk,
escrow_psbt_data.coordinator_escrow_pk,
) )
.await .await
{ {
@ -157,7 +156,8 @@ pub async fn handle_taker_bond(
} }
Ok(OfferTakenResponse { Ok(OfferTakenResponse {
trade_psbt_hex_to_sign: escrow_psbt_data.escrow_psbt_hex_taker, escrow_output_descriptor: escrow_output_data.escrow_output_descriptor,
escrow_tx_fee_address: escrow_output_data.escrow_tx_fee_address,
}) })
} }
@ -167,21 +167,22 @@ pub async fn get_offer_status_maker(
) -> Result<OfferTakenResponse, FetchOffersError> { ) -> Result<OfferTakenResponse, FetchOffersError> {
let database = &coordinator.coordinator_db; let database = &coordinator.coordinator_db;
let offer = match database let (descriptor, fee_address) = match database
.fetch_taken_offer_maker(&payload.offer_id_hex, &payload.robohash_hex) .fetch_escrow_output_information(&payload.offer_id_hex)
.await .await
{ {
Ok(offer) => offer, Ok(Some(descriptor_and_fee_addr)) => (descriptor_and_fee_addr.0, descriptor_and_fee_addr.1),
Ok(None) => {
return Err(FetchOffersError::NoOffersAvailable);
}
Err(e) => { Err(e) => {
return Err(FetchOffersError::Database(e.to_string())); return Err(FetchOffersError::Database(e.to_string()));
} }
}; };
match offer { Ok(OfferTakenResponse {
Some(offer) => Ok(OfferTakenResponse { escrow_output_descriptor: descriptor,
trade_psbt_hex_to_sign: offer, escrow_tx_fee_address: fee_address,
}), })
None => Err(FetchOffersError::NoOffersAvailable),
}
} }
pub async fn fetch_escrow_confirmation_status( pub async fn fetch_escrow_confirmation_status(

View File

@ -353,10 +353,9 @@ impl CoordinatorDB {
pub async fn add_taker_info_and_move_table( pub async fn add_taker_info_and_move_table(
&self, &self,
trade_and_taker_info: &OfferPsbtRequest, trade_and_taker_info: &OfferPsbtRequest,
trade_contract_psbt_maker: &str, escrow_output_descriptor: &str,
trade_contract_psbt_taker: &str, escrow_tx_fee_address: &str,
trade_tx_txid: String, escrow_taproot_pk_coordinator: &str,
escrow_taproot_pk_coordinator: String,
) -> Result<()> { ) -> Result<()> {
let public_offer = self let public_offer = self
.fetch_and_delete_offer_from_public_offers_table( .fetch_and_delete_offer_from_public_offers_table(
@ -368,9 +367,9 @@ impl CoordinatorDB {
"INSERT OR REPLACE INTO taken_offers (offer_id, robohash_maker, robohash_taker, is_buy_order, amount_sat, "INSERT OR REPLACE INTO taken_offers (offer_id, robohash_maker, robohash_taker, is_buy_order, amount_sat,
bond_ratio, offer_duration_ts, bond_address_maker, bond_address_taker, bond_amount_sat, bond_tx_hex_maker, bond_ratio, offer_duration_ts, bond_address_maker, bond_address_taker, bond_amount_sat, bond_tx_hex_maker,
bond_tx_hex_taker, payout_address_maker, payout_address_taker, taproot_pubkey_hex_maker, taproot_pubkey_hex_taker, musig_pub_nonce_hex_maker, musig_pubkey_hex_maker, bond_tx_hex_taker, payout_address_maker, payout_address_taker, taproot_pubkey_hex_maker, taproot_pubkey_hex_taker, musig_pub_nonce_hex_maker, musig_pubkey_hex_maker,
musig_pub_nonce_hex_taker, musig_pubkey_hex_taker, escrow_psbt_hex_maker, escrow_psbt_hex_taker, escrow_psbt_txid, escrow_psbt_is_confirmed, escrow_ongoing, musig_pub_nonce_hex_taker, musig_pubkey_hex_taker, escrow_output_descriptor, escrow_tx_fee_address, escrow_psbt_is_confirmed, escrow_ongoing,
escrow_taproot_pk_coordinator) escrow_taproot_pk_coordinator)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
) )
.bind(public_offer.offer_id) .bind(public_offer.offer_id)
.bind(public_offer.robohash_maker) .bind(public_offer.robohash_maker)
@ -392,9 +391,8 @@ impl CoordinatorDB {
.bind(public_offer.musig_pubkey_hex_maker) .bind(public_offer.musig_pubkey_hex_maker)
.bind(trade_and_taker_info.trade_data.musig_pub_nonce_hex.clone()) .bind(trade_and_taker_info.trade_data.musig_pub_nonce_hex.clone())
.bind(trade_and_taker_info.trade_data.musig_pubkey_hex.clone()) .bind(trade_and_taker_info.trade_data.musig_pubkey_hex.clone())
.bind(trade_contract_psbt_maker) .bind(escrow_output_descriptor)
.bind(trade_contract_psbt_taker) .bind(escrow_tx_fee_address)
.bind(trade_tx_txid)
.bind(0) .bind(0)
.bind(0) .bind(0)
.bind(escrow_taproot_pk_coordinator) .bind(escrow_taproot_pk_coordinator)
@ -404,13 +402,12 @@ impl CoordinatorDB {
Ok(()) Ok(())
} }
pub async fn fetch_taken_offer_maker( pub async fn fetch_escrow_output_information(
&self, &self,
offer_id_hex: &str, offer_id_hex: &str,
robohash_hex_maker: &str, ) -> Result<Option<(String, String)>> {
) -> Result<Option<String>> {
let offer = sqlx::query( let offer = sqlx::query(
"SELECT escrow_psbt_hex_maker, robohash_maker FROM taken_offers WHERE offer_id = ?", "SELECT escrow_output_descriptor, escrow_tx_fee_address FROM taken_offers WHERE offer_id = ?",
) )
.bind(offer_id_hex) .bind(offer_id_hex)
.fetch_optional(&*self.db_pool) .fetch_optional(&*self.db_pool)
@ -419,16 +416,9 @@ impl CoordinatorDB {
Some(offer) => offer, Some(offer) => offer,
None => return Ok(None), None => return Ok(None),
}; };
match offer.try_get::<Vec<u8>, _>("robohash_maker") { let descriptor = offer.try_get::<String, _>("escrow_output_descriptor")?;
Ok(robohash) => { let fee_address = offer.try_get::<String, _>("escrow_tx_fee_address")?;
if hex::encode(robohash) == *robohash_hex_maker { Ok(Some((descriptor, fee_address)))
Ok(offer.try_get("escrow_psbt_hex_maker")?)
} else {
Ok(None)
}
}
Err(_) => Ok(None),
}
} }
// returns a hashmap of RoboHash, MonitoringBond for the monitoring loop // returns a hashmap of RoboHash, MonitoringBond for the monitoring loop

View File

@ -91,7 +91,17 @@ pub fn build_escrow_transaction_output_descriptor(
// Create the descriptor // Create the descriptor
let descriptor = Descriptor::new_tr(internal_agg_musig_key, Some(final_tap_tree)) let descriptor = Descriptor::new_tr(internal_agg_musig_key, Some(final_tap_tree))
.context("Error assembling escrow output descriptor")?; .context("Error assembling escrow output descriptor")?;
descriptor.sanity_check()?;
debug!("Escrow descriptor: {}", descriptor.to_string()); debug!("Escrow descriptor: {}", descriptor);
Ok(descriptor.to_string()) Ok(descriptor.to_string())
} }
pub fn assemble_escrow_psbts(
coordinator: &Coordinator,
escrow_data: &EscrowPsbtConstructionData,
coordinator_pk: &XOnlyPublicKey,
) -> Result<()> {
panic!("Implement wallet.build_escrow_psbt()");
Ok(())
}

View File

@ -40,10 +40,9 @@ pub struct CoordinatorWallet<D: bdk::database::BatchDatabase> {
#[derive(Debug)] #[derive(Debug)]
pub struct EscrowPsbt { pub struct EscrowPsbt {
pub escrow_psbt_hex_maker: String, pub escrow_output_descriptor: String,
pub escrow_psbt_hex_taker: String, pub escrow_tx_fee_address: String,
pub escrow_psbt_txid: String, pub coordinator_xonly_escrow_pk: String,
pub coordinator_escrow_pk: String,
} }
#[derive(PartialEq, Debug, Clone)] #[derive(PartialEq, Debug, Clone)]
@ -232,23 +231,22 @@ impl<D: bdk::database::BatchDatabase> CoordinatorWallet<D> {
Ok(()) Ok(())
} }
pub async fn assemble_escrow_psbt( pub async fn get_escrow_psbt_outputs(
&self, &self,
db: &Arc<CoordinatorDB>, db: &Arc<CoordinatorDB>,
trade_id: &str, trade_id: &str,
) -> Result<EscrowPsbt> { ) -> Result<EscrowPsbt> {
let escrow_pubkeys = db.fetch_escrow_tx_payout_data(trade_id).await?; let escrow_pubkeys = db.fetch_escrow_tx_payout_data(trade_id).await?;
let coordinator_escrow_pk = self.get_coordinator_taproot_pk().await?; let coordinator_escrow_pk = self.get_coordinator_taproot_pk().await?;
let escrow_descriptor = let escrow_output_descriptor =
build_escrow_transaction_output_descriptor(&escrow_pubkeys, &coordinator_escrow_pk)?; build_escrow_transaction_output_descriptor(&escrow_pubkeys, &coordinator_escrow_pk)?;
let escrow_tx_fee_address = self.get_new_address().await?;
panic!("Dummy output"); Ok(EscrowPsbt {
// Ok(EscrowPsbt { escrow_output_descriptor,
// escrow_psbt_hex_maker: String::new(), escrow_tx_fee_address,
// escrow_psbt_hex_taker: String::new(), coordinator_xonly_escrow_pk: coordinator_escrow_pk.to_string(),
// escrow_psbt_txid: String::new(), })
// coordinator_escrow_pk,
// })
} }
pub async fn get_coordinator_taproot_pk(&self) -> Result<XOnlyPublicKey> { pub async fn get_coordinator_taproot_pk(&self) -> Result<XOnlyPublicKey> {

View File

@ -75,7 +75,7 @@ impl BondSubmissionRequest {
) -> Result<BondSubmissionRequest> { ) -> Result<BondSubmissionRequest> {
let signed_bond_hex = serialize_hex(&bond.to_owned().extract_tx()); let signed_bond_hex = serialize_hex(&bond.to_owned().extract_tx());
let musig_pub_nonce_hex = hex::encode(musig_data.nonce.get_pub_for_sharing()?.serialize()); let musig_pub_nonce_hex = hex::encode(musig_data.nonce.get_pub_for_sharing()?.serialize());
let musig_pubkey_hex = hex::encode(musig_data.public_key.0.serialize()); let musig_pubkey_hex = hex::encode(musig_data.public_key.to_string());
let taproot_pubkey_hex = hex::encode(taproot_pubkey.serialize()); let taproot_pubkey_hex = hex::encode(taproot_pubkey.serialize());
let request = BondSubmissionRequest { let request = BondSubmissionRequest {

View File

@ -9,3 +9,4 @@ Thinks to improve when implementing the production ready library/coordinator:
* use the same database as the existing (python) robosats coordinator instead of separate sqlite db? * use the same database as the existing (python) robosats coordinator instead of separate sqlite db?
* share single db for coordinator and bdk wallet instead of sqlite + bdk k/v db? * share single db for coordinator and bdk wallet instead of sqlite + bdk k/v db?
* add more test coverage * add more test coverage
* move as much logic as possible (without safety tradeoffs) to coordinator side to make client lean