Tidy up BroadcastTransaction()

This commit is contained in:
John Newbery
2019-07-23 11:49:53 -04:00
committed by Antoine Riard
parent b8eecf8e79
commit fb62f128bb
2 changed files with 30 additions and 16 deletions

View File

@@ -23,15 +23,17 @@ TransactionError BroadcastTransaction(const CTransactionRef tx, std::string& err
{ // cs_main scope
LOCK(cs_main);
// If the transaction is already confirmed in the chain, don't do anything
// and return early.
CCoinsViewCache &view = *pcoinsTip;
bool fHaveChain = false;
for (size_t o = 0; !fHaveChain && o < tx->vout.size(); o++) {
for (size_t o = 0; o < tx->vout.size(); o++) {
const Coin& existingCoin = view.AccessCoin(COutPoint(hashTx, o));
fHaveChain = !existingCoin.IsSpent();
// IsSpent doesnt mean the coin is spent, it means the output doesnt' exist.
// So if the output does exist, then this transaction exists in the chain.
if (!existingCoin.IsSpent()) return TransactionError::ALREADY_IN_CHAIN;
}
bool fHaveMempool = mempool.exists(hashTx);
if (!fHaveMempool && !fHaveChain) {
// push to local node and sync with wallets
if (!mempool.exists(hashTx)) {
// Transaction is not already in the mempool. Submit it.
CValidationState state;
bool fMissingInputs;
if (!AcceptToMemoryPool(mempool, state, std::move(tx), &fMissingInputs,
@@ -46,24 +48,31 @@ TransactionError BroadcastTransaction(const CTransactionRef tx, std::string& err
err_string = FormatStateMessage(state);
return TransactionError::MEMPOOL_ERROR;
}
} else if (wait_callback) {
// If wallet is enabled, ensure that the wallet has been made aware
// of the new transaction prior to returning. This prevents a race
// where a user might call sendrawtransaction with a transaction
// to/from their wallet, immediately call some wallet RPC, and get
// a stale result because callbacks have not yet been processed.
}
// Transaction was accepted to the mempool.
if (wait_callback) {
// For transactions broadcast from outside the wallet, make sure
// that the wallet has been notified of the transaction before
// continuing.
//
// This prevents a race where a user might call sendrawtransaction
// with a transaction to/from their wallet, immediately call some
// wallet RPC, and get a stale result because callbacks have not
// yet been processed.
CallFunctionInValidationInterfaceQueue([&promise] {
promise.set_value();
});
callback_set = true;
}
} else if (fHaveChain) {
return TransactionError::ALREADY_IN_CHAIN;
}
} // cs_main
if (callback_set) {
// Wait until Validation Interface clients have been notified of the
// transaction entering the mempool.
promise.get_future().wait();
}