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)]
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

View File

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

View File

@ -353,10 +353,9 @@ impl CoordinatorDB {
pub async fn add_taker_info_and_move_table(
&self,
trade_and_taker_info: &OfferPsbtRequest,
trade_contract_psbt_maker: &str,
trade_contract_psbt_taker: &str,
trade_tx_txid: String,
escrow_taproot_pk_coordinator: String,
escrow_output_descriptor: &str,
escrow_tx_fee_address: &str,
escrow_taproot_pk_coordinator: &str,
) -> Result<()> {
let public_offer = self
.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,
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,
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)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
)
.bind(public_offer.offer_id)
.bind(public_offer.robohash_maker)
@ -392,9 +391,8 @@ impl CoordinatorDB {
.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_pubkey_hex.clone())
.bind(trade_contract_psbt_maker)
.bind(trade_contract_psbt_taker)
.bind(trade_tx_txid)
.bind(escrow_output_descriptor)
.bind(escrow_tx_fee_address)
.bind(0)
.bind(0)
.bind(escrow_taproot_pk_coordinator)
@ -404,13 +402,12 @@ impl CoordinatorDB {
Ok(())
}
pub async fn fetch_taken_offer_maker(
pub async fn fetch_escrow_output_information(
&self,
offer_id_hex: &str,
robohash_hex_maker: &str,
) -> Result<Option<String>> {
) -> Result<Option<(String, String)>> {
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)
.fetch_optional(&*self.db_pool)
@ -419,16 +416,9 @@ impl CoordinatorDB {
Some(offer) => offer,
None => return Ok(None),
};
match offer.try_get::<Vec<u8>, _>("robohash_maker") {
Ok(robohash) => {
if hex::encode(robohash) == *robohash_hex_maker {
Ok(offer.try_get("escrow_psbt_hex_maker")?)
} else {
Ok(None)
}
}
Err(_) => Ok(None),
}
let descriptor = offer.try_get::<String, _>("escrow_output_descriptor")?;
let fee_address = offer.try_get::<String, _>("escrow_tx_fee_address")?;
Ok(Some((descriptor, fee_address)))
}
// 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
let descriptor = Descriptor::new_tr(internal_agg_musig_key, Some(final_tap_tree))
.context("Error assembling escrow output descriptor")?;
descriptor.sanity_check()?;
debug!("Escrow descriptor: {}", descriptor.to_string());
debug!("Escrow descriptor: {}", descriptor);
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)]
pub struct EscrowPsbt {
pub escrow_psbt_hex_maker: String,
pub escrow_psbt_hex_taker: String,
pub escrow_psbt_txid: String,
pub coordinator_escrow_pk: String,
pub escrow_output_descriptor: String,
pub escrow_tx_fee_address: String,
pub coordinator_xonly_escrow_pk: String,
}
#[derive(PartialEq, Debug, Clone)]
@ -232,23 +231,22 @@ impl<D: bdk::database::BatchDatabase> CoordinatorWallet<D> {
Ok(())
}
pub async fn assemble_escrow_psbt(
pub async fn get_escrow_psbt_outputs(
&self,
db: &Arc<CoordinatorDB>,
trade_id: &str,
) -> Result<EscrowPsbt> {
let escrow_pubkeys = db.fetch_escrow_tx_payout_data(trade_id).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)?;
let escrow_tx_fee_address = self.get_new_address().await?;
panic!("Dummy output");
// Ok(EscrowPsbt {
// escrow_psbt_hex_maker: String::new(),
// escrow_psbt_hex_taker: String::new(),
// escrow_psbt_txid: String::new(),
// coordinator_escrow_pk,
// })
Ok(EscrowPsbt {
escrow_output_descriptor,
escrow_tx_fee_address,
coordinator_xonly_escrow_pk: coordinator_escrow_pk.to_string(),
})
}
pub async fn get_coordinator_taproot_pk(&self) -> Result<XOnlyPublicKey> {

View File

@ -75,7 +75,7 @@ impl BondSubmissionRequest {
) -> Result<BondSubmissionRequest> {
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_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 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?
* share single db for coordinator and bdk wallet instead of sqlite + bdk k/v db?
* add more test coverage
* move as much logic as possible (without safety tradeoffs) to coordinator side to make client lean