mirror of
https://github.com/RoboSats/taptrade-core.git
synced 2025-07-31 07:01:40 +00:00
improve mempool lookup of escrow psbt
This commit is contained in:
@ -1,7 +1,7 @@
|
|||||||
BITCOIN_RPC_ADDRESS_PORT="127.0.0.1:8332"
|
BITCOIN_RPC_ADDRESS_PORT="127.0.0.1:8332"
|
||||||
BITCOIN_RPC_USER="coordinator"
|
BITCOIN_RPC_USER="coordinator"
|
||||||
BITCOIN_RPC_PASSWORD="test1234"
|
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)
|
BDK_DB_PATH="./dbs/bdk-wallet" # Path to the BDK Sled database (no .db postfix)
|
||||||
WALLET_XPRV="tprv8ZgxMBicQKsPdHuCSjhQuSZP1h6ZTeiRqREYS5guGPdtL7D1uNLpnJmb2oJep99Esq1NbNZKVJBNnD2ZhuXSK7G5eFmmcx73gsoa65e2U32"
|
WALLET_XPRV="tprv8ZgxMBicQKsPdHuCSjhQuSZP1h6ZTeiRqREYS5guGPdtL7D1uNLpnJmb2oJep99Esq1NbNZKVJBNnD2ZhuXSK7G5eFmmcx73gsoa65e2U32"
|
||||||
PUNISHMENT_ENABLED=1 # enable punishment for misbehaving traders
|
PUNISHMENT_ENABLED=1 # enable punishment for misbehaving traders
|
||||||
|
@ -107,7 +107,7 @@ async fn request_offer_status_maker(
|
|||||||
Ok(offer_taken_response) => Ok(Json(offer_taken_response).into_response()),
|
Ok(offer_taken_response) => Ok(Json(offer_taken_response).into_response()),
|
||||||
Err(FetchOffersError::NoOffersAvailable) => Ok(StatusCode::NO_CONTENT.into_response()),
|
Err(FetchOffersError::NoOffersAvailable) => Ok(StatusCode::NO_CONTENT.into_response()),
|
||||||
Err(FetchOffersError::Database(e)) => {
|
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())
|
Ok(StatusCode::INTERNAL_SERVER_ERROR.into_response())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ pub mod create_taproot;
|
|||||||
pub mod mempool_monitoring;
|
pub mod mempool_monitoring;
|
||||||
pub mod tx_confirmation_monitoring;
|
pub mod tx_confirmation_monitoring;
|
||||||
|
|
||||||
|
use axum::routing::trace;
|
||||||
|
|
||||||
use self::coordinator_utils::*;
|
use self::coordinator_utils::*;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@ -139,6 +141,10 @@ pub async fn handle_taker_bond(
|
|||||||
return Err(BondError::CoordinatorError(e.to_string()));
|
return Err(BondError::CoordinatorError(e.to_string()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
debug!(
|
||||||
|
"\nEscrow PSBT creation successful: {:?}",
|
||||||
|
escrow_output_data
|
||||||
|
);
|
||||||
|
|
||||||
if let Err(e) = database
|
if let Err(e) = database
|
||||||
.add_taker_info_and_move_table(payload, &escrow_output_data)
|
.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()));
|
return Err(BondError::CoordinatorError(e.to_string()));
|
||||||
}
|
}
|
||||||
|
trace!("Taker information added to database and moved table successfully");
|
||||||
Ok(OfferTakenResponse {
|
Ok(OfferTakenResponse {
|
||||||
escrow_psbt_hex: escrow_output_data.escrow_psbt_hex,
|
escrow_psbt_hex: escrow_output_data.escrow_psbt_hex,
|
||||||
escrow_output_descriptor: escrow_output_data.escrow_output_descriptor,
|
escrow_output_descriptor: escrow_output_data.escrow_output_descriptor,
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
use std::str::FromStr;
|
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::*;
|
use super::*;
|
||||||
|
|
||||||
@ -11,11 +17,44 @@ fn get_confirmations(
|
|||||||
let mut now_confirmed_txs = Vec::new();
|
let mut now_confirmed_txs = Vec::new();
|
||||||
for txid in unconfirmed_txids {
|
for txid in unconfirmed_txids {
|
||||||
let txid_struct = Txid::from_str(&txid)?;
|
let txid_struct = Txid::from_str(&txid)?;
|
||||||
let tx_info = coordinator
|
let tx_info = match coordinator
|
||||||
.coordinator_wallet
|
.coordinator_wallet
|
||||||
.json_rpc_client
|
.json_rpc_client
|
||||||
.as_ref()
|
.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 {
|
if let Some(confirmations) = tx_info.confirmations {
|
||||||
debug!(
|
debug!(
|
||||||
"Transaction {} in now confirmed with {} confirmations",
|
"Transaction {} in now confirmed with {} confirmations",
|
||||||
@ -35,7 +74,7 @@ pub async fn update_transaction_confirmations(coordinator: Arc<Coordinator>) {
|
|||||||
trace!("Checking for transaction confirmations");
|
trace!("Checking for transaction confirmations");
|
||||||
let unconfirmed_transactions = match coordinator
|
let unconfirmed_transactions = match coordinator
|
||||||
.coordinator_db
|
.coordinator_db
|
||||||
.fetch_unconfirmed_bond_txids()
|
.fetch_unconfirmed_escrow_txids()
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(txids) => txids,
|
Ok(txids) => txids,
|
||||||
|
@ -135,8 +135,8 @@ impl CoordinatorDB {
|
|||||||
musig_pubkey_compressed_hex_maker TEXT NOT NULL,
|
musig_pubkey_compressed_hex_maker TEXT NOT NULL,
|
||||||
musig_pub_nonce_hex_taker TEXT NOT NULL,
|
musig_pub_nonce_hex_taker TEXT NOT NULL,
|
||||||
musig_pubkey_compressed_hex_taker TEXT NOT NULL,
|
musig_pubkey_compressed_hex_taker TEXT NOT NULL,
|
||||||
escrow_psbt_hex TEXT,
|
escrow_psbt_hex TEXT NOT NULL,
|
||||||
escrow_psbt_txid TEXT,
|
escrow_psbt_txid TEXT NOT NULL,
|
||||||
escrow_psbt_is_confirmed INTEGER,
|
escrow_psbt_is_confirmed INTEGER,
|
||||||
maker_happy INTEGER,
|
maker_happy INTEGER,
|
||||||
taker_happy INTEGER,
|
taker_happy INTEGER,
|
||||||
@ -374,10 +374,10 @@ impl CoordinatorDB {
|
|||||||
sqlx::query(
|
sqlx::query(
|
||||||
"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_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_hex_taker, escrow_psbt_hex, escrow_output_descriptor, escrow_psbt_is_confirmed, escrow_ongoing,
|
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)
|
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.offer_id)
|
||||||
.bind(public_offer.robohash_maker)
|
.bind(public_offer.robohash_maker)
|
||||||
@ -399,8 +399,9 @@ 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(&escrow_tx_data.escrow_output_descriptor)
|
|
||||||
.bind(&escrow_tx_data.escrow_psbt_hex)
|
.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(0)
|
.bind(0)
|
||||||
.bind(&escrow_tx_data.coordinator_xonly_escrow_pk)
|
.bind(&escrow_tx_data.coordinator_xonly_escrow_pk)
|
||||||
@ -419,7 +420,7 @@ impl CoordinatorDB {
|
|||||||
) -> Result<Option<EscrowPsbt>> {
|
) -> Result<Option<EscrowPsbt>> {
|
||||||
let offer = sqlx::query(
|
let offer = sqlx::query(
|
||||||
"SELECT escrow_output_descriptor, escrow_amount_maker_sat,
|
"SELECT escrow_output_descriptor, escrow_amount_maker_sat,
|
||||||
escrow_amount_taker_sat, escrow_fee_per_participant, escrow_taproot_pk_coordinator
|
escrow_amount_taker_sat, escrow_fee_per_participant, escrow_taproot_pk_coordinator, escrow_psbt_hex, escrow_psbt_txid
|
||||||
FROM taken_offers WHERE offer_id = ?",
|
FROM taken_offers WHERE offer_id = ?",
|
||||||
)
|
)
|
||||||
.bind(offer_id_hex)
|
.bind(offer_id_hex)
|
||||||
@ -437,8 +438,10 @@ impl CoordinatorDB {
|
|||||||
let coordinator_xonly_escrow_pk =
|
let coordinator_xonly_escrow_pk =
|
||||||
offer.try_get::<String, _>("escrow_taproot_pk_coordinator")?;
|
offer.try_get::<String, _>("escrow_taproot_pk_coordinator")?;
|
||||||
let escrow_psbt_hex = offer.try_get::<String, _>("escrow_psbt_hex")?;
|
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 {
|
Ok(Some(EscrowPsbt {
|
||||||
|
escrow_tx_txid,
|
||||||
escrow_psbt_hex,
|
escrow_psbt_hex,
|
||||||
escrow_output_descriptor,
|
escrow_output_descriptor,
|
||||||
coordinator_xonly_escrow_pk,
|
coordinator_xonly_escrow_pk,
|
||||||
@ -555,7 +558,7 @@ impl CoordinatorDB {
|
|||||||
Ok(())
|
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 txids = Vec::new();
|
||||||
let mut rows = sqlx::query(
|
let mut rows = sqlx::query(
|
||||||
"SELECT escrow_psbt_txid FROM taken_offers WHERE escrow_psbt_is_confirmed = 0",
|
"SELECT escrow_psbt_txid FROM taken_offers WHERE escrow_psbt_is_confirmed = 0",
|
||||||
|
@ -4,7 +4,7 @@ mod database;
|
|||||||
mod wallet;
|
mod wallet;
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use bdk::sled;
|
use bdk::{database::MemoryDatabase, sled};
|
||||||
use communication::{api::*, api_server, communication_utils::*, handler_errors::*};
|
use communication::{api::*, api_server, communication_utils::*, handler_errors::*};
|
||||||
use coordinator::{
|
use coordinator::{
|
||||||
bond_monitoring::*, coordinator_utils::*,
|
bond_monitoring::*, coordinator_utils::*,
|
||||||
@ -25,7 +25,7 @@ use wallet::{escrow_psbt::*, wallet_utils::*, *};
|
|||||||
|
|
||||||
pub struct Coordinator {
|
pub struct Coordinator {
|
||||||
pub coordinator_db: Arc<CoordinatorDB>,
|
pub coordinator_db: Arc<CoordinatorDB>,
|
||||||
pub coordinator_wallet: Arc<CoordinatorWallet<sled::Tree>>,
|
pub coordinator_wallet: Arc<CoordinatorWallet<MemoryDatabase>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// populate .env with values before starting
|
// populate .env with values before starting
|
||||||
|
@ -157,15 +157,17 @@ impl<D: bdk::database::BatchDatabase> CoordinatorWallet<D> {
|
|||||||
|
|
||||||
let (escrow_psbt, details) = {
|
let (escrow_psbt, details) = {
|
||||||
// maybe we can generate a address/taproot pk directly from the descriptor without a new wallet?
|
// maybe we can generate a address/taproot pk directly from the descriptor without a new wallet?
|
||||||
let temp_wallet = Wallet::new(
|
// let temp_wallet = Wallet::new(
|
||||||
&escrow_output_descriptor,
|
// &escrow_output_descriptor,
|
||||||
None,
|
// None,
|
||||||
bitcoin::Network::Regtest,
|
// bitcoin::Network::Regtest,
|
||||||
MemoryDatabase::new(),
|
// MemoryDatabase::new(),
|
||||||
)?;
|
// )?;
|
||||||
let escrow_address = temp_wallet
|
// let escrow_address = temp_wallet
|
||||||
.get_address(bdk::wallet::AddressIndex::New)?
|
// .get_address(bdk::wallet::AddressIndex::New)?
|
||||||
.address;
|
// .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
|
// 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
|
// 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);
|
- (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 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
|
builder
|
||||||
.manually_selected_only()
|
.manually_selected_only()
|
||||||
.add_recipient(escrow_address.script_pubkey(), amount_escrow)
|
.add_recipient(escrow_address.script_pubkey(), amount_escrow)
|
||||||
@ -204,7 +209,10 @@ impl<D: bdk::database::BatchDatabase> CoordinatorWallet<D> {
|
|||||||
builder.finish()?
|
builder.finish()?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let escrow_tx_txid: String = details.txid.to_string();
|
||||||
|
|
||||||
Ok(EscrowPsbt {
|
Ok(EscrowPsbt {
|
||||||
|
escrow_tx_txid,
|
||||||
escrow_psbt_hex: escrow_psbt.to_string(),
|
escrow_psbt_hex: escrow_psbt.to_string(),
|
||||||
escrow_output_descriptor,
|
escrow_output_descriptor,
|
||||||
coordinator_xonly_escrow_pk: coordinator_escrow_pk.to_string(),
|
coordinator_xonly_escrow_pk: coordinator_escrow_pk.to_string(),
|
||||||
|
@ -44,6 +44,7 @@ pub struct CoordinatorWallet<D: bdk::database::BatchDatabase> {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct EscrowPsbt {
|
pub struct EscrowPsbt {
|
||||||
pub escrow_psbt_hex: String,
|
pub escrow_psbt_hex: String,
|
||||||
|
pub escrow_tx_txid: String,
|
||||||
pub escrow_output_descriptor: String,
|
pub escrow_output_descriptor: String,
|
||||||
pub coordinator_xonly_escrow_pk: String,
|
pub coordinator_xonly_escrow_pk: String,
|
||||||
pub escrow_amount_maker_sat: u64,
|
pub escrow_amount_maker_sat: u64,
|
||||||
@ -58,7 +59,7 @@ pub struct BondRequirements {
|
|||||||
pub min_input_sum_sat: u64,
|
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(
|
let wallet_xprv = ExtendedPrivKey::from_str(
|
||||||
&env::var("WALLET_XPRV").context("loading WALLET_XPRV from .env failed")?,
|
&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 mempool = MempoolHandler::new(json_rpc_client_clone).await;
|
||||||
let backend = RpcBlockchain::from_config(&rpc_config)?;
|
let backend = RpcBlockchain::from_config(&rpc_config)?;
|
||||||
// let backend = EsploraBlockchain::new(&env::var("ESPLORA_BACKEND")?, 1000);
|
// 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(
|
let wallet = Wallet::new(
|
||||||
Bip86(wallet_xprv, KeychainKind::External),
|
Bip86(wallet_xprv, KeychainKind::External),
|
||||||
Some(Bip86(wallet_xprv, KeychainKind::Internal)),
|
Some(Bip86(wallet_xprv, KeychainKind::Internal)),
|
||||||
bitcoin::Network::Regtest,
|
bitcoin::Network::Regtest,
|
||||||
sled_db,
|
MemoryDatabase::new(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
wallet
|
wallet
|
||||||
|
Reference in New Issue
Block a user