Factor out a new BroadcastTransaction function, performing the core work of the sendrawtransaction rpc, so that it can be used from the GUI code. Move it from src/rpc/ to src/node/.pull/643/head
parent
c734aaa15d
commit
81cd958848
@ -0,0 +1,79 @@
|
||||
// Copyright (c) 2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2018 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <consensus/validation.h>
|
||||
#include <net.h>
|
||||
#include <rpc/server.h>
|
||||
#include <txmempool.h>
|
||||
#include <validation.h>
|
||||
#include <validationinterface.h>
|
||||
#include <node/transaction.h>
|
||||
|
||||
#include <future>
|
||||
|
||||
uint256 BroadcastTransaction(const CTransactionRef tx, const bool allowhighfees) {
|
||||
std::promise<void> promise;
|
||||
const uint256& hashTx = tx->GetHash();
|
||||
|
||||
CAmount nMaxRawTxFee = maxTxFee;
|
||||
if (allowhighfees)
|
||||
nMaxRawTxFee = 0;
|
||||
|
||||
{ // cs_main scope
|
||||
LOCK(cs_main);
|
||||
CCoinsViewCache &view = *pcoinsTip;
|
||||
bool fHaveChain = false;
|
||||
for (size_t o = 0; !fHaveChain && o < tx->vout.size(); o++) {
|
||||
const Coin& existingCoin = view.AccessCoin(COutPoint(hashTx, o));
|
||||
fHaveChain = !existingCoin.IsSpent();
|
||||
}
|
||||
bool fHaveMempool = mempool.exists(hashTx);
|
||||
if (!fHaveMempool && !fHaveChain) {
|
||||
// push to local node and sync with wallets
|
||||
CValidationState state;
|
||||
bool fMissingInputs;
|
||||
if (!AcceptToMemoryPool(mempool, state, std::move(tx), &fMissingInputs,
|
||||
nullptr /* plTxnReplaced */, false /* bypass_limits */, nMaxRawTxFee)) {
|
||||
if (state.IsInvalid()) {
|
||||
throw JSONRPCError(RPC_TRANSACTION_REJECTED, FormatStateMessage(state));
|
||||
} else {
|
||||
if (fMissingInputs) {
|
||||
throw JSONRPCError(RPC_TRANSACTION_ERROR, "Missing inputs");
|
||||
}
|
||||
throw JSONRPCError(RPC_TRANSACTION_ERROR, FormatStateMessage(state));
|
||||
}
|
||||
} else {
|
||||
// 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.
|
||||
CallFunctionInValidationInterfaceQueue([&promise] {
|
||||
promise.set_value();
|
||||
});
|
||||
}
|
||||
} else if (fHaveChain) {
|
||||
throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain");
|
||||
} else {
|
||||
// Make sure we don't block forever if re-sending
|
||||
// a transaction already in mempool.
|
||||
promise.set_value();
|
||||
}
|
||||
|
||||
} // cs_main
|
||||
|
||||
promise.get_future().wait();
|
||||
|
||||
if(!g_connman)
|
||||
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
|
||||
|
||||
CInv inv(MSG_TX, hashTx);
|
||||
g_connman->ForEachNode([&inv](CNode* pnode)
|
||||
{
|
||||
pnode->PushInventory(inv);
|
||||
});
|
||||
|
||||
return hashTx;
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
// Copyright (c) 2017-2018 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_NODE_TRANSACTION_H
|
||||
#define BITCOIN_NODE_TRANSACTION_H
|
||||
|
||||
#include <primitives/transaction.h>
|
||||
#include <uint256.h>
|
||||
|
||||
/** Broadcast a transaction */
|
||||
uint256 BroadcastTransaction(CTransactionRef tx, bool allowhighfees = false);
|
||||
|
||||
#endif // BITCOIN_NODE_TRANSACTION_H
|
Loading…
Reference in new issue