Remove use of CCoinsViewMemPool::GetCoin in wallet code

This commit does not change behavior.
This commit is contained in:
Russell Yanofsky 2018-07-17 13:04:35 -04:00
parent 4e4d9e9f85
commit b1b2b23892
6 changed files with 75 additions and 23 deletions

View file

@ -154,6 +154,7 @@ BITCOIN_CORE_H = \
netaddress.h \
netbase.h \
netmessagemaker.h \
node/coin.h \
node/transaction.h \
noui.h \
optional.h \
@ -262,6 +263,7 @@ libbitcoin_server_a_SOURCES = \
miner.cpp \
net.cpp \
net_processing.cpp \
node/coin.cpp \
node/transaction.cpp \
noui.cpp \
outputtype.cpp \

View file

@ -9,6 +9,7 @@
#include <interfaces/handler.h>
#include <interfaces/wallet.h>
#include <net.h>
#include <node/coin.h>
#include <policy/fees.h>
#include <policy/policy.h>
#include <policy/rbf.h>
@ -287,6 +288,7 @@ public:
}
return true;
}
void findCoins(std::map<COutPoint, Coin>& coins) override { return FindCoins(coins); }
double guessVerificationProgress(const uint256& block_hash) override
{
LOCK(cs_main);

View file

@ -19,6 +19,7 @@ class CFeeRate;
class CRPCCommand;
class CScheduler;
class CValidationState;
class Coin;
class uint256;
enum class RBFTransactionState;
struct CBlockLocator;
@ -168,6 +169,11 @@ public:
int64_t* time = nullptr,
int64_t* max_time = nullptr) = 0;
//! Look up unspent output information. Returns coins in the mempool and in
//! the current chain UTXO set. Iterates through all the keys in the map and
//! populates the values.
virtual void findCoins(std::map<COutPoint, Coin>& coins) = 0;
//! Estimate fraction of total transactions verified if blocks up to
//! the specified block hash are verified.
virtual double guessVerificationProgress(const uint256& block_hash) = 0;

22
src/node/coin.cpp Normal file
View file

@ -0,0 +1,22 @@
// Copyright (c) 2019 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 <node/coin.h>
#include <txmempool.h>
#include <validation.h>
void FindCoins(std::map<COutPoint, Coin>& coins)
{
LOCK2(cs_main, ::mempool.cs);
assert(pcoinsTip);
CCoinsViewCache& chain_view = *::pcoinsTip;
CCoinsViewMemPool mempool_view(&chain_view, ::mempool);
for (auto& coin : coins) {
if (!mempool_view.GetCoin(coin.first, coin.second)) {
// Either the coin is not in the CCoinsViewCache or is spent. Clear it.
coin.second.Clear();
}
}
}

22
src/node/coin.h Normal file
View file

@ -0,0 +1,22 @@
// Copyright (c) 2019 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_COIN_H
#define BITCOIN_NODE_COIN_H
#include <map>
class COutPoint;
class Coin;
/**
* Look up unspent output information. Returns coins in the mempool and in the
* current chain UTXO set. Iterates through all the keys in the map and
* populates the values.
*
* @param[in,out] coins map to fill
*/
void FindCoins(std::map<COutPoint, Coin>& coins);
#endif // BITCOIN_NODE_COIN_H

View file

