improve mempool lookup of escrow psbt

This commit is contained in:
fbock
2024-08-06 13:27:21 +02:00
parent deedcd679f
commit 6adcabcb54
8 changed files with 89 additions and 32 deletions

View File

@ -1,9 +1,9 @@
BITCOIN_RPC_ADDRESS_PORT="127.0.0.1:8332"
BITCOIN_RPC_USER="coordinator"
BITCOIN_RPC_PASSWORD="test1234"
DATABASE_PATH="./dbs/trades.db" # path to the coordinator sqlite database storing the trades
DATABASE_PATH=":memory:" #"./dbs/trades.db" # path to the coordinator sqlite database storing the trades
BDK_DB_PATH="./dbs/bdk-wallet" # Path to the BDK Sled database (no .db postfix)
WALLET_XPRV="tprv8ZgxMBicQKsPdHuCSjhQuSZP1h6ZTeiRqREYS5guGPdtL7D1uNLpnJmb2oJep99Esq1NbNZKVJBNnD2ZhuXSK7G5eFmmcx73gsoa65e2U32"
PUNISHMENT_ENABLED=1 # enable punishment for misbehaving traders
PORT=9999 # port for the coordinator to listen on
COORDINATOR_FEERATE=1 # coordinator fee in percent of the trade amount
COORDINATOR_FEERATE=1 # coordinator fee in percent of the trade amount

View File

@ -107,7 +107,7 @@ async fn request_offer_status_maker(
Ok(offer_taken_response) => Ok(Json(offer_taken_response).into_response()),
Err(FetchOffersError::NoOffersAvailable) => Ok(StatusCode::NO_CONTENT.into_response()),
Err(FetchOffersError::Database(e)) => {
error!("Database error fetching offers: {e}");
error!("Database error fetching offer status maker: {e}");
Ok(StatusCode::INTERNAL_SERVER_ERROR.into_response())
}
}

View File

