Skip to content

Commit 81cd958

Browse files
committed
Factor BroadcastTransaction out of sendrawtransaction
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/.
1 parent c734aaa commit 81cd958

File tree

4 files changed

+99
-65
lines changed

4 files changed

+99
-65
lines changed

src/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ BITCOIN_CORE_H = \
152152
netaddress.h \
153153
netbase.h \
154154
netmessagemaker.h \
155+
node/transaction.h \
155156
noui.h \
156157
optional.h \
157158
outputtype.h \
@@ -255,6 +256,7 @@ libbitcoin_server_a_SOURCES = \
255256
miner.cpp \
256257
net.cpp \
257258
net_processing.cpp \
259+
node/transaction.cpp \
258260
noui.cpp \
259261
outputtype.cpp \
260262
policy/fees.cpp \

src/node/transaction.cpp

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright (c) 2010 Satoshi Nakamoto
2+
// Copyright (c) 2009-2018 The Bitcoin Core developers
3+
// Distributed under the MIT software license, see the accompanying
4+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5+
6+
#include <consensus/validation.h>
7+
#include <net.h>
8+
#include <rpc/server.h>
9+
#include <txmempool.h>
10+
#include <validation.h>
11+
#include <validationinterface.h>
12+
#include <node/transaction.h>
13+
14+
#include <future>
15+
16+
uint256 BroadcastTransaction(const CTransactionRef tx, const bool allowhighfees) {
17+
std::promise<void> promise;
18+
const uint256& hashTx = tx->GetHash();
19+
20+
CAmount nMaxRawTxFee = maxTxFee;
21+
if (allowhighfees)
22+
nMaxRawTxFee = 0;
23+
24+
{ // cs_main scope
25+
LOCK(cs_main);
26+
CCoinsViewCache &view = *pcoinsTip;
27+
bool fHaveChain = false;
28+
for (size_t o = 0; !fHaveChain && o < tx->vout.size(); o++) {
29+
const Coin& existingCoin = view.AccessCoin(COutPoint(hashTx, o));
30+
fHaveChain = !existingCoin.IsSpent();
31+
}
32+
bool fHaveMempool = mempool.exists(hashTx);
33+
if (!fHaveMempool && !fHaveChain) {
34+
// push to local node and sync with wallets
35+
CValidationState state;
36+
bool fMissingInputs;
37+
if (!AcceptToMemoryPool(mempool, state, std::move(tx), &fMissingInputs,
38+
nullptr /* plTxnReplaced */, false /* bypass_limits */, nMaxRawTxFee)) {
39+
if (state.IsInvalid()) {
40+
throw JSONRPCError(RPC_TRANSACTION_REJECTED, FormatStateMessage(state));
41+
} else {
42+
if (fMissingInputs) {
43+
throw JSONRPCError(RPC_TRANSACTION_ERROR, "Missing inputs");
44+
}
45+
throw JSONRPCError(RPC_TRANSACTION_ERROR, FormatStateMessage(state));
46+
}
47+
} else {
48+
// If wallet is enabled, ensure that the wallet has been made aware
49+
// of the new transaction prior to returning. This prevents a race
50+
// where a user might call sendrawtransaction with a transaction
51+
// to/from their wallet, immediately call some wallet RPC, and get
52+
// a stale result because callbacks have not yet been processed.
53+
CallFunctionInValidationInterfaceQueue([&promise] {
54+
promise.set_value();
55+
});
56+
}
57+
} else if (fHaveChain) {
58+
throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain");
59+
} else {
60+
// Make sure we don't block forever if re-sending
61+
// a transaction already in mempool.
62+
promise.set_value();
63+
}
64+
65+
} // cs_main
66+
67+
promise.get_future().wait();
68+
69+
if(!g_connman)
70+
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
71+
72+
CInv inv(MSG_TX, hashTx);
73+
g_connman->ForEachNode([&inv](CNode* pnode)
74+
{
75+
pnode->PushInventory(inv);
76+
});
77+
78+
return hashTx;
79+
}

src/node/transaction.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright (c) 2017-2018 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#ifndef BITCOIN_NODE_TRANSACTION_H
6+
#define BITCOIN_NODE_TRANSACTION_H
7+
8+
#include <primitives/transaction.h>
9+
#include <uint256.h>
10+
11+
/** Broadcast a transaction */
12+
uint256 BroadcastTransaction(CTransactionRef tx, bool allowhighfees = false);
13+
14+
#endif // BITCOIN_NODE_TRANSACTION_H

