@@ -23,15 +23,17 @@ TransactionError BroadcastTransaction(const CTransactionRef tx, std::string& err
2323
2424 { // cs_main scope
2525 LOCK (cs_main);
26+ // If the transaction is already confirmed in the chain, don't do anything
27+ // and return early.
2628 CCoinsViewCache &view = *pcoinsTip;
27- bool fHaveChain = false ;
28- for (size_t o = 0 ; !fHaveChain && o < tx->vout .size (); o++) {
29+ for (size_t o = 0 ; o < tx->vout .size (); o++) {
2930 const Coin& existingCoin = view.AccessCoin (COutPoint (hashTx, o));
30- fHaveChain = !existingCoin.IsSpent ();
31+ // IsSpent doesnt mean the coin is spent, it means the output doesnt' exist.
32+ // So if the output does exist, then this transaction exists in the chain.
33+ if (!existingCoin.IsSpent ()) return TransactionError::ALREADY_IN_CHAIN;
3134 }
32- bool fHaveMempool = mempool.exists (hashTx);
33- if (!fHaveMempool && !fHaveChain ) {
34- // push to local node and sync with wallets
35+ if (!mempool.exists (hashTx)) {
36+ // Transaction is not already in the mempool. Submit it.
3537 CValidationState state;
3638 bool fMissingInputs ;
3739 if (!AcceptToMemoryPool (mempool, state, std::move (tx), &fMissingInputs ,
@@ -46,24 +48,31 @@ TransactionError BroadcastTransaction(const CTransactionRef tx, std::string& err
4648 err_string = FormatStateMessage (state);
4749 return TransactionError::MEMPOOL_ERROR;
4850 }
49- } else if (wait_callback) {
50- // If wallet is enabled, ensure that the wallet has been made aware
51- // of the new transaction prior to returning. This prevents a race
52- // where a user might call sendrawtransaction with a transaction
53- // to/from their wallet, immediately call some wallet RPC, and get
54- // a stale result because callbacks have not yet been processed.
51+ }
52+
53+ // Transaction was accepted to the mempool.
54+
55+ if (wait_callback) {
56+ // For transactions broadcast from outside the wallet, make sure
57+ // that the wallet has been notified of the transaction before
58+ // continuing.
59+ //
60+ // This prevents a race where a user might call sendrawtransaction
61+ // with a transaction to/from their wallet, immediately call some
62+ // wallet RPC, and get a stale result because callbacks have not
63+ // yet been processed.
5564 CallFunctionInValidationInterfaceQueue ([&promise] {
5665 promise.set_value ();
5766 });
5867 callback_set = true ;
5968 }
60- } else if (fHaveChain ) {
61- return TransactionError::ALREADY_IN_CHAIN;
6269 }
6370
6471 } // cs_main
6572
6673 if (callback_set) {
74+ // Wait until Validation Interface clients have been notified of the
75+ // transaction entering the mempool.
6776 promise.get_future ().wait ();
6877 }
6978
0 commit comments