@ -11,6 +11,7 @@
#include <core_io.h>
#include <index/txindex.h>
#include <init.h>
#include <interfaces/chain.h>
#include <key_io.h>
#include <keystore.h>
#include <merkleblock.h>
@ -790,23 +791,20 @@ static UniValue combinerawtransaction(const JSONRPCRequest& request)
return EncodeHexTx(CTransaction(mergedTx));
}
// TODO(https://github.com/bitcoin/bitcoin/pull/10973#discussion_r267084237):
// This function is called from both wallet and node rpcs
// (signrawtransactionwithwallet and signrawtransactionwithkey). It should be
// moved to a util file so wallet code doesn't need to link against node code.
// Also the dependency on interfaces::Chain should be removed, so
// signrawtransactionwithkey doesn't need access to a Chain instance.
UniValue SignTransaction(interfaces::Chain& chain, CMutableTransaction& mtx, const UniValue& prevTxsUnival, CBasicKeyStore *keystore, bool is_temp_keystore, const UniValue& hashType)
{
// Fetch previous transactions (inputs):
CCoinsView viewDummy;
CCoinsViewCache view(&viewDummy);
{
LOCK2(cs_main, mempool.cs);
CCoinsViewCache &viewChain = *pcoinsTip;
CCoinsViewMemPool viewMempool(&viewChain, mempool);
view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view
for (const CTxIn& txin : mtx.vin) {
view.AccessCoin(txin.prevout); // Load entries from viewChain into view; can fail.
}
view.SetBackend(viewDummy); // switch back to avoid locking mempool for too long
std::map<COutPoint, Coin> coins;
for (const CTxIn& txin : mtx.vin) {
coins[txin.prevout]; // Create empty map entry keyed by prevout.
}
chain.findCoins(coins);
// Add previous txouts given in the RPC call:
if (!prevTxsUnival.isNull()) {
@ -838,10 +836,10 @@ UniValue SignTransaction(interfaces::Chain& chain, CMutableTransaction& mtx, con
CScript scriptPubKey(pkData.begin(), pkData.end());
{
const Coin& coin = view.AccessCoin(out);
if (!coin.IsSpent() && coin.out.scriptPubKey != scriptPubKey) {
auto coin = coins.find(out);
if (coin != coins.end() && !coin->second.IsSpent() && coin->second.out.scriptPubKey != scriptPubKey) {
std::string err("Previous output scriptPubKey mismatch:\n");
err = err + ScriptToAsmStr(coin.out.scriptPubKey) + "\nvs:\n"+
err = err + ScriptToAsmStr(coin->second.out.scriptPubKey) + "\nvs:\n"+
ScriptToAsmStr(scriptPubKey);
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err);
}
@ -852,7 +850,7 @@ UniValue SignTransaction(interfaces::Chain& chain, CMutableTransaction& mtx, con
newcoin.out.nValue = AmountFromValue(find_value(prevOut, "amount"));
}
newcoin.nHeight = 1;
view.AddCoin(out, std::move(newcoin), true);
coins[out] = std::move(newcoin);
}
// 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
// Sign what we can:
for (unsigned int i = 0; i < mtx.vin.size(); i++) {
CTxIn& txin = mtx.vin[i];
const Coin& coin = view.AccessCoin(txin.prevout);
if (coin.IsSpent()) {
auto coin = coins.find(txin.prevout);
if (coin == coins.end() || coin->second.IsSpent()) {
TxInErrorToJSON(txin, vErrors, "Input not found or already spent");
continue;
}
const CScript& prevPubKey = coin.out.scriptPubKey;
const CAmount& amount = coin.out.nValue;
const CScript& prevPubKey = coin->second.out.scriptPubKey;
const CAmount& amount = coin->second.out.nValue;
SignatureData sigdata = DataFromTransaction(mtx, i, coin.out);
SignatureData sigdata = DataFromTransaction(mtx, i, coin->second.out);
// Only sign SIGHASH_SINGLE if there's a corresponding output:
if (!fHashSingle || (i < mtx.vout.size())) {
ProduceSignature(*keystore, MutableTransactionSignatureCreator(&mtx, i, amount, nHashType), prevPubKey, sigdata);
@ -914,7 +912,7 @@ UniValue SignTransaction(interfaces::Chain& chain, CMutableTransaction& mtx, con
// amount must be specified for valid segwit signature
if (amount == MAX_MONEY && !txin.scriptWitness.IsNull()) {
throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing amount for %s", coin.out.ToString()));
throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing amount for %s", coin->second.out.ToString()));
}
ScriptError serror = SCRIPT_ERR_OK;