diff options
author | Russell Yanofsky <russ@yanofsky.org> | 2018-07-17 13:04:35 -0400 |
---|---|---|
committer | Russell Yanofsky <russ@yanofsky.org> | 2019-03-05 10:20:00 -0400 |
commit | b1b2b238928e7be044ad62cf1b222464907ece2c (patch) | |
tree | 50767a07bf5bdca1b6b4e2de761e90957febfaf0 | |
parent | 4e4d9e9f85eaf9c3bec48559bd4cad3e8a9333ca (diff) |
Remove use of CCoinsViewMemPool::GetCoin in wallet code
This commit does not change behavior.
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/interfaces/chain.cpp | 2 | ||||
-rw-r--r-- | src/interfaces/chain.h | 6 | ||||
-rw-r--r-- | src/node/coin.cpp | 22 | ||||
-rw-r--r-- | src/node/coin.h | 22 | ||||
-rw-r--r-- | src/rpc/rawtransaction.cpp | 44 |
6 files changed, 75 insertions, 23 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 14db963253..5131c6819a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 \ diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index f04d07d49d..7913c4473e 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -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); diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index 0936449e22..b4db9dda15 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -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; diff --git a/src/node/coin.cpp b/src/node/coin.cpp new file mode 100644 index 0000000000..bb98e63f3a --- /dev/null +++ b/src/node/coin.cpp @@ -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(); + } + } +} diff --git a/src/node/coin.h b/src/node/coin.h new file mode 100644 index 0000000000..eb95b75cfb --- /dev/null +++ b/src/node/coin.h @@ -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 diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index d19afaa8a1..1336740292 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -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; |