Skip to content

Commit b1b2b23

Browse files
committed
Remove use of CCoinsViewMemPool::GetCoin in wallet code
This commit does not change behavior.
1 parent 4e4d9e9 commit b1b2b23

File tree

6 files changed

+75
-23
lines changed

6 files changed

+75
-23
lines changed

src/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ BITCOIN_CORE_H = \
154154
netaddress.h \
155155
netbase.h \
156156
netmessagemaker.h \
157+
node/coin.h \
157158
node/transaction.h \
158159
noui.h \
159160
optional.h \
@@ -262,6 +263,7 @@ libbitcoin_server_a_SOURCES = \
262263
miner.cpp \
263264
net.cpp \
264265
net_processing.cpp \
266+
node/coin.cpp \
265267
node/transaction.cpp \
266268
noui.cpp \
267269
outputtype.cpp \

src/interfaces/chain.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <interfaces/handler.h>
1010
#include <interfaces/wallet.h>
1111
#include <net.h>
12+
#include <node/coin.h>
1213
#include <policy/fees.h>
1314
#include <policy/policy.h>
1415
#include <policy/rbf.h>
@@ -287,6 +288,7 @@ class ChainImpl : public Chain
287288
}
288289
return true;
289290
}
291+
void findCoins(std::map<COutPoint, Coin>& coins) override { return FindCoins(coins); }
290292
double guessVerificationProgress(const uint256& block_hash) override
291293
{
292294
LOCK(cs_main);

src/interfaces/chain.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class CFeeRate;
1919
class CRPCCommand;
2020
class CScheduler;
2121
class CValidationState;
22+
class Coin;
2223
class uint256;
2324
enum class RBFTransactionState;
2425
struct CBlockLocator;
@@ -168,6 +169,11 @@ class Chain
168169
int64_t* time = nullptr,
169170
int64_t* max_time = nullptr) = 0;
170171

172+
//! Look up unspent output information. Returns coins in the mempool and in
173+
//! the current chain UTXO set. Iterates through all the keys in the map and
174+
//! populates the values.
175+
virtual void findCoins(std::map<COutPoint, Coin>& coins) = 0;
176+
171177
//! Estimate fraction of total transactions verified if blocks up to
172178
//! the specified block hash are verified.
173179
virtual double guessVerificationProgress(const uint256& block_hash) = 0;

src/node/coin.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright (c) 2019 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+
#include <node/coin.h>
6+
7+
#include <txmempool.h>
8+
#include <validation.h>
9+
10+
void FindCoins(std::map<COutPoint, Coin>& coins)
11+
{
12+
LOCK2(cs_main, ::mempool.cs);
13+
assert(pcoinsTip);
14+
CCoinsViewCache& chain_view = *::pcoinsTip;
15+
CCoinsViewMemPool mempool_view(&chain_view, ::mempool);
16+
for (auto& coin : coins) {
17+
if (!mempool_view.GetCoin(coin.first, coin.second)) {
18+
// Either the coin is not in the CCoinsViewCache or is spent. Clear it.
19+
coin.second.Clear();
20+
}
21+
}
22+
}

src/node/coin.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright (c) 2019 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_COIN_H
6+
#define BITCOIN_NODE_COIN_H
7+
8+
#include <map>
9+
10+
class COutPoint;
11+
class Coin;
12+
13+
/**
14+
* Look up unspent output information. Returns coins in the mempool and in the
15+
* current chain UTXO set. Iterates through all the keys in the map and
16+
* populates the values.
17+
*
18+
* @param[in,out] coins map to fill
19+
*/
20+
void FindCoins(std::map<COutPoint, Coin>& coins);
21+
22+
#endif // BITCOIN_NODE_COIN_H

src/rpc/rawtransaction.cpp

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <core_io.h>
1212
#include <index/txindex.h>
1313
#include <init.h>
14+
#include <interfaces/chain.h>
1415
#include <key_io.h>
1516
#include <keystore.h>
1617
#include <merkleblock.h>
@@ -790,23 +791,20 @@ static UniValue combinerawtransaction(const JSONRPCRequest& request)
790791
return EncodeHexTx(CTransaction(mergedTx));
791792
}
792793

