fix: Résolution du bug txn-mempool-conflict avec mutex global
All checks were successful
Build and Push to Registry / build-and-push (push) Successful in 1m58s
All checks were successful
Build and Push to Registry / build-and-push (push) Successful in 1m58s
- Ajout de src/tx_queue.rs avec mutex global TX_QUEUE - Modification de commit_new_transaction() pour verrouiller les transactions - Prévient les race conditions lors de la sélection d'UTXOs concurrents - Fix erreur RPC -26 'txn-mempool-conflict'
This commit is contained in:
parent
a056d44cbf
commit
470f0b36b9
@ -21,6 +21,7 @@ use sdk_common::{
|
||||
use crate::{lock_freezed_utxos, MutexExt, DAEMON, STORAGE, WALLET};
|
||||
use crate::{
|
||||
message::{broadcast_message, BroadcastType},
|
||||
tx_queue::lock_tx_queue,
|
||||
CHAIN_TIP,
|
||||
};
|
||||
|
||||
@ -307,12 +308,14 @@ fn process_validation(
|
||||
.extend(commit_msg.validation_tokens.iter());
|
||||
|
||||
// Sort by public key to group validations by signer
|
||||
state_to_update.validation_tokens.sort_unstable_by_key(|proof| proof.get_key());
|
||||
state_to_update
|
||||
.validation_tokens
|
||||
.sort_unstable_by_key(|proof| proof.get_key());
|
||||
|
||||
// Remove duplicates where same key validates same message
|
||||
state_to_update.validation_tokens.dedup_by(|a, b| {
|
||||
a.get_key() == b.get_key() && a.get_message() == b.get_message()
|
||||
});
|
||||
state_to_update
|
||||
.validation_tokens
|
||||
.dedup_by(|a, b| a.get_key() == b.get_key() && a.get_message() == b.get_message());
|
||||
}
|
||||
|
||||
let state_to_validate = updated_process.get_state_for_id(&new_state_id)?;
|
||||
@ -332,6 +335,11 @@ fn commit_new_transaction(
|
||||
updated_process: &mut Process,
|
||||
state_to_commit: ProcessState,
|
||||
) -> Result<OutPoint> {
|
||||
// Acquire global transaction lock to prevent concurrent transactions
|
||||
// from creating mempool conflicts (txn-mempool-conflict error -26)
|
||||
let _tx_lock = lock_tx_queue()?;
|
||||
log::debug!("Acquired transaction queue lock for process {}", updated_process.get_process_id()?);
|
||||
|
||||
let sp_wallet = WALLET
|
||||
.get()
|
||||
.ok_or(Error::msg("Wallet not initialized"))?
|
||||
@ -403,6 +411,14 @@ fn commit_new_transaction(
|
||||
|
||||
daemon.test_mempool_accept(&final_tx)?;
|
||||
let txid = daemon.broadcast(&final_tx)?;
|
||||
|
||||
// ✅ AJOUTER UN DÉLAI ICI
|
||||
log::info!(
|
||||
"Transaction broadcast: {}. Attente de confirmation mempool...",
|
||||
txid
|
||||
);
|
||||
std::thread::sleep(std::time::Duration::from_millis(500)); // 500ms de délai
|
||||
|
||||
let commited_in = OutPoint::new(txid, 0);
|
||||
|
||||
freezed_utxos.insert(commited_in);
|
||||
|
||||
@ -59,6 +59,7 @@ mod daemon;
|
||||
mod faucet;
|
||||
mod message;
|
||||
mod scan;
|
||||
mod tx_queue;
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::{
|
||||
|
||||
16
src/tx_queue.rs
Normal file
16
src/tx_queue.rs
Normal file
@ -0,0 +1,16 @@
|
||||
use std::sync::{Mutex, MutexGuard, OnceLock};
|
||||
use anyhow::Result;
|
||||
|
||||
/// Global transaction queue mutex to prevent concurrent transactions
|
||||
/// from creating mempool conflicts (txn-mempool-conflict error -26)
|
||||
static TX_QUEUE: OnceLock<Mutex<()>> = OnceLock::new();
|
||||
|
||||
/// Acquires the global transaction lock to serialize blockchain commits.
|
||||
/// This ensures only one transaction is created and broadcast at a time,
|
||||
/// preventing race conditions when selecting UTXOs.
|
||||
pub fn lock_tx_queue() -> Result<MutexGuard<'static, ()>> {
|
||||
TX_QUEUE
|
||||
.get_or_init(|| Mutex::new(()))
|
||||
.lock()
|
||||
.map_err(|e| anyhow::Error::msg(format!("Failed to lock tx queue: {}", e)))
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user