aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am5
-rw-r--r--src/addrdb.cpp6
-rw-r--r--src/bech32.h5
-rw-r--r--src/bench/perf.h6
-rw-r--r--src/bench/verify_script.cpp2
-rw-r--r--src/bitcoind.cpp12
-rw-r--r--src/blockencodings.h6
-rw-r--r--src/chainparams.cpp1
-rw-r--r--src/compressor.cpp30
-rw-r--r--src/compressor.h31
-rw-r--r--src/consensus/merkle.h6
-rw-r--r--src/dbwrapper.cpp31
-rw-r--r--src/httprpc.cpp6
-rw-r--r--src/init.cpp81
-rw-r--r--src/init.h10
-rw-r--r--src/key_io.h6
-rw-r--r--src/keystore.cpp4
-rw-r--r--src/keystore.h15
-rw-r--r--src/miner.cpp4
-rw-r--r--src/netaddress.h8
-rw-r--r--src/policy/fees.h8
-rw-r--r--src/policy/policy.cpp4
-rw-r--r--src/policy/rbf.cpp8
-rw-r--r--src/policy/rbf.h8
-rw-r--r--src/protocol.h6
-rw-r--r--src/qt/bitcoin.cpp37
-rw-r--r--src/qt/bitcoingui.cpp62
-rw-r--r--src/qt/bitcoingui.h18
-rw-r--r--src/qt/clientmodel.cpp8
-rw-r--r--src/qt/clientmodel.h10
-rw-r--r--src/qt/forms/debugwindow.ui16
-rw-r--r--src/qt/guiutil.cpp9
-rw-r--r--src/qt/guiutil.h3
-rw-r--r--src/qt/receivecoinsdialog.cpp4
-rw-r--r--src/qt/receiverequestdialog.cpp9
-rw-r--r--src/qt/receiverequestdialog.h6
-rw-r--r--src/qt/recentrequeststablemodel.cpp3
-rw-r--r--src/qt/rpcconsole.cpp58
-rw-r--r--src/qt/rpcconsole.h11
-rw-r--r--src/qt/sendcoinsdialog.cpp5
-rw-r--r--src/qt/test/paymentrequestdata.h5
-rw-r--r--src/qt/test/rpcnestedtests.h6
-rw-r--r--src/qt/utilitydialog.cpp2
-rw-r--r--src/qt/walletframe.cpp11
-rw-r--r--src/qt/walletframe.h3
-rw-r--r--src/qt/walletmodel.cpp16
-rw-r--r--src/qt/walletmodel.h7
-rw-r--r--src/qt/walletview.cpp14
-rw-r--r--src/qt/walletview.h7
-rw-r--r--src/rest.cpp92
-rw-r--r--src/rpc/blockchain.cpp20
-rw-r--r--src/rpc/client.h6
-rw-r--r--src/rpc/mining.cpp12
-rw-r--r--src/rpc/protocol.h6
-rw-r--r--src/rpc/rawtransaction.cpp12
-rw-r--r--src/rpc/register.h6
-rw-r--r--src/rpc/server.cpp6
-rw-r--r--src/rpc/server.h7
-rw-r--r--src/script/bitcoinconsensus.h6
-rw-r--r--src/script/interpreter.cpp18
-rw-r--r--src/script/interpreter.h6
-rw-r--r--src/script/ismine.cpp10
-rw-r--r--src/script/ismine.h10
-rw-r--r--src/script/sign.cpp39
-rw-r--r--src/script/sign.h33
-rw-r--r--src/serialize.h10
-rw-r--r--src/test/blockchain_tests.cpp2
-rw-r--r--src/test/compress_tests.cpp8
-rw-r--r--src/test/data/tx_invalid.json4
-rw-r--r--src/test/multisig_tests.cpp2
-rw-r--r--src/test/net_tests.cpp6
-rw-r--r--src/test/prevector_tests.cpp2
-rw-r--r--src/test/script_tests.cpp134
-rw-r--r--src/test/serialize_tests.cpp16
-rw-r--r--src/test/sighash_tests.cpp4
-rw-r--r--src/test/streams_tests.cpp8
-rw-r--r--src/test/test_bitcoin.cpp2
-rw-r--r--src/test/transaction_tests.cpp2
-rw-r--r--src/test/txvalidationcache_tests.cpp8
-rw-r--r--src/test/util_tests.cpp65
-rw-r--r--src/test/versionbits_tests.cpp20
-rw-r--r--src/txdb.cpp2
-rw-r--r--src/txmempool.cpp2
-rw-r--r--src/txmempool.h2
-rw-r--r--src/util.cpp132
-rw-r--r--src/util.h18
-rw-r--r--src/validation.cpp85
-rw-r--r--src/validation.h5
-rw-r--r--src/versionbits.cpp28
-rw-r--r--src/versionbits.h18
-rw-r--r--src/wallet/coinselection.h6
-rw-r--r--src/wallet/crypter.h4
-rw-r--r--src/wallet/db.cpp10
-rw-r--r--src/wallet/db.h2
-rw-r--r--src/wallet/init.cpp22
-rw-r--r--src/wallet/init.h45
-rw-r--r--src/wallet/rpcdump.cpp2
-rw-r--r--src/wallet/rpcwallet.cpp4
-rw-r--r--src/wallet/test/accounting_tests.cpp2
-rw-r--r--src/wallet/test/coinselector_tests.cpp2
-rw-r--r--src/wallet/test/crypto_tests.cpp2
-rw-r--r--src/wallet/test/wallet_test_fixture.h7
-rw-r--r--src/wallet/wallet.cpp77
-rw-r--r--src/wallet/walletdb.cpp42
-rw-r--r--src/wallet/walletdb.h14
-rw-r--r--src/wallet/walletutil.h6
-rw-r--r--src/walletinitinterface.h51
107 files changed, 1095 insertions, 716 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 7c2fe56d9d..72e5cdb95d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -4,8 +4,8 @@
DIST_SUBDIRS = secp256k1 univalue
-AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) $(HARDENED_LDFLAGS) $(GPROF_LDFLAGS)
-AM_CXXFLAGS = $(HARDENED_CXXFLAGS) $(ERROR_CXXFLAGS) $(GPROF_CXXFLAGS)
+AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) $(HARDENED_LDFLAGS) $(GPROF_LDFLAGS) $(SANITIZER_LDFLAGS)
+AM_CXXFLAGS = $(HARDENED_CXXFLAGS) $(ERROR_CXXFLAGS) $(GPROF_CXXFLAGS) $(SANITIZER_CXXFLAGS)
AM_CPPFLAGS = $(HARDENED_CPPFLAGS)
EXTRA_LIBRARIES =
@@ -162,6 +162,7 @@ BITCOIN_CORE_H = \
validation.h \
validationinterface.h \
versionbits.h \
+ walletinitinterface.h \
wallet/coincontrol.h \
wallet/crypter.h \
wallet/db.h \
diff --git a/src/addrdb.cpp b/src/addrdb.cpp
index 675f3c28af..e4620e63c6 100644
--- a/src/addrdb.cpp
+++ b/src/addrdb.cpp
@@ -22,8 +22,8 @@ bool SerializeDB(Stream& stream, const Data& data)
// Write and commit header, data
try {
CHashWriter hasher(SER_DISK, CLIENT_VERSION);
- stream << FLATDATA(Params().MessageStart()) << data;
- hasher << FLATDATA(Params().MessageStart()) << data;
+ stream << Params().MessageStart() << data;
+ hasher << Params().MessageStart() << data;
stream << hasher.GetHash();
} catch (const std::exception& e) {
return error("%s: Serialize or I/O error - %s", __func__, e.what());
@@ -66,7 +66,7 @@ bool DeserializeDB(Stream& stream, Data& data, bool fCheckSum = true)
CHashVerifier<Stream> verifier(&stream);
// de-serialize file header (network specific magic number) and ..
unsigned char pchMsgTmp[4];
- verifier >> FLATDATA(pchMsgTmp);
+ verifier >> pchMsgTmp;
// ... verify the network matches ours
if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
return error("%s: Invalid network magic number", __func__);
diff --git a/src/bech32.h b/src/bech32.h
index 7ef7b22213..2e2823e974 100644
--- a/src/bech32.h
+++ b/src/bech32.h
@@ -9,6 +9,9 @@
//
// For more information, see BIP 173.
+#ifndef BITCOIN_BECH32_H
+#define BITCOIN_BECH32_H
+
#include <stdint.h>
#include <string>
#include <vector>
@@ -23,3 +26,5 @@ std::string Encode(const std::string& hrp, const std::vector<uint8_t>& values);
std::pair<std::string, std::vector<uint8_t>> Decode(const std::string& str);
} // namespace bech32
+
+#endif // BITCOIN_BECH32_H
diff --git a/src/bench/perf.h b/src/bench/perf.h
index 681bd0c8a2..73ea8b9647 100644
--- a/src/bench/perf.h
+++ b/src/bench/perf.h
@@ -3,8 +3,8 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/** Functions for measurement of CPU cycles */
-#ifndef H_PERF
-#define H_PERF
+#ifndef BITCOIN_BENCH_PERF_H
+#define BITCOIN_BENCH_PERF_H
#include <stdint.h>
@@ -34,4 +34,4 @@ uint64_t perf_cpucycles(void);
void perf_init(void);
void perf_fini(void);
-#endif // H_PERF
+#endif // BITCOIN_BENCH_PERF_H
diff --git a/src/bench/verify_script.cpp b/src/bench/verify_script.cpp
index 29dedeef0b..705fa368a5 100644
--- a/src/bench/verify_script.cpp
+++ b/src/bench/verify_script.cpp
@@ -75,7 +75,7 @@ static void VerifyScriptBench(benchmark::State& state)
CMutableTransaction txSpend = BuildSpendingTransaction(scriptSig, txCredit);
CScriptWitness& witness = txSpend.vin[0].scriptWitness;
witness.stack.emplace_back();
- key.Sign(SignatureHash(witScriptPubkey, txSpend, 0, SIGHASH_ALL, txCredit.vout[0].nValue, SIGVERSION_WITNESS_V0), witness.stack.back(), 0);
+ key.Sign(SignatureHash(witScriptPubkey, txSpend, 0, SIGHASH_ALL, txCredit.vout[0].nValue, SigVersion::WITNESS_V0), witness.stack.back(), 0);
witness.stack.back().push_back(static_cast<unsigned char>(SIGHASH_ALL));
witness.stack.push_back(ToByteVector(pubkey));
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index d3eb60725f..df7fad89c2 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -18,6 +18,10 @@
#include <httpserver.h>
#include <httprpc.h>
#include <utilstrencodings.h>
+#if ENABLE_WALLET
+#include <wallet/init.h>
+#endif
+#include <walletinitinterface.h>
#include <boost/thread.hpp>
@@ -59,6 +63,12 @@ bool AppInit(int argc, char* argv[])
{
bool fRet = false;
+#if ENABLE_WALLET
+ g_wallet_init_interface.reset(new WalletInit);
+#else
+ g_wallet_init_interface.reset(new DummyWalletInit);
+#endif
+
//
// Parameters
//
@@ -79,7 +89,7 @@ bool AppInit(int argc, char* argv[])
strUsage += "\n" + _("Usage:") + "\n" +
" bitcoind [options] " + strprintf(_("Start %s Daemon"), _(PACKAGE_NAME)) + "\n";
- strUsage += "\n" + HelpMessage(HMM_BITCOIND);
+ strUsage += "\n" + HelpMessage(HelpMessageMode::BITCOIND);
}
fprintf(stdout, "%s", strUsage.c_str());
diff --git a/src/blockencodings.h b/src/blockencodings.h
index f80821aa65..3a0828b307 100644
--- a/src/blockencodings.h
+++ b/src/blockencodings.h
@@ -2,8 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_BLOCK_ENCODINGS_H
-#define BITCOIN_BLOCK_ENCODINGS_H
+#ifndef BITCOIN_BLOCKENCODINGS_H
+#define BITCOIN_BLOCKENCODINGS_H
#include <primitives/block.h>
@@ -206,4 +206,4 @@ public:
ReadStatus FillBlock(CBlock& block, const std::vector<CTransactionRef>& vtx_missing);
};
-#endif
+#endif // BITCOIN_BLOCKENCODINGS_H
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index c2b3480f9d..6067503b0b 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -135,6 +135,7 @@ public:
vSeeds.emplace_back("seed.bitcoinstats.com"); // Christian Decker, supports x1 - xf
vSeeds.emplace_back("seed.bitcoin.jonasschnelli.ch"); // Jonas Schnelli, only supports x1, x5, x9, and xd
vSeeds.emplace_back("seed.btc.petertodd.org"); // Peter Todd, only supports x1, x5, x9, and xd
+ vSeeds.emplace_back("seed.bitcoin.sprovoost.nl"); // Sjors Provoost
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,0);
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,5);
diff --git a/src/compressor.cpp b/src/compressor.cpp
index 86de2900e9..da639a01af 100644
--- a/src/compressor.cpp
+++ b/src/compressor.cpp
@@ -9,7 +9,15 @@
#include <pubkey.h>
#include <script/standard.h>
-bool CScriptCompressor::IsToKeyID(CKeyID &hash) const
+/*
+ * These check for scripts for which a special case with a shorter encoding is defined.
+ * They are implemented separately from the CScript test, as these test for exact byte
+ * sequence correspondences, and are more strict. For example, IsToPubKey also verifies
+ * whether the public key is valid (as invalid ones cannot be represented in compressed
+ * form).
+ */
+
+static bool IsToKeyID(const CScript& script, CKeyID &hash)
{
if (script.size() == 25 && script[0] == OP_DUP && script[1] == OP_HASH160
&& script[2] == 20 && script[23] == OP_EQUALVERIFY
@@ -20,7 +28,7 @@ bool CScriptCompressor::IsToKeyID(CKeyID &hash) const
return false;
}
-bool CScriptCompressor::IsToScriptID(CScriptID &hash) const
+static bool IsToScriptID(const CScript& script, CScriptID &hash)
{
if (script.size() == 23 && script[0] == OP_HASH160 && script[1] == 20
&& script[22] == OP_EQUAL) {
@@ -30,7 +38,7 @@ bool CScriptCompressor::IsToScriptID(CScriptID &hash) const
return false;
}
-bool CScriptCompressor::IsToPubKey(CPubKey &pubkey) const
+static bool IsToPubKey(const CScript& script, CPubKey &pubkey)
{
if (script.size() == 35 && script[0] == 33 && script[34] == OP_CHECKSIG
&& (script[1] == 0x02 || script[1] == 0x03)) {
@@ -45,24 +53,24 @@ bool CScriptCompressor::IsToPubKey(CPubKey &pubkey) const
return false;
}
-bool CScriptCompressor::Compress(std::vector<unsigned char> &out) const
+bool CompressScript(const CScript& script, std::vector<unsigned char> &out)
{
CKeyID keyID;
- if (IsToKeyID(keyID)) {
+ if (IsToKeyID(script, keyID)) {
out.resize(21);
out[0] = 0x00;
memcpy(&out[1], &keyID, 20);
return true;
}
CScriptID scriptID;
- if (IsToScriptID(scriptID)) {
+ if (IsToScriptID(script, scriptID)) {
out.resize(21);
out[0] = 0x01;
memcpy(&out[1], &scriptID, 20);
return true;
}
CPubKey pubkey;
- if (IsToPubKey(pubkey)) {
+ if (IsToPubKey(script, pubkey)) {
out.resize(33);
memcpy(&out[1], &pubkey[1], 32);
if (pubkey[0] == 0x02 || pubkey[0] == 0x03) {
@@ -76,7 +84,7 @@ bool CScriptCompressor::Compress(std::vector<unsigned char> &out) const
return false;
}
-unsigned int CScriptCompressor::GetSpecialSize(unsigned int nSize) const
+unsigned int GetSpecialScriptSize(unsigned int nSize)
{
if (nSize == 0 || nSize == 1)
return 20;
@@ -85,7 +93,7 @@ unsigned int CScriptCompressor::GetSpecialSize(unsigned int nSize) const
return 0;
}
-bool CScriptCompressor::Decompress(unsigned int nSize, const std::vector<unsigned char> &in)
+bool DecompressScript(CScript& script, unsigned int nSize, const std::vector<unsigned char> &in)
{
switch(nSize) {
case 0x00:
@@ -139,7 +147,7 @@ bool CScriptCompressor::Decompress(unsigned int nSize, const std::vector<unsigne
// * if e==9, we only know the resulting number is not zero, so output 1 + 10*(n - 1) + 9
// (this is decodable, as d is in [1-9] and e is in [0-9])
-uint64_t CTxOutCompressor::CompressAmount(uint64_t n)
+uint64_t CompressAmount(uint64_t n)
{
if (n == 0)
return 0;
@@ -158,7 +166,7 @@ uint64_t CTxOutCompressor::CompressAmount(uint64_t n)
}
}
-uint64_t CTxOutCompressor::DecompressAmount(uint64_t x)
+uint64_t DecompressAmount(uint64_t x)
{
// x = 0 OR x = 1+10*(9*n + d - 1) + e OR x = 1+10*(n - 1) + 9
if (x == 0)
diff --git a/src/compressor.h b/src/compressor.h
index 6fcecd27e9..561c8e66d0 100644
--- a/src/compressor.h
+++ b/src/compressor.h
@@ -14,6 +14,13 @@ class CKeyID;
class CPubKey;
class CScriptID;
+bool CompressScript(const CScript& script, std::vector<unsigned char> &out);
+unsigned int GetSpecialScriptSize(unsigned int nSize);
+bool DecompressScript(CScript& script, unsigned int nSize, const std::vector<unsigned char> &out);
+
+uint64_t CompressAmount(uint64_t nAmount);
+uint64_t DecompressAmount(uint64_t nAmount);
+
/** Compact serializer for scripts.
*
* It detects common cases and encodes them much more efficiently.
@@ -37,28 +44,13 @@ private:
static const unsigned int nSpecialScripts = 6;
CScript &script;
-protected:
- /**
- * These check for scripts for which a special case with a shorter encoding is defined.
- * They are implemented separately from the CScript test, as these test for exact byte
- * sequence correspondences, and are more strict. For example, IsToPubKey also verifies
- * whether the public key is valid (as invalid ones cannot be represented in compressed
- * form).
- */
- bool IsToKeyID(CKeyID &hash) const;
- bool IsToScriptID(CScriptID &hash) const;
- bool IsToPubKey(CPubKey &pubkey) const;
-
- bool Compress(std::vector<unsigned char> &out) const;
- unsigned int GetSpecialSize(unsigned int nSize) const;
- bool Decompress(unsigned int nSize, const std::vector<unsigned char> &out);
public:
explicit CScriptCompressor(CScript &scriptIn) : script(scriptIn) { }
template<typename Stream>
void Serialize(Stream &s) const {
std::vector<unsigned char> compr;
- if (Compress(compr)) {
+ if (CompressScript(script, compr)) {
s << CFlatData(compr);
return;
}
@@ -72,9 +64,9 @@ public:
unsigned int nSize = 0;
s >> VARINT(nSize);
if (nSize < nSpecialScripts) {
- std::vector<unsigned char> vch(GetSpecialSize(nSize), 0x00);
+ std::vector<unsigned char> vch(GetSpecialScriptSize(nSize), 0x00);
s >> CFlatData(vch);
- Decompress(nSize, vch);
+ DecompressScript(script, nSize, vch);
return;
}
nSize -= nSpecialScripts;
@@ -96,9 +88,6 @@ private:
CTxOut &txout;
public:
- static uint64_t CompressAmount(uint64_t nAmount);
- static uint64_t DecompressAmount(uint64_t nAmount);
-
explicit CTxOutCompressor(CTxOut &txoutIn) : txout(txoutIn) { }
ADD_SERIALIZE_METHODS;
diff --git a/src/consensus/merkle.h b/src/consensus/merkle.h
index d57bb3412e..0afb73adb5 100644
--- a/src/consensus/merkle.h
+++ b/src/consensus/merkle.h
@@ -2,8 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_MERKLE
-#define BITCOIN_MERKLE
+#ifndef BITCOIN_CONSENSUS_MERKLE_H
+#define BITCOIN_CONSENSUS_MERKLE_H
#include <stdint.h>
#include <vector>
@@ -35,4 +35,4 @@ uint256 BlockWitnessMerkleRoot(const CBlock& block, bool* mutated = nullptr);
*/
std::vector<uint256> BlockMerkleBranch(const CBlock& block, uint32_t position);
-#endif
+#endif // BITCOIN_CONSENSUS_MERKLE_H
diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp
index fb0d4215a2..752f985bc0 100644
--- a/src/dbwrapper.cpp
+++ b/src/dbwrapper.cpp
@@ -71,6 +71,31 @@ public:
}
};
+static void SetMaxOpenFiles(leveldb::Options *options) {
+ // On most platforms the default setting of max_open_files (which is 1000)
+ // is optimal. On Windows using a large file count is OK because the handles
+ // do not interfere with select() loops. On 64-bit Unix hosts this value is
+ // also OK, because up to that amount LevelDB will use an mmap
+ // implementation that does not use extra file descriptors (the fds are
+ // closed after being mmaped).
+ //
+ // Increasing the value beyond the default is dangerous because LevelDB will
+ // fall back to a non-mmap implementation when the file count is too large.
+ // On 32-bit Unix host we should decrease the value because the handles use
+ // up real fds, and we want to avoid fd exhaustion issues.
+ //
+ // See PR #12495 for further discussion.
+
+ int default_open_files = options->max_open_files;
+#ifndef WIN32
+ if (sizeof(void*) < 8) {
+ options->max_open_files = 64;
+ }
+#endif
+ LogPrint(BCLog::LEVELDB, "LevelDB using max_open_files=%d (default=%d)\n",
+ options->max_open_files, default_open_files);
+}
+
static leveldb::Options GetOptions(size_t nCacheSize)
{
leveldb::Options options;
@@ -78,13 +103,13 @@ static leveldb::Options GetOptions(size_t nCacheSize)
options.write_buffer_size = nCacheSize / 4; // up to two write buffers may be held in memory simultaneously
options.filter_policy = leveldb::NewBloomFilterPolicy(10);
options.compression = leveldb::kNoCompression;
- options.max_open_files = 64;
options.info_log = new CBitcoinLevelDBLogger();
if (leveldb::kMajorVersion > 1 || (leveldb::kMajorVersion == 1 && leveldb::kMinorVersion >= 16)) {
// LevelDB versions before 1.16 consider short writes to be corruption. Only trigger error
// on corruption in later versions.
options.paranoid_checks = true;
}
+ SetMaxOpenFiles(&options);
return options;
}
@@ -159,12 +184,12 @@ bool CDBWrapper::WriteBatch(CDBBatch& batch, bool fSync)
const bool log_memory = LogAcceptCategory(BCLog::LEVELDB);
double mem_before = 0;
if (log_memory) {
- mem_before = DynamicMemoryUsage() / 1024 / 1024;
+ mem_before = DynamicMemoryUsage() / 1024.0 / 1024;
}
leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch);
dbwrapper_private::HandleError(status);
if (log_memory) {
- double mem_after = DynamicMemoryUsage() / 1024 / 1024;
+ double mem_after = DynamicMemoryUsage() / 1024.0 / 1024;
LogPrint(BCLog::LEVELDB, "WriteBatch memory usage: db=%s, before=%.1fMiB, after=%.1fMiB\n",
m_name, mem_before, mem_after);
}
diff --git a/src/httprpc.cpp b/src/httprpc.cpp
index 82ae733006..0a70619ba6 100644
--- a/src/httprpc.cpp
+++ b/src/httprpc.cpp
@@ -158,8 +158,9 @@ static bool HTTPReq_JSONRPC(HTTPRequest* req, const std::string &)
}
JSONRPCRequest jreq;
+ jreq.peerAddr = req->GetPeer().ToString();
if (!RPCAuthorized(authHeader.second, jreq.authUser)) {
- LogPrintf("ThreadRPCServer incorrect password attempt from %s\n", req->GetPeer().ToString());
+ LogPrintf("ThreadRPCServer incorrect password attempt from %s\n", jreq.peerAddr);
/* Deter brute-forcing
If this results in a DoS the user really
@@ -252,6 +253,9 @@ void StopHTTPRPC()
{
LogPrint(BCLog::RPC, "Stopping HTTP RPC server\n");
UnregisterHTTPHandler("/", true);
+#ifdef ENABLE_WALLET
+ UnregisterHTTPHandler("/wallet/", false);
+#endif
if (httpRPCTimerInterface) {
RPCUnsetTimerInterface(httpRPCTimerInterface.get());
httpRPCTimerInterface.reset();
diff --git a/src/init.cpp b/src/init.cpp
index 30ee0e694c..f6f522da66 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -43,10 +43,8 @@
#include <util.h>
#include <utilmoneystr.h>
#include <validationinterface.h>
-#ifdef ENABLE_WALLET
-#include <wallet/init.h>
-#endif
#include <warnings.h>
+#include <walletinitinterface.h>
#include <stdint.h>
#include <stdio.h>
#include <memory>
@@ -74,6 +72,7 @@ static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false;
std::unique_ptr<CConnman> g_connman;
std::unique_ptr<PeerLogicValidation> peerLogic;
+std::unique_ptr<WalletInitInterface> g_wallet_init_interface;
#if ENABLE_ZMQ
static CZMQNotificationInterface* pzmqNotificationInterface = nullptr;
@@ -116,7 +115,6 @@ static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat";
//
std::atomic<bool> fRequestShutdown(false);
-std::atomic<bool> fDumpMempoolLater(false);
void StartShutdown()
{
@@ -189,9 +187,7 @@ void Shutdown()
StopREST();
StopRPC();
StopHTTPServer();
-#ifdef ENABLE_WALLET
- FlushWallets();
-#endif
+ g_wallet_init_interface->Flush();
StopMapPort();
// Because these depend on each-other, we make sure that neither can be
@@ -208,7 +204,7 @@ void Shutdown()
threadGroup.interrupt_all();
threadGroup.join_all();
- if (fDumpMempoolLater && gArgs.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
+ if (g_is_mempool_loaded && gArgs.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
DumpMempool();
}
@@ -249,9 +245,7 @@ void Shutdown()
pcoinsdbview.reset();
pblocktree.reset();
}
-#ifdef ENABLE_WALLET
- StopWallets();
-#endif
+ g_wallet_init_interface->Stop();
#if ENABLE_ZMQ
if (pzmqNotificationInterface) {
@@ -271,9 +265,8 @@ void Shutdown()
UnregisterAllValidationInterfaces();
GetMainSignals().UnregisterBackgroundSignalScheduler();
GetMainSignals().UnregisterWithMempoolSignals(mempool);
-#ifdef ENABLE_WALLET
- CloseWallets();
-#endif
+ g_wallet_init_interface->Close();
+ g_wallet_init_interface.reset();
globalVerifyHandle.reset();
ECC_Stop();
LogPrintf("%s: done\n", __func__);
@@ -333,12 +326,13 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-version", _("Print version and exit"));
strUsage += HelpMessageOpt("-alertnotify=<cmd>", _("Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)"));
strUsage +=HelpMessageOpt("-assumevalid=<hex>", strprintf(_("If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)"), defaultChainParams->GetConsensus().defaultAssumeValid.GetHex(), testnetChainParams->GetConsensus().defaultAssumeValid.GetHex()));
+ strUsage += HelpMessageOpt("-blocksdir=<dir>", _("Specify blocks directory (default: <datadir>/blocks)"));
strUsage += HelpMessageOpt("-blocknotify=<cmd>", _("Execute command when the best block changes (%s in cmd is replaced by block hash)"));
strUsage += HelpMessageOpt("-blockreconstructionextratxn=<n>", strprintf(_("Extra transactions to keep in memory for compact block reconstructions (default: %u)"), DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN));
if (showDebug)
strUsage += HelpMessageOpt("-blocksonly", strprintf(_("Whether to operate in a blocks only mode (default: %u)"), DEFAULT_BLOCKSONLY));
strUsage += HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file. Relative paths will be prefixed by datadir location. (default: %s)"), BITCOIN_CONF_FILENAME));
- if (mode == HMM_BITCOIND)
+ if (mode == HelpMessageMode::BITCOIND)
{
#if HAVE_DECL_DAEMON
strUsage += HelpMessageOpt("-daemon", _("Run in the background as a daemon and accept commands"));
@@ -415,9 +409,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-whitelist=<IP address or network>", _("Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times.") +
" " + _("Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway"));
-#ifdef ENABLE_WALLET
- strUsage += GetWalletHelpString(showDebug);
-#endif
+ strUsage += g_wallet_init_interface->GetHelpString(showDebug);
#if ENABLE_ZMQ
strUsage += HelpMessageGroup(_("ZeroMQ notification options:"));
@@ -428,18 +420,16 @@ std::string HelpMessage(HelpMessageMode mode)
#endif
strUsage += HelpMessageGroup(_("Debugging/Testing options:"));
- if (showDebug)
- {
+ if (showDebug) {
strUsage += HelpMessageOpt("-checkblocks=<n>", strprintf(_("How many blocks to check at startup (default: %u, 0 = all)"), DEFAULT_CHECKBLOCKS));
strUsage += HelpMessageOpt("-checklevel=<n>", strprintf(_("How thorough the block verification of -checkblocks is (0-4, default: %u)"), DEFAULT_CHECKLEVEL));
- strUsage += HelpMessageOpt("-checkblockindex", strprintf("Do a full consistency check for mapBlockIndex, setBlockIndexCandidates, chainActive and mapBlocksUnlinked occasionally. Also sets -checkmempool (default: %u)", defaultChainParams->DefaultConsistencyChecks()));
+ strUsage += HelpMessageOpt("-checkblockindex", strprintf("Do a full consistency check for mapBlockIndex, setBlockIndexCandidates, chainActive and mapBlocksUnlinked occasionally. (default: %u)", defaultChainParams->DefaultConsistencyChecks()));
strUsage += HelpMessageOpt("-checkmempool=<n>", strprintf("Run checks every <n> transactions (default: %u)", defaultChainParams->DefaultConsistencyChecks()));
strUsage += HelpMessageOpt("-checkpoints", strprintf("Disable expensive verification for known chain history (default: %u)", DEFAULT_CHECKPOINTS_ENABLED));
strUsage += HelpMessageOpt("-disablesafemode", strprintf("Disable safemode, override a real safe mode event (default: %u)", DEFAULT_DISABLE_SAFEMODE));
strUsage += HelpMessageOpt("-deprecatedrpc=<method>", "Allows deprecated RPC method(s) to be used");
strUsage += HelpMessageOpt("-testsafemode", strprintf("Force safe mode (default: %u)", DEFAULT_TESTSAFEMODE));
strUsage += HelpMessageOpt("-dropmessagestest=<n>", "Randomly drop 1 of every <n> network messages");
- strUsage += HelpMessageOpt("-fuzzmessagestest=<n>", "Randomly fuzz 1 of every <n> network messages");
strUsage += HelpMessageOpt("-stopafterblockimport", strprintf("Stop running after importing blocks from disk (default: %u)", DEFAULT_STOPAFTERBLOCKIMPORT));
strUsage += HelpMessageOpt("-stopatheight", strprintf("Stop running after reaching the given height in the main chain (default: %u)", DEFAULT_STOPATHEIGHT));
@@ -491,8 +481,6 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-whitelistrelay", strprintf(_("Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)"), DEFAULT_WHITELISTRELAY));
strUsage += HelpMessageGroup(_("Block creation options:"));
- if (showDebug)
- strUsage += HelpMessageOpt("-blockmaxsize=<n>", "Set maximum BIP141 block weight to this * 4. Deprecated, use blockmaxweight");
strUsage += HelpMessageOpt("-blockmaxweight=<n>", strprintf(_("Set maximum BIP141 block weight (default: %d)"), DEFAULT_BLOCK_MAX_WEIGHT));
strUsage += HelpMessageOpt("-blockmintxfee=<amt>", strprintf(_("Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)"), CURRENCY_UNIT, FormatMoney(DEFAULT_BLOCK_MIN_TX_FEE)));
if (showDebug)
@@ -596,7 +584,7 @@ void CleanupBlockRevFiles()
// Remove the rev files immediately and insert the blk file paths into an
// ordered map keyed by block file index.
LogPrintf("Removing unusable blk?????.dat and rev?????.dat files for -reindex with -prune\n");
- fs::path blocksdir = GetDataDir() / "blocks";
+ fs::path blocksdir = GetBlocksDir();
for (fs::directory_iterator it(blocksdir); it != fs::directory_iterator(); it++) {
if (fs::is_regular_file(*it) &&
it->path().filename().string().length() == 12 &&
@@ -693,8 +681,8 @@ void ThreadImport(std::vector<fs::path> vImportFiles)
} // End scope of CImportingNow
if (gArgs.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
LoadMempool();
- fDumpMempoolLater = !fRequestShutdown;
}
+ g_is_mempool_loaded = !fRequestShutdown;
}
/** Sanity checks
@@ -798,15 +786,6 @@ void InitParameterInteraction()
if (gArgs.SoftSetBoolArg("-whitelistrelay", true))
LogPrintf("%s: parameter interaction: -whitelistforcerelay=1 -> setting -whitelistrelay=1\n", __func__);
}
-
- if (gArgs.IsArgSet("-blockmaxsize")) {
- unsigned int max_size = gArgs.GetArg("-blockmaxsize", 0);
- if (gArgs.SoftSetArg("blockmaxweight", strprintf("%d", max_size * WITNESS_SCALE_FACTOR))) {
- LogPrintf("%s: parameter interaction: -blockmaxsize=%d -> setting -blockmaxweight=%d (-blockmaxsize is deprecated!)\n", __func__, max_size, max_size * WITNESS_SCALE_FACTOR);
- } else {
- LogPrintf("%s: Ignoring blockmaxsize setting which is overridden by blockmaxweight", __func__);
- }
- }
}
static std::string ResolveErrMsg(const char * const optname, const std::string& strBind)
@@ -908,6 +887,10 @@ bool AppInitParameterInteraction()
// also see: InitParameterInteraction()
+ if (!fs::is_directory(GetBlocksDir(false))) {
+ return InitError(strprintf(_("Specified blocks directory \"%s\" does not exist.\n"), gArgs.GetArg("-blocksdir", "").c_str()));
+ }
+
// if using block pruning, then disallow txindex
if (gArgs.GetArg("-prune", 0)) {
if (gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX))
@@ -1093,10 +1076,7 @@ bool AppInitParameterInteraction()
return InitError(strprintf("acceptnonstdtxn is not currently supported for %s chain", chainparams.NetworkIDString()));
nBytesPerSigOp = gArgs.GetArg("-bytespersigop", nBytesPerSigOp);
-#ifdef ENABLE_WALLET
- if (!WalletParameterInteraction())
- return false;
-#endif
+ if (!g_wallet_init_interface->ParameterInteraction()) return false;
fIsBareMultisigStd = gArgs.GetBoolArg("-permitbaremultisig", DEFAULT_PERMIT_BAREMULTISIG);
fAcceptDatacarrier = gArgs.GetBoolArg("-datacarrier", DEFAULT_ACCEPT_DATACARRIER);
@@ -1262,9 +1242,7 @@ bool AppInitMain()
* available in the GUI RPC console even if external calls are disabled.
*/
RegisterAllCoreRPCCommands(tableRPC);
-#ifdef ENABLE_WALLET
- RegisterWalletRPC(tableRPC);
-#endif
+ g_wallet_init_interface->RegisterRPC(tableRPC);
/* Start the RPC server already. It will be started in "warmup" mode
* and not really process calls already (but it will signify connections
@@ -1281,10 +1259,8 @@ bool AppInitMain()
int64_t nStart;
// ********************************************************* Step 5: verify wallet database integrity
-#ifdef ENABLE_WALLET
- if (!VerifyWallets())
- return false;
-#endif
+ if (!g_wallet_init_interface->Verify()) return false;
+
// ********************************************************* Step 6: network initialization
// Note that we absolutely cannot open any actual connections
// until the very end ("start node") as the UTXO/block state
@@ -1602,12 +1578,7 @@ bool AppInitMain()
fFeeEstimatesInitialized = true;
// ********************************************************* Step 8: load wallet
-#ifdef ENABLE_WALLET
- if (!OpenWallets())
- return false;
-#else
- LogPrintf("No wallet support compiled in!\n");
-#endif
+ if (!g_wallet_init_interface->Open()) return false;
// ********************************************************* Step 9: data directory maintenance
@@ -1633,7 +1604,7 @@ bool AppInitMain()
// ********************************************************* Step 10: import blocks
- if (!CheckDiskSpace())
+ if (!CheckDiskSpace() && !CheckDiskSpace(0, true))
return false;
// Either install a handler to notify us when genesis activates, or set fHaveGenesis directly.
@@ -1753,9 +1724,7 @@ bool AppInitMain()
SetRPCWarmupFinished();
uiInterface.InitMessage(_("Done loading"));
-#ifdef ENABLE_WALLET
- StartWallets(scheduler);
-#endif
+ g_wallet_init_interface->Start(scheduler);
return true;
}
diff --git a/src/init.h b/src/init.h
index 33f97a55a5..c93a210154 100644
--- a/src/init.h
+++ b/src/init.h
@@ -6,11 +6,15 @@
#ifndef BITCOIN_INIT_H
#define BITCOIN_INIT_H
+#include <memory>
#include <string>
class CScheduler;
class CWallet;
+class WalletInitInterface;
+extern std::unique_ptr<WalletInitInterface> g_wallet_init_interface;
+
namespace boost
{
class thread_group;
@@ -57,9 +61,9 @@ bool AppInitLockDataDirectory();
bool AppInitMain();
/** The help message mode determines what help message to show */
-enum HelpMessageMode {
- HMM_BITCOIND,
- HMM_BITCOIN_QT
+enum class HelpMessageMode {
+ BITCOIND,
+ BITCOIN_QT
};
/** Help for options shared between UI and daemon (for -help) */
diff --git a/src/key_io.h b/src/key_io.h
index 6fc9a8059a..d75b5b31c8 100644
--- a/src/key_io.h
+++ b/src/key_io.h
@@ -3,8 +3,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_KEYIO_H
-#define BITCOIN_KEYIO_H
+#ifndef BITCOIN_KEY_IO_H
+#define BITCOIN_KEY_IO_H
#include <chainparams.h>
#include <key.h>
@@ -26,4 +26,4 @@ CTxDestination DecodeDestination(const std::string& str);
bool IsValidDestinationString(const std::string& str);
bool IsValidDestinationString(const std::string& str, const CChainParams& params);
-#endif // BITCOIN_KEYIO_H
+#endif // BITCOIN_KEY_IO_H
diff --git a/src/keystore.cpp b/src/keystore.cpp
index fab1b81c9a..dfdfa5ea9f 100644
--- a/src/keystore.cpp
+++ b/src/keystore.cpp
@@ -7,10 +7,6 @@
#include <util.h>
-bool CKeyStore::AddKey(const CKey &key) {
- return AddKeyPubKey(key, key.GetPubKey());
-}
-
void CBasicKeyStore::ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey)
{
AssertLockHeld(cs_KeyStore);
diff --git a/src/keystore.h b/src/keystore.h
index ffd3238fd6..fa912cb195 100644
--- a/src/keystore.h
+++ b/src/keystore.h
@@ -9,35 +9,27 @@
#include <key.h>
#include <pubkey.h>
#include <script/script.h>
+#include <script/sign.h>
#include <script/standard.h>
#include <sync.h>
#include <boost/signals2/signal.hpp>
/** A virtual base class for key stores */
-class CKeyStore
+class CKeyStore : public SigningProvider
{
-protected:
- mutable CCriticalSection cs_KeyStore;
-
public:
- virtual ~CKeyStore() {}
-
//! Add a key to the store.
virtual bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey) =0;
- virtual bool AddKey(const CKey &key);
//! Check whether a key corresponding to a given address is present in the store.
virtual bool HaveKey(const CKeyID &address) const =0;
- virtual bool GetKey(const CKeyID &address, CKey& keyOut) const =0;
virtual std::set<CKeyID> GetKeys() const =0;
- virtual bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const =0;
//! Support for BIP 0013 : see https://github.com/bitcoin/bips/blob/master/bip-0013.mediawiki
virtual bool AddCScript(const CScript& redeemScript) =0;
virtual bool HaveCScript(const CScriptID &hash) const =0;
virtual std::set<CScriptID> GetCScripts() const =0;
- virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const =0;
//! Support for Watch-only addresses
virtual bool AddWatchOnly(const CScript &dest) =0;
@@ -55,6 +47,8 @@ typedef std::set<CScript> WatchOnlySet;
class CBasicKeyStore : public CKeyStore
{
protected:
+ mutable CCriticalSection cs_KeyStore;
+
KeyMap mapKeys;
WatchKeyMap mapWatchKeys;
ScriptMap mapScripts;
@@ -64,6 +58,7 @@ protected:
public:
bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey) override;
+ bool AddKey(const CKey &key) { return AddKeyPubKey(key, key.GetPubKey()); }
bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const override;
bool HaveKey(const CKeyID &address) const override;
std::set<CKeyID> GetKeys() const override;
diff --git a/src/miner.cpp b/src/miner.cpp
index 4b86446774..0660df928c 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -68,9 +68,7 @@ BlockAssembler::BlockAssembler(const CChainParams& params, const Options& option
static BlockAssembler::Options DefaultOptions(const CChainParams& params)
{
// Block resource limits
- // If neither -blockmaxsize or -blockmaxweight is given, limit to DEFAULT_BLOCK_MAX_*
- // If only one is given, only restrict the specified resource.
- // If both are given, restrict both.
+ // If -blockmaxweight is not given, limit to DEFAULT_BLOCK_MAX_WEIGHT
BlockAssembler::Options options;
options.nBlockMaxWeight = gArgs.GetArg("-blockmaxweight", DEFAULT_BLOCK_MAX_WEIGHT);
if (gArgs.IsArgSet("-blockmintxfee")) {
diff --git a/src/netaddress.h b/src/netaddress.h
index 93bbb66491..ad6b55eb58 100644
--- a/src/netaddress.h
+++ b/src/netaddress.h
@@ -93,7 +93,7 @@ class CNetAddr
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(FLATDATA(ip));
+ READWRITE(ip);
}
friend class CSubNet;
@@ -131,8 +131,8 @@ class CSubNet
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(network);
- READWRITE(FLATDATA(netmask));
- READWRITE(FLATDATA(valid));
+ READWRITE(netmask);
+ READWRITE(valid);
}
};
@@ -166,7 +166,7 @@ class CService : public CNetAddr
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(FLATDATA(ip));
+ READWRITE(ip);
unsigned short portN = htons(port);
READWRITE(FLATDATA(portN));
if (ser_action.ForRead())
diff --git a/src/policy/fees.h b/src/policy/fees.h
index 5f69e989c1..afb4746def 100644
--- a/src/policy/fees.h
+++ b/src/policy/fees.h
@@ -2,8 +2,8 @@
// Copyright (c) 2009-2017 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_POLICYESTIMATOR_H
-#define BITCOIN_POLICYESTIMATOR_H
+#ifndef BITCOIN_POLICY_FEES_H
+#define BITCOIN_POLICY_FEES_H
#include <amount.h>
#include <policy/feerate.h>
@@ -68,7 +68,7 @@ class TxConfirmStats;
/* Identifier for each of the 3 different TxConfirmStats which will track
* history over different time horizons. */
-enum FeeEstimateHorizon {
+enum class FeeEstimateHorizon {
SHORT_HALFLIFE = 0,
MED_HALFLIFE = 1,
LONG_HALFLIFE = 2
@@ -294,4 +294,4 @@ private:
FastRandomContext insecure_rand;
};
-#endif /*BITCOIN_POLICYESTIMATOR_H */
+#endif // BITCOIN_POLICY_FEES_H
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
index db1ad4f26d..c3f65fb2ab 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -179,7 +179,7 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
{
std::vector<std::vector<unsigned char> > stack;
// convert the scriptSig into a stack, so we can inspect the redeemScript
- if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SIGVERSION_BASE))
+ if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SigVersion::BASE))
return false;
if (stack.empty())
return false;
@@ -215,7 +215,7 @@ bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
// If the scriptPubKey is P2SH, we try to extract the redeemScript casually by converting the scriptSig
// into a stack. We do not check IsPushOnly nor compare the hash as these will be done later anyway.
// If the check fails at this stage, we know that this txid must be a bad one.
- if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SIGVERSION_BASE))
+ if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SigVersion::BASE))
return false;
if (stack.empty())
return false;
diff --git a/src/policy/rbf.cpp b/src/policy/rbf.cpp
index c5a1741608..81b2a7fadc 100644
--- a/src/policy/rbf.cpp
+++ b/src/policy/rbf.cpp
@@ -22,13 +22,13 @@ RBFTransactionState IsRBFOptIn(const CTransaction &tx, CTxMemPool &pool)
// First check the transaction itself.
if (SignalsOptInRBF(tx)) {
- return RBF_TRANSACTIONSTATE_REPLACEABLE_BIP125;
+ return RBFTransactionState::REPLACEABLE_BIP125;
}
// If this transaction is not in our mempool, then we can't be sure
// we will know about all its inputs.
if (!pool.exists(tx.GetHash())) {
- return RBF_TRANSACTIONSTATE_UNKNOWN;
+ return RBFTransactionState::UNKNOWN;
}
// If all the inputs have nSequence >= maxint-1, it still might be
@@ -40,8 +40,8 @@ RBFTransactionState IsRBFOptIn(const CTransaction &tx, CTxMemPool &pool)
for (CTxMemPool::txiter it : setAncestors) {
if (SignalsOptInRBF(it->GetTx())) {
- return RBF_TRANSACTIONSTATE_REPLACEABLE_BIP125;
+ return RBFTransactionState::REPLACEABLE_BIP125;
}
}
- return RBF_TRANSACTIONSTATE_FINAL;
+ return RBFTransactionState::FINAL;
}
diff --git a/src/policy/rbf.h b/src/policy/rbf.h
index 72f51b0f03..b10532addf 100644
--- a/src/policy/rbf.h
+++ b/src/policy/rbf.h
@@ -9,10 +9,10 @@
static const uint32_t MAX_BIP125_RBF_SEQUENCE = 0xfffffffd;
-enum RBFTransactionState {
- RBF_TRANSACTIONSTATE_UNKNOWN,
- RBF_TRANSACTIONSTATE_REPLACEABLE_BIP125,
- RBF_TRANSACTIONSTATE_FINAL
+enum class RBFTransactionState {
+ UNKNOWN,
+ REPLACEABLE_BIP125,
+ FINAL
};
// Check whether the sequence numbers on this transaction are signaling
diff --git a/src/protocol.h b/src/protocol.h
index e518d11944..a07c5ea862 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -48,10 +48,10 @@ public:
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
{
- READWRITE(FLATDATA(pchMessageStart));
- READWRITE(FLATDATA(pchCommand));
+ READWRITE(pchMessageStart);
+ READWRITE(pchCommand);
READWRITE(nMessageSize);
- READWRITE(FLATDATA(pchChecksum));
+ READWRITE(pchChecksum);
}
char pchMessageStart[MESSAGE_START_SIZE];
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index ab381bfb5d..f853c04617 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -34,8 +34,10 @@
#include <warnings.h>
#ifdef ENABLE_WALLET
+#include <wallet/init.h>
#include <wallet/wallet.h>
#endif
+#include <walletinitinterface.h>
#include <stdint.h>
@@ -251,7 +253,7 @@ private:
QTimer *pollShutdownTimer;
#ifdef ENABLE_WALLET
PaymentServer* paymentServer;
- WalletModel *walletModel;
+ std::vector<WalletModel*> m_wallet_models;
#endif
int returnValue;
const PlatformStyle *platformStyle;
@@ -333,7 +335,7 @@ BitcoinApplication::BitcoinApplication(int &argc, char **argv):
pollShutdownTimer(0),
#ifdef ENABLE_WALLET
paymentServer(0),
- walletModel(0),
+ m_wallet_models(),
#endif
returnValue(0)
{
@@ -451,8 +453,10 @@ void BitcoinApplication::requestShutdown()
#ifdef ENABLE_WALLET
window->removeAllWallets();
- delete walletModel;
- walletModel = 0;
+ for (WalletModel *walletModel : m_wallet_models) {
+ delete walletModel;
+ }
+ m_wallet_models.clear();
#endif
delete clientModel;
clientModel = 0;
@@ -481,16 +485,20 @@ void BitcoinApplication::initializeResult(bool success)
window->setClientModel(clientModel);
#ifdef ENABLE_WALLET
- // TODO: Expose secondary wallets
- if (!vpwallets.empty())
- {
- walletModel = new WalletModel(platformStyle, vpwallets[0], optionsModel);
+ bool fFirstWallet = true;
+ for (CWalletRef pwallet : vpwallets) {
+ WalletModel * const walletModel = new WalletModel(platformStyle, pwallet, optionsModel);
- window->addWallet(BitcoinGUI::DEFAULT_WALLET, walletModel);
- window->setCurrentWallet(BitcoinGUI::DEFAULT_WALLET);
+ window->addWallet(walletModel);
+ if (fFirstWallet) {
+ window->setCurrentWallet(walletModel->getWalletName());
+ fFirstWallet = false;
+ }
connect(walletModel, SIGNAL(coinsSent(CWallet*,SendCoinsRecipient,QByteArray)),
paymentServer, SLOT(fetchPaymentACK(CWallet*,const SendCoinsRecipient&,QByteArray)));
+
+ m_wallet_models.push_back(walletModel);
}
#endif
@@ -617,7 +625,7 @@ int main(int argc, char *argv[])
if (!Intro::pickDataDirectory())
return EXIT_SUCCESS;
- /// 6. Determine availability of data directory and parse bitcoin.conf
+ /// 6. Determine availability of data and blocks directory and parse bitcoin.conf
/// - Do not call GetDataDir(true) before this step finishes
if (!fs::is_directory(GetDataDir(false)))
{
@@ -671,6 +679,11 @@ int main(int argc, char *argv[])
// Start up the payment server early, too, so impatient users that click on
// bitcoin: links repeatedly have their payment requests routed to this process:
app.createPaymentServer();
+
+ // Hook up the wallet init interface
+ g_wallet_init_interface.reset(new WalletInit);
+#else
+ g_wallet_init_interface.reset(new DummyWalletInit);
#endif
/// 9. Main GUI initialization
@@ -690,7 +703,7 @@ int main(int argc, char *argv[])
// Allow parameter interaction before we create the options model
app.parameterSetup();
// Load GUI settings from QSettings
- app.createOptionsModel(gArgs.IsArgSet("-resetguisettings"));
+ app.createOptionsModel(gArgs.GetBoolArg("-resetguisettings", false));
// Subscribe to global signals from core
uiInterface.InitMessage.connect(InitMessage);
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 427eb95a84..e4207fce99 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -21,6 +21,7 @@
#ifdef ENABLE_WALLET
#include <qt/walletframe.h>
#include <qt/walletmodel.h>
+#include <qt/walletview.h>
#endif // ENABLE_WALLET
#ifdef Q_OS_MAC
@@ -36,6 +37,7 @@
#include <QAction>
#include <QApplication>
+#include <QComboBox>
#include <QDateTime>
#include <QDesktopWidget>
#include <QDragEnterEvent>
@@ -70,10 +72,6 @@ const std::string BitcoinGUI::DEFAULT_UIPLATFORM =
#endif
;
-/** Display name for default wallet name. Uses tilde to avoid name
- * collisions in the future with additional wallets */
-const QString BitcoinGUI::DEFAULT_WALLET = "~Default";
-
BitcoinGUI::BitcoinGUI(const PlatformStyle *_platformStyle, const NetworkStyle *networkStyle, QWidget *parent) :
QMainWindow(parent),
enableWallet(false),
@@ -88,6 +86,7 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *_platformStyle, const NetworkStyle *
progressBar(0),
progressDialog(0),
appMenuBar(0),
+ appToolBar(0),
overviewAction(0),
historyAction(0),
quitAction(0),
@@ -455,6 +454,7 @@ void BitcoinGUI::createToolBars()
if(walletFrame)
{
QToolBar *toolbar = addToolBar(tr("Tabs toolbar"));
+ appToolBar = toolbar;
toolbar->setContextMenuPolicy(Qt::PreventContextMenu);
toolbar->setMovable(false);
toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
@@ -463,6 +463,15 @@ void BitcoinGUI::createToolBars()
toolbar->addAction(receiveCoinsAction);
toolbar->addAction(historyAction);
overviewAction->setChecked(true);
+
+#ifdef ENABLE_WALLET
+ QWidget *spacer = new QWidget();
+ spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ toolbar->addWidget(spacer);
+
+ m_wallet_selector = new QComboBox();
+ connect(m_wallet_selector, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(setCurrentWallet(const QString&)));
+#endif
}
}
@@ -529,12 +538,22 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel)
}
#ifdef ENABLE_WALLET
-bool BitcoinGUI::addWallet(const QString& name, WalletModel *walletModel)
+bool BitcoinGUI::addWallet(WalletModel *walletModel)
{
if(!walletFrame)
return false;
+ const QString name = walletModel->getWalletName();
setWalletActionsEnabled(true);
- return walletFrame->addWallet(name, walletModel);
+ m_wallet_selector->addItem(name);
+ if (m_wallet_selector->count() == 2) {
+ m_wallet_selector_label = new QLabel();
+ m_wallet_selector_label->setText(tr("Wallet:") + " ");
+ m_wallet_selector_label->setBuddy(m_wallet_selector);
+ appToolBar->addWidget(m_wallet_selector_label);
+ appToolBar->addWidget(m_wallet_selector);
+ }
+ rpcConsole->addWallet(walletModel);
+ return walletFrame->addWallet(walletModel);
}
bool BitcoinGUI::setCurrentWallet(const QString& name)
@@ -780,7 +799,7 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer
// Acquire current block source
enum BlockSource blockSource = clientModel->getBlockSource();
switch (blockSource) {
- case BLOCK_SOURCE_NETWORK:
+ case BlockSource::NETWORK:
if (header) {
updateHeadersSyncProgressLabel();
return;
@@ -788,17 +807,17 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer
progressBarLabel->setText(tr("Synchronizing with network..."));
updateHeadersSyncProgressLabel();
break;
- case BLOCK_SOURCE_DISK:
+ case BlockSource::DISK:
if (header) {
progressBarLabel->setText(tr("Indexing blocks on disk..."));
} else {
progressBarLabel->setText(tr("Processing blocks on disk..."));
}
break;
- case BLOCK_SOURCE_REINDEX:
+ case BlockSource::REINDEX:
progressBarLabel->setText(tr("Reindexing blocks on disk..."));
break;
- case BLOCK_SOURCE_NONE:
+ case BlockSource::NONE:
if (header) {
return;
}
@@ -983,12 +1002,15 @@ void BitcoinGUI::showEvent(QShowEvent *event)
}
#ifdef ENABLE_WALLET
-void BitcoinGUI::incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label)
+void BitcoinGUI::incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label, const QString& walletName)
{
// On new transaction, make an info balloon
QString msg = tr("Date: %1\n").arg(date) +
- tr("Amount: %1\n").arg(BitcoinUnits::formatWithUnit(unit, amount, true)) +
- tr("Type: %1\n").arg(type);
+ tr("Amount: %1\n").arg(BitcoinUnits::formatWithUnit(unit, amount, true));
+ if (WalletModel::isMultiwallet() && !walletName.isEmpty()) {
+ msg += tr("Wallet: %1\n").arg(walletName);
+ }
+ msg += tr("Type: %1\n").arg(type);
if (!label.isEmpty())
msg += tr("Label: %1\n").arg(label);
else if (!address.isEmpty())
@@ -1079,6 +1101,20 @@ void BitcoinGUI::setEncryptionStatus(int status)
break;
}
}
+
+void BitcoinGUI::updateWalletStatus()
+{
+ if (!walletFrame) {
+ return;
+ }
+ WalletView * const walletView = walletFrame->currentWalletView();
+ if (!walletView) {
+ return;
+ }
+ WalletModel * const walletModel = walletView->getWalletModel();
+ setEncryptionStatus(walletModel->getEncryptionStatus());
+ setHDStatus(walletModel->hdEnabled());
+}
#endif // ENABLE_WALLET
void BitcoinGUI::showNormalIfMinimized(bool fToggleHidden)
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index ddb7ecb76a..b9e92f2d5b 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -33,6 +33,7 @@ class ModalOverlay;
QT_BEGIN_NAMESPACE
class QAction;
+class QComboBox;
class QProgressBar;
class QProgressDialog;
QT_END_NAMESPACE
@@ -46,7 +47,6 @@ class BitcoinGUI : public QMainWindow
Q_OBJECT
public:
- static const QString DEFAULT_WALLET;
static const std::string DEFAULT_UIPLATFORM;
explicit BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *networkStyle, QWidget *parent = 0);
@@ -62,8 +62,7 @@ public:
The wallet model represents a bitcoin wallet, and offers access to the list of transactions, address book and sending
functionality.
*/
- bool addWallet(const QString& name, WalletModel *walletModel);
- bool setCurrentWallet(const QString& name);
+ bool addWallet(WalletModel *walletModel);
void removeAllWallets();
#endif // ENABLE_WALLET
bool enableWallet;
@@ -90,6 +89,7 @@ private:
QProgressDialog *progressDialog;
QMenuBar *appMenuBar;
+ QToolBar *appToolBar;
QAction *overviewAction;
QAction *historyAction;
QAction *quitAction;
@@ -112,6 +112,9 @@ private:
QAction *openAction;
QAction *showHelpMessageAction;
+ QLabel *m_wallet_selector_label;
+ QComboBox *m_wallet_selector;
+
QSystemTrayIcon *trayIcon;
QMenu *trayIconMenu;
Notificator *notificator;
@@ -171,6 +174,12 @@ public Q_SLOTS:
void message(const QString &title, const QString &message, unsigned int style, bool *ret = nullptr);
#ifdef ENABLE_WALLET
+ bool setCurrentWallet(const QString& name);
+ /** Set the UI status indicators based on the currently selected wallet.
+ */
+ void updateWalletStatus();
+
+private:
/** Set the encryption status as shown in the UI.
@param[in] status current encryption status
@see WalletModel::EncryptionStatus
@@ -183,10 +192,11 @@ public Q_SLOTS:
*/
void setHDStatus(int hdEnabled);
+public Q_SLOTS:
bool handlePaymentRequest(const SendCoinsRecipient& recipient);
/** Show incoming transaction notification for new transactions. */
- void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label);
+ void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label, const QString& walletName);
#endif // ENABLE_WALLET
private Q_SLOTS:
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index eaf2896bc3..40661d9ec3 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -177,13 +177,13 @@ bool ClientModel::inInitialBlockDownload() const
enum BlockSource ClientModel::getBlockSource() const
{
if (fReindex)
- return BLOCK_SOURCE_REINDEX;
+ return BlockSource::REINDEX;
else if (fImporting)
- return BLOCK_SOURCE_DISK;
+ return BlockSource::DISK;
else if (getNumConnections() > 0)
- return BLOCK_SOURCE_NETWORK;
+ return BlockSource::NETWORK;
- return BLOCK_SOURCE_NONE;
+ return BlockSource::NONE;
}
void ClientModel::setNetworkActive(bool active)
diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h
index 99ec2365a9..1118bc31b3 100644
--- a/src/qt/clientmodel.h
+++ b/src/qt/clientmodel.h
@@ -20,11 +20,11 @@ QT_BEGIN_NAMESPACE
class QTimer;
QT_END_NAMESPACE
-enum BlockSource {
- BLOCK_SOURCE_NONE,
- BLOCK_SOURCE_REINDEX,
- BLOCK_SOURCE_DISK,
- BLOCK_SOURCE_NETWORK
+enum class BlockSource {
+ NONE,
+ REINDEX,
+ DISK,
+ NETWORK
};
enum NumConnections {
diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui
index bba822882e..695ed61228 100644
--- a/src/qt/forms/debugwindow.ui
+++ b/src/qt/forms/debugwindow.ui
@@ -413,6 +413,22 @@
<number>4</number>
</property>
<item>
+ <widget class="QLabel" name="WalletSelectorLabel">
+ <property name="text">
+ <string>Wallet: </string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="WalletSelector">
+ <item>
+ <property name="text">
+ <string>(none)</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 16ef27a36a..7b653a99da 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -137,15 +137,6 @@ void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent)
widget->setCheckValidator(new BitcoinAddressCheckValidator(parent));
}
-void setupAmountWidget(QLineEdit *widget, QWidget *parent)
-{
- QDoubleValidator *amountValidator = new QDoubleValidator(parent);
- amountValidator->setDecimals(8);
- amountValidator->setBottom(0.0);
- widget->setValidator(amountValidator);
- widget->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
-}
-
bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
{
// return if URI is not valid or is no bitcoin: URI
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index 4b856986da..bbbeaf2c43 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -40,9 +40,8 @@ namespace GUIUtil
// Return a monospace font
QFont fixedPitchFont();
- // Set up widgets for address and amounts
+ // Set up widget for address
void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent);
- void setupAmountWidget(QLineEdit *widget, QWidget *parent);
// Parse "bitcoin:" URI into recipient object, return true on successful parsing
bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out);
diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp
index 132fb54d66..c8b6366db0 100644
--- a/src/qt/receivecoinsdialog.cpp
+++ b/src/qt/receivecoinsdialog.cpp
@@ -153,7 +153,7 @@ void ReceiveCoinsDialog::on_receiveButton_clicked()
ui->reqAmount->value(), ui->reqMessage->text());
ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this);
dialog->setAttribute(Qt::WA_DeleteOnClose);
- dialog->setModel(model->getOptionsModel());
+ dialog->setModel(model);
dialog->setInfo(info);
dialog->show();
clear();
@@ -166,7 +166,7 @@ void ReceiveCoinsDialog::on_recentRequestsView_doubleClicked(const QModelIndex &
{
const RecentRequestsTableModel *submodel = model->getRecentRequestsTableModel();
ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this);
- dialog->setModel(model->getOptionsModel());
+ dialog->setModel(model);
dialog->setInfo(submodel->entry(index.row()).recipient);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->show();
diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp
index d4cb0e5ba2..75146e2214 100644
--- a/src/qt/receiverequestdialog.cpp
+++ b/src/qt/receiverequestdialog.cpp
@@ -108,12 +108,12 @@ ReceiveRequestDialog::~ReceiveRequestDialog()
delete ui;
}
-void ReceiveRequestDialog::setModel(OptionsModel *_model)
+void ReceiveRequestDialog::setModel(WalletModel *_model)
{
this->model = _model;
if (_model)
- connect(_model, SIGNAL(displayUnitChanged(int)), this, SLOT(update()));
+ connect(_model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(update()));
// update the display unit if necessary
update();
@@ -143,11 +143,14 @@ void ReceiveRequestDialog::update()
html += "<a href=\""+uri+"\">" + GUIUtil::HtmlEscape(uri) + "</a><br>";
html += "<b>"+tr("Address")+"</b>: " + GUIUtil::HtmlEscape(info.address) + "<br>";
if(info.amount)
- html += "<b>"+tr("Amount")+"</b>: " + BitcoinUnits::formatHtmlWithUnit(model->getDisplayUnit(), info.amount) + "<br>";
+ html += "<b>"+tr("Amount")+"</b>: " + BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), info.amount) + "<br>";
if(!info.label.isEmpty())
html += "<b>"+tr("Label")+"</b>: " + GUIUtil::HtmlEscape(info.label) + "<br>";
if(!info.message.isEmpty())
html += "<b>"+tr("Message")+"</b>: " + GUIUtil::HtmlEscape(info.message) + "<br>";
+ if(model->isMultiwallet()) {
+ html += "<b>"+tr("Wallet")+"</b>: " + GUIUtil::HtmlEscape(model->getWalletName()) + "<br>";
+ }
ui->outUri->setText(html);
#ifdef USE_QRCODE
diff --git a/src/qt/receiverequestdialog.h b/src/qt/receiverequestdialog.h
index 21bbf1edb7..23c5529535 100644
--- a/src/qt/receiverequestdialog.h
+++ b/src/qt/receiverequestdialog.h
@@ -12,8 +12,6 @@
#include <QLabel>
#include <QPainter>
-class OptionsModel;
-
namespace Ui {
class ReceiveRequestDialog;
}
@@ -53,7 +51,7 @@ public:
explicit ReceiveRequestDialog(QWidget *parent = 0);
~ReceiveRequestDialog();
- void setModel(OptionsModel *model);
+ void setModel(WalletModel *model);
void setInfo(const SendCoinsRecipient &info);
private Q_SLOTS:
@@ -64,7 +62,7 @@ private Q_SLOTS:
private:
Ui::ReceiveRequestDialog *ui;
- OptionsModel *model;
+ WalletModel *model;
SendCoinsRecipient info;
};
diff --git a/src/qt/recentrequeststablemodel.cpp b/src/qt/recentrequeststablemodel.cpp
index 0dd7d46960..f045053c3b 100644
--- a/src/qt/recentrequeststablemodel.cpp
+++ b/src/qt/recentrequeststablemodel.cpp
@@ -139,10 +139,9 @@ bool RecentRequestsTableModel::removeRows(int row, int count, const QModelIndex
if(count > 0 && row >= 0 && (row+count) <= list.size())
{
- const RecentRequestEntry *rec;
for (int i = 0; i < count; ++i)
{
- rec = &list[row+i];
+ const RecentRequestEntry* rec = &list[row+i];
if (!walletModel->saveReceiveRequest(rec->recipient.address.toStdString(), rec->id, ""))
return false;
}
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 1aa4de03ca..c41e19f6f5 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -12,6 +12,7 @@
#include <qt/bantablemodel.h>
#include <qt/clientmodel.h>
#include <qt/platformstyle.h>
+#include <qt/walletmodel.h>
#include <chainparams.h>
#include <netbase.h>
#include <rpc/server.h>
@@ -84,7 +85,7 @@ class RPCExecutor : public QObject
Q_OBJECT
public Q_SLOTS:
- void request(const QString &command);
+ void request(const QString &command, const QString &walletID);
Q_SIGNALS:
void reply(int category, const QString &command);
@@ -145,7 +146,7 @@ public:
* @param[out] pstrFilteredOut Command line, filtered to remove any sensitive data
*/
-bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &strCommand, const bool fExecute, std::string * const pstrFilteredOut)
+bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &strCommand, const bool fExecute, std::string * const pstrFilteredOut, const std::string *walletID)
{
std::vector< std::vector<std::string> > stack;
stack.push_back(std::vector<std::string>());
@@ -303,10 +304,8 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &
req.params = RPCConvertValues(stack.back()[0], std::vector<std::string>(stack.back().begin() + 1, stack.back().end()));
req.strMethod = stack.back()[0];
#ifdef ENABLE_WALLET
- // TODO: Move this logic to WalletModel
- if (!vpwallets.empty()) {
- // in Qt, use always the wallet with index 0 when running with multiple wallets
- QByteArray encodedName = QUrl::toPercentEncoding(QString::fromStdString(vpwallets[0]->GetName()));
+ if (walletID && !walletID->empty()) {
+ QByteArray encodedName = QUrl::toPercentEncoding(QString::fromStdString(*walletID));
req.URI = "/wallet/"+std::string(encodedName.constData(), encodedName.length());
}
#endif
@@ -385,7 +384,7 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &
}
}
-void RPCExecutor::request(const QString &command)
+void RPCExecutor::request(const QString &command, const QString &walletID)
{
try
{
@@ -416,7 +415,8 @@ void RPCExecutor::request(const QString &command)
" example: getblock(getblockhash(0),true)[tx][0]\n\n")));
return;
}
- if(!RPCConsole::RPCExecuteCommandLine(result, executableCommand))
+ std::string wallet_id = walletID.toStdString();
+ if(!RPCConsole::RPCExecuteCommandLine(result, executableCommand, nullptr, &wallet_id))
{
Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \""));
return;
@@ -478,6 +478,10 @@ RPCConsole::RPCConsole(const PlatformStyle *_platformStyle, QWidget *parent) :
connect(ui->fontSmallerButton, SIGNAL(clicked()), this, SLOT(fontSmaller()));
connect(ui->btnClearTrafficGraph, SIGNAL(clicked()), ui->trafficGraph, SLOT(clear()));
+ // disable the wallet selector by default
+ ui->WalletSelector->setVisible(false);
+ ui->WalletSelectorLabel->setVisible(false);
+
// set library version labels
#ifdef ENABLE_WALLET
ui->berkeleyDBVersion->setText(DbEnv::version(0, 0, 0));
@@ -687,6 +691,23 @@ void RPCConsole::setClientModel(ClientModel *model)
}
}
+#ifdef ENABLE_WALLET
+void RPCConsole::addWallet(WalletModel * const walletModel)
+{
+ const QString name = walletModel->getWalletName();
+ // use name for text and internal data object (to allow to move to a wallet id later)
+ ui->WalletSelector->addItem(name, name);
+ if (ui->WalletSelector->count() == 2 && !isVisible()) {
+ // First wallet added, set to default so long as the window isn't presently visible (and potentially in use)
+ ui->WalletSelector->setCurrentIndex(1);
+ }
+ if (ui->WalletSelector->count() > 2) {
+ ui->WalletSelector->setVisible(true);
+ ui->WalletSelectorLabel->setVisible(true);
+ }
+}
+#endif
+
static QString categoryClass(int category)
{
switch(category)
@@ -874,8 +895,25 @@ void RPCConsole::on_lineEdit_returnPressed()
cmdBeforeBrowsing = QString();
+ QString walletID;
+#ifdef ENABLE_WALLET
+ const int wallet_index = ui->WalletSelector->currentIndex();
+ if (wallet_index > 0) {
+ walletID = (QString)ui->WalletSelector->itemData(wallet_index).value<QString>();
+ }
+
+ if (m_last_wallet_id != walletID) {
+ if (walletID.isEmpty()) {
+ message(CMD_REQUEST, tr("Executing command without any wallet"));
+ } else {
+ message(CMD_REQUEST, tr("Executing command using \"%1\" wallet").arg(walletID));
+ }
+ m_last_wallet_id = walletID;
+ }
+#endif
+
message(CMD_REQUEST, QString::fromStdString(strFilteredCmd));
- Q_EMIT cmdRequest(cmd);
+ Q_EMIT cmdRequest(cmd, walletID);
cmd = QString::fromStdString(strFilteredCmd);
@@ -923,7 +961,7 @@ void RPCConsole::startExecutor()
// Replies from executor object must go to this object
connect(executor, SIGNAL(reply(int,QString)), this, SLOT(message(int,QString)));
// Requests from this object must go to executor
- connect(this, SIGNAL(cmdRequest(QString)), executor, SLOT(request(QString)));
+ connect(this, SIGNAL(cmdRequest(QString, QString)), executor, SLOT(request(QString, QString)));
// On stopExecutor signal
// - quit the Qt event loop in the execution thread
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index c41cbb0933..c97260b2c3 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -17,6 +17,7 @@
class ClientModel;
class PlatformStyle;
class RPCTimerInterface;
+class WalletModel;
namespace Ui {
class RPCConsole;
@@ -36,12 +37,13 @@ public:
explicit RPCConsole(const PlatformStyle *platformStyle, QWidget *parent);
~RPCConsole();
- static bool RPCParseCommandLine(std::string &strResult, const std::string &strCommand, bool fExecute, std::string * const pstrFilteredOut = nullptr);
- static bool RPCExecuteCommandLine(std::string &strResult, const std::string &strCommand, std::string * const pstrFilteredOut = nullptr) {
- return RPCParseCommandLine(strResult, strCommand, true, pstrFilteredOut);
+ static bool RPCParseCommandLine(std::string &strResult, const std::string &strCommand, bool fExecute, std::string * const pstrFilteredOut = nullptr, const std::string *walletID = nullptr);
+ static bool RPCExecuteCommandLine(std::string &strResult, const std::string &strCommand, std::string * const pstrFilteredOut = nullptr, const std::string *walletID = nullptr) {
+ return RPCParseCommandLine(strResult, strCommand, true, pstrFilteredOut, walletID);
}
void setClientModel(ClientModel *model);
+ void addWallet(WalletModel * const walletModel);
enum MessageClass {
MC_ERROR,
@@ -120,7 +122,7 @@ public Q_SLOTS:
Q_SIGNALS:
// For RPC command executor
void stopExecutor();
- void cmdRequest(const QString &command);
+ void cmdRequest(const QString &command, const QString &walletID);
private:
void startExecutor();
@@ -151,6 +153,7 @@ private:
int consoleFontSize;
QCompleter *autoCompleter;
QThread thread;
+ QString m_last_wallet_id;
/** Update UI with latest network info from model. */
void updateNetworkState();
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index ec7edd48cd..8a52aadbb0 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -277,8 +277,11 @@ void SendCoinsDialog::on_sendButton_clicked()
QStringList formatted;
for (const SendCoinsRecipient &rcp : currentTransaction.getRecipients())
{
- // generate bold amount string
+ // generate bold amount string with wallet name in case of multiwallet
QString amount = "<b>" + BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), rcp.amount);
+ if (model->isMultiwallet()) {
+ amount.append(" <u>"+tr("from wallet %1").arg(GUIUtil::HtmlEscape(model->getWalletName()))+"</u> ");
+ }
amount.append("</b>");
// generate monospace address string
QString address = "<span style='font-family: monospace;'>" + rcp.address;
diff --git a/src/qt/test/paymentrequestdata.h b/src/qt/test/paymentrequestdata.h
index 74a2db8ea2..8e5a259f68 100644
--- a/src/qt/test/paymentrequestdata.h
+++ b/src/qt/test/paymentrequestdata.h
@@ -2,6 +2,9 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#ifndef BITCOIN_QT_TEST_PAYMENTREQUESTDATA_H
+#define BITCOIN_QT_TEST_PAYMENTREQUESTDATA_H
+
//
// Data for paymentservertests.cpp
//
@@ -458,3 +461,5 @@ iEBFUrBDJZU+UEezGwr7/zoECjo5ZY3PmtZcM2sILNjyweJF6XVzGqTxUw6pN6sW\
XR2T3Gy2LzRvhVA25QgGqpz0/juS2BtmNbsZPkN9gMMwKimgzc+PuCzmEKwPK9cQ\
YQ==\
";
+
+#endif // BITCOIN_QT_TEST_PAYMENTREQUESTDATA_H
diff --git a/src/qt/test/rpcnestedtests.h b/src/qt/test/rpcnestedtests.h
index 0ce1c66f44..7b3b38f62e 100644
--- a/src/qt/test/rpcnestedtests.h
+++ b/src/qt/test/rpcnestedtests.h
@@ -2,8 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_QT_TEST_RPC_NESTED_TESTS_H
-#define BITCOIN_QT_TEST_RPC_NESTED_TESTS_H
+#ifndef BITCOIN_QT_TEST_RPCNESTEDTESTS_H
+#define BITCOIN_QT_TEST_RPCNESTEDTESTS_H
#include <QObject>
#include <QTest>
@@ -19,4 +19,4 @@ class RPCNestedTests : public QObject
void rpcNestedTests();
};
-#endif // BITCOIN_QT_TEST_RPC_NESTED_TESTS_H
+#endif // BITCOIN_QT_TEST_RPCNESTEDTESTS_H
diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp
index 65e7775f2b..c19e6aae78 100644
--- a/src/qt/utilitydialog.cpp
+++ b/src/qt/utilitydialog.cpp
@@ -77,7 +77,7 @@ HelpMessageDialog::HelpMessageDialog(QWidget *parent, bool about) :
cursor.insertText(header);
cursor.insertBlock();
- std::string strUsage = HelpMessage(HMM_BITCOIN_QT);
+ std::string strUsage = HelpMessage(HelpMessageMode::BITCOIN_QT);
const bool showDebug = gArgs.GetBoolArg("-help-debug", false);
strUsage += HelpMessageGroup(tr("UI Options:").toStdString());
if (showDebug) {
diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp
index c0b9d04269..5b13353d7b 100644
--- a/src/qt/walletframe.cpp
+++ b/src/qt/walletframe.cpp
@@ -3,6 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <qt/walletframe.h>
+#include <qt/walletmodel.h>
#include <qt/bitcoingui.h>
#include <qt/walletview.h>
@@ -39,10 +40,16 @@ void WalletFrame::setClientModel(ClientModel *_clientModel)
this->clientModel = _clientModel;
}
-bool WalletFrame::addWallet(const QString& name, WalletModel *walletModel)
+bool WalletFrame::addWallet(WalletModel *walletModel)
{
- if (!gui || !clientModel || !walletModel || mapWalletViews.count(name) > 0)
+ if (!gui || !clientModel || !walletModel) {
return false;
+ }
+
+ const QString name = walletModel->getWalletName();
+ if (mapWalletViews.count(name) > 0) {
+ return false;
+ }
WalletView *walletView = new WalletView(platformStyle, this);
walletView->setBitcoinGUI(gui);
diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h
index 42ce69fea1..6eedcf370c 100644
--- a/src/qt/walletframe.h
+++ b/src/qt/walletframe.h
@@ -36,7 +36,7 @@ public:
void setClientModel(ClientModel *clientModel);
- bool addWallet(const QString& name, WalletModel *walletModel);
+ bool addWallet(WalletModel *walletModel);
bool setCurrentWallet(const QString& name);
bool removeWallet(const QString &name);
void removeAllWallets();
@@ -59,6 +59,7 @@ private:
const PlatformStyle *platformStyle;
+public:
WalletView *currentWalletView();
public Q_SLOTS:
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index d092ebedfb..795302be58 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -110,8 +110,9 @@ void WalletModel::updateStatus()
{
EncryptionStatus newEncryptionStatus = getEncryptionStatus();
- if(cachedEncryptionStatus != newEncryptionStatus)
- Q_EMIT encryptionStatusChanged(newEncryptionStatus);
+ if(cachedEncryptionStatus != newEncryptionStatus) {
+ Q_EMIT encryptionStatusChanged();
+ }
}
void WalletModel::pollBalanceChanged()
@@ -743,3 +744,14 @@ int WalletModel::getDefaultConfirmTarget() const
{
return nTxConfirmTarget;
}
+
+QString WalletModel::getWalletName() const
+{
+ LOCK(wallet->cs_wallet);
+ return QString::fromStdString(wallet->GetName());
+}
+
+bool WalletModel::isMultiwallet()
+{
+ return gArgs.GetArgs("-wallet").size() > 1;
+}
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index 64813e0f5a..ff4b38a804 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -136,6 +136,8 @@ public:
TransactionTableModel *getTransactionTableModel();
RecentRequestsTableModel *getRecentRequestsTableModel();
+ CWallet *getWallet() const { return wallet; };
+
CAmount getBalance(const CCoinControl *coinControl = nullptr) const;
CAmount getUnconfirmedBalance() const;
CAmount getImmatureBalance() const;
@@ -225,6 +227,9 @@ public:
int getDefaultConfirmTarget() const;
+ QString getWalletName() const;
+
+ static bool isMultiwallet();
private:
CWallet *wallet;
bool fHaveWatchOnly;
@@ -260,7 +265,7 @@ Q_SIGNALS:
const CAmount& watchOnlyBalance, const CAmount& watchUnconfBalance, const CAmount& watchImmatureBalance);
// Encryption status of wallet changed
- void encryptionStatusChanged(int status);
+ void encryptionStatusChanged();
// Signal emitted when wallet needs to be unlocked
// It is valid behaviour for listeners to keep the wallet locked after this signal;
diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp
index 64497a3431..cc4300a7a1 100644
--- a/src/qt/walletview.cpp
+++ b/src/qt/walletview.cpp
@@ -101,13 +101,13 @@ void WalletView::setBitcoinGUI(BitcoinGUI *gui)
connect(this, SIGNAL(message(QString,QString,unsigned int)), gui, SLOT(message(QString,QString,unsigned int)));
// Pass through encryption status changed signals
- connect(this, SIGNAL(encryptionStatusChanged(int)), gui, SLOT(setEncryptionStatus(int)));
+ connect(this, SIGNAL(encryptionStatusChanged()), gui, SLOT(updateWalletStatus()));
// Pass through transaction notifications
- connect(this, SIGNAL(incomingTransaction(QString,int,CAmount,QString,QString,QString)), gui, SLOT(incomingTransaction(QString,int,CAmount,QString,QString,QString)));
+ connect(this, SIGNAL(incomingTransaction(QString,int,CAmount,QString,QString,QString,QString)), gui, SLOT(incomingTransaction(QString,int,CAmount,QString,QString,QString,QString)));
// Connect HD enabled state signal
- connect(this, SIGNAL(hdEnabledStatusChanged(int)), gui, SLOT(setHDStatus(int)));
+ connect(this, SIGNAL(hdEnabledStatusChanged()), gui, SLOT(updateWalletStatus()));
}
}
@@ -137,11 +137,11 @@ void WalletView::setWalletModel(WalletModel *_walletModel)
connect(_walletModel, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int)));
// Handle changes in encryption status
- connect(_walletModel, SIGNAL(encryptionStatusChanged(int)), this, SIGNAL(encryptionStatusChanged(int)));
+ connect(_walletModel, SIGNAL(encryptionStatusChanged()), this, SIGNAL(encryptionStatusChanged()));
updateEncryptionStatus();
// update HD status
- Q_EMIT hdEnabledStatusChanged(_walletModel->hdEnabled());
+ Q_EMIT hdEnabledStatusChanged();
// Balloon pop-up for new transaction
connect(_walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
@@ -172,7 +172,7 @@ void WalletView::processNewTransaction(const QModelIndex& parent, int start, int
QString address = ttm->data(index, TransactionTableModel::AddressRole).toString();
QString label = ttm->data(index, TransactionTableModel::LabelRole).toString();
- Q_EMIT incomingTransaction(date, walletModel->getOptionsModel()->getDisplayUnit(), amount, type, address, label);
+ Q_EMIT incomingTransaction(date, walletModel->getOptionsModel()->getDisplayUnit(), amount, type, address, label, walletModel->getWalletName());
}
void WalletView::gotoOverviewPage()
@@ -234,7 +234,7 @@ void WalletView::showOutOfSyncWarning(bool fShow)
void WalletView::updateEncryptionStatus()
{
- Q_EMIT encryptionStatusChanged(walletModel->getEncryptionStatus());
+ Q_EMIT encryptionStatusChanged();
}
void WalletView::encryptWallet(bool status)
diff --git a/src/qt/walletview.h b/src/qt/walletview.h
index 30d68e4eff..878a5966d6 100644
--- a/src/qt/walletview.h
+++ b/src/qt/walletview.h
@@ -44,6 +44,7 @@ public:
The client model represents the part of the core that communicates with the P2P network, and is wallet-agnostic.
*/
void setClientModel(ClientModel *clientModel);
+ WalletModel *getWalletModel() { return walletModel; }
/** Set the wallet model.
The wallet model represents a bitcoin wallet, and offers access to the list of transactions, address book and sending
functionality.
@@ -119,11 +120,11 @@ Q_SIGNALS:
/** Fired when a message should be reported to the user */
void message(const QString &title, const QString &message, unsigned int style);
/** Encryption status of wallet changed */
- void encryptionStatusChanged(int status);
+ void encryptionStatusChanged();
/** HD-Enabled status of wallet changed (only possible during startup) */
- void hdEnabledStatusChanged(int hdEnabled);
+ void hdEnabledStatusChanged();
/** Notify that a new transaction appeared */
- void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label);
+ void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label, const QString& walletName);
/** Notify that the out of sync warning icon has been pressed */
void outOfSyncWarningClicked();
};
diff --git a/src/rest.cpp b/src/rest.cpp
index f47b40343b..5871b554a6 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -24,21 +24,21 @@
static const size_t MAX_GETUTXOS_OUTPOINTS = 15; //allow a max of 15 outpoints to be queried at once
-enum RetFormat {
- RF_UNDEF,
- RF_BINARY,
- RF_HEX,
- RF_JSON,
+enum class RetFormat {
+ UNDEF,
+ BINARY,
+ HEX,
+ JSON,
};
static const struct {
enum RetFormat rf;
const char* name;
} rf_names[] = {
- {RF_UNDEF, ""},
- {RF_BINARY, "bin"},
- {RF_HEX, "hex"},
- {RF_JSON, "json"},
+ {RetFormat::UNDEF, ""},
+ {RetFormat::BINARY, "bin"},
+ {RetFormat::HEX, "hex"},
+ {RetFormat::JSON, "json"},
};
struct CCoin {
@@ -162,20 +162,20 @@ static bool rest_headers(HTTPRequest* req,
}
switch (rf) {
- case RF_BINARY: {
+ case RetFormat::BINARY: {
std::string binaryHeader = ssHeader.str();
req->WriteHeader("Content-Type", "application/octet-stream");
req->WriteReply(HTTP_OK, binaryHeader);
return true;
}
- case RF_HEX: {
+ case RetFormat::HEX: {
std::string strHex = HexStr(ssHeader.begin(), ssHeader.end()) + "\n";
req->WriteHeader("Content-Type", "text/plain");
req->WriteReply(HTTP_OK, strHex);
return true;
}
- case RF_JSON: {
+ case RetFormat::JSON: {
UniValue jsonHeaders(UniValue::VARR);
{
LOCK(cs_main);
@@ -227,21 +227,21 @@ static bool rest_block(HTTPRequest* req,
ssBlock << block;
switch (rf) {
- case RF_BINARY: {
+ case RetFormat::BINARY: {
std::string binaryBlock = ssBlock.str();
req->WriteHeader("Content-Type", "application/octet-stream");
req->WriteReply(HTTP_OK, binaryBlock);
return true;
}
- case RF_HEX: {
+ case RetFormat::HEX: {
std::string strHex = HexStr(ssBlock.begin(), ssBlock.end()) + "\n";
req->WriteHeader("Content-Type", "text/plain");
req->WriteReply(HTTP_OK, strHex);
return true;
}
- case RF_JSON: {
+ case RetFormat::JSON: {
UniValue objBlock;
{
LOCK(cs_main);
@@ -280,7 +280,7 @@ static bool rest_chaininfo(HTTPRequest* req, const std::string& strURIPart)
const RetFormat rf = ParseDataFormat(param, strURIPart);
switch (rf) {
- case RF_JSON: {
+ case RetFormat::JSON: {
JSONRPCRequest jsonRequest;
jsonRequest.params = UniValue(UniValue::VARR);
UniValue chainInfoObject = getblockchaininfo(jsonRequest);
@@ -303,7 +303,7 @@ static bool rest_mempool_info(HTTPRequest* req, const std::string& strURIPart)
const RetFormat rf = ParseDataFormat(param, strURIPart);
switch (rf) {
- case RF_JSON: {
+ case RetFormat::JSON: {
UniValue mempoolInfoObject = mempoolInfoToJSON();
std::string strJSON = mempoolInfoObject.write() + "\n";
@@ -325,7 +325,7 @@ static bool rest_mempool_contents(HTTPRequest* req, const std::string& strURIPar
const RetFormat rf = ParseDataFormat(param, strURIPart);
switch (rf) {
- case RF_JSON: {
+ case RetFormat::JSON: {
UniValue mempoolObject = mempoolToJSON(true);
std::string strJSON = mempoolObject.write() + "\n";
@@ -359,21 +359,21 @@ static bool rest_tx(HTTPRequest* req, const std::string& strURIPart)
ssTx << tx;
switch (rf) {
- case RF_BINARY: {
+ case RetFormat::BINARY: {
std::string binaryTx = ssTx.str();
req->WriteHeader("Content-Type", "application/octet-stream");
req->WriteReply(HTTP_OK, binaryTx);
return true;
}
- case RF_HEX: {
+ case RetFormat::HEX: {
std::string strHex = HexStr(ssTx.begin(), ssTx.end()) + "\n";
req->WriteHeader("Content-Type", "text/plain");
req->WriteReply(HTTP_OK, strHex);
return true;
}
- case RF_JSON: {
+ case RetFormat::JSON: {
UniValue objTx(UniValue::VOBJ);
TxToUniv(*tx, hashBlock, objTx);
std::string strJSON = objTx.write() + "\n";
@@ -440,13 +440,13 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
}
switch (rf) {
- case RF_HEX: {
+ case RetFormat::HEX: {
// convert hex to bin, continue then with bin part
std::vector<unsigned char> strRequestV = ParseHex(strRequestMutable);
strRequestMutable.assign(strRequestV.begin(), strRequestV.end());
}
- case RF_BINARY: {
+ case RetFormat::BINARY: {
try {
//deserialize only if user sent a request
if (strRequestMutable.size() > 0)
@@ -466,7 +466,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
break;
}
- case RF_JSON: {
+ case RetFormat::JSON: {
if (!fInputParsed)
return RESTERR(req, HTTP_BAD_REQUEST, "Error: empty request");
break;
@@ -487,33 +487,35 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
std::vector<bool> hits;
bitmap.resize((vOutPoints.size() + 7) / 8);
{
- LOCK2(cs_main, mempool.cs);
-
- CCoinsView viewDummy;
- CCoinsViewCache view(&viewDummy);
-
- CCoinsViewCache& viewChain = *pcoinsTip;
- CCoinsViewMemPool viewMempool(&viewChain, mempool);
-
- if (fCheckMemPool)
- view.SetBackend(viewMempool); // switch cache backend to db+mempool in case user likes to query mempool
-
- for (size_t i = 0; i < vOutPoints.size(); i++) {
- bool hit = false;
- Coin coin;
- if (view.GetCoin(vOutPoints[i], coin) && !mempool.isSpent(vOutPoints[i])) {
- hit = true;
- outs.emplace_back(std::move(coin));
+ auto process_utxos = [&vOutPoints, &outs, &hits](const CCoinsView& view, const CTxMemPool& mempool) {
+ for (const COutPoint& vOutPoint : vOutPoints) {
+ Coin coin;
+ bool hit = !mempool.isSpent(vOutPoint) && view.GetCoin(vOutPoint, coin);
+ hits.push_back(hit);
+ if (hit) outs.emplace_back(std::move(coin));
}
+ };
+
+ if (fCheckMemPool) {
+ // use db+mempool as cache backend in case user likes to query mempool
+ LOCK2(cs_main, mempool.cs);
+ CCoinsViewCache& viewChain = *pcoinsTip;
+ CCoinsViewMemPool viewMempool(&viewChain, mempool);
+ process_utxos(viewMempool, mempool);
+ } else {
+ LOCK(cs_main); // no need to lock mempool!
+ process_utxos(*pcoinsTip, CTxMemPool());
+ }
- hits.push_back(hit);
+ for (size_t i = 0; i < hits.size(); ++i) {
+ const bool hit = hits[i];
bitmapStringRepresentation.append(hit ? "1" : "0"); // form a binary string representation (human-readable for json output)
bitmap[i / 8] |= ((uint8_t)hit) << (i % 8);
}
}
switch (rf) {
- case RF_BINARY: {
+ case RetFormat::BINARY: {
// serialize data
// use exact same output as mentioned in Bip64
CDataStream ssGetUTXOResponse(SER_NETWORK, PROTOCOL_VERSION);
@@ -525,7 +527,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
return true;
}
- case RF_HEX: {
+ case RetFormat::HEX: {
CDataStream ssGetUTXOResponse(SER_NETWORK, PROTOCOL_VERSION);
ssGetUTXOResponse << chainActive.Height() << chainActive.Tip()->GetBlockHash() << bitmap << outs;
std::string strHex = HexStr(ssGetUTXOResponse.begin(), ssGetUTXOResponse.end()) + "\n";
@@ -535,7 +537,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
return true;
}
- case RF_JSON: {
+ case RetFormat::JSON: {
UniValue objGetUTXOResponse(UniValue::VOBJ);
// pack in some essentials
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 169caddc59..31cbec4c86 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -1120,20 +1120,20 @@ static UniValue BIP9SoftForkDesc(const Consensus::Params& consensusParams, Conse
UniValue rv(UniValue::VOBJ);
const ThresholdState thresholdState = VersionBitsTipState(consensusParams, id);
switch (thresholdState) {
- case THRESHOLD_DEFINED: rv.pushKV("status", "defined"); break;
- case THRESHOLD_STARTED: rv.pushKV("status", "started"); break;
- case THRESHOLD_LOCKED_IN: rv.pushKV("status", "locked_in"); break;
- case THRESHOLD_ACTIVE: rv.pushKV("status", "active"); break;
- case THRESHOLD_FAILED: rv.pushKV("status", "failed"); break;
+ case ThresholdState::DEFINED: rv.pushKV("status", "defined"); break;
+ case ThresholdState::STARTED: rv.pushKV("status", "started"); break;
+ case ThresholdState::LOCKED_IN: rv.pushKV("status", "locked_in"); break;
+ case ThresholdState::ACTIVE: rv.pushKV("status", "active"); break;
+ case ThresholdState::FAILED: rv.pushKV("status", "failed"); break;
}
- if (THRESHOLD_STARTED == thresholdState)
+ if (ThresholdState::STARTED == thresholdState)
{
rv.pushKV("bit", consensusParams.vDeployments[id].bit);
}
rv.pushKV("startTime", consensusParams.vDeployments[id].nStartTime);
rv.pushKV("timeout", consensusParams.vDeployments[id].nTimeout);
rv.pushKV("since", VersionBitsTipStateSinceHeight(consensusParams, id));
- if (THRESHOLD_STARTED == thresholdState)
+ if (ThresholdState::STARTED == thresholdState)
{
UniValue statsUV(UniValue::VOBJ);
BIP9Stats statsStruct = VersionBitsTipStatistics(consensusParams, id);
@@ -1607,13 +1607,17 @@ UniValue savemempool(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() != 0) {
throw std::runtime_error(
"savemempool\n"
- "\nDumps the mempool to disk.\n"
+ "\nDumps the mempool to disk. It will fail until the previous dump is fully loaded.\n"
"\nExamples:\n"
+ HelpExampleCli("savemempool", "")
+ HelpExampleRpc("savemempool", "")
);
}
+ if (!g_is_mempool_loaded) {
+ throw JSONRPCError(RPC_MISC_ERROR, "The mempool was not loaded yet");
+ }
+
if (!DumpMempool()) {
throw JSONRPCError(RPC_MISC_ERROR, "Unable to dump mempool to disk");
}
diff --git a/src/rpc/client.h b/src/rpc/client.h
index e7cf035d8f..e09e1dedf3 100644
--- a/src/rpc/client.h
+++ b/src/rpc/client.h
@@ -3,8 +3,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_RPCCLIENT_H
-#define BITCOIN_RPCCLIENT_H
+#ifndef BITCOIN_RPC_CLIENT_H
+#define BITCOIN_RPC_CLIENT_H
#include <univalue.h>
@@ -19,4 +19,4 @@ UniValue RPCConvertNamedValues(const std::string& strMethod, const std::vector<s
*/
UniValue ParseNonRFCJSONValue(const std::string& strVal);
-#endif // BITCOIN_RPCCLIENT_H
+#endif // BITCOIN_RPC_CLIENT_H
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 0537628763..06882c0dfd 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -532,7 +532,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
pblock->nNonce = 0;
// NOTE: If at some point we support pre-segwit miners post-segwit-activation, this needs to take segwit support into consideration
- const bool fPreSegWit = (THRESHOLD_ACTIVE != VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT, versionbitscache));
+ const bool fPreSegWit = (ThresholdState::ACTIVE != VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT, versionbitscache));
UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
@@ -593,15 +593,15 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
Consensus::DeploymentPos pos = Consensus::DeploymentPos(j);
ThresholdState state = VersionBitsState(pindexPrev, consensusParams, pos, versionbitscache);
switch (state) {
- case THRESHOLD_DEFINED:
- case THRESHOLD_FAILED:
+ case ThresholdState::DEFINED:
+ case ThresholdState::FAILED:
// Not exposed to GBT at all
break;
- case THRESHOLD_LOCKED_IN:
+ case ThresholdState::LOCKED_IN:
// Ensure bit is set in block version
pblock->nVersion |= VersionBitsMask(consensusParams, pos);
// FALL THROUGH to get vbavailable set...
- case THRESHOLD_STARTED:
+ case ThresholdState::STARTED:
{
const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
vbavailable.pushKV(gbt_vb_name(pos), consensusParams.vDeployments[pos].bit);
@@ -613,7 +613,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
}
break;
}
- case THRESHOLD_ACTIVE:
+ case ThresholdState::ACTIVE:
{
// Add to rules only
const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
diff --git a/src/rpc/protocol.h b/src/rpc/protocol.h
index ff63bf4901..4a265735d2 100644
--- a/src/rpc/protocol.h
+++ b/src/rpc/protocol.h
@@ -3,8 +3,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_RPCPROTOCOL_H
-#define BITCOIN_RPCPROTOCOL_H
+#ifndef BITCOIN_RPC_PROTOCOL_H
+#define BITCOIN_RPC_PROTOCOL_H
#include <fs.h>
@@ -104,4 +104,4 @@ void DeleteAuthCookie();
/** Parse JSON-RPC batch reply into a vector */
std::vector<UniValue> JSONRPCProcessBatchReply(const UniValue &in, size_t num);
-#endif // BITCOIN_RPCPROTOCOL_H
+#endif // BITCOIN_RPC_PROTOCOL_H
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 3247c61242..9d7aa58894 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -1023,18 +1023,18 @@ UniValue signrawtransaction(const JSONRPCRequest& request)
new_request.params.push_back(request.params[1]);
new_request.params.push_back(request.params[3]);
return signrawtransactionwithkey(new_request);
- }
- // Otherwise sign with the wallet which does not take a privkeys parameter
+ } else {
#ifdef ENABLE_WALLET
- else {
+ // Otherwise sign with the wallet which does not take a privkeys parameter
new_request.params.push_back(request.params[0]);
new_request.params.push_back(request.params[1]);
new_request.params.push_back(request.params[3]);
return signrawtransactionwithwallet(new_request);
- }
+#else
+ // If we have made it this far, then wallet is disabled and no private keys were given, so fail here.
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "No private keys available.");
#endif
- // If we have made it this far, then wallet is disabled and no private keys were given, so fail here.
- throw JSONRPCError(RPC_INVALID_PARAMETER, "No private keys available.");
+ }
}
UniValue sendrawtransaction(const JSONRPCRequest& request)
diff --git a/src/rpc/register.h b/src/rpc/register.h
index 49aee2365f..b689740681 100644
--- a/src/rpc/register.h
+++ b/src/rpc/register.h
@@ -2,8 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_RPCREGISTER_H
-#define BITCOIN_RPCREGISTER_H
+#ifndef BITCOIN_RPC_REGISTER_H
+#define BITCOIN_RPC_REGISTER_H
/** These are in one header file to avoid creating tons of single-function
* headers for everything under src/rpc/ */
@@ -29,4 +29,4 @@ static inline void RegisterAllCoreRPCCommands(CRPCTable &t)
RegisterRawTransactionRPCCommands(t);
}
-#endif
+#endif // BITCOIN_RPC_REGISTER_H
diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp
index 54995ef000..c7c3b1f0d3 100644
--- a/src/rpc/server.cpp
+++ b/src/rpc/server.cpp
@@ -367,7 +367,11 @@ void JSONRPCRequest::parse(const UniValue& valRequest)
if (!valMethod.isStr())
throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string");
strMethod = valMethod.get_str();
- LogPrint(BCLog::RPC, "ThreadRPCServer method=%s\n", SanitizeString(strMethod));
+ if (fLogIPs)
+ LogPrint(BCLog::RPC, "ThreadRPCServer method=%s user=%s peeraddr=%s\n", SanitizeString(strMethod),
+ this->authUser, this->peerAddr);
+ else
+ LogPrint(BCLog::RPC, "ThreadRPCServer method=%s user=%s\n", SanitizeString(strMethod), this->authUser);
// Parse params
UniValue valParams = find_value(request, "params");
diff --git a/src/rpc/server.h b/src/rpc/server.h
index d25268a8ab..373914885c 100644
--- a/src/rpc/server.h
+++ b/src/rpc/server.h
@@ -3,8 +3,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_RPCSERVER_H
-#define BITCOIN_RPCSERVER_H
+#ifndef BITCOIN_RPC_SERVER_H
+#define BITCOIN_RPC_SERVER_H
#include <amount.h>
#include <rpc/protocol.h>
@@ -45,6 +45,7 @@ public:
bool fHelp;
std::string URI;
std::string authUser;
+ std::string peerAddr;
JSONRPCRequest() : id(NullUniValue), params(NullUniValue), fHelp(false) {}
void parse(const UniValue& valRequest);
@@ -205,4 +206,4 @@ std::string JSONRPCExecBatch(const JSONRPCRequest& jreq, const UniValue& vReq);
// Retrieves any serialization flags requested in command line argument
int RPCSerializationFlags();
-#endif // BITCOIN_RPCSERVER_H
+#endif // BITCOIN_RPC_SERVER_H
diff --git a/src/script/bitcoinconsensus.h b/src/script/bitcoinconsensus.h
index bb94c17528..5973808fa5 100644
--- a/src/script/bitcoinconsensus.h
+++ b/src/script/bitcoinconsensus.h
@@ -3,8 +3,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_BITCOINCONSENSUS_H
-#define BITCOIN_BITCOINCONSENSUS_H
+#ifndef BITCOIN_SCRIPT_BITCOINCONSENSUS_H
+#define BITCOIN_SCRIPT_BITCOINCONSENSUS_H
#include <stdint.h>
@@ -80,4 +80,4 @@ EXPORT_SYMBOL unsigned int bitcoinconsensus_version();
#undef EXPORT_SYMBOL
-#endif // BITCOIN_BITCOINCONSENSUS_H
+#endif // BITCOIN_SCRIPT_BITCOINCONSENSUS_H
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index ffaba393c0..07b2292d46 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -219,7 +219,7 @@ bool static CheckPubKeyEncoding(const valtype &vchPubKey, unsigned int flags, co
return set_error(serror, SCRIPT_ERR_PUBKEYTYPE);
}
// Only compressed keys are accepted in segwit
- if ((flags & SCRIPT_VERIFY_WITNESS_PUBKEYTYPE) != 0 && sigversion == SIGVERSION_WITNESS_V0 && !IsCompressedPubKey(vchPubKey)) {
+ if ((flags & SCRIPT_VERIFY_WITNESS_PUBKEYTYPE) != 0 && sigversion == SigVersion::WITNESS_V0 && !IsCompressedPubKey(vchPubKey)) {
return set_error(serror, SCRIPT_ERR_WITNESS_PUBKEYTYPE);
}
return true;
@@ -443,7 +443,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
if (stack.size() < 1)
return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL);
valtype& vch = stacktop(-1);
- if (sigversion == SIGVERSION_WITNESS_V0 && (flags & SCRIPT_VERIFY_MINIMALIF)) {
+ if (sigversion == SigVersion::WITNESS_V0 && (flags & SCRIPT_VERIFY_MINIMALIF)) {
if (vch.size() > 1)
return set_error(serror, SCRIPT_ERR_MINIMALIF);
if (vch.size() == 1 && vch[0] != 1)
@@ -890,7 +890,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
CScript scriptCode(pbegincodehash, pend);
// Drop the signature in pre-segwit scripts but not segwit scripts
- if (sigversion == SIGVERSION_BASE) {
+ if (sigversion == SigVersion::BASE) {
scriptCode.FindAndDelete(CScript(vchSig));
}
@@ -954,7 +954,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
for (int k = 0; k < nSigsCount; k++)
{
valtype& vchSig = stacktop(-isig-k);
- if (sigversion == SIGVERSION_BASE) {
+ if (sigversion == SigVersion::BASE) {
scriptCode.FindAndDelete(CScript(vchSig));
}
}
@@ -1182,7 +1182,7 @@ uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsig
{
assert(nIn < txTo.vin.size());
- if (sigversion == SIGVERSION_WITNESS_V0) {
+ if (sigversion == SigVersion::WITNESS_V0) {
uint256 hashPrevouts;
uint256 hashSequence;
uint256 hashOutputs;
@@ -1396,7 +1396,7 @@ static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion,
return set_error(serror, SCRIPT_ERR_PUSH_SIZE);
}
- if (!EvalScript(stack, scriptPubKey, flags, checker, SIGVERSION_WITNESS_V0, serror)) {
+ if (!EvalScript(stack, scriptPubKey, flags, checker, SigVersion::WITNESS_V0, serror)) {
return false;
}
@@ -1423,12 +1423,12 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C
}
std::vector<std::vector<unsigned char> > stack, stackCopy;
- if (!EvalScript(stack, scriptSig, flags, checker, SIGVERSION_BASE, serror))
+ if (!EvalScript(stack, scriptSig, flags, checker, SigVersion::BASE, serror))
// serror is set
return false;
if (flags & SCRIPT_VERIFY_P2SH)
stackCopy = stack;
- if (!EvalScript(stack, scriptPubKey, flags, checker, SIGVERSION_BASE, serror))
+ if (!EvalScript(stack, scriptPubKey, flags, checker, SigVersion::BASE, serror))
// serror is set
return false;
if (stack.empty())
@@ -1474,7 +1474,7 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C
CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end());
popstack(stack);
- if (!EvalScript(stack, pubKey2, flags, checker, SIGVERSION_BASE, serror))
+ if (!EvalScript(stack, pubKey2, flags, checker, SigVersion::BASE, serror))
// serror is set
return false;
if (stack.empty())
diff --git a/src/script/interpreter.h b/src/script/interpreter.h
index 4dad6b44c5..bb7750d783 100644
--- a/src/script/interpreter.h
+++ b/src/script/interpreter.h
@@ -123,10 +123,10 @@ struct PrecomputedTransactionData
explicit PrecomputedTransactionData(const CTransaction& tx);
};
-enum SigVersion
+enum class SigVersion
{
- SIGVERSION_BASE = 0,
- SIGVERSION_WITNESS_V0 = 1,
+ BASE = 0,
+ WITNESS_V0 = 1,
};
uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache = nullptr);
diff --git a/src/script/ismine.cpp b/src/script/ismine.cpp
index 35d794b983..05bc5e9bd6 100644
--- a/src/script/ismine.cpp
+++ b/src/script/ismine.cpp
@@ -61,7 +61,7 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey, bool&
break;
case TX_PUBKEY:
keyID = CPubKey(vSolutions[0]).GetID();
- if (sigversion != SIGVERSION_BASE && vSolutions[0].size() != 33) {
+ if (sigversion != SigVersion::BASE && vSolutions[0].size() != 33) {
isInvalid = true;
return ISMINE_NO;
}
@@ -76,14 +76,14 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey, bool&
// This also applies to the P2WSH case.
break;
}
- isminetype ret = ::IsMine(keystore, GetScriptForDestination(CKeyID(uint160(vSolutions[0]))), isInvalid, SIGVERSION_WITNESS_V0);
+ isminetype ret = ::IsMine(keystore, GetScriptForDestination(CKeyID(uint160(vSolutions[0]))), isInvalid, SigVersion::WITNESS_V0);
if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid))
return ret;
break;
}
case TX_PUBKEYHASH:
keyID = CKeyID(uint160(vSolutions[0]));
- if (sigversion != SIGVERSION_BASE) {
+ if (sigversion != SigVersion::BASE) {
CPubKey pubkey;
if (keystore.GetPubKey(keyID, pubkey) && !pubkey.IsCompressed()) {
isInvalid = true;
@@ -114,7 +114,7 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey, bool&
CScriptID scriptID = CScriptID(hash);
CScript subscript;
if (keystore.GetCScript(scriptID, subscript)) {
- isminetype ret = IsMine(keystore, subscript, isInvalid, SIGVERSION_WITNESS_V0);
+ isminetype ret = IsMine(keystore, subscript, isInvalid, SigVersion::WITNESS_V0);
if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid))
return ret;
}
@@ -129,7 +129,7 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey, bool&
// them) enable spend-out-from-under-you attacks, especially
// in shared-wallet situations.
std::vector<valtype> keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1);
- if (sigversion != SIGVERSION_BASE) {
+ if (sigversion != SigVersion::BASE) {
for (size_t i = 0; i < keys.size(); i++) {
if (keys[i].size() != 33) {
isInvalid = true;
diff --git a/src/script/ismine.h b/src/script/ismine.h
index c1338c3a8e..f93a66e35a 100644
--- a/src/script/ismine.h
+++ b/src/script/ismine.h
@@ -31,11 +31,11 @@ typedef uint8_t isminefilter;
/* isInvalid becomes true when the script is found invalid by consensus or policy. This will terminate the recursion
* and return ISMINE_NO immediately, as an invalid script should never be considered as "mine". This is needed as
* different SIGVERSION may have different network rules. Currently the only use of isInvalid is indicate uncompressed
- * keys in SIGVERSION_WITNESS_V0 script, but could also be used in similar cases in the future
+ * keys in SigVersion::WITNESS_V0 script, but could also be used in similar cases in the future
*/
-isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, bool& isInvalid, SigVersion = SIGVERSION_BASE);
-isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, SigVersion = SIGVERSION_BASE);
-isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest, bool& isInvalid, SigVersion = SIGVERSION_BASE);
-isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest, SigVersion = SIGVERSION_BASE);
+isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, bool& isInvalid, SigVersion = SigVersion::BASE);
+isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, SigVersion = SigVersion::BASE);
+isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest, bool& isInvalid, SigVersion = SigVersion::BASE);
+isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest, SigVersion = SigVersion::BASE);
#endif // BITCOIN_SCRIPT_ISMINE_H
diff --git a/src/script/sign.cpp b/src/script/sign.cpp
index baa712dc2d..910bb39ce6 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -6,7 +6,6 @@
#include <script/sign.h>
#include <key.h>
-#include <keystore.h>
#include <policy/policy.h>
#include <primitives/transaction.h>
#include <script/standard.h>
@@ -15,16 +14,16 @@
typedef std::vector<unsigned char> valtype;
-TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), amount(amountIn), checker(txTo, nIn, amountIn) {}
+TransactionSignatureCreator::TransactionSignatureCreator(const SigningProvider* provider, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : BaseSignatureCreator(provider), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), amount(amountIn), checker(txTo, nIn, amountIn) {}
bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode, SigVersion sigversion) const
{
CKey key;
- if (!keystore->GetKey(address, key))
+ if (!m_provider->GetKey(address, key))
return false;
// Signing with uncompressed keys is disabled in witness scripts
- if (sigversion == SIGVERSION_WITNESS_V0 && !key.IsCompressed())
+ if (sigversion == SigVersion::WITNESS_V0 && !key.IsCompressed())
return false;
uint256 hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion);
@@ -91,12 +90,12 @@ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptP
else
{
CPubKey vch;
- creator.KeyStore().GetPubKey(keyID, vch);
+ creator.Provider().GetPubKey(keyID, vch);
ret.push_back(ToByteVector(vch));
}
return true;
case TX_SCRIPTHASH:
- if (creator.KeyStore().GetCScript(uint160(vSolutions[0]), scriptRet)) {
+ if (creator.Provider().GetCScript(uint160(vSolutions[0]), scriptRet)) {
ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
return true;
}
@@ -112,7 +111,7 @@ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptP
case TX_WITNESS_V0_SCRIPTHASH:
CRIPEMD160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(h160.begin());
- if (creator.KeyStore().GetCScript(h160, scriptRet)) {
+ if (creator.Provider().GetCScript(h160, scriptRet)) {
ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
return true;
}
@@ -142,7 +141,7 @@ bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPu
{
std::vector<valtype> result;
txnouttype whichType;
- bool solved = SignStep(creator, fromPubKey, result, whichType, SIGVERSION_BASE);
+ bool solved = SignStep(creator, fromPubKey, result, whichType, SigVersion::BASE);
bool P2SH = false;
CScript subscript;
sigdata.scriptWitness.stack.clear();
@@ -153,7 +152,7 @@ bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPu
// the final scriptSig is the signatures from that
// and then the serialized subscript:
subscript = CScript(result[0].begin(), result[0].end());
- solved = solved && SignStep(creator, subscript, result, whichType, SIGVERSION_BASE) && whichType != TX_SCRIPTHASH;
+ solved = solved && SignStep(creator, subscript, result, whichType, SigVersion::BASE) && whichType != TX_SCRIPTHASH;
P2SH = true;
}
@@ -162,7 +161,7 @@ bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPu
CScript witnessscript;
witnessscript << OP_DUP << OP_HASH160 << ToByteVector(result[0]) << OP_EQUALVERIFY << OP_CHECKSIG;
txnouttype subType;
- solved = solved && SignStep(creator, witnessscript, result, subType, SIGVERSION_WITNESS_V0);
+ solved = solved && SignStep(creator, witnessscript, result, subType, SigVersion::WITNESS_V0);
sigdata.scriptWitness.stack = result;
result.clear();
}
@@ -170,7 +169,7 @@ bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPu
{
CScript witnessscript(result[0].begin(), result[0].end());
txnouttype subType;
- solved = solved && SignStep(creator, witnessscript, result, subType, SIGVERSION_WITNESS_V0) && subType != TX_SCRIPTHASH && subType != TX_WITNESS_V0_SCRIPTHASH && subType != TX_WITNESS_V0_KEYHASH;
+ solved = solved && SignStep(creator, witnessscript, result, subType, SigVersion::WITNESS_V0) && subType != TX_SCRIPTHASH && subType != TX_WITNESS_V0_SCRIPTHASH && subType != TX_WITNESS_V0_KEYHASH;
result.push_back(std::vector<unsigned char>(witnessscript.begin(), witnessscript.end()));
sigdata.scriptWitness.stack = result;
result.clear();
@@ -206,12 +205,12 @@ void UpdateTransaction(CMutableTransaction& tx, unsigned int nIn, const Signatur
UpdateInput(tx.vin[nIn], data);
}
-bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType)
+bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType)
{
assert(nIn < txTo.vin.size());
CTransaction txToConst(txTo);
- TransactionSignatureCreator creator(&keystore, &txToConst, nIn, amount, nHashType);
+ TransactionSignatureCreator creator(&provider, &txToConst, nIn, amount, nHashType);
SignatureData sigdata;
bool ret = ProduceSignature(creator, fromPubKey, sigdata);
@@ -219,14 +218,14 @@ bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutabl
return ret;
}
-bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
+bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
{
assert(nIn < txTo.vin.size());
CTxIn& txin = txTo.vin[nIn];
assert(txin.prevout.n < txFrom.vout.size());
const CTxOut& txout = txFrom.vout[txin.prevout.n];
- return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType);
+ return SignSignature(provider, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType);
}
static std::vector<valtype> CombineMultisig(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
@@ -294,7 +293,7 @@ struct Stacks
Stacks() {}
explicit Stacks(const std::vector<valtype>& scriptSigStack_) : script(scriptSigStack_), witness() {}
explicit Stacks(const SignatureData& data) : witness(data.scriptWitness.stack) {
- EvalScript(script, data.scriptSig, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), SIGVERSION_BASE);
+ EvalScript(script, data.scriptSig, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), SigVersion::BASE);
}
SignatureData Output() const {
@@ -370,7 +369,7 @@ static Stacks CombineSignatures(const CScript& scriptPubKey, const BaseSignature
sigs2.witness.pop_back();
sigs2.script = sigs2.witness;
sigs2.witness.clear();
- Stacks result = CombineSignatures(pubKey2, checker, txType2, vSolutions2, sigs1, sigs2, SIGVERSION_WITNESS_V0);
+ Stacks result = CombineSignatures(pubKey2, checker, txType2, vSolutions2, sigs1, sigs2, SigVersion::WITNESS_V0);
result.witness = result.script;
result.script.clear();
result.witness.push_back(valtype(pubKey2.begin(), pubKey2.end()));
@@ -388,7 +387,7 @@ SignatureData CombineSignatures(const CScript& scriptPubKey, const BaseSignature
std::vector<std::vector<unsigned char> > vSolutions;
Solver(scriptPubKey, txType, vSolutions);
- return CombineSignatures(scriptPubKey, checker, txType, vSolutions, Stacks(scriptSig1), Stacks(scriptSig2), SIGVERSION_BASE).Output();
+ return CombineSignatures(scriptPubKey, checker, txType, vSolutions, Stacks(scriptSig1), Stacks(scriptSig2), SigVersion::BASE).Output();
}
namespace {
@@ -427,13 +426,13 @@ bool DummySignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const
return true;
}
-bool IsSolvable(const CKeyStore& store, const CScript& script)
+bool IsSolvable(const SigningProvider& provider, const CScript& script)
{
// This check is to make sure that the script we created can actually be solved for and signed by us
// if we were to have the private keys. This is just to make sure that the script is valid and that,
// if found in a transaction, we would still accept and relay that transaction. In particular,
// it will reject witness outputs that require signing with an uncompressed public key.
- DummySignatureCreator creator(&store);
+ DummySignatureCreator creator(&provider);
SignatureData sigs;
// Make sure that STANDARD_SCRIPT_VERIFY_FLAGS includes SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, the most
// important property this function is designed to test for.
diff --git a/src/script/sign.h b/src/script/sign.h
index 2c749521cd..c301f0544f 100644
--- a/src/script/sign.h
+++ b/src/script/sign.h
@@ -8,21 +8,32 @@
#include <script/interpreter.h>
+class CKey;
class CKeyID;
-class CKeyStore;
class CScript;
+class CScriptID;
class CTransaction;
struct CMutableTransaction;
+/** An interface to be implemented by keystores that support signing. */
+class SigningProvider
+{
+public:
+ virtual ~SigningProvider() {}
+ virtual bool GetCScript(const CScriptID &scriptid, CScript& script) const =0;
+ virtual bool GetPubKey(const CKeyID &address, CPubKey& pubkey) const =0;
+ virtual bool GetKey(const CKeyID &address, CKey& key) const =0;
+};
+
/** Virtual base class for signature creators. */
class BaseSignatureCreator {
protected:
- const CKeyStore* keystore;
+ const SigningProvider* m_provider;
public:
- explicit BaseSignatureCreator(const CKeyStore* keystoreIn) : keystore(keystoreIn) {}
- const CKeyStore& KeyStore() const { return *keystore; };
+ explicit BaseSignatureCreator(const SigningProvider* provider) : m_provider(provider) {}
+ const SigningProvider& Provider() const { return *m_provider; }
virtual ~BaseSignatureCreator() {}
virtual const BaseSignatureChecker& Checker() const =0;
@@ -39,7 +50,7 @@ class TransactionSignatureCreator : public BaseSignatureCreator {
const TransactionSignatureChecker checker;
public:
- TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn=SIGHASH_ALL);
+ TransactionSignatureCreator(const SigningProvider* provider, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn=SIGHASH_ALL);
const BaseSignatureChecker& Checker() const override { return checker; }
bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const override;
};
@@ -48,13 +59,13 @@ class MutableTransactionSignatureCreator : public TransactionSignatureCreator {
CTransaction tx;
public:
- MutableTransactionSignatureCreator(const CKeyStore* keystoreIn, const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : TransactionSignatureCreator(keystoreIn, &tx, nInIn, amountIn, nHashTypeIn), tx(*txToIn) {}
+ MutableTransactionSignatureCreator(const SigningProvider* provider, const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : TransactionSignatureCreator(provider, &tx, nInIn, amountIn, nHashTypeIn), tx(*txToIn) {}
};
/** A signature creator that just produces 72-byte empty signatures. */
class DummySignatureCreator : public BaseSignatureCreator {
public:
- explicit DummySignatureCreator(const CKeyStore* keystoreIn) : BaseSignatureCreator(keystoreIn) {}
+ explicit DummySignatureCreator(const SigningProvider* provider) : BaseSignatureCreator(provider) {}
const BaseSignatureChecker& Checker() const override;
bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const override;
};
@@ -71,8 +82,8 @@ struct SignatureData {
bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& scriptPubKey, SignatureData& sigdata);
/** Produce a script signature for a transaction. */
-bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType);
-bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType);
+bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType);
+bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType);
/** Combine two script signatures using a generic signature checker, intelligently, possibly with OP_0 placeholders. */
SignatureData CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker, const SignatureData& scriptSig1, const SignatureData& scriptSig2);
@@ -84,8 +95,8 @@ void UpdateInput(CTxIn& input, const SignatureData& data);
/* Check whether we know how to sign for an output like this, assuming we
* have all private keys. While this function does not need private keys, the passed
- * keystore is used to look up public keys and redeemscripts by hash.
+ * provider is used to look up public keys and redeemscripts by hash.
* Solvability is unrelated to whether we consider this output to be ours. */
-bool IsSolvable(const CKeyStore& store, const CScript& script);
+bool IsSolvable(const SigningProvider& provider, const CScript& script);
#endif // BITCOIN_SCRIPT_SIGN_H
diff --git a/src/serialize.h b/src/serialize.h
index 91da6b0f80..247e915298 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -59,6 +59,12 @@ inline T* NCONST_PTR(const T* val)
return const_cast<T*>(val);
}
+//! Safely convert odd char pointer types to standard ones.
+inline char* CharCast(char* c) { return c; }
+inline char* CharCast(unsigned char* c) { return (char*)c; }
+inline const char* CharCast(const char* c) { return c; }
+inline const char* CharCast(const unsigned char* c) { return (const char*)c; }
+
/*
* Lowest-level serialization and conversion.
* @note Sizes of these types are verified in the tests
@@ -177,6 +183,8 @@ template<typename Stream> inline void Serialize(Stream& s, int64_t a ) { ser_wri
template<typename Stream> inline void Serialize(Stream& s, uint64_t a) { ser_writedata64(s, a); }
template<typename Stream> inline void Serialize(Stream& s, float a ) { ser_writedata32(s, ser_float_to_uint32(a)); }
template<typename Stream> inline void Serialize(Stream& s, double a ) { ser_writedata64(s, ser_double_to_uint64(a)); }
+template<typename Stream, int N> inline void Serialize(Stream& s, const char (&a)[N]) { s.write(a, N); }
+template<typename Stream, int N> inline void Serialize(Stream& s, const unsigned char (&a)[N]) { s.write(CharCast(a), N); }
template<typename Stream> inline void Unserialize(Stream& s, char& a ) { a = ser_readdata8(s); } // TODO Get rid of bare char
template<typename Stream> inline void Unserialize(Stream& s, int8_t& a ) { a = ser_readdata8(s); }
@@ -189,6 +197,8 @@ template<typename Stream> inline void Unserialize(Stream& s, int64_t& a ) { a =
template<typename Stream> inline void Unserialize(Stream& s, uint64_t& a) { a = ser_readdata64(s); }
template<typename Stream> inline void Unserialize(Stream& s, float& a ) { a = ser_uint32_to_float(ser_readdata32(s)); }
template<typename Stream> inline void Unserialize(Stream& s, double& a ) { a = ser_uint64_to_double(ser_readdata64(s)); }
+template<typename Stream, int N> inline void Unserialize(Stream& s, char (&a)[N]) { s.read(a, N); }
+template<typename Stream, int N> inline void Unserialize(Stream& s, unsigned char (&a)[N]) { s.read(CharCast(a), N); }
template<typename Stream> inline void Serialize(Stream& s, bool a) { char f=a; ser_writedata8(s, f); }
template<typename Stream> inline void Unserialize(Stream& s, bool& a) { char f=ser_readdata8(s); a=f; }
diff --git a/src/test/blockchain_tests.cpp b/src/test/blockchain_tests.cpp
index 55fdd2c071..32b408838c 100644
--- a/src/test/blockchain_tests.cpp
+++ b/src/test/blockchain_tests.cpp
@@ -54,7 +54,7 @@ void TestDifficulty(uint32_t nbits, double expected_difficulty)
RejectDifficultyMismatch(difficulty, expected_difficulty);
}
-BOOST_FIXTURE_TEST_SUITE(blockchain_difficulty_tests, BasicTestingSetup)
+BOOST_FIXTURE_TEST_SUITE(blockchain_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(get_difficulty_for_very_low_target)
{
diff --git a/src/test/compress_tests.cpp b/src/test/compress_tests.cpp
index 3c26013622..127cc154df 100644
--- a/src/test/compress_tests.cpp
+++ b/src/test/compress_tests.cpp
@@ -25,16 +25,16 @@
BOOST_FIXTURE_TEST_SUITE(compress_tests, BasicTestingSetup)
bool static TestEncode(uint64_t in) {
- return in == CTxOutCompressor::DecompressAmount(CTxOutCompressor::CompressAmount(in));
+ return in == DecompressAmount(CompressAmount(in));
}
bool static TestDecode(uint64_t in) {
- return in == CTxOutCompressor::CompressAmount(CTxOutCompressor::DecompressAmount(in));
+ return in == CompressAmount(DecompressAmount(in));
}
bool static TestPair(uint64_t dec, uint64_t enc) {
- return CTxOutCompressor::CompressAmount(dec) == enc &&
- CTxOutCompressor::DecompressAmount(enc) == dec;
+ return CompressAmount(dec) == enc &&
+ DecompressAmount(enc) == dec;
}
BOOST_AUTO_TEST_CASE(compress_amounts)
diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json
index f8a1347c31..abb46fe533 100644
--- a/src/test/data/tx_invalid.json
+++ b/src/test/data/tx_invalid.json
@@ -321,7 +321,7 @@
["where the pubkey is obtained through key recovery with sig and the wrong sighash."],
["This is to show that FindAndDelete is applied only to non-segwit scripts"],
["To show that the tests are 'correctly wrong', they should pass by modifying OP_CHECKSIG under interpreter.cpp"],
-["by replacing (sigversion == SIGVERSION_BASE) with (sigversion != SIGVERSION_BASE)"],
+["by replacing (sigversion == SigVersion::BASE) with (sigversion != SigVersion::BASE)"],
["Non-segwit: wrong sighash (without FindAndDelete) = 1ba1fe3bc90c5d1265460e684ce6774e324f0fabdf67619eda729e64e8b6bc08"],
[[["f18783ace138abac5d3a7a5cf08e88fe6912f267ef936452e0c27d090621c169", 7000, "HASH160 0x14 0x0c746489e2d83cdbb5b90b432773342ba809c134 EQUAL", 200000]],
"010000000169c12106097dc2e0526493ef67f21269fe888ef05c7a3a5dacab38e1ac8387f1581b0000b64830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e012103b12a1ec8428fc74166926318c15e17408fea82dbb157575e16a8c365f546248f4aad4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e01ffffffff0101000000000000000000000000", "P2SH,WITNESS"],
@@ -332,7 +332,7 @@
["Script is 2 CHECKMULTISIGVERIFY <sig1> <sig2> DROP"],
["52af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c0395960175"],
["Signature is 0 <sig1> <sig2> 2 <key1> <key2>"],
-["Should pass by replacing (sigversion == SIGVERSION_BASE) with (sigversion != SIGVERSION_BASE) under OP_CHECKMULTISIG"],
+["Should pass by replacing (sigversion == SigVersion::BASE) with (sigversion != SigVersion::BASE) under OP_CHECKMULTISIG"],
["Non-segwit: wrong sighash (without FindAndDelete) = 4bc6a53e8e16ef508c19e38bba08831daba85228b0211f323d4cb0999cf2a5e8"],
[[["9628667ad48219a169b41b020800162287d2c0f713c04157e95c484a8dcb7592", 7000, "HASH160 0x14 0x5748407f5ca5cdca53ba30b79040260770c9ee1b EQUAL", 200000]],
"01000000019275cb8d4a485ce95741c013f7c0d28722160008021bb469a11982d47a662896581b0000fd6f01004830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c039596015221023fd5dd42b44769c5653cbc5947ff30ab8871f240ad0c0e7432aefe84b5b4ff3421039d52178dbde360b83f19cf348deb04fa8360e1bf5634577be8e50fafc2b0e4ef4c9552af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c0395960175ffffffff0101000000000000000000000000", "P2SH,WITNESS"],
diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp
index 72d9d3d75c..b593f9633c 100644
--- a/src/test/multisig_tests.cpp
+++ b/src/test/multisig_tests.cpp
@@ -21,7 +21,7 @@ BOOST_FIXTURE_TEST_SUITE(multisig_tests, BasicTestingSetup)
CScript
sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transaction, int whichIn)
{
- uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL, 0, SIGVERSION_BASE);
+ uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL, 0, SigVersion::BASE);
CScript result;
result << OP_0; // CHECKMULTISIG bug workaround
diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp
index e03234060d..6552613c04 100644
--- a/src/test/net_tests.cpp
+++ b/src/test/net_tests.cpp
@@ -64,7 +64,7 @@ public:
CDataStream AddrmanToStream(CAddrManSerializationMock& _addrman)
{
CDataStream ssPeersIn(SER_DISK, CLIENT_VERSION);
- ssPeersIn << FLATDATA(Params().MessageStart());
+ ssPeersIn << Params().MessageStart();
ssPeersIn << _addrman;
std::string str = ssPeersIn.str();
std::vector<unsigned char> vchData(str.begin(), str.end());
@@ -110,7 +110,7 @@ BOOST_AUTO_TEST_CASE(caddrdb_read)
BOOST_CHECK(addrman1.size() == 0);
try {
unsigned char pchMsgTmp[4];
- ssPeers1 >> FLATDATA(pchMsgTmp);
+ ssPeers1 >> pchMsgTmp;
ssPeers1 >> addrman1;
} catch (const std::exception& e) {
exceptionThrown = true;
@@ -142,7 +142,7 @@ BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted)
BOOST_CHECK(addrman1.size() == 0);
try {
unsigned char pchMsgTmp[4];
- ssPeers1 >> FLATDATA(pchMsgTmp);
+ ssPeers1 >> pchMsgTmp;
ssPeers1 >> addrman1;
} catch (const std::exception& e) {
exceptionThrown = true;
diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp
index 01c3a6cedd..fe6f10d845 100644
--- a/src/test/prevector_tests.cpp
+++ b/src/test/prevector_tests.cpp
@@ -13,7 +13,7 @@
#include <boost/test/unit_test.hpp>
-BOOST_FIXTURE_TEST_SUITE(PrevectorTests, TestingSetup)
+BOOST_FIXTURE_TEST_SUITE(prevector_tests, TestingSetup)
template<unsigned int N, typename T>
class prevector_tester {
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index c7a497f3a7..46a2d13745 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -267,10 +267,10 @@ struct KeyData
}
};
-enum WitnessMode {
- WITNESS_NONE,
- WITNESS_PKH,
- WITNESS_SH
+enum class WitnessMode {
+ NONE,
+ PKH,
+ SH
};
class TestBuilder
@@ -308,15 +308,15 @@ private:
}
public:
- TestBuilder(const CScript& script_, const std::string& comment_, int flags_, bool P2SH = false, WitnessMode wm = WITNESS_NONE, int witnessversion = 0, CAmount nValue_ = 0) : script(script_), havePush(false), comment(comment_), flags(flags_), scriptError(SCRIPT_ERR_OK), nValue(nValue_)
+ TestBuilder(const CScript& script_, const std::string& comment_, int flags_, bool P2SH = false, WitnessMode wm = WitnessMode::NONE, int witnessversion = 0, CAmount nValue_ = 0) : script(script_), havePush(false), comment(comment_), flags(flags_), scriptError(SCRIPT_ERR_OK), nValue(nValue_)
{
CScript scriptPubKey = script;
- if (wm == WITNESS_PKH) {
+ if (wm == WitnessMode::PKH) {
uint160 hash;
CHash160().Write(&script[1], script.size() - 1).Finalize(hash.begin());
script = CScript() << OP_DUP << OP_HASH160 << ToByteVector(hash) << OP_EQUALVERIFY << OP_CHECKSIG;
scriptPubKey = CScript() << witnessversion << ToByteVector(hash);
- } else if (wm == WITNESS_SH) {
+ } else if (wm == WitnessMode::SH) {
witscript = scriptPubKey;
uint256 hash;
CSHA256().Write(&witscript[0], witscript.size()).Finalize(hash.begin());
@@ -361,7 +361,7 @@ public:
return *this;
}
- TestBuilder& PushSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32, SigVersion sigversion = SIGVERSION_BASE, CAmount amount = 0)
+ TestBuilder& PushSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32, SigVersion sigversion = SigVersion::BASE, CAmount amount = 0)
{
uint256 hash = SignatureHash(script, spendTx, 0, nHashType, amount, sigversion);
std::vector<unsigned char> vchSig, r, s;
@@ -379,7 +379,7 @@ public:
return *this;
}
- TestBuilder& PushWitSig(const CKey& key, CAmount amount = -1, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32, SigVersion sigversion = SIGVERSION_WITNESS_V0)
+ TestBuilder& PushWitSig(const CKey& key, CAmount amount = -1, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32, SigVersion sigversion = SigVersion::WITNESS_V0)
{
if (amount == -1)
amount = nValue;
@@ -747,57 +747,57 @@ BOOST_AUTO_TEST_CASE(script_build)
).PushSig(keys.key0).PushRedeem());
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
- "Basic P2WSH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH,
+ "Basic P2WSH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::SH,
0, 1).PushWitSig(keys.key0).PushWitRedeem());
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
- "Basic P2WPKH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_PKH,
+ "Basic P2WPKH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::PKH,
0, 1).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit());
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
- "Basic P2SH(P2WSH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH,
+ "Basic P2SH(P2WSH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WitnessMode::SH,
0, 1).PushWitSig(keys.key0).PushWitRedeem().PushRedeem());
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
- "Basic P2SH(P2WPKH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_PKH,
+ "Basic P2SH(P2WPKH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WitnessMode::PKH,
0, 1).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().PushRedeem());
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
- "Basic P2WSH with the wrong key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH
+ "Basic P2WSH with the wrong key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::SH
).PushWitSig(keys.key0).PushWitRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1),
- "Basic P2WPKH with the wrong key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_PKH
+ "Basic P2WPKH with the wrong key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::PKH
).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit().ScriptError(SCRIPT_ERR_EVAL_FALSE));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
- "Basic P2SH(P2WSH) with the wrong key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH
+ "Basic P2SH(P2WSH) with the wrong key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WitnessMode::SH
).PushWitSig(keys.key0).PushWitRedeem().PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1),
- "Basic P2SH(P2WPKH) with the wrong key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_PKH
+ "Basic P2SH(P2WPKH) with the wrong key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WitnessMode::PKH
).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit().PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
- "Basic P2WSH with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, false, WITNESS_SH
+ "Basic P2WSH with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, false, WitnessMode::SH
).PushWitSig(keys.key0).PushWitRedeem());
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1),
- "Basic P2WPKH with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, false, WITNESS_PKH
+ "Basic P2WPKH with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, false, WitnessMode::PKH
).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit());
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
- "Basic P2SH(P2WSH) with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, true, WITNESS_SH
+ "Basic P2SH(P2WSH) with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, true, WitnessMode::SH
).PushWitSig(keys.key0).PushWitRedeem().PushRedeem());
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1),
- "Basic P2SH(P2WPKH) with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, true, WITNESS_PKH
+ "Basic P2SH(P2WPKH) with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, true, WitnessMode::PKH
).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit().PushRedeem());
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
- "Basic P2WSH with wrong value", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH,
+ "Basic P2WSH with wrong value", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::SH,
0, 0).PushWitSig(keys.key0, 1).PushWitRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
- "Basic P2WPKH with wrong value", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_PKH,
+ "Basic P2WPKH with wrong value", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::PKH,
0, 0).PushWitSig(keys.key0, 1).Push(keys.pubkey0).AsWit().ScriptError(SCRIPT_ERR_EVAL_FALSE));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
- "Basic P2SH(P2WSH) with wrong value", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH,
+ "Basic P2SH(P2WSH) with wrong value", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WitnessMode::SH,
0, 0).PushWitSig(keys.key0, 1).PushWitRedeem().PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
- "Basic P2SH(P2WPKH) with wrong value", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_PKH,
+ "Basic P2SH(P2WPKH) with wrong value", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WitnessMode::PKH,
0, 0).PushWitSig(keys.key0, 1).Push(keys.pubkey0).AsWit().PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
"P2WPKH with future witness version", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH |
- SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM, false, WITNESS_PKH, 1
+ SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM, false, WitnessMode::PKH, 1
).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().ScriptError(SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM));
{
CScript witscript = CScript() << ToByteVector(keys.pubkey0);
@@ -810,22 +810,22 @@ BOOST_AUTO_TEST_CASE(script_build)
).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().ScriptError(SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH));
}
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
- "P2WSH with empty witness", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH
+ "P2WSH with empty witness", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::SH
).ScriptError(SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY));
{
CScript witscript = CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG;
tests.push_back(TestBuilder(witscript,
- "P2WSH with witness program mismatch", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH
+ "P2WSH with witness program mismatch", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::SH
).PushWitSig(keys.key0).Push(witscript).DamagePush(0).AsWit().ScriptError(SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH));
}
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
- "P2WPKH with witness program mismatch", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_PKH
+ "P2WPKH with witness program mismatch", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::PKH
).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().Push("0").AsWit().ScriptError(SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
- "P2WPKH with non-empty scriptSig", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_PKH
+ "P2WPKH with non-empty scriptSig", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::PKH
).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().Num(11).ScriptError(SCRIPT_ERR_WITNESS_MALLEATED));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1),
- "P2SH(P2WPKH) with superfluous push in scriptSig", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_PKH
+ "P2SH(P2WPKH) with superfluous push in scriptSig", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WitnessMode::PKH
).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit().Num(11).PushRedeem().ScriptError(SCRIPT_ERR_WITNESS_MALLEATED_P2SH));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"P2PK with witness", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH
@@ -833,95 +833,95 @@ BOOST_AUTO_TEST_CASE(script_build)
// Compressed keys should pass SCRIPT_VERIFY_WITNESS_PUBKEYTYPE
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG,
- "Basic P2WSH with compressed key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_SH,
+ "Basic P2WSH with compressed key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WitnessMode::SH,
0, 1).PushWitSig(keys.key0C).PushWitRedeem());
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C),
- "Basic P2WPKH with compressed key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_PKH,
+ "Basic P2WPKH with compressed key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WitnessMode::PKH,
0, 1).PushWitSig(keys.key0C).Push(keys.pubkey0C).AsWit());
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG,
- "Basic P2SH(P2WSH) with compressed key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_SH,
+ "Basic P2SH(P2WSH) with compressed key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WitnessMode::SH,
0, 1).PushWitSig(keys.key0C).PushWitRedeem().PushRedeem());
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C),
- "Basic P2SH(P2WPKH) with compressed key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_PKH,
+ "Basic P2SH(P2WPKH) with compressed key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WitnessMode::PKH,
0, 1).PushWitSig(keys.key0C).Push(keys.pubkey0C).AsWit().PushRedeem());
// Testing uncompressed key in witness with SCRIPT_VERIFY_WITNESS_PUBKEYTYPE
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
- "Basic P2WSH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_SH,
+ "Basic P2WSH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WitnessMode::SH,
0, 1).PushWitSig(keys.key0).PushWitRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
- "Basic P2WPKH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_PKH,
+ "Basic P2WPKH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WitnessMode::PKH,
0, 1).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
- "Basic P2SH(P2WSH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_SH,
+ "Basic P2SH(P2WSH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WitnessMode::SH,
0, 1).PushWitSig(keys.key0).PushWitRedeem().PushRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
- "Basic P2SH(P2WPKH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_PKH,
+ "Basic P2SH(P2WPKH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WitnessMode::PKH,
0, 1).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().PushRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
// P2WSH 1-of-2 multisig with compressed keys
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
- "P2WSH CHECKMULTISIG with compressed keys", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_SH,
+ "P2WSH CHECKMULTISIG with compressed keys", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WitnessMode::SH,
0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0C).PushWitRedeem());
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
- "P2SH(P2WSH) CHECKMULTISIG with compressed keys", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_SH,
+ "P2SH(P2WSH) CHECKMULTISIG with compressed keys", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WitnessMode::SH,
0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0C).PushWitRedeem().PushRedeem());
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
- "P2WSH CHECKMULTISIG with compressed keys", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_SH,
+ "P2WSH CHECKMULTISIG with compressed keys", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WitnessMode::SH,
0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1C).PushWitRedeem());
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
- "P2SH(P2WSH) CHECKMULTISIG with compressed keys", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_SH,
+ "P2SH(P2WSH) CHECKMULTISIG with compressed keys", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WitnessMode::SH,
0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1C).PushWitRedeem().PushRedeem());
// P2WSH 1-of-2 multisig with first key uncompressed
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG,
- "P2WSH CHECKMULTISIG with first key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH,
+ "P2WSH CHECKMULTISIG with first key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::SH,
0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0).PushWitRedeem());
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG,
- "P2SH(P2WSH) CHECKMULTISIG first key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH,
+ "P2SH(P2WSH) CHECKMULTISIG first key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WitnessMode::SH,
0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0).PushWitRedeem().PushRedeem());
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG,
- "P2WSH CHECKMULTISIG with first key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_SH,
+ "P2WSH CHECKMULTISIG with first key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WitnessMode::SH,
0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0).PushWitRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG,
- "P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_SH,
+ "P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WitnessMode::SH,
0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0).PushWitRedeem().PushRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG,
- "P2WSH CHECKMULTISIG with first key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH,
+ "P2WSH CHECKMULTISIG with first key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::SH,
0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1C).PushWitRedeem());
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG,
- "P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH,
+ "P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WitnessMode::SH,
0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1C).PushWitRedeem().PushRedeem());
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG,
- "P2WSH CHECKMULTISIG with first key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_SH,
+ "P2WSH CHECKMULTISIG with first key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WitnessMode::SH,
0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1C).PushWitRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG,
- "P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_SH,
+ "P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WitnessMode::SH,
0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1C).PushWitRedeem().PushRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
// P2WSH 1-of-2 multisig with second key uncompressed
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
- "P2WSH CHECKMULTISIG with second key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH,
+ "P2WSH CHECKMULTISIG with second key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::SH,
0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0C).PushWitRedeem());
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
- "P2SH(P2WSH) CHECKMULTISIG second key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH,
+ "P2SH(P2WSH) CHECKMULTISIG second key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WitnessMode::SH,
0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0C).PushWitRedeem().PushRedeem());
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
- "P2WSH CHECKMULTISIG with second key uncompressed and signing with the first key should pass as the uncompressed key is not used", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_SH,
+ "P2WSH CHECKMULTISIG with second key uncompressed and signing with the first key should pass as the uncompressed key is not used", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WitnessMode::SH,
0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0C).PushWitRedeem());
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
- "P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the first key should pass as the uncompressed key is not used", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_SH,
+ "P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the first key should pass as the uncompressed key is not used", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WitnessMode::SH,
0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0C).PushWitRedeem().PushRedeem());
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
- "P2WSH CHECKMULTISIG with second key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH,
+ "P2WSH CHECKMULTISIG with second key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::SH,
0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1).PushWitRedeem());
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
- "P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH,
+ "P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WitnessMode::SH,
0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1).PushWitRedeem().PushRedeem());
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
- "P2WSH CHECKMULTISIG with second key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_SH,
+ "P2WSH CHECKMULTISIG with second key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WitnessMode::SH,
0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1).PushWitRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
- "P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_SH,
+ "P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WitnessMode::SH,
0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1).PushWitRedeem().PushRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
std::set<std::string> tests_set;
@@ -1009,21 +1009,21 @@ BOOST_AUTO_TEST_CASE(script_PushData)
ScriptError err;
std::vector<std::vector<unsigned char> > directStack;
- BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SIGVERSION_BASE, &err));
+ BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
std::vector<std::vector<unsigned char> > pushdata1Stack;
- BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SIGVERSION_BASE, &err));
+ BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
BOOST_CHECK(pushdata1Stack == directStack);
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
std::vector<std::vector<unsigned char> > pushdata2Stack;
- BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SIGVERSION_BASE, &err));
+ BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
BOOST_CHECK(pushdata2Stack == directStack);
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
std::vector<std::vector<unsigned char> > pushdata4Stack;
- BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SIGVERSION_BASE, &err));
+ BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
BOOST_CHECK(pushdata4Stack == directStack);
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
}
@@ -1031,7 +1031,7 @@ BOOST_AUTO_TEST_CASE(script_PushData)
CScript
sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transaction)
{
- uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL, 0, SIGVERSION_BASE);
+ uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL, 0, SigVersion::BASE);
CScript result;
//
@@ -1227,15 +1227,15 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
// A couple of partially-signed versions:
std::vector<unsigned char> sig1;
- uint256 hash1 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_ALL, 0, SIGVERSION_BASE);
+ uint256 hash1 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_ALL, 0, SigVersion::BASE);
BOOST_CHECK(keys[0].Sign(hash1, sig1));
sig1.push_back(SIGHASH_ALL);
std::vector<unsigned char> sig2;
- uint256 hash2 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_NONE, 0, SIGVERSION_BASE);
+ uint256 hash2 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_NONE, 0, SigVersion::BASE);
BOOST_CHECK(keys[1].Sign(hash2, sig2));
sig2.push_back(SIGHASH_NONE);
std::vector<unsigned char> sig3;
- uint256 hash3 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_SINGLE, 0, SIGVERSION_BASE);
+ uint256 hash3 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_SINGLE, 0, SigVersion::BASE);
BOOST_CHECK(keys[2].Sign(hash3, sig3));
sig3.push_back(SIGHASH_SINGLE);
diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp
index 7a79a77e8b..9b8b7bdc56 100644
--- a/src/test/serialize_tests.cpp
+++ b/src/test/serialize_tests.cpp
@@ -19,11 +19,15 @@ protected:
int intval;
bool boolval;
std::string stringval;
- const char* charstrval;
+ char charstrval[16];
CTransactionRef txval;
public:
CSerializeMethodsTestSingle() = default;
- CSerializeMethodsTestSingle(int intvalin, bool boolvalin, std::string stringvalin, const char* charstrvalin, CTransaction txvalin) : intval(intvalin), boolval(boolvalin), stringval(std::move(stringvalin)), charstrval(charstrvalin), txval(MakeTransactionRef(txvalin)){}
+ CSerializeMethodsTestSingle(int intvalin, bool boolvalin, std::string stringvalin, const char* charstrvalin, CTransaction txvalin) : intval(intvalin), boolval(boolvalin), stringval(std::move(stringvalin)), txval(MakeTransactionRef(txvalin))
+ {
+ memcpy(charstrval, charstrvalin, sizeof(charstrval));
+ }
+
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
@@ -31,7 +35,7 @@ public:
READWRITE(intval);
READWRITE(boolval);
READWRITE(stringval);
- READWRITE(FLATDATA(charstrval));
+ READWRITE(charstrval);
READWRITE(txval);
}
@@ -53,7 +57,7 @@ public:
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(intval, boolval, stringval, FLATDATA(charstrval), txval);
+ READWRITE(intval, boolval, stringval, charstrval, txval);
}
};
@@ -344,7 +348,7 @@ BOOST_AUTO_TEST_CASE(class_methods)
int intval(100);
bool boolval(true);
std::string stringval("testing");
- const char* charstrval("testing charstr");
+ const char charstrval[16] = "testing charstr";
CMutableTransaction txval;
CSerializeMethodsTestSingle methodtest1(intval, boolval, stringval, charstrval, txval);
CSerializeMethodsTestMany methodtest2(intval, boolval, stringval, charstrval, txval);
@@ -360,7 +364,7 @@ BOOST_AUTO_TEST_CASE(class_methods)
BOOST_CHECK(methodtest2 == methodtest3);
BOOST_CHECK(methodtest3 == methodtest4);
- CDataStream ss2(SER_DISK, PROTOCOL_VERSION, intval, boolval, stringval, FLATDATA(charstrval), txval);
+ CDataStream ss2(SER_DISK, PROTOCOL_VERSION, intval, boolval, stringval, charstrval, txval);
ss2 >> methodtest3;
BOOST_CHECK(methodtest3 == methodtest4);
}
diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp
index 32cd3a50b0..a2bd8998b1 100644
--- a/src/test/sighash_tests.cpp
+++ b/src/test/sighash_tests.cpp
@@ -138,7 +138,7 @@ BOOST_AUTO_TEST_CASE(sighash_test)
uint256 sh, sho;
sho = SignatureHashOld(scriptCode, txTo, nIn, nHashType);
- sh = SignatureHash(scriptCode, txTo, nIn, nHashType, 0, SIGVERSION_BASE);
+ sh = SignatureHash(scriptCode, txTo, nIn, nHashType, 0, SigVersion::BASE);
#if defined(PRINT_SIGHASH_JSON)
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << txTo;
@@ -204,7 +204,7 @@ BOOST_AUTO_TEST_CASE(sighash_from_data)
continue;
}
- sh = SignatureHash(scriptCode, *tx, nIn, nHashType, 0, SIGVERSION_BASE);
+ sh = SignatureHash(scriptCode, *tx, nIn, nHashType, 0, SigVersion::BASE);
BOOST_CHECK_MESSAGE(sh.GetHex() == sigHashHex, strTest);
}
}
diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp
index 1108dab584..5d057108b1 100644
--- a/src/test/streams_tests.cpp
+++ b/src/test/streams_tests.cpp
@@ -57,16 +57,16 @@ BOOST_AUTO_TEST_CASE(streams_vector_writer)
BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 0, 0, 1, 2}}));
vch.clear();
- CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 0, FLATDATA(bytes));
+ CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 0, bytes);
BOOST_CHECK((vch == std::vector<unsigned char>{{3, 4, 5, 6}}));
- CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 0, FLATDATA(bytes));
+ CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 0, bytes);
BOOST_CHECK((vch == std::vector<unsigned char>{{3, 4, 5, 6}}));
vch.clear();
vch.resize(4, 8);
- CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 2, a, FLATDATA(bytes), b);
+ CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 2, a, bytes, b);
BOOST_CHECK((vch == std::vector<unsigned char>{{8, 8, 1, 3, 4, 5, 6, 2}}));
- CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 2, a, FLATDATA(bytes), b);
+ CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 2, a, bytes, b);
BOOST_CHECK((vch == std::vector<unsigned char>{{8, 8, 1, 3, 4, 5, 6, 2}}));
vch.clear();
}
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index 95c4825b84..9390a93b99 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -145,9 +145,9 @@ TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransaction>&
for (const CMutableTransaction& tx : txns)
block.vtx.push_back(MakeTransactionRef(tx));
// IncrementExtraNonce creates a valid coinbase and merkleRoot
- unsigned int extraNonce = 0;
{
LOCK(cs_main);
+ unsigned int extraNonce = 0;
IncrementExtraNonce(&block, chainActive.Tip(), extraNonce);
}
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index edfb35d155..b222392ee5 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -407,7 +407,7 @@ static CScript PushAll(const std::vector<valtype>& values)
void ReplaceRedeemScript(CScript& script, const CScript& redeemScript)
{
std::vector<valtype> stack;
- EvalScript(stack, script, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), SIGVERSION_BASE);
+ EvalScript(stack, script, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), SigVersion::BASE);
assert(stack.size() > 0);
stack.back() = std::vector<unsigned char>(redeemScript.begin(), redeemScript.end());
script = PushAll(stack);
diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp
index 1aa54189b6..7087c26774 100644
--- a/src/test/txvalidationcache_tests.cpp
+++ b/src/test/txvalidationcache_tests.cpp
@@ -56,7 +56,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
// Sign:
std::vector<unsigned char> vchSig;
- uint256 hash = SignatureHash(scriptPubKey, spends[i], 0, SIGHASH_ALL, 0, SIGVERSION_BASE);
+ uint256 hash = SignatureHash(scriptPubKey, spends[i], 0, SIGHASH_ALL, 0, SigVersion::BASE);
BOOST_CHECK(coinbaseKey.Sign(hash, vchSig));
vchSig.push_back((unsigned char)SIGHASH_ALL);
spends[i].vin[0].scriptSig << vchSig;
@@ -182,7 +182,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
// Sign, with a non-DER signature
{
std::vector<unsigned char> vchSig;
- uint256 hash = SignatureHash(p2pk_scriptPubKey, spend_tx, 0, SIGHASH_ALL, 0, SIGVERSION_BASE);
+ uint256 hash = SignatureHash(p2pk_scriptPubKey, spend_tx, 0, SIGHASH_ALL, 0, SigVersion::BASE);
BOOST_CHECK(coinbaseKey.Sign(hash, vchSig));
vchSig.push_back((unsigned char) 0); // padding byte makes this non-DER
vchSig.push_back((unsigned char)SIGHASH_ALL);
@@ -256,7 +256,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
// Sign
std::vector<unsigned char> vchSig;
- uint256 hash = SignatureHash(spend_tx.vout[2].scriptPubKey, invalid_with_cltv_tx, 0, SIGHASH_ALL, 0, SIGVERSION_BASE);
+ uint256 hash = SignatureHash(spend_tx.vout[2].scriptPubKey, invalid_with_cltv_tx, 0, SIGHASH_ALL, 0, SigVersion::BASE);
BOOST_CHECK(coinbaseKey.Sign(hash, vchSig));
vchSig.push_back((unsigned char)SIGHASH_ALL);
invalid_with_cltv_tx.vin[0].scriptSig = CScript() << vchSig << 101;
@@ -284,7 +284,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
// Sign
std::vector<unsigned char> vchSig;
- uint256 hash = SignatureHash(spend_tx.vout[3].scriptPubKey, invalid_with_csv_tx, 0, SIGHASH_ALL, 0, SIGVERSION_BASE);
+ uint256 hash = SignatureHash(spend_tx.vout[3].scriptPubKey, invalid_with_csv_tx, 0, SIGHASH_ALL, 0, SigVersion::BASE);
BOOST_CHECK(coinbaseKey.Sign(hash, vchSig));
vchSig.push_back((unsigned char)SIGHASH_ALL);
invalid_with_csv_tx.vin[0].scriptSig = CScript() << vchSig << 101;
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index b6f3cbe2b7..4b44bbadac 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -185,17 +185,11 @@ BOOST_AUTO_TEST_CASE(util_FormatISO8601Time)
BOOST_CHECK_EQUAL(FormatISO8601Time(1317425777), "23:36:17Z");
}
-class TestArgsManager : public ArgsManager
+struct TestArgsManager : public ArgsManager
{
-public:
- std::map<std::string, std::string>& GetMapArgs()
- {
- return mapArgs;
- };
- const std::map<std::string, std::vector<std::string> >& GetMapMultiArgs()
- {
- return mapMultiArgs;
- };
+ std::map<std::string, std::string>& GetMapArgs() { return mapArgs; }
+ const std::map<std::string, std::vector<std::string> >& GetMapMultiArgs() { return mapMultiArgs; }
+ const std::unordered_set<std::string>& GetNegatedArgs() { return m_negated_args; }
};
BOOST_AUTO_TEST_CASE(util_ParseParameters)
@@ -223,6 +217,54 @@ BOOST_AUTO_TEST_CASE(util_ParseParameters)
BOOST_CHECK(testArgs.GetArgs("-ccc").size() == 2);
}
+BOOST_AUTO_TEST_CASE(util_GetBoolArg)
+{
+ TestArgsManager testArgs;
+ const char *argv_test[] = {
+ "ignored", "-a", "-nob", "-c=0", "-d=1", "-e=false", "-f=true"};
+ testArgs.ParseParameters(7, (char**)argv_test);
+
+ // Each letter should be set.
+ for (char opt : "abcdef")
+ BOOST_CHECK(testArgs.IsArgSet({'-', opt}) || !opt);
+
+ // Nothing else should be in the map
+ BOOST_CHECK(testArgs.GetMapArgs().size() == 6 &&
+ testArgs.GetMapMultiArgs().size() == 6);
+
+ // The -no prefix should get stripped on the way in.
+ BOOST_CHECK(!testArgs.IsArgSet("-nob"));
+
+ // The -b option is flagged as negated, and nothing else is
+ BOOST_CHECK(testArgs.IsArgNegated("-b"));
+ BOOST_CHECK(testArgs.GetNegatedArgs().size() == 1);
+ BOOST_CHECK(!testArgs.IsArgNegated("-a"));
+
+ // Check expected values.
+ BOOST_CHECK(testArgs.GetBoolArg("-a", false) == true);
+ BOOST_CHECK(testArgs.GetBoolArg("-b", true) == false);
+ BOOST_CHECK(testArgs.GetBoolArg("-c", true) == false);
+ BOOST_CHECK(testArgs.GetBoolArg("-d", false) == true);
+ BOOST_CHECK(testArgs.GetBoolArg("-e", true) == false);
+ BOOST_CHECK(testArgs.GetBoolArg("-f", true) == false);
+}
+
+BOOST_AUTO_TEST_CASE(util_GetBoolArgEdgeCases)
+{
+ // Test some awful edge cases that hopefully no user will ever exercise.
+ TestArgsManager testArgs;
+ const char *argv_test[] = {"ignored", "-nofoo", "-foo", "-nobar=0"};
+ testArgs.ParseParameters(4, (char**)argv_test);
+
+ // This was passed twice, second one overrides the negative setting.
+ BOOST_CHECK(!testArgs.IsArgNegated("-foo"));
+ BOOST_CHECK(testArgs.GetBoolArg("-foo", false) == true);
+
+ // A double negative is a positive.
+ BOOST_CHECK(testArgs.IsArgNegated("-bar"));
+ BOOST_CHECK(testArgs.GetBoolArg("-bar", false) == true);
+}
+
BOOST_AUTO_TEST_CASE(util_GetArg)
{
TestArgsManager testArgs;
@@ -704,9 +746,8 @@ static constexpr char ExitCommand = 'X';
static void TestOtherProcess(fs::path dirname, std::string lockname, int fd)
{
char ch;
- int rv;
while (true) {
- rv = read(fd, &ch, 1); // Wait for command
+ int rv = read(fd, &ch, 1); // Wait for command
assert(rv == 1);
switch(ch) {
case LockCommand:
diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp
index 5d6f781404..92ef58e517 100644
--- a/src/test/versionbits_tests.cpp
+++ b/src/test/versionbits_tests.cpp
@@ -101,8 +101,8 @@ public:
VersionBitsTester& TestDefined() {
for (int i = 0; i < CHECKERS; i++) {
if (InsecureRandBits(i) == 0) {
- BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == THRESHOLD_DEFINED, strprintf("Test %i for DEFINED", num));
- BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == THRESHOLD_ACTIVE, strprintf("Test %i for ACTIVE (always active)", num));
+ BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::DEFINED, strprintf("Test %i for DEFINED", num));
+ BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE (always active)", num));
}
}
num++;
@@ -112,8 +112,8 @@ public:
VersionBitsTester& TestStarted() {
for (int i = 0; i < CHECKERS; i++) {
if (InsecureRandBits(i) == 0) {
- BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == THRESHOLD_STARTED, strprintf("Test %i for STARTED", num));
- BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == THRESHOLD_ACTIVE, strprintf("Test %i for ACTIVE (always active)", num));
+ BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::STARTED, strprintf("Test %i for STARTED", num));
+ BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE (always active)", num));
}
}
num++;
@@ -123,8 +123,8 @@ public:
VersionBitsTester& TestLockedIn() {
for (int i = 0; i < CHECKERS; i++) {
if (InsecureRandBits(i) == 0) {
- BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == THRESHOLD_LOCKED_IN, strprintf("Test %i for LOCKED_IN", num));
- BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == THRESHOLD_ACTIVE, strprintf("Test %i for ACTIVE (always active)", num));
+ BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::LOCKED_IN, strprintf("Test %i for LOCKED_IN", num));
+ BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE (always active)", num));
}
}
num++;
@@ -134,8 +134,8 @@ public:
VersionBitsTester& TestActive() {
for (int i = 0; i < CHECKERS; i++) {
if (InsecureRandBits(i) == 0) {
- BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == THRESHOLD_ACTIVE, strprintf("Test %i for ACTIVE", num));
- BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == THRESHOLD_ACTIVE, strprintf("Test %i for ACTIVE (always active)", num));
+ BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE", num));
+ BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE (always active)", num));
}
}
num++;
@@ -145,8 +145,8 @@ public:
VersionBitsTester& TestFailed() {
for (int i = 0; i < CHECKERS; i++) {
if (InsecureRandBits(i) == 0) {
- BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == THRESHOLD_FAILED, strprintf("Test %i for FAILED", num));
- BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == THRESHOLD_ACTIVE, strprintf("Test %i for ACTIVE (always active)", num));
+ BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::FAILED, strprintf("Test %i for FAILED", num));
+ BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE (always active)", num));
}
}
num++;
diff --git a/src/txdb.cpp b/src/txdb.cpp
index 91d6c98430..8550a7e889 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -147,7 +147,7 @@ size_t CCoinsViewDB::EstimateSize() const
return db.EstimateSize(DB_COIN, (char)(DB_COIN+1));
}
-CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
+CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(gArgs.IsArgSet("-blocksdir") ? GetDataDir() / "blocks" / "index" : GetBlocksDir() / "index", nCacheSize, fMemory, fWipe) {
}
bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 462c165cc4..d03429ca81 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -339,7 +339,7 @@ CTxMemPool::CTxMemPool(CBlockPolicyEstimator* estimator) :
nCheckFrequency = 0;
}
-bool CTxMemPool::isSpent(const COutPoint& outpoint)
+bool CTxMemPool::isSpent(const COutPoint& outpoint) const
{
LOCK(cs);
return mapNextTx.count(outpoint);
diff --git a/src/txmempool.h b/src/txmempool.h
index ff792cbdf0..a1cde6f779 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -550,7 +550,7 @@ public:
void _clear(); //lock free
bool CompareDepthAndScore(const uint256& hasha, const uint256& hashb);
void queryHashes(std::vector<uint256>& vtxid);
- bool isSpent(const COutPoint& outpoint);
+ bool isSpent(const COutPoint& outpoint) const;
unsigned int GetTransactionsUpdated() const;
void AddTransactionsUpdated(unsigned int n);
/**
diff --git a/src/util.cpp b/src/util.cpp
index 494d5c4eaf..490897899b 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -70,8 +70,6 @@
#include <malloc.h>
#endif
-#include <boost/algorithm/string/case_conv.hpp> // for to_lower()
-#include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith()
#include <boost/interprocess/sync/file_lock.hpp>
#include <boost/program_options/detail/config_file.hpp>
#include <boost/thread.hpp>
@@ -432,7 +430,23 @@ bool DirIsWritable(const fs::path& directory)
return true;
}
-/** Interpret string as boolean, for argument parsing */
+/**
+ * Interpret a string argument as a boolean.
+ *
+ * The definition of atoi() requires that non-numeric string values like "foo",
+ * return 0. This means that if a user unintentionally supplies a non-integer
+ * argument here, the return value is always false. This means that -foo=false
+ * does what the user probably expects, but -foo=true is well defined but does
+ * not do what they probably expected.
+ *
+ * The return value of atoi() is undefined when given input not representable as
+ * an int. On most systems this means string value between "-2147483648" and
+ * "2147483647" are well defined (this method will return true). Setting
+ * -txindex=2147483648 on most systems, however, is probably undefined.
+ *
+ * For a more extensive discussion of this topic (and a wide range of opinions
+ * on the Right Way to change this code), see PR12713.
+ */
static bool InterpretBool(const std::string& strValue)
{
if (strValue.empty())
@@ -440,13 +454,30 @@ static bool InterpretBool(const std::string& strValue)
return (atoi(strValue) != 0);
}
-/** Turn -noX into -X=0 */
-static void InterpretNegativeSetting(std::string& strKey, std::string& strValue)
+/**
+ * Interpret -nofoo as if the user supplied -foo=0.
+ *
+ * This method also tracks when the -no form was supplied, and treats "-foo" as
+ * a negated option when this happens. This can be later checked using the
+ * IsArgNegated() method. One use case for this is to have a way to disable
+ * options that are not normally boolean (e.g. using -nodebuglogfile to request
+ * that debug log output is not sent to any file at all).
+ */
+void ArgsManager::InterpretNegatedOption(std::string& key, std::string& val)
{
- if (strKey.length()>3 && strKey[0]=='-' && strKey[1]=='n' && strKey[2]=='o')
- {
- strKey = "-" + strKey.substr(3);
- strValue = InterpretBool(strValue) ? "0" : "1";
+ if (key.substr(0, 3) == "-no") {
+ bool bool_val = InterpretBool(val);
+ if (!bool_val ) {
+ // Double negatives like -nofoo=0 are supported (but discouraged)
+ LogPrintf("Warning: parsed potentially confusing double-negative %s=%s\n", key, val);
+ }
+ key.erase(1, 2);
+ m_negated_args.insert(key);
+ val = bool_val ? "0" : "1";
+ } else {
+ // In an invocation like "bitcoind -nofoo -foo" we want to unmark -foo
+ // as negated when we see the second option.
+ m_negated_args.erase(key);
}
}
@@ -455,34 +486,34 @@ void ArgsManager::ParseParameters(int argc, const char* const argv[])
LOCK(cs_args);
mapArgs.clear();
mapMultiArgs.clear();
-
- for (int i = 1; i < argc; i++)
- {
- std::string str(argv[i]);
- std::string strValue;
- size_t is_index = str.find('=');
- if (is_index != std::string::npos)
- {
- strValue = str.substr(is_index+1);
- str = str.substr(0, is_index);
+ m_negated_args.clear();
+
+ for (int i = 1; i < argc; i++) {
+ std::string key(argv[i]);
+ std::string val;
+ size_t is_index = key.find('=');
+ if (is_index != std::string::npos) {
+ val = key.substr(is_index + 1);
+ key.erase(is_index);
}
#ifdef WIN32
- boost::to_lower(str);
- if (boost::algorithm::starts_with(str, "/"))
- str = "-" + str.substr(1);
+ std::transform(key.begin(), key.end(), key.begin(), ::tolower);
+ if (key[0] == '/')
+ key[0] = '-';
#endif
- if (str[0] != '-')
+ if (key[0] != '-')
break;
- // Interpret --foo as -foo.
- // If both --foo and -foo are set, the last takes effect.
- if (str.length() > 1 && str[1] == '-')
- str = str.substr(1);
- InterpretNegativeSetting(str, strValue);
+ // Transform --foo to -foo
+ if (key.length() > 1 && key[1] == '-')
+ key.erase(0, 1);
- mapArgs[str] = strValue;
- mapMultiArgs[str].push_back(strValue);
+ // Transform -nofoo to -foo=0
+ InterpretNegatedOption(key, val);
+
+ mapArgs[key] = val;
+ mapMultiArgs[key].push_back(val);
}
}
@@ -500,6 +531,12 @@ bool ArgsManager::IsArgSet(const std::string& strArg) const
return mapArgs.count(strArg);
}
+bool ArgsManager::IsArgNegated(const std::string& strArg) const
+{
+ LOCK(cs_args);
+ return m_negated_args.find(strArg) != m_negated_args.end();
+}
+
std::string ArgsManager::GetArg(const std::string& strArg, const std::string& strDefault) const
{
LOCK(cs_args);
@@ -613,10 +650,41 @@ fs::path GetDefaultDataDir()
#endif
}
+static fs::path g_blocks_path_cached;
+static fs::path g_blocks_path_cache_net_specific;
static fs::path pathCached;
static fs::path pathCachedNetSpecific;
static CCriticalSection csPathCached;
+const fs::path &GetBlocksDir(bool fNetSpecific)
+{
+
+ LOCK(csPathCached);
+
+ fs::path &path = fNetSpecific ? g_blocks_path_cache_net_specific : g_blocks_path_cached;
+
+ // This can be called during exceptions by LogPrintf(), so we cache the
+ // value so we don't have to do memory allocations after that.
+ if (!path.empty())
+ return path;
+
+ if (gArgs.IsArgSet("-blocksdir")) {
+ path = fs::system_complete(gArgs.GetArg("-blocksdir", ""));
+ if (!fs::is_directory(path)) {
+ path = "";
+ return path;
+ }
+ } else {
+ path = GetDataDir(false);
+ }
+ if (fNetSpecific)
+ path /= BaseParams().DataDir();
+
+ path /= "blocks";
+ fs::create_directories(path);
+ return path;
+}
+
const fs::path &GetDataDir(bool fNetSpecific)
{
@@ -655,6 +723,8 @@ void ClearDatadirCache()
pathCached = fs::path();
pathCachedNetSpecific = fs::path();
+ g_blocks_path_cached = fs::path();
+ g_blocks_path_cache_net_specific = fs::path();
}
fs::path GetConfigFile(const std::string& confPath)
@@ -678,7 +748,7 @@ void ArgsManager::ReadConfigFile(const std::string& confPath)
// Don't overwrite existing settings so command line settings override bitcoin.conf
std::string strKey = std::string("-") + it->string_key;
std::string strValue = it->value[0];
- InterpretNegativeSetting(strKey, strValue);
+ InterpretNegatedOption(strKey, strValue);
if (mapArgs.count(strKey) == 0)
mapArgs[strKey] = strValue;
mapMultiArgs[strKey].push_back(strValue);
diff --git a/src/util.h b/src/util.h
index 04ff44f218..4c473c9354 100644
--- a/src/util.h
+++ b/src/util.h
@@ -25,6 +25,7 @@
#include <map>
#include <stdint.h>
#include <string>
+#include <unordered_set>
#include <vector>
#include <boost/signals2/signal.hpp>
@@ -183,6 +184,7 @@ void ReleaseDirectoryLocks();
bool TryCreateDirectories(const fs::path& p);
fs::path GetDefaultDataDir();
+const fs::path &GetBlocksDir(bool fNetSpecific = true);
const fs::path &GetDataDir(bool fNetSpecific = true);
void ClearDatadirCache();
fs::path GetConfigFile(const std::string& confPath);
@@ -223,6 +225,8 @@ protected:
mutable CCriticalSection cs_args;
std::map<std::string, std::string> mapArgs;
std::map<std::string, std::vector<std::string>> mapMultiArgs;
+ std::unordered_set<std::string> m_negated_args;
+
public:
void ParseParameters(int argc, const char*const argv[]);
void ReadConfigFile(const std::string& confPath);
@@ -244,6 +248,15 @@ public:
bool IsArgSet(const std::string& strArg) const;
/**
+ * Return true if the argument was originally passed as a negated option,
+ * i.e. -nofoo.
+ *
+ * @param strArg Argument to get (e.g. "-foo")
+ * @return true if the argument was passed negated
+ */
+ bool IsArgNegated(const std::string& strArg) const;
+
+ /**
* Return string argument or default value
*
* @param strArg Argument to get (e.g. "-foo")
@@ -291,6 +304,11 @@ public:
// Forces an arg setting. Called by SoftSetArg() if the arg hasn't already
// been set. Also called directly in testing.
void ForceSetArg(const std::string& strArg, const std::string& strValue);
+
+private:
+
+ // Munge -nofoo into -foo=0 and track the value as negated.
+ void InterpretNegatedOption(std::string &key, std::string &val);
};
extern ArgsManager gArgs;
diff --git a/src/validation.cpp b/src/validation.cpp
index 084dd1f121..df8729e382 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -227,6 +227,7 @@ CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE;
CBlockPolicyEstimator feeEstimator;
CTxMemPool mempool(&feeEstimator);
+std::atomic_bool g_is_mempool_loaded{false};
/** Constant stuff for coinbase transactions we create: */
CScript COINBASE_FLAGS;
@@ -280,11 +281,11 @@ std::unique_ptr<CCoinsViewDB> pcoinsdbview;
std::unique_ptr<CCoinsViewCache> pcoinsTip;
std::unique_ptr<CBlockTreeDB> pblocktree;
-enum FlushStateMode {
- FLUSH_STATE_NONE,
- FLUSH_STATE_IF_NEEDED,
- FLUSH_STATE_PERIODIC,
- FLUSH_STATE_ALWAYS
+enum class FlushStateMode {
+ NONE,
+ IF_NEEDED,
+ PERIODIC,
+ ALWAYS
};
// See definition for documentation
@@ -988,7 +989,7 @@ static bool AcceptToMemoryPoolWithTime(const CChainParams& chainparams, CTxMemPo
}
// After we've (potentially) uncached entries, ensure our coins cache is still within its size limits
CValidationState stateDummy;
- FlushStateToDisk(chainparams, stateDummy, FLUSH_STATE_PERIODIC);
+ FlushStateToDisk(chainparams, stateDummy, FlushStateMode::PERIODIC);
return res;
}
@@ -1082,7 +1083,7 @@ static bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMes
// Write index header
unsigned int nSize = GetSerializeSize(fileout, block);
- fileout << FLATDATA(messageStart) << nSize;
+ fileout << messageStart << nSize;
// Write block
long fileOutPos = ftell(fileout.Get());
@@ -1446,7 +1447,7 @@ bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint
// Write index header
unsigned int nSize = GetSerializeSize(fileout, blockundo);
- fileout << FLATDATA(messageStart) << nSize;
+ fileout << messageStart << nSize;
// Write undo data
long fileOutPos = ftell(fileout.Get());
@@ -1689,7 +1690,7 @@ int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Para
for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) {
ThresholdState state = VersionBitsState(pindexPrev, params, static_cast<Consensus::DeploymentPos>(i), versionbitscache);
- if (state == THRESHOLD_LOCKED_IN || state == THRESHOLD_STARTED) {
+ if (state == ThresholdState::LOCKED_IN || state == ThresholdState::STARTED) {
nVersion |= VersionBitsMask(params, static_cast<Consensus::DeploymentPos>(i));
}
}
@@ -1745,7 +1746,7 @@ static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consens
}
// Start enforcing BIP68 (sequence locks) and BIP112 (CHECKSEQUENCEVERIFY) using versionbits logic.
- if (VersionBitsState(pindex->pprev, consensusparams, Consensus::DEPLOYMENT_CSV, versionbitscache) == THRESHOLD_ACTIVE) {
+ if (VersionBitsState(pindex->pprev, consensusparams, Consensus::DEPLOYMENT_CSV, versionbitscache) == ThresholdState::ACTIVE) {
flags |= SCRIPT_VERIFY_CHECKSEQUENCEVERIFY;
}
@@ -1931,7 +1932,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
// Start enforcing BIP68 (sequence locks) and BIP112 (CHECKSEQUENCEVERIFY) using versionbits logic.
int nLockTimeFlags = 0;
- if (VersionBitsState(pindex->pprev, chainparams.GetConsensus(), Consensus::DEPLOYMENT_CSV, versionbitscache) == THRESHOLD_ACTIVE) {
+ if (VersionBitsState(pindex->pprev, chainparams.GetConsensus(), Consensus::DEPLOYMENT_CSV, versionbitscache) == ThresholdState::ACTIVE) {
nLockTimeFlags |= LOCKTIME_VERIFY_SEQUENCE;
}
@@ -2101,19 +2102,19 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState &
int64_t cacheSize = pcoinsTip->DynamicMemoryUsage();
int64_t nTotalSpace = nCoinCacheUsage + std::max<int64_t>(nMempoolSizeMax - nMempoolUsage, 0);
// The cache is large and we're within 10% and 10 MiB of the limit, but we have time now (not in the middle of a block processing).
- bool fCacheLarge = mode == FLUSH_STATE_PERIODIC && cacheSize > std::max((9 * nTotalSpace) / 10, nTotalSpace - MAX_BLOCK_COINSDB_USAGE * 1024 * 1024);
+ bool fCacheLarge = mode == FlushStateMode::PERIODIC && cacheSize > std::max((9 * nTotalSpace) / 10, nTotalSpace - MAX_BLOCK_COINSDB_USAGE * 1024 * 1024);
// The cache is over the limit, we have to write now.
- bool fCacheCritical = mode == FLUSH_STATE_IF_NEEDED && cacheSize > nTotalSpace;
+ bool fCacheCritical = mode == FlushStateMode::IF_NEEDED && cacheSize > nTotalSpace;
// It's been a while since we wrote the block index to disk. Do this frequently, so we don't need to redownload after a crash.
- bool fPeriodicWrite = mode == FLUSH_STATE_PERIODIC && nNow > nLastWrite + (int64_t)DATABASE_WRITE_INTERVAL * 1000000;
+ bool fPeriodicWrite = mode == FlushStateMode::PERIODIC && nNow > nLastWrite + (int64_t)DATABASE_WRITE_INTERVAL * 1000000;
// It's been very long since we flushed the cache. Do this infrequently, to optimize cache usage.
- bool fPeriodicFlush = mode == FLUSH_STATE_PERIODIC && nNow > nLastFlush + (int64_t)DATABASE_FLUSH_INTERVAL * 1000000;
+ bool fPeriodicFlush = mode == FlushStateMode::PERIODIC && nNow > nLastFlush + (int64_t)DATABASE_FLUSH_INTERVAL * 1000000;
// Combine all conditions that result in a full cache flush.
- fDoFullFlush = (mode == FLUSH_STATE_ALWAYS) || fCacheLarge || fCacheCritical || fPeriodicFlush || fFlushForPrune;
+ fDoFullFlush = (mode == FlushStateMode::ALWAYS) || fCacheLarge || fCacheCritical || fPeriodicFlush || fFlushForPrune;
// Write blocks and block index to disk.
if (fDoFullFlush || fPeriodicWrite) {
// Depend on nMinDiskSpace to ensure we can write block index
- if (!CheckDiskSpace(0))
+ if (!CheckDiskSpace(0, true))
return state.Error("out of disk space");
// First make sure all block and undo data is flushed to disk.
FlushBlockFile();
@@ -2155,7 +2156,7 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState &
nLastFlush = nNow;
}
}
- if (fDoFullFlush || ((mode == FLUSH_STATE_ALWAYS || mode == FLUSH_STATE_PERIODIC) && nNow > nLastSetChain + (int64_t)DATABASE_WRITE_INTERVAL * 1000000)) {
+ if (fDoFullFlush || ((mode == FlushStateMode::ALWAYS || mode == FlushStateMode::PERIODIC) && nNow > nLastSetChain + (int64_t)DATABASE_WRITE_INTERVAL * 1000000)) {
// Update best block in wallet (so we can detect restored wallets).
GetMainSignals().SetBestChain(chainActive.GetLocator());
nLastSetChain = nNow;
@@ -2169,14 +2170,14 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState &
void FlushStateToDisk() {
CValidationState state;
const CChainParams& chainparams = Params();
- FlushStateToDisk(chainparams, state, FLUSH_STATE_ALWAYS);
+ FlushStateToDisk(chainparams, state, FlushStateMode::ALWAYS);
}
void PruneAndFlush() {
CValidationState state;
fCheckForPruning = true;
const CChainParams& chainparams = Params();
- FlushStateToDisk(chainparams, state, FLUSH_STATE_NONE);
+ FlushStateToDisk(chainparams, state, FlushStateMode::NONE);
}
static void DoWarning(const std::string& strWarning)
@@ -2204,9 +2205,9 @@ void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainPar
for (int bit = 0; bit < VERSIONBITS_NUM_BITS; bit++) {
WarningBitsConditionChecker checker(bit);
ThresholdState state = checker.GetStateFor(pindex, chainParams.GetConsensus(), warningcache[bit]);
- if (state == THRESHOLD_ACTIVE || state == THRESHOLD_LOCKED_IN) {
+ if (state == ThresholdState::ACTIVE || state == ThresholdState::LOCKED_IN) {
const std::string strWarning = strprintf(_("Warning: unknown new rules activated (versionbit %i)"), bit);
- if (state == THRESHOLD_ACTIVE) {
+ if (state == ThresholdState::ACTIVE) {
DoWarning(strWarning);
} else {
warningMessages.push_back(strWarning);
@@ -2272,7 +2273,7 @@ bool CChainState::DisconnectTip(CValidationState& state, const CChainParams& cha
}
LogPrint(BCLog::BENCH, "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * MILLI);
// Write the chain state to disk, if necessary.
- if (!FlushStateToDisk(chainparams, state, FLUSH_STATE_IF_NEEDED))
+ if (!FlushStateToDisk(chainparams, state, FlushStateMode::IF_NEEDED))
return false;
if (disconnectpool) {
@@ -2410,7 +2411,7 @@ bool CChainState::ConnectTip(CValidationState& state, const CChainParams& chainp
int64_t nTime4 = GetTimeMicros(); nTimeFlush += nTime4 - nTime3;
LogPrint(BCLog::BENCH, " - Flush: %.2fms [%.2fs (%.2fms/blk)]\n", (nTime4 - nTime3) * MILLI, nTimeFlush * MICRO, nTimeFlush * MILLI / nBlocksTotal);
// Write the chain state to disk, if necessary.
- if (!FlushStateToDisk(chainparams, state, FLUSH_STATE_IF_NEEDED))
+ if (!FlushStateToDisk(chainparams, state, FlushStateMode::IF_NEEDED))
return false;
int64_t nTime5 = GetTimeMicros(); nTimeChainState += nTime5 - nTime4;
LogPrint(BCLog::BENCH, " - Writing chainstate: %.2fms [%.2fs (%.2fms/blk)]\n", (nTime5 - nTime4) * MILLI, nTimeChainState * MICRO, nTimeChainState * MILLI / nBlocksTotal);
@@ -2687,7 +2688,7 @@ bool CChainState::ActivateBestChain(CValidationState &state, const CChainParams&
CheckBlockIndex(chainparams.GetConsensus());
// Write changes periodically to disk, after relay.
- if (!FlushStateToDisk(chainparams, state, FLUSH_STATE_PERIODIC)) {
+ if (!FlushStateToDisk(chainparams, state, FlushStateMode::PERIODIC)) {
return false;
}
@@ -2958,7 +2959,7 @@ static bool FindBlockPos(CDiskBlockPos &pos, unsigned int nAddSize, unsigned int
if (nNewChunks > nOldChunks) {
if (fPruneMode)
fCheckForPruning = true;
- if (CheckDiskSpace(nNewChunks * BLOCKFILE_CHUNK_SIZE - pos.nPos)) {
+ if (CheckDiskSpace(nNewChunks * BLOCKFILE_CHUNK_SIZE - pos.nPos, true)) {
FILE *file = OpenBlockFile(pos);
if (file) {
LogPrintf("Pre-allocating up to position 0x%x in blk%05u.dat\n", nNewChunks * BLOCKFILE_CHUNK_SIZE, pos.nFile);
@@ -2991,7 +2992,7 @@ static bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos,
if (nNewChunks > nOldChunks) {
if (fPruneMode)
fCheckForPruning = true;
- if (CheckDiskSpace(nNewChunks * UNDOFILE_CHUNK_SIZE - pos.nPos)) {
+ if (CheckDiskSpace(nNewChunks * UNDOFILE_CHUNK_SIZE - pos.nPos, true)) {
FILE *file = OpenUndoFile(pos);
if (file) {
LogPrintf("Pre-allocating up to position 0x%x in rev%05u.dat\n", nNewChunks * UNDOFILE_CHUNK_SIZE, pos.nFile);
@@ -3081,7 +3082,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P
bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params)
{
LOCK(cs_main);
- return (VersionBitsState(pindexPrev, params, Consensus::DEPLOYMENT_SEGWIT, versionbitscache) == THRESHOLD_ACTIVE);
+ return (VersionBitsState(pindexPrev, params, Consensus::DEPLOYMENT_SEGWIT, versionbitscache) == ThresholdState::ACTIVE);
}
// Compute at which vout of the block's coinbase transaction the witness
@@ -3200,7 +3201,7 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c
// Start enforcing BIP113 (Median Time Past) using versionbits logic.
int nLockTimeFlags = 0;
- if (VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_CSV, versionbitscache) == THRESHOLD_ACTIVE) {
+ if (VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_CSV, versionbitscache) == ThresholdState::ACTIVE) {
nLockTimeFlags |= LOCKTIME_MEDIAN_TIME_PAST;
}
@@ -3228,13 +3229,13 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c
// Validation for witness commitments.
// * We compute the witness hash (which is the hash including witnesses) of all the block's transactions, except the
// coinbase (where 0x0000....0000 is used instead).
- // * The coinbase scriptWitness is a stack of a single 32-byte vector, containing a witness nonce (unconstrained).
+ // * The coinbase scriptWitness is a stack of a single 32-byte vector, containing a witness reserved value (unconstrained).
// * We build a merkle tree with all those witness hashes as leaves (similar to the hashMerkleRoot in the block header).
// * There must be at least one output whose scriptPubKey is a single 36-byte push, the first 4 bytes of which are
- // {0xaa, 0x21, 0xa9, 0xed}, and the following 32 bytes are SHA256^2(witness root, witness nonce). In case there are
+ // {0xaa, 0x21, 0xa9, 0xed}, and the following 32 bytes are SHA256^2(witness root, witness reserved value). In case there are
// multiple, the last one is used.
bool fHaveWitness = false;
- if (VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT, versionbitscache) == THRESHOLD_ACTIVE) {
+ if (VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT, versionbitscache) == ThresholdState::ACTIVE) {
int commitpos = GetWitnessCommitmentIndex(block);
if (commitpos != -1) {
bool malleated = false;
@@ -3243,7 +3244,7 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c
// already does not permit it, it is impossible to trigger in the
// witness tree.
if (block.vtx[0]->vin[0].scriptWitness.stack.size() != 1 || block.vtx[0]->vin[0].scriptWitness.stack[0].size() != 32) {
- return state.DoS(100, false, REJECT_INVALID, "bad-witness-nonce-size", true, strprintf("%s : invalid witness nonce size", __func__));
+ return state.DoS(100, false, REJECT_INVALID, "bad-witness-nonce-size", true, strprintf("%s : invalid witness reserved value size", __func__));
}
CHash256().Write(hashWitness.begin(), 32).Write(&block.vtx[0]->vin[0].scriptWitness.stack[0][0], 32).Finalize(hashWitness.begin());
if (memcmp(hashWitness.begin(), &block.vtx[0]->vout[commitpos].scriptPubKey[6], 32)) {
@@ -3262,7 +3263,7 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c
}
}
- // After the coinbase witness nonce and commitment are verified,
+ // After the coinbase witness reserved value and commitment are verified,
// we can check if the block weight passes (before we've checked the
// coinbase witness, it would be possible for the weight to be too
// large by filling up the coinbase witness, which doesn't change
@@ -3448,7 +3449,7 @@ bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CVali
}
if (fCheckForPruning)
- FlushStateToDisk(chainparams, state, FLUSH_STATE_NONE); // we just allocated more disk space for block files
+ FlushStateToDisk(chainparams, state, FlushStateMode::NONE); // we just allocated more disk space for block files
CheckBlockIndex(chainparams.GetConsensus());
@@ -3601,7 +3602,7 @@ void PruneBlockFilesManual(int nManualPruneHeight)
{
CValidationState state;
const CChainParams& chainparams = Params();
- FlushStateToDisk(chainparams, state, FLUSH_STATE_NONE, nManualPruneHeight);
+ FlushStateToDisk(chainparams, state, FlushStateMode::NONE, nManualPruneHeight);
}
/**
@@ -3666,9 +3667,9 @@ static void FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfte
nLastBlockWeCanPrune, count);
}
-bool CheckDiskSpace(uint64_t nAdditionalBytes)
+bool CheckDiskSpace(uint64_t nAdditionalBytes, bool blocks_dir)
{
- uint64_t nFreeBytesAvailable = fs::space(GetDataDir()).available;
+ uint64_t nFreeBytesAvailable = fs::space(blocks_dir ? GetBlocksDir() : GetDataDir()).available;
// Check for nMinDiskSpace bytes (currently 50MB)
if (nFreeBytesAvailable < nMinDiskSpace + nAdditionalBytes)
@@ -3711,7 +3712,7 @@ static FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly) {
fs::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix)
{
- return GetDataDir() / "blocks" / strprintf("%s%05u.dat", prefix, pos.nFile);
+ return GetBlocksDir() / strprintf("%s%05u.dat", prefix, pos.nFile);
}
CBlockIndex * CChainState::InsertBlockIndex(const uint256& hash)
@@ -4099,7 +4100,7 @@ bool CChainState::RewindBlockIndex(const CChainParams& params)
return error("RewindBlockIndex: unable to disconnect block at height %i", pindex->nHeight);
}
// Occasionally flush state to disk.
- if (!FlushStateToDisk(params, state, FLUSH_STATE_PERIODIC))
+ if (!FlushStateToDisk(params, state, FlushStateMode::PERIODIC))
return false;
}
@@ -4165,7 +4166,7 @@ bool RewindBlockIndex(const CChainParams& params) {
// and skip it here, we're about to -reindex-chainstate anyway, so
// it'll get called a bunch real soon.
CValidationState state;
- if (!FlushStateToDisk(params, state, FLUSH_STATE_ALWAYS)) {
+ if (!FlushStateToDisk(params, state, FlushStateMode::ALWAYS)) {
return false;
}
}
@@ -4288,7 +4289,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB
unsigned char buf[CMessageHeader::MESSAGE_START_SIZE];
blkdat.FindByte(chainparams.MessageStart()[0]);
nRewind = blkdat.GetPos()+1;
- blkdat >> FLATDATA(buf);
+ blkdat >> buf;
if (memcmp(buf, chainparams.MessageStart(), CMessageHeader::MESSAGE_START_SIZE))
continue;
// read size
diff --git a/src/validation.h b/src/validation.h
index a658d8c5d3..95c31bf0fc 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -158,6 +158,7 @@ extern CScript COINBASE_FLAGS;
extern CCriticalSection cs_main;
extern CBlockPolicyEstimator feeEstimator;
extern CTxMemPool mempool;
+extern std::atomic_bool g_is_mempool_loaded;
typedef std::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap;
extern BlockMap& mapBlockIndex;
extern uint64_t nLastBlockTx;
@@ -254,7 +255,7 @@ bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<cons
bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& block, CValidationState& state, const CChainParams& chainparams, const CBlockIndex** ppindex=nullptr, CBlockHeader *first_invalid=nullptr);
/** Check whether enough disk space is available for an incoming block */
-bool CheckDiskSpace(uint64_t nAdditionalBytes = 0);
+bool CheckDiskSpace(uint64_t nAdditionalBytes = 0, bool blocks_dir = false);
/** Open a block file (blk?????.dat) */
FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly = false);
/** Translation to a filesystem path */
@@ -411,7 +412,7 @@ bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& pa
/** When there are blocks in the active chain with missing data, rewind the chainstate and remove them from the block index */
bool RewindBlockIndex(const CChainParams& params);
-/** Update uncommitted block structures (currently: only the witness nonce). This is safe for submitted blocks. */
+/** Update uncommitted block structures (currently: only the witness reserved value). This is safe for submitted blocks. */
void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams);
/** Produce the necessary coinbase commitment for a block (modifies the hash, don't call for mined blocks). */
diff --git a/src/versionbits.cpp b/src/versionbits.cpp
index d2ee49db20..e3ec078173 100644
--- a/src/versionbits.cpp
+++ b/src/versionbits.cpp
@@ -29,7 +29,7 @@ ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex*
// Check if this deployment is always active.
if (nTimeStart == Consensus::BIP9Deployment::ALWAYS_ACTIVE) {
- return THRESHOLD_ACTIVE;
+ return ThresholdState::ACTIVE;
}
// A block's state is always the same as that of the first of its period, so it is computed based on a pindexPrev whose height equals a multiple of nPeriod - 1.
@@ -42,12 +42,12 @@ ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex*
while (cache.count(pindexPrev) == 0) {
if (pindexPrev == nullptr) {
// The genesis block is by definition defined.
- cache[pindexPrev] = THRESHOLD_DEFINED;
+ cache[pindexPrev] = ThresholdState::DEFINED;
break;
}
if (pindexPrev->GetMedianTimePast() < nTimeStart) {
// Optimization: don't recompute down further, as we know every earlier block will be before the start time
- cache[pindexPrev] = THRESHOLD_DEFINED;
+ cache[pindexPrev] = ThresholdState::DEFINED;
break;
}
vToCompute.push_back(pindexPrev);
@@ -65,17 +65,17 @@ ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex*
vToCompute.pop_back();
switch (state) {
- case THRESHOLD_DEFINED: {
+ case ThresholdState::DEFINED: {
if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
- stateNext = THRESHOLD_FAILED;
+ stateNext = ThresholdState::FAILED;
} else if (pindexPrev->GetMedianTimePast() >= nTimeStart) {
- stateNext = THRESHOLD_STARTED;
+ stateNext = ThresholdState::STARTED;
}
break;
}
- case THRESHOLD_STARTED: {
+ case ThresholdState::STARTED: {
if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
- stateNext = THRESHOLD_FAILED;
+ stateNext = ThresholdState::FAILED;
break;
}
// We need to count
@@ -88,17 +88,17 @@ ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex*
pindexCount = pindexCount->pprev;
}
if (count >= nThreshold) {
- stateNext = THRESHOLD_LOCKED_IN;
+ stateNext = ThresholdState::LOCKED_IN;
}
break;
}
- case THRESHOLD_LOCKED_IN: {
+ case ThresholdState::LOCKED_IN: {
// Always progresses into ACTIVE.
- stateNext = THRESHOLD_ACTIVE;
+ stateNext = ThresholdState::ACTIVE;
break;
}
- case THRESHOLD_FAILED:
- case THRESHOLD_ACTIVE: {
+ case ThresholdState::FAILED:
+ case ThresholdState::ACTIVE: {
// Nothing happens, these are terminal states.
break;
}
@@ -149,7 +149,7 @@ int AbstractThresholdConditionChecker::GetStateSinceHeightFor(const CBlockIndex*
const ThresholdState initialState = GetStateFor(pindexPrev, params, cache);
// BIP 9 about state DEFINED: "The genesis block is by definition in this state for each deployment."
- if (initialState == THRESHOLD_DEFINED) {
+ if (initialState == ThresholdState::DEFINED) {
return 0;
}
diff --git a/src/versionbits.h b/src/versionbits.h
index 1600dc8c93..8962a65057 100644
--- a/src/versionbits.h
+++ b/src/versionbits.h
@@ -2,8 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_CONSENSUS_VERSIONBITS
-#define BITCOIN_CONSENSUS_VERSIONBITS
+#ifndef BITCOIN_VERSIONBITS_H
+#define BITCOIN_VERSIONBITS_H
#include <chain.h>
#include <map>
@@ -17,12 +17,12 @@ static const int32_t VERSIONBITS_TOP_MASK = 0xE0000000UL;
/** Total bits available for versionbits */
static const int32_t VERSIONBITS_NUM_BITS = 29;
-enum ThresholdState {
- THRESHOLD_DEFINED,
- THRESHOLD_STARTED,
- THRESHOLD_LOCKED_IN,
- THRESHOLD_ACTIVE,
- THRESHOLD_FAILED,
+enum class ThresholdState {
+ DEFINED,
+ STARTED,
+ LOCKED_IN,
+ ACTIVE,
+ FAILED,
};
// A map that gives the state for blocks whose height is a multiple of Period().
@@ -77,4 +77,4 @@ BIP9Stats VersionBitsStatistics(const CBlockIndex* pindexPrev, const Consensus::
int VersionBitsStateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache);
uint32_t VersionBitsMask(const Consensus::Params& params, Consensus::DeploymentPos pos);
-#endif
+#endif // BITCOIN_VERSIONBITS_H
diff --git a/src/wallet/coinselection.h b/src/wallet/coinselection.h
index 4d1a43bc17..2b185879c6 100644
--- a/src/wallet/coinselection.h
+++ b/src/wallet/coinselection.h
@@ -2,8 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_COINSELECTION_H
-#define BITCOIN_COINSELECTION_H
+#ifndef BITCOIN_WALLET_COINSELECTION_H
+#define BITCOIN_WALLET_COINSELECTION_H
#include <amount.h>
#include <primitives/transaction.h>
@@ -51,4 +51,4 @@ bool SelectCoinsBnB(std::vector<CInputCoin>& utxo_pool, const CAmount& target_va
// Original coin selection algorithm as a fallback
bool KnapsackSolver(const CAmount& nTargetValue, std::vector<CInputCoin>& vCoins, std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet);
-#endif // BITCOIN_COINSELECTION_H
+#endif // BITCOIN_WALLET_COINSELECTION_H
diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h
index f3ae7144b4..fdeb4cfee0 100644
--- a/src/wallet/crypter.h
+++ b/src/wallet/crypter.h
@@ -67,7 +67,7 @@ public:
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial;
-namespace wallet_crypto
+namespace crypto_tests
{
class TestCrypter;
}
@@ -75,7 +75,7 @@ namespace wallet_crypto
/** Encryption/decryption context with key information */
class CCrypter
{
-friend class wallet_crypto::TestCrypter; // for test access to chKey/chIV
+friend class crypto_tests::TestCrypter; // for test access to chKey/chIV
private:
std::vector<unsigned char, secure_allocator<unsigned char>> vchKey;
std::vector<unsigned char, secure_allocator<unsigned char>> vchIV;
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
index ebe7b48da0..553cae4d02 100644
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -235,13 +235,13 @@ CDBEnv::VerifyResult CDBEnv::Verify(const std::string& strFile, recoverFunc_type
Db db(dbenv.get(), 0);
int result = db.verify(strFile.c_str(), nullptr, nullptr, 0);
if (result == 0)
- return VERIFY_OK;
+ return VerifyResult::VERIFY_OK;
else if (recoverFunc == nullptr)
- return RECOVER_FAIL;
+ return VerifyResult::RECOVER_FAIL;
// Try to recover:
bool fRecovered = (*recoverFunc)(fs::path(strPath) / strFile, out_backup_filename);
- return (fRecovered ? RECOVER_OK : RECOVER_FAIL);
+ return (fRecovered ? VerifyResult::RECOVER_OK : VerifyResult::RECOVER_FAIL);
}
bool CDB::Recover(const fs::path& file_path, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& newFilename)
@@ -347,7 +347,7 @@ bool CDB::VerifyDatabaseFile(const fs::path& file_path, std::string& warningStr,
{
std::string backup_filename;
CDBEnv::VerifyResult r = env->Verify(walletFile, recoverFunc, backup_filename);
- if (r == CDBEnv::RECOVER_OK)
+ if (r == CDBEnv::VerifyResult::RECOVER_OK)
{
warningStr = strprintf(_("Warning: Wallet file corrupt, data salvaged!"
" Original %s saved as %s in %s; if"
@@ -355,7 +355,7 @@ bool CDB::VerifyDatabaseFile(const fs::path& file_path, std::string& warningStr,
" restore from a backup."),
walletFile, backup_filename, walletDir);
}
- if (r == CDBEnv::RECOVER_FAIL)
+ if (r == CDBEnv::VerifyResult::RECOVER_FAIL)
{
errorStr = strprintf(_("%s corrupt, salvage failed"), walletFile);
return false;
diff --git a/src/wallet/db.h b/src/wallet/db.h
index b1ce451534..65bb8cc253 100644
--- a/src/wallet/db.h
+++ b/src/wallet/db.h
@@ -53,7 +53,7 @@ public:
* This must be called BEFORE strFile is opened.
* Returns true if strFile is OK.
*/
- enum VerifyResult { VERIFY_OK,
+ enum class VerifyResult { VERIFY_OK,
RECOVER_OK,
RECOVER_FAIL };
typedef bool (*recoverFunc_type)(const fs::path& file_path, std::string& out_backup_filename);
diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp
index 61481e01b6..3d7bb674f0 100644
--- a/src/wallet/init.cpp
+++ b/src/wallet/init.cpp
@@ -14,7 +14,7 @@
#include <wallet/wallet.h>
#include <wallet/walletutil.h>
-std::string GetWalletHelpString(bool showDebug)
+std::string WalletInit::GetHelpString(bool showDebug)
{
std::string strUsage = HelpMessageGroup(_("Wallet options:"));
strUsage += HelpMessageOpt("-addresstype", strprintf("What type of addresses to use (\"legacy\", \"p2sh-segwit\", or \"bech32\", default: \"%s\")", FormatOutputType(DEFAULT_ADDRESS_TYPE)));
@@ -56,7 +56,7 @@ std::string GetWalletHelpString(bool showDebug)
return strUsage;
}
-bool WalletParameterInteraction()
+bool WalletInit::ParameterInteraction()
{
if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
for (const std::string& wallet : gArgs.GetArgs("-wallet")) {
@@ -184,7 +184,7 @@ bool WalletParameterInteraction()
return true;
}
-void RegisterWalletRPC(CRPCTable &t)
+void WalletInit::RegisterRPC(CRPCTable &t)
{
if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
return;
@@ -193,7 +193,7 @@ void RegisterWalletRPC(CRPCTable &t)
RegisterWalletRPCCommands(t);
}
-bool VerifyWallets()
+bool WalletInit::Verify()
{
if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
return true;
@@ -268,7 +268,7 @@ bool VerifyWallets()
return true;
}
-bool OpenWallets()
+bool WalletInit::Open()
{
if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
LogPrintf("Wallet disabled!\n");
@@ -286,25 +286,29 @@ bool OpenWallets()
return true;
}
-void StartWallets(CScheduler& scheduler) {
+void WalletInit::Start(CScheduler& scheduler)
+{
for (CWalletRef pwallet : vpwallets) {
pwallet->postInitProcess(scheduler);
}
}
-void FlushWallets() {
+void WalletInit::Flush()
+{
for (CWalletRef pwallet : vpwallets) {
pwallet->Flush(false);
}
}
-void StopWallets() {
+void WalletInit::Stop()
+{
for (CWalletRef pwallet : vpwallets) {
pwallet->Flush(true);
}
}
-void CloseWallets() {
+void WalletInit::Close()
+{
for (CWalletRef pwallet : vpwallets) {
delete pwallet;
}
diff --git a/src/wallet/init.h b/src/wallet/init.h
index 0b3ee2dda2..f8be90d3e3 100644
--- a/src/wallet/init.h
+++ b/src/wallet/init.h
@@ -6,38 +6,43 @@
#ifndef BITCOIN_WALLET_INIT_H
#define BITCOIN_WALLET_INIT_H
+#include <walletinitinterface.h>
#include <string>
class CRPCTable;
class CScheduler;
-//! Return the wallets help message.
-std::string GetWalletHelpString(bool showDebug);
+class WalletInit : public WalletInitInterface {
+public:
-//! Wallets parameter interaction
-bool WalletParameterInteraction();
+ //! Return the wallets help message.
+ std::string GetHelpString(bool showDebug) override;
-//! Register wallet RPCs.
-void RegisterWalletRPC(CRPCTable &tableRPC);
+ //! Wallets parameter interaction
+ bool ParameterInteraction() override;
-//! Responsible for reading and validating the -wallet arguments and verifying the wallet database.
-// This function will perform salvage on the wallet if requested, as long as only one wallet is
-// being loaded (WalletParameterInteraction forbids -salvagewallet, -zapwallettxes or -upgradewallet with multiwallet).
-bool VerifyWallets();
+ //! Register wallet RPCs.
+ void RegisterRPC(CRPCTable &tableRPC) override;
-//! Load wallet databases.
-bool OpenWallets();
+ //! Responsible for reading and validating the -wallet arguments and verifying the wallet database.
+ // This function will perform salvage on the wallet if requested, as long as only one wallet is
+ // being loaded (WalletParameterInteraction forbids -salvagewallet, -zapwallettxes or -upgradewallet with multiwallet).
+ bool Verify() override;
-//! Complete startup of wallets.
-void StartWallets(CScheduler& scheduler);
+ //! Load wallet databases.
+ bool Open() override;
-//! Flush all wallets in preparation for shutdown.
-void FlushWallets();
+ //! Complete startup of wallets.
+ void Start(CScheduler& scheduler) override;
-//! Stop all wallets. Wallets will be flushed first.
-void StopWallets();
+ //! Flush all wallets in preparation for shutdown.
+ void Flush() override;
-//! Close all wallets.
-void CloseWallets();
+ //! Stop all wallets. Wallets will be flushed first.
+ void Stop() override;
+
+ //! Close all wallets.
+ void Close() override;
+};
#endif // BITCOIN_WALLET_INIT_H
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index 1721bc6df6..28b6153ce1 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -406,7 +406,7 @@ UniValue removeprunedfunds(const JSONRPCRequest& request)
vHash.push_back(hash);
std::vector<uint256> vHashOut;
- if (pwallet->ZapSelectTx(vHash, vHashOut) != DB_LOAD_OK) {
+ if (pwallet->ZapSelectTx(vHash, vHashOut) != DBErrors::LOAD_OK) {
throw JSONRPCError(RPC_WALLET_ERROR, "Could not properly delete the transaction.");
}
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 365dedfceb..c34b166a41 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -113,9 +113,9 @@ void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
if (confirms <= 0) {
LOCK(mempool.cs);
RBFTransactionState rbfState = IsRBFOptIn(*wtx.tx, mempool);
- if (rbfState == RBF_TRANSACTIONSTATE_UNKNOWN)
+ if (rbfState == RBFTransactionState::UNKNOWN)
rbfStatus = "unknown";
- else if (rbfState == RBF_TRANSACTIONSTATE_REPLACEABLE_BIP125)
+ else if (rbfState == RBFTransactionState::REPLACEABLE_BIP125)
rbfStatus = "yes";
}
entry.pushKV("bip125-replaceable", rbfStatus);
diff --git a/src/wallet/test/accounting_tests.cpp b/src/wallet/test/accounting_tests.cpp
index aae328d81f..cc6e491f53 100644
--- a/src/wallet/test/accounting_tests.cpp
+++ b/src/wallet/test/accounting_tests.cpp
@@ -18,7 +18,7 @@ GetResults(CWallet& wallet, std::map<CAmount, CAccountingEntry>& results)
std::list<CAccountingEntry> aes;
results.clear();
- BOOST_CHECK(wallet.ReorderTransactions() == DB_LOAD_OK);
+ BOOST_CHECK(wallet.ReorderTransactions() == DBErrors::LOAD_OK);
wallet.ListAccountCreditDebit("", aes);
for (CAccountingEntry& ae : aes)
{
diff --git a/src/wallet/test/coinselector_tests.cpp b/src/wallet/test/coinselector_tests.cpp
index 6c36e2e965..184a8a3f1f 100644
--- a/src/wallet/test/coinselector_tests.cpp
+++ b/src/wallet/test/coinselector_tests.cpp
@@ -14,7 +14,7 @@
#include <boost/test/unit_test.hpp>
#include <random>
-BOOST_FIXTURE_TEST_SUITE(coin_selection_tests, WalletTestingSetup)
+BOOST_FIXTURE_TEST_SUITE(coinselector_tests, WalletTestingSetup)
// how many times to run all the tests to have a chance to catch errors that only show up with particular random shuffles
#define RUN_TESTS 100
diff --git a/src/wallet/test/crypto_tests.cpp b/src/wallet/test/crypto_tests.cpp
index 89b2c4e796..d8c0cdf0f9 100644
--- a/src/wallet/test/crypto_tests.cpp
+++ b/src/wallet/test/crypto_tests.cpp
@@ -10,7 +10,7 @@
#include <boost/test/unit_test.hpp>
-BOOST_FIXTURE_TEST_SUITE(wallet_crypto, BasicTestingSetup)
+BOOST_FIXTURE_TEST_SUITE(crypto_tests, BasicTestingSetup)
class TestCrypter
{
diff --git a/src/wallet/test/wallet_test_fixture.h b/src/wallet/test/wallet_test_fixture.h
index 663836a955..23575391c4 100644
--- a/src/wallet/test/wallet_test_fixture.h
+++ b/src/wallet/test/wallet_test_fixture.h
@@ -2,8 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_WALLET_TEST_FIXTURE_H
-#define BITCOIN_WALLET_TEST_FIXTURE_H
+#ifndef BITCOIN_WALLET_TEST_WALLET_TEST_FIXTURE_H
+#define BITCOIN_WALLET_TEST_WALLET_TEST_FIXTURE_H
#include <test/test_bitcoin.h>
@@ -18,5 +18,4 @@ struct WalletTestingSetup: public TestingSetup {
CWallet m_wallet;
};
-#endif
-
+#endif // BITCOIN_WALLET_TEST_WALLET_TEST_FIXTURE_H
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index b37a411ef4..c9843599d6 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -727,11 +727,11 @@ DBErrors CWallet::ReorderTransactions()
if (pwtx)
{
if (!walletdb.WriteTx(*pwtx))
- return DB_LOAD_FAIL;
+ return DBErrors::LOAD_FAIL;
}
else
if (!walletdb.WriteAccountingEntry(pacentry->nEntryNo, *pacentry))
- return DB_LOAD_FAIL;
+ return DBErrors::LOAD_FAIL;
}
else
{
@@ -751,16 +751,16 @@ DBErrors CWallet::ReorderTransactions()
if (pwtx)
{
if (!walletdb.WriteTx(*pwtx))
- return DB_LOAD_FAIL;
+ return DBErrors::LOAD_FAIL;
}
else
if (!walletdb.WriteAccountingEntry(pacentry->nEntryNo, *pacentry))
- return DB_LOAD_FAIL;
+ return DBErrors::LOAD_FAIL;
}
}
walletdb.WriteOrderPosNext(nOrderPosNext);
- return DB_LOAD_OK;
+ return DBErrors::LOAD_OK;
}
int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb)
@@ -2890,20 +2890,11 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
nChangePosInOut = -1;
}
- // Fill vin
+ // Dummy fill vin for maximum size estimation
//
- // Note how the sequence number is set to non-maxint so that
- // the nLockTime set above actually works.
- //
- // BIP125 defines opt-in RBF as any nSequence < maxint-1, so
- // we use the highest possible value in that range (maxint-2)
- // to avoid conflicting with other possible uses of nSequence,
- // and in the spirit of "smallest possible change from prior
- // behavior."
- const uint32_t nSequence = coin_control.signalRbf ? MAX_BIP125_RBF_SEQUENCE : (CTxIn::SEQUENCE_FINAL - 1);
- for (const auto& coin : setCoins)
- txNew.vin.push_back(CTxIn(coin.outpoint,CScript(),
- nSequence));
+ for (const auto& coin : setCoins) {
+ txNew.vin.push_back(CTxIn(coin.outpoint,CScript()));
+ }
nBytes = CalculateMaximumSignedTxSize(txNew, this);
if (nBytes < 0) {
@@ -2993,11 +2984,29 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
if (nChangePosInOut == -1) reservekey.ReturnKey(); // Return any reserved key if we don't have change
+ // Shuffle selected coins and fill in final vin
+ txNew.vin.clear();
+ std::vector<CInputCoin> selected_coins(setCoins.begin(), setCoins.end());
+ std::shuffle(selected_coins.begin(), selected_coins.end(), FastRandomContext());
+
+ // Note how the sequence number is set to non-maxint so that
+ // the nLockTime set above actually works.
+ //
+ // BIP125 defines opt-in RBF as any nSequence < maxint-1, so
+ // we use the highest possible value in that range (maxint-2)
+ // to avoid conflicting with other possible uses of nSequence,
+ // and in the spirit of "smallest possible change from prior
+ // behavior."
+ const uint32_t nSequence = coin_control.signalRbf ? MAX_BIP125_RBF_SEQUENCE : (CTxIn::SEQUENCE_FINAL - 1);
+ for (const auto& coin : selected_coins) {
+ txNew.vin.push_back(CTxIn(coin.outpoint, CScript(), nSequence));
+ }
+
if (sign)
{
CTransaction txNewConst(txNew);
int nIn = 0;
- for (const auto& coin : setCoins)
+ for (const auto& coin : selected_coins)
{
const CScript& scriptPubKey = coin.txout.scriptPubKey;
SignatureData sigdata;
@@ -3137,7 +3146,7 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
fFirstRunRet = false;
DBErrors nLoadWalletRet = CWalletDB(*dbw,"cr+").LoadWallet(this);
- if (nLoadWalletRet == DB_NEED_REWRITE)
+ if (nLoadWalletRet == DBErrors::NEED_REWRITE)
{
if (dbw->Rewrite("\x04pool"))
{
@@ -3153,12 +3162,12 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
// This wallet is in its first run if all of these are empty
fFirstRunRet = mapKeys.empty() && mapCryptedKeys.empty() && mapWatchKeys.empty() && setWatchOnly.empty() && mapScripts.empty();
- if (nLoadWalletRet != DB_LOAD_OK)
+ if (nLoadWalletRet != DBErrors::LOAD_OK)
return nLoadWalletRet;
uiInterface.LoadWallet(this);
- return DB_LOAD_OK;
+ return DBErrors::LOAD_OK;
}
DBErrors CWallet::ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut)
@@ -3168,7 +3177,7 @@ DBErrors CWallet::ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256
for (uint256 hash : vHashOut)
mapWallet.erase(hash);
- if (nZapSelectTxRet == DB_NEED_REWRITE)
+ if (nZapSelectTxRet == DBErrors::NEED_REWRITE)
{
if (dbw->Rewrite("\x04pool"))
{
@@ -3181,19 +3190,19 @@ DBErrors CWallet::ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256
}
}
- if (nZapSelectTxRet != DB_LOAD_OK)
+ if (nZapSelectTxRet != DBErrors::LOAD_OK)
return nZapSelectTxRet;
MarkDirty();
- return DB_LOAD_OK;
+ return DBErrors::LOAD_OK;
}
DBErrors CWallet::ZapWalletTx(std::vector<CWalletTx>& vWtx)
{
DBErrors nZapWalletTxRet = CWalletDB(*dbw,"cr+").ZapWalletTx(vWtx);
- if (nZapWalletTxRet == DB_NEED_REWRITE)
+ if (nZapWalletTxRet == DBErrors::NEED_REWRITE)
{
if (dbw->Rewrite("\x04pool"))
{
@@ -3207,10 +3216,10 @@ DBErrors CWallet::ZapWalletTx(std::vector<CWalletTx>& vWtx)
}
}
- if (nZapWalletTxRet != DB_LOAD_OK)
+ if (nZapWalletTxRet != DBErrors::LOAD_OK)
return nZapWalletTxRet;
- return DB_LOAD_OK;
+ return DBErrors::LOAD_OK;
}
@@ -3922,7 +3931,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path&
std::unique_ptr<CWallet> tempWallet = MakeUnique<CWallet>(name, CWalletDBWrapper::Create(path));
DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx);
- if (nZapWalletRet != DB_LOAD_OK) {
+ if (nZapWalletRet != DBErrors::LOAD_OK) {
InitError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile));
return nullptr;
}
@@ -3934,23 +3943,23 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path&
bool fFirstRun = true;
CWallet *walletInstance = new CWallet(name, CWalletDBWrapper::Create(path));
DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
- if (nLoadWalletRet != DB_LOAD_OK)
+ if (nLoadWalletRet != DBErrors::LOAD_OK)
{
- if (nLoadWalletRet == DB_CORRUPT) {
+ if (nLoadWalletRet == DBErrors::CORRUPT) {
InitError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile));
return nullptr;
}
- else if (nLoadWalletRet == DB_NONCRITICAL_ERROR)
+ else if (nLoadWalletRet == DBErrors::NONCRITICAL_ERROR)
{
InitWarning(strprintf(_("Error reading %s! All keys read correctly, but transaction data"
" or address book entries might be missing or incorrect."),
walletFile));
}
- else if (nLoadWalletRet == DB_TOO_NEW) {
+ else if (nLoadWalletRet == DBErrors::TOO_NEW) {
InitError(strprintf(_("Error loading %s: Wallet requires newer version of %s"), walletFile, _(PACKAGE_NAME)));
return nullptr;
}
- else if (nLoadWalletRet == DB_NEED_REWRITE)
+ else if (nLoadWalletRet == DBErrors::NEED_REWRITE)
{
InitError(strprintf(_("Wallet needed to be rewritten: restart %s to complete"), _(PACKAGE_NAME)));
return nullptr;
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index 7f5f3b84b2..77cdfe7dd0 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -522,7 +522,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
{
CWalletScanState wss;
bool fNoncriticalErrors = false;
- DBErrors result = DB_LOAD_OK;
+ DBErrors result = DBErrors::LOAD_OK;
LOCK(pwallet->cs_wallet);
try {
@@ -530,7 +530,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
if (batch.Read((std::string)"minversion", nMinVersion))
{
if (nMinVersion > CLIENT_VERSION)
- return DB_TOO_NEW;
+ return DBErrors::TOO_NEW;
pwallet->LoadMinVersion(nMinVersion);
}
@@ -539,7 +539,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
if (!pcursor)
{
LogPrintf("Error getting wallet database cursor\n");
- return DB_CORRUPT;
+ return DBErrors::CORRUPT;
}
while (true)
@@ -553,7 +553,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
else if (ret != 0)
{
LogPrintf("Error reading next record from wallet database\n");
- return DB_CORRUPT;
+ return DBErrors::CORRUPT;
}
// Try to be tolerant of single corrupt records:
@@ -563,7 +563,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
// losing keys is considered a catastrophic error, anything else
// we assume the user can live with:
if (IsKeyType(strType) || strType == "defaultkey")
- result = DB_CORRUPT;
+ result = DBErrors::CORRUPT;
else
{
// Leave other errors alone, if we try to fix them we might make things worse.
@@ -582,15 +582,15 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
throw;
}
catch (...) {
- result = DB_CORRUPT;
+ result = DBErrors::CORRUPT;
}
- if (fNoncriticalErrors && result == DB_LOAD_OK)
- result = DB_NONCRITICAL_ERROR;
+ if (fNoncriticalErrors && result == DBErrors::LOAD_OK)
+ result = DBErrors::NONCRITICAL_ERROR;
// Any wallet corruption at all: skip any rewriting or
// upgrading, we don't want to make it worse.
- if (result != DB_LOAD_OK)
+ if (result != DBErrors::LOAD_OK)
return result;
LogPrintf("nFileVersion = %d\n", wss.nFileVersion);
@@ -607,7 +607,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
// Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc:
if (wss.fIsEncrypted && (wss.nFileVersion == 40000 || wss.nFileVersion == 50000))
- return DB_NEED_REWRITE;
+ return DBErrors::NEED_REWRITE;
if (wss.nFileVersion < CLIENT_VERSION) // Update
WriteVersion(CLIENT_VERSION);
@@ -626,14 +626,14 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
DBErrors CWalletDB::FindWalletTx(std::vector<uint256>& vTxHash, std::vector<CWalletTx>& vWtx)
{
- DBErrors result = DB_LOAD_OK;
+ DBErrors result = DBErrors::LOAD_OK;
try {
int nMinVersion = 0;
if (batch.Read((std::string)"minversion", nMinVersion))
{
if (nMinVersion > CLIENT_VERSION)
- return DB_TOO_NEW;
+ return DBErrors::TOO_NEW;
}
// Get cursor
@@ -641,7 +641,7 @@ DBErrors CWalletDB::FindWalletTx(std::vector<uint256>& vTxHash, std::vector<CWal
if (!pcursor)
{
LogPrintf("Error getting wallet database cursor\n");
- return DB_CORRUPT;
+ return DBErrors::CORRUPT;
}
while (true)
@@ -655,7 +655,7 @@ DBErrors CWalletDB::FindWalletTx(std::vector<uint256>& vTxHash, std::vector<CWal
else if (ret != 0)
{
LogPrintf("Error reading next record from wallet database\n");
- return DB_CORRUPT;
+ return DBErrors::CORRUPT;
}
std::string strType;
@@ -677,7 +677,7 @@ DBErrors CWalletDB::FindWalletTx(std::vector<uint256>& vTxHash, std::vector<CWal
throw;
}
catch (...) {
- result = DB_CORRUPT;
+ result = DBErrors::CORRUPT;
}
return result;
@@ -689,7 +689,7 @@ DBErrors CWalletDB::ZapSelectTx(std::vector<uint256>& vTxHashIn, std::vector<uin
std::vector<uint256> vTxHash;
std::vector<CWalletTx> vWtx;
DBErrors err = FindWalletTx(vTxHash, vWtx);
- if (err != DB_LOAD_OK) {
+ if (err != DBErrors::LOAD_OK) {
return err;
}
@@ -716,9 +716,9 @@ DBErrors CWalletDB::ZapSelectTx(std::vector<uint256>& vTxHashIn, std::vector<uin
}
if (delerror) {
- return DB_CORRUPT;
+ return DBErrors::CORRUPT;
}
- return DB_LOAD_OK;
+ return DBErrors::LOAD_OK;
}
DBErrors CWalletDB::ZapWalletTx(std::vector<CWalletTx>& vWtx)
@@ -726,16 +726,16 @@ DBErrors CWalletDB::ZapWalletTx(std::vector<CWalletTx>& vWtx)
// build list of wallet TXs
std::vector<uint256> vTxHash;
DBErrors err = FindWalletTx(vTxHash, vWtx);
- if (err != DB_LOAD_OK)
+ if (err != DBErrors::LOAD_OK)
return err;
// erase each wallet TX
for (uint256& hash : vTxHash) {
if (!EraseTx(hash))
- return DB_CORRUPT;
+ return DBErrors::CORRUPT;
}
- return DB_LOAD_OK;
+ return DBErrors::LOAD_OK;
}
void MaybeCompactWalletDB()
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
index 7d754c7284..606b7dace7 100644
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -46,14 +46,14 @@ class uint160;
class uint256;
/** Error statuses for the wallet database */
-enum DBErrors
+enum class DBErrors
{
- DB_LOAD_OK,
- DB_CORRUPT,
- DB_NONCRITICAL_ERROR,
- DB_TOO_NEW,
- DB_LOAD_FAIL,
- DB_NEED_REWRITE
+ LOAD_OK,
+ CORRUPT,
+ NONCRITICAL_ERROR,
+ TOO_NEW,
+ LOAD_FAIL,
+ NEED_REWRITE
};
/* simple HD chain data model */
diff --git a/src/wallet/walletutil.h b/src/wallet/walletutil.h
index 50ff736402..f12acacd00 100644
--- a/src/wallet/walletutil.h
+++ b/src/wallet/walletutil.h
@@ -2,8 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_WALLET_UTIL_H
-#define BITCOIN_WALLET_UTIL_H
+#ifndef BITCOIN_WALLET_WALLETUTIL_H
+#define BITCOIN_WALLET_WALLETUTIL_H
#include <chainparamsbase.h>
#include <util.h>
@@ -11,4 +11,4 @@
//! Get the path of the wallet directory.
fs::path GetWalletDir();
-#endif // BITCOIN_WALLET_UTIL_H
+#endif // BITCOIN_WALLET_WALLETUTIL_H
diff --git a/src/walletinitinterface.h b/src/walletinitinterface.h
new file mode 100644
index 0000000000..a7b52685dd
--- /dev/null
+++ b/src/walletinitinterface.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2017 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_WALLETINITINTERFACE_H
+#define BITCOIN_WALLETINITINTERFACE_H
+
+#include <string>
+
+class CScheduler;
+class CRPCTable;
+
+class WalletInitInterface {
+public:
+ /** Get wallet help string */
+ virtual std::string GetHelpString(bool showDebug) = 0;
+ /** Check wallet parameter interaction */
+ virtual bool ParameterInteraction() = 0;
+ /** Register wallet RPC*/
+ virtual void RegisterRPC(CRPCTable &) = 0;
+ /** Verify wallets */
+ virtual bool Verify() = 0;
+ /** Open wallets*/
+ virtual bool Open() = 0;
+ /** Start wallets*/
+ virtual void Start(CScheduler& scheduler) = 0;
+ /** Flush Wallets*/
+ virtual void Flush() = 0;
+ /** Stop Wallets*/
+ virtual void Stop() = 0;
+ /** Close wallets */
+ virtual void Close() = 0;
+
+ virtual ~WalletInitInterface() {}
+};
+
+class DummyWalletInit : public WalletInitInterface {
+public:
+
+ std::string GetHelpString(bool showDebug) override {return std::string{};}
+ bool ParameterInteraction() override {return true;}
+ void RegisterRPC(CRPCTable &) override {}
+ bool Verify() override {return true;}
+ bool Open() override {return true;}
+ void Start(CScheduler& scheduler) override {}
+ void Flush() override {}
+ void Stop() override {}
+ void Close() override {}
+};
+
+#endif // BITCOIN_WALLETINITINTERFACE_H