src/rpc/rawtransaction.cpp

Lines changed: 4 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#include <key_io.h>
1414
#include <keystore.h>
1515
#include <merkleblock.h>
16-
#include <net.h>
16+
#include <node/transaction.h>
1717
#include <policy/policy.h>
1818
#include <policy/rbf.h>
1919
#include <primitives/transaction.h>
@@ -24,13 +24,11 @@
2424
#include <script/script_error.h>
2525
#include <script/sign.h>
2626
#include <script/standard.h>
27-
#include <txmempool.h>
2827
#include <uint256.h>
2928
#include <util/strencodings.h>
3029
#include <validation.h>
3130
#include <validationinterface.h>
3231

33-
#include <future>
3432
#include <stdint.h>
3533

3634
#include <univalue.h>
@@ -1041,76 +1039,17 @@ static UniValue sendrawtransaction(const JSONRPCRequest& request)
10411039
},
10421040
}.ToString());
10431041

1044-
std::promise<void> promise;
1045-
10461042
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL});
10471043

10481044
// parse hex string from parameter
10491045
CMutableTransaction mtx;
10501046
if (!DecodeHexTx(mtx, request.params[0].get_str()))
10511047
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
10521048
CTransactionRef tx(MakeTransactionRef(std::move(mtx)));
1053-
const uint256& hashTx = tx->GetHash();
1054-
1055-
CAmount nMaxRawTxFee = maxTxFee;
1056-
if (!request.params[1].isNull() && request.params[1].get_bool())
1057-
nMaxRawTxFee = 0;
1058-
1059-
{ // cs_main scope
1060-
LOCK(cs_main);
1061-
CCoinsViewCache &view = *pcoinsTip;
1062-
bool fHaveChain = false;
1063-
for (size_t o = 0; !fHaveChain && o < tx->vout.size(); o++) {
1064-
const Coin& existingCoin = view.AccessCoin(COutPoint(hashTx, o));
1065-
fHaveChain = !existingCoin.IsSpent();
1066-
}
1067-
bool fHaveMempool = mempool.exists(hashTx);
1068-
if (!fHaveMempool && !fHaveChain) {
1069-
// push to local node and sync with wallets
1070-
CValidationState state;
1071-
bool fMissingInputs;
1072-
if (!AcceptToMemoryPool(mempool, state, std::move(tx), &fMissingInputs,
1073-
nullptr /* plTxnReplaced */, false /* bypass_limits */, nMaxRawTxFee)) {
1074-
if (state.IsInvalid()) {
1075-
throw JSONRPCError(RPC_TRANSACTION_REJECTED, FormatStateMessage(state));
1076-
} else {
1077-
if (fMissingInputs) {
1078-
throw JSONRPCError(RPC_TRANSACTION_ERROR, "Missing inputs");
1079-
}
1080-
throw JSONRPCError(RPC_TRANSACTION_ERROR, FormatStateMessage(state));
1081-
}
1082-
} else {
1083-
// If wallet is enabled, ensure that the wallet has been made aware
1084-
// of the new transaction prior to returning. This prevents a race
1085-
// where a user might call sendrawtransaction with a transaction
1086-
// to/from their wallet, immediately call some wallet RPC, and get
1087-
// a stale result because callbacks have not yet been processed.
1088-
CallFunctionInValidationInterfaceQueue([&promise] {
1089-
promise.set_value();
1090-
});
1091-
}
1092-
} else if (fHaveChain) {
1093-
throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain");
1094-
} else {
1095-
// Make sure we don't block forever if re-sending
1096-
// a transaction already in mempool.
1097-
promise.set_value();
1098-
}
1099-
1100-
} // cs_main
1101-
1102-
promise.get_future().wait();
1103-
1104-
if(!g_connman)
1105-
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
1106-
1107-
CInv inv(MSG_TX, hashTx);
1108-
g_connman->ForEachNode([&inv](CNode* pnode)
1109-
{
1110-
pnode->PushInventory(inv);
1111-
});
11121049

1113-
return hashTx.GetHex();
1050+
bool allowhighfees = false;
1051+
if (!request.params[1].isNull()) allowhighfees = request.params[1].get_bool();
1052+
return BroadcastTransaction(tx, allowhighfees).GetHex();
11141053
}
11151054

11161055
static UniValue testmempoolaccept(const JSONRPCRequest& request)

0 commit comments

Comments
 (0)