| 31 | } |
| 32 | |
| 33 | TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef tx, std::string& err_string, const CAmount& max_tx_fee, bool relay, bool wait_callback) |
| 34 | { |
| 35 | // BroadcastTransaction can be called by either sendrawtransaction RPC or the wallet. |
| 36 | // chainman, mempool and peerman are initialized before the RPC server and wallet are started |
| 37 | // and reset after the RPC sever and wallet are stopped. |
| 38 | assert(node.chainman); |
| 39 | assert(node.mempool); |
| 40 | assert(node.peerman); |
| 41 | |
| 42 | std::promise<void> promise; |
| 43 | uint256 txid = tx->GetHash(); |
| 44 | uint256 wtxid = tx->GetWitnessHash(); |
| 45 | bool callback_set = false; |
| 46 | |
| 47 | { |
| 48 | LOCK(cs_main); |
| 49 | |
| 50 | // If the transaction is already confirmed in the chain, don't do anything |
| 51 | // and return early. |
| 52 | CCoinsViewCache &view = node.chainman->ActiveChainstate().CoinsTip(); |
| 53 | for (size_t o = 0; o < tx->vout.size(); o++) { |
| 54 | const Coin& existingCoin = view.AccessCoin(COutPoint(txid, o)); |
| 55 | // IsSpent doesn't mean the coin is spent, it means the output doesn't exist. |
| 56 | // So if the output does exist, then this transaction exists in the chain. |
| 57 | if (!existingCoin.IsSpent()) return TransactionError::ALREADY_IN_CHAIN; |
| 58 | } |
| 59 | |
| 60 | if (auto mempool_tx = node.mempool->get(txid); mempool_tx) { |
| 61 | // There's already a transaction in the mempool with this txid. Don't |
| 62 | // try to submit this transaction to the mempool (since it'll be |
| 63 | // rejected as a TX_CONFLICT), but do attempt to reannounce the mempool |
| 64 | // transaction if relay=true. |
| 65 | // |
| 66 | // The mempool transaction may have the same or different witness (and |
| 67 | // wtxid) as this transaction. Use the mempool's wtxid for reannouncement. |
| 68 | wtxid = mempool_tx->GetWitnessHash(); |
| 69 | } else { |
| 70 | // Transaction is not already in the mempool. |
| 71 | if (max_tx_fee > 0) { |
| 72 | // First, call ATMP with test_accept and check the fee. If ATMP |
| 73 | // fails here, return error immediately. |
| 74 | const MempoolAcceptResult result = node.chainman->ProcessTransaction(tx, /*test_accept=*/ true); |
| 75 | if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) { |
| 76 | return HandleATMPError(result.m_state, err_string); |
| 77 | } else if (result.m_base_fees.value() > max_tx_fee) { |
| 78 | return TransactionError::MAX_FEE_EXCEEDED; |
| 79 | } |
| 80 | } |
| 81 | // Try to submit the transaction to the mempool. |
| 82 | const MempoolAcceptResult result = node.chainman->ProcessTransaction(tx, /*test_accept=*/ false); |
| 83 | if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) { |
| 84 | return HandleATMPError(result.m_state, err_string); |
| 85 | } |
| 86 | |
| 87 | // Transaction was accepted to the mempool. |
| 88 | |
| 89 | if (relay) { |
| 90 | // the mempool tracks locally submitted transactions to make a |
no test coverage detected