mirror of
https://github.com/RoboSats/taptrade-core.git
synced 2025-07-25 12:13:23 +00:00
improve mempool lookup of escrow psbt
This commit is contained in:
@ -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
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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(),
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user