@@ -23,15 +23,17 @@ TransactionError BroadcastTransaction(const CTransactionRef tx, std::string& err
23
23
24
24
{ // cs_main scope
25
25
LOCK (cs_main);
26
+ // If the transaction is already confirmed in the chain, don't do anything
27
+ // and return early.
26
28
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++) {
29
30
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;
31
34
}
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.
35
37
CValidationState state;
36
38
bool fMissingInputs ;
37
39
if (!AcceptToMemoryPool (mempool, state, std::move (tx), &fMissingInputs ,
@@ -46,24 +48,31 @@ TransactionError BroadcastTransaction(const CTransactionRef tx, std::string& err
46
48
err_string = FormatStateMessage (state);
47
49
return TransactionError::MEMPOOL_ERROR;
48
50
}
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.
55
64
CallFunctionInValidationInterfaceQueue ([&promise] {
56
65
promise.set_value ();
57
66
});
58
67
callback_set = true ;
59
68
}
60
- } else if (fHaveChain ) {
61
- return TransactionError::ALREADY_IN_CHAIN;
62
69
}
63
70
64
71
} // cs_main
65
72
66
73
if (callback_set) {
74
+ // Wait until Validation Interface clients have been notified of the
75
+ // transaction entering the mempool.
67
76
promise.get_future ().wait ();
68
77
}
69
78
0 commit comments