@ -4,6 +4,8 @@ pub mod create_taproot;
pub mod mempool_monitoring;
pub mod tx_confirmation_monitoring;
use axum::routing::trace;
use self::coordinator_utils::*;
use super::*;
@ -139,6 +141,10 @@ pub async fn handle_taker_bond(
return Err(BondError::CoordinatorError(e.to_string()));
}
};
debug!(
"\nEscrow PSBT creation successful: {:?}",
escrow_output_data
);
if let Err(e) = database
.add_taker_info_and_move_table(payload, &escrow_output_data)
@ -146,7 +152,7 @@ pub async fn handle_taker_bond(
{
return Err(BondError::CoordinatorError(e.to_string()));
}
trace!("Taker information added to database and moved table successfully");
Ok(OfferTakenResponse {
escrow_psbt_hex: escrow_output_data.escrow_psbt_hex,
escrow_output_descriptor: escrow_output_data.escrow_output_descriptor,

View File

@ -1,6 +1,12 @@
use std::str::FromStr;
use bdk::{bitcoin::Txid, bitcoincore_rpc::RpcApi};
use axum::Json;
use bdk::{
bitcoin::Txid,
bitcoincore_rpc::{
jsonrpc::error::RpcError, jsonrpc::Error as JsonRpcError, Error as CoreRpcError, RpcApi,
},
};
use super::*;
@ -11,11 +17,44 @@ fn get_confirmations(
let mut now_confirmed_txs = Vec::new();
for txid in unconfirmed_txids {
let txid_struct = Txid::from_str(&txid)?;
let tx_info = coordinator
let tx_info = match coordinator
.coordinator_wallet
.json_rpc_client
.as_ref()
.get_raw_transaction_info(&txid_struct, None)?;
.get_raw_transaction_info(&txid_struct, None)
{
Ok(tx_info) => tx_info,
Err(e) => match e {
CoreRpcError::JsonRpc(e) => {
if let JsonRpcError::Rpc(rpc_error) = e {
if rpc_error.code == -5 {
trace!("Escrow transaction {} not yet found in mempool", &txid);
continue;
} else {
return Err(anyhow!(
"Error fetching transaction info for {}: {:?}",
&txid,
rpc_error
));
}
} else {
return Err(anyhow!(
"Error fetching transaction info for {}: {:?}",
&txid,
e
));
}
}
_ => {
error!("Error fetching transaction info for {}: {:?}", &txid, e);
return Err(anyhow!(
"Error fetching transaction info for {}: {:?}",
&txid,
e
));
}
},
};
if let Some(confirmations) = tx_info.confirmations {
debug!(
"Transaction {} in now confirmed with {} confirmations",
@ -35,7 +74,7 @@ pub async fn update_transaction_confirmations(coordinator: Arc<Coordinator>) {
trace!("Checking for transaction confirmations");
let unconfirmed_transactions = match coordinator
.coordinator_db
.fetch_unconfirmed_bond_txids()
.fetch_unconfirmed_escrow_txids()
.await
{
Ok(txids) => txids,

View File

@ -135,8 +135,8 @@ impl CoordinatorDB {
musig_pubkey_compressed_hex_maker TEXT NOT NULL,
musig_pub_nonce_hex_taker TEXT NOT NULL,
musig_pubkey_compressed_hex_taker TEXT NOT NULL,
escrow_psbt_hex TEXT,
escrow_psbt_txid TEXT,
escrow_psbt_hex TEXT NOT NULL,
escrow_psbt_txid TEXT NOT NULL,
escrow_psbt_is_confirmed INTEGER,
maker_happy INTEGER,
taker_happy INTEGER,
@ -374,10 +374,10 @@ impl CoordinatorDB {
sqlx::query(
"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, escrow_output_descriptor, escrow_psbt_is_confirmed, escrow_ongoing,
bond_tx_hex_taker, payout_address_maker, payout_address_taker, taproot_xonly_pubkey_hex_maker, taproot_xonly_pubkey_hex_taker, musig_pub_nonce_hex_maker, musig_pubkey_compressed_hex_maker,
musig_pub_nonce_hex_taker, musig_pubkey_compressed_hex_taker, escrow_psbt_hex, escrow_psbt_txid, escrow_output_descriptor, escrow_psbt_is_confirmed, escrow_ongoing,
escrow_taproot_pk_coordinator, escrow_amount_maker_sat, escrow_amount_taker_sat, escrow_fee_per_participant)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
)
.bind(public_offer.offer_id)
.bind(public_offer.robohash_maker)
@ -399,8 +399,9 @@ 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(&escrow_tx_data.escrow_output_descriptor)
.bind(&escrow_tx_data.escrow_psbt_hex)
.bind(&escrow_tx_data.escrow_tx_txid)
.bind(&escrow_tx_data.escrow_output_descriptor)
.bind(0)
.bind(0)
.bind(&escrow_tx_data.coordinator_xonly_escrow_pk)
@ -418,8 +419,8 @@ impl CoordinatorDB {
offer_id_hex: &str,
) -> Result<Option<EscrowPsbt>> {
let offer = sqlx::query(
"SELECT escrow_output_descriptor, escrow_amount_maker_sat,
escrow_amount_taker_sat, escrow_fee_per_participant, escrow_taproot_pk_coordinator
"SELECT escrow_output_descriptor, escrow_amount_maker_sat,
escrow_amount_taker_sat, escrow_fee_per_participant, escrow_taproot_pk_coordinator, escrow_psbt_hex, escrow_psbt_txid
FROM taken_offers WHERE offer_id = ?",
)
.bind(offer_id_hex)
@ -437,8 +438,10 @@ impl CoordinatorDB {
let coordinator_xonly_escrow_pk =
offer.try_get::<String, _>("escrow_taproot_pk_coordinator")?;
let escrow_psbt_hex = offer.try_get::<String, _>("escrow_psbt_hex")?;
let escrow_tx_txid = offer.try_get::<String, _>("escrow_psbt_txid")?;
Ok(Some(EscrowPsbt {
escrow_tx_txid,
escrow_psbt_hex,
escrow_output_descriptor,
coordinator_xonly_escrow_pk,
@ -555,7 +558,7 @@ impl CoordinatorDB {
Ok(())
}
pub async fn fetch_unconfirmed_bond_txids(&self) -> Result<Vec<String>> {
pub async fn fetch_unconfirmed_escrow_txids(&self) -> Result<Vec<String>> {
let mut txids = Vec::new();
let mut rows = sqlx::query(
"SELECT escrow_psbt_txid FROM taken_offers WHERE escrow_psbt_is_confirmed = 0",

View File

@ -4,7 +4,7 @@ mod database;
mod wallet;
use anyhow::{anyhow, Result};
use bdk::sled;
use bdk::{database::MemoryDatabase, sled};
use communication::{api::*, api_server, communication_utils::*, handler_errors::*};
use coordinator::{
bond_monitoring::*, coordinator_utils::*,
@ -25,7 +25,7 @@ use wallet::{escrow_psbt::*, wallet_utils::*, *};
pub struct Coordinator {
pub coordinator_db: Arc<CoordinatorDB>,
pub coordinator_wallet: Arc<CoordinatorWallet<sled::Tree>>,
pub coordinator_wallet: Arc<CoordinatorWallet<MemoryDatabase>>,
}
// populate .env with values before starting

View File

@ -157,15 +157,17 @@ impl<D: bdk::database::BatchDatabase> CoordinatorWallet<D> {
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;
// 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;
let escrow_address =
Address::from_str(self.get_new_address().await?.as_str())?.assume_checked();
// 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
@ -177,7 +179,10 @@ impl<D: bdk::database::BatchDatabase> CoordinatorWallet<D> {
- (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();
let wallet = self.wallet.lock().await;
// let mut builder = temp_wallet.build_tx();
let mut builder = wallet.build_tx();
builder
.manually_selected_only()
.add_recipient(escrow_address.script_pubkey(), amount_escrow)
@ -204,7 +209,10 @@ impl<D: bdk::database::BatchDatabase> CoordinatorWallet<D> {
builder.finish()?
};
let escrow_tx_txid: String = details.txid.to_string();
Ok(EscrowPsbt {
escrow_tx_txid,
escrow_psbt_hex: escrow_psbt.to_string(),
escrow_output_descriptor,
coordinator_xonly_escrow_pk: coordinator_escrow_pk.to_string(),

View File

@ -44,6 +44,7 @@ pub struct CoordinatorWallet<D: bdk::database::BatchDatabase> {
#[derive(Debug)]
pub struct EscrowPsbt {
pub escrow_psbt_hex: String,
pub escrow_tx_txid: String,
pub escrow_output_descriptor: String,
pub coordinator_xonly_escrow_pk: String,
pub escrow_amount_maker_sat: u64,
@ -58,7 +59,7 @@ pub struct BondRequirements {
pub min_input_sum_sat: u64,
}
pub async fn init_coordinator_wallet() -> Result<CoordinatorWallet<sled::Tree>> {
pub async fn init_coordinator_wallet() -> Result<CoordinatorWallet<MemoryDatabase>> {
let wallet_xprv = ExtendedPrivKey::from_str(
&env::var("WALLET_XPRV").context("loading WALLET_XPRV from .env failed")?,
)?;
@ -87,12 +88,12 @@ pub async fn init_coordinator_wallet() -> Result<CoordinatorWallet<sled::Tree>>
let mempool = MempoolHandler::new(json_rpc_client_clone).await;
let backend = RpcBlockchain::from_config(&rpc_config)?;
// let backend = EsploraBlockchain::new(&env::var("ESPLORA_BACKEND")?, 1000);
let sled_db = sled::open(env::var("BDK_DB_PATH")?)?.open_tree("default_wallet")?;
// let sled_db = sled::open(env::var("BDK_DB_PATH")?)?.open_tree("default_wallet")?;
let wallet = Wallet::new(
Bip86(wallet_xprv, KeychainKind::External),
Some(Bip86(wallet_xprv, KeychainKind::Internal)),
bitcoin::Network::Regtest,
sled_db,
MemoryDatabase::new(),
)?;
wallet