diff options
Diffstat (limited to 'src')
85 files changed, 433 insertions, 456 deletions
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 367801dd78..499e7ea926 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -25,7 +25,6 @@ #include <stdio.h> #include <boost/algorithm/string.hpp> -#include <boost/assign/list_of.hpp> static bool fCreateBlank; static std::map<std::string,UniValue> registers; @@ -568,7 +567,11 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr) if (!prevOut.isObject()) throw std::runtime_error("expected prevtxs internal object"); - std::map<std::string,UniValue::VType> types = boost::assign::map_list_of("txid", UniValue::VSTR)("vout",UniValue::VNUM)("scriptPubKey",UniValue::VSTR); + std::map<std::string, UniValue::VType> types = { + {"txid", UniValue::VSTR}, + {"vout", UniValue::VNUM}, + {"scriptPubKey", UniValue::VSTR}, + }; if (!prevOut.checkObject(types)) throw std::runtime_error("prevtxs internal object typecheck fail"); diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 5922e45801..374678310c 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -20,7 +20,6 @@ #include "httprpc.h" #include "utilstrencodings.h" -#include <boost/algorithm/string/predicate.hpp> #include <boost/thread.hpp> #include <stdio.h> diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 04a2f680fa..3b42c5fb23 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -12,8 +12,6 @@ #include <assert.h> -#include <boost/assign/list_of.hpp> - #include "chainparamsseeds.h" static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesisOutputScript, uint32_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward) @@ -136,8 +134,8 @@ public: base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,0); base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,5); base58Prefixes[SECRET_KEY] = std::vector<unsigned char>(1,128); - base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x88)(0xB2)(0x1E).convert_to_container<std::vector<unsigned char> >(); - base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x88)(0xAD)(0xE4).convert_to_container<std::vector<unsigned char> >(); + base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x88, 0xB2, 0x1E}; + base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x88, 0xAD, 0xE4}; vFixedSeeds = std::vector<SeedSpec6>(pnSeed6_main, pnSeed6_main + ARRAYLEN(pnSeed6_main)); @@ -146,20 +144,21 @@ public: fMineBlocksOnDemand = false; checkpointData = (CCheckpointData) { - boost::assign::map_list_of - ( 11111, uint256S("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d")) - ( 33333, uint256S("0x000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6")) - ( 74000, uint256S("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20")) - (105000, uint256S("0x00000000000291ce28027faea320c8d2b054b2e0fe44a773f3eefb151d6bdc97")) - (134444, uint256S("0x00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe")) - (168000, uint256S("0x000000000000099e61ea72015e79632f216fe6cb33d7899acb35b75c8303b763")) - (193000, uint256S("0x000000000000059f452a5f7340de6682a977387c17010ff6e6c3bd83ca8b1317")) - (210000, uint256S("0x000000000000048b95347e83192f69cf0366076336c639f9b7228e9ba171342e")) - (216116, uint256S("0x00000000000001b4f4b433e81ee46494af945cf96014816a4e2370f11b23df4e")) - (225430, uint256S("0x00000000000001c108384350f74090433e7fcf79a606b8e797f065b130575932")) - (250000, uint256S("0x000000000000003887df1f29024b06fc2200b55f8af8f35453d7be294df2d214")) - (279000, uint256S("0x0000000000000001ae8c72a0b0c301f67e3afca10e819efa9041e458e9bd7e40")) - (295000, uint256S("0x00000000000000004d9b4ef50f0f9d686fd69db2e03af35a100370c64632a983")) + { + { 11111, uint256S("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d")}, + { 33333, uint256S("0x000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6")}, + { 74000, uint256S("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20")}, + {105000, uint256S("0x00000000000291ce28027faea320c8d2b054b2e0fe44a773f3eefb151d6bdc97")}, + {134444, uint256S("0x00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe")}, + {168000, uint256S("0x000000000000099e61ea72015e79632f216fe6cb33d7899acb35b75c8303b763")}, + {193000, uint256S("0x000000000000059f452a5f7340de6682a977387c17010ff6e6c3bd83ca8b1317")}, + {210000, uint256S("0x000000000000048b95347e83192f69cf0366076336c639f9b7228e9ba171342e")}, + {216116, uint256S("0x00000000000001b4f4b433e81ee46494af945cf96014816a4e2370f11b23df4e")}, + {225430, uint256S("0x00000000000001c108384350f74090433e7fcf79a606b8e797f065b130575932")}, + {250000, uint256S("0x000000000000003887df1f29024b06fc2200b55f8af8f35453d7be294df2d214")}, + {279000, uint256S("0x0000000000000001ae8c72a0b0c301f67e3afca10e819efa9041e458e9bd7e40")}, + {295000, uint256S("0x00000000000000004d9b4ef50f0f9d686fd69db2e03af35a100370c64632a983")}, + } }; chainTxData = ChainTxData{ @@ -234,8 +233,8 @@ public: base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,111); base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,196); base58Prefixes[SECRET_KEY] = std::vector<unsigned char>(1,239); - base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container<std::vector<unsigned char> >(); - base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94).convert_to_container<std::vector<unsigned char> >(); + base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x35, 0x87, 0xCF}; + base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x35, 0x83, 0x94}; vFixedSeeds = std::vector<SeedSpec6>(pnSeed6_test, pnSeed6_test + ARRAYLEN(pnSeed6_test)); @@ -245,8 +244,9 @@ public: checkpointData = (CCheckpointData) { - boost::assign::map_list_of - ( 546, uint256S("000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70")), + { + {546, uint256S("000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70")}, + } }; chainTxData = ChainTxData{ @@ -313,9 +313,10 @@ public: fRequireStandard = false; fMineBlocksOnDemand = true; - checkpointData = (CCheckpointData){ - boost::assign::map_list_of - ( 0, uint256S("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206")) + checkpointData = (CCheckpointData) { + { + {0, uint256S("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206")}, + } }; chainTxData = ChainTxData{ @@ -327,8 +328,8 @@ public: base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,111); base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,196); base58Prefixes[SECRET_KEY] = std::vector<unsigned char>(1,239); - base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container<std::vector<unsigned char> >(); - base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94).convert_to_container<std::vector<unsigned char> >(); + base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x35, 0x87, 0xCF}; + base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x35, 0x83, 0x94}; } }; diff --git a/src/checkqueue.h b/src/checkqueue.h index 63c104c02a..08017ff799 100644 --- a/src/checkqueue.h +++ b/src/checkqueue.h @@ -12,7 +12,6 @@ #include <boost/foreach.hpp> #include <boost/thread/condition_variable.hpp> -#include <boost/thread/locks.hpp> #include <boost/thread/mutex.hpp> template <typename T> diff --git a/src/coins.h b/src/coins.h index 476db8f37c..dc3210b8ac 100644 --- a/src/coins.h +++ b/src/coins.h @@ -17,7 +17,6 @@ #include <assert.h> #include <stdint.h> -#include <boost/foreach.hpp> #include <unordered_map> /** @@ -207,11 +206,14 @@ public: CCoinsViewCache(CCoinsView *baseIn); // Standard CCoinsView methods - bool GetCoin(const COutPoint &outpoint, Coin &coin) const; - bool HaveCoin(const COutPoint &outpoint) const; - uint256 GetBestBlock() const; + bool GetCoin(const COutPoint &outpoint, Coin &coin) const override; + bool HaveCoin(const COutPoint &outpoint) const override; + uint256 GetBestBlock() const override; void SetBestBlock(const uint256 &hashBlock); - bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock); + bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override; + CCoinsViewCursor* Cursor() const override { + throw std::logic_error("CCoinsViewCache cursor iteration not supported."); + } /** * Check if we have the given utxo already loaded in this cache. diff --git a/src/consensus/validation.h b/src/consensus/validation.h index 5a7d7f11a9..8fc3ef1b66 100644 --- a/src/consensus/validation.h +++ b/src/consensus/validation.h @@ -14,7 +14,7 @@ static const unsigned char REJECT_INVALID = 0x10; static const unsigned char REJECT_OBSOLETE = 0x11; static const unsigned char REJECT_DUPLICATE = 0x12; static const unsigned char REJECT_NONSTANDARD = 0x40; -static const unsigned char REJECT_DUST = 0x41; +// static const unsigned char REJECT_DUST = 0x41; // part of BIP 61 static const unsigned char REJECT_INSUFFICIENTFEE = 0x42; static const unsigned char REJECT_CHECKPOINT = 0x43; diff --git a/src/core_read.cpp b/src/core_read.cpp index a8d667e3bc..dd9b5726a3 100644 --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -18,7 +18,6 @@ #include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/split.hpp> -#include <boost/assign/list_of.hpp> CScript ParseScript(const std::string& s) { @@ -88,10 +87,32 @@ CScript ParseScript(const std::string& s) return result; } +// Check that all of the input and output scripts of a transaction contains valid opcodes +bool CheckTxScriptsSanity(const CMutableTransaction& tx) +{ + // Check input scripts for non-coinbase txs + if (!CTransaction(tx).IsCoinBase()) { + for (unsigned int i = 0; i < tx.vin.size(); i++) { + if (!tx.vin[i].scriptSig.HasValidOps() || tx.vin[i].scriptSig.size() > MAX_SCRIPT_SIZE) { + return false; + } + } + } + // Check output scripts + for (unsigned int i = 0; i < tx.vout.size(); i++) { + if (!tx.vout[i].scriptPubKey.HasValidOps() || tx.vout[i].scriptPubKey.size() > MAX_SCRIPT_SIZE) { + return false; + } + } + + return true; +} + bool DecodeHexTx(CMutableTransaction& tx, const std::string& strHexTx, bool fTryNoWitness) { - if (!IsHex(strHexTx)) + if (!IsHex(strHexTx)) { return false; + } std::vector<unsigned char> txData(ParseHex(strHexTx)); @@ -99,7 +120,7 @@ bool DecodeHexTx(CMutableTransaction& tx, const std::string& strHexTx, bool fTry CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS); try { ssData >> tx; - if (ssData.eof()) { + if (ssData.eof() && CheckTxScriptsSanity(tx)) { return true; } } @@ -111,8 +132,9 @@ bool DecodeHexTx(CMutableTransaction& tx, const std::string& strHexTx, bool fTry CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); try { ssData >> tx; - if (!ssData.empty()) + if (!ssData.empty()) { return false; + } } catch (const std::exception&) { return false; diff --git a/src/core_write.cpp b/src/core_write.cpp index d116e617ee..178519daf1 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -15,7 +15,6 @@ #include "utilmoneystr.h" #include "utilstrencodings.h" -#include <boost/assign/list_of.hpp> #include <boost/foreach.hpp> std::string FormatScript(const CScript& script) @@ -53,15 +52,14 @@ std::string FormatScript(const CScript& script) return ret.substr(0, ret.size() - 1); } -const std::map<unsigned char, std::string> mapSigHashTypes = - boost::assign::map_list_of - (static_cast<unsigned char>(SIGHASH_ALL), std::string("ALL")) - (static_cast<unsigned char>(SIGHASH_ALL|SIGHASH_ANYONECANPAY), std::string("ALL|ANYONECANPAY")) - (static_cast<unsigned char>(SIGHASH_NONE), std::string("NONE")) - (static_cast<unsigned char>(SIGHASH_NONE|SIGHASH_ANYONECANPAY), std::string("NONE|ANYONECANPAY")) - (static_cast<unsigned char>(SIGHASH_SINGLE), std::string("SINGLE")) - (static_cast<unsigned char>(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY), std::string("SINGLE|ANYONECANPAY")) - ; +const std::map<unsigned char, std::string> mapSigHashTypes = { + {static_cast<unsigned char>(SIGHASH_ALL), std::string("ALL")}, + {static_cast<unsigned char>(SIGHASH_ALL|SIGHASH_ANYONECANPAY), std::string("ALL|ANYONECANPAY")}, + {static_cast<unsigned char>(SIGHASH_NONE), std::string("NONE")}, + {static_cast<unsigned char>(SIGHASH_NONE|SIGHASH_ANYONECANPAY), std::string("NONE|ANYONECANPAY")}, + {static_cast<unsigned char>(SIGHASH_SINGLE), std::string("SINGLE")}, + {static_cast<unsigned char>(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY), std::string("SINGLE|ANYONECANPAY")}, +}; /** * Create the assembly string representation of a CScript object. diff --git a/src/crypto/aes.cpp b/src/crypto/aes.cpp index 1d469d0fb4..5e70d25eee 100644 --- a/src/crypto/aes.cpp +++ b/src/crypto/aes.cpp @@ -112,7 +112,6 @@ static int CBCEncrypt(const T& enc, const unsigned char iv[AES_BLOCKSIZE], const template <typename T> static int CBCDecrypt(const T& dec, const unsigned char iv[AES_BLOCKSIZE], const unsigned char* data, int size, bool pad, unsigned char* out) { - unsigned char padsize = 0; int written = 0; bool fail = false; const unsigned char* prev = iv; @@ -136,7 +135,7 @@ static int CBCDecrypt(const T& dec, const unsigned char iv[AES_BLOCKSIZE], const if (pad) { // If used, padding size is the value of the last decrypted byte. For // it to be valid, It must be between 1 and AES_BLOCKSIZE. - padsize = *--out; + unsigned char padsize = *--out; fail = !padsize | (padsize > AES_BLOCKSIZE); // If not well-formed, treat it as though there's no padding. diff --git a/src/fs.cpp b/src/fs.cpp index 6f2b768de3..a5e12f1cfc 100644 --- a/src/fs.cpp +++ b/src/fs.cpp @@ -1,7 +1,5 @@ #include "fs.h" -#include <boost/filesystem.hpp> - namespace fsbridge { FILE *fopen(const fs::path& p, const char *mode) diff --git a/src/httprpc.cpp b/src/httprpc.cpp index 5ab6d8d732..9e0bcd7a00 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -16,7 +16,6 @@ #include "ui_interface.h" #include "crypto/hmac_sha256.h" #include <stdio.h> -#include "utilstrencodings.h" #include <boost/algorithm/string.hpp> // boost::trim #include <boost/foreach.hpp> //BOOST_FOREACH diff --git a/src/httprpc.h b/src/httprpc.h index d354457188..a89a8f0fbf 100644 --- a/src/httprpc.h +++ b/src/httprpc.h @@ -8,8 +8,6 @@ #include <string> #include <map> -class HTTPRequest; - /** Start HTTP RPC subsystem. * Precondition; HTTP and RPC has been started. */ diff --git a/src/init.cpp b/src/init.cpp index 04d1280c92..56d0bd9b0e 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -55,7 +55,6 @@ #endif #include <boost/algorithm/string/classification.hpp> -#include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/split.hpp> #include <boost/bind.hpp> @@ -162,7 +161,6 @@ public: // Writes do not need similar protection, as failure to write is handled by the caller. }; -static CCoinsViewDB *pcoinsdbview = NULL; static CCoinsViewErrorCatcher *pcoinscatcher = NULL; static std::unique_ptr<ECCVerifyHandle> globalVerifyHandle; @@ -198,8 +196,9 @@ void Shutdown() StopRPC(); StopHTTPServer(); #ifdef ENABLE_WALLET - if (pwalletMain) - pwalletMain->Flush(false); + for (CWalletRef pwallet : vpwallets) { + pwallet->Flush(false); + } #endif MapPort(false); UnregisterValidationInterface(peerLogic.get()); @@ -239,8 +238,9 @@ void Shutdown() pblocktree = NULL; } #ifdef ENABLE_WALLET - if (pwalletMain) - pwalletMain->Flush(true); + for (CWalletRef pwallet : vpwallets) { + pwallet->Flush(true); + } #endif #if ENABLE_ZMQ @@ -260,8 +260,10 @@ void Shutdown() #endif UnregisterAllValidationInterfaces(); #ifdef ENABLE_WALLET - delete pwalletMain; - pwalletMain = NULL; + for (CWalletRef pwallet : vpwallets) { + delete pwallet; + } + vpwallets.clear(); #endif globalVerifyHandle.reset(); ECC_Stop(); @@ -1673,8 +1675,9 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) uiInterface.InitMessage(_("Done loading")); #ifdef ENABLE_WALLET - if (pwalletMain) - pwalletMain->postInitProcess(scheduler); + for (CWalletRef pwallet : vpwallets) { + pwallet->postInitProcess(scheduler); + } #endif return !fRequestShutdown; diff --git a/src/keystore.cpp b/src/keystore.cpp index b17567e99b..8454175ca8 100644 --- a/src/keystore.cpp +++ b/src/keystore.cpp @@ -9,8 +9,6 @@ #include "pubkey.h" #include "util.h" -#include <boost/foreach.hpp> - bool CKeyStore::AddKey(const CKey &key) { return AddKeyPubKey(key, key.GetPubKey()); } diff --git a/src/keystore.h b/src/keystore.h index d9290722e1..a2621f2de4 100644 --- a/src/keystore.h +++ b/src/keystore.h @@ -13,7 +13,6 @@ #include "sync.h" #include <boost/signals2/signal.hpp> -#include <boost/variant.hpp> /** A virtual base class for key stores */ class CKeyStore diff --git a/src/memusage.h b/src/memusage.h index b69acafffd..710120d285 100644 --- a/src/memusage.h +++ b/src/memusage.h @@ -16,8 +16,6 @@ #include <unordered_set> #include <boost/foreach.hpp> -#include <boost/unordered_set.hpp> -#include <boost/unordered_map.hpp> namespace memusage { @@ -148,8 +146,6 @@ static inline size_t DynamicUsage(const std::shared_ptr<X>& p) return p ? MallocUsage(sizeof(X)) + MallocUsage(sizeof(stl_shared_counter)) : 0; } -// Boost data structures - template<typename X> struct unordered_node : private X { @@ -158,18 +154,6 @@ private: }; template<typename X, typename Y> -static inline size_t DynamicUsage(const boost::unordered_set<X, Y>& s) -{ - return MallocUsage(sizeof(unordered_node<X>)) * s.size() + MallocUsage(sizeof(void*) * s.bucket_count()); -} - -template<typename X, typename Y, typename Z> -static inline size_t DynamicUsage(const boost::unordered_map<X, Y, Z>& m) -{ - return MallocUsage(sizeof(unordered_node<std::pair<const X, Y> >)) * m.size() + MallocUsage(sizeof(void*) * m.bucket_count()); -} - -template<typename X, typename Y> static inline size_t DynamicUsage(const std::unordered_set<X, Y>& s) { return MallocUsage(sizeof(unordered_node<X>)) * s.size() + MallocUsage(sizeof(void*) * s.bucket_count()); diff --git a/src/miner.h b/src/miner.h index 1f3c9d652f..5c9cfd78f0 100644 --- a/src/miner.h +++ b/src/miner.h @@ -16,9 +16,7 @@ class CBlockIndex; class CChainParams; -class CReserveKey; class CScript; -class CWallet; namespace Consensus { struct Params; }; diff --git a/src/net.cpp b/src/net.cpp index 14ac5618eb..75d1719e86 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -469,35 +469,31 @@ void CConnman::ClearBanned() bool CConnman::IsBanned(CNetAddr ip) { - bool fResult = false; + LOCK(cs_setBanned); + for (banmap_t::iterator it = setBanned.begin(); it != setBanned.end(); it++) { - LOCK(cs_setBanned); - for (banmap_t::iterator it = setBanned.begin(); it != setBanned.end(); it++) - { - CSubNet subNet = (*it).first; - CBanEntry banEntry = (*it).second; + CSubNet subNet = (*it).first; + CBanEntry banEntry = (*it).second; - if(subNet.Match(ip) && GetTime() < banEntry.nBanUntil) - fResult = true; + if (subNet.Match(ip) && GetTime() < banEntry.nBanUntil) { + return true; } } - return fResult; + return false; } bool CConnman::IsBanned(CSubNet subnet) { - bool fResult = false; + LOCK(cs_setBanned); + banmap_t::iterator i = setBanned.find(subnet); + if (i != setBanned.end()) { - LOCK(cs_setBanned); - banmap_t::iterator i = setBanned.find(subnet); - if (i != setBanned.end()) - { - CBanEntry banEntry = (*i).second; - if (GetTime() < banEntry.nBanUntil) - fResult = true; + CBanEntry banEntry = (*i).second; + if (GetTime() < banEntry.nBanUntil) { + return true; } } - return fResult; + return false; } void CConnman::Ban(const CNetAddr& addr, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) { @@ -101,7 +101,6 @@ struct AddedNodeInfo bool fInbound; }; -class CTransaction; class CNodeStats; class CClientUIInterface; diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 4ca02c281d..3d38350d9b 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -30,8 +30,6 @@ #include "utilstrencodings.h" #include "validationinterface.h" -#include <boost/thread.hpp> - #if defined(NDEBUG) # error "Bitcoin cannot be compiled without assertions." #endif diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index 7a9af5edc2..3c3a2fb651 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -855,13 +855,13 @@ bool CBlockPolicyEstimator::Read(CAutoFile& filein) try { LOCK(cs_feeEstimator); int nVersionRequired, nVersionThatWrote; - unsigned int nFileBestSeenHeight, nFileHistoricalFirst, nFileHistoricalBest; filein >> nVersionRequired >> nVersionThatWrote; if (nVersionRequired > CLIENT_VERSION) return error("CBlockPolicyEstimator::Read(): up-version (%d) fee estimate file", nVersionRequired); // Read fee estimates file into temporary variables so existing data // structures aren't corrupted if there is an exception. + unsigned int nFileBestSeenHeight; filein >> nFileBestSeenHeight; if (nVersionThatWrote < 149900) { @@ -890,6 +890,7 @@ bool CBlockPolicyEstimator::Read(CAutoFile& filein) } } else { // nVersionThatWrote >= 149900 + unsigned int nFileHistoricalFirst, nFileHistoricalBest; filein >> nFileHistoricalFirst >> nFileHistoricalBest; if (nFileHistoricalFirst > nFileHistoricalBest || nFileHistoricalBest > nFileBestSeenHeight) { throw std::runtime_error("Corrupt estimates file. Historical block range for estimates is invalid"); diff --git a/src/qt/addressbookpage.h b/src/qt/addressbookpage.h index c22566d473..3c00fd0809 100644 --- a/src/qt/addressbookpage.h +++ b/src/qt/addressbookpage.h @@ -8,7 +8,6 @@ #include <QDialog> class AddressTableModel; -class OptionsModel; class PlatformStyle; namespace Ui { @@ -20,7 +19,6 @@ class QItemSelection; class QMenu; class QModelIndex; class QSortFilterProxyModel; -class QTableView; QT_END_NAMESPACE /** Widget that shows a list of sending or receiving addresses. diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 23ec3ab434..6d8760c071 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -474,9 +474,10 @@ void BitcoinApplication::initializeResult(bool success) window->setClientModel(clientModel); #ifdef ENABLE_WALLET - if(pwalletMain) + // TODO: Expose secondary wallets + if (!vpwallets.empty()) { - walletModel = new WalletModel(platformStyle, pwalletMain, optionsModel); + walletModel = new WalletModel(platformStyle, vpwallets[0], optionsModel); window->addWallet(BitcoinGUI::DEFAULT_WALLET, walletModel); window->setCurrentWallet(BitcoinGUI::DEFAULT_WALLET); diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 62d419d3ef..8731caafc7 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -31,8 +31,6 @@ class WalletModel; class HelpMessageDialog; class ModalOverlay; -class CWallet; - QT_BEGIN_NAMESPACE class QAction; class QProgressBar; diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 4c92e2144e..6447cae1bb 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -10,13 +10,10 @@ #include <atomic> -class AddressTableModel; class BanTableModel; class OptionsModel; class PeerTableModel; -class TransactionTableModel; -class CWallet; class CBlockIndex; QT_BEGIN_NAMESPACE diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index 135cf6f701..1f14abf2c9 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -20,8 +20,6 @@ #include "validation.h" // For mempool #include "wallet/wallet.h" -#include <boost/assign/list_of.hpp> // for 'map_list_of()' - #include <QApplication> #include <QCheckBox> #include <QCursor> diff --git a/src/qt/coincontroldialog.h b/src/qt/coincontroldialog.h index 0b8162f858..99a9f893ff 100644 --- a/src/qt/coincontroldialog.h +++ b/src/qt/coincontroldialog.h @@ -20,7 +20,6 @@ class PlatformStyle; class WalletModel; class CCoinControl; -class CTxMemPool; namespace Ui { class CoinControlDialog; diff --git a/src/qt/coincontroltreewidget.cpp b/src/qt/coincontroltreewidget.cpp index f86bc0851f..88510b6168 100644 --- a/src/qt/coincontroltreewidget.cpp +++ b/src/qt/coincontroltreewidget.cpp @@ -16,9 +16,10 @@ void CoinControlTreeWidget::keyPressEvent(QKeyEvent *event) if (event->key() == Qt::Key_Space) // press spacebar -> select checkbox { event->ignore(); - int COLUMN_CHECKBOX = 0; - if(this->currentItem()) + if (this->currentItem()) { + int COLUMN_CHECKBOX = 0; this->currentItem()->setCheckState(COLUMN_CHECKBOX, ((this->currentItem()->checkState(COLUMN_CHECKBOX) == Qt::Checked) ? Qt::Unchecked : Qt::Checked)); + } } else if (event->key() == Qt::Key_Escape) // press esc -> close dialog { diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index efb25aaf18..9cdd02e1f0 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -21,8 +21,6 @@ #include "wallet/wallet.h" // for CWallet::GetRequiredFee() #endif -#include <boost/thread.hpp> - #include <QDataWidgetMapper> #include <QDir> #include <QIntValidator> diff --git a/src/qt/receivecoinsdialog.h b/src/qt/receivecoinsdialog.h index 1d0491c0d5..385f98565c 100644 --- a/src/qt/receivecoinsdialog.h +++ b/src/qt/receivecoinsdialog.h @@ -15,7 +15,6 @@ #include <QPoint> #include <QVariant> -class OptionsModel; class PlatformStyle; class WalletModel; diff --git a/src/qt/recentrequeststablemodel.cpp b/src/qt/recentrequeststablemodel.cpp index dac3979290..e4c857e40b 100644 --- a/src/qt/recentrequeststablemodel.cpp +++ b/src/qt/recentrequeststablemodel.cpp @@ -55,10 +55,9 @@ QVariant RecentRequestsTableModel::data(const QModelIndex &index, int role) cons if(!index.isValid() || index.row() >= list.length()) return QVariant(); - const RecentRequestEntry *rec = &list[index.row()]; - if(role == Qt::DisplayRole || role == Qt::EditRole) { + const RecentRequestEntry *rec = &list[index.row()]; switch(index.column()) { case Date: diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index b200cb1127..b17693e1ca 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -13,8 +13,6 @@ #include "clientmodel.h" #include "guiutil.h" #include "platformstyle.h" -#include "bantablemodel.h" - #include "chainparams.h" #include "netbase.h" #include "rpc/server.h" diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index a932f129be..ff7040ac5b 100644 --- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -13,7 +13,6 @@ #include <QTimer> class ClientModel; -class OptionsModel; class PlatformStyle; class SendCoinsEntry; class SendCoinsRecipient; diff --git a/src/qt/trafficgraphwidget.cpp b/src/qt/trafficgraphwidget.cpp index 601d554c02..06f9c5134a 100644 --- a/src/qt/trafficgraphwidget.cpp +++ b/src/qt/trafficgraphwidget.cpp @@ -47,13 +47,14 @@ int TrafficGraphWidget::getGraphRangeMins() const void TrafficGraphWidget::paintPath(QPainterPath &path, QQueue<float> &samples) { - int h = height() - YMARGIN * 2, w = width() - XMARGIN * 2; - int sampleCount = samples.size(), x = XMARGIN + w, y; + int sampleCount = samples.size(); if(sampleCount > 0) { + int h = height() - YMARGIN * 2, w = width() - XMARGIN * 2; + int x = XMARGIN + w; path.moveTo(x, YMARGIN + h); for(int i = 0; i < sampleCount; ++i) { x = XMARGIN + w - w * i / DESIRED_SAMPLES; - y = YMARGIN + h - (int)(h * samples.at(i) / fMax); + int y = YMARGIN + h - (int)(h * samples.at(i) / fMax); path.lineTo(x, y); } path.lineTo(x, YMARGIN + h); diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index f27abc2104..ae51eba902 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -26,8 +26,6 @@ #include <QIcon> #include <QList> -#include <boost/foreach.hpp> - // Amount column is right-aligned it contains numbers static int column_alignments[] = { Qt::AlignLeft|Qt::AlignVCenter, /* status */ diff --git a/src/qt/utilitydialog.h b/src/qt/utilitydialog.h index 1b6781c5fc..acaa864148 100644 --- a/src/qt/utilitydialog.h +++ b/src/qt/utilitydialog.h @@ -9,7 +9,6 @@ #include <QObject> class BitcoinGUI; -class ClientModel; namespace Ui { class HelpMessageDialog; diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index b66c1c2b64..388472f076 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -19,6 +19,7 @@ #include "rpc/server.h" #include "streams.h" #include "sync.h" +#include "txdb.h" #include "txmempool.h" #include "util.h" #include "utilstrencodings.h" @@ -921,7 +922,7 @@ UniValue gettxoutsetinfo(const JSONRPCRequest& request) CCoinsStats stats; FlushStateToDisk(); - if (GetUTXOStats(pcoinsTip, stats)) { + if (GetUTXOStats(pcoinsdbview, stats)) { ret.push_back(Pair("height", (int64_t)stats.nHeight)); ret.push_back(Pair("bestblock", stats.hashBlock.GetHex())); ret.push_back(Pair("transactions", (int64_t)stats.nTransactions)); diff --git a/src/rpc/blockchain.h b/src/rpc/blockchain.h index c021441b0a..960edfd56f 100644 --- a/src/rpc/blockchain.h +++ b/src/rpc/blockchain.h @@ -7,9 +7,6 @@ class CBlock; class CBlockIndex; -class CScript; -class CTransaction; -class uint256; class UniValue; /** diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 8dd84e20c9..c5585a9fba 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -10,7 +10,6 @@ #include <set> #include <stdint.h> -#include <boost/algorithm/string/case_conv.hpp> // for to_lower() #include <univalue.h> class CRPCConvertParam @@ -113,7 +112,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "estimaterawfee", 0, "nblocks" }, { "estimaterawfee", 1, "threshold" }, { "estimaterawfee", 2, "horizon" }, - { "prioritisetransaction", 1, "priority_delta" }, + { "prioritisetransaction", 1, "dummy" }, { "prioritisetransaction", 2, "fee_delta" }, { "setban", 2, "bantime" }, { "setban", 3, "absolute" }, diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index cfe42ec7d8..ab9f40d466 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -27,8 +27,6 @@ #include <memory> #include <stdint.h> -#include <boost/assign/list_of.hpp> - #include <univalue.h> /** @@ -98,15 +96,13 @@ UniValue getnetworkhashps(const JSONRPCRequest& request) UniValue generateBlocks(std::shared_ptr<CReserveScript> coinbaseScript, int nGenerate, uint64_t nMaxTries, bool keepScript) { static const int nInnerLoopCount = 0x10000; - int nHeightStart = 0; int nHeightEnd = 0; int nHeight = 0; { // Don't keep cs_main locked LOCK(cs_main); - nHeightStart = chainActive.Height(); - nHeight = nHeightStart; - nHeightEnd = nHeightStart+nGenerate; + nHeight = chainActive.Height(); + nHeightEnd = nHeight+nGenerate; } unsigned int nExtraNonce = 0; UniValue blockHashes(UniValue::VARR); @@ -259,11 +255,12 @@ UniValue prioritisetransaction(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 3) throw std::runtime_error( - "prioritisetransaction <txid> <priority delta> <fee delta>\n" + "prioritisetransaction <txid> <dummy value> <fee delta>\n" "Accepts the transaction into mined blocks at a higher (or lower) priority\n" "\nArguments:\n" "1. \"txid\" (string, required) The transaction id.\n" - "2. priority_delta (numeric, optional) Fee-independent priority adjustment. Not supported, so must be zero or null.\n" + "2. dummy (numeric, optional) API-Compatibility for previous API. Must be zero or null.\n" + " DEPRECATED. For forward compatibility use named arguments and omit this parameter.\n" "3. fee_delta (numeric, required) The fee value (in satoshis) to add (or subtract, if negative).\n" " The fee is not actually paid, only the algorithm for selecting transactions into a block\n" " considers the transaction as it would have paid a higher (or lower) fee.\n" @@ -280,7 +277,7 @@ UniValue prioritisetransaction(const JSONRPCRequest& request) CAmount nAmount = request.params[2].get_int64(); if (!(request.params[1].isNull() || request.params[1].get_real() == 0)) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Priority is not supported, and adjustment thereof must be zero."); + throw JSONRPCError(RPC_INVALID_PARAMETER, "Priority is no longer supported, dummy argument to prioritisetransaction must be 0."); } mempool.PrioritiseTransaction(hash, nAmount); @@ -819,7 +816,7 @@ UniValue estimatefee(const JSONRPCRequest& request) + HelpExampleCli("estimatefee", "6") ); - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VNUM)); + RPCTypeCheck(request.params, {UniValue::VNUM}); int nBlocks = request.params[0].get_int(); if (nBlocks < 1) @@ -860,7 +857,7 @@ UniValue estimatesmartfee(const JSONRPCRequest& request) + HelpExampleCli("estimatesmartfee", "6") ); - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VNUM)); + RPCTypeCheck(request.params, {UniValue::VNUM}); int nBlocks = request.params[0].get_int(); bool conservative = true; @@ -917,7 +914,7 @@ UniValue estimaterawfee(const JSONRPCRequest& request) + HelpExampleCli("estimaterawfee", "6 0.9 1") ); - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VNUM)(UniValue::VNUM)(UniValue::VNUM), true); + RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM, UniValue::VNUM}, true); RPCTypeCheckArgument(request.params[0], UniValue::VNUM); int nBlocks = request.params[0].get_int(); double threshold = 0.95; @@ -964,7 +961,7 @@ static const CRPCCommand commands[] = // --------------------- ------------------------ ----------------------- ---------- { "mining", "getnetworkhashps", &getnetworkhashps, true, {"nblocks","height"} }, { "mining", "getmininginfo", &getmininginfo, true, {} }, - { "mining", "prioritisetransaction", &prioritisetransaction, true, {"txid","priority_delta","fee_delta"} }, + { "mining", "prioritisetransaction", &prioritisetransaction, true, {"txid","dummy","fee_delta"} }, { "mining", "getblocktemplate", &getblocktemplate, true, {"template_request"} }, { "mining", "submitblock", &submitblock, true, {"hexdata","parameters"} }, diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 76aa7ec992..5af6bbef33 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -27,8 +27,6 @@ #include <malloc.h> #endif -#include <boost/assign/list_of.hpp> - #include <univalue.h> /** @@ -472,7 +470,7 @@ UniValue setmocktime(const JSONRPCRequest& request) // ensure all call sites of GetTime() are accessing this safely. LOCK(cs_main); - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VNUM)); + RPCTypeCheck(request.params, {UniValue::VNUM}); SetMockTime(request.params[0].get_int64()); return NullUniValue; diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 00ddd9d16f..63fd197a6b 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -31,8 +31,6 @@ #include <stdint.h> -#include <boost/assign/list_of.hpp> - #include <univalue.h> @@ -327,7 +325,7 @@ UniValue createrawtransaction(const JSONRPCRequest& request) + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"{\\\"data\\\":\\\"00010203\\\"}\"") ); - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VARR)(UniValue::VOBJ)(UniValue::VNUM), true); + RPCTypeCheck(request.params, {UniValue::VARR, UniValue::VOBJ, UniValue::VNUM}, true); if (request.params[0].isNull() || request.params[1].isNull()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, arguments 1 and 2 must be non-null"); @@ -472,7 +470,7 @@ UniValue decoderawtransaction(const JSONRPCRequest& request) ); LOCK(cs_main); - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)); + RPCTypeCheck(request.params, {UniValue::VSTR}); CMutableTransaction mtx; @@ -510,7 +508,7 @@ UniValue decodescript(const JSONRPCRequest& request) + HelpExampleRpc("decodescript", "\"hexstring\"") ); - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)); + RPCTypeCheck(request.params, {UniValue::VSTR}); UniValue r(UniValue::VOBJ); CScript script; @@ -621,7 +619,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request) #else LOCK(cs_main); #endif - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)(UniValue::VARR)(UniValue::VARR)(UniValue::VSTR), true); + RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR, UniValue::VARR, UniValue::VSTR}, true); std::vector<unsigned char> txData(ParseHexV(request.params[0], "argument 1")); CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); @@ -756,15 +754,14 @@ UniValue signrawtransaction(const JSONRPCRequest& request) int nHashType = SIGHASH_ALL; if (request.params.size() > 3 && !request.params[3].isNull()) { - static std::map<std::string, int> mapSigHashValues = - boost::assign::map_list_of - (std::string("ALL"), int(SIGHASH_ALL)) - (std::string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY)) - (std::string("NONE"), int(SIGHASH_NONE)) - (std::string("NONE|ANYONECANPAY"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY)) - (std::string("SINGLE"), int(SIGHASH_SINGLE)) - (std::string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY)) - ; + static std::map<std::string, int> mapSigHashValues = { + {std::string("ALL"), int(SIGHASH_ALL)}, + {std::string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY)}, + {std::string("NONE"), int(SIGHASH_NONE)}, + {std::string("NONE|ANYONECANPAY"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY)}, + {std::string("SINGLE"), int(SIGHASH_SINGLE)}, + {std::string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY)}, + }; std::string strHashType = request.params[3].get_str(); if (mapSigHashValues.count(strHashType)) nHashType = mapSigHashValues[strHashType]; @@ -846,7 +843,7 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) ); LOCK(cs_main); - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL)); + RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL}); // parse hex string from parameter CMutableTransaction mtx; @@ -855,7 +852,6 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) CTransactionRef tx(MakeTransactionRef(std::move(mtx))); const uint256& hashTx = tx->GetHash(); - bool fLimitFree = true; CAmount nMaxRawTxFee = maxTxFee; if (request.params.size() > 1 && request.params[1].get_bool()) nMaxRawTxFee = 0; @@ -871,6 +867,7 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) // push to local node and sync with wallets CValidationState state; bool fMissingInputs; + bool fLimitFree = true; if (!AcceptToMemoryPool(mempool, state, std::move(tx), fLimitFree, &fMissingInputs, NULL, false, nMaxRawTxFee)) { if (state.IsInvalid()) { throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason())); diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index c5fbff0077..31771dffb8 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -18,9 +18,7 @@ #include <boost/bind.hpp> #include <boost/foreach.hpp> -#include <boost/shared_ptr.hpp> #include <boost/signals2/signal.hpp> -#include <boost/thread.hpp> #include <boost/algorithm/string/case_conv.hpp> // for to_upper() #include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/split.hpp> diff --git a/src/rpc/server.h b/src/rpc/server.h index a893f49033..b20c827727 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -28,9 +28,6 @@ namespace RPCServer void OnPreCommand(std::function<void (const CRPCCommand&)> slot); } -class CBlockIndex; -class CNetAddr; - /** Wrapper for UniValue::VType, which includes typeAny: * Used to denote don't care type. Only used by RPCTypeCheckObj */ struct UniValueType { diff --git a/src/script/script.cpp b/src/script/script.cpp index 70eb8a139b..a10b619f7d 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -267,3 +267,16 @@ std::string CScriptWitness::ToString() const } return ret + ")"; } + +bool CScript::HasValidOps() const +{ + CScript::const_iterator it = begin(); + while (it < end()) { + opcodetype opcode; + std::vector<unsigned char> item; + if (!GetOp(it, opcode, item) || opcode > MAX_OPCODE || item.size() > MAX_SCRIPT_ELEMENT_SIZE) { + return false; + } + } + return true; +} diff --git a/src/script/script.h b/src/script/script.h index 95a5999a13..23706b9826 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -190,6 +190,9 @@ enum opcodetype OP_INVALIDOPCODE = 0xff, }; +// Maximum value that an opcode can be +static const unsigned int MAX_OPCODE = OP_NOP10; + const char* GetOpName(opcodetype opcode); class scriptnum_error : public std::runtime_error @@ -630,6 +633,9 @@ public: bool IsPushOnly(const_iterator pc) const; bool IsPushOnly() const; + /** Check if the script contains valid OP_CODES */ + bool HasValidOps() const; + /** * Returns whether the script is guaranteed to fail at execution, * regardless of the initial stack. This allows outputs to be pruned diff --git a/src/script/sign.cpp b/src/script/sign.cpp index 5682418546..123f88bd6f 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -141,10 +141,9 @@ static CScript PushAll(const std::vector<valtype>& values) bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPubKey, SignatureData& sigdata) { CScript script = fromPubKey; - bool solved = true; std::vector<valtype> result; txnouttype whichType; - solved = SignStep(creator, script, result, whichType, SIGVERSION_BASE); + bool solved = SignStep(creator, script, result, whichType, SIGVERSION_BASE); bool P2SH = false; CScript subscript; sigdata.scriptWitness.stack.clear(); diff --git a/src/sync.h b/src/sync.h index 9274f50d8b..20974f5fbc 100644 --- a/src/sync.h +++ b/src/sync.h @@ -9,7 +9,6 @@ #include "threadsafety.h" #include <boost/thread/condition_variable.hpp> -#include <boost/thread/locks.hpp> #include <boost/thread/mutex.hpp> #include <boost/thread/recursive_mutex.hpp> diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index a7a3a1bdf0..4a284517a1 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -18,9 +18,6 @@ #include <stdint.h> -#include <boost/assign/list_of.hpp> // for 'map_list_of()' -#include <boost/date_time/posix_time/posix_time_types.hpp> -#include <boost/foreach.hpp> #include <boost/test/unit_test.hpp> // Tests these internal-to-net_processing.cpp methods: diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index 6cd998990b..b33cdb9fe6 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -15,7 +15,6 @@ #include "utilstrencodings.h" #include "test/test_bitcoin.h" -#include <boost/foreach.hpp> #include <boost/test/unit_test.hpp> #include <univalue.h> diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp index 1788ee1326..2085b5cb2b 100644 --- a/src/test/bloom_tests.cpp +++ b/src/test/bloom_tests.cpp @@ -19,7 +19,6 @@ #include <vector> #include <boost/test/unit_test.hpp> -#include <boost/tuple/tuple.hpp> BOOST_FIXTURE_TEST_SUITE(bloom_tests, BasicTestingSetup) diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp index bf999eb524..6ae0bcadd0 100644 --- a/src/test/checkqueue_tests.cpp +++ b/src/test/checkqueue_tests.cpp @@ -402,12 +402,12 @@ BOOST_AUTO_TEST_CASE(test_CheckQueueControl_Locks) { boost::thread_group tg; std::mutex m; - bool has_lock {false}; - bool has_tried {false}; - bool done {false}; - bool done_ack {false}; std::condition_variable cv; { + bool has_lock {false}; + bool has_tried {false}; + bool done {false}; + bool done_ack {false}; std::unique_lock<std::mutex> l(m); tg.create_thread([&]{ CCheckQueueControl<FakeCheck> control(queue.get()); diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index a72975d6e4..4fd3ff9cf1 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -36,7 +36,7 @@ class CCoinsViewTest : public CCoinsView std::map<COutPoint, Coin> map_; public: - bool GetCoin(const COutPoint& outpoint, Coin& coin) const + bool GetCoin(const COutPoint& outpoint, Coin& coin) const override { std::map<COutPoint, Coin>::const_iterator it = map_.find(outpoint); if (it == map_.end()) { @@ -50,15 +50,15 @@ public: return true; } - bool HaveCoin(const COutPoint& outpoint) const + bool HaveCoin(const COutPoint& outpoint) const override { Coin coin; return GetCoin(outpoint, coin); } - uint256 GetBestBlock() const { return hashBestBlock_; } + uint256 GetBestBlock() const override { return hashBestBlock_; } - bool BatchWrite(CCoinsMap& mapCoins, const uint256& hashBlock) + bool BatchWrite(CCoinsMap& mapCoins, const uint256& hashBlock) override { for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end(); ) { if (it->second.flags & CCoinsCacheEntry::DIRTY) { diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index a4f0e17c99..391ad14ffa 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -16,7 +16,6 @@ #include <vector> -#include <boost/assign/list_of.hpp> #include <boost/test/unit_test.hpp> #include <openssl/aes.h> #include <openssl/evp.h> diff --git a/src/test/cuckoocache_tests.cpp b/src/test/cuckoocache_tests.cpp index ed391e184c..1004482224 100644 --- a/src/test/cuckoocache_tests.cpp +++ b/src/test/cuckoocache_tests.cpp @@ -7,8 +7,6 @@ #include "test/test_bitcoin.h" #include "random.h" #include <thread> -#include <boost/thread.hpp> - /** Test Suite for CuckooCache * diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index 2d8a419bdb..be631ce7a6 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -7,8 +7,6 @@ #include "random.h" #include "test/test_bitcoin.h" -#include <boost/assign/std/vector.hpp> // for 'operator+=()' -#include <boost/assert.hpp> #include <boost/test/unit_test.hpp> // Test if a string consists entirely of null characters diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index 1afef5b1ce..e4b4b85720 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -7,7 +7,6 @@ #include <string> -#include <boost/assign/list_of.hpp> #include <boost/test/unit_test.hpp> BOOST_FIXTURE_TEST_SUITE(netbase_tests, BasicTestingSetup) @@ -269,18 +268,18 @@ BOOST_AUTO_TEST_CASE(subnet_test) BOOST_AUTO_TEST_CASE(netbase_getgroup) { - BOOST_CHECK(ResolveIP("127.0.0.1").GetGroup() == boost::assign::list_of(0)); // Local -> !Routable() - BOOST_CHECK(ResolveIP("257.0.0.1").GetGroup() == boost::assign::list_of(0)); // !Valid -> !Routable() - BOOST_CHECK(ResolveIP("10.0.0.1").GetGroup() == boost::assign::list_of(0)); // RFC1918 -> !Routable() - BOOST_CHECK(ResolveIP("169.254.1.1").GetGroup() == boost::assign::list_of(0)); // RFC3927 -> !Routable() - BOOST_CHECK(ResolveIP("1.2.3.4").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // IPv4 - BOOST_CHECK(ResolveIP("::FFFF:0:102:304").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC6145 - BOOST_CHECK(ResolveIP("64:FF9B::102:304").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC6052 - BOOST_CHECK(ResolveIP("2002:102:304:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC3964 - BOOST_CHECK(ResolveIP("2001:0:9999:9999:9999:9999:FEFD:FCFB").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC4380 - BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetGroup() == boost::assign::list_of((unsigned char)NET_TOR)(239)); // Tor - BOOST_CHECK(ResolveIP("2001:470:abcd:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV6)(32)(1)(4)(112)(175)); //he.net - BOOST_CHECK(ResolveIP("2001:2001:9999:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV6)(32)(1)(32)(1)); //IPv6 + BOOST_CHECK(ResolveIP("127.0.0.1").GetGroup() == std::vector<unsigned char>({0})); // Local -> !Routable() + BOOST_CHECK(ResolveIP("257.0.0.1").GetGroup() == std::vector<unsigned char>({0})); // !Valid -> !Routable() + BOOST_CHECK(ResolveIP("10.0.0.1").GetGroup() == std::vector<unsigned char>({0})); // RFC1918 -> !Routable() + BOOST_CHECK(ResolveIP("169.254.1.1").GetGroup() == std::vector<unsigned char>({0})); // RFC3927 -> !Routable() + BOOST_CHECK(ResolveIP("1.2.3.4").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // IPv4 + BOOST_CHECK(ResolveIP("::FFFF:0:102:304").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC6145 + BOOST_CHECK(ResolveIP("64:FF9B::102:304").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC6052 + BOOST_CHECK(ResolveIP("2002:102:304:9999:9999:9999:9999:9999").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC3964 + BOOST_CHECK(ResolveIP("2001:0:9999:9999:9999:9999:FEFD:FCFB").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC4380 + BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_TOR, 239})); // Tor + BOOST_CHECK(ResolveIP("2001:470:abcd:9999:9999:9999:9999:9999").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV6, 32, 1, 4, 112, 175})); //he.net + BOOST_CHECK(ResolveIP("2001:2001:9999:9999:9999:9999:9999:9999").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV6, 32, 1, 32, 1})); //IPv6 } diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index 708a9ca508..c1d216d094 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -13,7 +13,6 @@ #include <vector> -#include <boost/assign/list_of.hpp> #include <boost/test/unit_test.hpp> class CPartialMerkleTreeTester : public CPartialMerkleTree @@ -109,14 +108,15 @@ BOOST_AUTO_TEST_CASE(pmt_test1) BOOST_AUTO_TEST_CASE(pmt_malleability) { - std::vector<uint256> vTxid = boost::assign::list_of - (ArithToUint256(1))(ArithToUint256(2)) - (ArithToUint256(3))(ArithToUint256(4)) - (ArithToUint256(5))(ArithToUint256(6)) - (ArithToUint256(7))(ArithToUint256(8)) - (ArithToUint256(9))(ArithToUint256(10)) - (ArithToUint256(9))(ArithToUint256(10)); - std::vector<bool> vMatch = boost::assign::list_of(false)(false)(false)(false)(false)(false)(false)(false)(false)(true)(true)(false); + std::vector<uint256> vTxid = { + ArithToUint256(1), ArithToUint256(2), + ArithToUint256(3), ArithToUint256(4), + ArithToUint256(5), ArithToUint256(6), + ArithToUint256(7), ArithToUint256(8), + ArithToUint256(9), ArithToUint256(10), + ArithToUint256(9), ArithToUint256(10), + }; + std::vector<bool> vMatch = {false, false, false, false, false, false, false, false, false, true, true, false}; CPartialMerkleTree tree(vTxid, vMatch); std::vector<unsigned int> vIndex; diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 7cf2a744ea..134bd7c609 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -11,7 +11,6 @@ #include "test/test_bitcoin.h" #include <boost/algorithm/string.hpp> -#include <boost/assign/list_of.hpp> #include <boost/test/unit_test.hpp> #include <univalue.h> @@ -324,20 +323,20 @@ BOOST_AUTO_TEST_CASE(rpc_convert_values_generatetoaddress) { UniValue result; - BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", boost::assign::list_of("101")("mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a"))); + BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", {"101", "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a"})); BOOST_CHECK_EQUAL(result[0].get_int(), 101); BOOST_CHECK_EQUAL(result[1].get_str(), "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a"); - BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", boost::assign::list_of("101")("mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU"))); + BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", {"101", "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU"})); BOOST_CHECK_EQUAL(result[0].get_int(), 101); BOOST_CHECK_EQUAL(result[1].get_str(), "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU"); - BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", boost::assign::list_of("1")("mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a")("9"))); + BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", {"1", "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a", "9"})); BOOST_CHECK_EQUAL(result[0].get_int(), 1); BOOST_CHECK_EQUAL(result[1].get_str(), "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a"); BOOST_CHECK_EQUAL(result[2].get_int(), 9); - BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", boost::assign::list_of("1")("mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU")("9"))); + BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", {"1", "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU", "9"})); BOOST_CHECK_EQUAL(result[0].get_int(), 1); BOOST_CHECK_EQUAL(result[1].get_str(), "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU"); BOOST_CHECK_EQUAL(result[2].get_int(), 9); diff --git a/src/test/scheduler_tests.cpp b/src/test/scheduler_tests.cpp index e4ddf9d618..1de865776e 100644 --- a/src/test/scheduler_tests.cpp +++ b/src/test/scheduler_tests.cpp @@ -8,8 +8,6 @@ #include "test/test_bitcoin.h" #include <boost/bind.hpp> -#include <boost/random/mersenne_twister.hpp> -#include <boost/random/uniform_int_distribution.hpp> #include <boost/thread.hpp> #include <boost/test/unit_test.hpp> @@ -56,10 +54,10 @@ BOOST_AUTO_TEST_CASE(manythreads) boost::mutex counterMutex[10]; int counter[10] = { 0 }; - boost::random::mt19937 rng(42); - boost::random::uniform_int_distribution<> zeroToNine(0, 9); - boost::random::uniform_int_distribution<> randomMsec(-11, 1000); - boost::random::uniform_int_distribution<> randomDelta(-1000, 1000); + FastRandomContext rng(42); + auto zeroToNine = [](FastRandomContext& rc) -> int { return rc.randrange(10); }; // [0, 9] + auto randomMsec = [](FastRandomContext& rc) -> int { return -11 + rc.randrange(1012); }; // [-11, 1000] + auto randomDelta = [](FastRandomContext& rc) -> int { return -1000 + rc.randrange(2001); }; // [-1000, 1000] boost::chrono::system_clock::time_point start = boost::chrono::system_clock::now(); boost::chrono::system_clock::time_point now = start; diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 343c645cb1..70544cacd6 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -1438,4 +1438,18 @@ BOOST_AUTO_TEST_CASE(script_FindAndDelete) BOOST_CHECK(s == expect); } +BOOST_AUTO_TEST_CASE(script_HasValidOps) +{ + // Exercise the HasValidOps functionality + CScript script; + script = ScriptFromHex("76a9141234567890abcdefa1a2a3a4a5a6a7a8a9a0aaab88ac"); // Normal script + BOOST_CHECK(script.HasValidOps()); + script = ScriptFromHex("76a914ff34567890abcdefa1a2a3a4a5a6a7a8a9a0aaab88ac"); + BOOST_CHECK(script.HasValidOps()); + script = ScriptFromHex("ff88ac"); // Script with OP_INVALIDOPCODE explicit + BOOST_CHECK(!script.HasValidOps()); + script = ScriptFromHex("88acc0"); // Script with undefined opcode + BOOST_CHECK(!script.HasValidOps()); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index d882ca7a63..1ca83a7cf8 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -29,7 +29,6 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); if (nIn >= txTo.vin.size()) { - printf("ERROR: SignatureHash(): nIn=%d out of range\n", nIn); return one; } CMutableTransaction txTmp(txTo); @@ -60,7 +59,6 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un unsigned int nOut = nIn; if (nOut >= txTmp.vout.size()) { - printf("ERROR: SignatureHash(): nOut=%d out of range\n", nOut); return one; } txTmp.vout.resize(nOut+1); diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp index 4e117448fe..eddb80aed5 100644 --- a/src/test/sigopcount_tests.cpp +++ b/src/test/sigopcount_tests.cpp @@ -12,7 +12,6 @@ #include <vector> -#include <boost/foreach.hpp> #include <boost/test/unit_test.hpp> // Helpers: diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp index 94b5cc119b..af2a152aa5 100644 --- a/src/test/streams_tests.cpp +++ b/src/test/streams_tests.cpp @@ -7,7 +7,6 @@ #include "test/test_bitcoin.h" #include <boost/assign/std/vector.hpp> // for 'operator+=()' -#include <boost/assert.hpp> #include <boost/test/unit_test.hpp> using namespace boost::assign; // bring 'operator+=()' into scope diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index c1aea1680a..11e3df92e1 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -25,8 +25,6 @@ #include <memory> -#include <boost/thread.hpp> - uint256 insecure_rand_seed = GetRandHash(); FastRandomContext insecure_rand_ctx(insecure_rand_seed); diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 5c7516fbf1..e146bb238c 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -26,9 +26,7 @@ #include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/split.hpp> -#include <boost/assign/list_of.hpp> #include <boost/test/unit_test.hpp> -#include <boost/assign/list_of.hpp> #include <boost/foreach.hpp> #include <univalue.h> @@ -38,24 +36,25 @@ typedef std::vector<unsigned char> valtype; // In script_tests.cpp extern UniValue read_json(const std::string& jsondata); -static std::map<std::string, unsigned int> mapFlagNames = boost::assign::map_list_of - (std::string("NONE"), (unsigned int)SCRIPT_VERIFY_NONE) - (std::string("P2SH"), (unsigned int)SCRIPT_VERIFY_P2SH) - (std::string("STRICTENC"), (unsigned int)SCRIPT_VERIFY_STRICTENC) - (std::string("DERSIG"), (unsigned int)SCRIPT_VERIFY_DERSIG) - (std::string("LOW_S"), (unsigned int)SCRIPT_VERIFY_LOW_S) - (std::string("SIGPUSHONLY"), (unsigned int)SCRIPT_VERIFY_SIGPUSHONLY) - (std::string("MINIMALDATA"), (unsigned int)SCRIPT_VERIFY_MINIMALDATA) - (std::string("NULLDUMMY"), (unsigned int)SCRIPT_VERIFY_NULLDUMMY) - (std::string("DISCOURAGE_UPGRADABLE_NOPS"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) - (std::string("CLEANSTACK"), (unsigned int)SCRIPT_VERIFY_CLEANSTACK) - (std::string("MINIMALIF"), (unsigned int)SCRIPT_VERIFY_MINIMALIF) - (std::string("NULLFAIL"), (unsigned int)SCRIPT_VERIFY_NULLFAIL) - (std::string("CHECKLOCKTIMEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY) - (std::string("CHECKSEQUENCEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKSEQUENCEVERIFY) - (std::string("WITNESS"), (unsigned int)SCRIPT_VERIFY_WITNESS) - (std::string("DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM) - (std::string("WITNESS_PUBKEYTYPE"), (unsigned int)SCRIPT_VERIFY_WITNESS_PUBKEYTYPE); +static std::map<std::string, unsigned int> mapFlagNames = { + {std::string("NONE"), (unsigned int)SCRIPT_VERIFY_NONE}, + {std::string("P2SH"), (unsigned int)SCRIPT_VERIFY_P2SH}, + {std::string("STRICTENC"), (unsigned int)SCRIPT_VERIFY_STRICTENC}, + {std::string("DERSIG"), (unsigned int)SCRIPT_VERIFY_DERSIG}, + {std::string("LOW_S"), (unsigned int)SCRIPT_VERIFY_LOW_S}, + {std::string("SIGPUSHONLY"), (unsigned int)SCRIPT_VERIFY_SIGPUSHONLY}, + {std::string("MINIMALDATA"), (unsigned int)SCRIPT_VERIFY_MINIMALDATA}, + {std::string("NULLDUMMY"), (unsigned int)SCRIPT_VERIFY_NULLDUMMY}, + {std::string("DISCOURAGE_UPGRADABLE_NOPS"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS}, + {std::string("CLEANSTACK"), (unsigned int)SCRIPT_VERIFY_CLEANSTACK}, + {std::string("MINIMALIF"), (unsigned int)SCRIPT_VERIFY_MINIMALIF}, + {std::string("NULLFAIL"), (unsigned int)SCRIPT_VERIFY_NULLFAIL}, + {std::string("CHECKLOCKTIMEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY}, + {std::string("CHECKSEQUENCEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKSEQUENCEVERIFY}, + {std::string("WITNESS"), (unsigned int)SCRIPT_VERIFY_WITNESS}, + {std::string("DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM}, + {std::string("WITNESS_PUBKEYTYPE"), (unsigned int)SCRIPT_VERIFY_WITNESS_PUBKEYTYPE}, +}; unsigned int ParseScriptFlags(std::string strFlags) { diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 8a37139f1d..e3baa0556a 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -18,7 +18,6 @@ #include <boost/bind.hpp> #include <boost/signals2/signal.hpp> #include <boost/foreach.hpp> -#include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/split.hpp> #include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/replace.hpp> diff --git a/src/txmempool.h b/src/txmempool.h index 0316b42ba2..7ca3b18a1e 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -28,7 +28,6 @@ #include <boost/signals2/signal.hpp> -class CAutoFile; class CBlockIndex; /** Fake height value used in Coin to signify they are only in the memory pool (since 0.8) */ diff --git a/src/ui_interface.h b/src/ui_interface.h index 065d23fbb4..090402aeed 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -12,9 +12,7 @@ #include <boost/signals2/last_value.hpp> #include <boost/signals2/signal.hpp> -class CBasicKeyStore; class CWallet; -class uint256; class CBlockIndex; /** General change type (added, updated, removed). */ diff --git a/src/util.cpp b/src/util.cpp index 653a4f072a..0a14e8bb9e 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -77,11 +77,8 @@ #endif #include <boost/algorithm/string/case_conv.hpp> // for to_lower() -#include <boost/algorithm/string/join.hpp> #include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith() -#include <boost/foreach.hpp> #include <boost/program_options/detail/config_file.hpp> -#include <boost/program_options/parsers.hpp> #include <boost/thread.hpp> #include <openssl/crypto.h> #include <openssl/rand.h> @@ -477,6 +474,7 @@ void ArgsManager::ForceSetArg(const std::string& strArg, const std::string& strV { LOCK(cs_args); mapArgs[strArg] = strValue; + mapMultiArgs[strArg].clear(); mapMultiArgs[strArg].push_back(strValue); } diff --git a/src/util.h b/src/util.h index 4386ddd550..8f8b249749 100644 --- a/src/util.h +++ b/src/util.h @@ -28,7 +28,6 @@ #include <vector> #include <boost/signals2/signal.hpp> -#include <boost/thread/exceptions.hpp> static const bool DEFAULT_LOGTIMEMICROS = false; static const bool DEFAULT_LOGIPS = false; diff --git a/src/validation.cpp b/src/validation.cpp index eaefa95411..9350735bab 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -44,7 +44,6 @@ #include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/join.hpp> -#include <boost/math/distributions/poisson.hpp> #include <boost/thread.hpp> #if defined(NDEBUG) @@ -175,6 +174,7 @@ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& loc return chain.Genesis(); } +CCoinsViewDB *pcoinsdbview = NULL; CCoinsViewCache *pcoinsTip = NULL; CBlockTreeDB *pblocktree = NULL; @@ -2294,6 +2294,7 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, CBlockIndex *pindexMostWork = NULL; CBlockIndex *pindexNewTip = NULL; + int nStopAtHeight = GetArg("-stopatheight", DEFAULT_STOPATHEIGHT); do { boost::this_thread::interruption_point(); if (ShutdownRequested()) @@ -2343,6 +2344,8 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, if (pindexFork != pindexNewTip) { uiInterface.NotifyBlockTip(fInitialDownload, pindexNewTip); } + + if (nStopAtHeight && pindexNewTip && pindexNewTip->nHeight >= nStopAtHeight) StartShutdown(); } while (pindexNewTip != pindexMostWork); CheckBlockIndex(chainparams.GetConsensus()); @@ -2351,9 +2354,6 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, return false; } - int nStopAtHeight = GetArg("-stopatheight", DEFAULT_STOPATHEIGHT); - if (nStopAtHeight && pindexNewTip && pindexNewTip->nHeight >= nStopAtHeight) StartShutdown(); - return true; } diff --git a/src/validation.h b/src/validation.h index 3a7f7cf1bc..15e19bc511 100644 --- a/src/validation.h +++ b/src/validation.h @@ -30,18 +30,15 @@ #include <atomic> -#include <boost/unordered_map.hpp> - class CBlockIndex; class CBlockTreeDB; -class CBloomFilter; class CChainParams; +class CCoinsViewDB; class CInv; class CConnman; class CScriptCheck; class CBlockPolicyEstimator; class CTxMemPool; -class CValidationInterface; class CValidationState; struct ChainTxData; @@ -161,7 +158,7 @@ extern CScript COINBASE_FLAGS; extern CCriticalSection cs_main; extern CBlockPolicyEstimator feeEstimator; extern CTxMemPool mempool; -typedef boost::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap; +typedef std::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap; extern BlockMap mapBlockIndex; extern uint64_t nLastBlockTx; extern uint64_t nLastBlockSize; @@ -442,6 +439,9 @@ bool ResetBlockFailureFlags(CBlockIndex *pindex); /** The currently-connected chain of blocks (protected by cs_main). */ extern CChain chainActive; +/** Global variable that points to the coins database (protected by cs_main) */ +extern CCoinsViewDB *pcoinsdbview; + /** Global variable that points to the active CCoinsView (protected by cs_main) */ extern CCoinsViewCache *pcoinsTip; diff --git a/src/version.h b/src/version.h index 0f69b2f02b..d528212490 100644 --- a/src/version.h +++ b/src/version.h @@ -27,9 +27,6 @@ static const int CADDR_TIME_VERSION = 31402; //! BIP 0031, pong message, is enabled for all versions AFTER this one static const int BIP0031_VERSION = 60000; -//! "mempool" command, enhanced "getdata" behavior starts with this version -static const int MEMPOOL_GD_VERSION = 60002; - //! "filter*" commands are disabled without NODE_BLOOM after and including this version static const int NO_BLOOM_VERSION = 70011; diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h index 275e435f73..f1c4f57428 100644 --- a/src/wallet/crypter.h +++ b/src/wallet/crypter.h @@ -9,8 +9,6 @@ #include "serialize.h" #include "support/allocators/secure.h" -class uint256; - const unsigned int WALLET_CRYPTO_KEY_SIZE = 32; const unsigned int WALLET_CRYPTO_SALT_SIZE = 8; const unsigned int WALLET_CRYPTO_IV_SIZE = 16; diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 89f204bc31..74b82a8616 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -20,7 +20,6 @@ #include <boost/foreach.hpp> #include <boost/thread.hpp> -#include <boost/version.hpp> // // CDB @@ -143,7 +142,7 @@ void CDBEnv::MakeMock() fMockDb = true; } -CDBEnv::VerifyResult CDBEnv::Verify(const std::string& strFile, bool (*recoverFunc)(const std::string& strFile)) +CDBEnv::VerifyResult CDBEnv::Verify(const std::string& strFile, recoverFunc_type recoverFunc, std::string& out_backup_filename) { LOCK(cs_db); assert(mapFileUseCount.count(strFile) == 0); @@ -156,21 +155,21 @@ CDBEnv::VerifyResult CDBEnv::Verify(const std::string& strFile, bool (*recoverFu return RECOVER_FAIL; // Try to recover: - bool fRecovered = (*recoverFunc)(strFile); + bool fRecovered = (*recoverFunc)(strFile, out_backup_filename); return (fRecovered ? RECOVER_OK : RECOVER_FAIL); } -bool CDB::Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue)) +bool CDB::Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& newFilename) { // Recovery procedure: - // move wallet file to wallet.timestamp.bak + // move wallet file to walletfilename.timestamp.bak // Call Salvage with fAggressive=true to // get as much data as possible. // Rewrite salvaged data to fresh wallet file // Set -rescan so any missing transactions will be // found. int64_t now = GetTime(); - std::string newFilename = strprintf("wallet.%d.bak", now); + newFilename = strprintf("%s.%d.bak", filename, now); int result = bitdb.dbenv->dbrename(NULL, filename.c_str(), NULL, newFilename.c_str(), DB_AUTO_COMMIT); @@ -260,18 +259,19 @@ bool CDB::VerifyEnvironment(const std::string& walletFile, const fs::path& dataD return true; } -bool CDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, bool (*recoverFunc)(const std::string& strFile)) +bool CDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, CDBEnv::recoverFunc_type recoverFunc) { if (fs::exists(dataDir / walletFile)) { - CDBEnv::VerifyResult r = bitdb.Verify(walletFile, recoverFunc); + std::string backup_filename; + CDBEnv::VerifyResult r = bitdb.Verify(walletFile, recoverFunc, backup_filename); if (r == CDBEnv::RECOVER_OK) { warningStr = strprintf(_("Warning: Wallet file corrupt, data salvaged!" " Original %s saved as %s in %s; if" " your balance or transactions are incorrect you should" " restore from a backup."), - walletFile, "wallet.{timestamp}.bak", dataDir); + walletFile, backup_filename, dataDir); } if (r == CDBEnv::RECOVER_FAIL) { @@ -360,7 +360,6 @@ void CDBEnv::CheckpointLSN(const std::string& strFile) CDB::CDB(CWalletDBWrapper& dbw, const char* pszMode, bool fFlushOnCloseIn) : pdb(NULL), activeTxn(NULL) { - int ret; fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w')); fFlushOnClose = fFlushOnCloseIn; env = dbw.env; @@ -383,6 +382,7 @@ CDB::CDB(CWalletDBWrapper& dbw, const char* pszMode, bool fFlushOnCloseIn) : pdb ++env->mapFileUseCount[strFile]; pdb = env->mapDb[strFile]; if (pdb == NULL) { + int ret; pdb = new Db(env->dbenv, 0); bool fMockDb = env->IsMock(); @@ -433,6 +433,11 @@ void CDB::Flush() env->dbenv->txn_checkpoint(nMinutes ? GetArg("-dblogsize", DEFAULT_WALLET_DBLOGSIZE) * 1024 : 0, nMinutes, 0); } +void CWalletDBWrapper::IncrementUpdateCounter() +{ + ++nUpdateCounter; +} + void CDB::Close() { if (!pdb) diff --git a/src/wallet/db.h b/src/wallet/db.h index 3c6870d169..7cccc65660 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -13,6 +13,7 @@ #include "sync.h" #include "version.h" +#include <atomic> #include <map> #include <string> #include <vector> @@ -55,7 +56,8 @@ public: enum VerifyResult { VERIFY_OK, RECOVER_OK, RECOVER_FAIL }; - VerifyResult Verify(const std::string& strFile, bool (*recoverFunc)(const std::string& strFile)); + typedef bool (*recoverFunc_type)(const std::string& strFile, std::string& out_backup_filename); + VerifyResult Verify(const std::string& strFile, recoverFunc_type recoverFunc, std::string& out_backup_filename); /** * Salvage data from a file that Verify says is bad. * fAggressive sets the DB_AGGRESSIVE flag (see berkeley DB->verify() method documentation). @@ -93,13 +95,13 @@ class CWalletDBWrapper friend class CDB; public: /** Create dummy DB handle */ - CWalletDBWrapper(): env(nullptr) + CWalletDBWrapper() : nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0), env(nullptr) { } /** Create DB handle to real database */ - CWalletDBWrapper(CDBEnv *env_in, const std::string &strFile_in): - env(env_in), strFile(strFile_in) + CWalletDBWrapper(CDBEnv *env_in, const std::string &strFile_in) : + nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0), env(env_in), strFile(strFile_in) { } @@ -119,6 +121,13 @@ public: */ void Flush(bool shutdown); + void IncrementUpdateCounter(); + + std::atomic<unsigned int> nUpdateCounter; + unsigned int nLastSeen; + unsigned int nLastFlushed; + int64_t nLastWalletUpdate; + private: /** BerkeleyDB specific */ CDBEnv *env; @@ -149,7 +158,7 @@ public: void Flush(); void Close(); - static bool Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue)); + static bool Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& out_backup_filename); /* flush the wallet passively (TRY_LOCK) ideal to be called periodically */ @@ -157,7 +166,7 @@ public: /* verifies the database environment */ static bool VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr); /* verifies the database file */ - static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, bool (*recoverFunc)(const std::string& strFile)); + static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, CDBEnv::recoverFunc_type recoverFunc); private: CDB(const CDB&); diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 457e937bb8..e771ce9bb3 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -26,7 +26,6 @@ #include <univalue.h> -#include <boost/assign/list_of.hpp> #include <boost/foreach.hpp> std::string static EncodeDumpTime(int64_t nTime) { @@ -1070,7 +1069,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest) // clang-format on - RPCTypeCheck(mainRequest.params, boost::assign::list_of(UniValue::VARR)(UniValue::VOBJ)); + RPCTypeCheck(mainRequest.params, {UniValue::VARR, UniValue::VOBJ}); const UniValue& requests = mainRequest.params[0]; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 0841c23b86..4b8a8b81e4 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -9,7 +9,6 @@ #include "consensus/validation.h" #include "core_io.h" #include "init.h" -#include "wallet/coincontrol.h" #include "validation.h" #include "net.h" #include "policy/feerate.h" @@ -28,13 +27,12 @@ #include <stdint.h> -#include <boost/assign/list_of.hpp> - #include <univalue.h> CWallet *GetWalletForJSONRPCRequest(const JSONRPCRequest& request) { - return pwalletMain; + // TODO: Some way to access secondary wallets + return vpwallets.empty() ? nullptr : vpwallets[0]; } std::string HelpRequiringPassphrase(CWallet * const pwallet) @@ -2255,9 +2253,9 @@ UniValue lockunspent(const JSONRPCRequest& request) LOCK2(cs_main, pwallet->cs_wallet); if (request.params.size() == 1) - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VBOOL)); + RPCTypeCheck(request.params, {UniValue::VBOOL}); else - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VBOOL)(UniValue::VARR)); + RPCTypeCheck(request.params, {UniValue::VBOOL, UniValue::VARR}); bool fUnlock = request.params[0].get_bool(); @@ -2678,7 +2676,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) + HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"") ); - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)); + RPCTypeCheck(request.params, {UniValue::VSTR}); CCoinControl coinControl; coinControl.destChange = CNoDestination(); @@ -2697,7 +2695,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) coinControl.fAllowWatchOnly = request.params[1].get_bool(); } else { - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)(UniValue::VOBJ)); + RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VOBJ}); UniValue options = request.params[1]; @@ -2837,7 +2835,7 @@ UniValue bumpfee(const JSONRPCRequest& request) HelpExampleCli("bumpfee", "<txid>")); } - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)(UniValue::VOBJ)); + RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VOBJ}); uint256 hash; hash.SetHex(request.params[0].get_str()); diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp index 1989bf8d9b..922fcc8e89 100644 --- a/src/wallet/test/wallet_test_fixture.cpp +++ b/src/wallet/test/wallet_test_fixture.cpp @@ -8,6 +8,8 @@ #include "wallet/db.h" #include "wallet/wallet.h" +CWallet *pwalletMain; + WalletTestingSetup::WalletTestingSetup(const std::string& chainName): TestingSetup(chainName) { diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index b30748d66b..96a1b14b60 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -15,10 +15,11 @@ #include "validation.h" #include "wallet/test/wallet_test_fixture.h" -#include <boost/foreach.hpp> #include <boost/test/unit_test.hpp> #include <univalue.h> +extern CWallet* pwalletMain; + extern UniValue importmulti(const JSONRPCRequest& request); extern UniValue dumpwallet(const JSONRPCRequest& request); extern UniValue importwallet(const JSONRPCRequest& request); @@ -402,8 +403,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) // after. { CWallet wallet; - CWallet *backup = ::pwalletMain; - ::pwalletMain = &wallet; + vpwallets.insert(vpwallets.begin(), &wallet); UniValue keys; keys.setArray(); UniValue key; @@ -434,7 +434,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) "downloading and rescanning the relevant blocks (see -reindex and -rescan " "options).\"}},{\"success\":true}]", 0, oldTip->GetBlockTimeMax(), TIMESTAMP_WINDOW)); - ::pwalletMain = backup; + vpwallets.erase(vpwallets.begin()); } } @@ -444,7 +444,6 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) // than or equal to key birthday. BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) { - CWallet *pwalletMainBackup = ::pwalletMain; LOCK(cs_main); // Create two blocks with same timestamp to verify that importwallet rescan @@ -470,7 +469,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) JSONRPCRequest request; request.params.setArray(); request.params.push_back("wallet.backup"); - ::pwalletMain = &wallet; + vpwallets.insert(vpwallets.begin(), &wallet); ::dumpwallet(request); } @@ -482,7 +481,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) JSONRPCRequest request; request.params.setArray(); request.params.push_back("wallet.backup"); - ::pwalletMain = &wallet; + vpwallets[0] = &wallet; ::importwallet(request); BOOST_CHECK_EQUAL(wallet.mapWallet.size(), 3); @@ -495,7 +494,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) } SetMockTime(0); - ::pwalletMain = pwalletMainBackup; + vpwallets.erase(vpwallets.begin()); } // Check that GetImmatureCredit() returns a newly calculated value instead of diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index b2706d09f6..eb6de4870f 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -35,7 +35,7 @@ #include <boost/algorithm/string/replace.hpp> #include <boost/thread.hpp> -CWallet* pwalletMain = NULL; +std::vector<CWalletRef> vpwallets; /** Transaction fee set by the user */ CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE); unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET; @@ -440,30 +440,40 @@ bool CWallet::Verify() if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) return true; - uiInterface.InitMessage(_("Verifying wallet...")); - std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT); + uiInterface.InitMessage(_("Verifying wallet(s)...")); - std::string strError; - if (!CWalletDB::VerifyEnvironment(walletFile, GetDataDir().string(), strError)) - return InitError(strError); + for (const std::string& walletFile : gArgs.GetArgs("-wallet")) { + if (boost::filesystem::path(walletFile).filename() != walletFile) { + return InitError(_("-wallet parameter must only specify a filename (not a path)")); + } else if (SanitizeString(walletFile, SAFE_CHARS_FILENAME) != walletFile) { + return InitError(_("Invalid characters in -wallet filename")); + } - if (GetBoolArg("-salvagewallet", false)) - { - // Recover readable keypairs: - CWallet dummyWallet; - if (!CWalletDB::Recover(walletFile, (void *)&dummyWallet, CWalletDB::RecoverKeysOnlyFilter)) + std::string strError; + if (!CWalletDB::VerifyEnvironment(walletFile, GetDataDir().string(), strError)) { + return InitError(strError); + } + + if (GetBoolArg("-salvagewallet", false)) { + // Recover readable keypairs: + CWallet dummyWallet; + std::string backup_filename; + if (!CWalletDB::Recover(walletFile, (void *)&dummyWallet, CWalletDB::RecoverKeysOnlyFilter, backup_filename)) { + return false; + } + } + + std::string strWarning; + bool dbV = CWalletDB::VerifyDatabaseFile(walletFile, GetDataDir().string(), strWarning, strError); + if (!strWarning.empty()) { + InitWarning(strWarning); + } + if (!dbV) { + InitError(strError); return false; + } } - std::string strWarning; - bool dbV = CWalletDB::VerifyDatabaseFile(walletFile, GetDataDir().string(), strWarning, strError); - if (!strWarning.empty()) - InitWarning(strWarning); - if (!dbV) - { - InitError(strError); - return false; - } return true; } @@ -2867,8 +2877,9 @@ bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry) bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry, CWalletDB *pwalletdb) { - if (!pwalletdb->WriteAccountingEntry_Backend(acentry)) + if (!pwalletdb->WriteAccountingEntry(++nAccountingEntryNumber, acentry)) { return false; + } laccentries.push_back(acentry); CAccountingEntry & entry = laccentries.back(); @@ -3188,10 +3199,10 @@ void CWallet::ReturnKey(int64_t nIndex) bool CWallet::GetKeyFromPool(CPubKey& result, bool internal) { - int64_t nIndex = 0; CKeyPool keypool; { LOCK(cs_wallet); + int64_t nIndex = 0; ReserveKeyFromKeyPool(nIndex, keypool, internal); if (nIndex == -1) { @@ -3880,7 +3891,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) walletInstance->ScanForWalletTransactions(pindexRescan, true); LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart); walletInstance->SetBestChain(chainActive.GetLocator()); - CWalletDB::IncrementUpdateCounter(); + walletInstance->dbw->IncrementUpdateCounter(); // Restore wallet transaction metadata after -zapwallettxes=1 if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2") @@ -3922,24 +3933,17 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) bool CWallet::InitLoadWallet() { if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) { - pwalletMain = NULL; LogPrintf("Wallet disabled!\n"); return true; } - std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT); - - if (boost::filesystem::path(walletFile).filename() != walletFile) { - return InitError(_("-wallet parameter must only specify a filename (not a path)")); - } else if (SanitizeString(walletFile, SAFE_CHARS_FILENAME) != walletFile) { - return InitError(_("Invalid characters in -wallet filename")); - } - - CWallet * const pwallet = CreateWalletFromFile(walletFile); - if (!pwallet) { - return false; + for (const std::string& walletFile : gArgs.GetArgs("-wallet")) { + CWallet * const pwallet = CreateWalletFromFile(walletFile); + if (!pwallet) { + return false; + } + vpwallets.push_back(pwallet); } - pwalletMain = pwallet; return true; } @@ -3960,6 +3964,9 @@ void CWallet::postInitProcess(CScheduler& scheduler) bool CWallet::ParameterInteraction() { + SoftSetArg("-wallet", DEFAULT_WALLET_DAT); + const bool is_multiwallet = gArgs.GetArgs("-wallet").size() > 1; + if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) return true; @@ -3968,15 +3975,27 @@ bool CWallet::ParameterInteraction() } if (GetBoolArg("-salvagewallet", false) && SoftSetBoolArg("-rescan", true)) { + if (is_multiwallet) { + return InitError(strprintf("%s is only allowed with a single wallet file", "-salvagewallet")); + } // Rewrite just private keys: rescan to find transactions LogPrintf("%s: parameter interaction: -salvagewallet=1 -> setting -rescan=1\n", __func__); } // -zapwallettx implies a rescan if (GetBoolArg("-zapwallettxes", false) && SoftSetBoolArg("-rescan", true)) { + if (is_multiwallet) { + return InitError(strprintf("%s is only allowed with a single wallet file", "-zapwallettxes")); + } LogPrintf("%s: parameter interaction: -zapwallettxes=<mode> -> setting -rescan=1\n", __func__); } + if (is_multiwallet) { + if (GetBoolArg("-upgradewallet", false)) { + return InitError(strprintf("%s is only allowed with a single wallet file", "-upgradewallet")); + } + } + if (GetBoolArg("-sysperms", false)) return InitError("-sysperms is not allowed in combination with enabled wallet functionality"); if (GetArg("-prune", 0) && GetBoolArg("-rescan", false)) diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index a9c50aee4d..6c6eb69180 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -29,7 +29,8 @@ #include <utility> #include <vector> -extern CWallet* pwalletMain; +typedef CWallet* CWalletRef; +extern std::vector<CWalletRef> vpwallets; /** * Settings @@ -782,6 +783,7 @@ public: nMasterKeyMaxID = 0; pwalletdbEncryption = NULL; nOrderPosNext = 0; + nAccountingEntryNumber = 0; nNextResend = 0; nLastResend = 0; nTimeFirstKey = 0; @@ -799,6 +801,7 @@ public: TxItems wtxOrdered; int64_t nOrderPosNext; + uint64_t nAccountingEntryNumber; std::map<uint256, int> mapRequestCount; std::map<CTxDestination, CAddressBookData> mapAddressBook; diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 342c797dd3..7731fa5631 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -18,63 +18,50 @@ #include <atomic> -#include <boost/version.hpp> #include <boost/foreach.hpp> #include <boost/thread.hpp> -static uint64_t nAccountingEntryNumber = 0; - -static std::atomic<unsigned int> nWalletDBUpdateCounter; - // // CWalletDB // bool CWalletDB::WriteName(const std::string& strAddress, const std::string& strName) { - nWalletDBUpdateCounter++; - return batch.Write(std::make_pair(std::string("name"), strAddress), strName); + return WriteIC(std::make_pair(std::string("name"), strAddress), strName); } bool CWalletDB::EraseName(const std::string& strAddress) { // This should only be used for sending addresses, never for receiving addresses, // receiving addresses must always have an address book entry if they're not change return. - nWalletDBUpdateCounter++; - return batch.Erase(std::make_pair(std::string("name"), strAddress)); + return EraseIC(std::make_pair(std::string("name"), strAddress)); } bool CWalletDB::WritePurpose(const std::string& strAddress, const std::string& strPurpose) { - nWalletDBUpdateCounter++; - return batch.Write(std::make_pair(std::string("purpose"), strAddress), strPurpose); + return WriteIC(std::make_pair(std::string("purpose"), strAddress), strPurpose); } bool CWalletDB::ErasePurpose(const std::string& strPurpose) { - nWalletDBUpdateCounter++; - return batch.Erase(std::make_pair(std::string("purpose"), strPurpose)); + return EraseIC(std::make_pair(std::string("purpose"), strPurpose)); } bool CWalletDB::WriteTx(const CWalletTx& wtx) { - nWalletDBUpdateCounter++; - return batch.Write(std::make_pair(std::string("tx"), wtx.GetHash()), wtx); + return WriteIC(std::make_pair(std::string("tx"), wtx.GetHash()), wtx); } bool CWalletDB::EraseTx(uint256 hash) { - nWalletDBUpdateCounter++; - return batch.Erase(std::make_pair(std::string("tx"), hash)); + return EraseIC(std::make_pair(std::string("tx"), hash)); } bool CWalletDB::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata& keyMeta) { - nWalletDBUpdateCounter++; - - if (!batch.Write(std::make_pair(std::string("keymeta"), vchPubKey), - keyMeta, false)) + if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta, false)) { return false; + } // hash pubkey/privkey to accelerate wallet load std::vector<unsigned char> vchKey; @@ -82,7 +69,7 @@ bool CWalletDB::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, c vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end()); vchKey.insert(vchKey.end(), vchPrivKey.begin(), vchPrivKey.end()); - return batch.Write(std::make_pair(std::string("key"), vchPubKey), std::make_pair(vchPrivKey, Hash(vchKey.begin(), vchKey.end())), false); + return WriteIC(std::make_pair(std::string("key"), vchPubKey), std::make_pair(vchPrivKey, Hash(vchKey.begin(), vchKey.end())), false); } bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey, @@ -90,55 +77,53 @@ bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey, const CKeyMetadata &keyMeta) { const bool fEraseUnencryptedKey = true; - nWalletDBUpdateCounter++; - if (!batch.Write(std::make_pair(std::string("keymeta"), vchPubKey), - keyMeta)) + if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta)) { return false; + } - if (!batch.Write(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false)) + if (!WriteIC(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false)) { return false; + } if (fEraseUnencryptedKey) { - batch.Erase(std::make_pair(std::string("key"), vchPubKey)); - batch.Erase(std::make_pair(std::string("wkey"), vchPubKey)); + EraseIC(std::make_pair(std::string("key"), vchPubKey)); + EraseIC(std::make_pair(std::string("wkey"), vchPubKey)); } + return true; } bool CWalletDB::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey) { - nWalletDBUpdateCounter++; - return batch.Write(std::make_pair(std::string("mkey"), nID), kMasterKey, true); + return WriteIC(std::make_pair(std::string("mkey"), nID), kMasterKey, true); } bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript) { - nWalletDBUpdateCounter++; - return batch.Write(std::make_pair(std::string("cscript"), hash), *(const CScriptBase*)(&redeemScript), false); + return WriteIC(std::make_pair(std::string("cscript"), hash), *(const CScriptBase*)(&redeemScript), false); } bool CWalletDB::WriteWatchOnly(const CScript &dest, const CKeyMetadata& keyMeta) { - nWalletDBUpdateCounter++; - if (!batch.Write(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)), keyMeta)) + if (!WriteIC(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)), keyMeta)) { return false; - return batch.Write(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)), '1'); + } + return WriteIC(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)), '1'); } bool CWalletDB::EraseWatchOnly(const CScript &dest) { - nWalletDBUpdateCounter++; - if (!batch.Erase(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)))) + if (!EraseIC(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)))) { return false; - return batch.Erase(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest))); + } + return EraseIC(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest))); } bool CWalletDB::WriteBestBlock(const CBlockLocator& locator) { - nWalletDBUpdateCounter++; - batch.Write(std::string("bestblock"), CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan - return batch.Write(std::string("bestblock_nomerkle"), locator); + WriteIC(std::string("bestblock"), CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan + return WriteIC(std::string("bestblock_nomerkle"), locator); } bool CWalletDB::ReadBestBlock(CBlockLocator& locator) @@ -149,14 +134,12 @@ bool CWalletDB::ReadBestBlock(CBlockLocator& locator) bool CWalletDB::WriteOrderPosNext(int64_t nOrderPosNext) { - nWalletDBUpdateCounter++; - return batch.Write(std::string("orderposnext"), nOrderPosNext); + return WriteIC(std::string("orderposnext"), nOrderPosNext); } bool CWalletDB::WriteDefaultKey(const CPubKey& vchPubKey) { - nWalletDBUpdateCounter++; - return batch.Write(std::string("defaultkey"), vchPubKey); + return WriteIC(std::string("defaultkey"), vchPubKey); } bool CWalletDB::ReadPool(int64_t nPool, CKeyPool& keypool) @@ -166,19 +149,17 @@ bool CWalletDB::ReadPool(int64_t nPool, CKeyPool& keypool) bool CWalletDB::WritePool(int64_t nPool, const CKeyPool& keypool) { - nWalletDBUpdateCounter++; - return batch.Write(std::make_pair(std::string("pool"), nPool), keypool); + return WriteIC(std::make_pair(std::string("pool"), nPool), keypool); } bool CWalletDB::ErasePool(int64_t nPool) { - nWalletDBUpdateCounter++; - return batch.Erase(std::make_pair(std::string("pool"), nPool)); + return EraseIC(std::make_pair(std::string("pool"), nPool)); } bool CWalletDB::WriteMinVersion(int nVersion) { - return batch.Write(std::string("minversion"), nVersion); + return WriteIC(std::string("minversion"), nVersion); } bool CWalletDB::ReadAccount(const std::string& strAccount, CAccount& account) @@ -189,17 +170,12 @@ bool CWalletDB::ReadAccount(const std::string& strAccount, CAccount& account) bool CWalletDB::WriteAccount(const std::string& strAccount, const CAccount& account) { - return batch.Write(std::make_pair(std::string("acc"), strAccount), account); + return WriteIC(std::make_pair(std::string("acc"), strAccount), account); } bool CWalletDB::WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry) { - return batch.Write(std::make_pair(std::string("acentry"), std::make_pair(acentry.strAccount, nAccEntryNum)), acentry); -} - -bool CWalletDB::WriteAccountingEntry_Backend(const CAccountingEntry& acentry) -{ - return WriteAccountingEntry(++nAccountingEntryNumber, acentry); + return WriteIC(std::make_pair(std::string("acentry"), std::make_pair(acentry.strAccount, nAccEntryNum)), acentry); } CAmount CWalletDB::GetAccountCreditDebit(const std::string& strAccount) @@ -338,8 +314,9 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, ssKey >> strAccount; uint64_t nNumber; ssKey >> nNumber; - if (nNumber > nAccountingEntryNumber) - nAccountingEntryNumber = nNumber; + if (nNumber > pwallet->nAccountingEntryNumber) { + pwallet->nAccountingEntryNumber = nNumber; + } if (!wss.fAnyUnordered) { @@ -785,38 +762,39 @@ void MaybeCompactWalletDB() return; } - static unsigned int nLastSeen = CWalletDB::GetUpdateCounter(); - static unsigned int nLastFlushed = CWalletDB::GetUpdateCounter(); - static int64_t nLastWalletUpdate = GetTime(); + for (CWalletRef pwallet : vpwallets) { + CWalletDBWrapper& dbh = pwallet->GetDBHandle(); - if (nLastSeen != CWalletDB::GetUpdateCounter()) - { - nLastSeen = CWalletDB::GetUpdateCounter(); - nLastWalletUpdate = GetTime(); - } + unsigned int nUpdateCounter = dbh.nUpdateCounter; - if (nLastFlushed != CWalletDB::GetUpdateCounter() && GetTime() - nLastWalletUpdate >= 2) - { - if (CDB::PeriodicFlush(pwalletMain->GetDBHandle())) { - nLastFlushed = CWalletDB::GetUpdateCounter(); + if (dbh.nLastSeen != nUpdateCounter) { + dbh.nLastSeen = nUpdateCounter; + dbh.nLastWalletUpdate = GetTime(); + } + + if (dbh.nLastFlushed != nUpdateCounter && GetTime() - dbh.nLastWalletUpdate >= 2) { + if (CDB::PeriodicFlush(dbh)) { + dbh.nLastFlushed = nUpdateCounter; + } } } + fOneThread = false; } // // Try to (very carefully!) recover wallet file if there is a problem. // -bool CWalletDB::Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue)) +bool CWalletDB::Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& out_backup_filename) { - return CDB::Recover(filename, callbackDataIn, recoverKVcallback); + return CDB::Recover(filename, callbackDataIn, recoverKVcallback, out_backup_filename); } -bool CWalletDB::Recover(const std::string& filename) +bool CWalletDB::Recover(const std::string& filename, std::string& out_backup_filename) { // recover without a key filter callback // results in recovering all record types - return CWalletDB::Recover(filename, NULL, NULL); + return CWalletDB::Recover(filename, NULL, NULL, out_backup_filename); } bool CWalletDB::RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, CDataStream ssValue) @@ -849,36 +827,23 @@ bool CWalletDB::VerifyEnvironment(const std::string& walletFile, const fs::path& bool CWalletDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr) { - return CDB::VerifyDatabaseFile(walletFile, dataDir, errorStr, warningStr, CWalletDB::Recover); + return CDB::VerifyDatabaseFile(walletFile, dataDir, warningStr, errorStr, CWalletDB::Recover); } bool CWalletDB::WriteDestData(const std::string &address, const std::string &key, const std::string &value) { - nWalletDBUpdateCounter++; - return batch.Write(std::make_pair(std::string("destdata"), std::make_pair(address, key)), value); + return WriteIC(std::make_pair(std::string("destdata"), std::make_pair(address, key)), value); } bool CWalletDB::EraseDestData(const std::string &address, const std::string &key) { - nWalletDBUpdateCounter++; - return batch.Erase(std::make_pair(std::string("destdata"), std::make_pair(address, key))); + return EraseIC(std::make_pair(std::string("destdata"), std::make_pair(address, key))); } bool CWalletDB::WriteHDChain(const CHDChain& chain) { - nWalletDBUpdateCounter++; - return batch.Write(std::string("hdchain"), chain); -} - -void CWalletDB::IncrementUpdateCounter() -{ - nWalletDBUpdateCounter++; -} - -unsigned int CWalletDB::GetUpdateCounter() -{ - return nWalletDBUpdateCounter; + return WriteIC(std::string("hdchain"), chain); } bool CWalletDB::TxnBegin() diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index cd9fe279c5..d78f143ebd 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -140,9 +140,31 @@ public: */ class CWalletDB { +private: + template <typename K, typename T> + bool WriteIC(const K& key, const T& value, bool fOverwrite = true) + { + if (!batch.Write(key, value, fOverwrite)) { + return false; + } + m_dbw.IncrementUpdateCounter(); + return true; + } + + template <typename K> + bool EraseIC(const K& key) + { + if (!batch.Erase(key)) { + return false; + } + m_dbw.IncrementUpdateCounter(); + return true; + } + public: CWalletDB(CWalletDBWrapper& dbw, const char* pszMode = "r+", bool _fFlushOnClose = true) : - batch(dbw, pszMode, _fFlushOnClose) + batch(dbw, pszMode, _fFlushOnClose), + m_dbw(dbw) { } @@ -180,7 +202,6 @@ public: /// This writes directly to the database, and will not update the CWallet's cached accounting entries! /// Use wallet.AddAccountingEntry instead, to write *and* update its caches. bool WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry); - bool WriteAccountingEntry_Backend(const CAccountingEntry& acentry); bool ReadAccount(const std::string& strAccount, CAccount& account); bool WriteAccount(const std::string& strAccount, const CAccount& account); @@ -197,9 +218,9 @@ public: DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx); DBErrors ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut); /* Try to (very carefully!) recover wallet database (with a possible key type filter) */ - static bool Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue)); + static bool Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& out_backup_filename); /* Recover convenience-function to bypass the key filter callback, called when verify fails, recovers everything */ - static bool Recover(const std::string& filename); + static bool Recover(const std::string& filename, std::string& out_backup_filename); /* Recover filter (used as callback), will only let keys (cryptographical keys) as KV/key-type pass through */ static bool RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, CDataStream ssValue); /* Function to determine if a certain KV/key-type is a key (cryptographical key) type */ @@ -212,9 +233,6 @@ public: //! write the hdchain model (external chain child index counter) bool WriteHDChain(const CHDChain& chain); - static void IncrementUpdateCounter(); - static unsigned int GetUpdateCounter(); - //! Begin a new transaction bool TxnBegin(); //! Commit current transaction @@ -227,6 +245,7 @@ public: bool WriteVersion(int nVersion); private: CDB batch; + CWalletDBWrapper& m_dbw; CWalletDB(const CWalletDB&); void operator=(const CWalletDB&); |