794+
// TODO(https://github.com/bitcoin/bitcoin/pull/10973#discussion_r267084237):
795+
// This function is called from both wallet and node rpcs
796+
// (signrawtransactionwithwallet and signrawtransactionwithkey). It should be
797+
// moved to a util file so wallet code doesn't need to link against node code.
798+
// Also the dependency on interfaces::Chain should be removed, so
799+
// signrawtransactionwithkey doesn't need access to a Chain instance.
793800
UniValue SignTransaction(interfaces::Chain& chain, CMutableTransaction& mtx, const UniValue& prevTxsUnival, CBasicKeyStore *keystore, bool is_temp_keystore, const UniValue& hashType)
794801
{
795802
// Fetch previous transactions (inputs):
796-
CCoinsView viewDummy;
797-
CCoinsViewCache view(&viewDummy);
798-
{
799-
LOCK2(cs_main, mempool.cs);
800-
CCoinsViewCache &viewChain = *pcoinsTip;
801-
CCoinsViewMemPool viewMempool(&viewChain, mempool);
802-
view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view
803-
804-
for (const CTxIn& txin : mtx.vin) {
805-
view.AccessCoin(txin.prevout); // Load entries from viewChain into view; can fail.
806-
}
807-
808-
view.SetBackend(viewDummy); // switch back to avoid locking mempool for too long
803+
std::map<COutPoint, Coin> coins;
804+
for (const CTxIn& txin : mtx.vin) {
805+
coins[txin.prevout]; // Create empty map entry keyed by prevout.
809806
}
807+
chain.findCoins(coins);
810808

811809
// Add previous txouts given in the RPC call:
812810
if (!prevTxsUnival.isNull()) {
@@ -838,10 +836,10 @@ UniValue SignTransaction(interfaces::Chain& chain, CMutableTransaction& mtx, con
838836
CScript scriptPubKey(pkData.begin(), pkData.end());
839837

840838
{
841-
const Coin& coin = view.AccessCoin(out);
842-
if (!coin.IsSpent() && coin.out.scriptPubKey != scriptPubKey) {
839+
auto coin = coins.find(out);
840+
if (coin != coins.end() && !coin->second.IsSpent() && coin->second.out.scriptPubKey != scriptPubKey) {
843841
std::string err("Previous output scriptPubKey mismatch:\n");
844-
err = err + ScriptToAsmStr(coin.out.scriptPubKey) + "\nvs:\n"+
842+
err = err + ScriptToAsmStr(coin->second.out.scriptPubKey) + "\nvs:\n"+
845843
ScriptToAsmStr(scriptPubKey);
846844
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err);
847845
}
@@ -852,7 +850,7 @@ UniValue SignTransaction(interfaces::Chain& chain, CMutableTransaction& mtx, con
852850
newcoin.out.nValue = AmountFromValue(find_value(prevOut, "amount"));
853851
}
854852
newcoin.nHeight = 1;
855-
view.AddCoin(out, std::move(newcoin), true);
853+
coins[out] = std::move(newcoin);
856854
}
857855

858856
// if redeemScript and private keys were given, add redeemScript to the keystore so it can be signed
@@ -896,15 +894,15 @@ UniValue SignTransaction(interfaces::Chain& chain, CMutableTransaction& mtx, con
896894
// Sign what we can:
897895
for (unsigned int i = 0; i < mtx.vin.size(); i++) {
898896
CTxIn& txin = mtx.vin[i];
899-
const Coin& coin = view.AccessCoin(txin.prevout);
900-
if (coin.IsSpent()) {
897+
auto coin = coins.find(txin.prevout);
898+
if (coin == coins.end() || coin->second.IsSpent()) {
901899
TxInErrorToJSON(txin, vErrors, "Input not found or already spent");
902900
continue;
903901
}
904-
const CScript& prevPubKey = coin.out.scriptPubKey;
905-
const CAmount& amount = coin.out.nValue;
902+
const CScript& prevPubKey = coin->second.out.scriptPubKey;
903+
const CAmount& amount = coin->second.out.nValue;
906904

907-
SignatureData sigdata = DataFromTransaction(mtx, i, coin.out);
905+
SignatureData sigdata = DataFromTransaction(mtx, i, coin->second.out);
908906
// Only sign SIGHASH_SINGLE if there's a corresponding output:
909907
if (!fHashSingle || (i < mtx.vout.size())) {
910908
ProduceSignature(*keystore, MutableTransactionSignatureCreator(&mtx, i, amount, nHashType), prevPubKey, sigdata);
@@ -914,7 +912,7 @@ UniValue SignTransaction(interfaces::Chain& chain, CMutableTransaction& mtx, con
914912

915913
// amount must be specified for valid segwit signature
916914
if (amount == MAX_MONEY && !txin.scriptWitness.IsNull()) {
917-
throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing amount for %s", coin.out.ToString()));
915+
throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing amount for %s", coin->second.out.ToString()));
918916
}
919917

920918
ScriptError serror = SCRIPT_ERR_OK;

0 commit comments

Comments
 (0)