I discovered a race condition in sendrawtransaction. For details: see my comment in https://github.com/bitcoin/bitcoin/commit/1d46fe3327f6645fd79b442cd72ef422418c1a50.

If you send a raw transaction which has already been broadcasted, then you don't know whether you'll receive an RPC_TRANSACTION_ALREADY_IN_CHAIN exception, since you don't know whether a new block has just been received, which includes the transaction. There are use cases where such RPC_TRANSACTION_ALREADY_IN_CHAIN occurrences do not indicate an error; however, since this type of occurrence is very rare, developers are not likely to be aware of the possibility, and silence the exception. As a result, applications can potentially experience hard-to-diagnose, very rare errors.

I think the core of the problem is that sendrawtransaction tries to combine two use cases:
A: publish a transaction on the Bitcoin network
B: re-transmit an already known transaction to peers
RPC_TRANSACTION_ALREADY_IN_CHAIN might make sense for B, but for A (which is, IMHO, the primary use case) it is confusing.

#include <util/string.h>
#include <validation.h>
#include <validationinterface.h>
#include <numeric>
#include <stdint.h>
#include <univalue.h>
static void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
{
    
    
    
    
    
    TxToUniv(tx, uint256(), entry, true, RPCSerializationFlags());
    if (!hashBlock.IsNull()) {
        LOCK(cs_main);
        entry.pushKV("blockhash", hashBlock.GetHex());
        CBlockIndex* pindex = LookupBlockIndex(hashBlock);
        if (pindex) {
            if (::ChainActive().Contains(pindex)) {
                entry.pushKV("confirmations", 1 + ::ChainActive().Height() - pindex->nHeight);
                entry.pushKV("time", pindex->GetBlockTime());
                entry.pushKV("blocktime", pindex->GetBlockTime());
            }
            else
                entry.pushKV("confirmations", 0);
        }
    }
}
static RPCHelpMan getrawtransaction()