aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am7
-rw-r--r--src/Makefile.qttest.include6
-rw-r--r--src/Makefile.test.include3
-rw-r--r--src/addrman.h2
-rw-r--r--src/base58.cpp59
-rw-r--r--src/base58.h29
-rw-r--r--src/bench/crypto_hash.cpp2
-rw-r--r--src/bitcoin-cli.cpp9
-rw-r--r--src/bitcoin-tx.cpp33
-rw-r--r--src/chain.h10
-rw-r--r--src/chainparamsbase.cpp2
-rw-r--r--src/coins.h10
-rw-r--r--src/consensus/validation.h11
-rw-r--r--src/core_write.cpp5
-rw-r--r--src/crypto/common.h2
-rw-r--r--src/crypto/sha256.cpp4
-rw-r--r--src/dbwrapper.cpp2
-rw-r--r--src/hash.h14
-rw-r--r--src/init.cpp95
-rw-r--r--src/key.h5
-rw-r--r--src/keystore.h32
-rw-r--r--src/miner.cpp39
-rw-r--r--src/miner.h9
-rw-r--r--src/net.cpp115
-rw-r--r--src/net.h37
-rw-r--r--src/net_processing.cpp277
-rw-r--r--src/net_processing.h35
-rw-r--r--src/policy/policy.cpp33
-rw-r--r--src/policy/policy.h4
-rw-r--r--src/primitives/transaction.cpp8
-rw-r--r--src/primitives/transaction.h4
-rw-r--r--src/qt/addresstablemodel.cpp22
-rw-r--r--src/qt/bitcoinaddressvalidator.cpp4
-rw-r--r--src/qt/bitcoingui.cpp9
-rw-r--r--src/qt/coincontroldialog.cpp2
-rw-r--r--src/qt/forms/optionsdialog.ui12
-rw-r--r--src/qt/forms/sendcoinsdialog.ui9
-rw-r--r--src/qt/guiutil.cpp72
-rw-r--r--src/qt/guiutil.h5
-rw-r--r--src/qt/macnotificationhandler.h7
-rw-r--r--src/qt/macnotificationhandler.mm14
-rw-r--r--src/qt/modaloverlay.cpp26
-rw-r--r--src/qt/notificator.cpp66
-rw-r--r--src/qt/notificator.h3
-rw-r--r--src/qt/optionsmodel.cpp22
-rw-r--r--src/qt/paymentserver.cpp15
-rw-r--r--src/qt/rpcconsole.cpp11
-rw-r--r--src/qt/sendcoinsdialog.cpp27
-rw-r--r--src/qt/signverifymessagedialog.cpp26
-rw-r--r--src/qt/splashscreen.cpp32
-rw-r--r--src/qt/splashscreen.h4
-rw-r--r--src/qt/test/paymentservertests.cpp14
-rw-r--r--src/qt/test/rpcnestedtests.cpp10
-rw-r--r--src/qt/test/test_main.cpp6
-rw-r--r--src/qt/test/wallettests.cpp8
-rw-r--r--src/qt/transactiondesc.cpp11
-rw-r--r--src/qt/transactionrecord.cpp4
-rw-r--r--src/qt/walletframe.cpp2
-rw-r--r--src/qt/walletmodel.cpp17
-rw-r--r--src/qt/walletmodel.h2
-rw-r--r--src/rest.cpp21
-rw-r--r--src/rpc/blockchain.cpp81
-rw-r--r--src/rpc/client.cpp4
-rw-r--r--src/rpc/mining.cpp38
-rw-r--r--src/rpc/misc.cpp159
-rw-r--r--src/rpc/net.cpp26
-rw-r--r--src/rpc/rawtransaction.cpp51
-rw-r--r--src/rpc/safemode.cpp14
-rw-r--r--src/rpc/safemode.h12
-rw-r--r--src/rpc/server.cpp15
-rw-r--r--src/rpc/server.h2
-rw-r--r--src/script/interpreter.cpp2
-rw-r--r--src/script/ismine.cpp2
-rw-r--r--src/script/standard.cpp4
-rw-r--r--src/script/standard.h5
-rw-r--r--src/streams.h16
-rw-r--r--src/support/cleanse.cpp30
-rw-r--r--src/support/lockedpool.h12
-rw-r--r--src/test/DoS_tests.cpp22
-rw-r--r--src/test/README.md5
-rw-r--r--src/test/base58_tests.cpp32
-rw-r--r--src/test/bip32_tests.cpp2
-rw-r--r--src/test/bloom_tests.cpp4
-rw-r--r--src/test/crypto_tests.cpp44
-rw-r--r--src/test/getarg_tests.cpp2
-rw-r--r--src/test/key_tests.cpp27
-rw-r--r--src/test/miner_tests.cpp1
-rw-r--r--src/test/multisig_tests.cpp91
-rw-r--r--src/test/script_P2SH_tests.cpp3
-rw-r--r--src/test/script_standard_tests.cpp740
-rw-r--r--src/test/skiplist_tests.cpp4
-rw-r--r--src/test/test_bitcoin.cpp10
-rw-r--r--src/test/test_bitcoin.h2
-rw-r--r--src/test/test_bitcoin_fuzzy.cpp2
-rw-r--r--src/test/testutil.cpp15
-rw-r--r--src/test/testutil.h15
-rw-r--r--src/test/transaction_tests.cpp3
-rw-r--r--src/test/util_tests.cpp25
-rw-r--r--src/txdb.cpp6
-rw-r--r--src/txdb.h8
-rw-r--r--src/txmempool.h7
-rw-r--r--src/ui_interface.h10
-rw-r--r--src/uint256.cpp2
-rw-r--r--src/uint256.h2
-rw-r--r--src/utilstrencodings.cpp13
-rw-r--r--src/utilstrencodings.h6
-rw-r--r--src/validation.cpp39
-rw-r--r--src/validation.h27
-rw-r--r--src/wallet/crypter.cpp11
-rw-r--r--src/wallet/crypter.h26
-rw-r--r--src/wallet/db.cpp2
-rw-r--r--src/wallet/db.h7
-rw-r--r--src/wallet/init.cpp38
-rw-r--r--src/wallet/init.h24
-rw-r--r--src/wallet/rpcdump.cpp85
-rw-r--r--src/wallet/rpcwallet.cpp296
-rw-r--r--src/wallet/rpcwallet.h3
-rw-r--r--src/wallet/test/crypto_tests.cpp2
-rw-r--r--src/wallet/wallet.cpp44
-rw-r--r--src/wallet/wallet.h6
-rw-r--r--src/wallet/walletdb.cpp6
-rw-r--r--src/wallet/walletdb.h5
122 files changed, 2067 insertions, 1516 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index dea656869d..ebae53a8c1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,7 +18,6 @@ else
LIBUNIVALUE = $(UNIVALUE_LIBS)
endif
-BITCOIN_CONFIG_INCLUDES=-I$(builddir)/config
BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS)
BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include
@@ -130,6 +129,7 @@ BITCOIN_CORE_H = \
rpc/client.h \
rpc/mining.h \
rpc/protocol.h \
+ rpc/safemode.h \
rpc/server.h \
rpc/register.h \
scheduler.h \
@@ -210,6 +210,7 @@ libbitcoin_server_a_SOURCES = \
rpc/misc.cpp \
rpc/net.cpp \
rpc/rawtransaction.cpp \
+ rpc/safemode.cpp \
rpc/server.cpp \
script/sigcache.cpp \
script/ismine.cpp \
@@ -250,7 +251,7 @@ libbitcoin_wallet_a_SOURCES = \
$(BITCOIN_CORE_H)
# crypto primitives library
-crypto_libbitcoin_crypto_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_CONFIG_INCLUDES)
+crypto_libbitcoin_crypto_a_CPPFLAGS = $(AM_CPPFLAGS)
crypto_libbitcoin_crypto_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
crypto_libbitcoin_crypto_a_SOURCES = \
crypto/aes.cpp \
@@ -271,7 +272,7 @@ crypto_libbitcoin_crypto_a_SOURCES = \
crypto/sha512.cpp \
crypto/sha512.h
-if EXPERIMENTAL_ASM
+if USE_ASM
crypto_libbitcoin_crypto_a_SOURCES += crypto/sha256_sse4.cpp
endif
diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include
index 02f30bc952..ea2ed17472 100644
--- a/src/Makefile.qttest.include
+++ b/src/Makefile.qttest.include
@@ -25,12 +25,10 @@ TEST_QT_H = \
qt/test/wallettests.h
TEST_BITCOIN_CPP = \
- test/test_bitcoin.cpp \
- test/testutil.cpp
+ test/test_bitcoin.cpp
TEST_BITCOIN_H = \
- test/test_bitcoin.h \
- test/testutil.h
+ test/test_bitcoin.h
qt_test_test_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \
$(QT_INCLUDES) $(QT_TEST_INCLUDES) $(PROTOBUF_CFLAGS)
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 6415b3d2e3..3a932f460d 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -65,6 +65,7 @@ BITCOIN_TESTS =\
test/scheduler_tests.cpp \
test/script_P2SH_tests.cpp \
test/script_tests.cpp \
+ test/script_standard_tests.cpp \
test/scriptnum_tests.cpp \
test/serialize_tests.cpp \
test/sighash_tests.cpp \
@@ -74,8 +75,6 @@ BITCOIN_TESTS =\
test/test_bitcoin.cpp \
test/test_bitcoin.h \
test/test_bitcoin_main.cpp \
- test/testutil.cpp \
- test/testutil.h \
test/timedata_tests.cpp \
test/torcontrol_tests.cpp \
test/transaction_tests.cpp \
diff --git a/src/addrman.h b/src/addrman.h
index 547088aedf..18f3062287 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -472,6 +472,8 @@ public:
nTried = 0;
nNew = 0;
nLastGood = 1; //Initially at 1 so that "never" is strictly worse.
+ mapInfo.clear();
+ mapAddr.clear();
}
CAddrMan()
diff --git a/src/base58.cpp b/src/base58.cpp
index 3802f953f9..3b907c20d6 100644
--- a/src/base58.cpp
+++ b/src/base58.cpp
@@ -212,6 +212,28 @@ int CBase58Data::CompareTo(const CBase58Data& b58) const
namespace
{
+/** base58-encoded Bitcoin addresses.
+ * Public-key-hash-addresses have version 0 (or 111 testnet).
+ * The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
+ * Script-hash-addresses have version 5 (or 196 testnet).
+ * The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
+ */
+class CBitcoinAddress : public CBase58Data {
+public:
+ bool Set(const CKeyID &id);
+ bool Set(const CScriptID &id);
+ bool Set(const CTxDestination &dest);
+ bool IsValid() const;
+ bool IsValid(const CChainParams &params) const;
+
+ CBitcoinAddress() {}
+ CBitcoinAddress(const CTxDestination &dest) { Set(dest); }
+ CBitcoinAddress(const std::string& strAddress) { SetString(strAddress); }
+ CBitcoinAddress(const char* pszAddress) { SetString(pszAddress); }
+
+ CTxDestination Get() const;
+};
+
class CBitcoinAddressVisitor : public boost::static_visitor<bool>
{
private:
@@ -271,21 +293,6 @@ CTxDestination CBitcoinAddress::Get() const
return CNoDestination();
}
-bool CBitcoinAddress::GetKeyID(CKeyID& keyID) const
-{
- if (!IsValid() || vchVersion != Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
- return false;
- uint160 id;
- memcpy(&id, vchData.data(), 20);
- keyID = CKeyID(id);
- return true;
-}
-
-bool CBitcoinAddress::IsScript() const
-{
- return IsValid() && vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS);
-}
-
void CBitcoinSecret::SetKey(const CKey& vchSecret)
{
assert(vchSecret.IsValid());
@@ -318,3 +325,25 @@ bool CBitcoinSecret::SetString(const std::string& strSecret)
{
return SetString(strSecret.c_str());
}
+
+std::string EncodeDestination(const CTxDestination& dest)
+{
+ CBitcoinAddress addr(dest);
+ if (!addr.IsValid()) return "";
+ return addr.ToString();
+}
+
+CTxDestination DecodeDestination(const std::string& str)
+{
+ return CBitcoinAddress(str).Get();
+}
+
+bool IsValidDestinationString(const std::string& str, const CChainParams& params)
+{
+ return CBitcoinAddress(str).IsValid(params);
+}
+
+bool IsValidDestinationString(const std::string& str)
+{
+ return CBitcoinAddress(str).IsValid();
+}
diff --git a/src/base58.h b/src/base58.h
index db12208f74..4b895ca022 100644
--- a/src/base58.h
+++ b/src/base58.h
@@ -95,30 +95,6 @@ public:
bool operator> (const CBase58Data& b58) const { return CompareTo(b58) > 0; }
};
-/** base58-encoded Bitcoin addresses.
- * Public-key-hash-addresses have version 0 (or 111 testnet).
- * The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
- * Script-hash-addresses have version 5 (or 196 testnet).
- * The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
- */
-class CBitcoinAddress : public CBase58Data {
-public:
- bool Set(const CKeyID &id);
- bool Set(const CScriptID &id);
- bool Set(const CTxDestination &dest);
- bool IsValid() const;
- bool IsValid(const CChainParams &params) const;
-
- CBitcoinAddress() {}
- CBitcoinAddress(const CTxDestination &dest) { Set(dest); }
- CBitcoinAddress(const std::string& strAddress) { SetString(strAddress); }
- CBitcoinAddress(const char* pszAddress) { SetString(pszAddress); }
-
- CTxDestination Get() const;
- bool GetKeyID(CKeyID &keyID) const;
- bool IsScript() const;
-};
-
/**
* A base58-encoded secret key
*/
@@ -167,4 +143,9 @@ public:
typedef CBitcoinExtKeyBase<CExtKey, BIP32_EXTKEY_SIZE, CChainParams::EXT_SECRET_KEY> CBitcoinExtKey;
typedef CBitcoinExtKeyBase<CExtPubKey, BIP32_EXTKEY_SIZE, CChainParams::EXT_PUBLIC_KEY> CBitcoinExtPubKey;
+std::string EncodeDestination(const CTxDestination& dest);
+CTxDestination DecodeDestination(const std::string& str);
+bool IsValidDestinationString(const std::string& str);
+bool IsValidDestinationString(const std::string& str, const CChainParams& params);
+
#endif // BITCOIN_BASE58_H
diff --git a/src/bench/crypto_hash.cpp b/src/bench/crypto_hash.cpp
index 2914a36c7b..410a08e512 100644
--- a/src/bench/crypto_hash.cpp
+++ b/src/bench/crypto_hash.cpp
@@ -47,7 +47,7 @@ static void SHA256_32b(benchmark::State& state)
std::vector<uint8_t> in(32,0);
while (state.KeepRunning()) {
for (int i = 0; i < 1000000; i++) {
- CSHA256().Write(in.data(), in.size()).Finalize(&in[0]);
+ CSHA256().Write(in.data(), in.size()).Finalize(in.data());
}
}
}
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index fca6083ea8..3c94c99b3e 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -296,19 +296,22 @@ int CommandLineRPC(int argc, char *argv[])
}
std::string rpcPass;
if (gArgs.GetBoolArg("-stdinrpcpass", false)) {
- if(!std::getline(std::cin,rpcPass))
+ if (!std::getline(std::cin, rpcPass)) {
throw std::runtime_error("-stdinrpcpass specified but failed to read from standard input");
+ }
gArgs.ForceSetArg("-rpcpassword", rpcPass);
}
std::vector<std::string> args = std::vector<std::string>(&argv[1], &argv[argc]);
if (gArgs.GetBoolArg("-stdin", false)) {
// Read one arg per line from stdin and append
std::string line;
- while (std::getline(std::cin,line))
+ while (std::getline(std::cin, line)) {
args.push_back(line);
+ }
}
- if (args.size() < 1)
+ if (args.size() < 1) {
throw std::runtime_error("too few parameters (need at least command)");
+ }
std::string strMethod = args[0];
args.erase(args.begin()); // Remove trailing method name from arguments vector
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index cff90d13af..e4f44435ba 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -271,11 +271,11 @@ static void MutateTxAddOutAddr(CMutableTransaction& tx, const std::string& strIn
// extract and validate ADDRESS
std::string strAddr = vStrInputParts[1];
- CBitcoinAddress addr(strAddr);
- if (!addr.IsValid())
+ CTxDestination destination = DecodeDestination(strAddr);
+ if (!IsValidDestination(destination)) {
throw std::runtime_error("invalid TX output address");
- // build standard output script via GetScriptForDestination()
- CScript scriptPubKey = GetScriptForDestination(addr.Get());
+ }
+ CScript scriptPubKey = GetScriptForDestination(destination);
// construct TxOut, append to transaction output list
CTxOut txout(value, scriptPubKey);
@@ -310,14 +310,15 @@ static void MutateTxAddOutPubKey(CMutableTransaction& tx, const std::string& str
}
if (bSegWit) {
+ if (!pubkey.IsCompressed()) {
+ throw std::runtime_error("Uncompressed pubkeys are not useable for SegWit outputs");
+ }
// Call GetScriptForWitness() to build a P2WSH scriptPubKey
scriptPubKey = GetScriptForWitness(scriptPubKey);
}
if (bScriptHash) {
- // Get the address for the redeem script, then call
- // GetScriptForDestination() to construct a P2SH scriptPubKey.
- CBitcoinAddress redeemScriptAddr(scriptPubKey);
- scriptPubKey = GetScriptForDestination(redeemScriptAddr.Get());
+ // Get the ID for the script, and then construct a P2SH destination for it.
+ scriptPubKey = GetScriptForDestination(CScriptID(scriptPubKey));
}
// construct TxOut, append to transaction output list
@@ -377,14 +378,17 @@ static void MutateTxAddOutMultiSig(CMutableTransaction& tx, const std::string& s
CScript scriptPubKey = GetScriptForMultisig(required, pubkeys);
if (bSegWit) {
+ for (CPubKey& pubkey : pubkeys) {
+ if (!pubkey.IsCompressed()) {
+ throw std::runtime_error("Uncompressed pubkeys are not useable for SegWit outputs");
+ }
+ }
// Call GetScriptForWitness() to build a P2WSH scriptPubKey
scriptPubKey = GetScriptForWitness(scriptPubKey);
}
if (bScriptHash) {
- // Get the address for the redeem script, then call
- // GetScriptForDestination() to construct a P2SH scriptPubKey.
- CBitcoinAddress addr(scriptPubKey);
- scriptPubKey = GetScriptForDestination(addr.Get());
+ // Get the ID for the script, and then construct a P2SH destination for it.
+ scriptPubKey = GetScriptForDestination(CScriptID(scriptPubKey));
}
// construct TxOut, append to transaction output list
@@ -444,11 +448,10 @@ static void MutateTxAddOutScript(CMutableTransaction& tx, const std::string& str
}
if (bSegWit) {
- scriptPubKey = GetScriptForWitness(scriptPubKey);
+ scriptPubKey = GetScriptForWitness(scriptPubKey);
}
if (bScriptHash) {
- CBitcoinAddress addr(scriptPubKey);
- scriptPubKey = GetScriptForDestination(addr.Get());
+ scriptPubKey = GetScriptForDestination(CScriptID(scriptPubKey));
}
// construct TxOut, append to transaction output list
diff --git a/src/chain.h b/src/chain.h
index ef7e6f9554..f1036e5d92 100644
--- a/src/chain.h
+++ b/src/chain.h
@@ -204,14 +204,14 @@ public:
unsigned int nChainTx;
//! Verification status of this block. See enum BlockStatus
- unsigned int nStatus;
+ uint32_t nStatus;
//! block header
- int nVersion;
+ int32_t nVersion;
uint256 hashMerkleRoot;
- unsigned int nTime;
- unsigned int nBits;
- unsigned int nNonce;
+ uint32_t nTime;
+ uint32_t nBits;
+ uint32_t nNonce;
//! (memory only) Sequential id assigned to distinguish order in which blocks are received.
int32_t nSequenceId;
diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp
index 224c9eb0ea..c966683b72 100644
--- a/src/chainparamsbase.cpp
+++ b/src/chainparamsbase.cpp
@@ -57,7 +57,7 @@ class CBaseRegTestParams : public CBaseChainParams
public:
CBaseRegTestParams()
{
- nRPCPort = 18332;
+ nRPCPort = 18443;
strDataDir = "regtest";
}
};
diff --git a/src/coins.h b/src/coins.h
index efb5ce869c..181b2fd4b9 100644
--- a/src/coins.h
+++ b/src/coins.h
@@ -214,6 +214,11 @@ protected:
public:
CCoinsViewCache(CCoinsView *baseIn);
+ /**
+ * By deleting the copy constructor, we prevent accidentally using it when one intends to create a cache on top of a base cache.
+ */
+ CCoinsViewCache(const CCoinsViewCache &) = delete;
+
// Standard CCoinsView methods
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override;
bool HaveCoin(const COutPoint &outpoint) const override;
@@ -290,11 +295,6 @@ public:
private:
CCoinsMap::iterator FetchCoin(const COutPoint &outpoint) const;
-
- /**
- * By making the copy constructor private, we prevent accidentally using it when one intends to create a cache on top of a base cache.
- */
- CCoinsViewCache(const CCoinsViewCache &);
};
//! Utility function to add all of a transaction's outputs to a cache.
diff --git a/src/consensus/validation.h b/src/consensus/validation.h
index 5494ce40ea..b6740c9d9f 100644
--- a/src/consensus/validation.h
+++ b/src/consensus/validation.h
@@ -89,17 +89,16 @@ public:
std::string GetDebugMessage() const { return strDebugMessage; }
};
+// These implement the weight = (stripped_size * 4) + witness_size formula,
+// using only serialization with and without witness data. As witness_size
+// is equal to total_size - stripped_size, this formula is identical to:
+// weight = (stripped_size * 3) + total_size.
static inline int64_t GetTransactionWeight(const CTransaction& tx)
{
- return ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR -1) + ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
+ return ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
}
-
static inline int64_t GetBlockWeight(const CBlock& block)
{
- // This implements the weight = (stripped_size * 4) + witness_size formula,
- // using only serialization with and without witness data. As witness_size
- // is equal to total_size - stripped_size, this formula is identical to:
- // weight = (stripped_size * 3) + total_size.
return ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION);
}
diff --git a/src/core_write.cpp b/src/core_write.cpp
index 1431fa0c9b..e16db13650 100644
--- a/src/core_write.cpp
+++ b/src/core_write.cpp
@@ -148,8 +148,9 @@ void ScriptPubKeyToUniv(const CScript& scriptPubKey,
out.pushKV("type", GetTxnOutputType(type));
UniValue a(UniValue::VARR);
- for (const CTxDestination& addr : addresses)
- a.push_back(CBitcoinAddress(addr).ToString());
+ for (const CTxDestination& addr : addresses) {
+ a.push_back(EncodeDestination(addr));
+ }
out.pushKV("addresses", a);
}
diff --git a/src/crypto/common.h b/src/crypto/common.h
index bcca3d30ea..bd9bc9420b 100644
--- a/src/crypto/common.h
+++ b/src/crypto/common.h
@@ -6,7 +6,7 @@
#define BITCOIN_CRYPTO_COMMON_H
#if defined(HAVE_CONFIG_H)
-#include "bitcoin-config.h"
+#include "config/bitcoin-config.h"
#endif
#include <stdint.h>
diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp
index 15d6db90c2..29afe86ec7 100644
--- a/src/crypto/sha256.cpp
+++ b/src/crypto/sha256.cpp
@@ -10,7 +10,7 @@
#include <atomic>
#if defined(__x86_64__) || defined(__amd64__)
-#if defined(EXPERIMENTAL_ASM)
+#if defined(USE_ASM)
#include <cpuid.h>
namespace sha256_sse4
{
@@ -178,7 +178,7 @@ TransformType Transform = sha256::Transform;
std::string SHA256AutoDetect()
{
-#if defined(EXPERIMENTAL_ASM) && (defined(__x86_64__) || defined(__amd64__))
+#if defined(USE_ASM) && (defined(__x86_64__) || defined(__amd64__))
uint32_t eax, ebx, ecx, edx;
if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) && (ecx >> 19) & 1) {
Transform = sha256_sse4::Transform;
diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp
index 72eeeef2c3..dfc90f3ab9 100644
--- a/src/dbwrapper.cpp
+++ b/src/dbwrapper.cpp
@@ -19,7 +19,7 @@ class CBitcoinLevelDBLogger : public leveldb::Logger {
public:
// This code is adapted from posix_logger.h, which is why it is using vsprintf.
// Please do not do this in normal code
- virtual void Logv(const char * format, va_list ap) override {
+ void Logv(const char * format, va_list ap) override {
if (!LogAcceptCategory(BCLog::LEVELDB)) {
return;
}
diff --git a/src/hash.h b/src/hash.h
index ad59bb1817..474b13d65b 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -88,20 +88,6 @@ inline uint256 Hash(const T1 p1begin, const T1 p1end,
return result;
}
-/** Compute the 256-bit hash of the concatenation of three objects. */
-template<typename T1, typename T2, typename T3>
-inline uint256 Hash(const T1 p1begin, const T1 p1end,
- const T2 p2begin, const T2 p2end,
- const T3 p3begin, const T3 p3end) {
- static const unsigned char pblank[1] = {};
- uint256 result;
- CHash256().Write(p1begin == p1end ? pblank : (const unsigned char*)&p1begin[0], (p1end - p1begin) * sizeof(p1begin[0]))
- .Write(p2begin == p2end ? pblank : (const unsigned char*)&p2begin[0], (p2end - p2begin) * sizeof(p2begin[0]))
- .Write(p3begin == p3end ? pblank : (const unsigned char*)&p3begin[0], (p3end - p3begin) * sizeof(p3begin[0]))
- .Finalize((unsigned char*)&result);
- return result;
-}
-
/** Compute the 160-bit hash an object. */
template<typename T1>
inline uint160 Hash160(const T1 pbegin, const T1 pend)
diff --git a/src/init.cpp b/src/init.cpp
index 7c99dc74ef..e80170b24d 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -30,6 +30,7 @@
#include "policy/policy.h"
#include "rpc/server.h"
#include "rpc/register.h"
+#include "rpc/safemode.h"
#include "rpc/blockchain.h"
#include "script/standard.h"
#include "script/sigcache.h"
@@ -44,7 +45,6 @@
#include "validationinterface.h"
#ifdef ENABLE_WALLET
#include "wallet/init.h"
-#include "wallet/wallet.h"
#endif
#include "warnings.h"
#include <stdint.h>
@@ -70,7 +70,6 @@
bool fFeeEstimatesInitialized = false;
static const bool DEFAULT_PROXYRANDOMIZE = true;
static const bool DEFAULT_REST_ENABLE = false;
-static const bool DEFAULT_DISABLE_SAFEMODE = true;
static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false;
std::unique_ptr<CConnman> g_connman;
@@ -103,12 +102,11 @@ static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat";
// created by AppInit() or the Qt main() function.
//
// A clean exit happens when StartShutdown() or the SIGTERM
-// signal handler sets fRequestShutdown, which triggers
-// the DetectShutdownThread(), which interrupts the main thread group.
-// DetectShutdownThread() then exits, which causes AppInit() to
-// continue (it .joins the shutdown thread).
-// Shutdown() is then
-// called to clean up database connections, and stop other
+// signal handler sets fRequestShutdown, which makes main thread's
+// WaitForShutdown() interrupts the thread group.
+// And then, WaitForShutdown() makes all other on-going threads
+// in the thread group join the main thread.
+// Shutdown() is then called to clean up database connections, and stop other
// threads that should only be stopped after the main network-processing
// threads have exited.
//
@@ -189,17 +187,18 @@ void Shutdown()
StopRPC();
StopHTTPServer();
#ifdef ENABLE_WALLET
- for (CWalletRef pwallet : vpwallets) {
- pwallet->Flush(false);
- }
+ FlushWallets();
#endif
MapPort(false);
+
+ // Because these depend on each-other, we make sure that neither can be
+ // using the other before destroying them.
UnregisterValidationInterface(peerLogic.get());
+ if(g_connman) g_connman->Stop();
peerLogic.reset();
g_connman.reset();
StopTorControl();
- UnregisterNodeSignals(GetNodeSignals());
if (fDumpMempoolLater && gArgs.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
DumpMempool();
}
@@ -246,9 +245,7 @@ void Shutdown()
pblocktree = nullptr;
}
#ifdef ENABLE_WALLET
- for (CWalletRef pwallet : vpwallets) {
- pwallet->Flush(true);
- }
+ StopWallets();
#endif
#if ENABLE_ZMQ
@@ -269,10 +266,7 @@ void Shutdown()
UnregisterAllValidationInterfaces();
GetMainSignals().UnregisterBackgroundSignalScheduler();
#ifdef ENABLE_WALLET
- for (CWalletRef pwallet : vpwallets) {
- delete pwallet;
- }
- vpwallets.clear();
+ CloseWallets();
#endif
globalVerifyHandle.reset();
ECC_Stop();
@@ -318,15 +312,6 @@ void OnRPCStopped()
LogPrint(BCLog::RPC, "RPC stopped.\n");
}
-void OnRPCPreCommand(const CRPCCommand& cmd)
-{
- // Observe safe mode
- std::string strWarning = GetWarnings("rpc");
- if (strWarning != "" && !gArgs.GetBoolArg("-disablesafemode", DEFAULT_DISABLE_SAFEMODE) &&
- !cmd.okSafeMode)
- throw JSONRPCError(RPC_FORBIDDEN_BY_SAFE_MODE, std::string("Safe mode: ") + strWarning);
-}
-
std::string HelpMessage(HelpMessageMode mode)
{
const auto defaultBaseParams = CreateBaseChainParams(CBaseChainParams::MAIN);
@@ -363,6 +348,9 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-maxorphantx=<n>", strprintf(_("Keep at most <n> unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS));
strUsage += HelpMessageOpt("-maxmempool=<n>", strprintf(_("Keep the transaction memory pool below <n> megabytes (default: %u)"), DEFAULT_MAX_MEMPOOL_SIZE));
strUsage += HelpMessageOpt("-mempoolexpiry=<n>", strprintf(_("Do not keep transactions in the mempool longer than <n> hours (default: %u)"), DEFAULT_MEMPOOL_EXPIRY));
+ if (showDebug) {
+ strUsage += HelpMessageOpt("-minimumchainwork=<hex>", strprintf("Minimum work assumed to exist on a valid chain in hex (default: %s, testnet: %s)", defaultChainParams->GetConsensus().nMinimumChainWork.GetHex(), testnetChainParams->GetConsensus().nMinimumChainWork.GetHex()));
+ }
strUsage += HelpMessageOpt("-persistmempool", strprintf(_("Whether to save the mempool on shutdown and load on restart (default: %u)"), DEFAULT_PERSIST_MEMPOOL));
strUsage += HelpMessageOpt("-blockreconstructionextratxn=<n>", strprintf(_("Extra transactions to keep in memory for compact block reconstructions (default: %u)"), DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN));
strUsage += HelpMessageOpt("-par=<n>", strprintf(_("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)"),
@@ -495,7 +483,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageGroup(_("Block creation options:"));
strUsage += HelpMessageOpt("-blockmaxweight=<n>", strprintf(_("Set maximum BIP141 block weight (default: %d)"), DEFAULT_BLOCK_MAX_WEIGHT));
- strUsage += HelpMessageOpt("-blockmaxsize=<n>", strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE));
+ strUsage += HelpMessageOpt("-blockmaxsize=<n>", _("Set maximum BIP141 block weight to this * 4. Deprecated, use blockmaxweight"));
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)
strUsage += HelpMessageOpt("-blockversion=<n>", "Override block version to test forking scenarios");
@@ -721,7 +709,6 @@ bool AppInitServers(boost::thread_group& threadGroup)
{
RPCServer::OnStarted(&OnRPCStarted);
RPCServer::OnStopped(&OnRPCStopped);
- RPCServer::OnPreCommand(&OnRPCPreCommand);
if (!InitHTTPServer())
return false;
if (!StartRPC())
@@ -797,6 +784,15 @@ 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)
@@ -980,6 +976,20 @@ bool AppInitParameterInteraction()
else
LogPrintf("Validating signatures for all blocks.\n");
+ if (gArgs.IsArgSet("-minimumchainwork")) {
+ const std::string minChainWorkStr = gArgs.GetArg("-minimumchainwork", "");
+ if (!IsHexNumber(minChainWorkStr)) {
+ return InitError(strprintf("Invalid non-hex (%s) minimum chain work value specified", minChainWorkStr));
+ }
+ nMinimumChainWork = UintToArith256(uint256S(minChainWorkStr));
+ } else {
+ nMinimumChainWork = UintToArith256(chainparams.GetConsensus().nMinimumChainWork);
+ }
+ LogPrintf("Setting nMinimumChainWork=%s\n", nMinimumChainWork.GetHex());
+ if (nMinimumChainWork < UintToArith256(chainparams.GetConsensus().nMinimumChainWork)) {
+ LogPrintf("Warning: nMinimumChainWork set below default value of %s\n", chainparams.GetConsensus().nMinimumChainWork.GetHex());
+ }
+
// mempool limits
int64_t nMempoolSizeMax = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
int64_t nMempoolSizeMin = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) * 1000 * 40;
@@ -1024,7 +1034,7 @@ bool AppInitParameterInteraction()
RegisterAllCoreRPCCommands(tableRPC);
#ifdef ENABLE_WALLET
- RegisterWalletRPCCommands(tableRPC);
+ RegisterWalletRPC(tableRPC);
#endif
nConnectTimeout = gArgs.GetArg("-timeout", DEFAULT_CONNECT_TIMEOUT);
@@ -1246,7 +1256,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
// ********************************************************* Step 5: verify wallet database integrity
#ifdef ENABLE_WALLET
- if (!WalletVerify())
+ if (!VerifyWallets())
return false;
#endif
// ********************************************************* Step 6: network initialization
@@ -1261,7 +1271,6 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
peerLogic.reset(new PeerLogicValidation(&connman));
RegisterValidationInterface(peerLogic.get());
- RegisterNodeSignals(GetNodeSignals());
// sanitize comments per BIP-0014, format user agent and check total size
std::vector<std::string> uacomments;
@@ -1567,7 +1576,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
// ********************************************************* Step 8: load wallet
#ifdef ENABLE_WALLET
- if (!InitLoadWallet())
+ if (!OpenWallets())
return false;
#else
LogPrintf("No wallet support compiled in!\n");
@@ -1652,8 +1661,10 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
connOptions.nMaxFeeler = 1;
connOptions.nBestHeight = chainActive.Height();
connOptions.uiInterface = &uiInterface;
+ connOptions.m_msgproc = peerLogic.get();
connOptions.nSendBufferMaxSize = 1000*gArgs.GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER);
connOptions.nReceiveFloodSize = 1000*gArgs.GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER);
+ connOptions.m_added_nodes = gArgs.GetArgs("-addnode");
connOptions.nMaxOutboundTimeframe = nMaxOutboundTimeframe;
connOptions.nMaxOutboundLimit = nMaxOutboundLimit;
@@ -1684,10 +1695,16 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
connOptions.vWhitelistedRange.push_back(subnet);
}
- if (gArgs.IsArgSet("-seednode")) {
- connOptions.vSeedNodes = gArgs.GetArgs("-seednode");
- }
+ connOptions.vSeedNodes = gArgs.GetArgs("-seednode");
+ // Initiate outbound connections unless connect=0
+ connOptions.m_use_addrman_outgoing = !gArgs.IsArgSet("-connect");
+ if (!connOptions.m_use_addrman_outgoing) {
+ const auto connect = gArgs.GetArgs("-connect");
+ if (connect.size() != 1 || connect[0] != "0") {
+ connOptions.m_specified_outgoing = connect;
+ }
+ }
if (!connman.Start(scheduler, connOptions)) {
return false;
}
@@ -1698,9 +1715,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
uiInterface.InitMessage(_("Done loading"));
#ifdef ENABLE_WALLET
- for (CWalletRef pwallet : vpwallets) {
- pwallet->postInitProcess(scheduler);
- }
+ StartWallets(scheduler);
#endif
return !fRequestShutdown;
diff --git a/src/key.h b/src/key.h
index 151e63531b..54b5be2270 100644
--- a/src/key.h
+++ b/src/key.h
@@ -56,11 +56,6 @@ public:
keydata.resize(32);
}
- //! Destructor (again necessary because of memlocking).
- ~CKey()
- {
- }
-
friend bool operator==(const CKey& a, const CKey& b)
{
return a.fCompressed == b.fCompressed &&
diff --git a/src/keystore.h b/src/keystore.h
index 965ae0c79a..9b85ddb0ec 100644
--- a/src/keystore.h
+++ b/src/keystore.h
@@ -30,7 +30,7 @@ public:
//! 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 void GetKeys(std::set<CKeyID> &setAddress) 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
@@ -71,18 +71,14 @@ public:
}
return result;
}
- void GetKeys(std::set<CKeyID> &setAddress) const override
+ std::set<CKeyID> GetKeys() const override
{
- setAddress.clear();
- {
- LOCK(cs_KeyStore);
- KeyMap::const_iterator mi = mapKeys.begin();
- while (mi != mapKeys.end())
- {
- setAddress.insert((*mi).first);
- mi++;
- }
+ LOCK(cs_KeyStore);
+ std::set<CKeyID> set_address;
+ for (const auto& mi : mapKeys) {
+ set_address.insert(mi.first);
}
+ return set_address;
}
bool GetKey(const CKeyID &address, CKey &keyOut) const override
{
@@ -97,14 +93,14 @@ public:
}
return false;
}
- virtual bool AddCScript(const CScript& redeemScript) override;
- virtual bool HaveCScript(const CScriptID &hash) const override;
- virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const override;
+ bool AddCScript(const CScript& redeemScript) override;
+ bool HaveCScript(const CScriptID &hash) const override;
+ bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const override;
- virtual bool AddWatchOnly(const CScript &dest) override;
- virtual bool RemoveWatchOnly(const CScript &dest) override;
- virtual bool HaveWatchOnly(const CScript &dest) const override;
- virtual bool HaveWatchOnly() const override;
+ bool AddWatchOnly(const CScript &dest) override;
+ bool RemoveWatchOnly(const CScript &dest) override;
+ bool HaveWatchOnly(const CScript &dest) const override;
+ bool HaveWatchOnly() const override;
};
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial;
diff --git a/src/miner.cpp b/src/miner.cpp
index f1942ec570..a9989f4b17 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -43,7 +43,6 @@
// its ancestors.
uint64_t nLastBlockTx = 0;
-uint64_t nLastBlockSize = 0;
uint64_t nLastBlockWeight = 0;
int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
@@ -64,7 +63,6 @@ int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParam
BlockAssembler::Options::Options() {
blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE);
nBlockMaxWeight = DEFAULT_BLOCK_MAX_WEIGHT;
- nBlockMaxSize = DEFAULT_BLOCK_MAX_SIZE;
}
BlockAssembler::BlockAssembler(const CChainParams& params, const Options& options) : chainparams(params)
@@ -72,10 +70,6 @@ BlockAssembler::BlockAssembler(const CChainParams& params, const Options& option
blockMinFeeRate = options.blockMinFeeRate;
// Limit weight to between 4K and MAX_BLOCK_WEIGHT-4K for sanity:
nBlockMaxWeight = std::max<size_t>(4000, std::min<size_t>(MAX_BLOCK_WEIGHT - 4000, options.nBlockMaxWeight));
- // Limit size to between 1K and MAX_BLOCK_SERIALIZED_SIZE-1K for sanity:
- nBlockMaxSize = std::max<size_t>(1000, std::min<size_t>(MAX_BLOCK_SERIALIZED_SIZE - 1000, options.nBlockMaxSize));
- // Whether we need to account for byte usage (in addition to weight usage)
- fNeedSizeAccounting = (nBlockMaxSize < MAX_BLOCK_SERIALIZED_SIZE - 1000);
}
static BlockAssembler::Options DefaultOptions(const CChainParams& params)
@@ -85,20 +79,7 @@ static BlockAssembler::Options DefaultOptions(const CChainParams& params)
// If only one is given, only restrict the specified resource.
// If both are given, restrict both.
BlockAssembler::Options options;
- options.nBlockMaxWeight = DEFAULT_BLOCK_MAX_WEIGHT;
- options.nBlockMaxSize = DEFAULT_BLOCK_MAX_SIZE;
- bool fWeightSet = false;
- if (gArgs.IsArgSet("-blockmaxweight")) {
- options.nBlockMaxWeight = gArgs.GetArg("-blockmaxweight", DEFAULT_BLOCK_MAX_WEIGHT);
- options.nBlockMaxSize = MAX_BLOCK_SERIALIZED_SIZE;
- fWeightSet = true;
- }
- if (gArgs.IsArgSet("-blockmaxsize")) {
- options.nBlockMaxSize = gArgs.GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE);
- if (!fWeightSet) {
- options.nBlockMaxWeight = options.nBlockMaxSize * WITNESS_SCALE_FACTOR;
- }
- }
+ options.nBlockMaxWeight = gArgs.GetArg("-blockmaxweight", DEFAULT_BLOCK_MAX_WEIGHT);
if (gArgs.IsArgSet("-blockmintxfee")) {
CAmount n = 0;
ParseMoney(gArgs.GetArg("-blockmintxfee", ""), n);
@@ -116,7 +97,6 @@ void BlockAssembler::resetBlock()
inBlock.clear();
// Reserve space for coinbase tx
- nBlockSize = 1000;
nBlockWeight = 4000;
nBlockSigOpsCost = 400;
fIncludeWitness = false;
@@ -145,6 +125,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
LOCK2(cs_main, mempool.cs);
CBlockIndex* pindexPrev = chainActive.Tip();
+ assert(pindexPrev != nullptr);
nHeight = pindexPrev->nHeight + 1;
pblock->nVersion = ComputeBlockVersion(pindexPrev, chainparams.GetConsensus());
@@ -175,7 +156,6 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
int64_t nTime1 = GetTimeMicros();
nLastBlockTx = nBlockTx;
- nLastBlockSize = nBlockSize;
nLastBlockWeight = nBlockWeight;
// Create coinbase transaction.
@@ -190,8 +170,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
pblocktemplate->vchCoinbaseCommitment = GenerateCoinbaseCommitment(*pblock, pindexPrev, chainparams.GetConsensus());
pblocktemplate->vTxFees[0] = -nFees;
- uint64_t nSerializeSize = GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION);
- LogPrintf("CreateNewBlock(): total size: %u block weight: %u txs: %u fees: %ld sigops %d\n", nSerializeSize, GetBlockWeight(*pblock), nBlockTx, nFees, nBlockSigOpsCost);
+ LogPrintf("CreateNewBlock(): block weight: %u txs: %u fees: %ld sigops %d\n", GetBlockWeight(*pblock), nBlockTx, nFees, nBlockSigOpsCost);
// Fill in header
pblock->hashPrevBlock = pindexPrev->GetBlockHash();
@@ -238,22 +217,13 @@ bool BlockAssembler::TestPackage(uint64_t packageSize, int64_t packageSigOpsCost
// - transaction finality (locktime)
// - premature witness (in case segwit transactions are added to mempool before
// segwit activation)
-// - serialized size (in case -blockmaxsize is in use)
bool BlockAssembler::TestPackageTransactions(const CTxMemPool::setEntries& package)
{
- uint64_t nPotentialBlockSize = nBlockSize; // only used with fNeedSizeAccounting
for (const CTxMemPool::txiter it : package) {
if (!IsFinalTx(it->GetTx(), nHeight, nLockTimeCutoff))
return false;
if (!fIncludeWitness && it->GetTx().HasWitness())
return false;
- if (fNeedSizeAccounting) {
- uint64_t nTxSize = ::GetSerializeSize(it->GetTx(), SER_NETWORK, PROTOCOL_VERSION);
- if (nPotentialBlockSize + nTxSize >= nBlockMaxSize) {
- return false;
- }
- nPotentialBlockSize += nTxSize;
- }
}
return true;
}
@@ -263,9 +233,6 @@ void BlockAssembler::AddToBlock(CTxMemPool::txiter iter)
pblock->vtx.emplace_back(iter->GetSharedTx());
pblocktemplate->vTxFees.push_back(iter->GetFee());
pblocktemplate->vTxSigOpsCost.push_back(iter->GetSigOpCost());
- if (fNeedSizeAccounting) {
- nBlockSize += ::GetSerializeSize(iter->GetTx(), SER_NETWORK, PROTOCOL_VERSION);
- }
nBlockWeight += iter->GetTxWeight();
++nBlockTx;
nBlockSigOpsCost += iter->GetSigOpCost();
diff --git a/src/miner.h b/src/miner.h
index 6e5fe761db..db165e71c6 100644
--- a/src/miner.h
+++ b/src/miner.h
@@ -11,8 +11,8 @@
#include <stdint.h>
#include <memory>
-#include "boost/multi_index_container.hpp"
-#include "boost/multi_index/ordered_index.hpp"
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/ordered_index.hpp>
class CBlockIndex;
class CChainParams;
@@ -139,13 +139,11 @@ private:
// Configuration parameters for the block size
bool fIncludeWitness;
- unsigned int nBlockMaxWeight, nBlockMaxSize;
- bool fNeedSizeAccounting;
+ unsigned int nBlockMaxWeight;
CFeeRate blockMinFeeRate;
// Information on the current status of the block
uint64_t nBlockWeight;
- uint64_t nBlockSize;
uint64_t nBlockTx;
uint64_t nBlockSigOpsCost;
CAmount nFees;
@@ -160,7 +158,6 @@ public:
struct Options {
Options();
size_t nBlockMaxWeight;
- size_t nBlockMaxSize;
CFeeRate blockMinFeeRate;
};
diff --git a/src/net.cpp b/src/net.cpp
index 1af317726a..c3f16a8f1f 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -89,10 +89,6 @@ std::string strSubVersion;
limitedmap<uint256, int64_t> mapAlreadyAskedFor(MAX_INV_SZ);
-// Signals for message handling
-static CNodeSignals g_signals;
-CNodeSignals& GetNodeSignals() { return g_signals; }
-
void CConnman::AddOneShot(const std::string& strDest)
{
LOCK(cs_vOneShots);
@@ -139,11 +135,10 @@ static std::vector<CAddress> convertSeed6(const std::vector<SeedSpec6> &vSeedsIn
const int64_t nOneWeek = 7*24*60*60;
std::vector<CAddress> vSeedsOut;
vSeedsOut.reserve(vSeedsIn.size());
- for (std::vector<SeedSpec6>::const_iterator i(vSeedsIn.begin()); i != vSeedsIn.end(); ++i)
- {
+ for (const auto& seed_in : vSeedsIn) {
struct in6_addr ip;
- memcpy(&ip, i->addr, sizeof(ip));
- CAddress addr(CService(ip, i->port), NODE_NETWORK);
+ memcpy(&ip, seed_in.addr, sizeof(ip));
+ CAddress addr(CService(ip, seed_in.port), NODE_NETWORK);
addr.nTime = GetTime() - GetRand(nOneWeek) - nOneWeek;
vSeedsOut.push_back(addr);
}
@@ -303,18 +298,22 @@ bool IsReachable(const CNetAddr& addr)
CNode* CConnman::FindNode(const CNetAddr& ip)
{
LOCK(cs_vNodes);
- for (CNode* pnode : vNodes)
- if ((CNetAddr)pnode->addr == ip)
- return (pnode);
+ for (CNode* pnode : vNodes) {
+ if ((CNetAddr)pnode->addr == ip) {
+ return pnode;
+ }
+ }
return nullptr;
}
CNode* CConnman::FindNode(const CSubNet& subNet)
{
LOCK(cs_vNodes);
- for (CNode* pnode : vNodes)
- if (subNet.Match((CNetAddr)pnode->addr))
- return (pnode);
+ for (CNode* pnode : vNodes) {
+ if (subNet.Match((CNetAddr)pnode->addr)) {
+ return pnode;
+ }
+ }
return nullptr;
}
@@ -323,7 +322,7 @@ CNode* CConnman::FindNode(const std::string& addrName)
LOCK(cs_vNodes);
for (CNode* pnode : vNodes) {
if (pnode->GetAddrName() == addrName) {
- return (pnode);
+ return pnode;
}
}
return nullptr;
@@ -332,9 +331,11 @@ CNode* CConnman::FindNode(const std::string& addrName)
CNode* CConnman::FindNode(const CService& addr)
{
LOCK(cs_vNodes);
- for (CNode* pnode : vNodes)
- if ((CService)pnode->addr == addr)
- return (pnode);
+ for (CNode* pnode : vNodes) {
+ if ((CService)pnode->addr == addr) {
+ return pnode;
+ }
+ }
return nullptr;
}
@@ -478,10 +479,9 @@ void CConnman::ClearBanned()
bool CConnman::IsBanned(CNetAddr ip)
{
LOCK(cs_setBanned);
- for (banmap_t::iterator it = setBanned.begin(); it != setBanned.end(); it++)
- {
- CSubNet subNet = (*it).first;
- CBanEntry banEntry = (*it).second;
+ for (const auto& it : setBanned) {
+ CSubNet subNet = it.first;
+ CBanEntry banEntry = it.second;
if (subNet.Match(ip) && GetTime() < banEntry.nBanUntil) {
return true;
@@ -956,7 +956,7 @@ bool CConnman::AttemptToEvictConnection()
{
LOCK(cs_vNodes);
- for (CNode *node : vNodes) {
+ for (const CNode* node : vNodes) {
if (node->fWhitelisted)
continue;
if (!node->fInbound)
@@ -1034,9 +1034,9 @@ bool CConnman::AttemptToEvictConnection()
// Disconnect from the network group with the most connections
NodeId evicted = vEvictionCandidates.front().id;
LOCK(cs_vNodes);
- for(std::vector<CNode*>::const_iterator it(vNodes.begin()); it != vNodes.end(); ++it) {
- if ((*it)->GetId() == evicted) {
- (*it)->fDisconnect = true;
+ for (CNode* pnode : vNodes) {
+ if (pnode->GetId() == evicted) {
+ pnode->fDisconnect = true;
return true;
}
}
@@ -1060,9 +1060,9 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
bool whitelisted = hListenSocket.whitelisted || IsWhitelistedRange(addr);
{
LOCK(cs_vNodes);
- for (CNode* pnode : vNodes)
- if (pnode->fInbound)
- nInbound++;
+ for (const CNode* pnode : vNodes) {
+ if (pnode->fInbound) nInbound++;
+ }
}
if (hSocket == INVALID_SOCKET)
@@ -1114,7 +1114,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addr, CalculateKeyedNetGroup(addr), nonce, addr_bind, "", true);
pnode->AddRef();
pnode->fWhitelisted = whitelisted;
- GetNodeSignals().InitializeNode(pnode, *this);
+ m_msgproc->InitializeNode(pnode);
LogPrint(BCLog::NET, "connection from %s accepted\n", addr.ToString());
@@ -1674,15 +1674,15 @@ void CConnman::ProcessOneShot()
}
}
-void CConnman::ThreadOpenConnections()
+void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
{
// Connect to specific addresses
- if (gArgs.IsArgSet("-connect"))
+ if (!connect.empty())
{
for (int64_t nLoop = 0;; nLoop++)
{
ProcessOneShot();
- for (const std::string& strAddr : gArgs.GetArgs("-connect"))
+ for (const std::string& strAddr : connect)
{
CAddress addr(CService(), NODE_NONE);
OpenNetworkConnection(addr, false, nullptr, strAddr.c_str());
@@ -1854,8 +1854,7 @@ std::vector<AddedNodeInfo> CConnman::GetAddedNodeInfo()
{
LOCK(cs_vAddedNodes);
ret.reserve(vAddedNodes.size());
- for (const std::string& strAddNode : vAddedNodes)
- lAddresses.push_back(strAddNode);
+ std::copy(vAddedNodes.cbegin(), vAddedNodes.cend(), std::back_inserter(lAddresses));
}
@@ -1901,11 +1900,6 @@ std::vector<AddedNodeInfo> CConnman::GetAddedNodeInfo()
void CConnman::ThreadOpenAddedConnections()
{
- {
- LOCK(cs_vAddedNodes);
- vAddedNodes = gArgs.GetArgs("-addnode");
- }
-
while (true)
{
CSemaphoreGrant grant(*semAddnode);
@@ -1966,7 +1960,7 @@ bool CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai
if (fAddnode)
pnode->fAddnode = true;
- GetNodeSignals().InitializeNode(pnode, *this);
+ m_msgproc->InitializeNode(pnode);
{
LOCK(cs_vNodes);
vNodes.push_back(pnode);
@@ -1996,16 +1990,16 @@ void CConnman::ThreadMessageHandler()
continue;
// Receive messages
- bool fMoreNodeWork = GetNodeSignals().ProcessMessages(pnode, *this, flagInterruptMsgProc);
+ bool fMoreNodeWork = m_msgproc->ProcessMessages(pnode, flagInterruptMsgProc);
fMoreWork |= (fMoreNodeWork && !pnode->fPauseSend);
if (flagInterruptMsgProc)
return;
-
// Send messages
{
LOCK(pnode->cs_sendProcessing);
- GetNodeSignals().SendMessages(pnode, *this, flagInterruptMsgProc);
+ m_msgproc->SendMessages(pnode, flagInterruptMsgProc);
}
+
if (flagInterruptMsgProc)
return;
}
@@ -2324,6 +2318,7 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
//
// Start threads
//
+ assert(m_msgproc);
InterruptSocks5(false);
interruptNet.reset();
flagInterruptMsgProc = false;
@@ -2344,9 +2339,16 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
// Initiate outbound connections from -addnode
threadOpenAddedConnections = std::thread(&TraceThread<std::function<void()> >, "addcon", std::function<void()>(std::bind(&CConnman::ThreadOpenAddedConnections, this)));
- // Initiate outbound connections unless connect=0
- if (!gArgs.IsArgSet("-connect") || gArgs.GetArgs("-connect").size() != 1 || gArgs.GetArgs("-connect")[0] != "0")
- threadOpenConnections = std::thread(&TraceThread<std::function<void()> >, "opencon", std::function<void()>(std::bind(&CConnman::ThreadOpenConnections, this)));
+ if (connOptions.m_use_addrman_outgoing && !connOptions.m_specified_outgoing.empty()) {
+ if (clientInterface) {
+ clientInterface->ThreadSafeMessageBox(
+ _("Cannot provide specific connections and have addrman find outgoing connections at the same."),
+ "", CClientUIInterface::MSG_ERROR);
+ }
+ return false;
+ }
+ if (connOptions.m_use_addrman_outgoing || !connOptions.m_specified_outgoing.empty())
+ threadOpenConnections = std::thread(&TraceThread<std::function<void()> >, "opencon", std::function<void()>(std::bind(&CConnman::ThreadOpenConnections, this, connOptions.m_specified_outgoing)));
// Process messages
threadMessageHandler = std::thread(&TraceThread<std::function<void()> >, "msghand", std::function<void()>(std::bind(&CConnman::ThreadMessageHandler, this)));
@@ -2443,9 +2445,10 @@ void CConnman::DeleteNode(CNode* pnode)
{
assert(pnode);
bool fUpdateConnectionTime = false;
- GetNodeSignals().FinalizeNode(pnode->GetId(), fUpdateConnectionTime);
- if(fUpdateConnectionTime)
+ m_msgproc->FinalizeNode(pnode->GetId(), fUpdateConnectionTime);
+ if(fUpdateConnectionTime) {
addrman.Connected(pnode->addr);
+ }
delete pnode;
}
@@ -2483,9 +2486,8 @@ std::vector<CAddress> CConnman::GetAddresses()
bool CConnman::AddNode(const std::string& strNode)
{
LOCK(cs_vAddedNodes);
- for(std::vector<std::string>::const_iterator it = vAddedNodes.begin(); it != vAddedNodes.end(); ++it) {
- if (strNode == *it)
- return false;
+ for (const std::string& it : vAddedNodes) {
+ if (strNode == it) return false;
}
vAddedNodes.push_back(strNode);
@@ -2511,9 +2513,11 @@ size_t CConnman::GetNodeCount(NumConnections flags)
return vNodes.size();
int nNum = 0;
- for(std::vector<CNode*>::const_iterator it = vNodes.begin(); it != vNodes.end(); ++it)
- if (flags & ((*it)->fInbound ? CONNECTIONS_IN : CONNECTIONS_OUT))
+ for (const auto& pnode : vNodes) {
+ if (flags & (pnode->fInbound ? CONNECTIONS_IN : CONNECTIONS_OUT)) {
nNum++;
+ }
+ }
return nNum;
}
@@ -2523,8 +2527,7 @@ void CConnman::GetNodeStats(std::vector<CNodeStats>& vstats)
vstats.clear();
LOCK(cs_vNodes);
vstats.reserve(vNodes.size());
- for(std::vector<CNode*>::iterator it = vNodes.begin(); it != vNodes.end(); ++it) {
- CNode* pnode = *it;
+ for (CNode* pnode : vNodes) {
vstats.emplace_back();
pnode->copyStats(vstats.back());
}
diff --git a/src/net.h b/src/net.h
index a32736aa97..905d6eb956 100644
--- a/src/net.h
+++ b/src/net.h
@@ -33,7 +33,6 @@
#include <arpa/inet.h>
#endif
-#include <boost/signals2/signal.hpp>
class CScheduler;
class CNode;
@@ -116,7 +115,7 @@ struct CSerializedNetMsg
std::string command;
};
-
+class NetEventsInterface;
class CConnman
{
public:
@@ -138,6 +137,7 @@ public:
int nMaxFeeler = 0;
int nBestHeight = 0;
CClientUIInterface* uiInterface = nullptr;
+ NetEventsInterface* m_msgproc = nullptr;
unsigned int nSendBufferMaxSize = 0;
unsigned int nReceiveFloodSize = 0;
uint64_t nMaxOutboundTimeframe = 0;
@@ -145,6 +145,9 @@ public:
std::vector<std::string> vSeedNodes;
std::vector<CSubNet> vWhitelistedRange;
std::vector<CService> vBinds, vWhiteBinds;
+ bool m_use_addrman_outgoing = true;
+ std::vector<std::string> m_specified_outgoing;
+ std::vector<std::string> m_added_nodes;
};
void Init(const Options& connOptions) {
@@ -156,11 +159,13 @@ public:
nMaxFeeler = connOptions.nMaxFeeler;
nBestHeight = connOptions.nBestHeight;
clientInterface = connOptions.uiInterface;
+ m_msgproc = connOptions.m_msgproc;
nSendBufferMaxSize = connOptions.nSendBufferMaxSize;
nReceiveFloodSize = connOptions.nReceiveFloodSize;
nMaxOutboundTimeframe = connOptions.nMaxOutboundTimeframe;
nMaxOutboundLimit = connOptions.nMaxOutboundLimit;
vWhitelistedRange = connOptions.vWhitelistedRange;
+ vAddedNodes = connOptions.m_added_nodes;
}
CConnman(uint64_t seed0, uint64_t seed1);
@@ -308,7 +313,7 @@ private:
void ThreadOpenAddedConnections();
void AddOneShot(const std::string& strDest);
void ProcessOneShot();
- void ThreadOpenConnections();
+ void ThreadOpenConnections(std::vector<std::string> connect);
void ThreadMessageHandler();
void AcceptConnection(const ListenSocket& hListenSocket);
void ThreadSocketHandler();
@@ -396,6 +401,7 @@ private:
int nMaxFeeler;
std::atomic<int> nBestHeight;
CClientUIInterface* clientInterface;
+ NetEventsInterface* m_msgproc;
/** SipHasher seeds for deterministic randomness */
const uint64_t nSeed0, nSeed1;
@@ -436,19 +442,18 @@ struct CombinerAll
}
};
-// Signals for message handling
-struct CNodeSignals
+/**
+ * Interface for message handling
+ */
+class NetEventsInterface
{
- boost::signals2::signal<bool (CNode*, CConnman&, std::atomic<bool>&), CombinerAll> ProcessMessages;
- boost::signals2::signal<bool (CNode*, CConnman&, std::atomic<bool>&), CombinerAll> SendMessages;
- boost::signals2::signal<void (CNode*, CConnman&)> InitializeNode;
- boost::signals2::signal<void (NodeId, bool&)> FinalizeNode;
+public:
+ virtual bool ProcessMessages(CNode* pnode, std::atomic<bool>& interrupt) = 0;
+ virtual bool SendMessages(CNode* pnode, std::atomic<bool>& interrupt) = 0;
+ virtual void InitializeNode(CNode* pnode) = 0;
+ virtual void FinalizeNode(NodeId id, bool& update_connection_time) = 0;
};
-
-CNodeSignals& GetNodeSignals();
-
-
enum
{
LOCAL_NONE, // unknown
@@ -699,13 +704,11 @@ public:
CNode(NodeId id, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress &addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress &addrBindIn, const std::string &addrNameIn = "", bool fInboundIn = false);
~CNode();
+ CNode(const CNode&) = delete;
+ CNode& operator=(const CNode&) = delete;
private:
- CNode(const CNode&);
- void operator=(const CNode&);
const NodeId id;
-
-
const uint64_t nLocalHostNonce;
// Services offered to this peer
const ServiceFlags nLocalServices;
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 596ae1139b..b8900d9888 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -123,11 +123,6 @@ namespace {
std::deque<std::pair<int64_t, MapRelay::iterator>> vRelayExpiration;
} // namespace
-//////////////////////////////////////////////////////////////////////////////
-//
-// Registration of network node signals.
-//
-
namespace {
struct CBlockReject {
@@ -244,7 +239,7 @@ void UpdatePreferredDownload(CNode* node, CNodeState* state)
nPreferredDownload += state->fPreferredDownload;
}
-void PushNodeVersion(CNode *pnode, CConnman& connman, int64_t nTime)
+void PushNodeVersion(CNode *pnode, CConnman* connman, int64_t nTime)
{
ServiceFlags nLocalNodeServices = pnode->GetLocalServices();
uint64_t nonce = pnode->GetLocalNonce();
@@ -255,7 +250,7 @@ void PushNodeVersion(CNode *pnode, CConnman& connman, int64_t nTime)
CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService(), addr.nServices));
CAddress addrMe = CAddress(CService(), nLocalNodeServices);
- connman.PushMessage(pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERSION, PROTOCOL_VERSION, (uint64_t)nLocalNodeServices, nTime, addrYou, addrMe,
+ connman->PushMessage(pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERSION, PROTOCOL_VERSION, (uint64_t)nLocalNodeServices, nTime, addrYou, addrMe,
nonce, strSubVersion, nNodeStartingHeight, ::fRelayTxes));
if (fLogIPs) {
@@ -265,49 +260,6 @@ void PushNodeVersion(CNode *pnode, CConnman& connman, int64_t nTime)
}
}
-void InitializeNode(CNode *pnode, CConnman& connman) {
- CAddress addr = pnode->addr;
- std::string addrName = pnode->GetAddrName();
- NodeId nodeid = pnode->GetId();
- {
- LOCK(cs_main);
- mapNodeState.emplace_hint(mapNodeState.end(), std::piecewise_construct, std::forward_as_tuple(nodeid), std::forward_as_tuple(addr, std::move(addrName)));
- }
- if(!pnode->fInbound)
- PushNodeVersion(pnode, connman, GetTime());
-}
-
-void FinalizeNode(NodeId nodeid, bool& fUpdateConnectionTime) {
- fUpdateConnectionTime = false;
- LOCK(cs_main);
- CNodeState *state = State(nodeid);
-
- if (state->fSyncStarted)
- nSyncStarted--;
-
- if (state->nMisbehavior == 0 && state->fCurrentlyConnected) {
- fUpdateConnectionTime = true;
- }
-
- for (const QueuedBlock& entry : state->vBlocksInFlight) {
- mapBlocksInFlight.erase(entry.hash);
- }
- EraseOrphansFor(nodeid);
- nPreferredDownload -= state->fPreferredDownload;
- nPeersWithValidatedDownloads -= (state->nBlocksInFlightValidHeaders != 0);
- assert(nPeersWithValidatedDownloads >= 0);
-
- mapNodeState.erase(nodeid);
-
- if (mapNodeState.empty()) {
- // Do a consistency check after the last peer is removed.
- assert(mapBlocksInFlight.empty());
- assert(nPreferredDownload == 0);
- assert(nPeersWithValidatedDownloads == 0);
- }
- LogPrint(BCLog::NET, "Cleared nodestate for peer=%d\n", nodeid);
-}
-
// Requires cs_main.
// Returns a bool indicating whether we requested this block.
// Also used if a block was /not/ received and timed out or started with another peer
@@ -315,6 +267,7 @@ bool MarkBlockAsReceived(const uint256& hash) {
std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator> >::iterator itInFlight = mapBlocksInFlight.find(hash);
if (itInFlight != mapBlocksInFlight.end()) {
CNodeState *state = State(itInFlight->second.first);
+ assert(state != nullptr);
state->nBlocksInFlightValidHeaders -= itInFlight->second.second->fValidatedHeaders;
if (state->nBlocksInFlightValidHeaders == 0 && itInFlight->second.second->fValidatedHeaders) {
// Last validated block on the queue was received.
@@ -402,7 +355,7 @@ void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) {
}
}
-void MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid, CConnman& connman) {
+void MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid, CConnman* connman) {
AssertLockHeld(cs_main);
CNodeState* nodestate = State(nodeid);
if (!nodestate || !nodestate->fSupportsDesiredCmpctVersion) {
@@ -417,20 +370,20 @@ void MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid, CConnman& connman) {
return;
}
}
- connman.ForNode(nodeid, [&connman](CNode* pfrom){
+ connman->ForNode(nodeid, [connman](CNode* pfrom){
bool fAnnounceUsingCMPCTBLOCK = false;
uint64_t nCMPCTBLOCKVersion = (pfrom->GetLocalServices() & NODE_WITNESS) ? 2 : 1;
if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
// As per BIP152, we only get 3 of our peers to announce
// blocks using compact encodings.
- connman.ForNode(lNodesAnnouncingHeaderAndIDs.front(), [&connman, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion](CNode* pnodeStop){
- connman.PushMessage(pnodeStop, CNetMsgMaker(pnodeStop->GetSendVersion()).Make(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion));
+ connman->ForNode(lNodesAnnouncingHeaderAndIDs.front(), [connman, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion](CNode* pnodeStop){
+ connman->PushMessage(pnodeStop, CNetMsgMaker(pnodeStop->GetSendVersion()).Make(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion));
return true;
});
lNodesAnnouncingHeaderAndIDs.pop_front();
}
fAnnounceUsingCMPCTBLOCK = true;
- connman.PushMessage(pfrom, CNetMsgMaker(pfrom->GetSendVersion()).Make(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion));
+ connman->PushMessage(pfrom, CNetMsgMaker(pfrom->GetSendVersion()).Make(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion));
lNodesAnnouncingHeaderAndIDs.push_back(pfrom->GetId());
return true;
});
@@ -466,7 +419,7 @@ void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<con
// Make sure pindexBestKnownBlock is up to date, we'll need it.
ProcessBlockAvailability(nodeid);
- if (state->pindexBestKnownBlock == nullptr || state->pindexBestKnownBlock->nChainWork < chainActive.Tip()->nChainWork || state->pindexBestKnownBlock->nChainWork < UintToArith256(consensusParams.nMinimumChainWork)) {
+ if (state->pindexBestKnownBlock == nullptr || state->pindexBestKnownBlock->nChainWork < chainActive.Tip()->nChainWork || state->pindexBestKnownBlock->nChainWork < nMinimumChainWork) {
// This peer has nothing interesting.
return;
}
@@ -543,6 +496,50 @@ void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<con
} // namespace
+void PeerLogicValidation::InitializeNode(CNode *pnode) {
+ CAddress addr = pnode->addr;
+ std::string addrName = pnode->GetAddrName();
+ NodeId nodeid = pnode->GetId();
+ {
+ LOCK(cs_main);
+ mapNodeState.emplace_hint(mapNodeState.end(), std::piecewise_construct, std::forward_as_tuple(nodeid), std::forward_as_tuple(addr, std::move(addrName)));
+ }
+ if(!pnode->fInbound)
+ PushNodeVersion(pnode, connman, GetTime());
+}
+
+void PeerLogicValidation::FinalizeNode(NodeId nodeid, bool& fUpdateConnectionTime) {
+ fUpdateConnectionTime = false;
+ LOCK(cs_main);
+ CNodeState *state = State(nodeid);
+ assert(state != nullptr);
+
+ if (state->fSyncStarted)
+ nSyncStarted--;
+
+ if (state->nMisbehavior == 0 && state->fCurrentlyConnected) {
+ fUpdateConnectionTime = true;
+ }
+
+ for (const QueuedBlock& entry : state->vBlocksInFlight) {
+ mapBlocksInFlight.erase(entry.hash);
+ }
+ EraseOrphansFor(nodeid);
+ nPreferredDownload -= state->fPreferredDownload;
+ nPeersWithValidatedDownloads -= (state->nBlocksInFlightValidHeaders != 0);
+ assert(nPeersWithValidatedDownloads >= 0);
+
+ mapNodeState.erase(nodeid);
+
+ if (mapNodeState.empty()) {
+ // Do a consistency check after the last peer is removed.
+ assert(mapBlocksInFlight.empty());
+ assert(nPreferredDownload == 0);
+ assert(nPeersWithValidatedDownloads == 0);
+ }
+ LogPrint(BCLog::NET, "Cleared nodestate for peer=%d\n", nodeid);
+}
+
bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) {
LOCK(cs_main);
CNodeState *state = State(nodeid);
@@ -558,22 +555,6 @@ bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) {
return true;
}
-void RegisterNodeSignals(CNodeSignals& nodeSignals)
-{
- nodeSignals.ProcessMessages.connect(&ProcessMessages);
- nodeSignals.SendMessages.connect(&SendMessages);
- nodeSignals.InitializeNode.connect(&InitializeNode);
- nodeSignals.FinalizeNode.connect(&FinalizeNode);
-}
-
-void UnregisterNodeSignals(CNodeSignals& nodeSignals)
-{
- nodeSignals.ProcessMessages.disconnect(&ProcessMessages);
- nodeSignals.SendMessages.disconnect(&SendMessages);
- nodeSignals.InitializeNode.disconnect(&InitializeNode);
- nodeSignals.FinalizeNode.disconnect(&FinalizeNode);
-}
-
//////////////////////////////////////////////////////////////////////////////
//
// mapOrphanTransactions
@@ -865,7 +846,7 @@ void PeerLogicValidation::BlockChecked(const CBlock& block, const CValidationSta
!IsInitialBlockDownload() &&
mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
if (it != mapBlockSource.end()) {
- MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first, *connman);
+ MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first, connman);
}
}
if (it != mapBlockSource.end())
@@ -910,16 +891,16 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
return true;
}
-static void RelayTransaction(const CTransaction& tx, CConnman& connman)
+static void RelayTransaction(const CTransaction& tx, CConnman* connman)
{
CInv inv(MSG_TX, tx.GetHash());
- connman.ForEachNode([&inv](CNode* pnode)
+ connman->ForEachNode([&inv](CNode* pnode)
{
pnode->PushInventory(inv);
});
}
-static void RelayAddress(const CAddress& addr, bool fReachable, CConnman& connman)
+static void RelayAddress(const CAddress& addr, bool fReachable, CConnman* connman)
{
unsigned int nRelayNodes = fReachable ? 2 : 1; // limited relaying of addresses outside our network(s)
@@ -927,7 +908,7 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman& connma
// Use deterministic randomness to send to the same nodes for 24 hours
// at a time so the addrKnowns of the chosen nodes prevent repeats
uint64_t hashAddr = addr.GetHash();
- const CSipHasher hasher = connman.GetDeterministicRandomizer(RANDOMIZER_ID_ADDRESS_RELAY).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24*60*60));
+ const CSipHasher hasher = connman->GetDeterministicRandomizer(RANDOMIZER_ID_ADDRESS_RELAY).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24*60*60));
FastRandomContext insecure_rand;
std::array<std::pair<uint64_t, CNode*>,2> best{{{0, nullptr}, {0, nullptr}}};
@@ -952,10 +933,10 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman& connma
}
};
- connman.ForEachNodeThen(std::move(sortfunc), std::move(pushfunc));
+ connman->ForEachNodeThen(std::move(sortfunc), std::move(pushfunc));
}
-void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParams, CConnman& connman, const std::atomic<bool>& interruptMsgProc)
+void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParams, CConnman* connman, const std::atomic<bool>& interruptMsgProc)
{
std::deque<CInv>::iterator it = pfrom->vRecvGetData.begin();
std::vector<CInv> vNotFound;
@@ -1017,7 +998,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
// disconnect node in case we have reached the outbound limit for serving historical blocks
// never disconnect whitelisted nodes
static const int nOneWeek = 7 * 24 * 60 * 60; // assume > 1 week = historical
- if (send && connman.OutboundTargetReached(true) && ( ((pindexBestHeader != nullptr) && (pindexBestHeader->GetBlockTime() - mi->second->GetBlockTime() > nOneWeek)) || inv.type == MSG_FILTERED_BLOCK) && !pfrom->fWhitelisted)
+ if (send && connman->OutboundTargetReached(true) && ( ((pindexBestHeader != nullptr) && (pindexBestHeader->GetBlockTime() - mi->second->GetBlockTime() > nOneWeek)) || inv.type == MSG_FILTERED_BLOCK) && !pfrom->fWhitelisted)
{
LogPrint(BCLog::NET, "historical block serving limit reached, disconnect peer=%d\n", pfrom->GetId());
@@ -1040,9 +1021,9 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
pblock = pblockRead;
}
if (inv.type == MSG_BLOCK)
- connman.PushMessage(pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCK, *pblock));
+ connman->PushMessage(pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCK, *pblock));
else if (inv.type == MSG_WITNESS_BLOCK)
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::BLOCK, *pblock));
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::BLOCK, *pblock));
else if (inv.type == MSG_FILTERED_BLOCK)
{
bool sendMerkleBlock = false;
@@ -1055,7 +1036,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
}
}
if (sendMerkleBlock) {
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::MERKLEBLOCK, merkleBlock));
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::MERKLEBLOCK, merkleBlock));
// CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see
// This avoids hurting performance by pointlessly requiring a round-trip
// Note that there is currently no way for a node to request any single transactions we didn't send here -
@@ -1064,7 +1045,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
// however we MUST always provide at least what the remote peer needs
typedef std::pair<unsigned int, uint256> PairType;
for (PairType& pair : merkleBlock.vMatchedTxn)
- connman.PushMessage(pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::TX, *pblock->vtx[pair.first]));
+ connman->PushMessage(pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::TX, *pblock->vtx[pair.first]));
}
// else
// no response
@@ -1079,13 +1060,13 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
int nSendFlags = fPeerWantsWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS;
if (CanDirectFetch(consensusParams) && mi->second->nHeight >= chainActive.Height() - MAX_CMPCTBLOCK_DEPTH) {
if ((fPeerWantsWitness || !fWitnessesPresentInARecentCompactBlock) && a_recent_compact_block && a_recent_compact_block->header.GetHash() == mi->second->GetBlockHash()) {
- connman.PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, *a_recent_compact_block));
+ connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, *a_recent_compact_block));
} else {
CBlockHeaderAndShortTxIDs cmpctblock(*pblock, fPeerWantsWitness);
- connman.PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, cmpctblock));
+ connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, cmpctblock));
}
} else {
- connman.PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::BLOCK, *pblock));
+ connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::BLOCK, *pblock));
}
}
@@ -1097,7 +1078,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
// wait for other stuff first.
std::vector<CInv> vInv;
vInv.push_back(CInv(MSG_BLOCK, chainActive.Tip()->GetBlockHash()));
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::INV, vInv));
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::INV, vInv));
pfrom->hashContinue.SetNull();
}
}
@@ -1109,14 +1090,14 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
auto mi = mapRelay.find(inv.hash);
int nSendFlags = (inv.type == MSG_TX ? SERIALIZE_TRANSACTION_NO_WITNESS : 0);
if (mi != mapRelay.end()) {
- connman.PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *mi->second));
+ connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *mi->second));
push = true;
} else if (pfrom->timeLastMempoolReq) {
auto txinfo = mempool.info(inv.hash);
// To protect privacy, do not answer getdata using the mempool when
// that TX couldn't have been INVed in reply to a MEMPOOL request.
if (txinfo.tx && txinfo.nTime <= pfrom->timeLastMempoolReq) {
- connman.PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *txinfo.tx));
+ connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *txinfo.tx));
push = true;
}
}
@@ -1143,7 +1124,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
// do that because they want to know about (and store and rebroadcast and
// risk analyze) the dependencies of transactions relevant to them, without
// having to download the entire memory pool.
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::NOTFOUND, vNotFound));
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::NOTFOUND, vNotFound));
}
}
@@ -1155,7 +1136,7 @@ uint32_t GetFetchFlags(CNode* pfrom) {
return nFetchFlags;
}
-inline void static SendBlockTransactions(const CBlock& block, const BlockTransactionsRequest& req, CNode* pfrom, CConnman& connman) {
+inline void static SendBlockTransactions(const CBlock& block, const BlockTransactionsRequest& req, CNode* pfrom, CConnman* connman) {
BlockTransactions resp(req);
for (size_t i = 0; i < req.indexes.size(); i++) {
if (req.indexes[i] >= block.vtx.size()) {
@@ -1169,10 +1150,10 @@ inline void static SendBlockTransactions(const CBlock& block, const BlockTransac
LOCK(cs_main);
const CNetMsgMaker msgMaker(pfrom->GetSendVersion());
int nSendFlags = State(pfrom->GetId())->fWantsCmpctWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS;
- connman.PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::BLOCKTXN, resp));
+ connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::BLOCKTXN, resp));
}
-bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CConnman& connman, const std::atomic<bool>& interruptMsgProc)
+bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CConnman* connman, const std::atomic<bool>& interruptMsgProc)
{
LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->GetId());
if (gArgs.IsArgSet("-dropmessagestest") && GetRand(gArgs.GetArg("-dropmessagestest", 0)) == 0)
@@ -1225,7 +1206,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// Each connection can only send one version message
if (pfrom->nVersion != 0)
{
- connman.PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_DUPLICATE, std::string("Duplicate version message")));
+ connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_DUPLICATE, std::string("Duplicate version message")));
LOCK(cs_main);
Misbehaving(pfrom->GetId(), 1);
return false;
@@ -1249,12 +1230,12 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
nServices = ServiceFlags(nServiceInt);
if (!pfrom->fInbound)
{
- connman.SetServices(pfrom->addr, nServices);
+ connman->SetServices(pfrom->addr, nServices);
}
if (pfrom->nServicesExpected & ~nServices)
{
LogPrint(BCLog::NET, "peer=%d does not offer the expected services (%08x offered, %08x expected); disconnecting\n", pfrom->GetId(), nServices, pfrom->nServicesExpected);
- connman.PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_NONSTANDARD,
+ connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_NONSTANDARD,
strprintf("Expected to offer services %08x", pfrom->nServicesExpected)));
pfrom->fDisconnect = true;
return false;
@@ -1275,7 +1256,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
{
// disconnect from peers older than this proto version
LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->GetId(), nVersion);
- connman.PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE,
+ connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE,
strprintf("Version must be %d or greater", MIN_PEER_PROTO_VERSION)));
pfrom->fDisconnect = true;
return false;
@@ -1295,7 +1276,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (!vRecv.empty())
vRecv >> fRelay;
// Disconnect if we connected to ourself
- if (pfrom->fInbound && !connman.CheckIncomingNonce(nNonce))
+ if (pfrom->fInbound && !connman->CheckIncomingNonce(nNonce))
{
LogPrintf("connected to self at %s, disconnecting\n", pfrom->addr.ToString());
pfrom->fDisconnect = true;
@@ -1311,7 +1292,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (pfrom->fInbound)
PushNodeVersion(pfrom, connman, GetAdjustedTime());
- connman.PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERACK));
+ connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERACK));
pfrom->nServices = nServices;
pfrom->SetAddrLocal(addrMe);
@@ -1362,12 +1343,12 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
}
// Get recent addresses
- if (pfrom->fOneShot || pfrom->nVersion >= CADDR_TIME_VERSION || connman.GetAddressCount() < 1000)
+ if (pfrom->fOneShot || pfrom->nVersion >= CADDR_TIME_VERSION || connman->GetAddressCount() < 1000)
{
- connman.PushMessage(pfrom, CNetMsgMaker(nSendVersion).Make(NetMsgType::GETADDR));
+ connman->PushMessage(pfrom, CNetMsgMaker(nSendVersion).Make(NetMsgType::GETADDR));
pfrom->fGetAddr = true;
}
- connman.MarkAddressGood(pfrom->addr);
+ connman->MarkAddressGood(pfrom->addr);
}
std::string remoteAddr;
@@ -1386,7 +1367,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// If the peer is old enough to have the old alert system, send it the final alert.
if (pfrom->nVersion <= 70012) {
CDataStream finalAlert(ParseHex("60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"), SER_NETWORK, PROTOCOL_VERSION);
- connman.PushMessage(pfrom, CNetMsgMaker(nSendVersion).Make("alert", finalAlert));
+ connman->PushMessage(pfrom, CNetMsgMaker(nSendVersion).Make("alert", finalAlert));
}
// Feeler connections exist only to verify if address is online.
@@ -1424,7 +1405,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// We send this to non-NODE NETWORK peers as well, because even
// non-NODE NETWORK peers can announce blocks (such as pruning
// nodes)
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::SENDHEADERS));
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::SENDHEADERS));
}
if (pfrom->nVersion >= SHORT_IDS_BLOCKS_VERSION) {
// Tell our peer we are willing to provide version 1 or 2 cmpctblocks
@@ -1435,9 +1416,9 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
bool fAnnounceUsingCMPCTBLOCK = false;
uint64_t nCMPCTBLOCKVersion = 2;
if (pfrom->GetLocalServices() & NODE_WITNESS)
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion));
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion));
nCMPCTBLOCKVersion = 1;
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion));
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion));
}
pfrom->fSuccessfullyConnected = true;
}
@@ -1456,7 +1437,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
vRecv >> vAddr;
// Don't want addr from older versions unless seeding
- if (pfrom->nVersion < CADDR_TIME_VERSION && connman.GetAddressCount() > 1000)
+ if (pfrom->nVersion < CADDR_TIME_VERSION && connman->GetAddressCount() > 1000)
return true;
if (vAddr.size() > 1000)
{
@@ -1490,7 +1471,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (fReachable)
vAddrOk.push_back(addr);
}
- connman.AddNewAddresses(vAddrOk, pfrom->addr, 2 * 60 * 60);
+ connman->AddNewAddresses(vAddrOk, pfrom->addr, 2 * 60 * 60);
if (vAddr.size() < 1000)
pfrom->fGetAddr = false;
if (pfrom->fOneShot)
@@ -1568,7 +1549,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// fell back to inv we probably have a reorg which we should get the headers for first,
// we now only provide a getheaders response here. When we receive the headers, we will
// then ask for the blocks we need.
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), inv.hash));
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), inv.hash));
LogPrint(BCLog::NET, "getheaders (%d) %s to peer=%d\n", pindexBestHeader->nHeight, inv.hash.ToString(), pfrom->GetId());
}
}
@@ -1774,7 +1755,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// will re-announce the new block via headers (or compact blocks again)
// in the SendMessages logic.
nodestate->pindexBestHeaderSent = pindex ? pindex : chainActive.Tip();
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::HEADERS, vHeaders));
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::HEADERS, vHeaders));
}
@@ -1955,7 +1936,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
pfrom->GetId(),
FormatStateMessage(state));
if (state.GetRejectCode() > 0 && state.GetRejectCode() < REJECT_INTERNAL) // Never send AcceptToMemoryPool's internal codes over P2P
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(),
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(),
state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash));
if (nDoS > 0) {
Misbehaving(pfrom->GetId(), nDoS);
@@ -1975,7 +1956,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (mapBlockIndex.find(cmpctblock.header.hashPrevBlock) == mapBlockIndex.end()) {
// Doesn't connect (or is genesis), instead of DoSing in AcceptBlockHeader, request deeper headers
if (!IsInitialBlockDownload())
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), uint256()));
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), uint256()));
return true;
}
}
@@ -2030,7 +2011,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// so we just grab the block via normal getdata
std::vector<CInv> vInv(1);
vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(pfrom), cmpctblock.header.GetHash());
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv));
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv));
}
return true;
}
@@ -2074,7 +2055,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// Duplicate txindexes, the block is now in-flight, so just request it
std::vector<CInv> vInv(1);
vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(pfrom), cmpctblock.header.GetHash());
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv));
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv));
return true;
}
@@ -2091,7 +2072,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
fProcessBLOCKTXN = true;
} else {
req.blockhash = pindex->GetBlockHash();
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETBLOCKTXN, req));
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETBLOCKTXN, req));
}
} else {
// This block is either already in flight from a different
@@ -2117,7 +2098,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// mempool will probably be useless - request the block normally
std::vector<CInv> vInv(1);
vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(pfrom), cmpctblock.header.GetHash());
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv));
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv));
return true;
} else {
// If this was an announce-cmpctblock, we want the same treatment as a header message
@@ -2191,7 +2172,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// Might have collided, fall back to getdata now :(
std::vector<CInv> invs;
invs.push_back(CInv(MSG_BLOCK | GetFetchFlags(pfrom), resp.blockhash));
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, invs));
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, invs));
} else {
// Block is either okay, or possibly we received
// READ_STATUS_CHECKBLOCK_FAILED.
@@ -2272,7 +2253,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// nUnconnectingHeaders gets reset back to 0.
if (mapBlockIndex.find(headers[0].hashPrevBlock) == mapBlockIndex.end() && nCount < MAX_BLOCKS_TO_ANNOUNCE) {
nodestate->nUnconnectingHeaders++;
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), uint256()));
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), uint256()));
LogPrint(BCLog::NET, "received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d, nUnconnectingHeaders=%d)\n",
headers[0].GetHash().ToString(),
headers[0].hashPrevBlock.ToString(),
@@ -2327,7 +2308,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// TODO: optimize: if pindexLast is an ancestor of chainActive.Tip or pindexBestHeader, continue
// from there instead.
LogPrint(BCLog::NET, "more getheaders (%d) to end to peer=%d (startheight:%d)\n", pindexLast->nHeight, pfrom->GetId(), pfrom->nStartingHeight);
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexLast), uint256()));
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexLast), uint256()));
}
bool fCanDirectFetch = CanDirectFetch(chainparams.GetConsensus());
@@ -2377,7 +2358,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// In any case, we want to download using a compact block, not a regular one
vGetData[0] = CInv(MSG_CMPCT_BLOCK, vGetData[0].hash);
}
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, vGetData));
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, vGetData));
}
}
}
@@ -2438,7 +2419,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
pfrom->fSentAddr = true;
pfrom->vAddrToSend.clear();
- std::vector<CAddress> vAddr = connman.GetAddresses();
+ std::vector<CAddress> vAddr = connman->GetAddresses();
FastRandomContext insecure_rand;
for (const CAddress &addr : vAddr)
pfrom->PushAddress(addr, insecure_rand);
@@ -2454,7 +2435,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return true;
}
- if (connman.OutboundTargetReached(false) && !pfrom->fWhitelisted)
+ if (connman->OutboundTargetReached(false) && !pfrom->fWhitelisted)
{
LogPrint(BCLog::NET, "mempool request with bandwidth limit reached, disconnect peer=%d\n", pfrom->GetId());
pfrom->fDisconnect = true;
@@ -2483,7 +2464,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// it, if the remote node sends a ping once per second and this node takes 5
// seconds to respond to each, the 5th ping the remote sends would appear to
// return very quickly.
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::PONG, nonce));
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::PONG, nonce));
}
}
@@ -2629,13 +2610,13 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return true;
}
-static bool SendRejectsAndCheckIfBanned(CNode* pnode, CConnman& connman)
+static bool SendRejectsAndCheckIfBanned(CNode* pnode, CConnman* connman)
{
AssertLockHeld(cs_main);
CNodeState &state = *State(pnode->GetId());
for (const CBlockReject& reject : state.rejects) {
- connman.PushMessage(pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, (std::string)NetMsgType::BLOCK, reject.chRejectCode, reject.strRejectReason, reject.hashBlock));
+ connman->PushMessage(pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, (std::string)NetMsgType::BLOCK, reject.chRejectCode, reject.strRejectReason, reject.hashBlock));
}
state.rejects.clear();
@@ -2651,7 +2632,7 @@ static bool SendRejectsAndCheckIfBanned(CNode* pnode, CConnman& connman)
LogPrintf("Warning: not banning local peer %s!\n", pnode->addr.ToString());
else
{
- connman.Ban(pnode->addr, BanReasonNodeMisbehaving);
+ connman->Ban(pnode->addr, BanReasonNodeMisbehaving);
}
}
return true;
@@ -2659,7 +2640,7 @@ static bool SendRejectsAndCheckIfBanned(CNode* pnode, CConnman& connman)
return false;
}
-bool ProcessMessages(CNode* pfrom, CConnman& connman, const std::atomic<bool>& interruptMsgProc)
+bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& interruptMsgProc)
{
const CChainParams& chainparams = Params();
//
@@ -2693,7 +2674,7 @@ bool ProcessMessages(CNode* pfrom, CConnman& connman, const std::atomic<bool>& i
// Just take one message
msgs.splice(msgs.begin(), pfrom->vProcessMsg, pfrom->vProcessMsg.begin());
pfrom->nProcessQueueSize -= msgs.front().vRecv.size() + CMessageHeader::HEADER_SIZE;
- pfrom->fPauseRecv = pfrom->nProcessQueueSize > connman.GetReceiveFloodSize();
+ pfrom->fPauseRecv = pfrom->nProcessQueueSize > connman->GetReceiveFloodSize();
fMoreWork = !pfrom->vProcessMsg.empty();
}
CNetMessage& msg(msgs.front());
@@ -2742,7 +2723,7 @@ bool ProcessMessages(CNode* pfrom, CConnman& connman, const std::atomic<bool>& i
}
catch (const std::ios_base::failure& e)
{
- connman.PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_MALFORMED, std::string("error parsing message")));
+ connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_MALFORMED, std::string("error parsing message")));
if (strstr(e.what(), "end of data"))
{
// Allow exceptions from under-length message on vRecv
@@ -2796,7 +2777,7 @@ public:
}
};
-bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interruptMsgProc)
+bool PeerLogicValidation::SendMessages(CNode* pto, std::atomic<bool>& interruptMsgProc)
{
const Consensus::Params& consensusParams = Params().GetConsensus();
{
@@ -2828,11 +2809,11 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
pto->nPingUsecStart = GetTimeMicros();
if (pto->nVersion > BIP0031_VERSION) {
pto->nPingNonceSent = nonce;
- connman.PushMessage(pto, msgMaker.Make(NetMsgType::PING, nonce));
+ connman->PushMessage(pto, msgMaker.Make(NetMsgType::PING, nonce));
} else {
// Peer is too old to support ping command with nonce, pong will never arrive.
pto->nPingNonceSent = 0;
- connman.PushMessage(pto, msgMaker.Make(NetMsgType::PING));
+ connman->PushMessage(pto, msgMaker.Make(NetMsgType::PING));
}
}
@@ -2867,14 +2848,14 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
// receiver rejects addr messages larger than 1000
if (vAddr.size() >= 1000)
{
- connman.PushMessage(pto, msgMaker.Make(NetMsgType::ADDR, vAddr));
+ connman->PushMessage(pto, msgMaker.Make(NetMsgType::ADDR, vAddr));
vAddr.clear();
}
}
}
pto->vAddrToSend.clear();
if (!vAddr.empty())
- connman.PushMessage(pto, msgMaker.Make(NetMsgType::ADDR, vAddr));
+ connman->PushMessage(pto, msgMaker.Make(NetMsgType::ADDR, vAddr));
// we only send the big addr message once
if (pto->vAddrToSend.capacity() > 40)
pto->vAddrToSend.shrink_to_fit();
@@ -2901,7 +2882,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
if (pindexStart->pprev)
pindexStart = pindexStart->pprev;
LogPrint(BCLog::NET, "initial getheaders (%d) to peer=%d (startheight:%d)\n", pindexStart->nHeight, pto->GetId(), pto->nStartingHeight);
- connman.PushMessage(pto, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexStart), uint256()));
+ connman->PushMessage(pto, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexStart), uint256()));
}
}
@@ -2910,7 +2891,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
// transactions become unconfirmed and spams other nodes.
if (!fReindex && !fImporting && !IsInitialBlockDownload())
{
- GetMainSignals().Broadcast(nTimeBestReceived, &connman);
+ GetMainSignals().Broadcast(nTimeBestReceived, connman);
}
//
@@ -2994,10 +2975,10 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
LOCK(cs_most_recent_block);
if (most_recent_block_hash == pBestIndex->GetBlockHash()) {
if (state.fWantsCmpctWitness || !fWitnessesPresentInMostRecentCompactBlock)
- connman.PushMessage(pto, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, *most_recent_compact_block));
+ connman->PushMessage(pto, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, *most_recent_compact_block));
else {
CBlockHeaderAndShortTxIDs cmpctblock(*most_recent_block, state.fWantsCmpctWitness);
- connman.PushMessage(pto, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, cmpctblock));
+ connman->PushMessage(pto, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, cmpctblock));
}
fGotBlockFromCache = true;
}
@@ -3007,7 +2988,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
bool ret = ReadBlockFromDisk(block, pBestIndex, consensusParams);
assert(ret);
CBlockHeaderAndShortTxIDs cmpctblock(block, state.fWantsCmpctWitness);
- connman.PushMessage(pto, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, cmpctblock));
+ connman->PushMessage(pto, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, cmpctblock));
}
state.pindexBestHeaderSent = pBestIndex;
} else if (state.fPreferHeaders) {
@@ -3020,7 +3001,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
LogPrint(BCLog::NET, "%s: sending header %s to peer=%d\n", __func__,
vHeaders.front().GetHash().ToString(), pto->GetId());
}
- connman.PushMessage(pto, msgMaker.Make(NetMsgType::HEADERS, vHeaders));
+ connman->PushMessage(pto, msgMaker.Make(NetMsgType::HEADERS, vHeaders));
state.pindexBestHeaderSent = pBestIndex;
} else
fRevertToInv = true;
@@ -3066,7 +3047,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
for (const uint256& hash : pto->vInventoryBlockToSend) {
vInv.push_back(CInv(MSG_BLOCK, hash));
if (vInv.size() == MAX_INV_SZ) {
- connman.PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
+ connman->PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
vInv.clear();
}
}
@@ -3112,7 +3093,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
pto->filterInventoryKnown.insert(hash);
vInv.push_back(inv);
if (vInv.size() == MAX_INV_SZ) {
- connman.PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
+ connman->PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
vInv.clear();
}
}
@@ -3178,7 +3159,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
}
}
if (vInv.size() == MAX_INV_SZ) {
- connman.PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
+ connman->PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
vInv.clear();
}
pto->filterInventoryKnown.insert(hash);
@@ -3186,7 +3167,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
}
}
if (!vInv.empty())
- connman.PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
+ connman->PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
// Detect whether we're stalling
nNow = GetTimeMicros();
@@ -3281,7 +3262,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
vGetData.push_back(inv);
if (vGetData.size() >= 1000)
{
- connman.PushMessage(pto, msgMaker.Make(NetMsgType::GETDATA, vGetData));
+ connman->PushMessage(pto, msgMaker.Make(NetMsgType::GETDATA, vGetData));
vGetData.clear();
}
} else {
@@ -3291,7 +3272,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
pto->mapAskFor.erase(pto->mapAskFor.begin());
}
if (!vGetData.empty())
- connman.PushMessage(pto, msgMaker.Make(NetMsgType::GETDATA, vGetData));
+ connman->PushMessage(pto, msgMaker.Make(NetMsgType::GETDATA, vGetData));
//
// Message: feefilter
@@ -3308,7 +3289,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
// We always have a fee filter of at least minRelayTxFee
filterToSend = std::max(filterToSend, ::minRelayTxFee.GetFeePerK());
if (filterToSend != pto->lastSentFeeFilter) {
- connman.PushMessage(pto, msgMaker.Make(NetMsgType::FEEFILTER, filterToSend));
+ connman->PushMessage(pto, msgMaker.Make(NetMsgType::FEEFILTER, filterToSend));
pto->lastSentFeeFilter = filterToSend;
}
pto->nextSendTimeFeeFilter = PoissonNextSend(timeNow, AVG_FEEFILTER_BROADCAST_INTERVAL);
diff --git a/src/net_processing.h b/src/net_processing.h
index f4a43980a5..79745cdd42 100644
--- a/src/net_processing.h
+++ b/src/net_processing.h
@@ -22,22 +22,31 @@ static const unsigned int DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN = 100;
static constexpr int64_t HEADERS_DOWNLOAD_TIMEOUT_BASE = 15 * 60 * 1000000; // 15 minutes
static constexpr int64_t HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER = 1000; // 1ms/header
-/** Register with a network node to receive its signals */
-void RegisterNodeSignals(CNodeSignals& nodeSignals);
-/** Unregister a network node */
-void UnregisterNodeSignals(CNodeSignals& nodeSignals);
-
-class PeerLogicValidation : public CValidationInterface {
+class PeerLogicValidation : public CValidationInterface, public NetEventsInterface {
private:
CConnman* connman;
public:
- explicit PeerLogicValidation(CConnman* connmanIn);
+ explicit PeerLogicValidation(CConnman* connman);
void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected, const std::vector<CTransactionRef>& vtxConflicted) override;
void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override;
void BlockChecked(const CBlock& block, const CValidationState& state) override;
void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr<const CBlock>& pblock) override;
+
+
+ void InitializeNode(CNode* pnode) override;
+ void FinalizeNode(NodeId nodeid, bool& fUpdateConnectionTime) override;
+ /** Process protocol messages received from a given node */
+ bool ProcessMessages(CNode* pfrom, std::atomic<bool>& interrupt) override;
+ /**
+ * Send queued protocol messages to be sent to a give node.
+ *
+ * @param[in] pto The node which we are sending messages to.
+ * @param[in] interrupt Interrupt condition for processing threads
+ * @return True if there is more work to be done
+ */
+ bool SendMessages(CNode* pto, std::atomic<bool>& interrupt) override;
};
struct CNodeStateStats {
@@ -52,16 +61,4 @@ bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats);
/** Increase a node's misbehavior score. */
void Misbehaving(NodeId nodeid, int howmuch);
-/** Process protocol messages received from a given node */
-bool ProcessMessages(CNode* pfrom, CConnman& connman, const std::atomic<bool>& interrupt);
-/**
- * Send queued protocol messages to be sent to a give node.
- *
- * @param[in] pto The node which we are sending messages to.
- * @param[in] connman The connection manager for that node.
- * @param[in] interrupt Interrupt condition for processing threads
- * @return True if there is more work to be done
- */
-bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interrupt);
-
#endif // BITCOIN_NET_PROCESSING_H
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
index 605e3e0696..56912d0375 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -54,23 +54,6 @@ bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
return (txout.nValue < GetDustThreshold(txout, dustRelayFeeIn));
}
- /**
- * Check transaction inputs to mitigate two
- * potential denial-of-service attacks:
- *
- * 1. scriptSigs with extra data stuffed into them,
- * not consumed by scriptPubKey (or P2SH script)
- * 2. P2SH scripts with a crazy number of expensive
- * CHECKSIG/CHECKMULTISIG operations
- *
- * Why bother? To avoid denial-of-service attacks; an attacker
- * can submit a standard HASH... OP_EQUAL transaction,
- * which will get accepted into blocks. The redemption
- * script can be anything; an attacker could use a very
- * expensive-to-check-upon-redemption script like:
- * DUP CHECKSIG DROP ... repeated 100 times... OP_1
- */
-
bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType, const bool witnessEnabled)
{
std::vector<std::vector<unsigned char> > vSolutions;
@@ -160,6 +143,22 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason, const bool witnes
return true;
}
+/**
+ * Check transaction inputs to mitigate two
+ * potential denial-of-service attacks:
+ *
+ * 1. scriptSigs with extra data stuffed into them,
+ * not consumed by scriptPubKey (or P2SH script)
+ * 2. P2SH scripts with a crazy number of expensive
+ * CHECKSIG/CHECKMULTISIG operations
+ *
+ * Why bother? To avoid denial-of-service attacks; an attacker
+ * can submit a standard HASH... OP_EQUAL transaction,
+ * which will get accepted into blocks. The redemption
+ * script can be anything; an attacker could use a very
+ * expensive-to-check-upon-redemption script like:
+ * DUP CHECKSIG DROP ... repeated 100 times... OP_1
+ */
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
{
if (tx.IsCoinBase())
diff --git a/src/policy/policy.h b/src/policy/policy.h
index c06820f84e..ef71dd73bc 100644
--- a/src/policy/policy.h
+++ b/src/policy/policy.h
@@ -16,10 +16,8 @@
class CCoinsViewCache;
class CTxOut;
-/** Default for -blockmaxsize, which controls the maximum size of block the mining code will create **/
-static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000;
/** Default for -blockmaxweight, which controls the range of block weights the mining code will create **/
-static const unsigned int DEFAULT_BLOCK_MAX_WEIGHT = 3000000;
+static const unsigned int DEFAULT_BLOCK_MAX_WEIGHT = MAX_BLOCK_WEIGHT - 4000;
/** Default for -blockmintxfee, which sets the minimum feerate for a transaction in blocks created by mining code **/
static const unsigned int DEFAULT_BLOCK_MIN_TX_FEE = 1000;
/** The maximum weight for transactions we're willing to relay/mine */
diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp
index 9b6a814e1f..e0a106adb9 100644
--- a/src/primitives/transaction.cpp
+++ b/src/primitives/transaction.cpp
@@ -55,7 +55,7 @@ std::string CTxOut::ToString() const
}
CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nLockTime(0) {}
-CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) {}
+CMutableTransaction::CMutableTransaction(const CTransaction& tx) : vin(tx.vin), vout(tx.vout), nVersion(tx.nVersion), nLockTime(tx.nLockTime) {}
uint256 CMutableTransaction::GetHash() const
{
@@ -76,9 +76,9 @@ uint256 CTransaction::GetWitnessHash() const
}
/* For backward compatibility, the hash is initialized to 0. TODO: remove the need for this default constructor entirely. */
-CTransaction::CTransaction() : nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0), hash() {}
-CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime), hash(ComputeHash()) {}
-CTransaction::CTransaction(CMutableTransaction &&tx) : nVersion(tx.nVersion), vin(std::move(tx.vin)), vout(std::move(tx.vout)), nLockTime(tx.nLockTime), hash(ComputeHash()) {}
+CTransaction::CTransaction() : vin(), vout(), nVersion(CTransaction::CURRENT_VERSION), nLockTime(0), hash() {}
+CTransaction::CTransaction(const CMutableTransaction &tx) : vin(tx.vin), vout(tx.vout), nVersion(tx.nVersion), nLockTime(tx.nLockTime), hash(ComputeHash()) {}
+CTransaction::CTransaction(CMutableTransaction &&tx) : vin(std::move(tx.vin)), vout(std::move(tx.vout)), nVersion(tx.nVersion), nLockTime(tx.nLockTime), hash(ComputeHash()) {}
CAmount CTransaction::GetValueOut() const
{
diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h
index 041034bb8b..18d524e23d 100644
--- a/src/primitives/transaction.h
+++ b/src/primitives/transaction.h
@@ -278,9 +278,9 @@ public:
// actually immutable; deserialization and assignment are implemented,
// and bypass the constness. This is safe, as they update the entire
// structure, including the hash.
- const int32_t nVersion;
const std::vector<CTxIn> vin;
const std::vector<CTxOut> vout;
+ const int32_t nVersion;
const uint32_t nLockTime;
private:
@@ -361,9 +361,9 @@ public:
/** A mutable version of CTransaction. */
struct CMutableTransaction
{
- int32_t nVersion;
std::vector<CTxIn> vin;
std::vector<CTxOut> vout;
+ int32_t nVersion;
uint32_t nLockTime;
CMutableTransaction();
diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp
index 2fa032abdc..0eb7ec4306 100644
--- a/src/qt/addresstablemodel.cpp
+++ b/src/qt/addresstablemodel.cpp
@@ -82,14 +82,14 @@ public:
LOCK(wallet->cs_wallet);
for (const std::pair<CTxDestination, CAddressBookData>& item : wallet->mapAddressBook)
{
- const CBitcoinAddress& address = item.first;
- bool fMine = IsMine(*wallet, address.Get());
+ const CTxDestination& address = item.first;
+ bool fMine = IsMine(*wallet, address);
AddressTableEntry::Type addressType = translateTransactionType(
QString::fromStdString(item.second.purpose), fMine);
const std::string& strName = item.second.name;
cachedAddressTable.append(AddressTableEntry(addressType,
QString::fromStdString(strName),
- QString::fromStdString(address.ToString())));
+ QString::fromStdString(EncodeDestination(address))));
}
}
// qLowerBound() and qUpperBound() require our cachedAddressTable list to be sorted in asc order
@@ -246,7 +246,7 @@ bool AddressTableModel::setData(const QModelIndex &index, const QVariant &value,
if(role == Qt::EditRole)
{
LOCK(wallet->cs_wallet); /* For SetAddressBook / DelAddressBook */
- CTxDestination curAddress = CBitcoinAddress(rec->address.toStdString()).Get();
+ CTxDestination curAddress = DecodeDestination(rec->address.toStdString());
if(index.column() == Label)
{
// Do nothing, if old label == new label
@@ -257,7 +257,7 @@ bool AddressTableModel::setData(const QModelIndex &index, const QVariant &value,
}
wallet->SetAddressBook(curAddress, value.toString().toStdString(), strPurpose);
} else if(index.column() == Address) {
- CTxDestination newAddress = CBitcoinAddress(value.toString().toStdString()).Get();
+ CTxDestination newAddress = DecodeDestination(value.toString().toStdString());
// Refuse to set invalid address, set error status and return false
if(boost::get<CNoDestination>(&newAddress))
{
@@ -358,7 +358,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
// Check for duplicate addresses
{
LOCK(wallet->cs_wallet);
- if(wallet->mapAddressBook.count(CBitcoinAddress(strAddress).Get()))
+ if(wallet->mapAddressBook.count(DecodeDestination(strAddress)))
{
editStatus = DUPLICATE_ADDRESS;
return QString();
@@ -384,7 +384,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
return QString();
}
}
- strAddress = CBitcoinAddress(newKey.GetID()).ToString();
+ strAddress = EncodeDestination(newKey.GetID());
}
else
{
@@ -394,7 +394,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
// Add entry
{
LOCK(wallet->cs_wallet);
- wallet->SetAddressBook(CBitcoinAddress(strAddress).Get(), strLabel,
+ wallet->SetAddressBook(DecodeDestination(strAddress), strLabel,
(type == Send ? "send" : "receive"));
}
return QString::fromStdString(strAddress);
@@ -412,7 +412,7 @@ bool AddressTableModel::removeRows(int row, int count, const QModelIndex &parent
}
{
LOCK(wallet->cs_wallet);
- wallet->DelAddressBook(CBitcoinAddress(rec->address.toStdString()).Get());
+ wallet->DelAddressBook(DecodeDestination(rec->address.toStdString()));
}
return true;
}
@@ -423,8 +423,8 @@ QString AddressTableModel::labelForAddress(const QString &address) const
{
{
LOCK(wallet->cs_wallet);
- CBitcoinAddress address_parsed(address.toStdString());
- std::map<CTxDestination, CAddressBookData>::iterator mi = wallet->mapAddressBook.find(address_parsed.Get());
+ CTxDestination destination = DecodeDestination(address.toStdString());
+ std::map<CTxDestination, CAddressBookData>::iterator mi = wallet->mapAddressBook.find(destination);
if (mi != wallet->mapAddressBook.end())
{
return QString::fromStdString(mi->second.name);
diff --git a/src/qt/bitcoinaddressvalidator.cpp b/src/qt/bitcoinaddressvalidator.cpp
index d712705c43..4dd1092806 100644
--- a/src/qt/bitcoinaddressvalidator.cpp
+++ b/src/qt/bitcoinaddressvalidator.cpp
@@ -89,9 +89,9 @@ QValidator::State BitcoinAddressCheckValidator::validate(QString &input, int &po
{
Q_UNUSED(pos);
// Validate the passed Bitcoin address
- CBitcoinAddress addr(input.toStdString());
- if (addr.IsValid())
+ if (IsValidDestinationString(input.toStdString())) {
return QValidator::Acceptable;
+ }
return QValidator::Invalid;
}
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index be2d21daee..dc55141900 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -123,7 +123,11 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *_platformStyle, const NetworkStyle *
spinnerFrame(0),
platformStyle(_platformStyle)
{
- GUIUtil::restoreWindowGeometry("nWindow", QSize(850, 550), this);
+ QSettings settings;
+ if (!restoreGeometry(settings.value("MainWindowGeometry").toByteArray())) {
+ // Restore failed (perhaps missing setting), center the window
+ move(QApplication::desktop()->availableGeometry().center() - frameGeometry().center());
+ }
QString windowTitle = tr(PACKAGE_NAME) + " - ";
#ifdef ENABLE_WALLET
@@ -261,7 +265,8 @@ BitcoinGUI::~BitcoinGUI()
// Unsubscribe from notifications from core
unsubscribeFromCoreSignals();
- GUIUtil::saveWindowGeometry("nWindow", this);
+ QSettings settings;
+ settings.setValue("MainWindowGeometry", saveGeometry());
if(trayIcon) // Hide tray icon, as deleting will let it linger until quit (on Ubuntu)
trayIcon->hide();
#ifdef Q_OS_MAC
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index 562c361799..3ca43eae22 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -660,7 +660,7 @@ void CoinControlDialog::updateView()
QString sAddress = "";
if(ExtractDestination(out.tx->tx->vout[out.i].scriptPubKey, outputAddress))
{
- sAddress = QString::fromStdString(CBitcoinAddress(outputAddress).ToString());
+ sAddress = QString::fromStdString(EncodeDestination(outputAddress));
// if listMode or change => show bitcoin address. In tree mode, address is not shown again for direct wallet address outputs
if (!treeMode || (!(sAddress == sWalletAddress)))
diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui
index 14078b9ee8..e31bfee05e 100644
--- a/src/qt/forms/optionsdialog.ui
+++ b/src/qt/forms/optionsdialog.ui
@@ -199,10 +199,10 @@
<item>
<widget class="QCheckBox" name="allowIncoming">
<property name="toolTip">
- <string>Accept connections from outside</string>
+ <string>Accept connections from outside.</string>
</property>
<property name="text">
- <string>Allow incoming connections</string>
+ <string>Allow incomin&amp;g connections</string>
</property>
</widget>
</item>
@@ -399,7 +399,7 @@
<string>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</string>
</property>
<property name="text">
- <string>Use separate SOCKS5 proxy to reach peers via Tor hidden services:</string>
+ <string>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</string>
</property>
</widget>
</item>
@@ -507,10 +507,10 @@
<item>
<widget class="QCheckBox" name="hideTrayIcon">
<property name="toolTip">
- <string>&amp;Hide the icon from the system tray.</string>
+ <string>Hide the icon from the system tray.</string>
</property>
<property name="text">
- <string>Hide tray icon</string>
+ <string>&amp;Hide tray icon</string>
</property>
</widget>
</item>
@@ -610,7 +610,7 @@
<string>Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |.</string>
</property>
<property name="text">
- <string>Third party transaction URLs</string>
+ <string>&amp;Third party transaction URLs</string>
</property>
<property name="buddy">
<cstring>thirdPartyTxUrls</cstring>
diff --git a/src/qt/forms/sendcoinsdialog.ui b/src/qt/forms/sendcoinsdialog.ui
index 1e2f2302b9..a0e48334c1 100644
--- a/src/qt/forms/sendcoinsdialog.ui
+++ b/src/qt/forms/sendcoinsdialog.ui
@@ -846,19 +846,13 @@
<item>
<layout class="QHBoxLayout" name="horizontalLayoutFee13">
<item>
- <widget class="QRadioButton" name="radioCustomPerKilobyte">
+ <widget class="QLabel" name="labelCustomPerKilobyte">
<property name="toolTip">
<string>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then &quot;per kilobyte&quot; only pays 250 satoshis in fee, while &quot;total at least&quot; pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</string>
</property>
<property name="text">
<string>per kilobyte</string>
</property>
- <property name="checked">
- <bool>true</bool>
- </property>
- <attribute name="buttonGroup">
- <string notr="true">groupCustomFee</string>
- </attribute>
</widget>
</item>
<item>
@@ -1285,6 +1279,5 @@
<connections/>
<buttongroups>
<buttongroup name="groupFee"/>
- <buttongroup name="groupCustomFee"/>
</buttongroups>
</ui>
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index f3c5daebec..b916df69aa 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -112,8 +112,9 @@ static std::string DummyAddress(const CChainParams &params)
sourcedata.insert(sourcedata.end(), dummydata, dummydata + sizeof(dummydata));
for(int i=0; i<256; ++i) { // Try every trailing byte
std::string s = EncodeBase58(sourcedata.data(), sourcedata.data() + sourcedata.size());
- if (!CBitcoinAddress(s).IsValid())
+ if (!IsValidDestinationString(s)) {
return s;
+ }
sourcedata[sourcedata.size()-1] += 1;
}
return "";
@@ -248,7 +249,7 @@ QString formatBitcoinURI(const SendCoinsRecipient &info)
bool isDust(const QString& address, const CAmount& amount)
{
- CTxDestination dest = CBitcoinAddress(address.toStdString()).Get();
+ CTxDestination dest = DecodeDestination(address.toStdString());
CScript script = GetScriptForDestination(dest);
CTxOut txOut(amount, script);
return IsDust(txOut, ::dustRelayFee);
@@ -780,47 +781,64 @@ bool SetStartOnSystemStartup(bool fAutoStart)
LSSharedFileListItemRef findStartupItemInList(LSSharedFileListRef list, CFURLRef findUrl);
LSSharedFileListItemRef findStartupItemInList(LSSharedFileListRef list, CFURLRef findUrl)
{
- // loop through the list of startup items and try to find the bitcoin app
CFArrayRef listSnapshot = LSSharedFileListCopySnapshot(list, nullptr);
+ if (listSnapshot == nullptr) {
+ return nullptr;
+ }
+
+ // loop through the list of startup items and try to find the bitcoin app
for(int i = 0; i < CFArrayGetCount(listSnapshot); i++) {
LSSharedFileListItemRef item = (LSSharedFileListItemRef)CFArrayGetValueAtIndex(listSnapshot, i);
UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes;
CFURLRef currentItemURL = nullptr;
#if defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED >= 10100
- if(&LSSharedFileListItemCopyResolvedURL)
- currentItemURL = LSSharedFileListItemCopyResolvedURL(item, resolutionFlags, nullptr);
+ if(&LSSharedFileListItemCopyResolvedURL)
+ currentItemURL = LSSharedFileListItemCopyResolvedURL(item, resolutionFlags, nullptr);
#if defined(MAC_OS_X_VERSION_MIN_REQUIRED) && MAC_OS_X_VERSION_MIN_REQUIRED < 10100
- else
- LSSharedFileListItemResolve(item, resolutionFlags, &currentItemURL, nullptr);
+ else
+ LSSharedFileListItemResolve(item, resolutionFlags, &currentItemURL, nullptr);
#endif
#else
- LSSharedFileListItemResolve(item, resolutionFlags, &currentItemURL, nullptr);
+ LSSharedFileListItemResolve(item, resolutionFlags, &currentItemURL, nullptr);
#endif
- if(currentItemURL && CFEqual(currentItemURL, findUrl)) {
- // found
- CFRelease(currentItemURL);
- return item;
- }
if(currentItemURL) {
+ if (CFEqual(currentItemURL, findUrl)) {
+ // found
+ CFRelease(listSnapshot);
+ CFRelease(currentItemURL);
+ return item;
+ }
CFRelease(currentItemURL);
}
}
+
+ CFRelease(listSnapshot);
return nullptr;
}
bool GetStartOnSystemStartup()
{
CFURLRef bitcoinAppUrl = CFBundleCopyBundleURL(CFBundleGetMainBundle());
+ if (bitcoinAppUrl == nullptr) {
+ return false;
+ }
+
LSSharedFileListRef loginItems = LSSharedFileListCreate(nullptr, kLSSharedFileListSessionLoginItems, nullptr);
LSSharedFileListItemRef foundItem = findStartupItemInList(loginItems, bitcoinAppUrl);
+
+ CFRelease(bitcoinAppUrl);
return !!foundItem; // return boolified object
}
bool SetStartOnSystemStartup(bool fAutoStart)
{
CFURLRef bitcoinAppUrl = CFBundleCopyBundleURL(CFBundleGetMainBundle());
+ if (bitcoinAppUrl == nullptr) {
+ return false;
+ }
+
LSSharedFileListRef loginItems = LSSharedFileListCreate(nullptr, kLSSharedFileListSessionLoginItems, nullptr);
LSSharedFileListItemRef foundItem = findStartupItemInList(loginItems, bitcoinAppUrl);
@@ -832,6 +850,8 @@ bool SetStartOnSystemStartup(bool fAutoStart)
// remove item
LSSharedFileListItemRemove(loginItems, foundItem);
}
+
+ CFRelease(bitcoinAppUrl);
return true;
}
#pragma GCC diagnostic pop
@@ -842,32 +862,6 @@ bool SetStartOnSystemStartup(bool fAutoStart) { return false; }
#endif
-void saveWindowGeometry(const QString& strSetting, QWidget *parent)
-{
- QSettings settings;
- settings.setValue(strSetting + "Pos", parent->pos());
- settings.setValue(strSetting + "Size", parent->size());
-}
-
-void restoreWindowGeometry(const QString& strSetting, const QSize& defaultSize, QWidget *parent)
-{
- QSettings settings;
- QPoint pos = settings.value(strSetting + "Pos").toPoint();
- QSize size = settings.value(strSetting + "Size", defaultSize).toSize();
-
- parent->resize(size);
- parent->move(pos);
-
- if ((!pos.x() && !pos.y()) || (QApplication::desktop()->screenNumber(parent) == -1))
- {
- QRect screen = QApplication::desktop()->screenGeometry();
- QPoint defaultPos((screen.width() - defaultSize.width()) / 2,
- (screen.height() - defaultSize.height()) / 2);
- parent->resize(defaultSize);
- parent->move(defaultPos);
- }
-}
-
void setClipboard(const QString& str)
{
QApplication::clipboard()->setText(str, QClipboard::Clipboard);
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index d6aa8c4ea6..d10818d0c8 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -179,11 +179,6 @@ namespace GUIUtil
bool GetStartOnSystemStartup();
bool SetStartOnSystemStartup(bool fAutoStart);
- /** Save window size and position */
- void saveWindowGeometry(const QString& strSetting, QWidget *parent);
- /** Restore window size and position */
- void restoreWindowGeometry(const QString& strSetting, const QSize &defaultSizeIn, QWidget *parent);
-
/* Convert QString to OS specific boost path through UTF-8 */
fs::path qstringToBoostPath(const QString &path);
diff --git a/src/qt/macnotificationhandler.h b/src/qt/macnotificationhandler.h
index d4749b3d5f..3a005c3c46 100644
--- a/src/qt/macnotificationhandler.h
+++ b/src/qt/macnotificationhandler.h
@@ -7,20 +7,17 @@
#include <QObject>
-/** Macintosh-specific notification handler (supports UserNotificationCenter and Growl).
+/** Macintosh-specific notification handler (supports UserNotificationCenter).
*/
class MacNotificationHandler : public QObject
{
Q_OBJECT
public:
- /** shows a 10.8+ UserNotification in the UserNotificationCenter
+ /** shows a macOS 10.8+ UserNotification in the UserNotificationCenter
*/
void showNotification(const QString &title, const QString &text);
- /** executes AppleScript */
- void sendAppleScript(const QString &script);
-
/** check if OS can handle UserNotifications */
bool hasUserNotificationCenterSupport(void);
static MacNotificationHandler *instance();
diff --git a/src/qt/macnotificationhandler.mm b/src/qt/macnotificationhandler.mm
index 4c96d08c8a..1b16c5f524 100644
--- a/src/qt/macnotificationhandler.mm
+++ b/src/qt/macnotificationhandler.mm
@@ -47,20 +47,6 @@ void MacNotificationHandler::showNotification(const QString &title, const QStrin
}
}
-// sendAppleScript just take a QString and executes it as apple script
-void MacNotificationHandler::sendAppleScript(const QString &script)
-{
- QByteArray utf8 = script.toUtf8();
- char* cString = (char *)utf8.constData();
- NSString *scriptApple = [[NSString alloc] initWithUTF8String:cString];
-
- NSAppleScript *as = [[NSAppleScript alloc] initWithSource:scriptApple];
- NSDictionary *err = nil;
- [as executeAndReturnError:&err];
- [as release];
- [scriptApple release];
-}
-
bool MacNotificationHandler::hasUserNotificationCenterSupport(void)
{
Class possibleClass = NSClassFromString(@"NSUserNotificationCenter");
diff --git a/src/qt/modaloverlay.cpp b/src/qt/modaloverlay.cpp
index a83f285034..e32a0bdda8 100644
--- a/src/qt/modaloverlay.cpp
+++ b/src/qt/modaloverlay.cpp
@@ -82,36 +82,38 @@ void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVeri
blockProcessTime.push_front(qMakePair(currentDate.toMSecsSinceEpoch(), nVerificationProgress));
// show progress speed if we have more then one sample
- if (blockProcessTime.size() >= 2)
- {
- double progressStart = blockProcessTime[0].second;
+ if (blockProcessTime.size() >= 2) {
double progressDelta = 0;
double progressPerHour = 0;
qint64 timeDelta = 0;
qint64 remainingMSecs = 0;
double remainingProgress = 1.0 - nVerificationProgress;
- for (int i = 1; i < blockProcessTime.size(); i++)
- {
+ for (int i = 1; i < blockProcessTime.size(); i++) {
QPair<qint64, double> sample = blockProcessTime[i];
// take first sample after 500 seconds or last available one
if (sample.first < (currentDate.toMSecsSinceEpoch() - 500 * 1000) || i == blockProcessTime.size() - 1) {
- progressDelta = progressStart-sample.second;
+ progressDelta = blockProcessTime[0].second - sample.second;
timeDelta = blockProcessTime[0].first - sample.first;
- progressPerHour = progressDelta/(double)timeDelta*1000*3600;
- remainingMSecs = remainingProgress / progressDelta * timeDelta;
+ progressPerHour = progressDelta / (double) timeDelta * 1000 * 3600;
+ remainingMSecs = (progressDelta > 0) ? remainingProgress / progressDelta * timeDelta : -1;
break;
}
}
// show progress increase per hour
- ui->progressIncreasePerH->setText(QString::number(progressPerHour*100, 'f', 2)+"%");
+ ui->progressIncreasePerH->setText(QString::number(progressPerHour * 100, 'f', 2)+"%");
// show expected remaining time
- ui->expectedTimeLeft->setText(GUIUtil::formatNiceTimeOffset(remainingMSecs/1000.0));
+ if(remainingMSecs >= 0) {
+ ui->expectedTimeLeft->setText(GUIUtil::formatNiceTimeOffset(remainingMSecs / 1000.0));
+ } else {
+ ui->expectedTimeLeft->setText(QObject::tr("unknown"));
+ }
static const int MAX_SAMPLES = 5000;
- if (blockProcessTime.count() > MAX_SAMPLES)
- blockProcessTime.remove(MAX_SAMPLES, blockProcessTime.count()-MAX_SAMPLES);
+ if (blockProcessTime.count() > MAX_SAMPLES) {
+ blockProcessTime.remove(MAX_SAMPLES, blockProcessTime.count() - MAX_SAMPLES);
+ }
}
// show the last block date
diff --git a/src/qt/notificator.cpp b/src/qt/notificator.cpp
index a7a7a4ce11..937928315b 100644
--- a/src/qt/notificator.cpp
+++ b/src/qt/notificator.cpp
@@ -60,22 +60,6 @@ Notificator::Notificator(const QString &_programName, QSystemTrayIcon *_trayIcon
if( MacNotificationHandler::instance()->hasUserNotificationCenterSupport()) {
mode = UserNotificationCenter;
}
- else {
- // Check if Growl is installed (based on Qt's tray icon implementation)
- CFURLRef cfurl;
- OSStatus status = LSGetApplicationForInfo(kLSUnknownType, kLSUnknownCreator, CFSTR("growlTicket"), kLSRolesAll, 0, &cfurl);
- if (status != kLSApplicationNotFoundErr) {
- CFBundleRef bundle = CFBundleCreate(0, cfurl);
- if (CFStringCompare(CFBundleGetIdentifier(bundle), CFSTR("com.Growl.GrowlHelperApp"), kCFCompareCaseInsensitive | kCFCompareBackwards) == kCFCompareEqualTo) {
- if (CFStringHasSuffix(CFURLGetString(cfurl), CFSTR("/Growl.app/")))
- mode = Growl13;
- else
- mode = Growl12;
- }
- CFRelease(cfurl);
- CFRelease(bundle);
- }
- }
#endif
}
@@ -241,52 +225,6 @@ void Notificator::notifySystray(Class cls, const QString &title, const QString &
// Based on Qt's tray icon implementation
#ifdef Q_OS_MAC
-void Notificator::notifyGrowl(Class cls, const QString &title, const QString &text, const QIcon &icon)
-{
- const QString script(
- "tell application \"%5\"\n"
- " set the allNotificationsList to {\"Notification\"}\n" // -- Make a list of all the notification types (all)
- " set the enabledNotificationsList to {\"Notification\"}\n" // -- Make a list of the notifications (enabled)
- " register as application \"%1\" all notifications allNotificationsList default notifications enabledNotificationsList\n" // -- Register our script with Growl
- " notify with name \"Notification\" title \"%2\" description \"%3\" application name \"%1\"%4\n" // -- Send a Notification
- "end tell"
- );
-
- QString notificationApp(QApplication::applicationName());
- if (notificationApp.isEmpty())
- notificationApp = "Application";
-
- QPixmap notificationIconPixmap;
- if (icon.isNull()) { // If no icon specified, set icon based on class
- QStyle::StandardPixmap sicon = QStyle::SP_MessageBoxQuestion;
- switch (cls)
- {
- case Information: sicon = QStyle::SP_MessageBoxInformation; break;
- case Warning: sicon = QStyle::SP_MessageBoxWarning; break;
- case Critical: sicon = QStyle::SP_MessageBoxCritical; break;
- }
- notificationIconPixmap = QApplication::style()->standardPixmap(sicon);
- }
- else {
- QSize size = icon.actualSize(QSize(48, 48));
- notificationIconPixmap = icon.pixmap(size);
- }
-
- QString notificationIcon;
- QTemporaryFile notificationIconFile;
- if (!notificationIconPixmap.isNull() && notificationIconFile.open()) {
- QImageWriter writer(&notificationIconFile, "PNG");
- if (writer.write(notificationIconPixmap.toImage()))
- notificationIcon = QString(" image from location \"file://%1\"").arg(notificationIconFile.fileName());
- }
-
- QString quotedTitle(title), quotedText(text);
- quotedTitle.replace("\\", "\\\\").replace("\"", "\\");
- quotedText.replace("\\", "\\\\").replace("\"", "\\");
- QString growlApp(this->mode == Notificator::Growl13 ? "Growl" : "GrowlHelperApp");
- MacNotificationHandler::instance()->sendAppleScript(script.arg(notificationApp, quotedTitle, quotedText, notificationIcon, growlApp));
-}
-
void Notificator::notifyMacUserNotificationCenter(Class cls, const QString &title, const QString &text, const QIcon &icon) {
// icon is not supported by the user notification center yet. OSX will use the app icon.
MacNotificationHandler::instance()->showNotification(title, text);
@@ -310,10 +248,6 @@ void Notificator::notify(Class cls, const QString &title, const QString &text, c
case UserNotificationCenter:
notifyMacUserNotificationCenter(cls, title, text, icon);
break;
- case Growl12:
- case Growl13:
- notifyGrowl(cls, title, text, icon);
- break;
#endif
default:
if(cls == Critical)
diff --git a/src/qt/notificator.h b/src/qt/notificator.h
index f92b791d4a..67f2b1df69 100644
--- a/src/qt/notificator.h
+++ b/src/qt/notificator.h
@@ -58,8 +58,6 @@ private:
None, /**< Ignore informational notifications, and show a modal pop-up dialog for Critical notifications. */
Freedesktop, /**< Use DBus org.freedesktop.Notifications */
QSystemTray, /**< Use QSystemTray::showMessage */
- Growl12, /**< Use the Growl 1.2 notification system (Mac only) */
- Growl13, /**< Use the Growl 1.3 notification system (Mac only) */
UserNotificationCenter /**< Use the 10.8+ User Notification Center (Mac only) */
};
QString programName;
@@ -72,7 +70,6 @@ private:
#endif
void notifySystray(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout);
#ifdef Q_OS_MAC
- void notifyGrowl(Class cls, const QString &title, const QString &text, const QIcon &icon);
void notifyMacUserNotificationCenter(Class cls, const QString &title, const QString &text, const QIcon &icon);
#endif
};
diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp
index e9960a01b1..feb00a33b0 100644
--- a/src/qt/optionsmodel.cpp
+++ b/src/qt/optionsmodel.cpp
@@ -151,10 +151,32 @@ void OptionsModel::Init(bool resetSettings)
language = settings.value("language").toString();
}
+/** Helper function to copy contents from one QSettings to another.
+ * By using allKeys this also covers nested settings in a hierarchy.
+ */
+static void CopySettings(QSettings& dst, const QSettings& src)
+{
+ for (const QString& key : src.allKeys()) {
+ dst.setValue(key, src.value(key));
+ }
+}
+
+/** Back up a QSettings to an ini-formatted file. */
+static void BackupSettings(const fs::path& filename, const QSettings& src)
+{
+ qWarning() << "Backing up GUI settings to" << GUIUtil::boostPathToQString(filename);
+ QSettings dst(GUIUtil::boostPathToQString(filename), QSettings::IniFormat);
+ dst.clear();
+ CopySettings(dst, src);
+}
+
void OptionsModel::Reset()
{
QSettings settings;
+ // Backup old settings to chain-specific datadir for troubleshooting
+ BackupSettings(GetDataDir(true) / "guisettings.ini.bak", settings);
+
// Save the strDataDir setting
QString dataDir = Intro::getDefaultDataDirectory();
dataDir = settings.value("strDataDir", dataDir).toString();
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index d4137d280f..169684cf6d 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -218,17 +218,15 @@ void PaymentServer::ipcParseCommandLine(int argc, char* argv[])
SendCoinsRecipient r;
if (GUIUtil::parseBitcoinURI(arg, &r) && !r.address.isEmpty())
{
- CBitcoinAddress address(r.address.toStdString());
auto tempChainParams = CreateChainParams(CBaseChainParams::MAIN);
- if (address.IsValid(*tempChainParams))
- {
+ if (IsValidDestinationString(r.address.toStdString(), *tempChainParams)) {
SelectParams(CBaseChainParams::MAIN);
- }
- else {
+ } else {
tempChainParams = CreateChainParams(CBaseChainParams::TESTNET);
- if (address.IsValid(*tempChainParams))
+ if (IsValidDestinationString(r.address.toStdString(), *tempChainParams)) {
SelectParams(CBaseChainParams::TESTNET);
+ }
}
}
}
@@ -441,8 +439,7 @@ void PaymentServer::handleURIOrFile(const QString& s)
SendCoinsRecipient recipient;
if (GUIUtil::parseBitcoinURI(s, &recipient))
{
- CBitcoinAddress address(recipient.address.toStdString());
- if (!address.IsValid()) {
+ if (!IsValidDestinationString(recipient.address.toStdString())) {
Q_EMIT message(tr("URI handling"), tr("Invalid payment address %1").arg(recipient.address),
CClientUIInterface::MSG_ERROR);
}
@@ -560,7 +557,7 @@ bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, Sen
CTxDestination dest;
if (ExtractDestination(sendingTo.first, dest)) {
// Append destination address
- addresses.append(QString::fromStdString(CBitcoinAddress(dest).ToString()));
+ addresses.append(QString::fromStdString(EncodeDestination(dest)));
}
else if (!recipient.authenticatedMerchant.isEmpty()) {
// Unauthenticated payment requests to custom bitcoin addresses are not supported
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 3590a98efa..d895fc1663 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -28,6 +28,7 @@
#include <wallet/wallet.h>
#endif
+#include <QDesktopWidget>
#include <QKeyEvent>
#include <QMenu>
#include <QMessageBox>
@@ -428,7 +429,11 @@ RPCConsole::RPCConsole(const PlatformStyle *_platformStyle, QWidget *parent) :
consoleFontSize(0)
{
ui->setupUi(this);
- GUIUtil::restoreWindowGeometry("nRPCConsoleWindow", this->size(), this);
+ QSettings settings;
+ if (!restoreGeometry(settings.value("RPCConsoleWindowGeometry").toByteArray())) {
+ // Restore failed (perhaps missing setting), center the window
+ move(QApplication::desktop()->availableGeometry().center() - frameGeometry().center());
+ }
ui->openDebugLogfileButton->setToolTip(ui->openDebugLogfileButton->toolTip().arg(tr(PACKAGE_NAME)));
@@ -466,14 +471,14 @@ RPCConsole::RPCConsole(const PlatformStyle *_platformStyle, QWidget *parent) :
ui->detailWidget->hide();
ui->peerHeading->setText(tr("Select a peer to view detailed information."));
- QSettings settings;
consoleFontSize = settings.value(fontSizeSettingsKey, QFontInfo(QFont()).pointSize()).toInt();
clear();
}
RPCConsole::~RPCConsole()
{
- GUIUtil::saveWindowGeometry("nRPCConsoleWindow", this);
+ QSettings settings;
+ settings.setValue("RPCConsoleWindowGeometry", saveGeometry());
RPCUnsetTimerInterface(rpcTimerInterface);
delete rpcTimerInterface;
delete ui;
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index 625e435742..6309070fef 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -114,10 +114,6 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *p
settings.setValue("nFeeRadio", 1); // custom
if (!settings.contains("nFeeRadio"))
settings.setValue("nFeeRadio", 0); // recommended
- if (!settings.contains("nCustomFeeRadio") && settings.contains("nTransactionFee") && settings.value("nTransactionFee").toLongLong() > 0) // compatibility
- settings.setValue("nCustomFeeRadio", 1); // total at least
- if (!settings.contains("nCustomFeeRadio"))
- settings.setValue("nCustomFeeRadio", 0); // per kilobyte
if (!settings.contains("nSmartFeeSliderPosition"))
settings.setValue("nSmartFeeSliderPosition", 0);
if (!settings.contains("nTransactionFee"))
@@ -127,8 +123,6 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *p
ui->groupFee->setId(ui->radioSmartFee, 0);
ui->groupFee->setId(ui->radioCustomFee, 1);
ui->groupFee->button((int)std::max(0, std::min(1, settings.value("nFeeRadio").toInt())))->setChecked(true);
- ui->groupCustomFee->setId(ui->radioCustomPerKilobyte, 0);
- ui->groupCustomFee->button((int)std::max(0, std::min(1, settings.value("nCustomFeeRadio").toInt())))->setChecked(true);
ui->customFee->setValue(settings.value("nTransactionFee").toLongLong());
ui->checkBoxMinimumFee->setChecked(settings.value("fPayOnlyMinFee").toBool());
minimizeFeeSection(settings.value("fFeeSectionMinimized").toBool());
@@ -178,7 +172,6 @@ void SendCoinsDialog::setModel(WalletModel *_model)
connect(ui->confTargetSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(coinControlUpdateLabels()));
connect(ui->groupFee, SIGNAL(buttonClicked(int)), this, SLOT(updateFeeSectionControls()));
connect(ui->groupFee, SIGNAL(buttonClicked(int)), this, SLOT(coinControlUpdateLabels()));
- connect(ui->groupCustomFee, SIGNAL(buttonClicked(int)), this, SLOT(coinControlUpdateLabels()));
connect(ui->customFee, SIGNAL(valueChanged()), this, SLOT(coinControlUpdateLabels()));
connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(setMinimumFee()));
connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(updateFeeSectionControls()));
@@ -214,7 +207,6 @@ SendCoinsDialog::~SendCoinsDialog()
QSettings settings;
settings.setValue("fFeeSectionMinimized", fFeeMinimized);
settings.setValue("nFeeRadio", ui->groupFee->checkedId());
- settings.setValue("nCustomFeeRadio", ui->groupCustomFee->checkedId());
settings.setValue("nConfTarget", getConfTargetForIndex(ui->confTargetSelector->currentIndex()));
settings.setValue("nTransactionFee", (qint64)ui->customFee->value());
settings.setValue("fPayOnlyMinFee", ui->checkBoxMinimumFee->isChecked());
@@ -609,7 +601,6 @@ void SendCoinsDialog::on_buttonMinimizeFee_clicked()
void SendCoinsDialog::setMinimumFee()
{
- ui->radioCustomPerKilobyte->setChecked(true);
ui->customFee->setValue(GetRequiredFee(1000));
}
@@ -622,7 +613,7 @@ void SendCoinsDialog::updateFeeSectionControls()
ui->labelFeeEstimation ->setEnabled(ui->radioSmartFee->isChecked());
ui->checkBoxMinimumFee ->setEnabled(ui->radioCustomFee->isChecked());
ui->labelMinFeeWarning ->setEnabled(ui->radioCustomFee->isChecked());
- ui->radioCustomPerKilobyte ->setEnabled(ui->radioCustomFee->isChecked() && !ui->checkBoxMinimumFee->isChecked());
+ ui->labelCustomPerKilobyte ->setEnabled(ui->radioCustomFee->isChecked() && !ui->checkBoxMinimumFee->isChecked());
ui->customFee ->setEnabled(ui->radioCustomFee->isChecked() && !ui->checkBoxMinimumFee->isChecked());
}
@@ -634,8 +625,7 @@ void SendCoinsDialog::updateFeeMinimizedLabel()
if (ui->radioSmartFee->isChecked())
ui->labelFeeMinimized->setText(ui->labelSmartFee->text());
else {
- ui->labelFeeMinimized->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), ui->customFee->value()) +
- ((ui->radioCustomPerKilobyte->isChecked()) ? "/kB" : ""));
+ ui->labelFeeMinimized->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), ui->customFee->value()) + "/kB");
}
}
@@ -777,22 +767,19 @@ void SendCoinsDialog::coinControlChangeEdited(const QString& text)
CoinControlDialog::coinControl->destChange = CNoDestination();
ui->labelCoinControlChangeLabel->setStyleSheet("QLabel{color:red;}");
- CBitcoinAddress addr = CBitcoinAddress(text.toStdString());
+ const CTxDestination dest = DecodeDestination(text.toStdString());
if (text.isEmpty()) // Nothing entered
{
ui->labelCoinControlChangeLabel->setText("");
}
- else if (!addr.IsValid()) // Invalid address
+ else if (!IsValidDestination(dest)) // Invalid address
{
ui->labelCoinControlChangeLabel->setText(tr("Warning: Invalid Bitcoin address"));
}
else // Valid address
{
- CKeyID keyid;
- addr.GetKeyID(keyid);
- if (!model->havePrivKey(keyid)) // Unknown change address
- {
+ if (!model->IsSpendable(dest)) {
ui->labelCoinControlChangeLabel->setText(tr("Warning: Unknown change address"));
// confirmation dialog
@@ -800,7 +787,7 @@ void SendCoinsDialog::coinControlChangeEdited(const QString& text)
QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel);
if(btnRetVal == QMessageBox::Yes)
- CoinControlDialog::coinControl->destChange = addr.Get();
+ CoinControlDialog::coinControl->destChange = dest;
else
{
ui->lineEditCoinControlChange->setText("");
@@ -819,7 +806,7 @@ void SendCoinsDialog::coinControlChangeEdited(const QString& text)
else
ui->labelCoinControlChangeLabel->setText(tr("(no label)"));
- CoinControlDialog::coinControl->destChange = addr.Get();
+ CoinControlDialog::coinControl->destChange = dest;
}
}
}
diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp
index 0950ed0234..cba9d4da38 100644
--- a/src/qt/signverifymessagedialog.cpp
+++ b/src/qt/signverifymessagedialog.cpp
@@ -117,16 +117,14 @@ void SignVerifyMessageDialog::on_signMessageButton_SM_clicked()
/* Clear old signature to ensure users don't get confused on error with an old signature displayed */
ui->signatureOut_SM->clear();
- CBitcoinAddress addr(ui->addressIn_SM->text().toStdString());
- if (!addr.IsValid())
- {
+ CTxDestination destination = DecodeDestination(ui->addressIn_SM->text().toStdString());
+ if (!IsValidDestination(destination)) {
ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
ui->statusLabel_SM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again."));
return;
}
- CKeyID keyID;
- if (!addr.GetKeyID(keyID))
- {
+ const CKeyID* keyID = boost::get<CKeyID>(&destination);
+ if (!keyID) {
ui->addressIn_SM->setValid(false);
ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
ui->statusLabel_SM->setText(tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again."));
@@ -142,7 +140,7 @@ void SignVerifyMessageDialog::on_signMessageButton_SM_clicked()
}
CKey key;
- if (!model->getPrivKey(keyID, key))
+ if (!model->getPrivKey(*keyID, key))
{
ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
ui->statusLabel_SM->setText(tr("Private key for the entered address is not available."));
@@ -164,7 +162,7 @@ void SignVerifyMessageDialog::on_signMessageButton_SM_clicked()
ui->statusLabel_SM->setStyleSheet("QLabel { color: green; }");
ui->statusLabel_SM->setText(QString("<nobr>") + tr("Message signed.") + QString("</nobr>"));
- ui->signatureOut_SM->setText(QString::fromStdString(EncodeBase64(&vchSig[0], vchSig.size())));
+ ui->signatureOut_SM->setText(QString::fromStdString(EncodeBase64(vchSig.data(), vchSig.size())));
}
void SignVerifyMessageDialog::on_copySignatureButton_SM_clicked()
@@ -197,16 +195,13 @@ void SignVerifyMessageDialog::on_addressBookButton_VM_clicked()
void SignVerifyMessageDialog::on_verifyMessageButton_VM_clicked()
{
- CBitcoinAddress addr(ui->addressIn_VM->text().toStdString());
- if (!addr.IsValid())
- {
+ CTxDestination destination = DecodeDestination(ui->addressIn_VM->text().toStdString());
+ if (!IsValidDestination(destination)) {
ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
ui->statusLabel_VM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again."));
return;
}
- CKeyID keyID;
- if (!addr.GetKeyID(keyID))
- {
+ if (!boost::get<CKeyID>(&destination)) {
ui->addressIn_VM->setValid(false);
ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
ui->statusLabel_VM->setText(tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again."));
@@ -237,8 +232,7 @@ void SignVerifyMessageDialog::on_verifyMessageButton_VM_clicked()
return;
}
- if (!(CBitcoinAddress(pubkey.GetID()) == addr))
- {
+ if (!(CTxDestination(pubkey.GetID()) == destination)) {
ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
ui->statusLabel_VM->setText(QString("<nobr>") + tr("Message verification failed.") + QString("</nobr>"));
return;
diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp
index 1b7cc69231..a1fbba963c 100644
--- a/src/qt/splashscreen.cpp
+++ b/src/qt/splashscreen.cpp
@@ -142,8 +142,8 @@ SplashScreen::~SplashScreen()
bool SplashScreen::eventFilter(QObject * obj, QEvent * ev) {
if (ev->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev);
- if(keyEvent->text()[0] == 'q' && breakAction != nullptr) {
- breakAction();
+ if(keyEvent->text()[0] == 'q') {
+ StartShutdown();
}
}
return QObject::eventFilter(obj, ev);
@@ -170,27 +170,18 @@ static void InitMessage(SplashScreen *splash, const std::string &message)
Q_ARG(QColor, QColor(55,55,55)));
}
-static void ShowProgress(SplashScreen *splash, const std::string &title, int nProgress)
+static void ShowProgress(SplashScreen *splash, const std::string &title, int nProgress, bool resume_possible)
{
- InitMessage(splash, title + strprintf("%d", nProgress) + "%");
-}
-
-void SplashScreen::setBreakAction(const std::function<void(void)> &action)
-{
- breakAction = action;
-}
-
-static void SetProgressBreakAction(SplashScreen *splash, const std::function<void(void)> &action)
-{
- QMetaObject::invokeMethod(splash, "setBreakAction",
- Qt::QueuedConnection,
- Q_ARG(std::function<void(void)>, action));
+ InitMessage(splash, title + std::string("\n") +
+ (resume_possible ? _("(press q to shutdown and continue later)")
+ : _("press q to shutdown")) +
+ strprintf("\n%d", nProgress) + "%");
}
#ifdef ENABLE_WALLET
void SplashScreen::ConnectWallet(CWallet* wallet)
{
- wallet->ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2));
+ wallet->ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2, false));
connectedWallets.push_back(wallet);
}
#endif
@@ -199,8 +190,7 @@ void SplashScreen::subscribeToCoreSignals()
{
// Connect signals to client
uiInterface.InitMessage.connect(boost::bind(InitMessage, this, _1));
- uiInterface.ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2));
- uiInterface.SetProgressBreakAction.connect(boost::bind(SetProgressBreakAction, this, _1));
+ uiInterface.ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2, _3));
#ifdef ENABLE_WALLET
uiInterface.LoadWallet.connect(boost::bind(&SplashScreen::ConnectWallet, this, _1));
#endif
@@ -210,10 +200,10 @@ void SplashScreen::unsubscribeFromCoreSignals()
{
// Disconnect signals from client
uiInterface.InitMessage.disconnect(boost::bind(InitMessage, this, _1));
- uiInterface.ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2));
+ uiInterface.ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2, _3));
#ifdef ENABLE_WALLET
for (CWallet* const & pwallet : connectedWallets) {
- pwallet->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2));
+ pwallet->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2, false));
}
#endif
}
diff --git a/src/qt/splashscreen.h b/src/qt/splashscreen.h
index a88ebb98a8..c6cfd503f7 100644
--- a/src/qt/splashscreen.h
+++ b/src/qt/splashscreen.h
@@ -36,8 +36,6 @@ public Q_SLOTS:
/** Show message and progress */
void showMessage(const QString &message, int alignment, const QColor &color);
- /** Sets the break action */
- void setBreakAction(const std::function<void(void)> &action);
protected:
bool eventFilter(QObject * obj, QEvent * ev);
@@ -55,8 +53,6 @@ private:
int curAlignment;
QList<CWallet*> connectedWallets;
-
- std::function<void(void)> breakAction;
};
#endif // BITCOIN_QT_SPLASHSCREEN_H
diff --git a/src/qt/test/paymentservertests.cpp b/src/qt/test/paymentservertests.cpp
index c7830071ed..273bd10487 100644
--- a/src/qt/test/paymentservertests.cpp
+++ b/src/qt/test/paymentservertests.cpp
@@ -24,7 +24,7 @@ X509 *parse_b64der_cert(const char* cert_data)
{
std::vector<unsigned char> data = DecodeBase64(cert_data);
assert(data.size() > 0);
- const unsigned char* dptr = &data[0];
+ const unsigned char* dptr = data.data();
X509 *cert = d2i_X509(nullptr, &dptr, data.size());
assert(cert);
return cert;
@@ -43,7 +43,7 @@ static SendCoinsRecipient handleRequest(PaymentServer* server, std::vector<unsig
// Write data to a temp file:
QTemporaryFile f;
f.open();
- f.write((const char*)&data[0], data.size());
+ f.write((const char*)data.data(), data.size());
f.close();
// Create a QObject, install event filter from PaymentServer
@@ -139,7 +139,7 @@ void PaymentServerTests::paymentServerTests()
// Contains a testnet paytoaddress, so payment request network doesn't match client network:
data = DecodeBase64(paymentrequest1_cert2_BASE64);
- byteArray = QByteArray((const char*)&data[0], data.size());
+ byteArray = QByteArray((const char*)data.data(), data.size());
r.paymentRequest.parse(byteArray);
// Ensure the request is initialized, because network "main" is default, even for
// uninitialized payment requests and that will fail our test here.
@@ -148,7 +148,7 @@ void PaymentServerTests::paymentServerTests()
// Expired payment request (expires is set to 1 = 1970-01-01 00:00:01):
data = DecodeBase64(paymentrequest2_cert2_BASE64);
- byteArray = QByteArray((const char*)&data[0], data.size());
+ byteArray = QByteArray((const char*)data.data(), data.size());
r.paymentRequest.parse(byteArray);
// Ensure the request is initialized
QVERIFY(r.paymentRequest.IsInitialized());
@@ -159,7 +159,7 @@ void PaymentServerTests::paymentServerTests()
// 9223372036854775807 (uint64), 9223372036854775807 (int64_t) and -1 (int32_t)
// -1 is 1969-12-31 23:59:59 (for a 32 bit time values)
data = DecodeBase64(paymentrequest3_cert2_BASE64);
- byteArray = QByteArray((const char*)&data[0], data.size());
+ byteArray = QByteArray((const char*)data.data(), data.size());
r.paymentRequest.parse(byteArray);
// Ensure the request is initialized
QVERIFY(r.paymentRequest.IsInitialized());
@@ -170,7 +170,7 @@ void PaymentServerTests::paymentServerTests()
// 9223372036854775808 (uint64), -9223372036854775808 (int64_t) and 0 (int32_t)
// 0 is 1970-01-01 00:00:00 (for a 32 bit time values)
data = DecodeBase64(paymentrequest4_cert2_BASE64);
- byteArray = QByteArray((const char*)&data[0], data.size());
+ byteArray = QByteArray((const char*)data.data(), data.size());
r.paymentRequest.parse(byteArray);
// Ensure the request is initialized
QVERIFY(r.paymentRequest.IsInitialized());
@@ -190,7 +190,7 @@ void PaymentServerTests::paymentServerTests()
// Payment request with amount overflow (amount is set to 21000001 BTC):
data = DecodeBase64(paymentrequest5_cert2_BASE64);
- byteArray = QByteArray((const char*)&data[0], data.size());
+ byteArray = QByteArray((const char*)data.data(), data.size());
r.paymentRequest.parse(byteArray);
// Ensure the request is initialized
QVERIFY(r.paymentRequest.IsInitialized());
diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp
index cd9ab23457..70fdd4bf58 100644
--- a/src/qt/test/rpcnestedtests.cpp
+++ b/src/qt/test/rpcnestedtests.cpp
@@ -11,7 +11,6 @@
#include "rpc/register.h"
#include "rpc/server.h"
#include "rpcconsole.h"
-#include "test/testutil.h"
#include "test/test_bitcoin.h"
#include "univalue.h"
#include "util.h"
@@ -29,7 +28,7 @@ static UniValue rpcNestedTest_rpc(const JSONRPCRequest& request)
static const CRPCCommand vRPCCommands[] =
{
- { "test", "rpcNestedTest", &rpcNestedTest_rpc, true, {} },
+ { "test", "rpcNestedTest", &rpcNestedTest_rpc, {} },
};
void RPCNestedTests::rpcNestedTests()
@@ -37,11 +36,6 @@ void RPCNestedTests::rpcNestedTests()
// do some test setup
// could be moved to a more generic place when we add more tests on QT level
tableRPC.appendCommand("rpcNestedTest", &vRPCCommands[0]);
- ClearDatadirCache();
- std::string path = QDir::tempPath().toStdString() + "/" + strprintf("test_bitcoin_qt_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000)));
- QDir dir(QString::fromStdString(path));
- dir.mkpath(".");
- gArgs.ForceSetArg("-datadir", path);
//mempool.setSanityCheck(1.0);
TestingSetup test;
@@ -136,6 +130,4 @@ void RPCNestedTests::rpcNestedTests()
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest(abc,,abc)"), std::runtime_error); //don't tollerate empty arguments when using ,
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest(abc,,)"), std::runtime_error); //don't tollerate empty arguments when using ,
#endif
-
- fs::remove_all(fs::path(path));
}
diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp
index 80a00a634a..4c04e67ccc 100644
--- a/src/qt/test/test_main.cpp
+++ b/src/qt/test/test_main.cpp
@@ -53,6 +53,10 @@ int main(int argc, char *argv[])
SetupNetworking();
SelectParams(CBaseChainParams::MAIN);
noui_connect();
+ ClearDatadirCache();
+ fs::path pathTemp = fs::temp_directory_path() / strprintf("test_bitcoin-qt_%lu_%i", (unsigned long)GetTime(), (int)GetRand(100000));
+ fs::create_directories(pathTemp);
+ gArgs.ForceSetArg("-datadir", pathTemp.string());
bool fInvalid = false;
@@ -97,5 +101,7 @@ int main(int argc, char *argv[])
}
#endif
+ fs::remove_all(pathTemp);
+
return fInvalid;
}
diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp
index ff1eb59f16..5031d7651d 100644
--- a/src/qt/test/wallettests.cpp
+++ b/src/qt/test/wallettests.cpp
@@ -57,11 +57,11 @@ void ConfirmSend(QString* text = nullptr, bool cancel = false)
}
//! Send coins to address and return txid.
-uint256 SendCoins(CWallet& wallet, SendCoinsDialog& sendCoinsDialog, const CBitcoinAddress& address, CAmount amount, bool rbf)
+uint256 SendCoins(CWallet& wallet, SendCoinsDialog& sendCoinsDialog, const CTxDestination& address, CAmount amount, bool rbf)
{
QVBoxLayout* entries = sendCoinsDialog.findChild<QVBoxLayout*>("entries");
SendCoinsEntry* entry = qobject_cast<SendCoinsEntry*>(entries->itemAt(0)->widget());
- entry->findChild<QValidatedLineEdit*>("payTo")->setText(QString::fromStdString(address.ToString()));
+ entry->findChild<QValidatedLineEdit*>("payTo")->setText(QString::fromStdString(EncodeDestination(address)));
entry->findChild<BitcoinAmountField*>("payAmount")->setValue(amount);
sendCoinsDialog.findChild<QFrame*>("frameFee")
->findChild<QFrame*>("frameFeeSelection")
@@ -172,8 +172,8 @@ void TestSendCoins()
// Send two transactions, and verify they are added to transaction list.
TransactionTableModel* transactionTableModel = walletModel.getTransactionTableModel();
QCOMPARE(transactionTableModel->rowCount({}), 105);
- uint256 txid1 = SendCoins(wallet, sendCoinsDialog, CBitcoinAddress(CKeyID()), 5 * COIN, false /* rbf */);
- uint256 txid2 = SendCoins(wallet, sendCoinsDialog, CBitcoinAddress(CKeyID()), 10 * COIN, true /* rbf */);
+ uint256 txid1 = SendCoins(wallet, sendCoinsDialog, CKeyID(), 5 * COIN, false /* rbf */);
+ uint256 txid2 = SendCoins(wallet, sendCoinsDialog, CKeyID(), 10 * COIN, true /* rbf */);
QCOMPARE(transactionTableModel->rowCount({}), 107);
QVERIFY(FindTx(*transactionTableModel, txid1).isValid());
QVERIFY(FindTx(*transactionTableModel, txid2).isValid());
diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp
index bcacc47ef3..74f5c774a0 100644
--- a/src/qt/transactiondesc.cpp
+++ b/src/qt/transactiondesc.cpp
@@ -91,9 +91,8 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
if (nNet > 0)
{
// Credit
- if (CBitcoinAddress(rec->address).IsValid())
- {
- CTxDestination address = CBitcoinAddress(rec->address).Get();
+ CTxDestination address = DecodeDestination(rec->address);
+ if (IsValidDestination(address)) {
if (wallet->mapAddressBook.count(address))
{
strHTML += "<b>" + tr("From") + ":</b> " + tr("unknown") + "<br>";
@@ -118,7 +117,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
// Online transaction
std::string strAddress = wtx.mapValue["to"];
strHTML += "<b>" + tr("To") + ":</b> ";
- CTxDestination dest = CBitcoinAddress(strAddress).Get();
+ CTxDestination dest = DecodeDestination(strAddress);
if (wallet->mapAddressBook.count(dest) && !wallet->mapAddressBook[dest].name.empty())
strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[dest].name) + " ";
strHTML += GUIUtil::HtmlEscape(strAddress) + "<br>";
@@ -189,7 +188,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
strHTML += "<b>" + tr("To") + ":</b> ";
if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].name.empty())
strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " ";
- strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString());
+ strHTML += GUIUtil::HtmlEscape(EncodeDestination(address));
if(toSelf == ISMINE_SPENDABLE)
strHTML += " (own address)";
else if(toSelf & ISMINE_WATCH_ONLY)
@@ -304,7 +303,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
{
if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].name.empty())
strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " ";
- strHTML += QString::fromStdString(CBitcoinAddress(address).ToString());
+ strHTML += QString::fromStdString(EncodeDestination(address));
}
strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatHtmlWithUnit(unit, vout.nValue);
strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) & ISMINE_SPENDABLE ? tr("true") : tr("false")) + "</li>";
diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp
index 36d98ce49d..d40ffd22cd 100644
--- a/src/qt/transactionrecord.cpp
+++ b/src/qt/transactionrecord.cpp
@@ -55,7 +55,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
{
// Received by Bitcoin Address
sub.type = TransactionRecord::RecvWithAddress;
- sub.address = CBitcoinAddress(address).ToString();
+ sub.address = EncodeDestination(address);
}
else
{
@@ -127,7 +127,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
{
// Sent to Bitcoin Address
sub.type = TransactionRecord::SendToAddress;
- sub.address = CBitcoinAddress(address).ToString();
+ sub.address = EncodeDestination(address);
}
else
{
diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp
index f3183320f0..714a594318 100644
--- a/src/qt/walletframe.cpp
+++ b/src/qt/walletframe.cpp
@@ -7,6 +7,7 @@
#include "bitcoingui.h"
#include "walletview.h"
+#include <cassert>
#include <cstdio>
#include <QHBoxLayout>
@@ -69,6 +70,7 @@ bool WalletFrame::setCurrentWallet(const QString& name)
WalletView *walletView = mapWalletViews.value(name);
walletStack->setCurrentWidget(walletView);
+ assert(walletView);
walletView->updateEncryptionStatus();
return true;
}
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index 445d00e9c8..53b1c2967c 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -188,8 +188,7 @@ void WalletModel::updateWatchOnlyFlag(bool fHaveWatchonly)
bool WalletModel::validateAddress(const QString &address)
{
- CBitcoinAddress addressParsed(address.toStdString());
- return addressParsed.IsValid();
+ return IsValidDestinationString(address.toStdString());
}
WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransaction &transaction, const CCoinControl& coinControl)
@@ -247,7 +246,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
setAddress.insert(rcp.address);
++nAddresses;
- CScript scriptPubKey = GetScriptForDestination(CBitcoinAddress(rcp.address.toStdString()).Get());
+ CScript scriptPubKey = GetScriptForDestination(DecodeDestination(rcp.address.toStdString()));
CRecipient recipient = {scriptPubKey, rcp.amount, rcp.fSubtractFeeFromAmount};
vecSend.push_back(recipient);
@@ -348,7 +347,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
if (!rcp.paymentRequest.IsInitialized())
{
std::string strAddress = rcp.address.toStdString();
- CTxDestination dest = CBitcoinAddress(strAddress).Get();
+ CTxDestination dest = DecodeDestination(strAddress);
std::string strLabel = rcp.label.toStdString();
{
LOCK(wallet->cs_wallet);
@@ -464,7 +463,7 @@ static void NotifyAddressBookChanged(WalletModel *walletmodel, CWallet *wallet,
const CTxDestination &address, const std::string &label, bool isMine,
const std::string &purpose, ChangeType status)
{
- QString strAddress = QString::fromStdString(CBitcoinAddress(address).ToString());
+ QString strAddress = QString::fromStdString(EncodeDestination(address));
QString strLabel = QString::fromStdString(label);
QString strPurpose = QString::fromStdString(purpose);
@@ -561,9 +560,9 @@ bool WalletModel::getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
return wallet->GetPubKey(address, vchPubKeyOut);
}
-bool WalletModel::havePrivKey(const CKeyID &address) const
+bool WalletModel::IsSpendable(const CTxDestination& dest) const
{
- return wallet->HaveKey(address);
+ return IsMine(*wallet, dest) & ISMINE_SPENDABLE;
}
bool WalletModel::getPrivKey(const CKeyID &address, CKey& vchPrivKeyOut) const
@@ -596,7 +595,7 @@ bool WalletModel::isSpent(const COutPoint& outpoint) const
void WalletModel::listCoins(std::map<QString, std::vector<COutput> >& mapCoins) const
{
for (auto& group : wallet->ListCoins()) {
- auto& resultGroup = mapCoins[QString::fromStdString(CBitcoinAddress(group.first).ToString())];
+ auto& resultGroup = mapCoins[QString::fromStdString(EncodeDestination(group.first))];
for (auto& coin : group.second) {
resultGroup.emplace_back(std::move(coin));
}
@@ -634,7 +633,7 @@ void WalletModel::loadReceiveRequests(std::vector<std::string>& vReceiveRequests
bool WalletModel::saveReceiveRequest(const std::string &sAddress, const int64_t nId, const std::string &sRequest)
{
- CTxDestination dest = CBitcoinAddress(sAddress).Get();
+ CTxDestination dest = DecodeDestination(sAddress);
std::stringstream ss;
ss << nId;
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index 6be36a57e2..05733f8272 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -190,7 +190,7 @@ public:
UnlockContext requestUnlock();
bool getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const;
- bool havePrivKey(const CKeyID &address) const;
+ bool IsSpendable(const CTxDestination& dest) const;
bool getPrivKey(const CKeyID &address, CKey& vchPrivKeyOut) const;
void getOutputs(const std::vector<COutPoint>& vOutpoints, std::vector<COutput>& vOutputs);
bool isSpent(const COutPoint& outpoint) const;
diff --git a/src/rest.cpp b/src/rest.cpp
index 154ee04eed..0b2c843d5f 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -190,9 +190,6 @@ static bool rest_headers(HTTPRequest* req,
return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: .bin, .hex)");
}
}
-
- // not reached
- return true; // continue to process further HTTP reqs on this cxn
}
static bool rest_block(HTTPRequest* req,
@@ -253,9 +250,6 @@ static bool rest_block(HTTPRequest* req,
return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: " + AvailableDataFormatsString() + ")");
}
}
-
- // not reached
- return true; // continue to process further HTTP reqs on this cxn
}
static bool rest_block_extended(HTTPRequest* req, const std::string& strURIPart)
@@ -292,9 +286,6 @@ static bool rest_chaininfo(HTTPRequest* req, const std::string& strURIPart)
return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: json)");
}
}
-
- // not reached
- return true; // continue to process further HTTP reqs on this cxn
}
static bool rest_mempool_info(HTTPRequest* req, const std::string& strURIPart)
@@ -317,9 +308,6 @@ static bool rest_mempool_info(HTTPRequest* req, const std::string& strURIPart)
return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: json)");
}
}
-
- // not reached
- return true; // continue to process further HTTP reqs on this cxn
}
static bool rest_mempool_contents(HTTPRequest* req, const std::string& strURIPart)
@@ -342,9 +330,6 @@ static bool rest_mempool_contents(HTTPRequest* req, const std::string& strURIPar
return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: json)");
}
}
-
- // not reached
- return true; // continue to process further HTTP reqs on this cxn
}
static bool rest_tx(HTTPRequest* req, const std::string& strURIPart)
@@ -394,9 +379,6 @@ static bool rest_tx(HTTPRequest* req, const std::string& strURIPart)
return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: " + AvailableDataFormatsString() + ")");
}
}
-
- // not reached
- return true; // continue to process further HTTP reqs on this cxn
}
static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
@@ -581,9 +563,6 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: " + AvailableDataFormatsString() + ")");
}
}
-
- // not reached
- return true; // continue to process further HTTP reqs on this cxn
}
static const struct {
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index e6b78516ed..46f4f16321 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -343,6 +343,7 @@ std::string EntryDescriptionString()
" \"ancestorcount\" : n, (numeric) number of in-mempool ancestor transactions (including this one)\n"
" \"ancestorsize\" : n, (numeric) virtual transaction size of in-mempool ancestors (including this one)\n"
" \"ancestorfees\" : n, (numeric) modified fees (see above) of in-mempool ancestors (including this one)\n"
+ " \"wtxid\" : hash, (string) hash of serialized transaction, including witness data\n"
" \"depends\" : [ (array) unconfirmed transactions used as inputs for this transaction\n"
" \"transactionid\", (string) parent transaction id\n"
" ... ]\n";
@@ -363,6 +364,7 @@ void entryToJSON(UniValue &info, const CTxMemPoolEntry &e)
info.push_back(Pair("ancestorcount", e.GetCountWithAncestors()));
info.push_back(Pair("ancestorsize", e.GetSizeWithAncestors()));
info.push_back(Pair("ancestorfees", e.GetModFeesWithAncestors()));
+ info.push_back(Pair("wtxid", mempool.vTxHashes[e.vTxHashesIdx].first.ToString()));
const CTransaction& tx = e.GetTx();
std::set<std::string> setDepends;
for (const CTxIn& txin : tx.vin)
@@ -812,6 +814,7 @@ static void ApplyStats(CCoinsStats &stats, CHashWriter& ss, const uint256& hash,
static bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats)
{
std::unique_ptr<CCoinsViewCursor> pcursor(view->Cursor());
+ assert(pcursor);
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
stats.hashBlock = pcursor->GetBestBlock();
@@ -1344,7 +1347,7 @@ UniValue getmempoolinfo(const JSONRPCRequest& request)
" \"bytes\": xxxxx, (numeric) Sum of all virtual transaction sizes as defined in BIP 141. Differs from actual serialized size because witness data is discounted\n"
" \"usage\": xxxxx, (numeric) Total memory usage for the mempool\n"
" \"maxmempool\": xxxxx, (numeric) Maximum memory usage for the mempool\n"
- " \"mempoolminfee\": xxxxx (numeric) Minimum feerate (" + CURRENCY_UNIT + " per KB) for tx to be accepted\n"
+ " \"mempoolminfee\": xxxxx (numeric) Minimum fee rate in " + CURRENCY_UNIT + "/kB for tx to be accepted\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("getmempoolinfo", "")
@@ -1515,6 +1518,8 @@ UniValue getchaintxstats(const JSONRPCRequest& request)
pindex = chainActive.Tip();
}
}
+
+ assert(pindex != nullptr);
if (blockcount < 1 || blockcount >= pindex->nHeight) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block count: should be between 1 and the block's height");
@@ -1532,36 +1537,56 @@ UniValue getchaintxstats(const JSONRPCRequest& request)
return ret;
}
+UniValue savemempool(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.size() != 0) {
+ throw std::runtime_error(
+ "savemempool\n"
+ "\nDumps the mempool to disk.\n"
+ "\nExamples:\n"
+ + HelpExampleCli("savemempool", "")
+ + HelpExampleRpc("savemempool", "")
+ );
+ }
+
+ if (!DumpMempool()) {
+ throw JSONRPCError(RPC_MISC_ERROR, "Unable to dump mempool to disk");
+ }
+
+ return NullUniValue;
+}
+
static const CRPCCommand commands[] =
-{ // category name actor (function) okSafe argNames
- // --------------------- ------------------------ ----------------------- ------ ----------
- { "blockchain", "getblockchaininfo", &getblockchaininfo, true, {} },
- { "blockchain", "getchaintxstats", &getchaintxstats, true, {"nblocks", "blockhash"} },
- { "blockchain", "getbestblockhash", &getbestblockhash, true, {} },
- { "blockchain", "getblockcount", &getblockcount, true, {} },
- { "blockchain", "getblock", &getblock, true, {"blockhash","verbosity|verbose"} },
- { "blockchain", "getblockhash", &getblockhash, true, {"height"} },
- { "blockchain", "getblockheader", &getblockheader, true, {"blockhash","verbose"} },
- { "blockchain", "getchaintips", &getchaintips, true, {} },
- { "blockchain", "getdifficulty", &getdifficulty, true, {} },
- { "blockchain", "getmempoolancestors", &getmempoolancestors, true, {"txid","verbose"} },
- { "blockchain", "getmempooldescendants", &getmempooldescendants, true, {"txid","verbose"} },
- { "blockchain", "getmempoolentry", &getmempoolentry, true, {"txid"} },
- { "blockchain", "getmempoolinfo", &getmempoolinfo, true, {} },
- { "blockchain", "getrawmempool", &getrawmempool, true, {"verbose"} },
- { "blockchain", "gettxout", &gettxout, true, {"txid","n","include_mempool"} },
- { "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true, {} },
- { "blockchain", "pruneblockchain", &pruneblockchain, true, {"height"} },
- { "blockchain", "verifychain", &verifychain, true, {"checklevel","nblocks"} },
-
- { "blockchain", "preciousblock", &preciousblock, true, {"blockhash"} },
+{ // category name actor (function) argNames
+ // --------------------- ------------------------ ----------------------- ----------
+ { "blockchain", "getblockchaininfo", &getblockchaininfo, {} },
+ { "blockchain", "getchaintxstats", &getchaintxstats, {"nblocks", "blockhash"} },
+ { "blockchain", "getbestblockhash", &getbestblockhash, {} },
+ { "blockchain", "getblockcount", &getblockcount, {} },
+ { "blockchain", "getblock", &getblock, {"blockhash","verbosity|verbose"} },
+ { "blockchain", "getblockhash", &getblockhash, {"height"} },
+ { "blockchain", "getblockheader", &getblockheader, {"blockhash","verbose"} },
+ { "blockchain", "getchaintips", &getchaintips, {} },
+ { "blockchain", "getdifficulty", &getdifficulty, {} },
+ { "blockchain", "getmempoolancestors", &getmempoolancestors, {"txid","verbose"} },
+ { "blockchain", "getmempooldescendants", &getmempooldescendants, {"txid","verbose"} },
+ { "blockchain", "getmempoolentry", &getmempoolentry, {"txid"} },
+ { "blockchain", "getmempoolinfo", &getmempoolinfo, {} },
+ { "blockchain", "getrawmempool", &getrawmempool, {"verbose"} },
+ { "blockchain", "gettxout", &gettxout, {"txid","n","include_mempool"} },
+ { "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, {} },
+ { "blockchain", "pruneblockchain", &pruneblockchain, {"height"} },
+ { "blockchain", "savemempool", &savemempool, {} },
+ { "blockchain", "verifychain", &verifychain, {"checklevel","nblocks"} },
+
+ { "blockchain", "preciousblock", &preciousblock, {"blockhash"} },
/* Not shown in help */
- { "hidden", "invalidateblock", &invalidateblock, true, {"blockhash"} },
- { "hidden", "reconsiderblock", &reconsiderblock, true, {"blockhash"} },
- { "hidden", "waitfornewblock", &waitfornewblock, true, {"timeout"} },
- { "hidden", "waitforblock", &waitforblock, true, {"blockhash","timeout"} },
- { "hidden", "waitforblockheight", &waitforblockheight, true, {"height","timeout"} },
+ { "hidden", "invalidateblock", &invalidateblock, {"blockhash"} },
+ { "hidden", "reconsiderblock", &reconsiderblock, {"blockhash"} },
+ { "hidden", "waitfornewblock", &waitfornewblock, {"timeout"} },
+ { "hidden", "waitforblock", &waitforblock, {"blockhash","timeout"} },
+ { "hidden", "waitforblockheight", &waitforblockheight, {"height","timeout"} },
};
void RegisterBlockchainRPCCommands(CRPCTable &t)
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index 4179453782..406ad2f6ec 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -115,8 +115,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "keypoolrefill", 0, "newsize" },
{ "getrawmempool", 0, "verbose" },
{ "estimatefee", 0, "nblocks" },
- { "estimatesmartfee", 0, "nblocks" },
- { "estimaterawfee", 0, "nblocks" },
+ { "estimatesmartfee", 0, "conf_target" },
+ { "estimaterawfee", 0, "conf_target" },
{ "estimaterawfee", 1, "threshold" },
{ "prioritisetransaction", 1, "dummy" },
{ "prioritisetransaction", 2, "fee_delta" },
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 2692e59155..f0ffa07e12 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -176,12 +176,13 @@ UniValue generatetoaddress(const JSONRPCRequest& request)
nMaxTries = request.params[2].get_int();
}
- CBitcoinAddress address(request.params[1].get_str());
- if (!address.IsValid())
+ CTxDestination destination = DecodeDestination(request.params[1].get_str());
+ if (!IsValidDestination(destination)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Error: Invalid address");
+ }
std::shared_ptr<CReserveScript> coinbaseScript = std::make_shared<CReserveScript>();
- coinbaseScript->reserveScript = GetScriptForDestination(address.Get());
+ coinbaseScript->reserveScript = GetScriptForDestination(destination);
return generateBlocks(coinbaseScript, nGenerate, nMaxTries, false);
}
@@ -195,7 +196,6 @@ UniValue getmininginfo(const JSONRPCRequest& request)
"\nResult:\n"
"{\n"
" \"blocks\": nnn, (numeric) The current block\n"
- " \"currentblocksize\": nnn, (numeric) The last block size\n"
" \"currentblockweight\": nnn, (numeric) The last block weight\n"
" \"currentblocktx\": nnn, (numeric) The last block transaction\n"
" \"difficulty\": xxx.xxxxx (numeric) The current difficulty\n"
@@ -214,7 +214,6 @@ UniValue getmininginfo(const JSONRPCRequest& request)
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("blocks", (int)chainActive.Height()));
- obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize));
obj.push_back(Pair("currentblockweight", (uint64_t)nLastBlockWeight));
obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx));
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
@@ -336,7 +335,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
" n (numeric) transactions before this one (by 1-based index in 'transactions' list) that must be present in the final block if this one is\n"
" ,...\n"
" ],\n"
- " \"fee\": n, (numeric) difference in value between transaction inputs and outputs (in Satoshis); for coinbase transactions, this is a negative Number of the total collected block fees (ie, not including the block subsidy); if key is not present, fee is unknown and clients MUST NOT assume there isn't one\n"
+ " \"fee\": n, (numeric) difference in value between transaction inputs and outputs (in satoshis); for coinbase transactions, this is a negative Number of the total collected block fees (ie, not including the block subsidy); if key is not present, fee is unknown and clients MUST NOT assume there isn't one\n"
" \"sigops\" : n, (numeric) total SigOps cost, as counted for purposes of block limits; if key is not present, sigop cost is unknown and clients MUST NOT assume it is zero\n"
" \"weight\" : n, (numeric) total transaction weight, as counted for purposes of block limits\n"
" \"required\" : true|false (boolean) if provided and true, this transaction must be in the final block\n"
@@ -346,7 +345,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
" \"coinbaseaux\" : { (json object) data that should be included in the coinbase's scriptSig content\n"
" \"flags\" : \"xx\" (string) key name is to be ignored, and value included in scriptSig\n"
" },\n"
- " \"coinbasevalue\" : n, (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in Satoshis)\n"
+ " \"coinbasevalue\" : n, (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in satoshis)\n"
" \"coinbasetxn\" : { ... }, (json object) information for coinbase transaction\n"
" \"target\" : \"xxxx\", (string) The hash target\n"
" \"mintime\" : xxx, (numeric) The minimum timestamp appropriate for next block time in seconds since epoch (Jan 1 1970 GMT)\n"
@@ -825,7 +824,7 @@ UniValue estimatesmartfee(const JSONRPCRequest& request)
" \"CONSERVATIVE\"\n"
"\nResult:\n"
"{\n"
- " \"feerate\" : x.x, (numeric, optional) estimate fee-per-kilobyte (in BTC)\n"
+ " \"feerate\" : x.x, (numeric, optional) estimate fee rate in " + CURRENCY_UNIT + "/kB\n"
" \"errors\": [ str... ] (json array of strings, optional) Errors encountered during processing\n"
" \"blocks\" : n (numeric) block number where estimate was found\n"
"}\n"
@@ -884,7 +883,7 @@ UniValue estimaterawfee(const JSONRPCRequest& request)
"\nResult:\n"
"{\n"
" \"short\" : { (json object, optional) estimate for short time horizon\n"
- " \"feerate\" : x.x, (numeric, optional) estimate fee-per-kilobyte (in BTC)\n"
+ " \"feerate\" : x.x, (numeric, optional) estimate fee rate in " + CURRENCY_UNIT + "/kB\n"
" \"decay\" : x.x, (numeric) exponential decay (per block) for historical moving average of confirmation data\n"
" \"scale\" : x, (numeric) The resolution of confirmation targets at this time horizon\n"
" \"pass\" : { (json object, optional) information about the lowest range of feerates to succeed in meeting the threshold\n"
@@ -967,20 +966,21 @@ UniValue estimaterawfee(const JSONRPCRequest& request)
}
static const CRPCCommand commands[] =
-{ // category name actor (function) okSafeMode
+{ // category name actor (function) argNames
// --------------------- ------------------------ ----------------------- ----------
- { "mining", "getnetworkhashps", &getnetworkhashps, true, {"nblocks","height"} },
- { "mining", "getmininginfo", &getmininginfo, true, {} },
- { "mining", "prioritisetransaction", &prioritisetransaction, true, {"txid","dummy","fee_delta"} },
- { "mining", "getblocktemplate", &getblocktemplate, true, {"template_request"} },
- { "mining", "submitblock", &submitblock, true, {"hexdata","dummy"} },
+ { "mining", "getnetworkhashps", &getnetworkhashps, {"nblocks","height"} },
+ { "mining", "getmininginfo", &getmininginfo, {} },
+ { "mining", "prioritisetransaction", &prioritisetransaction, {"txid","dummy","fee_delta"} },
+ { "mining", "getblocktemplate", &getblocktemplate, {"template_request"} },
+ { "mining", "submitblock", &submitblock, {"hexdata","dummy"} },
+
- { "generating", "generatetoaddress", &generatetoaddress, true, {"nblocks","address","maxtries"} },
+ { "generating", "generatetoaddress", &generatetoaddress, {"nblocks","address","maxtries"} },
- { "util", "estimatefee", &estimatefee, true, {"nblocks"} },
- { "util", "estimatesmartfee", &estimatesmartfee, true, {"conf_target", "estimate_mode"} },
+ { "util", "estimatefee", &estimatefee, {"nblocks"} },
+ { "util", "estimatesmartfee", &estimatesmartfee, {"conf_target", "estimate_mode"} },
- { "hidden", "estimaterawfee", &estimaterawfee, true, {"conf_target", "threshold"} },
+ { "hidden", "estimaterawfee", &estimaterawfee, {"conf_target", "threshold"} },
};
void RegisterMiningRPCCommands(CRPCTable &t)
diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index a6af24f7e1..f8cdf57d14 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -31,94 +31,6 @@
#include <univalue.h>
-/**
- * @note Do not add or change anything in the information returned by this
- * method. `getinfo` exists for backwards-compatibility only. It combines
- * information from wildly different sources in the program, which is a mess,
- * and is thus planned to be deprecated eventually.
- *
- * Based on the source of the information, new information should be added to:
- * - `getblockchaininfo`,
- * - `getnetworkinfo` or
- * - `getwalletinfo`
- *
- * Or alternatively, create a specific query method for the information.
- **/
-UniValue getinfo(const JSONRPCRequest& request)
-{
- if (request.fHelp || request.params.size() != 0)
- throw std::runtime_error(
- "getinfo\n"
- "\nDEPRECATED. Returns an object containing various state info.\n"
- "\nResult:\n"
- "{\n"
- " \"deprecation-warning\": \"...\" (string) warning that the getinfo command is deprecated and will be removed in 0.16\n"
- " \"version\": xxxxx, (numeric) the server version\n"
- " \"protocolversion\": xxxxx, (numeric) the protocol version\n"
- " \"walletversion\": xxxxx, (numeric) the wallet version\n"
- " \"balance\": xxxxxxx, (numeric) the total bitcoin balance of the wallet\n"
- " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n"
- " \"timeoffset\": xxxxx, (numeric) the time offset\n"
- " \"connections\": xxxxx, (numeric) the number of connections\n"
- " \"proxy\": \"host:port\", (string, optional) the proxy used by the server\n"
- " \"difficulty\": xxxxxx, (numeric) the current difficulty\n"
- " \"testnet\": true|false, (boolean) if the server is using testnet or not\n"
- " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since Unix epoch) of the oldest pre-generated key in the key pool\n"
- " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
- " \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n"
- " \"paytxfee\": x.xxxx, (numeric) the transaction fee set in " + CURRENCY_UNIT + "/kB\n"
- " \"relayfee\": x.xxxx, (numeric) minimum relay fee for transactions in " + CURRENCY_UNIT + "/kB\n"
- " \"errors\": \"...\" (string) any error messages\n"
- "}\n"
- "\nExamples:\n"
- + HelpExampleCli("getinfo", "")
- + HelpExampleRpc("getinfo", "")
- );
-
-#ifdef ENABLE_WALLET
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
-
- LOCK2(cs_main, pwallet ? &pwallet->cs_wallet : nullptr);
-#else
- LOCK(cs_main);
-#endif
-
- proxyType proxy;
- GetProxy(NET_IPV4, proxy);
-
- UniValue obj(UniValue::VOBJ);
- obj.push_back(Pair("deprecation-warning", "WARNING: getinfo is deprecated and will be fully removed in 0.16."
- " Projects should transition to using getblockchaininfo, getnetworkinfo, and getwalletinfo before upgrading to 0.16"));
- obj.push_back(Pair("version", CLIENT_VERSION));
- obj.push_back(Pair("protocolversion", PROTOCOL_VERSION));
-#ifdef ENABLE_WALLET
- if (pwallet) {
- obj.push_back(Pair("walletversion", pwallet->GetVersion()));
- obj.push_back(Pair("balance", ValueFromAmount(pwallet->GetBalance())));
- }
-#endif
- obj.push_back(Pair("blocks", (int)chainActive.Height()));
- obj.push_back(Pair("timeoffset", GetTimeOffset()));
- if(g_connman)
- obj.push_back(Pair("connections", (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL)));
- obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.proxy.ToStringIPPort() : std::string())));
- obj.push_back(Pair("difficulty", (double)GetDifficulty()));
- obj.push_back(Pair("testnet", Params().NetworkIDString() == CBaseChainParams::TESTNET));
-#ifdef ENABLE_WALLET
- if (pwallet) {
- obj.push_back(Pair("keypoololdest", pwallet->GetOldestKeyPoolTime()));
- obj.push_back(Pair("keypoolsize", (int)pwallet->GetKeyPoolSize()));
- }
- if (pwallet && pwallet->IsCrypted()) {
- obj.push_back(Pair("unlocked_until", pwallet->nRelockTime));
- }
- obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
-#endif
- obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
- obj.push_back(Pair("errors", GetWarnings("statusbar")));
- return obj;
-}
-
#ifdef ENABLE_WALLET
class DescribeAddressVisitor : public boost::static_visitor<UniValue>
{
@@ -152,8 +64,9 @@ public:
obj.push_back(Pair("script", GetTxnOutputType(whichType)));
obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end())));
UniValue a(UniValue::VARR);
- for (const CTxDestination& addr : addresses)
- a.push_back(CBitcoinAddress(addr).ToString());
+ for (const CTxDestination& addr : addresses) {
+ a.push_back(EncodeDestination(addr));
+ }
obj.push_back(Pair("addresses", a));
if (whichType == TX_MULTISIG)
obj.push_back(Pair("sigsrequired", nRequired));
@@ -207,15 +120,14 @@ UniValue validateaddress(const JSONRPCRequest& request)
LOCK(cs_main);
#endif
- CBitcoinAddress address(request.params[0].get_str());
- bool isValid = address.IsValid();
+ CTxDestination dest = DecodeDestination(request.params[0].get_str());
+ bool isValid = IsValidDestination(dest);
UniValue ret(UniValue::VOBJ);
ret.push_back(Pair("isvalid", isValid));
if (isValid)
{
- CTxDestination dest = address.Get();
- std::string currentAddress = address.ToString();
+ std::string currentAddress = EncodeDestination(dest);
ret.push_back(Pair("address", currentAddress));
CScript scriptPubKey = GetScriptForDestination(dest);
@@ -230,10 +142,10 @@ UniValue validateaddress(const JSONRPCRequest& request)
if (pwallet && pwallet->mapAddressBook.count(dest)) {
ret.push_back(Pair("account", pwallet->mapAddressBook[dest].name));
}
- CKeyID keyID;
if (pwallet) {
const auto& meta = pwallet->mapKeyMetadata;
- auto it = address.GetKeyID(keyID) ? meta.find(keyID) : meta.end();
+ const CKeyID *keyID = boost::get<CKeyID>(&dest);
+ auto it = keyID ? meta.find(*keyID) : meta.end();
if (it == meta.end()) {
it = meta.find(CScriptID(scriptPubKey));
}
@@ -277,16 +189,15 @@ CScript _createmultisig_redeemScript(CWallet * const pwallet, const UniValue& pa
const std::string& ks = keys[i].get_str();
#ifdef ENABLE_WALLET
// Case 1: Bitcoin address and we have full public key:
- CBitcoinAddress address(ks);
- if (pwallet && address.IsValid()) {
- CKeyID keyID;
- if (!address.GetKeyID(keyID))
- throw std::runtime_error(
- strprintf("%s does not refer to a key",ks));
+ CTxDestination dest = DecodeDestination(ks);
+ if (pwallet && IsValidDestination(dest)) {
+ const CKeyID *keyID = boost::get<CKeyID>(&dest);
+ if (!keyID) {
+ throw std::runtime_error(strprintf("%s does not refer to a key", ks));
+ }
CPubKey vchPubKey;
- if (!pwallet->GetPubKey(keyID, vchPubKey)) {
- throw std::runtime_error(
- strprintf("no full public key for address %s",ks));
+ if (!pwallet->GetPubKey(*keyID, vchPubKey)) {
+ throw std::runtime_error(strprintf("no full public key for address %s", ks));
}
if (!vchPubKey.IsFullyValid())
throw std::runtime_error(" Invalid public key: "+ks);
@@ -357,10 +268,9 @@ UniValue createmultisig(const JSONRPCRequest& request)
// Construct using pay-to-script-hash:
CScript inner = _createmultisig_redeemScript(pwallet, request.params);
CScriptID innerID(inner);
- CBitcoinAddress address(innerID);
UniValue result(UniValue::VOBJ);
- result.push_back(Pair("address", address.ToString()));
+ result.push_back(Pair("address", EncodeDestination(innerID)));
result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
return result;
@@ -395,13 +305,15 @@ UniValue verifymessage(const JSONRPCRequest& request)
std::string strSign = request.params[1].get_str();
std::string strMessage = request.params[2].get_str();
- CBitcoinAddress addr(strAddress);
- if (!addr.IsValid())
+ CTxDestination destination = DecodeDestination(strAddress);
+ if (!IsValidDestination(destination)) {
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
+ }
- CKeyID keyID;
- if (!addr.GetKeyID(keyID))
+ const CKeyID *keyID = boost::get<CKeyID>(&destination);
+ if (!keyID) {
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
+ }
bool fInvalid = false;
std::vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
@@ -417,7 +329,7 @@ UniValue verifymessage(const JSONRPCRequest& request)
if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
return false;
- return (pubkey.GetID() == keyID);
+ return (pubkey.GetID() == *keyID);
}
UniValue signmessagewithprivkey(const JSONRPCRequest& request)
@@ -459,7 +371,7 @@ UniValue signmessagewithprivkey(const JSONRPCRequest& request)
if (!key.SignCompact(ss.GetHash(), vchSig))
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
- return EncodeBase64(&vchSig[0], vchSig.size());
+ return EncodeBase64(vchSig.data(), vchSig.size());
}
UniValue setmocktime(const JSONRPCRequest& request)
@@ -649,20 +561,19 @@ UniValue echo(const JSONRPCRequest& request)
}
static const CRPCCommand commands[] =
-{ // category name actor (function) okSafeMode
+{ // category name actor (function) argNames
// --------------------- ------------------------ ----------------------- ----------
- { "control", "getinfo", &getinfo, true, {} }, /* uses wallet if enabled */
- { "control", "getmemoryinfo", &getmemoryinfo, true, {"mode"} },
- { "util", "validateaddress", &validateaddress, true, {"address"} }, /* uses wallet if enabled */
- { "util", "createmultisig", &createmultisig, true, {"nrequired","keys"} },
- { "util", "verifymessage", &verifymessage, true, {"address","signature","message"} },
- { "util", "signmessagewithprivkey", &signmessagewithprivkey, true, {"privkey","message"} },
+ { "control", "getmemoryinfo", &getmemoryinfo, {"mode"} },
+ { "util", "validateaddress", &validateaddress, {"address"} }, /* uses wallet if enabled */
+ { "util", "createmultisig", &createmultisig, {"nrequired","keys"} },
+ { "util", "verifymessage", &verifymessage, {"address","signature","message"} },
+ { "util", "signmessagewithprivkey", &signmessagewithprivkey, {"privkey","message"} },
/* Not shown in help */
- { "hidden", "setmocktime", &setmocktime, true, {"timestamp"}},
- { "hidden", "echo", &echo, true, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}},
- { "hidden", "echojson", &echo, true, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}},
- { "hidden", "logging", &logging, true, {"include", "exclude"}},
+ { "hidden", "setmocktime", &setmocktime, {"timestamp"}},
+ { "hidden", "echo", &echo, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}},
+ { "hidden", "echojson", &echo, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}},
+ { "hidden", "logging", &logging, {"include", "exclude"}},
};
void RegisterMiscRPCCommands(CRPCTable &t)
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index f19b968244..7faf216047 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -623,20 +623,20 @@ UniValue setnetworkactive(const JSONRPCRequest& request)
}
static const CRPCCommand commands[] =
-{ // category name actor (function) okSafeMode
+{ // category name actor (function) argNames
// --------------------- ------------------------ ----------------------- ----------
- { "network", "getconnectioncount", &getconnectioncount, true, {} },
- { "network", "ping", &ping, true, {} },
- { "network", "getpeerinfo", &getpeerinfo, true, {} },
- { "network", "addnode", &addnode, true, {"node","command"} },
- { "network", "disconnectnode", &disconnectnode, true, {"address", "nodeid"} },
- { "network", "getaddednodeinfo", &getaddednodeinfo, true, {"node"} },
- { "network", "getnettotals", &getnettotals, true, {} },
- { "network", "getnetworkinfo", &getnetworkinfo, true, {} },
- { "network", "setban", &setban, true, {"subnet", "command", "bantime", "absolute"} },
- { "network", "listbanned", &listbanned, true, {} },
- { "network", "clearbanned", &clearbanned, true, {} },
- { "network", "setnetworkactive", &setnetworkactive, true, {"state"} },
+ { "network", "getconnectioncount", &getconnectioncount, {} },
+ { "network", "ping", &ping, {} },
+ { "network", "getpeerinfo", &getpeerinfo, {} },
+ { "network", "addnode", &addnode, {"node","command"} },
+ { "network", "disconnectnode", &disconnectnode, {"address", "nodeid"} },
+ { "network", "getaddednodeinfo", &getaddednodeinfo, {"node"} },
+ { "network", "getnettotals", &getnettotals, {} },
+ { "network", "getnetworkinfo", &getnetworkinfo, {} },
+ { "network", "setban", &setban, {"subnet", "command", "bantime", "absolute"} },
+ { "network", "listbanned", &listbanned, {} },
+ { "network", "clearbanned", &clearbanned, {} },
+ { "network", "setnetworkactive", &setnetworkactive, {"state"} },
};
void RegisterNetRPCCommands(CRPCTable &t)
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 934576a391..b2fc6a357a 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -16,6 +16,7 @@
#include "policy/policy.h"
#include "policy/rbf.h"
#include "primitives/transaction.h"
+#include "rpc/safemode.h"
#include "rpc/server.h"
#include "script/script.h"
#include "script/script_error.h"
@@ -383,7 +384,7 @@ UniValue createrawtransaction(const JSONRPCRequest& request)
rawTx.vin.push_back(in);
}
- std::set<CBitcoinAddress> setAddress;
+ std::set<CTxDestination> destinations;
std::vector<std::string> addrList = sendTo.getKeys();
for (const std::string& name_ : addrList) {
@@ -393,15 +394,16 @@ UniValue createrawtransaction(const JSONRPCRequest& request)
CTxOut out(0, CScript() << OP_RETURN << data);
rawTx.vout.push_back(out);
} else {
- CBitcoinAddress address(name_);
- if (!address.IsValid())
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ")+name_);
+ CTxDestination destination = DecodeDestination(name_);
+ if (!IsValidDestination(destination)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ") + name_);
+ }
- if (setAddress.count(address))
- throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ")+name_);
- setAddress.insert(address);
+ if (!destinations.insert(destination).second) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_);
+ }
- CScript scriptPubKey = GetScriptForDestination(address.Get());
+ CScript scriptPubKey = GetScriptForDestination(destination);
CAmount nAmount = AmountFromValue(sendTo[name_]);
CTxOut out(nAmount, scriptPubKey);
@@ -528,7 +530,7 @@ UniValue decodescript(const JSONRPCRequest& request)
if (type.isStr() && type.get_str() != "scripthash") {
// P2SH cannot be wrapped in a P2SH. If this script is already a P2SH,
// don't return the address for a P2SH of the P2SH.
- r.push_back(Pair("p2sh", CBitcoinAddress(CScriptID(script)).ToString()));
+ r.push_back(Pair("p2sh", EncodeDestination(CScriptID(script))));
}
return r;
@@ -703,6 +705,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request)
+ HelpExampleRpc("signrawtransaction", "\"myhex\"")
);
+ ObserveSafeMode();
#ifdef ENABLE_WALLET
LOCK2(cs_main, pwallet ? &pwallet->cs_wallet : nullptr);
#else
@@ -870,7 +873,12 @@ UniValue signrawtransaction(const JSONRPCRequest& request)
ScriptError serror = SCRIPT_ERR_OK;
if (!VerifyScript(txin.scriptSig, prevPubKey, &txin.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), &serror)) {
- TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror));
+ if (serror == SCRIPT_ERR_INVALID_STACK_OPERATION) {
+ // Unable to sign input and verification failed (possible attempt to partially sign).
+ TxInErrorToJSON(txin, vErrors, "Unable to sign input, invalid stack size (possibly missing key)");
+ } else {
+ TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror));
+ }
}
}
bool fComplete = vErrors.empty();
@@ -908,6 +916,7 @@ UniValue sendrawtransaction(const JSONRPCRequest& request)
+ HelpExampleRpc("sendrawtransaction", "\"signedhex\"")
);
+ ObserveSafeMode();
LOCK(cs_main);
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL});
@@ -959,18 +968,18 @@ UniValue sendrawtransaction(const JSONRPCRequest& request)
}
static const CRPCCommand commands[] =
-{ // category name actor (function) okSafeMode
+{ // category name actor (function) argNames
// --------------------- ------------------------ ----------------------- ----------
- { "rawtransactions", "getrawtransaction", &getrawtransaction, true, {"txid","verbose"} },
- { "rawtransactions", "createrawtransaction", &createrawtransaction, true, {"inputs","outputs","locktime","replaceable"} },
- { "rawtransactions", "decoderawtransaction", &decoderawtransaction, true, {"hexstring"} },
- { "rawtransactions", "decodescript", &decodescript, true, {"hexstring"} },
- { "rawtransactions", "sendrawtransaction", &sendrawtransaction, false, {"hexstring","allowhighfees"} },
- { "rawtransactions", "combinerawtransaction", &combinerawtransaction, true, {"txs"} },
- { "rawtransactions", "signrawtransaction", &signrawtransaction, false, {"hexstring","prevtxs","privkeys","sighashtype"} }, /* uses wallet if enabled */
-
- { "blockchain", "gettxoutproof", &gettxoutproof, true, {"txids", "blockhash"} },
- { "blockchain", "verifytxoutproof", &verifytxoutproof, true, {"proof"} },
+ { "rawtransactions", "getrawtransaction", &getrawtransaction, {"txid","verbose"} },
+ { "rawtransactions", "createrawtransaction", &createrawtransaction, {"inputs","outputs","locktime","replaceable"} },
+ { "rawtransactions", "decoderawtransaction", &decoderawtransaction, {"hexstring"} },
+ { "rawtransactions", "decodescript", &decodescript, {"hexstring"} },
+ { "rawtransactions", "sendrawtransaction", &sendrawtransaction, {"hexstring","allowhighfees"} },
+ { "rawtransactions", "combinerawtransaction", &combinerawtransaction, {"txs"} },
+ { "rawtransactions", "signrawtransaction", &signrawtransaction, {"hexstring","prevtxs","privkeys","sighashtype"} }, /* uses wallet if enabled */
+
+ { "blockchain", "gettxoutproof", &gettxoutproof, {"txids", "blockhash"} },
+ { "blockchain", "verifytxoutproof", &verifytxoutproof, {"proof"} },
};
void RegisterRawTransactionRPCCommands(CRPCTable &t)
diff --git a/src/rpc/safemode.cpp b/src/rpc/safemode.cpp
new file mode 100644
index 0000000000..24770ad47f
--- /dev/null
+++ b/src/rpc/safemode.cpp
@@ -0,0 +1,14 @@
+#include "safemode.h"
+
+#include "rpc/protocol.h"
+#include "util.h"
+#include "warnings.h"
+
+void ObserveSafeMode()
+{
+ std::string warning = GetWarnings("rpc");
+ if (warning != "" && !gArgs.GetBoolArg("-disablesafemode", DEFAULT_DISABLE_SAFEMODE)) {
+ throw JSONRPCError(RPC_FORBIDDEN_BY_SAFE_MODE, std::string("Safe mode: ") + warning);
+ }
+}
+
diff --git a/src/rpc/safemode.h b/src/rpc/safemode.h
new file mode 100644
index 0000000000..8466d6b2f9
--- /dev/null
+++ b/src/rpc/safemode.h
@@ -0,0 +1,12 @@
+// 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_RPC_SAFEMODE_H
+#define BITCOIN_RPC_SAFEMODE_H
+
+static const bool DEFAULT_DISABLE_SAFEMODE = true;
+
+void ObserveSafeMode();
+
+#endif // BITCOIN_RPC_SAFEMODE_H
diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp
index 9ad8d228fa..428ab3b9b0 100644
--- a/src/rpc/server.cpp
+++ b/src/rpc/server.cpp
@@ -51,11 +51,6 @@ void RPCServer::OnStopped(std::function<void ()> slot)
g_rpcSignals.Stopped.connect(slot);
}
-void RPCServer::OnPreCommand(std::function<void (const CRPCCommand&)> slot)
-{
- g_rpcSignals.PreCommand.connect(boost::bind(slot, _1));
-}
-
void RPCTypeCheck(const UniValue& params,
const std::list<UniValue::VType>& typesExpected,
bool fAllowNull)
@@ -267,12 +262,12 @@ UniValue uptime(const JSONRPCRequest& jsonRequest)
* Call Table
*/
static const CRPCCommand vRPCCommands[] =
-{ // category name actor (function) okSafe argNames
- // --------------------- ------------------------ ----------------------- ------ ----------
+{ // category name actor (function) argNames
+ // --------------------- ------------------------ ----------------------- ----------
/* Overall control/query calls */
- { "control", "help", &help, true, {"command"} },
- { "control", "stop", &stop, true, {} },
- { "control", "uptime", &uptime, true, {} },
+ { "control", "help", &help, {"command"} },
+ { "control", "stop", &stop, {} },
+ { "control", "uptime", &uptime, {} },
};
CRPCTable::CRPCTable()
diff --git a/src/rpc/server.h b/src/rpc/server.h
index 89b1d169d5..777acbcb94 100644
--- a/src/rpc/server.h
+++ b/src/rpc/server.h
@@ -25,7 +25,6 @@ namespace RPCServer
{
void OnStarted(std::function<void ()> slot);
void OnStopped(std::function<void ()> slot);
- void OnPreCommand(std::function<void (const CRPCCommand&)> slot);
}
/** Wrapper for UniValue::VType, which includes typeAny:
@@ -134,7 +133,6 @@ public:
std::string category;
std::string name;
rpcfn_type actor;
- bool okSafeMode;
std::vector<std::string> argNames;
};
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index f9716dfc66..7315500e3b 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -1366,7 +1366,7 @@ static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion,
stack = std::vector<std::vector<unsigned char> >(witness.stack.begin(), witness.stack.end() - 1);
uint256 hashScriptPubKey;
CSHA256().Write(&scriptPubKey[0], scriptPubKey.size()).Finalize(hashScriptPubKey.begin());
- if (memcmp(hashScriptPubKey.begin(), &program[0], 32)) {
+ if (memcmp(hashScriptPubKey.begin(), program.data(), 32)) {
return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH);
}
} else if (program.size() == 20) {
diff --git a/src/script/ismine.cpp b/src/script/ismine.cpp
index 0a39619734..c3aade1774 100644
--- a/src/script/ismine.cpp
+++ b/src/script/ismine.cpp
@@ -46,6 +46,8 @@ isminetype IsMine(const CKeyStore &keystore, const CTxDestination& dest, bool& i
isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey, bool& isInvalid, SigVersion sigversion)
{
+ isInvalid = false;
+
std::vector<valtype> vSolutions;
txnouttype whichType;
if (!Solver(scriptPubKey, whichType, vSolutions)) {
diff --git a/src/script/standard.cpp b/src/script/standard.cpp
index 2aed393921..b6e2232ab4 100644
--- a/src/script/standard.cpp
+++ b/src/script/standard.cpp
@@ -317,3 +317,7 @@ CScript GetScriptForWitness(const CScript& redeemscript)
ret << OP_0 << ToByteVector(hash);
return ret;
}
+
+bool IsValidDestination(const CTxDestination& dest) {
+ return dest.which() != 0;
+}
diff --git a/src/script/standard.h b/src/script/standard.h
index 7619192264..8df143a3a3 100644
--- a/src/script/standard.h
+++ b/src/script/standard.h
@@ -77,10 +77,13 @@ public:
* * CNoDestination: no destination set
* * CKeyID: TX_PUBKEYHASH destination
* * CScriptID: TX_SCRIPTHASH destination
- * A CTxDestination is the internal data type encoded in a CBitcoinAddress
+ * A CTxDestination is the internal data type encoded in a bitcoin address
*/
typedef boost::variant<CNoDestination, CKeyID, CScriptID> CTxDestination;
+/** Check whether a CTxDestination is a CNoDestination. */
+bool IsValidDestination(const CTxDestination& dest);
+
/** Get the name of a txnouttype as a C string, or nullptr if unknown. */
const char* GetTxnOutputType(txnouttype t);
diff --git a/src/streams.h b/src/streams.h
index 159847279d..9a3badea57 100644
--- a/src/streams.h
+++ b/src/streams.h
@@ -455,10 +455,6 @@ public:
class CAutoFile
{
private:
- // Disallow copies
- CAutoFile(const CAutoFile&);
- CAutoFile& operator=(const CAutoFile&);
-
const int nType;
const int nVersion;
@@ -475,6 +471,10 @@ public:
fclose();
}
+ // Disallow copies
+ CAutoFile(const CAutoFile&) = delete;
+ CAutoFile& operator=(const CAutoFile&) = delete;
+
void fclose()
{
if (file) {
@@ -564,10 +564,6 @@ public:
class CBufferedFile
{
private:
- // Disallow copies
- CBufferedFile(const CBufferedFile&);
- CBufferedFile& operator=(const CBufferedFile&);
-
const int nType;
const int nVersion;
@@ -609,6 +605,10 @@ public:
fclose();
}
+ // Disallow copies
+ CBufferedFile(const CBufferedFile&) = delete;
+ CBufferedFile& operator=(const CBufferedFile&) = delete;
+
int GetVersion() const { return nVersion; }
int GetType() const { return nType; }
diff --git a/src/support/cleanse.cpp b/src/support/cleanse.cpp
index a2141b2449..95899c9f02 100644
--- a/src/support/cleanse.cpp
+++ b/src/support/cleanse.cpp
@@ -5,9 +5,35 @@
#include "cleanse.h"
-#include <openssl/crypto.h>
+#include <cstring>
+/* Compilers have a bad habit of removing "superfluous" memset calls that
+ * are trying to zero memory. For example, when memset()ing a buffer and
+ * then free()ing it, the compiler might decide that the memset is
+ * unobservable and thus can be removed.
+ *
+ * Previously we used OpenSSL which tried to stop this by a) implementing
+ * memset in assembly on x86 and b) putting the function in its own file
+ * for other platforms.
+ *
+ * This change removes those tricks in favour of using asm directives to
+ * scare the compiler away. As best as our compiler folks can tell, this is
+ * sufficient and will continue to be so.
+ *
+ * Adam Langley <agl@google.com>
+ * Commit: ad1907fe73334d6c696c8539646c21b11178f20f
+ * BoringSSL (LICENSE: ISC)
+ */
void memory_cleanse(void *ptr, size_t len)
{
- OPENSSL_cleanse(ptr, len);
+ std::memset(ptr, 0, len);
+
+ /* As best as we can tell, this is sufficient to break any optimisations that
+ might try to eliminate "superfluous" memsets. If there's an easy way to
+ detect memset_s, it would be better to use that. */
+#if defined(_MSC_VER)
+ __asm;
+#else
+ __asm__ __volatile__("" : : "r"(ptr) : "memory");
+#endif
}
diff --git a/src/support/lockedpool.h b/src/support/lockedpool.h
index cecbdec1aa..834f0371e2 100644
--- a/src/support/lockedpool.h
+++ b/src/support/lockedpool.h
@@ -50,6 +50,9 @@ public:
Arena(void *base, size_t size, size_t alignment);
virtual ~Arena();
+ Arena(const Arena& other) = delete; // non construction-copyable
+ Arena& operator=(const Arena&) = delete; // non copyable
+
/** Memory statistics. */
struct Stats
{
@@ -85,9 +88,6 @@ public:
*/
bool addressInArena(void *ptr) const { return ptr >= base && ptr < end; }
private:
- Arena(const Arena& other) = delete; // non construction-copyable
- Arena& operator=(const Arena&) = delete; // non copyable
-
/** Map of chunk address to chunk information. This class makes use of the
* sorted order to merge previous and next chunks during deallocation.
*/
@@ -153,6 +153,9 @@ public:
explicit LockedPool(std::unique_ptr<LockedPageAllocator> allocator, LockingFailed_Callback lf_cb_in = nullptr);
~LockedPool();
+ LockedPool(const LockedPool& other) = delete; // non construction-copyable
+ LockedPool& operator=(const LockedPool&) = delete; // non copyable
+
/** Allocate size bytes from this arena.
* Returns pointer on success, or 0 if memory is full or
* the application tried to allocate 0 bytes.
@@ -168,9 +171,6 @@ public:
/** Get pool usage statistics */
Stats stats() const;
private:
- LockedPool(const LockedPool& other) = delete; // non construction-copyable
- LockedPool& operator=(const LockedPool&) = delete; // non copyable
-
std::unique_ptr<LockedPageAllocator> allocator;
/** Create an arena from locked pages */
diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp
index ffbeeb7d91..b88ad5ed1b 100644
--- a/src/test/DoS_tests.cpp
+++ b/src/test/DoS_tests.cpp
@@ -50,26 +50,26 @@ BOOST_AUTO_TEST_CASE(DoS_banning)
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 0, 0, CAddress(), "", true);
dummyNode1.SetSendVersion(PROTOCOL_VERSION);
- GetNodeSignals().InitializeNode(&dummyNode1, *connman);
+ peerLogic->InitializeNode(&dummyNode1);
dummyNode1.nVersion = 1;
dummyNode1.fSuccessfullyConnected = true;
Misbehaving(dummyNode1.GetId(), 100); // Should get banned
- SendMessages(&dummyNode1, *connman, interruptDummy);
+ peerLogic->SendMessages(&dummyNode1, interruptDummy);
BOOST_CHECK(connman->IsBanned(addr1));
BOOST_CHECK(!connman->IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned
CAddress addr2(ip(0xa0b0c002), NODE_NONE);
CNode dummyNode2(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr2, 1, 1, CAddress(), "", true);
dummyNode2.SetSendVersion(PROTOCOL_VERSION);
- GetNodeSignals().InitializeNode(&dummyNode2, *connman);
+ peerLogic->InitializeNode(&dummyNode2);
dummyNode2.nVersion = 1;
dummyNode2.fSuccessfullyConnected = true;
Misbehaving(dummyNode2.GetId(), 50);
- SendMessages(&dummyNode2, *connman, interruptDummy);
+ peerLogic->SendMessages(&dummyNode2, interruptDummy);
BOOST_CHECK(!connman->IsBanned(addr2)); // 2 not banned yet...
BOOST_CHECK(connman->IsBanned(addr1)); // ... but 1 still should be
Misbehaving(dummyNode2.GetId(), 50);
- SendMessages(&dummyNode2, *connman, interruptDummy);
+ peerLogic->SendMessages(&dummyNode2, interruptDummy);
BOOST_CHECK(connman->IsBanned(addr2));
}
@@ -82,17 +82,17 @@ BOOST_AUTO_TEST_CASE(DoS_banscore)
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 3, 1, CAddress(), "", true);
dummyNode1.SetSendVersion(PROTOCOL_VERSION);
- GetNodeSignals().InitializeNode(&dummyNode1, *connman);
+ peerLogic->InitializeNode(&dummyNode1);
dummyNode1.nVersion = 1;
dummyNode1.fSuccessfullyConnected = true;
Misbehaving(dummyNode1.GetId(), 100);
- SendMessages(&dummyNode1, *connman, interruptDummy);
+ peerLogic->SendMessages(&dummyNode1, interruptDummy);
BOOST_CHECK(!connman->IsBanned(addr1));
Misbehaving(dummyNode1.GetId(), 10);
- SendMessages(&dummyNode1, *connman, interruptDummy);
+ peerLogic->SendMessages(&dummyNode1, interruptDummy);
BOOST_CHECK(!connman->IsBanned(addr1));
Misbehaving(dummyNode1.GetId(), 1);
- SendMessages(&dummyNode1, *connman, interruptDummy);
+ peerLogic->SendMessages(&dummyNode1, interruptDummy);
BOOST_CHECK(connman->IsBanned(addr1));
gArgs.ForceSetArg("-banscore", std::to_string(DEFAULT_BANSCORE_THRESHOLD));
}
@@ -108,12 +108,12 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
CAddress addr(ip(0xa0b0c001), NODE_NONE);
CNode dummyNode(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr, 4, 4, CAddress(), "", true);
dummyNode.SetSendVersion(PROTOCOL_VERSION);
- GetNodeSignals().InitializeNode(&dummyNode, *connman);
+ peerLogic->InitializeNode(&dummyNode);
dummyNode.nVersion = 1;
dummyNode.fSuccessfullyConnected = true;
Misbehaving(dummyNode.GetId(), 100);
- SendMessages(&dummyNode, *connman, interruptDummy);
+ peerLogic->SendMessages(&dummyNode, interruptDummy);
BOOST_CHECK(connman->IsBanned(addr));
SetMockTime(nStartTime+60*60);
diff --git a/src/test/README.md b/src/test/README.md
index eeb04c6ffa..dbaa9c27f3 100644
--- a/src/test/README.md
+++ b/src/test/README.md
@@ -5,7 +5,10 @@ and tests weren't explicitly disabled.
After configuring, they can be run with `make check`.
-To run the bitcoind tests manually, launch `src/test/test_bitcoin`.
+To run the bitcoind tests manually, launch `src/test/test_bitcoin`. To recompile
+after a test file was modified, run `make` and then run the test again. If you
+modify a non-test file, use `make -C src/test` to recompile only what's needed
+to run the bitcoind tests.
To add more bitcoind tests, add `BOOST_AUTO_TEST_CASE` functions to the existing
.cpp files in the `test/` directory or add new .cpp files that
diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp
index ee633249e9..4829590c54 100644
--- a/src/test/base58_tests.cpp
+++ b/src/test/base58_tests.cpp
@@ -121,7 +121,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
{
UniValue tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid)));
CBitcoinSecret secret;
- CBitcoinAddress addr;
+ CTxDestination destination;
SelectParams(CBaseChainParams::MAIN);
for (unsigned int idx = 0; idx < tests.size(); idx++) {
@@ -145,7 +145,6 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
{
bool isCompressed = find_value(metadata, "isCompressed").get_bool();
// Must be valid private key
- // Note: CBitcoinSecret::SetString tests isValid, whereas CBitcoinAddress does not!
BOOST_CHECK_MESSAGE(secret.SetString(exp_base58string), "!SetString:"+ strTest);
BOOST_CHECK_MESSAGE(secret.IsValid(), "!IsValid:" + strTest);
CKey privkey = secret.GetKey();
@@ -153,18 +152,17 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
BOOST_CHECK_MESSAGE(privkey.size() == exp_payload.size() && std::equal(privkey.begin(), privkey.end(), exp_payload.begin()), "key mismatch:" + strTest);
// Private key must be invalid public key
- addr.SetString(exp_base58string);
- BOOST_CHECK_MESSAGE(!addr.IsValid(), "IsValid privkey as pubkey:" + strTest);
+ destination = DecodeDestination(exp_base58string);
+ BOOST_CHECK_MESSAGE(!IsValidDestination(destination), "IsValid privkey as pubkey:" + strTest);
}
else
{
std::string exp_addrType = find_value(metadata, "addrType").get_str(); // "script" or "pubkey"
// Must be valid public key
- BOOST_CHECK_MESSAGE(addr.SetString(exp_base58string), "SetString:" + strTest);
- BOOST_CHECK_MESSAGE(addr.IsValid(), "!IsValid:" + strTest);
- BOOST_CHECK_MESSAGE(addr.IsScript() == (exp_addrType == "script"), "isScript mismatch" + strTest);
- CTxDestination dest = addr.Get();
- BOOST_CHECK_MESSAGE(boost::apply_visitor(TestAddrTypeVisitor(exp_addrType), dest), "addrType mismatch" + strTest);
+ destination = DecodeDestination(exp_base58string);
+ BOOST_CHECK_MESSAGE(IsValidDestination(destination), "!IsValid:" + strTest);
+ BOOST_CHECK_MESSAGE((boost::get<CScriptID>(&destination) != nullptr) == (exp_addrType == "script"), "isScript mismatch" + strTest);
+ BOOST_CHECK_MESSAGE(boost::apply_visitor(TestAddrTypeVisitor(exp_addrType), destination), "addrType mismatch" + strTest);
// Public key must be invalid private key
secret.SetString(exp_base58string);
@@ -226,17 +224,11 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
BOOST_ERROR("Bad addrtype: " << strTest);
continue;
}
- CBitcoinAddress addrOut;
- BOOST_CHECK_MESSAGE(addrOut.Set(dest), "encode dest: " + strTest);
- BOOST_CHECK_MESSAGE(addrOut.ToString() == exp_base58string, "mismatch: " + strTest);
+ std::string address = EncodeDestination(dest);
+ BOOST_CHECK_MESSAGE(address == exp_base58string, "mismatch: " + strTest);
}
}
- // Visiting a CNoDestination must fail
- CBitcoinAddress dummyAddr;
- CTxDestination nodest = CNoDestination();
- BOOST_CHECK(!dummyAddr.Set(nodest));
-
SelectParams(CBaseChainParams::MAIN);
}
@@ -245,7 +237,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_invalid)
{
UniValue tests = read_json(std::string(json_tests::base58_keys_invalid, json_tests::base58_keys_invalid + sizeof(json_tests::base58_keys_invalid))); // Negative testcases
CBitcoinSecret secret;
- CBitcoinAddress addr;
+ CTxDestination destination;
for (unsigned int idx = 0; idx < tests.size(); idx++) {
UniValue test = tests[idx];
@@ -258,8 +250,8 @@ BOOST_AUTO_TEST_CASE(base58_keys_invalid)
std::string exp_base58string = test[0].get_str();
// must be invalid as public and as private key
- addr.SetString(exp_base58string);
- BOOST_CHECK_MESSAGE(!addr.IsValid(), "IsValid pubkey:" + strTest);
+ destination = DecodeDestination(exp_base58string);
+ BOOST_CHECK_MESSAGE(!IsValidDestination(destination), "IsValid pubkey:" + strTest);
secret.SetString(exp_base58string);
BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid privkey:" + strTest);
}
diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp
index c851ab2849..e123c26ad0 100644
--- a/src/test/bip32_tests.cpp
+++ b/src/test/bip32_tests.cpp
@@ -91,7 +91,7 @@ void RunTest(const TestVector &test) {
std::vector<unsigned char> seed = ParseHex(test.strHexMaster);
CExtKey key;
CExtPubKey pubkey;
- key.SetMaster(&seed[0], seed.size());
+ key.SetMaster(seed.data(), seed.size());
pubkey = key.Neuter();
for (const TestDerivation &derive : test.vDerive) {
unsigned char data[74];
diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp
index 2085b5cb2b..9274ceefcb 100644
--- a/src/test/bloom_tests.cpp
+++ b/src/test/bloom_tests.cpp
@@ -154,8 +154,8 @@ BOOST_AUTO_TEST_CASE(bloom_match)
COutPoint prevOutPoint(uint256S("0x90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"), 0);
{
std::vector<unsigned char> data(32 + sizeof(unsigned int));
- memcpy(&data[0], prevOutPoint.hash.begin(), 32);
- memcpy(&data[32], &prevOutPoint.n, sizeof(unsigned int));
+ memcpy(data.data(), prevOutPoint.hash.begin(), 32);
+ memcpy(data.data()+32, &prevOutPoint.n, sizeof(unsigned int));
filter.insert(data);
}
BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match manually serialized COutPoint");
diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp
index 391ad14ffa..c748b2448c 100644
--- a/src/test/crypto_tests.cpp
+++ b/src/test/crypto_tests.cpp
@@ -58,12 +58,12 @@ void TestRIPEMD160(const std::string &in, const std::string &hexout) { TestVecto
void TestHMACSHA256(const std::string &hexkey, const std::string &hexin, const std::string &hexout) {
std::vector<unsigned char> key = ParseHex(hexkey);
- TestVector(CHMAC_SHA256(&key[0], key.size()), ParseHex(hexin), ParseHex(hexout));
+ TestVector(CHMAC_SHA256(key.data(), key.size()), ParseHex(hexin), ParseHex(hexout));
}
void TestHMACSHA512(const std::string &hexkey, const std::string &hexin, const std::string &hexout) {
std::vector<unsigned char> key = ParseHex(hexkey);
- TestVector(CHMAC_SHA512(&key[0], key.size()), ParseHex(hexin), ParseHex(hexout));
+ TestVector(CHMAC_SHA512(key.data(), key.size()), ParseHex(hexin), ParseHex(hexout));
}
void TestAES128(const std::string &hexkey, const std::string &hexin, const std::string &hexout)
@@ -76,13 +76,13 @@ void TestAES128(const std::string &hexkey, const std::string &hexin, const std::
assert(key.size() == 16);
assert(in.size() == 16);
assert(correctout.size() == 16);
- AES128Encrypt enc(&key[0]);
+ AES128Encrypt enc(key.data());
buf.resize(correctout.size());
buf2.resize(correctout.size());
- enc.Encrypt(&buf[0], &in[0]);
+ enc.Encrypt(buf.data(), in.data());
BOOST_CHECK_EQUAL(HexStr(buf), HexStr(correctout));
- AES128Decrypt dec(&key[0]);
- dec.Decrypt(&buf2[0], &buf[0]);
+ AES128Decrypt dec(key.data());
+ dec.Decrypt(buf2.data(), buf.data());
BOOST_CHECK_EQUAL(HexStr(buf2), HexStr(in));
}
@@ -96,12 +96,12 @@ void TestAES256(const std::string &hexkey, const std::string &hexin, const std::
assert(key.size() == 32);
assert(in.size() == 16);
assert(correctout.size() == 16);
- AES256Encrypt enc(&key[0]);
+ AES256Encrypt enc(key.data());
buf.resize(correctout.size());
- enc.Encrypt(&buf[0], &in[0]);
+ enc.Encrypt(buf.data(), in.data());
BOOST_CHECK(buf == correctout);
- AES256Decrypt dec(&key[0]);
- dec.Decrypt(&buf[0], &buf[0]);
+ AES256Decrypt dec(key.data());
+ dec.Decrypt(buf.data(), buf.data());
BOOST_CHECK(buf == in);
}
@@ -114,16 +114,16 @@ void TestAES128CBC(const std::string &hexkey, const std::string &hexiv, bool pad
std::vector<unsigned char> realout(in.size() + AES_BLOCKSIZE);
// Encrypt the plaintext and verify that it equals the cipher
- AES128CBCEncrypt enc(&key[0], &iv[0], pad);
- int size = enc.Encrypt(&in[0], in.size(), &realout[0]);
+ AES128CBCEncrypt enc(key.data(), iv.data(), pad);
+ int size = enc.Encrypt(in.data(), in.size(), realout.data());
realout.resize(size);
BOOST_CHECK(realout.size() == correctout.size());
BOOST_CHECK_MESSAGE(realout == correctout, HexStr(realout) + std::string(" != ") + hexout);
// Decrypt the cipher and verify that it equals the plaintext
std::vector<unsigned char> decrypted(correctout.size());
- AES128CBCDecrypt dec(&key[0], &iv[0], pad);
- size = dec.Decrypt(&correctout[0], correctout.size(), &decrypted[0]);
+ AES128CBCDecrypt dec(key.data(), iv.data(), pad);
+ size = dec.Decrypt(correctout.data(), correctout.size(), decrypted.data());
decrypted.resize(size);
BOOST_CHECK(decrypted.size() == in.size());
BOOST_CHECK_MESSAGE(decrypted == in, HexStr(decrypted) + std::string(" != ") + hexin);
@@ -133,12 +133,12 @@ void TestAES128CBC(const std::string &hexkey, const std::string &hexiv, bool pad
{
std::vector<unsigned char> sub(i, in.end());
std::vector<unsigned char> subout(sub.size() + AES_BLOCKSIZE);
- int _size = enc.Encrypt(&sub[0], sub.size(), &subout[0]);
+ int _size = enc.Encrypt(sub.data(), sub.size(), subout.data());
if (_size != 0)
{
subout.resize(_size);
std::vector<unsigned char> subdecrypted(subout.size());
- _size = dec.Decrypt(&subout[0], subout.size(), &subdecrypted[0]);
+ _size = dec.Decrypt(subout.data(), subout.size(), subdecrypted.data());
subdecrypted.resize(_size);
BOOST_CHECK(decrypted.size() == in.size());
BOOST_CHECK_MESSAGE(subdecrypted == sub, HexStr(subdecrypted) + std::string(" != ") + HexStr(sub));
@@ -155,16 +155,16 @@ void TestAES256CBC(const std::string &hexkey, const std::string &hexiv, bool pad
std::vector<unsigned char> realout(in.size() + AES_BLOCKSIZE);
// Encrypt the plaintext and verify that it equals the cipher
- AES256CBCEncrypt enc(&key[0], &iv[0], pad);
- int size = enc.Encrypt(&in[0], in.size(), &realout[0]);
+ AES256CBCEncrypt enc(key.data(), iv.data(), pad);
+ int size = enc.Encrypt(in.data(), in.size(), realout.data());
realout.resize(size);
BOOST_CHECK(realout.size() == correctout.size());
BOOST_CHECK_MESSAGE(realout == correctout, HexStr(realout) + std::string(" != ") + hexout);
// Decrypt the cipher and verify that it equals the plaintext
std::vector<unsigned char> decrypted(correctout.size());
- AES256CBCDecrypt dec(&key[0], &iv[0], pad);
- size = dec.Decrypt(&correctout[0], correctout.size(), &decrypted[0]);
+ AES256CBCDecrypt dec(key.data(), iv.data(), pad);
+ size = dec.Decrypt(correctout.data(), correctout.size(), decrypted.data());
decrypted.resize(size);
BOOST_CHECK(decrypted.size() == in.size());
BOOST_CHECK_MESSAGE(decrypted == in, HexStr(decrypted) + std::string(" != ") + hexin);
@@ -174,12 +174,12 @@ void TestAES256CBC(const std::string &hexkey, const std::string &hexiv, bool pad
{
std::vector<unsigned char> sub(i, in.end());
std::vector<unsigned char> subout(sub.size() + AES_BLOCKSIZE);
- int _size = enc.Encrypt(&sub[0], sub.size(), &subout[0]);
+ int _size = enc.Encrypt(sub.data(), sub.size(), subout.data());
if (_size != 0)
{
subout.resize(_size);
std::vector<unsigned char> subdecrypted(subout.size());
- _size = dec.Decrypt(&subout[0], subout.size(), &subdecrypted[0]);
+ _size = dec.Decrypt(subout.data(), subout.size(), subdecrypted.data());
subdecrypted.resize(_size);
BOOST_CHECK(decrypted.size() == in.size());
BOOST_CHECK_MESSAGE(subdecrypted == sub, HexStr(subdecrypted) + std::string(" != ") + HexStr(sub));
diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp
index 18a7e59933..40f0ecd5f1 100644
--- a/src/test/getarg_tests.cpp
+++ b/src/test/getarg_tests.cpp
@@ -27,7 +27,7 @@ static void ResetArgs(const std::string& strArg)
for (std::string& s : vecArg)
vecChar.push_back(s.c_str());
- gArgs.ParseParameters(vecChar.size(), &vecChar[0]);
+ gArgs.ParseParameters(vecChar.size(), vecChar.data());
}
BOOST_AUTO_TEST_CASE(boolarg)
diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp
index 559b3caf1c..91c0175412 100644
--- a/src/test/key_tests.cpp
+++ b/src/test/key_tests.cpp
@@ -16,17 +16,16 @@
#include <boost/test/unit_test.hpp>
-static const std::string strSecret1 ("5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjHHfmFiWtmAbrj");
-static const std::string strSecret2 ("5KC4ejrDjv152FGwP386VD1i2NYc5KkfSMyv1nGy1VGDxGHqVY3");
-static const std::string strSecret1C ("Kwr371tjA9u2rFSMZjTNun2PXXP3WPZu2afRHTcta6KxEUdm1vEw");
-static const std::string strSecret2C ("L3Hq7a8FEQwJkW1M2GNKDW28546Vp5miewcCzSqUD9kCAXrJdS3g");
-static const CBitcoinAddress addr1 ("1QFqqMUD55ZV3PJEJZtaKCsQmjLT6JkjvJ");
-static const CBitcoinAddress addr2 ("1F5y5E5FMc5YzdJtB9hLaUe43GDxEKXENJ");
-static const CBitcoinAddress addr1C("1NoJrossxPBKfCHuJXT4HadJrXRE9Fxiqs");
-static const CBitcoinAddress addr2C("1CRj2HyM1CXWzHAXLQtiGLyggNT9WQqsDs");
+static const std::string strSecret1 = "5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjHHfmFiWtmAbrj";
+static const std::string strSecret2 = "5KC4ejrDjv152FGwP386VD1i2NYc5KkfSMyv1nGy1VGDxGHqVY3";
+static const std::string strSecret1C = "Kwr371tjA9u2rFSMZjTNun2PXXP3WPZu2afRHTcta6KxEUdm1vEw";
+static const std::string strSecret2C = "L3Hq7a8FEQwJkW1M2GNKDW28546Vp5miewcCzSqUD9kCAXrJdS3g";
+static const std::string addr1 = "1QFqqMUD55ZV3PJEJZtaKCsQmjLT6JkjvJ";
+static const std::string addr2 = "1F5y5E5FMc5YzdJtB9hLaUe43GDxEKXENJ";
+static const std::string addr1C = "1NoJrossxPBKfCHuJXT4HadJrXRE9Fxiqs";
+static const std::string addr2C = "1CRj2HyM1CXWzHAXLQtiGLyggNT9WQqsDs";
-
-static const std::string strAddressBad("1HV9Lc3sNHZxwj4Zk6fB38tEmBryq2cBiF");
+static const std::string strAddressBad = "1HV9Lc3sNHZxwj4Zk6fB38tEmBryq2cBiF";
BOOST_FIXTURE_TEST_SUITE(key_tests, BasicTestingSetup)
@@ -74,10 +73,10 @@ BOOST_AUTO_TEST_CASE(key_test1)
BOOST_CHECK(!key2C.VerifyPubKey(pubkey2));
BOOST_CHECK(key2C.VerifyPubKey(pubkey2C));
- BOOST_CHECK(addr1.Get() == CTxDestination(pubkey1.GetID()));
- BOOST_CHECK(addr2.Get() == CTxDestination(pubkey2.GetID()));
- BOOST_CHECK(addr1C.Get() == CTxDestination(pubkey1C.GetID()));
- BOOST_CHECK(addr2C.Get() == CTxDestination(pubkey2C.GetID()));
+ BOOST_CHECK(DecodeDestination(addr1) == CTxDestination(pubkey1.GetID()));
+ BOOST_CHECK(DecodeDestination(addr2) == CTxDestination(pubkey2.GetID()));
+ BOOST_CHECK(DecodeDestination(addr1C) == CTxDestination(pubkey1C.GetID()));
+ BOOST_CHECK(DecodeDestination(addr2C) == CTxDestination(pubkey2C.GetID()));
for (int n=0; n<16; n++)
{
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index 9fa9a8509c..41e0626eb9 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -32,7 +32,6 @@ static BlockAssembler AssemblerForTest(const CChainParams& params) {
BlockAssembler::Options options;
options.nBlockMaxWeight = MAX_BLOCK_WEIGHT;
- options.nBlockMaxSize = MAX_BLOCK_SERIALIZED_SIZE;
options.blockMinFeeRate = blockMinFeeRate;
return BlockAssembler(params, options);
}
diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp
index 5e89ef60d2..de7f3b48f5 100644
--- a/src/test/multisig_tests.cpp
+++ b/src/test/multisig_tests.cpp
@@ -16,8 +16,6 @@
#include <boost/test/unit_test.hpp>
-typedef std::vector<unsigned char> valtype;
-
BOOST_FIXTURE_TEST_SUITE(multisig_tests, BasicTestingSetup)
CScript
@@ -173,95 +171,6 @@ BOOST_AUTO_TEST_CASE(multisig_IsStandard)
BOOST_CHECK(!::IsStandard(malformed[i], whichType));
}
-BOOST_AUTO_TEST_CASE(multisig_Solver1)
-{
- // Tests Solver() that returns lists of keys that are
- // required to satisfy a ScriptPubKey
- //
- // Also tests IsMine() and ExtractDestination()
- //
- // Note: ExtractDestination for the multisignature transactions
- // always returns false for this release, even if you have
- // one key that would satisfy an (a|b) or 2-of-3 keys needed
- // to spend an escrow transaction.
- //
- CBasicKeyStore keystore, emptykeystore, partialkeystore;
- CKey key[3];
- CTxDestination keyaddr[3];
- for (int i = 0; i < 3; i++)
- {
- key[i].MakeNewKey(true);
- keystore.AddKey(key[i]);
- keyaddr[i] = key[i].GetPubKey().GetID();
- }
- partialkeystore.AddKey(key[0]);
-
- {
- std::vector<valtype> solutions;
- txnouttype whichType;
- CScript s;
- s << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG;
- BOOST_CHECK(Solver(s, whichType, solutions));
- BOOST_CHECK(solutions.size() == 1);
- CTxDestination addr;
- BOOST_CHECK(ExtractDestination(s, addr));
- BOOST_CHECK(addr == keyaddr[0]);
- BOOST_CHECK(IsMine(keystore, s));
- BOOST_CHECK(!IsMine(emptykeystore, s));
- }
- {
- std::vector<valtype> solutions;
- txnouttype whichType;
- CScript s;
- s << OP_DUP << OP_HASH160 << ToByteVector(key[0].GetPubKey().GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
- BOOST_CHECK(Solver(s, whichType, solutions));
- BOOST_CHECK(solutions.size() == 1);
- CTxDestination addr;
- BOOST_CHECK(ExtractDestination(s, addr));
- BOOST_CHECK(addr == keyaddr[0]);
- BOOST_CHECK(IsMine(keystore, s));
- BOOST_CHECK(!IsMine(emptykeystore, s));
- }
- {
- std::vector<valtype> solutions;
- txnouttype whichType;
- CScript s;
- s << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
- BOOST_CHECK(Solver(s, whichType, solutions));
- BOOST_CHECK_EQUAL(solutions.size(), 4U);
- CTxDestination addr;
- BOOST_CHECK(!ExtractDestination(s, addr));
- BOOST_CHECK(IsMine(keystore, s));
- BOOST_CHECK(!IsMine(emptykeystore, s));
- BOOST_CHECK(!IsMine(partialkeystore, s));
- }
- {
- std::vector<valtype> solutions;
- txnouttype whichType;
- CScript s;
- s << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
- BOOST_CHECK(Solver(s, whichType, solutions));
- BOOST_CHECK_EQUAL(solutions.size(), 4U);
- std::vector<CTxDestination> addrs;
- int nRequired;
- BOOST_CHECK(ExtractDestinations(s, whichType, addrs, nRequired));
- BOOST_CHECK(addrs[0] == keyaddr[0]);
- BOOST_CHECK(addrs[1] == keyaddr[1]);
- BOOST_CHECK(nRequired == 1);
- BOOST_CHECK(IsMine(keystore, s));
- BOOST_CHECK(!IsMine(emptykeystore, s));
- BOOST_CHECK(!IsMine(partialkeystore, s));
- }
- {
- std::vector<valtype> solutions;
- txnouttype whichType;
- CScript s;
- s << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
- BOOST_CHECK(Solver(s, whichType, solutions));
- BOOST_CHECK(solutions.size() == 5);
- }
-}
-
BOOST_AUTO_TEST_CASE(multisig_Sign)
{
// Test SignSignature() (and therefore the version of Solver() that signs transactions)
diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp
index efd0f77d9f..58aa32c969 100644
--- a/src/test/script_P2SH_tests.cpp
+++ b/src/test/script_P2SH_tests.cpp
@@ -112,8 +112,7 @@ BOOST_AUTO_TEST_CASE(sign)
{
CScript sigSave = txTo[i].vin[0].scriptSig;
txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig;
- const CTxOut& output = txFrom.vout[txTo[i].vin[0].prevout.n];
- bool sigOK = CScriptCheck(output.scriptPubKey, output.nValue, txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false, &txdata)();
+ bool sigOK = CScriptCheck(txFrom.vout[txTo[i].vin[0].prevout.n], txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false, &txdata)();
if (i == j)
BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j));
else
diff --git a/src/test/script_standard_tests.cpp b/src/test/script_standard_tests.cpp
new file mode 100644
index 0000000000..3d17a0dbb6
--- /dev/null
+++ b/src/test/script_standard_tests.cpp
@@ -0,0 +1,740 @@
+// 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.
+
+#include "key.h"
+#include "keystore.h"
+#include "script/ismine.h"
+#include "script/script.h"
+#include "script/script_error.h"
+#include "script/standard.h"
+#include "test/test_bitcoin.h"
+
+#include <boost/test/unit_test.hpp>
+
+
+BOOST_FIXTURE_TEST_SUITE(script_standard_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(script_standard_Solver_success)
+{
+ CKey keys[3];
+ CPubKey pubkeys[3];
+ for (int i = 0; i < 3; i++) {
+ keys[i].MakeNewKey(true);
+ pubkeys[i] = keys[i].GetPubKey();
+ }
+
+ CScript s;
+ txnouttype whichType;
+ std::vector<std::vector<unsigned char> > solutions;
+
+ // TX_PUBKEY
+ s.clear();
+ s << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
+ BOOST_CHECK(Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(whichType, TX_PUBKEY);
+ BOOST_CHECK_EQUAL(solutions.size(), 1);
+ BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0]));
+
+ // TX_PUBKEYHASH
+ s.clear();
+ s << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
+ BOOST_CHECK(Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(whichType, TX_PUBKEYHASH);
+ BOOST_CHECK_EQUAL(solutions.size(), 1);
+ BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0].GetID()));
+
+ // TX_SCRIPTHASH
+ CScript redeemScript(s); // initialize with leftover P2PKH script
+ s.clear();
+ s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
+ BOOST_CHECK(Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(whichType, TX_SCRIPTHASH);
+ BOOST_CHECK_EQUAL(solutions.size(), 1);
+ BOOST_CHECK(solutions[0] == ToByteVector(CScriptID(redeemScript)));
+
+ // TX_MULTISIG
+ s.clear();
+ s << OP_1 <<
+ ToByteVector(pubkeys[0]) <<
+ ToByteVector(pubkeys[1]) <<
+ OP_2 << OP_CHECKMULTISIG;
+ BOOST_CHECK(Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(whichType, TX_MULTISIG);
+ BOOST_CHECK_EQUAL(solutions.size(), 4);
+ BOOST_CHECK(solutions[0] == std::vector<unsigned char>({1}));
+ BOOST_CHECK(solutions[1] == ToByteVector(pubkeys[0]));
+ BOOST_CHECK(solutions[2] == ToByteVector(pubkeys[1]));
+ BOOST_CHECK(solutions[3] == std::vector<unsigned char>({2}));
+
+ s.clear();
+ s << OP_2 <<
+ ToByteVector(pubkeys[0]) <<
+ ToByteVector(pubkeys[1]) <<
+ ToByteVector(pubkeys[2]) <<
+ OP_3 << OP_CHECKMULTISIG;
+ BOOST_CHECK(Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(whichType, TX_MULTISIG);
+ BOOST_CHECK_EQUAL(solutions.size(), 5);
+ BOOST_CHECK(solutions[0] == std::vector<unsigned char>({2}));
+ BOOST_CHECK(solutions[1] == ToByteVector(pubkeys[0]));
+ BOOST_CHECK(solutions[2] == ToByteVector(pubkeys[1]));
+ BOOST_CHECK(solutions[3] == ToByteVector(pubkeys[2]));
+ BOOST_CHECK(solutions[4] == std::vector<unsigned char>({3}));
+
+ // TX_NULL_DATA
+ s.clear();
+ s << OP_RETURN <<
+ std::vector<unsigned char>({0}) <<
+ std::vector<unsigned char>({75}) <<
+ std::vector<unsigned char>({255});
+ BOOST_CHECK(Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(whichType, TX_NULL_DATA);
+ BOOST_CHECK_EQUAL(solutions.size(), 0);
+
+ // TX_WITNESS_V0_KEYHASH
+ s.clear();
+ s << OP_0 << ToByteVector(pubkeys[0].GetID());
+ BOOST_CHECK(Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(whichType, TX_WITNESS_V0_KEYHASH);
+ BOOST_CHECK_EQUAL(solutions.size(), 1);
+ BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0].GetID()));
+
+ // TX_WITNESS_V0_SCRIPTHASH
+ uint256 scriptHash;
+ CSHA256().Write(&redeemScript[0], redeemScript.size())
+ .Finalize(scriptHash.begin());
+
+ s.clear();
+ s << OP_0 << ToByteVector(scriptHash);
+ BOOST_CHECK(Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(whichType, TX_WITNESS_V0_SCRIPTHASH);
+ BOOST_CHECK_EQUAL(solutions.size(), 1);
+ BOOST_CHECK(solutions[0] == ToByteVector(scriptHash));
+
+ // TX_NONSTANDARD
+ s.clear();
+ s << OP_9 << OP_ADD << OP_11 << OP_EQUAL;
+ BOOST_CHECK(!Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(whichType, TX_NONSTANDARD);
+}
+
+BOOST_AUTO_TEST_CASE(script_standard_Solver_failure)
+{
+ CKey key;
+ CPubKey pubkey;
+ key.MakeNewKey(true);
+ pubkey = key.GetPubKey();
+
+ CScript s;
+ txnouttype whichType;
+ std::vector<std::vector<unsigned char> > solutions;
+
+ // TX_PUBKEY with incorrectly sized pubkey
+ s.clear();
+ s << std::vector<unsigned char>(30, 0x01) << OP_CHECKSIG;
+ BOOST_CHECK(!Solver(s, whichType, solutions));
+
+ // TX_PUBKEYHASH with incorrectly sized key hash
+ s.clear();
+ s << OP_DUP << OP_HASH160 << ToByteVector(pubkey) << OP_EQUALVERIFY << OP_CHECKSIG;
+ BOOST_CHECK(!Solver(s, whichType, solutions));
+
+ // TX_SCRIPTHASH with incorrectly sized script hash
+ s.clear();
+ s << OP_HASH160 << std::vector<unsigned char>(21, 0x01) << OP_EQUAL;
+ BOOST_CHECK(!Solver(s, whichType, solutions));
+
+ // TX_MULTISIG 0/2
+ s.clear();
+ s << OP_0 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
+ BOOST_CHECK(!Solver(s, whichType, solutions));
+
+ // TX_MULTISIG 2/1
+ s.clear();
+ s << OP_2 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
+ BOOST_CHECK(!Solver(s, whichType, solutions));
+
+ // TX_MULTISIG n = 2 with 1 pubkey
+ s.clear();
+ s << OP_1 << ToByteVector(pubkey) << OP_2 << OP_CHECKMULTISIG;
+ BOOST_CHECK(!Solver(s, whichType, solutions));
+
+ // TX_MULTISIG n = 1 with 0 pubkeys
+ s.clear();
+ s << OP_1 << OP_1 << OP_CHECKMULTISIG;
+ BOOST_CHECK(!Solver(s, whichType, solutions));
+
+ // TX_NULL_DATA with other opcodes
+ s.clear();
+ s << OP_RETURN << std::vector<unsigned char>({75}) << OP_ADD;
+ BOOST_CHECK(!Solver(s, whichType, solutions));
+
+ // TX_WITNESS with unknown version
+ s.clear();
+ s << OP_1 << ToByteVector(pubkey);
+ BOOST_CHECK(!Solver(s, whichType, solutions));
+
+ // TX_WITNESS with incorrect program size
+ s.clear();
+ s << OP_0 << std::vector<unsigned char>(19, 0x01);
+ BOOST_CHECK(!Solver(s, whichType, solutions));
+}
+
+BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination)
+{
+ CKey key;
+ CPubKey pubkey;
+ key.MakeNewKey(true);
+ pubkey = key.GetPubKey();
+
+ CScript s;
+ CTxDestination address;
+
+ // TX_PUBKEY
+ s.clear();
+ s << ToByteVector(pubkey) << OP_CHECKSIG;
+ BOOST_CHECK(ExtractDestination(s, address));
+ BOOST_CHECK(boost::get<CKeyID>(&address) &&
+ *boost::get<CKeyID>(&address) == pubkey.GetID());
+
+ // TX_PUBKEYHASH
+ s.clear();
+ s << OP_DUP << OP_HASH160 << ToByteVector(pubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
+ BOOST_CHECK(ExtractDestination(s, address));
+ BOOST_CHECK(boost::get<CKeyID>(&address) &&
+ *boost::get<CKeyID>(&address) == pubkey.GetID());
+
+ // TX_SCRIPTHASH
+ CScript redeemScript(s); // initialize with leftover P2PKH script
+ s.clear();
+ s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
+ BOOST_CHECK(ExtractDestination(s, address));
+ BOOST_CHECK(boost::get<CScriptID>(&address) &&
+ *boost::get<CScriptID>(&address) == CScriptID(redeemScript));
+
+ // TX_MULTISIG
+ s.clear();
+ s << OP_1 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
+ BOOST_CHECK(!ExtractDestination(s, address));
+
+ // TX_NULL_DATA
+ s.clear();
+ s << OP_RETURN << std::vector<unsigned char>({75});
+ BOOST_CHECK(!ExtractDestination(s, address));
+
+ // TX_WITNESS_V0_KEYHASH
+ s.clear();
+ s << OP_0 << ToByteVector(pubkey);
+ BOOST_CHECK(!ExtractDestination(s, address));
+
+ // TX_WITNESS_V0_SCRIPTHASH
+ s.clear();
+ s << OP_0 << ToByteVector(CScriptID(redeemScript));
+ BOOST_CHECK(!ExtractDestination(s, address));
+}
+
+BOOST_AUTO_TEST_CASE(script_standard_ExtractDestinations)
+{
+ CKey keys[3];
+ CPubKey pubkeys[3];
+ for (int i = 0; i < 3; i++) {
+ keys[i].MakeNewKey(true);
+ pubkeys[i] = keys[i].GetPubKey();
+ }
+
+ CScript s;
+ txnouttype whichType;
+ std::vector<CTxDestination> addresses;
+ int nRequired;
+
+ // TX_PUBKEY
+ s.clear();
+ s << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
+ BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired));
+ BOOST_CHECK_EQUAL(whichType, TX_PUBKEY);
+ BOOST_CHECK_EQUAL(addresses.size(), 1);
+ BOOST_CHECK_EQUAL(nRequired, 1);
+ BOOST_CHECK(boost::get<CKeyID>(&addresses[0]) &&
+ *boost::get<CKeyID>(&addresses[0]) == pubkeys[0].GetID());
+
+ // TX_PUBKEYHASH
+ s.clear();
+ s << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
+ BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired));
+ BOOST_CHECK_EQUAL(whichType, TX_PUBKEYHASH);
+ BOOST_CHECK_EQUAL(addresses.size(), 1);
+ BOOST_CHECK_EQUAL(nRequired, 1);
+ BOOST_CHECK(boost::get<CKeyID>(&addresses[0]) &&
+ *boost::get<CKeyID>(&addresses[0]) == pubkeys[0].GetID());
+
+ // TX_SCRIPTHASH
+ CScript redeemScript(s); // initialize with leftover P2PKH script
+ s.clear();
+ s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
+ BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired));
+ BOOST_CHECK_EQUAL(whichType, TX_SCRIPTHASH);
+ BOOST_CHECK_EQUAL(addresses.size(), 1);
+ BOOST_CHECK_EQUAL(nRequired, 1);
+ BOOST_CHECK(boost::get<CScriptID>(&addresses[0]) &&
+ *boost::get<CScriptID>(&addresses[0]) == CScriptID(redeemScript));
+
+ // TX_MULTISIG
+ s.clear();
+ s << OP_2 <<
+ ToByteVector(pubkeys[0]) <<
+ ToByteVector(pubkeys[1]) <<
+ OP_2 << OP_CHECKMULTISIG;
+ BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired));
+ BOOST_CHECK_EQUAL(whichType, TX_MULTISIG);
+ BOOST_CHECK_EQUAL(addresses.size(), 2);
+ BOOST_CHECK_EQUAL(nRequired, 2);
+ BOOST_CHECK(boost::get<CKeyID>(&addresses[0]) &&
+ *boost::get<CKeyID>(&addresses[0]) == pubkeys[0].GetID());
+ BOOST_CHECK(boost::get<CKeyID>(&addresses[1]) &&
+ *boost::get<CKeyID>(&addresses[1]) == pubkeys[1].GetID());
+
+ // TX_NULL_DATA
+ s.clear();
+ s << OP_RETURN << std::vector<unsigned char>({75});
+ BOOST_CHECK(!ExtractDestinations(s, whichType, addresses, nRequired));
+
+ // TX_WITNESS_V0_KEYHASH
+ s.clear();
+ s << OP_0 << ToByteVector(pubkeys[0].GetID());
+ BOOST_CHECK(!ExtractDestinations(s, whichType, addresses, nRequired));
+
+ // TX_WITNESS_V0_SCRIPTHASH
+ s.clear();
+ s << OP_0 << ToByteVector(CScriptID(redeemScript));
+ BOOST_CHECK(!ExtractDestinations(s, whichType, addresses, nRequired));
+}
+
+BOOST_AUTO_TEST_CASE(script_standard_GetScriptFor_)
+{
+ CKey keys[3];
+ CPubKey pubkeys[3];
+ for (int i = 0; i < 3; i++) {
+ keys[i].MakeNewKey(true);
+ pubkeys[i] = keys[i].GetPubKey();
+ }
+
+ CScript expected, result;
+
+ // CKeyID
+ expected.clear();
+ expected << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
+ result = GetScriptForDestination(pubkeys[0].GetID());
+ BOOST_CHECK(result == expected);
+
+ // CScriptID
+ CScript redeemScript(result);
+ expected.clear();
+ expected << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
+ result = GetScriptForDestination(CScriptID(redeemScript));
+ BOOST_CHECK(result == expected);
+
+ // CNoDestination
+ expected.clear();
+ result = GetScriptForDestination(CNoDestination());
+ BOOST_CHECK(result == expected);
+
+ // GetScriptForRawPubKey
+ expected.clear();
+ expected << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
+ result = GetScriptForRawPubKey(pubkeys[0]);
+ BOOST_CHECK(result == expected);
+
+ // GetScriptForMultisig
+ expected.clear();
+ expected << OP_2 <<
+ ToByteVector(pubkeys[0]) <<
+ ToByteVector(pubkeys[1]) <<
+ ToByteVector(pubkeys[2]) <<
+ OP_3 << OP_CHECKMULTISIG;
+ result = GetScriptForMultisig(2, std::vector<CPubKey>(pubkeys, pubkeys + 3));
+ BOOST_CHECK(result == expected);
+
+ // GetScriptForWitness
+ CScript witnessScript;
+
+ witnessScript << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
+ expected.clear();
+ expected << OP_0 << ToByteVector(pubkeys[0].GetID());
+ result = GetScriptForWitness(witnessScript);
+ BOOST_CHECK(result == expected);
+
+ witnessScript.clear();
+ witnessScript << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
+ result = GetScriptForWitness(witnessScript);
+ BOOST_CHECK(result == expected);
+
+ witnessScript.clear();
+ witnessScript << OP_1 << ToByteVector(pubkeys[0]) << OP_1 << OP_CHECKMULTISIG;
+
+ uint256 scriptHash;
+ CSHA256().Write(&witnessScript[0], witnessScript.size())
+ .Finalize(scriptHash.begin());
+
+ expected.clear();
+ expected << OP_0 << ToByteVector(scriptHash);
+ result = GetScriptForWitness(witnessScript);
+ BOOST_CHECK(result == expected);
+}
+
+BOOST_AUTO_TEST_CASE(script_standard_IsMine)
+{
+ CKey keys[2];
+ CPubKey pubkeys[2];
+ for (int i = 0; i < 2; i++) {
+ keys[i].MakeNewKey(true);
+ pubkeys[i] = keys[i].GetPubKey();
+ }
+
+ CKey uncompressedKey;
+ uncompressedKey.MakeNewKey(false);
+ CPubKey uncompressedPubkey = uncompressedKey.GetPubKey();
+
+ CScript scriptPubKey;
+ isminetype result;
+ bool isInvalid;
+
+ // P2PK compressed
+ {
+ CBasicKeyStore keystore;
+ scriptPubKey.clear();
+ scriptPubKey << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
+
+ // Keystore does not have key
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(!isInvalid);
+
+ // Keystore has key
+ keystore.AddKey(keys[0]);
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ BOOST_CHECK(!isInvalid);
+ }
+
+ // P2PK uncompressed
+ {
+ CBasicKeyStore keystore;
+ scriptPubKey.clear();
+ scriptPubKey << ToByteVector(uncompressedPubkey) << OP_CHECKSIG;
+
+ // Keystore does not have key
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(!isInvalid);
+
+ // Keystore has key
+ keystore.AddKey(uncompressedKey);
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ BOOST_CHECK(!isInvalid);
+ }
+
+ // P2PKH compressed
+ {
+ CBasicKeyStore keystore;
+ scriptPubKey.clear();
+ scriptPubKey << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
+
+ // Keystore does not have key
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(!isInvalid);
+
+ // Keystore has key
+ keystore.AddKey(keys[0]);
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ BOOST_CHECK(!isInvalid);
+ }
+
+ // P2PKH uncompressed
+ {
+ CBasicKeyStore keystore;
+ scriptPubKey.clear();
+ scriptPubKey << OP_DUP << OP_HASH160 << ToByteVector(uncompressedPubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
+
+ // Keystore does not have key
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(!isInvalid);
+
+ // Keystore has key
+ keystore.AddKey(uncompressedKey);
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ BOOST_CHECK(!isInvalid);
+ }
+
+ // P2SH
+ {
+ CBasicKeyStore keystore;
+
+ CScript redeemScript;
+ redeemScript << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
+
+ scriptPubKey.clear();
+ scriptPubKey << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
+
+ // Keystore does not have redeemScript or key
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(!isInvalid);
+
+ // Keystore has redeemScript but no key
+ keystore.AddCScript(redeemScript);
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(!isInvalid);
+
+ // Keystore has redeemScript and key
+ keystore.AddKey(keys[0]);
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ BOOST_CHECK(!isInvalid);
+ }
+
+ // P2WPKH compressed
+ {
+ CBasicKeyStore keystore;
+ keystore.AddKey(keys[0]);
+
+ scriptPubKey.clear();
+ scriptPubKey << OP_0 << ToByteVector(pubkeys[0].GetID());
+
+ // Keystore has key, but no P2SH redeemScript
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(!isInvalid);
+
+ // Keystore has key and P2SH redeemScript
+ keystore.AddCScript(scriptPubKey);
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ BOOST_CHECK(!isInvalid);
+ }
+
+ // P2WPKH uncompressed
+ {
+ CBasicKeyStore keystore;
+ keystore.AddKey(uncompressedKey);
+
+ scriptPubKey.clear();
+ scriptPubKey << OP_0 << ToByteVector(uncompressedPubkey.GetID());
+
+ // Keystore has key, but no P2SH redeemScript
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(!isInvalid);
+
+ // Keystore has key and P2SH redeemScript
+ keystore.AddCScript(scriptPubKey);
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(isInvalid);
+ }
+
+ // scriptPubKey multisig
+ {
+ CBasicKeyStore keystore;
+
+ scriptPubKey.clear();
+ scriptPubKey << OP_2 <<
+ ToByteVector(uncompressedPubkey) <<
+ ToByteVector(pubkeys[1]) <<
+ OP_2 << OP_CHECKMULTISIG;
+
+ // Keystore does not have any keys
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(!isInvalid);
+
+ // Keystore has 1/2 keys
+ keystore.AddKey(uncompressedKey);
+
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(!isInvalid);
+
+ // Keystore has 2/2 keys
+ keystore.AddKey(keys[1]);
+
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ BOOST_CHECK(!isInvalid);
+ }
+
+ // P2SH multisig
+ {
+ CBasicKeyStore keystore;
+ keystore.AddKey(uncompressedKey);
+ keystore.AddKey(keys[1]);
+
+ CScript redeemScript;
+ redeemScript << OP_2 <<
+ ToByteVector(uncompressedPubkey) <<
+ ToByteVector(pubkeys[1]) <<
+ OP_2 << OP_CHECKMULTISIG;
+
+ scriptPubKey.clear();
+ scriptPubKey << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
+
+ // Keystore has no redeemScript
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(!isInvalid);
+
+ // Keystore has redeemScript
+ keystore.AddCScript(redeemScript);
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ BOOST_CHECK(!isInvalid);
+ }
+
+ // P2WSH multisig with compressed keys
+ {
+ CBasicKeyStore keystore;
+ keystore.AddKey(keys[0]);
+ keystore.AddKey(keys[1]);
+
+ CScript witnessScript;
+ witnessScript << OP_2 <<
+ ToByteVector(pubkeys[0]) <<
+ ToByteVector(pubkeys[1]) <<
+ OP_2 << OP_CHECKMULTISIG;
+
+ uint256 scriptHash;
+ CSHA256().Write(&witnessScript[0], witnessScript.size())
+ .Finalize(scriptHash.begin());
+
+ scriptPubKey.clear();
+ scriptPubKey << OP_0 << ToByteVector(scriptHash);
+
+ // Keystore has keys, but no witnessScript or P2SH redeemScript
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(!isInvalid);
+
+ // Keystore has keys and witnessScript, but no P2SH redeemScript
+ keystore.AddCScript(witnessScript);
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(!isInvalid);
+
+ // Keystore has keys, witnessScript, P2SH redeemScript
+ keystore.AddCScript(scriptPubKey);
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ BOOST_CHECK(!isInvalid);
+ }
+
+ // P2WSH multisig with uncompressed key
+ {
+ CBasicKeyStore keystore;
+ keystore.AddKey(uncompressedKey);
+ keystore.AddKey(keys[1]);
+
+ CScript witnessScript;
+ witnessScript << OP_2 <<
+ ToByteVector(uncompressedPubkey) <<
+ ToByteVector(pubkeys[1]) <<
+ OP_2 << OP_CHECKMULTISIG;
+
+ uint256 scriptHash;
+ CSHA256().Write(&witnessScript[0], witnessScript.size())
+ .Finalize(scriptHash.begin());
+
+ scriptPubKey.clear();
+ scriptPubKey << OP_0 << ToByteVector(scriptHash);
+
+ // Keystore has keys, but no witnessScript or P2SH redeemScript
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(!isInvalid);
+
+ // Keystore has keys and witnessScript, but no P2SH redeemScript
+ keystore.AddCScript(witnessScript);
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(!isInvalid);
+
+ // Keystore has keys, witnessScript, P2SH redeemScript
+ keystore.AddCScript(scriptPubKey);
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(isInvalid);
+ }
+
+ // P2WSH multisig wrapped in P2SH
+ {
+ CBasicKeyStore keystore;
+
+ CScript witnessScript;
+ witnessScript << OP_2 <<
+ ToByteVector(pubkeys[0]) <<
+ ToByteVector(pubkeys[1]) <<
+ OP_2 << OP_CHECKMULTISIG;
+
+ uint256 scriptHash;
+ CSHA256().Write(&witnessScript[0], witnessScript.size())
+ .Finalize(scriptHash.begin());
+
+ CScript redeemScript;
+ redeemScript << OP_0 << ToByteVector(scriptHash);
+
+ scriptPubKey.clear();
+ scriptPubKey << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
+
+ // Keystore has no witnessScript, P2SH redeemScript, or keys
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(!isInvalid);
+
+ // Keystore has witnessScript and P2SH redeemScript, but no keys
+ keystore.AddCScript(redeemScript);
+ keystore.AddCScript(witnessScript);
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(!isInvalid);
+
+ // Keystore has keys, witnessScript, P2SH redeemScript
+ keystore.AddKey(keys[0]);
+ keystore.AddKey(keys[1]);
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ BOOST_CHECK(!isInvalid);
+ }
+
+ // OP_RETURN
+ {
+ CBasicKeyStore keystore;
+ keystore.AddKey(keys[0]);
+
+ scriptPubKey.clear();
+ scriptPubKey << OP_RETURN << ToByteVector(pubkeys[0]);
+
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(!isInvalid);
+ }
+
+ // Nonstandard
+ {
+ CBasicKeyStore keystore;
+ keystore.AddKey(keys[0]);
+
+ scriptPubKey.clear();
+ scriptPubKey << OP_9 << OP_ADD << OP_11 << OP_EQUAL;
+
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(!isInvalid);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp
index e3654e67ad..164cbd873f 100644
--- a/src/test/skiplist_tests.cpp
+++ b/src/test/skiplist_tests.cpp
@@ -39,7 +39,7 @@ BOOST_AUTO_TEST_CASE(skiplist_test)
BOOST_CHECK(vIndex[SKIPLIST_LENGTH - 1].GetAncestor(from) == &vIndex[from]);
BOOST_CHECK(vIndex[from].GetAncestor(to) == &vIndex[to]);
- BOOST_CHECK(vIndex[from].GetAncestor(0) == &vIndex[0]);
+ BOOST_CHECK(vIndex[from].GetAncestor(0) == vIndex.data());
}
}
@@ -64,7 +64,7 @@ BOOST_AUTO_TEST_CASE(getlocator_test)
for (unsigned int i=0; i<vBlocksSide.size(); i++) {
vHashSide[i] = ArithToUint256(i + 50000 + (arith_uint256(1) << 128)); // Add 1<<128 to the hashes, so GetLow64() still returns the height.
vBlocksSide[i].nHeight = i + 50000;
- vBlocksSide[i].pprev = i ? &vBlocksSide[i - 1] : &vBlocksMain[49999];
+ vBlocksSide[i].pprev = i ? &vBlocksSide[i - 1] : (vBlocksMain.data()+49999);
vBlocksSide[i].phashBlock = &vHashSide[i];
vBlocksSide[i].BuildSkip();
BOOST_CHECK_EQUAL((int)UintToArith256(vBlocksSide[i].GetBlockHash()).GetLow64(), vBlocksSide[i].nHeight);
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index 94ec7c03f5..045655983c 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -22,8 +22,6 @@
#include "rpc/register.h"
#include "script/sigcache.h"
-#include "test/testutil.h"
-
#include <memory>
uint256 insecure_rand_seed = GetRandHash();
@@ -50,7 +48,6 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
BasicTestingSetup::~BasicTestingSetup()
{
ECC_Stop();
- g_connman.reset();
}
TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(chainName)
@@ -61,7 +58,7 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
RegisterAllCoreRPCCommands(tableRPC);
ClearDatadirCache();
- pathTemp = GetTempPath() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(100000)));
+ pathTemp = fs::temp_directory_path() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(100000)));
fs::create_directories(pathTemp);
gArgs.ForceSetArg("-datadir", pathTemp.string());
@@ -88,16 +85,17 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
threadGroup.create_thread(&ThreadScriptCheck);
g_connman = std::unique_ptr<CConnman>(new CConnman(0x1337, 0x1337)); // Deterministic randomness for tests.
connman = g_connman.get();
- RegisterNodeSignals(GetNodeSignals());
+ peerLogic.reset(new PeerLogicValidation(connman));
}
TestingSetup::~TestingSetup()
{
- UnregisterNodeSignals(GetNodeSignals());
threadGroup.interrupt_all();
threadGroup.join_all();
GetMainSignals().FlushBackgroundCallbacks();
GetMainSignals().UnregisterBackgroundSignalScheduler();
+ g_connman.reset();
+ peerLogic.reset();
UnloadBlockIndex();
delete pcoinsTip;
delete pcoinsdbview;
diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h
index 2ddac2f076..6ada96f887 100644
--- a/src/test/test_bitcoin.h
+++ b/src/test/test_bitcoin.h
@@ -49,12 +49,14 @@ struct BasicTestingSetup {
* Included are data directory, coins database, script check threads setup.
*/
class CConnman;
+class PeerLogicValidation;
struct TestingSetup: public BasicTestingSetup {
CCoinsViewDB *pcoinsdbview;
fs::path pathTemp;
boost::thread_group threadGroup;
CConnman* connman;
CScheduler scheduler;
+ std::unique_ptr<PeerLogicValidation> peerLogic;
explicit TestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
~TestingSetup();
diff --git a/src/test/test_bitcoin_fuzzy.cpp b/src/test/test_bitcoin_fuzzy.cpp
index de14251601..50e4076d07 100644
--- a/src/test/test_bitcoin_fuzzy.cpp
+++ b/src/test/test_bitcoin_fuzzy.cpp
@@ -67,7 +67,7 @@ int do_fuzz()
if (buffer.size() < sizeof(uint32_t)) return 0;
uint32_t test_id = 0xffffffff;
- memcpy(&test_id, &buffer[0], sizeof(uint32_t));
+ memcpy(&test_id, buffer.data(), sizeof(uint32_t));
buffer.erase(buffer.begin(), buffer.begin() + sizeof(uint32_t));
if (test_id >= TEST_ID_END) return 0;
diff --git a/src/test/testutil.cpp b/src/test/testutil.cpp
deleted file mode 100644
index 591d0bf302..0000000000
--- a/src/test/testutil.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2009-2016 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#include "testutil.h"
-
-#ifdef WIN32
-#include <shlobj.h>
-#endif
-
-#include "fs.h"
-
-fs::path GetTempPath() {
- return fs::temp_directory_path();
-}
diff --git a/src/test/testutil.h b/src/test/testutil.h
deleted file mode 100644
index cbe784d640..0000000000
--- a/src/test/testutil.h
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2009-2016 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-/**
- * Utility functions shared by unit tests
- */
-#ifndef BITCOIN_TEST_TESTUTIL_H
-#define BITCOIN_TEST_TESTUTIL_H
-
-#include "fs.h"
-
-fs::path GetTempPath();
-
-#endif // BITCOIN_TEST_TESTUTIL_H
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index 6654634bf1..cb6ab7cdbe 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -480,8 +480,7 @@ BOOST_AUTO_TEST_CASE(test_big_witness_transaction) {
for(uint32_t i = 0; i < mtx.vin.size(); i++) {
std::vector<CScriptCheck> vChecks;
- const CTxOut& output = coins[tx.vin[i].prevout.n].out;
- CScriptCheck check(output.scriptPubKey, output.nValue, tx, i, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false, &txdata);
+ CScriptCheck check(coins[tx.vin[i].prevout.n].out, tx, i, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false, &txdata);
vChecks.push_back(CScriptCheck());
check.swap(vChecks.back());
control.Add(vChecks);
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 5679086969..6ec544290d 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -253,6 +253,31 @@ BOOST_AUTO_TEST_CASE(util_IsHex)
BOOST_CHECK(!IsHex("0x0000"));
}
+BOOST_AUTO_TEST_CASE(util_IsHexNumber)
+{
+ BOOST_CHECK(IsHexNumber("0x0"));
+ BOOST_CHECK(IsHexNumber("0"));
+ BOOST_CHECK(IsHexNumber("0x10"));
+ BOOST_CHECK(IsHexNumber("10"));
+ BOOST_CHECK(IsHexNumber("0xff"));
+ BOOST_CHECK(IsHexNumber("ff"));
+ BOOST_CHECK(IsHexNumber("0xFfa"));
+ BOOST_CHECK(IsHexNumber("Ffa"));
+ BOOST_CHECK(IsHexNumber("0x00112233445566778899aabbccddeeffAABBCCDDEEFF"));
+ BOOST_CHECK(IsHexNumber("00112233445566778899aabbccddeeffAABBCCDDEEFF"));
+
+ BOOST_CHECK(!IsHexNumber("")); // empty string not allowed
+ BOOST_CHECK(!IsHexNumber("0x")); // empty string after prefix not allowed
+ BOOST_CHECK(!IsHexNumber("0x0 ")); // no spaces at end,
+ BOOST_CHECK(!IsHexNumber(" 0x0")); // or beginning,
+ BOOST_CHECK(!IsHexNumber("0x 0")); // or middle,
+ BOOST_CHECK(!IsHexNumber(" ")); // etc.
+ BOOST_CHECK(!IsHexNumber("0x0ga")); // invalid character
+ BOOST_CHECK(!IsHexNumber("x0")); // broken prefix
+ BOOST_CHECK(!IsHexNumber("0x0x00")); // two prefixes not allowed
+
+}
+
BOOST_AUTO_TEST_CASE(util_seed_insecure_rand)
{
SeedInsecureRand(true);
diff --git a/src/txdb.cpp b/src/txdb.cpp
index 797ae5713f..134bb8721b 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -371,9 +371,9 @@ bool CCoinsViewDB::Upgrade() {
int64_t count = 0;
LogPrintf("Upgrading utxo-set database...\n");
LogPrintf("[0%%]...");
+ uiInterface.ShowProgress(_("Upgrading UTXO database"), 0, true);
size_t batch_size = 1 << 24;
CDBBatch batch(db);
- uiInterface.SetProgressBreakAction(StartShutdown);
int reportDone = 0;
std::pair<unsigned char, uint256> key;
std::pair<unsigned char, uint256> prev_key = {DB_COINS, uint256()};
@@ -386,7 +386,7 @@ bool CCoinsViewDB::Upgrade() {
if (count++ % 256 == 0) {
uint32_t high = 0x100 * *key.second.begin() + *(key.second.begin() + 1);
int percentageDone = (int)(high * 100.0 / 65536.0 + 0.5);
- uiInterface.ShowProgress(_("Upgrading UTXO database") + "\n"+ _("(press q to shutdown and continue later)") + "\n", percentageDone);
+ uiInterface.ShowProgress(_("Upgrading UTXO database"), percentageDone, true);
if (reportDone < percentageDone/10) {
// report max. every 10% step
LogPrintf("[%d%%]...", percentageDone);
@@ -420,7 +420,7 @@ bool CCoinsViewDB::Upgrade() {
}
db.WriteBatch(batch);
db.CompactRange({DB_COINS, uint256()}, key);
- uiInterface.SetProgressBreakAction(std::function<void(void)>());
+ uiInterface.ShowProgress("", 100, false);
LogPrintf("[%s].\n", ShutdownRequested() ? "CANCELLED" : "DONE");
return !ShutdownRequested();
}
diff --git a/src/txdb.h b/src/txdb.h
index d1cd5a4250..c254ba91c8 100644
--- a/src/txdb.h
+++ b/src/txdb.h
@@ -110,10 +110,10 @@ class CBlockTreeDB : public CDBWrapper
{
public:
explicit CBlockTreeDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false);
-private:
- CBlockTreeDB(const CBlockTreeDB&);
- void operator=(const CBlockTreeDB&);
-public:
+
+ CBlockTreeDB(const CBlockTreeDB&) = delete;
+ CBlockTreeDB& operator=(const CBlockTreeDB&) = delete;
+
bool WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo);
bool ReadBlockFileInfo(int nFile, CBlockFileInfo &fileinfo);
bool ReadLastBlockFile(int &nFile);
diff --git a/src/txmempool.h b/src/txmempool.h
index 65586a6e6e..b07886579c 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -21,11 +21,10 @@
#include "sync.h"
#include "random.h"
-#include "boost/multi_index_container.hpp"
-#include "boost/multi_index/ordered_index.hpp"
-#include "boost/multi_index/hashed_index.hpp"
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/hashed_index.hpp>
+#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
-
#include <boost/signals2/signal.hpp>
class CBlockIndex;
diff --git a/src/ui_interface.h b/src/ui_interface.h
index 762dd19b19..7f68c578ee 100644
--- a/src/ui_interface.h
+++ b/src/ui_interface.h
@@ -94,11 +94,11 @@ public:
/** A wallet has been loaded. */
boost::signals2::signal<void (CWallet* wallet)> LoadWallet;
- /** Show progress e.g. for verifychain */
- boost::signals2::signal<void (const std::string &title, int nProgress)> ShowProgress;
-
- /** Set progress break action (possible "cancel button" triggers that action) */
- boost::signals2::signal<void (std::function<void(void)> action)> SetProgressBreakAction;
+ /**
+ * Show progress e.g. for verifychain.
+ * resume_possible indicates shutting down now will result in the current progress action resuming upon restart.
+ */
+ boost::signals2::signal<void (const std::string &title, int nProgress, bool resume_possible)> ShowProgress;
/** New block has been accepted */
boost::signals2::signal<void (bool, const CBlockIndex *)> NotifyBlockTip;
diff --git a/src/uint256.cpp b/src/uint256.cpp
index c4c7b716fe..736a0d4fe2 100644
--- a/src/uint256.cpp
+++ b/src/uint256.cpp
@@ -14,7 +14,7 @@ template <unsigned int BITS>
base_blob<BITS>::base_blob(const std::vector<unsigned char>& vch)
{
assert(vch.size() == sizeof(data));
- memcpy(data, &vch[0], sizeof(data));
+ memcpy(data, vch.data(), sizeof(data));
}
template <unsigned int BITS>
diff --git a/src/uint256.h b/src/uint256.h
index 3ed694d723..94a4f7fc30 100644
--- a/src/uint256.h
+++ b/src/uint256.h
@@ -111,7 +111,6 @@ public:
class uint160 : public base_blob<160> {
public:
uint160() {}
- explicit uint160(const base_blob<160>& b) : base_blob<160>(b) {}
explicit uint160(const std::vector<unsigned char>& vch) : base_blob<160>(vch) {}
};
@@ -123,7 +122,6 @@ public:
class uint256 : public base_blob<256> {
public:
uint256() {}
- explicit uint256(const base_blob<256>& b) : base_blob<256>(b) {}
explicit uint256(const std::vector<unsigned char>& vch) : base_blob<256>(vch) {}
/** A cheap hash function that just returns 64 bits from the result, it can be
diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp
index fd233f6757..741680e93f 100644
--- a/src/utilstrencodings.cpp
+++ b/src/utilstrencodings.cpp
@@ -65,6 +65,19 @@ bool IsHex(const std::string& str)
return (str.size() > 0) && (str.size()%2 == 0);
}
+bool IsHexNumber(const std::string& str)
+{
+ size_t starting_location = 0;
+ if (str.size() > 2 && *str.begin() == '0' && *(str.begin()+1) == 'x') {
+ starting_location = 2;
+ }
+ for (auto c : str.substr(starting_location)) {
+ if (HexDigit(c) < 0) return false;
+ }
+ // Return false for empty string or "0x".
+ return (str.size() > starting_location);
+}
+
std::vector<unsigned char> ParseHex(const char* psz)
{
// convert hex dump to vector
diff --git a/src/utilstrencodings.h b/src/utilstrencodings.h
index 53da60e8f1..192f33fb29 100644
--- a/src/utilstrencodings.h
+++ b/src/utilstrencodings.h
@@ -38,7 +38,13 @@ std::string SanitizeString(const std::string& str, int rule = SAFE_CHARS_DEFAULT
std::vector<unsigned char> ParseHex(const char* psz);
std::vector<unsigned char> ParseHex(const std::string& str);
signed char HexDigit(char c);
+/* Returns true if each character in str is a hex character, and has an even
+ * number of hex digits.*/
bool IsHex(const std::string& str);
+/**
+* Return true if the string is a hex number, optionally prefixed with "0x"
+*/
+bool IsHexNumber(const std::string& str);
std::vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid = nullptr);
std::string DecodeBase64(const std::string& str);
std::string EncodeBase64(const unsigned char* pch, size_t len);
diff --git a/src/validation.cpp b/src/validation.cpp
index 3b9636839d..bd9640e749 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -83,6 +83,7 @@ int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE;
bool fEnableReplacement = DEFAULT_ENABLE_REPLACEMENT;
uint256 hashAssumeValid;
+arith_uint256 nMinimumChainWork;
CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE;
@@ -218,7 +219,7 @@ bool CheckFinalTx(const CTransaction &tx, int flags)
// IsFinalTx() with one more than chainActive.Height().
const int nBlockHeight = chainActive.Height() + 1;
- // BIP113 will require that time-locked transactions have nLockTime set to
+ // BIP113 requires that time-locked transactions have nLockTime set to
// less than the median time of the previous block they're contained in.
// When the next block is created its previous block will be the current
// chain tip, so we use that to calculate the median time passed to
@@ -254,6 +255,8 @@ bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp, bool
AssertLockHeld(mempool.cs);
CBlockIndex* tip = chainActive.Tip();
+ assert(tip != nullptr);
+
CBlockIndex index;
index.pprev = tip;
// CheckSequenceLocks() uses chainActive.Height()+1 to evaluate
@@ -1035,8 +1038,6 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams)
bool IsInitialBlockDownload()
{
- const CChainParams& chainParams = Params();
-
// Once this function has returned false, it must remain false.
static std::atomic<bool> latchToFalse{false};
// Optimization: pre-test latch before taking the lock.
@@ -1050,7 +1051,7 @@ bool IsInitialBlockDownload()
return true;
if (chainActive.Tip() == nullptr)
return true;
- if (chainActive.Tip()->nChainWork < UintToArith256(chainParams.GetConsensus().nMinimumChainWork))
+ if (chainActive.Tip()->nChainWork < nMinimumChainWork)
return true;
if (chainActive.Tip()->GetBlockTime() < (GetTime() - nMaxTipAge))
return true;
@@ -1202,7 +1203,7 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight)
bool CScriptCheck::operator()() {
const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;
const CScriptWitness *witness = &ptxTo->vin[nIn].scriptWitness;
- return VerifyScript(scriptSig, scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore, *txdata), &error);
+ return VerifyScript(scriptSig, m_tx_out.scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, m_tx_out.nValue, cacheStore, *txdata), &error);
}
int GetSpendHeight(const CCoinsViewCache& inputs)
@@ -1284,11 +1285,9 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
// a sanity check that our caching is not introducing consensus
// failures through additional data in, eg, the coins being
// spent being checked as a part of CScriptCheck.
- const CScript& scriptPubKey = coin.out.scriptPubKey;
- const CAmount amount = coin.out.nValue;
// Verify signature
- CScriptCheck check(scriptPubKey, amount, tx, i, flags, cacheSigStore, &txdata);
+ CScriptCheck check(coin.out, tx, i, flags, cacheSigStore, &txdata);
if (pvChecks) {
pvChecks->push_back(CScriptCheck());
check.swap(pvChecks->back());
@@ -1300,7 +1299,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
// arguments; if so, don't trigger DoS protection to
// avoid splitting the network between upgraded and
// non-upgraded nodes.
- CScriptCheck check2(scriptPubKey, amount, tx, i,
+ CScriptCheck check2(coin.out, tx, i,
flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheSigStore, &txdata);
if (check2())
return state.Invalid(false, REJECT_NONSTANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError())));
@@ -1670,7 +1669,7 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd
if (it != mapBlockIndex.end()) {
if (it->second->GetAncestor(pindex->nHeight) == pindex &&
pindexBestHeader->GetAncestor(pindex->nHeight) == pindex &&
- pindexBestHeader->nChainWork >= UintToArith256(chainparams.GetConsensus().nMinimumChainWork)) {
+ pindexBestHeader->nChainWork >= nMinimumChainWork) {
// This block is a member of the assumed verified chain and an ancestor of the best header.
// The equivalent time check discourages hash power from extorting the network via DOS attack
// into accepting an invalid block through telling users they must manually set assumevalid.
@@ -1710,6 +1709,7 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd
// before the first had been spent. Since those coinbases are sufficiently buried its no longer possible to create further
// duplicate transactions descending from the known pairs either.
// If we're on the known chain at height greater than where BIP34 activated, we can save the db accesses needed for the BIP30 check.
+ assert(pindex->pprev);
CBlockIndex *pindexBIP34height = pindex->pprev->GetAncestor(chainparams.GetConsensus().BIP34Height);
//Only continue to enforce if we're below BIP34 activation height or the block hash at that height doesn't correspond.
fEnforceBIP30 = fEnforceBIP30 && (!pindexBIP34height || !(pindexBIP34height->GetBlockHash() == chainparams.GetConsensus().BIP34Hash));
@@ -1849,6 +1849,7 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd
if (!pblocktree->WriteTxIndex(vPos))
return AbortNode(state, "Failed to write transaction index");
+ assert(pindex->phashBlock);
// add this block to the view's block chain
view.SetBestBlock(pindex->GetBlockHash());
@@ -3569,12 +3570,12 @@ bool LoadChainTip(const CChainParams& chainparams)
CVerifyDB::CVerifyDB()
{
- uiInterface.ShowProgress(_("Verifying blocks..."), 0);
+ uiInterface.ShowProgress(_("Verifying blocks..."), 0, false);
}
CVerifyDB::~CVerifyDB()
{
- uiInterface.ShowProgress("", 100);
+ uiInterface.ShowProgress("", 100, false);
}
bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, int nCheckLevel, int nCheckDepth)
@@ -3604,7 +3605,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
LogPrintf("[%d%%]...", percentageDone);
reportDone = percentageDone/10;
}
- uiInterface.ShowProgress(_("Verifying blocks..."), percentageDone);
+ uiInterface.ShowProgress(_("Verifying blocks..."), percentageDone, false);
if (pindex->nHeight < chainActive.Height()-nCheckDepth)
break;
if (fPruneMode && !(pindex->nStatus & BLOCK_HAVE_DATA)) {
@@ -3655,7 +3656,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
CBlockIndex *pindex = pindexState;
while (pindex != chainActive.Tip()) {
boost::this_thread::interruption_point();
- uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, 100 - (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * 50))));
+ uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, 100 - (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * 50))), false);
pindex = chainActive.Next(pindex);
CBlock block;
if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus()))
@@ -3702,7 +3703,7 @@ bool ReplayBlocks(const CChainParams& params, CCoinsView* view)
if (hashHeads.empty()) return true; // We're already in a consistent state.
if (hashHeads.size() != 2) return error("ReplayBlocks(): unknown inconsistent state");
- uiInterface.ShowProgress(_("Replaying blocks..."), 0);
+ uiInterface.ShowProgress(_("Replaying blocks..."), 0, false);
LogPrintf("Replaying blocks\n");
const CBlockIndex* pindexOld = nullptr; // Old tip during the interrupted flush.
@@ -3753,7 +3754,7 @@ bool ReplayBlocks(const CChainParams& params, CCoinsView* view)
cache.SetBestBlock(pindexNew->GetBlockHash());
cache.Flush();
- uiInterface.ShowProgress("", 100);
+ uiInterface.ShowProgress("", 100, false);
return true;
}
@@ -4332,7 +4333,7 @@ bool LoadMempool(void)
return true;
}
-void DumpMempool(void)
+bool DumpMempool(void)
{
int64_t start = GetTimeMicros();
@@ -4352,7 +4353,7 @@ void DumpMempool(void)
try {
FILE* filestr = fsbridge::fopen(GetDataDir() / "mempool.dat.new", "wb");
if (!filestr) {
- return;
+ return false;
}
CAutoFile file(filestr, SER_DISK, CLIENT_VERSION);
@@ -4376,7 +4377,9 @@ void DumpMempool(void)
LogPrintf("Dumped mempool: %gs to copy, %gs to dump\n", (mid-start)*MICRO, (last-mid)*MICRO);
} catch (const std::exception& e) {
LogPrintf("Failed to dump mempool: %s. Continuing anyway.\n", e.what());
+ return false;
}
+ return true;
}
//! Guess how far we are in the verification process at the given block index
diff --git a/src/validation.h b/src/validation.h
index d0f6cdc135..bba621b84f 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -45,9 +45,9 @@ struct ChainTxData;
struct PrecomputedTransactionData;
struct LockPoints;
-/** Default for DEFAULT_WHITELISTRELAY. */
+/** Default for -whitelistrelay. */
static const bool DEFAULT_WHITELISTRELAY = true;
-/** Default for DEFAULT_WHITELISTFORCERELAY. */
+/** Default for -whitelistforcerelay. */
static const bool DEFAULT_WHITELISTFORCERELAY = true;
/** Default for -minrelaytxfee, minimum relay fee for transactions */
static const unsigned int DEFAULT_MIN_RELAY_TX_FEE = 1000;
@@ -94,8 +94,8 @@ static const int MAX_CMPCTBLOCK_DEPTH = 5;
static const int MAX_BLOCKTXN_DEPTH = 10;
/** Size of the "block download window": how far ahead of our current height do we fetch?
* Larger windows tolerate larger download speed differences between peer, but increase the potential
- * degree of disordering of blocks on disk (which make reindexing and in the future perhaps pruning
- * harder). We'll probably want to make this a per-peer adaptive value at some point. */
+ * degree of disordering of blocks on disk (which make reindexing and pruning harder). We'll probably
+ * want to make this a per-peer adaptive value at some point. */
static const unsigned int BLOCK_DOWNLOAD_WINDOW = 1024;
/** Time to wait (in seconds) between writing blocks/block index to disk. */
static const unsigned int DATABASE_WRITE_INTERVAL = 60 * 60;
@@ -161,7 +161,6 @@ extern CTxMemPool mempool;
typedef std::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap;
extern BlockMap mapBlockIndex;
extern uint64_t nLastBlockTx;
-extern uint64_t nLastBlockSize;
extern uint64_t nLastBlockWeight;
extern const std::string strMessageMagic;
extern CWaitableCriticalSection csBestBlock;
@@ -186,6 +185,9 @@ extern bool fEnableReplacement;
/** Block hash whose ancestors we will assume to have valid scripts without checking them. */
extern uint256 hashAssumeValid;
+/** Minimum work we will assume exists on some valid chain. */
+extern arith_uint256 nMinimumChainWork;
+
/** Best header we've seen so far (used for getheaders queries' starting points). */
extern CBlockIndex *pindexBestHeader;
@@ -355,8 +357,7 @@ bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp = null
class CScriptCheck
{
private:
- CScript scriptPubKey;
- CAmount amount;
+ CTxOut m_tx_out;
const CTransaction *ptxTo;
unsigned int nIn;
unsigned int nFlags;
@@ -365,17 +366,15 @@ private:
PrecomputedTransactionData *txdata;
public:
- CScriptCheck(): amount(0), ptxTo(nullptr), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {}
- CScriptCheck(const CScript& scriptPubKeyIn, const CAmount amountIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn, PrecomputedTransactionData* txdataIn) :
- scriptPubKey(scriptPubKeyIn), amount(amountIn),
- ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR), txdata(txdataIn) { }
+ CScriptCheck(): ptxTo(nullptr), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {}
+ CScriptCheck(const CTxOut& outIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn, PrecomputedTransactionData* txdataIn) :
+ m_tx_out(outIn), ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR), txdata(txdataIn) { }
bool operator()();
void swap(CScriptCheck &check) {
- scriptPubKey.swap(check.scriptPubKey);
std::swap(ptxTo, check.ptxTo);
- std::swap(amount, check.amount);
+ std::swap(m_tx_out, check.m_tx_out);
std::swap(nIn, check.nIn);
std::swap(nFlags, check.nFlags);
std::swap(cacheStore, check.cacheStore);
@@ -475,7 +474,7 @@ static const unsigned int REJECT_HIGHFEE = 0x100;
CBlockFileInfo* GetBlockFileInfo(size_t n);
/** Dump the mempool to disk. */
-void DumpMempool();
+bool DumpMempool();
/** Load the mempool from disk. */
bool LoadMempool();
diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp
index dcce88cedc..8db3bfd69c 100644
--- a/src/wallet/crypter.cpp
+++ b/src/wallet/crypter.cpp
@@ -27,8 +27,7 @@ int CCrypter::BytesToKeySHA512AES(const std::vector<unsigned char>& chSalt, cons
CSHA512 di;
di.Write((const unsigned char*)strKeyData.c_str(), strKeyData.size());
- if(chSalt.size())
- di.Write(&chSalt[0], chSalt.size());
+ di.Write(chSalt.data(), chSalt.size());
di.Finalize(buf);
for(int i = 0; i != count - 1; i++)
@@ -82,7 +81,7 @@ bool CCrypter::Encrypt(const CKeyingMaterial& vchPlaintext, std::vector<unsigned
vchCiphertext.resize(vchPlaintext.size() + AES_BLOCKSIZE);
AES256CBCEncrypt enc(vchKey.data(), vchIV.data(), true);
- size_t nLen = enc.Encrypt(&vchPlaintext[0], vchPlaintext.size(), &vchCiphertext[0]);
+ size_t nLen = enc.Encrypt(&vchPlaintext[0], vchPlaintext.size(), vchCiphertext.data());
if(nLen < vchPlaintext.size())
return false;
vchCiphertext.resize(nLen);
@@ -101,7 +100,7 @@ bool CCrypter::Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingM
vchPlaintext.resize(nLen);
AES256CBCDecrypt dec(vchKey.data(), vchIV.data(), true);
- nLen = dec.Decrypt(&vchCiphertext[0], vchCiphertext.size(), &vchPlaintext[0]);
+ nLen = dec.Decrypt(vchCiphertext.data(), vchCiphertext.size(), &vchPlaintext[0]);
if(nLen == 0)
return false;
vchPlaintext.resize(nLen);
@@ -113,7 +112,7 @@ static bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMateri
{
CCrypter cKeyCrypter;
std::vector<unsigned char> chIV(WALLET_CRYPTO_IV_SIZE);
- memcpy(&chIV[0], &nIV, WALLET_CRYPTO_IV_SIZE);
+ memcpy(chIV.data(), &nIV, WALLET_CRYPTO_IV_SIZE);
if(!cKeyCrypter.SetKey(vMasterKey, chIV))
return false;
return cKeyCrypter.Encrypt(*((const CKeyingMaterial*)&vchPlaintext), vchCiphertext);
@@ -123,7 +122,7 @@ static bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<u
{
CCrypter cKeyCrypter;
std::vector<unsigned char> chIV(WALLET_CRYPTO_IV_SIZE);
- memcpy(&chIV[0], &nIV, WALLET_CRYPTO_IV_SIZE);
+ memcpy(chIV.data(), &nIV, WALLET_CRYPTO_IV_SIZE);
if(!cKeyCrypter.SetKey(vMasterKey, chIV))
return false;
return cKeyCrypter.Decrypt(vchCiphertext, *((CKeyingMaterial*)&vchPlaintext));
diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h
index f1e8a25650..eac258b287 100644
--- a/src/wallet/crypter.h
+++ b/src/wallet/crypter.h
@@ -16,13 +16,13 @@ const unsigned int WALLET_CRYPTO_IV_SIZE = 16;
/**
* Private key encryption is done based on a CMasterKey,
* which holds a salt and random encryption key.
- *
+ *
* CMasterKeys are encrypted using AES-256-CBC using a key
* derived using derivation method nDerivationMethod
* (0 == EVP_sha512()) and derivation iterations nDeriveIterations.
* vchOtherDerivationParameters is provided for alternative algorithms
* which may require more parameters (such as scrypt).
- *
+ *
* Wallet Private Keys are then encrypted using AES-256-CBC
* with the double-sha256 of the public key as the IV, and the
* master key's key as the encryption key (see keystore.[ch]).
@@ -162,28 +162,26 @@ public:
{
{
LOCK(cs_KeyStore);
- if (!IsCrypted())
+ if (!IsCrypted()) {
return CBasicKeyStore::HaveKey(address);
+ }
return mapCryptedKeys.count(address) > 0;
}
return false;
}
bool GetKey(const CKeyID &address, CKey& keyOut) const override;
bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const override;
- void GetKeys(std::set<CKeyID> &setAddress) const override
+ std::set<CKeyID> GetKeys() const override
{
- if (!IsCrypted())
- {
- CBasicKeyStore::GetKeys(setAddress);
- return;
+ LOCK(cs_KeyStore);
+ if (!IsCrypted()) {
+ return CBasicKeyStore::GetKeys();
}
- setAddress.clear();
- CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
- while (mi != mapCryptedKeys.end())
- {
- setAddress.insert((*mi).first);
- mi++;
+ std::set<CKeyID> set_address;
+ for (const auto& mi : mapCryptedKeys) {
+ set_address.insert(mi.first);
}
+ return set_address;
}
/**
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
index d2fe4866fa..d66ba48421 100644
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -558,7 +558,6 @@ bool CDB::Rewrite(CWalletDBWrapper& dbw, const char* pszSkip)
}
MilliSleep(100);
}
- return false;
}
@@ -684,7 +683,6 @@ bool CWalletDBWrapper::Backup(const std::string& strDest)
}
MilliSleep(100);
}
- return false;
}
void CWalletDBWrapper::Flush(bool shutdown)
diff --git a/src/wallet/db.h b/src/wallet/db.h
index 6f3cfe9557..14283ac8f8 100644
--- a/src/wallet/db.h
+++ b/src/wallet/db.h
@@ -156,6 +156,9 @@ public:
explicit CDB(CWalletDBWrapper& dbw, const char* pszMode = "r+", bool fFlushOnCloseIn=true);
~CDB() { Close(); }
+ CDB(const CDB&) = delete;
+ CDB& operator=(const CDB&) = delete;
+
void Flush();
void Close();
static bool Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& out_backup_filename);
@@ -168,10 +171,6 @@ public:
/* verifies the database file */
static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, CDBEnv::recoverFunc_type recoverFunc);
-private:
- CDB(const CDB&);
- void operator=(const CDB&);
-
public:
template <typename K, typename T>
bool Read(const K& key, T& value)
diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp
index 18365b1b72..c984df1df8 100644
--- a/src/wallet/init.cpp
+++ b/src/wallet/init.cpp
@@ -10,6 +10,7 @@
#include "utilmoneystr.h"
#include "validation.h"
#include "wallet/wallet.h"
+#include "wallet/rpcwallet.h"
std::string GetWalletHelpString(bool showDebug)
{
@@ -29,7 +30,6 @@ std::string GetWalletHelpString(bool showDebug)
strUsage += HelpMessageOpt("-salvagewallet", _("Attempt to recover private keys from a corrupt wallet on startup"));
strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), DEFAULT_SPEND_ZEROCONF_CHANGE));
strUsage += HelpMessageOpt("-txconfirmtarget=<n>", strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), DEFAULT_TX_CONFIRM_TARGET));
- strUsage += HelpMessageOpt("-usehd", _("Use hierarchical deterministic key generation (HD) after BIP32. Only has effect during wallet creation/first start") + " " + strprintf(_("(default: %u)"), DEFAULT_USE_HD_WALLET));
strUsage += HelpMessageOpt("-walletrbf", strprintf(_("Send transactions with full-RBF opt-in enabled (default: %u)"), DEFAULT_WALLET_RBF));
strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format on startup"));
strUsage += HelpMessageOpt("-wallet=<file>", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), DEFAULT_WALLET_DAT));
@@ -171,7 +171,14 @@ bool WalletParameterInteraction()
return true;
}
-bool WalletVerify()
+void RegisterWalletRPC(CRPCTable &t)
+{
+ if (gArgs.GetBoolArg("-disablewallet", false)) return;
+
+ RegisterWalletRPCCommands(t);
+}
+
+bool VerifyWallets()
{
if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET))
return true;
@@ -228,7 +235,7 @@ bool WalletVerify()
return true;
}
-bool InitLoadWallet()
+bool OpenWallets()
{
if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
LogPrintf("Wallet disabled!\n");
@@ -245,3 +252,28 @@ bool InitLoadWallet()
return true;
}
+
+void StartWallets(CScheduler& scheduler) {
+ for (CWalletRef pwallet : vpwallets) {
+ pwallet->postInitProcess(scheduler);
+ }
+}
+
+void FlushWallets() {
+ for (CWalletRef pwallet : vpwallets) {
+ pwallet->Flush(false);
+ }
+}
+
+void StopWallets() {
+ for (CWalletRef pwallet : vpwallets) {
+ pwallet->Flush(true);
+ }
+}
+
+void CloseWallets() {
+ for (CWalletRef pwallet : vpwallets) {
+ delete pwallet;
+ }
+ vpwallets.clear();
+}
diff --git a/src/wallet/init.h b/src/wallet/init.h
index fa2251506d..0b3ee2dda2 100644
--- a/src/wallet/init.h
+++ b/src/wallet/init.h
@@ -8,18 +8,36 @@
#include <string>
+class CRPCTable;
+class CScheduler;
+
//! Return the wallets help message.
std::string GetWalletHelpString(bool showDebug);
//! Wallets parameter interaction
bool WalletParameterInteraction();
+//! Register wallet RPCs.
+void RegisterWalletRPC(CRPCTable &tableRPC);
+
//! 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 (CWallet::ParameterInteraction forbids -salvagewallet, -zapwallettxes or -upgradewallet with multiwallet).
-bool WalletVerify();
+// being loaded (WalletParameterInteraction forbids -salvagewallet, -zapwallettxes or -upgradewallet with multiwallet).
+bool VerifyWallets();
//! Load wallet databases.
-bool InitLoadWallet();
+bool OpenWallets();
+
+//! Complete startup of wallets.
+void StartWallets(CScheduler& scheduler);
+
+//! Flush all wallets in preparation for shutdown.
+void FlushWallets();
+
+//! Stop all wallets. Wallets will be flushed first.
+void StopWallets();
+
+//! Close all wallets.
+void CloseWallets();
#endif // BITCOIN_WALLET_INIT_H
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index 67c6d9ec64..9539cc9f42 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -4,6 +4,7 @@
#include "base58.h"
#include "chain.h"
+#include "rpc/safemode.h"
#include "rpc/server.h"
#include "init.h"
#include "validation.h"
@@ -174,12 +175,13 @@ UniValue abortrescan(const JSONRPCRequest& request)
+ HelpExampleRpc("abortrescan", "")
);
+ ObserveSafeMode();
if (!pwallet->IsScanning() || pwallet->IsAbortingRescan()) return false;
pwallet->AbortRescan();
return true;
}
-void ImportAddress(CWallet*, const CBitcoinAddress& address, const std::string& strLabel);
+void ImportAddress(CWallet*, const CTxDestination& dest, const std::string& strLabel);
void ImportScript(CWallet* const pwallet, const CScript& script, const std::string& strLabel, bool isRedeemScript)
{
if (!isRedeemScript && ::IsMine(*pwallet, script) == ISMINE_SPENDABLE) {
@@ -196,7 +198,7 @@ void ImportScript(CWallet* const pwallet, const CScript& script, const std::stri
if (!pwallet->HaveCScript(script) && !pwallet->AddCScript(script)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet");
}
- ImportAddress(pwallet, CBitcoinAddress(CScriptID(script)), strLabel);
+ ImportAddress(pwallet, CScriptID(script), strLabel);
} else {
CTxDestination destination;
if (ExtractDestination(script, destination)) {
@@ -205,13 +207,13 @@ void ImportScript(CWallet* const pwallet, const CScript& script, const std::stri
}
}
-void ImportAddress(CWallet* const pwallet, const CBitcoinAddress& address, const std::string& strLabel)
+void ImportAddress(CWallet* const pwallet, const CTxDestination& dest, const std::string& strLabel)
{
- CScript script = GetScriptForDestination(address.Get());
+ CScript script = GetScriptForDestination(dest);
ImportScript(pwallet, script, strLabel, false);
// add to address book or update label
- if (address.IsValid())
- pwallet->SetAddressBook(address.Get(), strLabel, "receive");
+ if (IsValidDestination(dest))
+ pwallet->SetAddressBook(dest, strLabel, "receive");
}
UniValue importaddress(const JSONRPCRequest& request)
@@ -263,11 +265,12 @@ UniValue importaddress(const JSONRPCRequest& request)
LOCK2(cs_main, pwallet->cs_wallet);
- CBitcoinAddress address(request.params[0].get_str());
- if (address.IsValid()) {
- if (fP2SH)
+ CTxDestination dest = DecodeDestination(request.params[0].get_str());
+ if (IsValidDestination(dest)) {
+ if (fP2SH) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Cannot use the p2sh flag with an address - use a script instead");
- ImportAddress(pwallet, address, strLabel);
+ }
+ ImportAddress(pwallet, dest, strLabel);
} else if (IsHex(request.params[0].get_str())) {
std::vector<unsigned char> data(ParseHex(request.params[0].get_str()));
ImportScript(pwallet, CScript(data.begin(), data.end()), strLabel, fP2SH);
@@ -430,7 +433,7 @@ UniValue importpubkey(const JSONRPCRequest& request)
LOCK2(cs_main, pwallet->cs_wallet);
- ImportAddress(pwallet, CBitcoinAddress(pubKey.GetID()), strLabel);
+ ImportAddress(pwallet, pubKey.GetID(), strLabel);
ImportScript(pwallet, GetScriptForRawPubKey(pubKey), strLabel, false);
if (fRescan)
@@ -504,7 +507,7 @@ UniValue importwallet(const JSONRPCRequest& request)
assert(key.VerifyPubKey(pubkey));
CKeyID keyid = pubkey.GetID();
if (pwallet->HaveKey(keyid)) {
- LogPrintf("Skipping import of %s (key already present)\n", CBitcoinAddress(keyid).ToString());
+ LogPrintf("Skipping import of %s (key already present)\n", EncodeDestination(keyid));
continue;
}
int64_t nTime = DecodeDumpTime(vstr[1]);
@@ -522,7 +525,7 @@ UniValue importwallet(const JSONRPCRequest& request)
fLabel = true;
}
}
- LogPrintf("Importing %s...\n", CBitcoinAddress(keyid).ToString());
+ LogPrintf("Importing %s...\n", EncodeDestination(keyid));
if (!pwallet->AddKeyPubKey(key, pubkey)) {
fGood = false;
continue;
@@ -571,14 +574,16 @@ UniValue dumpprivkey(const JSONRPCRequest& request)
EnsureWalletIsUnlocked(pwallet);
std::string strAddress = request.params[0].get_str();
- CBitcoinAddress address;
- if (!address.SetString(strAddress))
+ CTxDestination dest = DecodeDestination(strAddress);
+ if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
- CKeyID keyID;
- if (!address.GetKeyID(keyID))
+ }
+ const CKeyID *keyID = boost::get<CKeyID>(&dest);
+ if (!keyID) {
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to a key");
+ }
CKey vchSecret;
- if (!pwallet->GetKey(keyID, vchSecret)) {
+ if (!pwallet->GetKey(*keyID, vchSecret)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " + strAddress + " is not known");
}
return CBitcoinSecret(vchSecret).ToString();
@@ -657,7 +662,7 @@ UniValue dumpwallet(const JSONRPCRequest& request)
for (std::vector<std::pair<int64_t, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
const CKeyID &keyid = it->second;
std::string strTime = EncodeDumpTime(it->first);
- std::string strAddr = CBitcoinAddress(keyid).ToString();
+ std::string strAddr = EncodeDestination(keyid);
CKey key;
if (pwallet->GetKey(keyid, key)) {
file << strprintf("%s %s ", CBitcoinSecret(key).ToString(), strTime);
@@ -713,14 +718,14 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6
// Parse the output.
CScript script;
- CBitcoinAddress address;
+ CTxDestination dest;
if (!isScript) {
- address = CBitcoinAddress(output);
- if (!address.IsValid()) {
+ dest = DecodeDestination(output);
+ if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
}
- script = GetScriptForDestination(address.Get());
+ script = GetScriptForDestination(dest);
} else {
if (!IsHex(output)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid scriptPubKey");
@@ -778,8 +783,8 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet");
}
- CBitcoinAddress redeemAddress = CBitcoinAddress(CScriptID(redeemScript));
- CScript redeemDestination = GetScriptForDestination(redeemAddress.Get());
+ CTxDestination redeem_dest = CScriptID(redeemScript);
+ CScript redeemDestination = GetScriptForDestination(redeem_dest);
if (::IsMine(*pwallet, redeemDestination) == ISMINE_SPENDABLE) {
throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
@@ -792,8 +797,8 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6
}
// add to address book or update label
- if (address.IsValid()) {
- pwallet->SetAddressBook(address.Get(), label, "receive");
+ if (IsValidDestination(dest)) {
+ pwallet->SetAddressBook(dest, label, "receive");
}
// Import private keys.
@@ -852,27 +857,25 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey is not a valid public key");
}
- CBitcoinAddress pubKeyAddress = CBitcoinAddress(pubKey.GetID());
+ CTxDestination pubkey_dest = pubKey.GetID();
// Consistency check.
- if (!isScript && !(pubKeyAddress.Get() == address.Get())) {
+ if (!isScript && !(pubkey_dest == dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
}
// Consistency check.
if (isScript) {
- CBitcoinAddress scriptAddress;
CTxDestination destination;
if (ExtractDestination(script, destination)) {
- scriptAddress = CBitcoinAddress(destination);
- if (!(scriptAddress.Get() == pubKeyAddress.Get())) {
+ if (!(destination == pubkey_dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
}
}
}
- CScript pubKeyScript = GetScriptForDestination(pubKeyAddress.Get());
+ CScript pubKeyScript = GetScriptForDestination(pubkey_dest);
if (::IsMine(*pwallet, pubKeyScript) == ISMINE_SPENDABLE) {
throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
@@ -885,8 +888,8 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6
}
// add to address book or update label
- if (pubKeyAddress.IsValid()) {
- pwallet->SetAddressBook(pubKeyAddress.Get(), label, "receive");
+ if (IsValidDestination(pubkey_dest)) {
+ pwallet->SetAddressBook(pubkey_dest, label, "receive");
}
// TODO Is this necessary?
@@ -925,21 +928,19 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6
CPubKey pubKey = key.GetPubKey();
assert(key.VerifyPubKey(pubKey));
- CBitcoinAddress pubKeyAddress = CBitcoinAddress(pubKey.GetID());
+ CTxDestination pubkey_dest = pubKey.GetID();
// Consistency check.
- if (!isScript && !(pubKeyAddress.Get() == address.Get())) {
+ if (!isScript && !(pubkey_dest == dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
}
// Consistency check.
if (isScript) {
- CBitcoinAddress scriptAddress;
CTxDestination destination;
if (ExtractDestination(script, destination)) {
- scriptAddress = CBitcoinAddress(destination);
- if (!(scriptAddress.Get() == pubKeyAddress.Get())) {
+ if (!(destination == pubkey_dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
}
}
@@ -978,8 +979,8 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6
if (scriptPubKey.getType() == UniValue::VOBJ) {
// add to address book or update label
- if (address.IsValid()) {
- pwallet->SetAddressBook(address.Get(), label, "receive");
+ if (IsValidDestination(dest)) {
+ pwallet->SetAddressBook(dest, label, "receive");
}
}
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 4ea53c4132..ae89b3c0a1 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -16,6 +16,7 @@
#include "policy/policy.h"
#include "policy/rbf.h"
#include "rpc/mining.h"
+#include "rpc/safemode.h"
#include "rpc/server.h"
#include "script/sign.h"
#include "timedata.h"
@@ -169,18 +170,18 @@ UniValue getnewaddress(const JSONRPCRequest& request)
pwallet->SetAddressBook(keyID, strAccount, "receive");
- return CBitcoinAddress(keyID).ToString();
+ return EncodeDestination(keyID);
}
-CBitcoinAddress GetAccountAddress(CWallet* const pwallet, std::string strAccount, bool bForceNew=false)
+CTxDestination GetAccountAddress(CWallet* const pwallet, std::string strAccount, bool bForceNew=false)
{
CPubKey pubKey;
if (!pwallet->GetAccountPubkey(pubKey, strAccount, bForceNew)) {
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
}
- return CBitcoinAddress(pubKey.GetID());
+ return pubKey.GetID();
}
UniValue getaccountaddress(const JSONRPCRequest& request)
@@ -212,7 +213,7 @@ UniValue getaccountaddress(const JSONRPCRequest& request)
UniValue ret(UniValue::VSTR);
- ret = GetAccountAddress(pwallet, strAccount).ToString();
+ ret = EncodeDestination(GetAccountAddress(pwallet, strAccount));
return ret;
}
@@ -251,7 +252,7 @@ UniValue getrawchangeaddress(const JSONRPCRequest& request)
CKeyID keyID = vchPubKey.GetID();
- return CBitcoinAddress(keyID).ToString();
+ return EncodeDestination(keyID);
}
@@ -276,24 +277,25 @@ UniValue setaccount(const JSONRPCRequest& request)
LOCK2(cs_main, pwallet->cs_wallet);
- CBitcoinAddress address(request.params[0].get_str());
- if (!address.IsValid())
+ CTxDestination dest = DecodeDestination(request.params[0].get_str());
+ if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
+ }
std::string strAccount;
if (!request.params[1].isNull())
strAccount = AccountFromValue(request.params[1]);
// Only add the account if the address is yours.
- if (IsMine(*pwallet, address.Get())) {
+ if (IsMine(*pwallet, dest)) {
// Detect when changing the account of an address that is the 'unused current key' of another account:
- if (pwallet->mapAddressBook.count(address.Get())) {
- std::string strOldAccount = pwallet->mapAddressBook[address.Get()].name;
- if (address == GetAccountAddress(pwallet, strOldAccount)) {
+ if (pwallet->mapAddressBook.count(dest)) {
+ std::string strOldAccount = pwallet->mapAddressBook[dest].name;
+ if (dest == GetAccountAddress(pwallet, strOldAccount)) {
GetAccountAddress(pwallet, strOldAccount, true);
}
}
- pwallet->SetAddressBook(address.Get(), strAccount, "receive");
+ pwallet->SetAddressBook(dest, strAccount, "receive");
}
else
throw JSONRPCError(RPC_MISC_ERROR, "setaccount can only be used with own address");
@@ -324,12 +326,13 @@ UniValue getaccount(const JSONRPCRequest& request)
LOCK2(cs_main, pwallet->cs_wallet);
- CBitcoinAddress address(request.params[0].get_str());
- if (!address.IsValid())
+ CTxDestination dest = DecodeDestination(request.params[0].get_str());
+ if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
+ }
std::string strAccount;
- std::map<CTxDestination, CAddressBookData>::iterator mi = pwallet->mapAddressBook.find(address.Get());
+ std::map<CTxDestination, CAddressBookData>::iterator mi = pwallet->mapAddressBook.find(dest);
if (mi != pwallet->mapAddressBook.end() && !(*mi).second.name.empty()) {
strAccount = (*mi).second.name;
}
@@ -366,11 +369,12 @@ UniValue getaddressesbyaccount(const JSONRPCRequest& request)
// Find all addresses that have the given account
UniValue ret(UniValue::VARR);
- for (const std::pair<CBitcoinAddress, CAddressBookData>& item : pwallet->mapAddressBook) {
- const CBitcoinAddress& address = item.first;
+ for (const std::pair<CTxDestination, CAddressBookData>& item : pwallet->mapAddressBook) {
+ const CTxDestination& dest = item.first;
const std::string& strName = item.second.name;
- if (strName == strAccount)
- ret.push_back(address.ToString());
+ if (strName == strAccount) {
+ ret.push_back(EncodeDestination(dest));
+ }
}
return ret;
}
@@ -450,11 +454,13 @@ UniValue sendtoaddress(const JSONRPCRequest& request)
+ HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\"")
);
+ ObserveSafeMode();
LOCK2(cs_main, pwallet->cs_wallet);
- CBitcoinAddress address(request.params[0].get_str());
- if (!address.IsValid())
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
+ CTxDestination dest = DecodeDestination(request.params[0].get_str());
+ if (!IsValidDestination(dest)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
+ }
// Amount
CAmount nAmount = AmountFromValue(request.params[1]);
@@ -491,7 +497,7 @@ UniValue sendtoaddress(const JSONRPCRequest& request)
EnsureWalletIsUnlocked(pwallet);
- SendMoney(pwallet, address.Get(), nAmount, fSubtractFeeFromAmount, wtx, coin_control);
+ SendMoney(pwallet, dest, nAmount, fSubtractFeeFromAmount, wtx, coin_control);
return wtx.GetHash().GetHex();
}
@@ -526,20 +532,21 @@ UniValue listaddressgroupings(const JSONRPCRequest& request)
+ HelpExampleRpc("listaddressgroupings", "")
);
+ ObserveSafeMode();
LOCK2(cs_main, pwallet->cs_wallet);
UniValue jsonGroupings(UniValue::VARR);
std::map<CTxDestination, CAmount> balances = pwallet->GetAddressBalances();
- for (std::set<CTxDestination> grouping : pwallet->GetAddressGroupings()) {
+ for (const std::set<CTxDestination>& grouping : pwallet->GetAddressGroupings()) {
UniValue jsonGrouping(UniValue::VARR);
- for (CTxDestination address : grouping)
+ for (const CTxDestination& address : grouping)
{
UniValue addressInfo(UniValue::VARR);
- addressInfo.push_back(CBitcoinAddress(address).ToString());
+ addressInfo.push_back(EncodeDestination(address));
addressInfo.push_back(ValueFromAmount(balances[address]));
{
- if (pwallet->mapAddressBook.find(CBitcoinAddress(address).Get()) != pwallet->mapAddressBook.end()) {
- addressInfo.push_back(pwallet->mapAddressBook.find(CBitcoinAddress(address).Get())->second.name);
+ if (pwallet->mapAddressBook.find(address) != pwallet->mapAddressBook.end()) {
+ addressInfo.push_back(pwallet->mapAddressBook.find(address)->second.name);
}
}
jsonGrouping.push_back(addressInfo);
@@ -584,16 +591,18 @@ UniValue signmessage(const JSONRPCRequest& request)
std::string strAddress = request.params[0].get_str();
std::string strMessage = request.params[1].get_str();
- CBitcoinAddress addr(strAddress);
- if (!addr.IsValid())
+ CTxDestination dest = DecodeDestination(strAddress);
+ if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
+ }
- CKeyID keyID;
- if (!addr.GetKeyID(keyID))
+ const CKeyID *keyID = boost::get<CKeyID>(&dest);
+ if (!keyID) {
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
+ }
CKey key;
- if (!pwallet->GetKey(keyID, key)) {
+ if (!pwallet->GetKey(*keyID, key)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
}
@@ -605,7 +614,7 @@ UniValue signmessage(const JSONRPCRequest& request)
if (!key.SignCompact(ss.GetHash(), vchSig))
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
- return EncodeBase64(&vchSig[0], vchSig.size());
+ return EncodeBase64(vchSig.data(), vchSig.size());
}
UniValue getreceivedbyaddress(const JSONRPCRequest& request)
@@ -635,13 +644,15 @@ UniValue getreceivedbyaddress(const JSONRPCRequest& request)
+ HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", 6")
);
+ ObserveSafeMode();
LOCK2(cs_main, pwallet->cs_wallet);
// Bitcoin address
- CBitcoinAddress address = CBitcoinAddress(request.params[0].get_str());
- if (!address.IsValid())
+ CTxDestination dest = DecodeDestination(request.params[0].get_str());
+ if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
- CScript scriptPubKey = GetScriptForDestination(address.Get());
+ }
+ CScript scriptPubKey = GetScriptForDestination(dest);
if (!IsMine(*pwallet, scriptPubKey)) {
return ValueFromAmount(0);
}
@@ -695,6 +706,7 @@ UniValue getreceivedbyaccount(const JSONRPCRequest& request)
+ HelpExampleRpc("getreceivedbyaccount", "\"tabby\", 6")
);
+ ObserveSafeMode();
LOCK2(cs_main, pwallet->cs_wallet);
// Minimum confirmations
@@ -767,6 +779,7 @@ UniValue getbalance(const JSONRPCRequest& request)
+ HelpExampleRpc("getbalance", "\"*\", 6")
);
+ ObserveSafeMode();
LOCK2(cs_main, pwallet->cs_wallet);
const UniValue& account_value = request.params[0];
@@ -811,6 +824,7 @@ UniValue getunconfirmedbalance(const JSONRPCRequest &request)
"getunconfirmedbalance\n"
"Returns the server's total unconfirmed balance\n");
+ ObserveSafeMode();
LOCK2(cs_main, pwallet->cs_wallet);
return ValueFromAmount(pwallet->GetUnconfirmedBalance());
@@ -845,6 +859,7 @@ UniValue movecmd(const JSONRPCRequest& request)
+ HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"")
);
+ ObserveSafeMode();
LOCK2(cs_main, pwallet->cs_wallet);
std::string strFrom = AccountFromValue(request.params[0]);
@@ -903,12 +918,14 @@ UniValue sendfrom(const JSONRPCRequest& request)
+ HelpExampleRpc("sendfrom", "\"tabby\", \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.01, 6, \"donation\", \"seans outpost\"")
);
+ ObserveSafeMode();
LOCK2(cs_main, pwallet->cs_wallet);
std::string strAccount = AccountFromValue(request.params[0]);
- CBitcoinAddress address(request.params[1].get_str());
- if (!address.IsValid())
+ CTxDestination dest = DecodeDestination(request.params[1].get_str());
+ if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
+ }
CAmount nAmount = AmountFromValue(request.params[2]);
if (nAmount <= 0)
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
@@ -931,7 +948,7 @@ UniValue sendfrom(const JSONRPCRequest& request)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
CCoinControl no_coin_control; // This is a deprecated API
- SendMoney(pwallet, address.Get(), nAmount, false, wtx, no_coin_control);
+ SendMoney(pwallet, dest, nAmount, false, wtx, no_coin_control);
return wtx.GetHash().GetHex();
}
@@ -986,6 +1003,7 @@ UniValue sendmany(const JSONRPCRequest& request)
+ HelpExampleRpc("sendmany", "\"\", \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\", 6, \"testing\"")
);
+ ObserveSafeMode();
LOCK2(cs_main, pwallet->cs_wallet);
if (pwallet->GetBroadcastTransactions() && !g_connman) {
@@ -1022,22 +1040,23 @@ UniValue sendmany(const JSONRPCRequest& request)
}
}
- std::set<CBitcoinAddress> setAddress;
+ std::set<CTxDestination> destinations;
std::vector<CRecipient> vecSend;
CAmount totalAmount = 0;
std::vector<std::string> keys = sendTo.getKeys();
- for (const std::string& name_ : keys)
- {
- CBitcoinAddress address(name_);
- if (!address.IsValid())
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ")+name_);
+ for (const std::string& name_ : keys) {
+ CTxDestination dest = DecodeDestination(name_);
+ if (!IsValidDestination(dest)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ") + name_);
+ }
- if (setAddress.count(address))
- throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ")+name_);
- setAddress.insert(address);
+ if (destinations.count(dest)) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_);
+ }
+ destinations.insert(dest);
- CScript scriptPubKey = GetScriptForDestination(address.Get());
+ CScript scriptPubKey = GetScriptForDestination(dest);
CAmount nAmount = AmountFromValue(sendTo[name_]);
if (nAmount <= 0)
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
@@ -1128,7 +1147,7 @@ UniValue addmultisigaddress(const JSONRPCRequest& request)
pwallet->AddCScript(inner);
pwallet->SetAddressBook(innerID, strAccount, "send");
- return CBitcoinAddress(innerID).ToString();
+ return EncodeDestination(innerID);
}
class Witnessifier : public boost::static_visitor<bool>
@@ -1216,12 +1235,12 @@ UniValue addwitnessaddress(const JSONRPCRequest& request)
}
}
- CBitcoinAddress address(request.params[0].get_str());
- if (!address.IsValid())
+ CTxDestination dest = DecodeDestination(request.params[0].get_str());
+ if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
+ }
Witnessifier w(pwallet);
- CTxDestination dest = address.Get();
bool ret = boost::apply_visitor(w, dest);
if (!ret) {
throw JSONRPCError(RPC_WALLET_ERROR, "Public key or redeemscript not known to wallet, or the key is uncompressed");
@@ -1229,7 +1248,7 @@ UniValue addwitnessaddress(const JSONRPCRequest& request)
pwallet->SetAddressBook(w.result, "", "receive");
- return CBitcoinAddress(w.result).ToString();
+ return EncodeDestination(w.result);
}
struct tallyitem
@@ -1264,7 +1283,7 @@ UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool fByA
filter = filter | ISMINE_WATCH_ONLY;
// Tally
- std::map<CBitcoinAddress, tallyitem> mapTally;
+ std::map<CTxDestination, tallyitem> mapTally;
for (const std::pair<uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
const CWalletTx& wtx = pairWtx.second;
@@ -1297,10 +1316,10 @@ UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool fByA
// Reply
UniValue ret(UniValue::VARR);
std::map<std::string, tallyitem> mapAccountTally;
- for (const std::pair<CBitcoinAddress, CAddressBookData>& item : pwallet->mapAddressBook) {
- const CBitcoinAddress& address = item.first;
+ for (const std::pair<CTxDestination, CAddressBookData>& item : pwallet->mapAddressBook) {
+ const CTxDestination& dest = item.first;
const std::string& strAccount = item.second.name;
- std::map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
+ std::map<CTxDestination, tallyitem>::iterator it = mapTally.find(dest);
if (it == mapTally.end() && !fIncludeEmpty)
continue;
@@ -1326,7 +1345,7 @@ UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool fByA
UniValue obj(UniValue::VOBJ);
if(fIsWatchonly)
obj.push_back(Pair("involvesWatchonly", true));
- obj.push_back(Pair("address", address.ToString()));
+ obj.push_back(Pair("address", EncodeDestination(dest)));
obj.push_back(Pair("account", strAccount));
obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
@@ -1403,6 +1422,7 @@ UniValue listreceivedbyaddress(const JSONRPCRequest& request)
+ HelpExampleRpc("listreceivedbyaddress", "6, true, true")
);
+ ObserveSafeMode();
LOCK2(cs_main, pwallet->cs_wallet);
return ListReceived(pwallet, request.params, false);
@@ -1442,6 +1462,7 @@ UniValue listreceivedbyaccount(const JSONRPCRequest& request)
+ HelpExampleRpc("listreceivedbyaccount", "6, true, true")
);
+ ObserveSafeMode();
LOCK2(cs_main, pwallet->cs_wallet);
return ListReceived(pwallet, request.params, true);
@@ -1449,9 +1470,9 @@ UniValue listreceivedbyaccount(const JSONRPCRequest& request)
static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
{
- CBitcoinAddress addr;
- if (addr.Set(dest))
- entry.push_back(Pair("address", addr.ToString()));
+ if (IsValidDestination(dest)) {
+ entry.push_back(Pair("address", EncodeDestination(dest)));
+ }
}
/**
@@ -1629,6 +1650,7 @@ UniValue listtransactions(const JSONRPCRequest& request)
+ HelpExampleRpc("listtransactions", "\"*\", 20, 100")
);
+ ObserveSafeMode();
LOCK2(cs_main, pwallet->cs_wallet);
std::string strAccount = "*";
@@ -1722,6 +1744,7 @@ UniValue listaccounts(const JSONRPCRequest& request)
+ HelpExampleRpc("listaccounts", "6")
);
+ ObserveSafeMode();
LOCK2(cs_main, pwallet->cs_wallet);
int nMinDepth = 1;
@@ -1830,6 +1853,7 @@ UniValue listsinceblock(const JSONRPCRequest& request)
+ HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6")
);
+ ObserveSafeMode();
LOCK2(cs_main, pwallet->cs_wallet);
const CBlockIndex* pindex = nullptr; // Block index of the specified block or the common ancestor, if the block provided was in a deactivated chain.
@@ -1961,6 +1985,7 @@ UniValue gettransaction(const JSONRPCRequest& request)
+ HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
);
+ ObserveSafeMode();
LOCK2(cs_main, pwallet->cs_wallet);
uint256 hash;
@@ -2022,6 +2047,7 @@ UniValue abandontransaction(const JSONRPCRequest& request)
+ HelpExampleRpc("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
);
+ ObserveSafeMode();
LOCK2(cs_main, pwallet->cs_wallet);
uint256 hash;
@@ -2454,6 +2480,7 @@ UniValue listlockunspent(const JSONRPCRequest& request)
+ HelpExampleRpc("listlockunspent", "")
);
+ ObserveSafeMode();
LOCK2(cs_main, pwallet->cs_wallet);
std::vector<COutPoint> vOutpts;
@@ -2532,6 +2559,7 @@ UniValue getwalletinfo(const JSONRPCRequest& request)
+ HelpExampleRpc("getwalletinfo", "")
);
+ ObserveSafeMode();
LOCK2(cs_main, pwallet->cs_wallet);
UniValue obj(UniValue::VOBJ);
@@ -2684,6 +2712,8 @@ UniValue listunspent(const JSONRPCRequest& request)
+ HelpExampleRpc("listunspent", "6, 9999999, [] , true, { \"minimumAmount\": 0.005 } ")
);
+ ObserveSafeMode();
+
int nMinDepth = 1;
if (!request.params[0].isNull()) {
RPCTypeCheckArgument(request.params[0], UniValue::VNUM);
@@ -2696,18 +2726,19 @@ UniValue listunspent(const JSONRPCRequest& request)
nMaxDepth = request.params[1].get_int();
}
- std::set<CBitcoinAddress> setAddress;
+ std::set<CTxDestination> destinations;
if (!request.params[2].isNull()) {
RPCTypeCheckArgument(request.params[2], UniValue::VARR);
UniValue inputs = request.params[2].get_array();
for (unsigned int idx = 0; idx < inputs.size(); idx++) {
const UniValue& input = inputs[idx];
- CBitcoinAddress address(input.get_str());
- if (!address.IsValid())
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ")+input.get_str());
- if (setAddress.count(address))
- throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ")+input.get_str());
- setAddress.insert(address);
+ CTxDestination dest = DecodeDestination(input.get_str());
+ if (!IsValidDestination(dest)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ") + input.get_str());
+ }
+ if (!destinations.insert(dest).second) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + input.get_str());
+ }
}
}
@@ -2749,7 +2780,7 @@ UniValue listunspent(const JSONRPCRequest& request)
const CScript& scriptPubKey = out.tx->tx->vout[out.i].scriptPubKey;
bool fValidAddress = ExtractDestination(scriptPubKey, address);
- if (setAddress.size() && (!fValidAddress || !setAddress.count(address)))
+ if (destinations.size() && (!fValidAddress || !destinations.count(address)))
continue;
UniValue entry(UniValue::VOBJ);
@@ -2757,7 +2788,7 @@ UniValue listunspent(const JSONRPCRequest& request)
entry.push_back(Pair("vout", out.i));
if (fValidAddress) {
- entry.push_back(Pair("address", CBitcoinAddress(address).ToString()));
+ entry.push_back(Pair("address", EncodeDestination(address)));
if (pwallet->mapAddressBook.count(address)) {
entry.push_back(Pair("account", pwallet->mapAddressBook[address].name));
@@ -2812,7 +2843,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
" \"changePosition\" (numeric, optional, default random) The index of the change output\n"
" \"includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n"
" \"lockUnspents\" (boolean, optional, default false) Lock selected unspent outputs\n"
- " \"feeRate\" (numeric, optional, default not set: makes wallet determine the fee) Set a specific feerate (" + CURRENCY_UNIT + " per KB)\n"
+ " \"feeRate\" (numeric, optional, default not set: makes wallet determine the fee) Set a specific fee rate in " + CURRENCY_UNIT + "/kB\n"
" \"subtractFeeFromOutputs\" (array, optional) A json array of integers.\n"
" The fee will be equally deducted from the amount of each specified output.\n"
" The outputs are specified by their zero-based index, before any change output is added.\n"
@@ -2845,6 +2876,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
+ HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")
);
+ ObserveSafeMode();
RPCTypeCheck(request.params, {UniValue::VSTR});
CCoinControl coinControl;
@@ -2879,12 +2911,13 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
true, true);
if (options.exists("changeAddress")) {
- CBitcoinAddress address(options["changeAddress"].get_str());
+ CTxDestination dest = DecodeDestination(options["changeAddress"].get_str());
- if (!address.IsValid())
+ if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "changeAddress must be a valid bitcoin address");
+ }
- coinControl.destChange = address.Get();
+ coinControl.destChange = dest;
}
if (options.exists("changePosition"))
@@ -3159,67 +3192,64 @@ extern UniValue removeprunedfunds(const JSONRPCRequest& request);
extern UniValue importmulti(const JSONRPCRequest& request);
static const CRPCCommand commands[] =
-{ // category name actor (function) okSafeMode
- // --------------------- ------------------------ ----------------------- ----------
- { "rawtransactions", "fundrawtransaction", &fundrawtransaction, false, {"hexstring","options"} },
- { "hidden", "resendwallettransactions", &resendwallettransactions, true, {} },
- { "wallet", "abandontransaction", &abandontransaction, false, {"txid"} },
- { "wallet", "abortrescan", &abortrescan, false, {} },
- { "wallet", "addmultisigaddress", &addmultisigaddress, true, {"nrequired","keys","account"} },
- { "wallet", "addwitnessaddress", &addwitnessaddress, true, {"address"} },
- { "wallet", "backupwallet", &backupwallet, true, {"destination"} },
- { "wallet", "bumpfee", &bumpfee, true, {"txid", "options"} },
- { "wallet", "dumpprivkey", &dumpprivkey, true, {"address"} },
- { "wallet", "dumpwallet", &dumpwallet, true, {"filename"} },
- { "wallet", "encryptwallet", &encryptwallet, true, {"passphrase"} },
- { "wallet", "getaccountaddress", &getaccountaddress, true, {"account"} },
- { "wallet", "getaccount", &getaccount, true, {"address"} },
- { "wallet", "getaddressesbyaccount", &getaddressesbyaccount, true, {"account"} },
- { "wallet", "getbalance", &getbalance, false, {"account","minconf","include_watchonly"} },
- { "wallet", "getnewaddress", &getnewaddress, true, {"account"} },
- { "wallet", "getrawchangeaddress", &getrawchangeaddress, true, {} },
- { "wallet", "getreceivedbyaccount", &getreceivedbyaccount, false, {"account","minconf"} },
- { "wallet", "getreceivedbyaddress", &getreceivedbyaddress, false, {"address","minconf"} },
- { "wallet", "gettransaction", &gettransaction, false, {"txid","include_watchonly"} },
- { "wallet", "getunconfirmedbalance", &getunconfirmedbalance, false, {} },
- { "wallet", "getwalletinfo", &getwalletinfo, false, {} },
- { "wallet", "importmulti", &importmulti, true, {"requests","options"} },
- { "wallet", "importprivkey", &importprivkey, true, {"privkey","label","rescan"} },
- { "wallet", "importwallet", &importwallet, true, {"filename"} },
- { "wallet", "importaddress", &importaddress, true, {"address","label","rescan","p2sh"} },
- { "wallet", "importprunedfunds", &importprunedfunds, true, {"rawtransaction","txoutproof"} },
- { "wallet", "importpubkey", &importpubkey, true, {"pubkey","label","rescan"} },
- { "wallet", "keypoolrefill", &keypoolrefill, true, {"newsize"} },
- { "wallet", "listaccounts", &listaccounts, false, {"minconf","include_watchonly"} },
- { "wallet", "listaddressgroupings", &listaddressgroupings, false, {} },
- { "wallet", "listlockunspent", &listlockunspent, false, {} },
- { "wallet", "listreceivedbyaccount", &listreceivedbyaccount, false, {"minconf","include_empty","include_watchonly"} },
- { "wallet", "listreceivedbyaddress", &listreceivedbyaddress, false, {"minconf","include_empty","include_watchonly"} },
- { "wallet", "listsinceblock", &listsinceblock, false, {"blockhash","target_confirmations","include_watchonly","include_removed"} },
- { "wallet", "listtransactions", &listtransactions, false, {"account","count","skip","include_watchonly"} },
- { "wallet", "listunspent", &listunspent, false, {"minconf","maxconf","addresses","include_unsafe","query_options"} },
- { "wallet", "listwallets", &listwallets, true, {} },
- { "wallet", "lockunspent", &lockunspent, true, {"unlock","transactions"} },
- { "wallet", "move", &movecmd, false, {"fromaccount","toaccount","amount","minconf","comment"} },
- { "wallet", "sendfrom", &sendfrom, false, {"fromaccount","toaddress","amount","minconf","comment","comment_to"} },
- { "wallet", "sendmany", &sendmany, false, {"fromaccount","amounts","minconf","comment","subtractfeefrom","replaceable","conf_target","estimate_mode"} },
- { "wallet", "sendtoaddress", &sendtoaddress, false, {"address","amount","comment","comment_to","subtractfeefromamount","replaceable","conf_target","estimate_mode"} },
- { "wallet", "setaccount", &setaccount, true, {"address","account"} },
- { "wallet", "settxfee", &settxfee, true, {"amount"} },
- { "wallet", "signmessage", &signmessage, true, {"address","message"} },
- { "wallet", "walletlock", &walletlock, true, {} },
- { "wallet", "walletpassphrasechange", &walletpassphrasechange, true, {"oldpassphrase","newpassphrase"} },
- { "wallet", "walletpassphrase", &walletpassphrase, true, {"passphrase","timeout"} },
- { "wallet", "removeprunedfunds", &removeprunedfunds, true, {"txid"} },
-
- { "generating", "generate", &generate, true, {"nblocks","maxtries"} },
+{ // category name actor (function) argNames
+ // --------------------- ------------------------ ----------------------- ----------
+ { "rawtransactions", "fundrawtransaction", &fundrawtransaction, {"hexstring","options"} },
+ { "hidden", "resendwallettransactions", &resendwallettransactions, {} },
+ { "wallet", "abandontransaction", &abandontransaction, {"txid"} },
+ { "wallet", "abortrescan", &abortrescan, {} },
+ { "wallet", "addmultisigaddress", &addmultisigaddress, {"nrequired","keys","account"} },
+ { "wallet", "addwitnessaddress", &addwitnessaddress, {"address"} },
+ { "wallet", "backupwallet", &backupwallet, {"destination"} },
+ { "wallet", "bumpfee", &bumpfee, {"txid", "options"} },
+ { "wallet", "dumpprivkey", &dumpprivkey, {"address"} },
+ { "wallet", "dumpwallet", &dumpwallet, {"filename"} },
+ { "wallet", "encryptwallet", &encryptwallet, {"passphrase"} },
+ { "wallet", "getaccountaddress", &getaccountaddress, {"account"} },
+ { "wallet", "getaccount", &getaccount, {"address"} },
+ { "wallet", "getaddressesbyaccount", &getaddressesbyaccount, {"account"} },
+ { "wallet", "getbalance", &getbalance, {"account","minconf","include_watchonly"} },
+ { "wallet", "getnewaddress", &getnewaddress, {"account"} },
+ { "wallet", "getrawchangeaddress", &getrawchangeaddress, {} },
+ { "wallet", "getreceivedbyaccount", &getreceivedbyaccount, {"account","minconf"} },
+ { "wallet", "getreceivedbyaddress", &getreceivedbyaddress, {"address","minconf"} },
+ { "wallet", "gettransaction", &gettransaction, {"txid","include_watchonly"} },
+ { "wallet", "getunconfirmedbalance", &getunconfirmedbalance, {} },
+ { "wallet", "getwalletinfo", &getwalletinfo, {} },
+ { "wallet", "importmulti", &importmulti, {"requests","options"} },
+ { "wallet", "importprivkey", &importprivkey, {"privkey","label","rescan"} },
+ { "wallet", "importwallet", &importwallet, {"filename"} },
+ { "wallet", "importaddress", &importaddress, {"address","label","rescan","p2sh"} },
+ { "wallet", "importprunedfunds", &importprunedfunds, {"rawtransaction","txoutproof"} },
+ { "wallet", "importpubkey", &importpubkey, {"pubkey","label","rescan"} },
+ { "wallet", "keypoolrefill", &keypoolrefill, {"newsize"} },
+ { "wallet", "listaccounts", &listaccounts, {"minconf","include_watchonly"} },
+ { "wallet", "listaddressgroupings", &listaddressgroupings, {} },
+ { "wallet", "listlockunspent", &listlockunspent, {} },
+ { "wallet", "listreceivedbyaccount", &listreceivedbyaccount, {"minconf","include_empty","include_watchonly"} },
+ { "wallet", "listreceivedbyaddress", &listreceivedbyaddress, {"minconf","include_empty","include_watchonly"} },
+ { "wallet", "listsinceblock", &listsinceblock, {"blockhash","target_confirmations","include_watchonly","include_removed"} },
+ { "wallet", "listtransactions", &listtransactions, {"account","count","skip","include_watchonly"} },
+ { "wallet", "listunspent", &listunspent, {"minconf","maxconf","addresses","include_unsafe","query_options"} },
+ { "wallet", "listwallets", &listwallets, {} },
+ { "wallet", "lockunspent", &lockunspent, {"unlock","transactions"} },
+ { "wallet", "move", &movecmd, {"fromaccount","toaccount","amount","minconf","comment"} },
+ { "wallet", "sendfrom", &sendfrom, {"fromaccount","toaddress","amount","minconf","comment","comment_to"} },
+ { "wallet", "sendmany", &sendmany, {"fromaccount","amounts","minconf","comment","subtractfeefrom","replaceable","conf_target","estimate_mode"} },
+ { "wallet", "sendtoaddress", &sendtoaddress, {"address","amount","comment","comment_to","subtractfeefromamount","replaceable","conf_target","estimate_mode"} },
+ { "wallet", "setaccount", &setaccount, {"address","account"} },
+ { "wallet", "settxfee", &settxfee, {"amount"} },
+ { "wallet", "signmessage", &signmessage, {"address","message"} },
+ { "wallet", "walletlock", &walletlock, {} },
+ { "wallet", "walletpassphrasechange", &walletpassphrasechange, {"oldpassphrase","newpassphrase"} },
+ { "wallet", "walletpassphrase", &walletpassphrase, {"passphrase","timeout"} },
+ { "wallet", "removeprunedfunds", &removeprunedfunds, {"txid"} },
+
+ { "generating", "generate", &generate, {"nblocks","maxtries"} },
};
void RegisterWalletRPCCommands(CRPCTable &t)
{
- if (gArgs.GetBoolArg("-disablewallet", false))
- return;
-
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
t.appendCommand(commands[vcidx].name, &commands[vcidx]);
}
diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h
index db0808b93b..14e51610d9 100644
--- a/src/wallet/rpcwallet.h
+++ b/src/wallet/rpcwallet.h
@@ -5,7 +5,10 @@
#ifndef BITCOIN_WALLET_RPCWALLET_H
#define BITCOIN_WALLET_RPCWALLET_H
+#include <string>
+
class CRPCTable;
+class CWallet;
class JSONRPCRequest;
void RegisterWalletRPCCommands(CRPCTable &t);
diff --git a/src/wallet/test/crypto_tests.cpp b/src/wallet/test/crypto_tests.cpp
index cbd74b6f96..f4dabc50c0 100644
--- a/src/wallet/test/crypto_tests.cpp
+++ b/src/wallet/test/crypto_tests.cpp
@@ -80,7 +80,7 @@ BOOST_AUTO_TEST_CASE(passphrase) {
std::string hash(GetRandHash().ToString());
std::vector<unsigned char> vchSalt(8);
- GetRandBytes(&vchSalt[0], vchSalt.size());
+ GetRandBytes(vchSalt.data(), vchSalt.size());
uint32_t rounds = InsecureRand32();
if (rounds > 30000)
rounds = 30000;
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 4b48735e16..d83203f409 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -307,7 +307,7 @@ bool CWallet::LoadCScript(const CScript& redeemScript)
* these. Do not add them to the wallet and warn. */
if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
{
- std::string strAddr = CBitcoinAddress(CScriptID(redeemScript)).ToString();
+ std::string strAddr = EncodeDestination(CScriptID(redeemScript));
LogPrintf("%s: Warning: This wallet contains a redeemScript of size %i which exceeds maximum size %i thus can never be redeemed. Do not use address %s.\n",
__func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr);
return true;
@@ -519,6 +519,7 @@ void CWallet::SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator> ran
const uint256& hash = it->second;
CWalletTx* copyTo = &mapWallet[hash];
if (copyFrom == copyTo) continue;
+ assert(copyFrom && "Oldest wallet transaction in range assumed to have been found.");
if (!copyFrom->IsEquivalentTo(*copyTo)) continue;
copyTo->mapValue = copyFrom->mapValue;
copyTo->vOrderForm = copyFrom->vOrderForm;
@@ -3081,9 +3082,9 @@ bool CWallet::SetAddressBook(const CTxDestination& address, const std::string& s
}
NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address) != ISMINE_NO,
strPurpose, (fUpdated ? CT_UPDATED : CT_NEW) );
- if (!strPurpose.empty() && !CWalletDB(*dbw).WritePurpose(CBitcoinAddress(address).ToString(), strPurpose))
+ if (!strPurpose.empty() && !CWalletDB(*dbw).WritePurpose(EncodeDestination(address), strPurpose))
return false;
- return CWalletDB(*dbw).WriteName(CBitcoinAddress(address).ToString(), strName);
+ return CWalletDB(*dbw).WriteName(EncodeDestination(address), strName);
}
bool CWallet::DelAddressBook(const CTxDestination& address)
@@ -3092,7 +3093,7 @@ bool CWallet::DelAddressBook(const CTxDestination& address)
LOCK(cs_wallet); // mapAddressBook
// Delete destdata tuples associated with address
- std::string strAddress = CBitcoinAddress(address).ToString();
+ std::string strAddress = EncodeDestination(address);
for (const std::pair<std::string, std::string> &item : mapAddressBook[address].destdata)
{
CWalletDB(*dbw).EraseDestData(strAddress, item.first);
@@ -3102,8 +3103,8 @@ bool CWallet::DelAddressBook(const CTxDestination& address)
NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address) != ISMINE_NO, "", CT_DELETED);
- CWalletDB(*dbw).ErasePurpose(CBitcoinAddress(address).ToString());
- return CWalletDB(*dbw).EraseName(CBitcoinAddress(address).ToString());
+ CWalletDB(*dbw).ErasePurpose(EncodeDestination(address));
+ return CWalletDB(*dbw).EraseName(EncodeDestination(address));
}
const std::string& CWallet::GetAccountName(const CScript& scriptPubKey) const
@@ -3609,13 +3610,10 @@ void CWallet::GetKeyBirthTimes(std::map<CTxDestination, int64_t> &mapKeyBirth) c
// map in which we'll infer heights of other keys
CBlockIndex *pindexMax = chainActive[std::max(0, chainActive.Height() - 144)]; // the tip can be reorganized; use a 144-block safety margin
std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
- std::set<CKeyID> setKeys;
- GetKeys(setKeys);
- for (const CKeyID &keyid : setKeys) {
+ for (const CKeyID &keyid : GetKeys()) {
if (mapKeyBirth.count(keyid) == 0)
mapKeyFirstBlock[keyid] = pindexMax;
}
- setKeys.clear();
// if there are no such keys, we're done
if (mapKeyFirstBlock.empty())
@@ -3720,14 +3718,14 @@ bool CWallet::AddDestData(const CTxDestination &dest, const std::string &key, co
return false;
mapAddressBook[dest].destdata.insert(std::make_pair(key, value));
- return CWalletDB(*dbw).WriteDestData(CBitcoinAddress(dest).ToString(), key, value);
+ return CWalletDB(*dbw).WriteDestData(EncodeDestination(dest), key, value);
}
bool CWallet::EraseDestData(const CTxDestination &dest, const std::string &key)
{
if (!mapAddressBook[dest].destdata.erase(key))
return false;
- return CWalletDB(*dbw).EraseDestData(CBitcoinAddress(dest).ToString(), key);
+ return CWalletDB(*dbw).EraseDestData(EncodeDestination(dest), key);
}
bool CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
@@ -3838,17 +3836,17 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile)
if (fFirstRun)
{
- // Create new keyUser and set as default key
- if (gArgs.GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET) && !walletInstance->IsHDEnabled()) {
-
- // ensure this wallet.dat can only be opened by clients supporting HD with chain split
- walletInstance->SetMinVersion(FEATURE_HD_SPLIT);
-
- // generate a new master key
- CPubKey masterPubKey = walletInstance->GenerateNewHDMasterKey();
- if (!walletInstance->SetHDMasterKey(masterPubKey))
- throw std::runtime_error(std::string(__func__) + ": Storing master key failed");
+ // ensure this wallet.dat can only be opened by clients supporting HD with chain split and expects no default key
+ if (!gArgs.GetBoolArg("-usehd", true)) {
+ InitError(strprintf(_("Error creating %s: You can't create non-HD wallets with this version."), walletFile));
+ return nullptr;
}
+ walletInstance->SetMinVersion(FEATURE_NO_DEFAULT_KEY);
+
+ // generate a new master key
+ CPubKey masterPubKey = walletInstance->GenerateNewHDMasterKey();
+ if (!walletInstance->SetHDMasterKey(masterPubKey))
+ throw std::runtime_error(std::string(__func__) + ": Storing master key failed");
// Top up the keypool
if (!walletInstance->TopUpKeyPool()) {
@@ -3859,7 +3857,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile)
walletInstance->SetBestChain(chainActive.GetLocator());
}
else if (gArgs.IsArgSet("-usehd")) {
- bool useHD = gArgs.GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET);
+ bool useHD = gArgs.GetBoolArg("-usehd", true);
if (walletInstance->IsHDEnabled() && !useHD) {
InitError(strprintf(_("Error loading %s: You can't disable HD on an already existing HD wallet"), walletFile));
return nullptr;
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 73ad3bdeca..c4af192f36 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -65,8 +65,6 @@ static const unsigned int DEFAULT_TX_CONFIRM_TARGET = 6;
static const bool DEFAULT_WALLET_RBF = false;
static const bool DEFAULT_WALLETBROADCAST = true;
static const bool DEFAULT_DISABLE_WALLET = false;
-//! if set, all keys will be derived by using BIP32
-static const bool DEFAULT_USE_HD_WALLET = true;
extern const char * DEFAULT_WALLET_DAT;
@@ -87,7 +85,7 @@ enum class FeeEstimateMode;
/** (client) version numbers for particular wallet features */
enum WalletFeature
{
- FEATURE_BASE = 10500, // the earliest version new wallets supports (only useful for getinfo's clientversion output)
+ FEATURE_BASE = 10500, // the earliest version new wallets supports (only useful for getwalletinfo's clientversion output)
FEATURE_WALLETCRYPT = 40000, // wallet encryption
FEATURE_COMPRPUBKEY = 60000, // compressed public keys
@@ -96,6 +94,8 @@ enum WalletFeature
FEATURE_HD_SPLIT = 139900, // Wallet with HD chain split (change outputs will use m/0'/1'/k)
+ FEATURE_NO_DEFAULT_KEY = 159900, // Wallet without a default key written
+
FEATURE_LATEST = FEATURE_COMPRPUBKEY // HD is optional, use FEATURE_COMPRPUBKEY as latest version
};
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index 12da3cce64..52370a8eb5 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -253,13 +253,13 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
{
std::string strAddress;
ssKey >> strAddress;
- ssValue >> pwallet->mapAddressBook[CBitcoinAddress(strAddress).Get()].name;
+ ssValue >> pwallet->mapAddressBook[DecodeDestination(strAddress)].name;
}
else if (strType == "purpose")
{
std::string strAddress;
ssKey >> strAddress;
- ssValue >> pwallet->mapAddressBook[CBitcoinAddress(strAddress).Get()].purpose;
+ ssValue >> pwallet->mapAddressBook[DecodeDestination(strAddress)].purpose;
}
else if (strType == "tx")
{
@@ -493,7 +493,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
ssKey >> strAddress;
ssKey >> strKey;
ssValue >> strValue;
- if (!pwallet->LoadDestData(CBitcoinAddress(strAddress).Get(), strKey, strValue))
+ if (!pwallet->LoadDestData(DecodeDestination(strAddress), strKey, strValue))
{
strErr = "Error reading wallet database: LoadDestData failed";
return false;
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
index 4f8ea185d5..3a146179af 100644
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -167,6 +167,8 @@ public:
m_dbw(dbw)
{
}
+ CWalletDB(const CWalletDB&) = delete;
+ CWalletDB& operator=(const CWalletDB&) = delete;
bool WriteName(const std::string& strAddress, const std::string& strName);
bool EraseName(const std::string& strAddress);
@@ -244,9 +246,6 @@ public:
private:
CDB batch;
CWalletDBWrapper& m_dbw;
-
- CWalletDB(const CWalletDB&);
- void operator=(const CWalletDB&);
};
//! Compacts BDB state so that wallet.dat is self-contained (if there are changes)