aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am5
-rw-r--r--src/amount.h45
-rw-r--r--src/bench/checkblock.cpp4
-rw-r--r--src/bitcoin-cli.cpp4
-rw-r--r--src/bitcoin-tx.cpp8
-rw-r--r--src/chainparams.cpp38
-rw-r--r--src/chainparams.h16
-rw-r--r--src/chainparamsbase.cpp24
-rw-r--r--src/chainparamsbase.h16
-rw-r--r--src/core_write.cpp2
-rw-r--r--src/init.cpp31
-rw-r--r--src/key.cpp8
-rw-r--r--src/key.h3
-rw-r--r--src/merkleblock.cpp2
-rw-r--r--src/miner.cpp5
-rw-r--r--src/net.cpp22
-rw-r--r--src/net.h3
-rw-r--r--src/net_processing.cpp121
-rw-r--r--src/netaddress.cpp6
-rw-r--r--src/netaddress.h1
-rw-r--r--src/policy/feerate.cpp (renamed from src/amount.cpp)2
-rw-r--r--src/policy/feerate.h54
-rw-r--r--src/policy/fees.h1
-rw-r--r--src/policy/policy.cpp39
-rw-r--r--src/policy/policy.h6
-rw-r--r--src/primitives/transaction.h41
-rw-r--r--src/qt/bantablemodel.cpp4
-rw-r--r--src/qt/coincontroldialog.cpp7
-rw-r--r--src/qt/guiutil.cpp2
-rw-r--r--src/qt/paymentserver.cpp12
-rw-r--r--src/qt/rpcconsole.cpp2
-rw-r--r--src/random.cpp55
-rw-r--r--src/rest.cpp9
-rw-r--r--src/rpc/blockchain.cpp74
-rw-r--r--src/rpc/client.cpp1
-rw-r--r--src/rpc/rawtransaction.cpp78
-rw-r--r--src/script/interpreter.cpp6
-rw-r--r--src/test/addrman_tests.cpp195
-rw-r--r--src/test/amount_tests.cpp39
-rw-r--r--src/test/main_tests.cpp7
-rw-r--r--src/test/miner_tests.cpp3
-rw-r--r--src/test/pow_tests.cpp32
-rw-r--r--src/test/versionbits_tests.cpp6
-rw-r--r--src/txmempool.h1
-rw-r--r--src/utiltime.cpp12
-rw-r--r--src/validation.cpp67
-rw-r--r--src/validation.h7
-rw-r--r--src/wallet/coincontrol.h1
-rw-r--r--src/wallet/db.cpp9
-rw-r--r--src/wallet/db.h1
-rw-r--r--src/wallet/feebumper.cpp4
-rw-r--r--src/wallet/rpcwallet.cpp1
-rw-r--r--src/wallet/wallet.cpp44
-rw-r--r--src/wallet/wallet.h15
54 files changed, 640 insertions, 561 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index cb88171348..14d55a944f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -116,6 +116,7 @@ BITCOIN_CORE_H = \
netbase.h \
netmessagemaker.h \
noui.h \
+ policy/feerate.h \
policy/fees.h \
policy/policy.h \
policy/rbf.h \
@@ -178,8 +179,8 @@ libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h
libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS)
libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libbitcoin_server_a_SOURCES = \
- addrman.cpp \
addrdb.cpp \
+ addrman.cpp \
bloom.cpp \
blockencodings.cpp \
chain.cpp \
@@ -301,7 +302,6 @@ libbitcoin_consensus_a_SOURCES = \
libbitcoin_common_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
libbitcoin_common_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libbitcoin_common_a_SOURCES = \
- amount.cpp \
base58.cpp \
chainparams.cpp \
coins.cpp \
@@ -312,6 +312,7 @@ libbitcoin_common_a_SOURCES = \
keystore.cpp \
netaddress.cpp \
netbase.cpp \
+ policy/feerate.cpp \
protocol.cpp \
scheduler.cpp \
script/sign.cpp \
diff --git a/src/amount.h b/src/amount.h
index 93060f7193..2bd367cba2 100644
--- a/src/amount.h
+++ b/src/amount.h
@@ -6,10 +6,7 @@
#ifndef BITCOIN_AMOUNT_H
#define BITCOIN_AMOUNT_H
-#include "serialize.h"
-
-#include <stdlib.h>
-#include <string>
+#include <stdint.h>
/** Amount in satoshis (Can be negative) */
typedef int64_t CAmount;
@@ -17,8 +14,6 @@ typedef int64_t CAmount;
static const CAmount COIN = 100000000;
static const CAmount CENT = 1000000;
-extern const std::string CURRENCY_UNIT;
-
/** No amount larger than this (in satoshi) is valid.
*
* Note that this constant is *not* the total money supply, which in Bitcoin
@@ -31,42 +26,4 @@ extern const std::string CURRENCY_UNIT;
static const CAmount MAX_MONEY = 21000000 * COIN;
inline bool MoneyRange(const CAmount& nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
-/**
- * Fee rate in satoshis per kilobyte: CAmount / kB
- */
-class CFeeRate
-{
-private:
- CAmount nSatoshisPerK; // unit is satoshis-per-1,000-bytes
-public:
- /** Fee rate of 0 satoshis per kB */
- CFeeRate() : nSatoshisPerK(0) { }
- explicit CFeeRate(const CAmount& _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) { }
- /** Constructor for a fee rate in satoshis per kB. The size in bytes must not exceed (2^63 - 1)*/
- CFeeRate(const CAmount& nFeePaid, size_t nBytes);
- CFeeRate(const CFeeRate& other) { nSatoshisPerK = other.nSatoshisPerK; }
- /**
- * Return the fee in satoshis for the given size in bytes.
- */
- CAmount GetFee(size_t nBytes) const;
- /**
- * Return the fee in satoshis for a size of 1000 bytes
- */
- CAmount GetFeePerK() const { return GetFee(1000); }
- friend bool operator<(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK < b.nSatoshisPerK; }
- friend bool operator>(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK > b.nSatoshisPerK; }
- friend bool operator==(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK == b.nSatoshisPerK; }
- friend bool operator<=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK <= b.nSatoshisPerK; }
- friend bool operator>=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK >= b.nSatoshisPerK; }
- CFeeRate& operator+=(const CFeeRate& a) { nSatoshisPerK += a.nSatoshisPerK; return *this; }
- std::string ToString() const;
-
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(nSatoshisPerK);
- }
-};
-
#endif // BITCOIN_AMOUNT_H
diff --git a/src/bench/checkblock.cpp b/src/bench/checkblock.cpp
index c6c932454a..195388839e 100644
--- a/src/bench/checkblock.cpp
+++ b/src/bench/checkblock.cpp
@@ -40,7 +40,7 @@ static void DeserializeAndCheckBlockTest(benchmark::State& state)
char a = '\0';
stream.write(&a, 1); // Prevent compaction
- Consensus::Params params = Params(CBaseChainParams::MAIN).GetConsensus();
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
while (state.KeepRunning()) {
CBlock block; // Note that CBlock caches its checked state, so we need to recreate it here
@@ -48,7 +48,7 @@ static void DeserializeAndCheckBlockTest(benchmark::State& state)
assert(stream.Rewind(sizeof(block_bench::block413567)));
CValidationState validationState;
- assert(CheckBlock(block, validationState, params));
+ assert(CheckBlock(block, validationState, chainParams->GetConsensus()));
}
}
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index 5edd43d41e..885b787b4d 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -30,6 +30,8 @@ static const int CONTINUE_EXECUTION=-1;
std::string HelpMessageCli()
{
+ const auto defaultBaseParams = CreateBaseChainParams(CBaseChainParams::MAIN);
+ const auto testnetBaseParams = CreateBaseChainParams(CBaseChainParams::TESTNET);
std::string strUsage;
strUsage += HelpMessageGroup(_("Options:"));
strUsage += HelpMessageOpt("-?", _("This help message"));
@@ -38,7 +40,7 @@ std::string HelpMessageCli()
AppendParamsHelpMessages(strUsage);
strUsage += HelpMessageOpt("-named", strprintf(_("Pass named instead of positional arguments (default: %s)"), DEFAULT_NAMED));
strUsage += HelpMessageOpt("-rpcconnect=<ip>", strprintf(_("Send commands to node running on <ip> (default: %s)"), DEFAULT_RPCCONNECT));
- strUsage += HelpMessageOpt("-rpcport=<port>", strprintf(_("Connect to JSON-RPC on <port> (default: %u or testnet: %u)"), BaseParams(CBaseChainParams::MAIN).RPCPort(), BaseParams(CBaseChainParams::TESTNET).RPCPort()));
+ strUsage += HelpMessageOpt("-rpcport=<port>", strprintf(_("Connect to JSON-RPC on <port> (default: %u or testnet: %u)"), defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort()));
strUsage += HelpMessageOpt("-rpcwait", _("Wait for RPC server to start"));
strUsage += HelpMessageOpt("-rpcuser=<user>", _("Username for JSON-RPC connections"));
strUsage += HelpMessageOpt("-rpcpassword=<pw>", _("Password for JSON-RPC connections"));
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index 83b855cbcf..45738b5df8 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -657,11 +657,13 @@ static void MutateTx(CMutableTransaction& tx, const std::string& command,
MutateTxDelOutput(tx, commandVal);
else if (command == "outaddr")
MutateTxAddOutAddr(tx, commandVal);
- else if (command == "outpubkey")
+ else if (command == "outpubkey") {
+ if (!ecc) { ecc.reset(new Secp256k1Init()); }
MutateTxAddOutPubKey(tx, commandVal);
- else if (command == "outmultisig")
+ } else if (command == "outmultisig") {
+ if (!ecc) { ecc.reset(new Secp256k1Init()); }
MutateTxAddOutMultiSig(tx, commandVal);
- else if (command == "outscript")
+ } else if (command == "outscript")
MutateTxAddOutScript(tx, commandVal);
else if (command == "outdata")
MutateTxAddOutData(tx, commandVal);
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index 1dc29826af..5055fb3e0a 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -55,6 +55,12 @@ static CBlock CreateGenesisBlock(uint32_t nTime, uint32_t nNonce, uint32_t nBits
return CreateGenesisBlock(pszTimestamp, genesisOutputScript, nTime, nNonce, nBits, nVersion, genesisReward);
}
+void CChainParams::UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout)
+{
+ consensus.vDeployments[d].nStartTime = nStartTime;
+ consensus.vDeployments[d].nTimeout = nTimeout;
+}
+
/**
* Main network
*/
@@ -165,7 +171,6 @@ public:
};
}
};
-static CMainParams mainParams;
/**
* Testnet (v3)
@@ -253,7 +258,6 @@ public:
}
};
-static CTestNetParams testNetParams;
/**
* Regression test
@@ -326,42 +330,34 @@ public:
base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container<std::vector<unsigned char> >();
base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94).convert_to_container<std::vector<unsigned char> >();
}
-
- void UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout)
- {
- consensus.vDeployments[d].nStartTime = nStartTime;
- consensus.vDeployments[d].nTimeout = nTimeout;
- }
};
-static CRegTestParams regTestParams;
-static CChainParams *pCurrentParams = 0;
+static std::unique_ptr<CChainParams> globalChainParams;
const CChainParams &Params() {
- assert(pCurrentParams);
- return *pCurrentParams;
+ assert(globalChainParams);
+ return *globalChainParams;
}
-CChainParams& Params(const std::string& chain)
+std::unique_ptr<CChainParams> CreateChainParams(const std::string& chain)
{
if (chain == CBaseChainParams::MAIN)
- return mainParams;
+ return std::unique_ptr<CChainParams>(new CMainParams());
else if (chain == CBaseChainParams::TESTNET)
- return testNetParams;
+ return std::unique_ptr<CChainParams>(new CTestNetParams());
else if (chain == CBaseChainParams::REGTEST)
- return regTestParams;
- else
- throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain));
+ return std::unique_ptr<CChainParams>(new CRegTestParams());
+ throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain));
}
void SelectParams(const std::string& network)
{
SelectBaseParams(network);
- pCurrentParams = &Params(network);
+ globalChainParams = CreateChainParams(network);
}
-void UpdateRegtestBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout)
+void UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout)
{
- regTestParams.UpdateBIP9Parameters(d, nStartTime, nTimeout);
+ globalChainParams->UpdateBIP9Parameters(d, nStartTime, nTimeout);
}
diff --git a/src/chainparams.h b/src/chainparams.h
index 4fe88c691c..e5312d1080 100644
--- a/src/chainparams.h
+++ b/src/chainparams.h
@@ -11,6 +11,7 @@
#include "primitives/block.h"
#include "protocol.h"
+#include <memory>
#include <vector>
struct CDNSSeedData {
@@ -75,6 +76,7 @@ public:
const std::vector<SeedSpec6>& FixedSeeds() const { return vFixedSeeds; }
const CCheckpointData& Checkpoints() const { return checkpointData; }
const ChainTxData& TxData() const { return chainTxData; }
+ void UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout);
protected:
CChainParams() {}
@@ -95,15 +97,17 @@ protected:
};
/**
- * Return the currently selected parameters. This won't change after app
- * startup, except for unit tests.
+ * Creates and returns a std::unique_ptr<CChainParams> of the chosen chain.
+ * @returns a CChainParams* of the chosen chain.
+ * @throws a std::runtime_error if the chain is not supported.
*/
-const CChainParams &Params();
+std::unique_ptr<CChainParams> CreateChainParams(const std::string& chain);
/**
- * @returns CChainParams for the given BIP70 chain name.
+ * Return the currently selected parameters. This won't change after app
+ * startup, except for unit tests.
*/
-CChainParams& Params(const std::string& chain);
+const CChainParams &Params();
/**
* Sets the params returned by Params() to those for the given BIP70 chain name.
@@ -114,6 +118,6 @@ void SelectParams(const std::string& chain);
/**
* Allows modifying the BIP9 regtest parameters.
*/
-void UpdateRegtestBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout);
+void UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout);
#endif // BITCOIN_CHAINPARAMS_H
diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp
index cb71a8b550..43c9a13c54 100644
--- a/src/chainparamsbase.cpp
+++ b/src/chainparamsbase.cpp
@@ -35,7 +35,6 @@ public:
nRPCPort = 8332;
}
};
-static CBaseMainParams mainParams;
/**
* Testnet (v3)
@@ -49,7 +48,6 @@ public:
strDataDir = "testnet3";
}
};
-static CBaseTestNetParams testNetParams;
/*
* Regression test
@@ -63,31 +61,30 @@ public:
strDataDir = "regtest";
}
};
-static CBaseRegTestParams regTestParams;
-static CBaseChainParams* pCurrentBaseParams = 0;
+static std::unique_ptr<CBaseChainParams> globalChainBaseParams;
const CBaseChainParams& BaseParams()
{
- assert(pCurrentBaseParams);
- return *pCurrentBaseParams;
+ assert(globalChainBaseParams);
+ return *globalChainBaseParams;
}
-CBaseChainParams& BaseParams(const std::string& chain)
+std::unique_ptr<CBaseChainParams> CreateBaseChainParams(const std::string& chain)
{
if (chain == CBaseChainParams::MAIN)
- return mainParams;
+ return std::unique_ptr<CBaseChainParams>(new CBaseMainParams());
else if (chain == CBaseChainParams::TESTNET)
- return testNetParams;
+ return std::unique_ptr<CBaseChainParams>(new CBaseTestNetParams());
else if (chain == CBaseChainParams::REGTEST)
- return regTestParams;
+ return std::unique_ptr<CBaseChainParams>(new CBaseRegTestParams());
else
throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain));
}
void SelectBaseParams(const std::string& chain)
{
- pCurrentBaseParams = &BaseParams(chain);
+ globalChainBaseParams = CreateBaseChainParams(chain);
}
std::string ChainNameFromCommandLine()
@@ -103,8 +100,3 @@ std::string ChainNameFromCommandLine()
return CBaseChainParams::TESTNET;
return CBaseChainParams::MAIN;
}
-
-bool AreBaseParamsConfigured()
-{
- return pCurrentBaseParams != NULL;
-}
diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h
index 59493afb9b..fc101f5b77 100644
--- a/src/chainparamsbase.h
+++ b/src/chainparamsbase.h
@@ -5,6 +5,7 @@
#ifndef BITCOIN_CHAINPARAMSBASE_H
#define BITCOIN_CHAINPARAMSBASE_H
+#include <memory>
#include <string>
#include <vector>
@@ -31,6 +32,13 @@ protected:
};
/**
+ * Creates and returns a std::unique_ptr<CBaseChainParams> of the chosen chain.
+ * @returns a CBaseChainParams* of the chosen chain.
+ * @throws a std::runtime_error if the chain is not supported.
+ */
+std::unique_ptr<CBaseChainParams> CreateBaseChainParams(const std::string& chain);
+
+/**
* Append the help messages for the chainparams options to the
* parameter string.
*/
@@ -42,8 +50,6 @@ void AppendParamsHelpMessages(std::string& strUsage, bool debugHelp=true);
*/
const CBaseChainParams& BaseParams();
-CBaseChainParams& BaseParams(const std::string& chain);
-
/** Sets the params returned by Params() to those for the given network. */
void SelectBaseParams(const std::string& chain);
@@ -53,10 +59,4 @@ void SelectBaseParams(const std::string& chain);
*/
std::string ChainNameFromCommandLine();
-/**
- * Return true if SelectBaseParamsFromCommandLine() has been called to select
- * a network.
- */
-bool AreBaseParamsConfigured();
-
#endif // BITCOIN_CHAINPARAMSBASE_H
diff --git a/src/core_write.cpp b/src/core_write.cpp
index a3ca87c8b5..d116e617ee 100644
--- a/src/core_write.cpp
+++ b/src/core_write.cpp
@@ -151,6 +151,8 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry)
entry.pushKV("txid", tx.GetHash().GetHex());
entry.pushKV("hash", tx.GetWitnessHash().GetHex());
entry.pushKV("version", tx.nVersion);
+ entry.pushKV("size", (int)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION));
+ entry.pushKV("vsize", (GetTransactionWeight(tx) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR);
entry.pushKV("locktime", (int64_t)tx.nLockTime);
UniValue vin(UniValue::VARR);
diff --git a/src/init.cpp b/src/init.cpp
index f06c9e1100..135fd469c0 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -25,6 +25,7 @@
#include "netbase.h"
#include "net.h"
#include "net_processing.h"
+#include "policy/feerate.h"
#include "policy/fees.h"
#include "policy/policy.h"
#include "rpc/server.h"
@@ -208,8 +209,9 @@ void Shutdown()
StopTorControl();
UnregisterNodeSignals(GetNodeSignals());
- if (fDumpMempoolLater)
+ if (fDumpMempoolLater && GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
DumpMempool();
+ }
if (fFeeEstimatesInitialized)
{
@@ -327,6 +329,10 @@ void OnRPCPreCommand(const CRPCCommand& cmd)
std::string HelpMessage(HelpMessageMode mode)
{
+ const auto defaultBaseParams = CreateBaseChainParams(CBaseChainParams::MAIN);
+ const auto testnetBaseParams = CreateBaseChainParams(CBaseChainParams::TESTNET);
+ const auto defaultChainParams = CreateChainParams(CBaseChainParams::MAIN);
+ const auto testnetChainParams = CreateChainParams(CBaseChainParams::TESTNET);
const bool showDebug = GetBoolArg("-help-debug", false);
// When adding new options to the categories, please keep and ensure alphabetical ordering.
@@ -338,7 +344,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-blocknotify=<cmd>", _("Execute command when the best block changes (%s in cmd is replaced by block hash)"));
if (showDebug)
strUsage += HelpMessageOpt("-blocksonly", strprintf(_("Whether to operate in a blocks only mode (default: %u)"), DEFAULT_BLOCKSONLY));
- strUsage +=HelpMessageOpt("-assumevalid=<hex>", strprintf(_("If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)"), Params(CBaseChainParams::MAIN).GetConsensus().defaultAssumeValid.GetHex(), Params(CBaseChainParams::TESTNET).GetConsensus().defaultAssumeValid.GetHex()));
+ strUsage +=HelpMessageOpt("-assumevalid=<hex>", strprintf(_("If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)"), defaultChainParams->GetConsensus().defaultAssumeValid.GetHex(), testnetChainParams->GetConsensus().defaultAssumeValid.GetHex()));
strUsage += HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file (default: %s)"), BITCOIN_CONF_FILENAME));
if (mode == HMM_BITCOIND)
{
@@ -354,6 +360,7 @@ 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));
+ 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)"),
-GetNumCores(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS));
@@ -391,7 +398,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-onlynet=<net>", _("Only connect to nodes in network <net> (ipv4, ipv6 or onion)"));
strUsage += HelpMessageOpt("-permitbaremultisig", strprintf(_("Relay non-P2SH multisig (default: %u)"), DEFAULT_PERMIT_BAREMULTISIG));
strUsage += HelpMessageOpt("-peerbloomfilters", strprintf(_("Support filtering of blocks and transaction with bloom filters (default: %u)"), DEFAULT_PEERBLOOMFILTERS));
- strUsage += HelpMessageOpt("-port=<port>", strprintf(_("Listen for connections on <port> (default: %u or testnet: %u)"), Params(CBaseChainParams::MAIN).GetDefaultPort(), Params(CBaseChainParams::TESTNET).GetDefaultPort()));
+ strUsage += HelpMessageOpt("-port=<port>", strprintf(_("Listen for connections on <port> (default: %u or testnet: %u)"), defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort()));
strUsage += HelpMessageOpt("-proxy=<ip:port>", _("Connect through SOCKS5 proxy"));
strUsage += HelpMessageOpt("-proxyrandomize", strprintf(_("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)"), DEFAULT_PROXYRANDOMIZE));
strUsage += HelpMessageOpt("-seednode=<ip>", _("Connect to a node to retrieve peer addresses, and disconnect"));
@@ -428,14 +435,16 @@ std::string HelpMessage(HelpMessageMode mode)
{
strUsage += HelpMessageOpt("-checkblocks=<n>", strprintf(_("How many blocks to check at startup (default: %u, 0 = all)"), DEFAULT_CHECKBLOCKS));
strUsage += HelpMessageOpt("-checklevel=<n>", strprintf(_("How thorough the block verification of -checkblocks is (0-4, default: %u)"), DEFAULT_CHECKLEVEL));
- strUsage += HelpMessageOpt("-checkblockindex", strprintf("Do a full consistency check for mapBlockIndex, setBlockIndexCandidates, chainActive and mapBlocksUnlinked occasionally. Also sets -checkmempool (default: %u)", Params(CBaseChainParams::MAIN).DefaultConsistencyChecks()));
- strUsage += HelpMessageOpt("-checkmempool=<n>", strprintf("Run checks every <n> transactions (default: %u)", Params(CBaseChainParams::MAIN).DefaultConsistencyChecks()));
+ strUsage += HelpMessageOpt("-checkblockindex", strprintf("Do a full consistency check for mapBlockIndex, setBlockIndexCandidates, chainActive and mapBlocksUnlinked occasionally. Also sets -checkmempool (default: %u)", defaultChainParams->DefaultConsistencyChecks()));
+ strUsage += HelpMessageOpt("-checkmempool=<n>", strprintf("Run checks every <n> transactions (default: %u)", defaultChainParams->DefaultConsistencyChecks()));
strUsage += HelpMessageOpt("-checkpoints", strprintf("Disable expensive verification for known chain history (default: %u)", DEFAULT_CHECKPOINTS_ENABLED));
strUsage += HelpMessageOpt("-disablesafemode", strprintf("Disable safemode, override a real safe mode event (default: %u)", DEFAULT_DISABLE_SAFEMODE));
strUsage += HelpMessageOpt("-testsafemode", strprintf("Force safe mode (default: %u)", DEFAULT_TESTSAFEMODE));
strUsage += HelpMessageOpt("-dropmessagestest=<n>", "Randomly drop 1 of every <n> network messages");
strUsage += HelpMessageOpt("-fuzzmessagestest=<n>", "Randomly fuzz 1 of every <n> network messages");
strUsage += HelpMessageOpt("-stopafterblockimport", strprintf("Stop running after importing blocks from disk (default: %u)", DEFAULT_STOPAFTERBLOCKIMPORT));
+ strUsage += HelpMessageOpt("-stopatheight", strprintf("Stop running after reaching the given height in the main chain (default: %u)", DEFAULT_STOPATHEIGHT));
+
strUsage += HelpMessageOpt("-limitancestorcount=<n>", strprintf("Do not accept transactions if number of in-mempool ancestors is <n> or more (default: %u)", DEFAULT_ANCESTOR_LIMIT));
strUsage += HelpMessageOpt("-limitancestorsize=<n>", strprintf("Do not accept transactions whose size with all in-mempool ancestors exceeds <n> kilobytes (default: %u)", DEFAULT_ANCESTOR_SIZE_LIMIT));
strUsage += HelpMessageOpt("-limitdescendantcount=<n>", strprintf("Do not accept transactions if any ancestor would have <n> or more in-mempool descendants (default: %u)", DEFAULT_DESCENDANT_LIMIT));
@@ -468,7 +477,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageGroup(_("Node relay options:"));
if (showDebug) {
- strUsage += HelpMessageOpt("-acceptnonstdtxn", strprintf("Relay and mine \"non-standard\" transactions (%sdefault: %u)", "testnet/regtest only; ", !Params(CBaseChainParams::TESTNET).RequireStandard()));
+ strUsage += HelpMessageOpt("-acceptnonstdtxn", strprintf("Relay and mine \"non-standard\" transactions (%sdefault: %u)", "testnet/regtest only; ", defaultChainParams->RequireStandard()));
strUsage += HelpMessageOpt("-incrementalrelayfee=<amt>", strprintf("Fee rate (in %s/kB) used to define cost of relay, used for mempool limiting and BIP 125 replacement. (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_INCREMENTAL_RELAY_FEE)));
strUsage += HelpMessageOpt("-dustrelayfee=<amt>", strprintf("Fee rate (in %s/kB) used to defined dust, the value of an output such that it will cost about 1/3 of its value in fees at this fee rate to spend it. (default: %s)", CURRENCY_UNIT, FormatMoney(DUST_RELAY_TX_FEE)));
}
@@ -496,7 +505,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-rpcuser=<user>", _("Username for JSON-RPC connections"));
strUsage += HelpMessageOpt("-rpcpassword=<pw>", _("Password for JSON-RPC connections"));
strUsage += HelpMessageOpt("-rpcauth=<userpw>", _("Username and hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=<USERNAME>/rpcpassword=<PASSWORD> pair of arguments. This option can be specified multiple times"));
- strUsage += HelpMessageOpt("-rpcport=<port>", strprintf(_("Listen for JSON-RPC connections on <port> (default: %u or testnet: %u)"), BaseParams(CBaseChainParams::MAIN).RPCPort(), BaseParams(CBaseChainParams::TESTNET).RPCPort()));
+ strUsage += HelpMessageOpt("-rpcport=<port>", strprintf(_("Listen for JSON-RPC connections on <port> (default: %u or testnet: %u)"), defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort()));
strUsage += HelpMessageOpt("-rpcallowip=<ip>", _("Allow JSON-RPC connections from specified source. Valid for <ip> are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times"));
strUsage += HelpMessageOpt("-rpcserialversion", strprintf(_("Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)"), DEFAULT_RPC_SERIALIZE_VERSION));
strUsage += HelpMessageOpt("-rpcthreads=<n>", strprintf(_("Set the number of threads to service RPC calls (default: %d)"), DEFAULT_HTTP_THREADS));
@@ -677,8 +686,10 @@ void ThreadImport(std::vector<fs::path> vImportFiles)
StartShutdown();
}
} // End scope of CImportingNow
- LoadMempool();
- fDumpMempoolLater = !fRequestShutdown;
+ if (GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
+ LoadMempool();
+ fDumpMempoolLater = !fRequestShutdown;
+ }
}
/** Sanity checks
@@ -1117,7 +1128,7 @@ bool AppInitParameterInteraction()
for (int j=0; j<(int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j)
{
if (vDeploymentParams[0].compare(VersionBitsDeploymentInfo[j].name) == 0) {
- UpdateRegtestBIP9Parameters(Consensus::DeploymentPos(j), nStartTime, nTimeout);
+ UpdateBIP9Parameters(Consensus::DeploymentPos(j), nStartTime, nTimeout);
found = true;
LogPrintf("Setting BIP9 activation parameters for %s to start=%ld, timeout=%ld\n", vDeploymentParams[0], nStartTime, nTimeout);
break;
diff --git a/src/key.cpp b/src/key.cpp
index b4f0dc8202..5a75647f1a 100644
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -131,14 +131,6 @@ void CKey::MakeNewKey(bool fCompressedIn) {
fCompressed = fCompressedIn;
}
-bool CKey::SetPrivKey(const CPrivKey &privkey, bool fCompressedIn) {
- if (!ec_privkey_import_der(secp256k1_context_sign, (unsigned char*)begin(), &privkey[0], privkey.size()))
- return false;
- fCompressed = fCompressedIn;
- fValid = true;
- return true;
-}
-
CPrivKey CKey::GetPrivKey() const {
assert(fValid);
CPrivKey privkey;
diff --git a/src/key.h b/src/key.h
index 925a8d186d..2c6f151727 100644
--- a/src/key.h
+++ b/src/key.h
@@ -94,9 +94,6 @@ public:
//! Check whether the public key corresponding to this private key is (to be) compressed.
bool IsCompressed() const { return fCompressed; }
- //! Initialize from a CPrivKey (serialized OpenSSL private key data).
- bool SetPrivKey(const CPrivKey& vchPrivKey, bool fCompressed);
-
//! Generate a new private key using a cryptographic PRNG.
void MakeNewKey(bool fCompressed);
diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp
index e3f3e4621a..78d7cd6001 100644
--- a/src/merkleblock.cpp
+++ b/src/merkleblock.cpp
@@ -65,7 +65,7 @@ uint256 CPartialMerkleTree::CalcHash(int height, unsigned int pos, const std::ve
} else {
// calculate left hash
uint256 left = CalcHash(height-1, pos*2, vTxid), right;
- // calculate right hash if not beyond the end of the array - copy left hash otherwise1
+ // calculate right hash if not beyond the end of the array - copy left hash otherwise
if (pos*2+1 < CalcTreeWidth(height-1))
right = CalcHash(height-1, pos*2+1, vTxid);
else
diff --git a/src/miner.cpp b/src/miner.cpp
index 386d75c4be..9d2959723a 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -15,6 +15,7 @@
#include "hash.h"
#include "validation.h"
#include "net.h"
+#include "policy/feerate.h"
#include "policy/policy.h"
#include "pow.h"
#include "primitives/transaction.h"
@@ -317,9 +318,7 @@ int BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& already
bool BlockAssembler::SkipMapTxEntry(CTxMemPool::txiter it, indexed_modified_transaction_set &mapModifiedTx, CTxMemPool::setEntries &failedTx)
{
assert (it != mempool.mapTx.end());
- if (mapModifiedTx.count(it) || inBlock.count(it) || failedTx.count(it))
- return true;
- return false;
+ return mapModifiedTx.count(it) || inBlock.count(it) || failedTx.count(it);
}
void BlockAssembler::SortForBlock(const CTxMemPool::setEntries& package, CTxMemPool::txiter entry, std::vector<CTxMemPool::txiter>& sortedEntries)
diff --git a/src/net.cpp b/src/net.cpp
index 50b192e2ca..1d90804627 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -418,10 +418,10 @@ void CConnman::DumpBanlist()
CBanDB bandb;
banmap_t banmap;
- SetBannedSetDirty(false);
GetBanned(banmap);
- if (!bandb.Write(banmap))
- SetBannedSetDirty(true);
+ if (bandb.Write(banmap)) {
+ SetBannedSetDirty(false);
+ }
LogPrint(BCLog::NET, "Flushed %d banned node ips/subnets to banlist.dat %dms\n",
banmap.size(), GetTimeMillis() - nStart);
@@ -541,6 +541,8 @@ bool CConnman::Unban(const CSubNet &subNet) {
void CConnman::GetBanned(banmap_t &banMap)
{
LOCK(cs_setBanned);
+ // Sweep the banlist so expired bans are not returned
+ SweepBanned();
banMap = setBanned; //create a thread safe copy
}
@@ -946,7 +948,7 @@ bool CConnman::AttemptToEvictConnection()
continue;
if (node->fDisconnect)
continue;
- NodeEvictionCandidate candidate = {node->id, node->nTimeConnected, node->nMinPingUsecTime,
+ NodeEvictionCandidate candidate = {node->GetId(), node->nTimeConnected, node->nMinPingUsecTime,
node->nLastBlockTime, node->nLastTXTime,
(node->nServices & nRelevantServices) == nRelevantServices,
node->fRelayTxes, node->pfilter != NULL, node->addr, node->nKeyedNetGroup};
@@ -1372,7 +1374,7 @@ void CConnman::ThreadSocketHandler()
{
if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
{
- LogPrint(BCLog::NET, "socket no message in first 60 seconds, %d %d from %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0, pnode->id);
+ LogPrint(BCLog::NET, "socket no message in first 60 seconds, %d %d from %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0, pnode->GetId());
pnode->fDisconnect = true;
}
else if (nTime - pnode->nLastSend > TIMEOUT_INTERVAL)
@@ -1392,7 +1394,7 @@ void CConnman::ThreadSocketHandler()
}
else if (!pnode->fSuccessfullyConnected)
{
- LogPrintf("version handshake timeout from %d\n", pnode->id);
+ LogPrintf("version handshake timeout from %d\n", pnode->GetId());
pnode->fDisconnect = true;
}
}
@@ -2485,7 +2487,7 @@ bool CConnman::DisconnectNode(NodeId id)
{
LOCK(cs_vNodes);
for(CNode* pnode : vNodes) {
- if (id == pnode->id) {
+ if (id == pnode->GetId()) {
pnode->fDisconnect = true;
return true;
}
@@ -2623,10 +2625,10 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn
nTimeConnected(GetSystemTimeInSeconds()),
addr(addrIn),
fInbound(fInboundIn),
- id(idIn),
nKeyedNetGroup(nKeyedNetGroupIn),
addrKnown(5000, 0.001),
filterInventoryKnown(50000, 0.000001),
+ id(idIn),
nLocalHostNonce(nLocalHostNonceIn),
nLocalServices(nLocalServicesIn),
nMyStartingHeight(nMyStartingHeightIn),
@@ -2742,7 +2744,7 @@ void CConnman::PushMessage(CNode* pnode, CSerializedNetMsg&& msg)
{
size_t nMessageSize = msg.data.size();
size_t nTotalSize = nMessageSize + CMessageHeader::HEADER_SIZE;
- LogPrint(BCLog::NET, "sending %s (%d bytes) peer=%d\n", SanitizeString(msg.command.c_str()), nMessageSize, pnode->id);
+ LogPrint(BCLog::NET, "sending %s (%d bytes) peer=%d\n", SanitizeString(msg.command.c_str()), nMessageSize, pnode->GetId());
std::vector<unsigned char> serializedHeader;
serializedHeader.reserve(CMessageHeader::HEADER_SIZE);
@@ -2780,7 +2782,7 @@ bool CConnman::ForNode(NodeId id, std::function<bool(CNode* pnode)> func)
CNode* found = nullptr;
LOCK(cs_vNodes);
for (auto&& pnode : vNodes) {
- if(pnode->id == id) {
+ if(pnode->GetId() == id) {
found = pnode;
break;
}
diff --git a/src/net.h b/src/net.h
index 4a63ef84e7..bea04bc580 100644
--- a/src/net.h
+++ b/src/net.h
@@ -14,6 +14,7 @@
#include "hash.h"
#include "limitedmap.h"
#include "netaddress.h"
+#include "policy/feerate.h"
#include "protocol.h"
#include "random.h"
#include "streams.h"
@@ -611,7 +612,6 @@ public:
CCriticalSection cs_filter;
CBloomFilter* pfilter;
std::atomic<int> nRefCount;
- const NodeId id;
const uint64_t nKeyedNetGroup;
std::atomic_bool fPauseRecv;
@@ -682,6 +682,7 @@ public:
private:
CNode(const CNode&);
void operator=(const CNode&);
+ const NodeId id;
const uint64_t nLocalHostNonce;
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 718a7de031..4d924b5cdb 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -815,7 +815,7 @@ void PeerLogicValidation::NewPoWValidBlock(const CBlockIndex *pindex, const std:
!PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->pprev)) {
LogPrint(BCLog::NET, "%s sending header-and-ids %s to peer=%d\n", "PeerLogicValidation::NewPoWValidBlock",
- hashBlock.ToString(), pnode->id);
+ hashBlock.ToString(), pnode->GetId());
connman->PushMessage(pnode, msgMaker.Make(NetMsgType::CMPCTBLOCK, *pcmpctblock));
state.pindexBestHeaderSent = pindex;
}
@@ -950,7 +950,7 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman& connma
auto sortfunc = [&best, &hasher, nRelayNodes](CNode* pnode) {
if (pnode->nVersion >= CADDR_TIME_VERSION) {
- uint64_t hashKey = CSipHasher(hasher).Write(pnode->id).Finalize();
+ uint64_t hashKey = CSipHasher(hasher).Write(pnode->GetId()).Finalize();
for (unsigned int i = 0; i < nRelayNodes; i++) {
if (hashKey > best[i].first) {
std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
@@ -1162,7 +1162,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
}
}
-uint32_t GetFetchFlags(CNode* pfrom, const CBlockIndex* pprev, const Consensus::Params& chainparams) {
+uint32_t GetFetchFlags(CNode* pfrom) {
uint32_t nFetchFlags = 0;
if ((pfrom->GetLocalServices() & NODE_WITNESS) && State(pfrom->GetId())->fHaveWitness) {
nFetchFlags |= MSG_WITNESS_FLAG;
@@ -1176,7 +1176,7 @@ inline void static SendBlockTransactions(const CBlock& block, const BlockTransac
if (req.indexes[i] >= block.vtx.size()) {
LOCK(cs_main);
Misbehaving(pfrom->GetId(), 100);
- LogPrintf("Peer %d sent us a getblocktxn with out-of-bounds tx indices", pfrom->id);
+ LogPrintf("Peer %d sent us a getblocktxn with out-of-bounds tx indices", pfrom->GetId());
return;
}
resp.txn[i] = block.vtx[req.indexes[i]];
@@ -1189,7 +1189,7 @@ inline void static SendBlockTransactions(const CBlock& block, const BlockTransac
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->id);
+ LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->GetId());
if (IsArgSet("-dropmessagestest") && GetRand(GetArg("-dropmessagestest", 0)) == 0)
{
LogPrintf("dropmessagestest DROPPING RECV MESSAGE\n");
@@ -1268,7 +1268,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
}
if (pfrom->nServicesExpected & ~nServices)
{
- LogPrint(BCLog::NET, "peer=%d does not offer the expected services (%08x offered, %08x expected); disconnecting\n", pfrom->id, nServices, pfrom->nServicesExpected);
+ 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,
strprintf("Expected to offer services %08x", pfrom->nServicesExpected)));
pfrom->fDisconnect = true;
@@ -1278,7 +1278,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (nVersion < MIN_PEER_PROTO_VERSION)
{
// disconnect from peers older than this proto version
- LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, nVersion);
+ 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,
strprintf("Version must be %d or greater", MIN_PEER_PROTO_VERSION)));
pfrom->fDisconnect = true;
@@ -1380,7 +1380,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
LogPrintf("receive version message: %s: version %d, blocks=%d, us=%s, peer=%d%s\n",
cleanSubVer, pfrom->nVersion,
- pfrom->nStartingHeight, addrMe.ToString(), pfrom->id,
+ pfrom->nStartingHeight, addrMe.ToString(), pfrom->GetId(),
remoteAddr);
int64_t nTimeOffset = nTime - GetTime();
@@ -1550,9 +1550,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
LOCK(cs_main);
- uint32_t nFetchFlags = GetFetchFlags(pfrom, chainActive.Tip(), chainparams.GetConsensus());
-
- std::vector<CInv> vToFetch;
+ uint32_t nFetchFlags = GetFetchFlags(pfrom);
for (unsigned int nInv = 0; nInv < vInv.size(); nInv++)
{
@@ -1562,7 +1560,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return true;
bool fAlreadyHave = AlreadyHave(inv);
- LogPrint(BCLog::NET, "got inv: %s %s peer=%d\n", inv.ToString(), fAlreadyHave ? "have" : "new", pfrom->id);
+ LogPrint(BCLog::NET, "got inv: %s %s peer=%d\n", inv.ToString(), fAlreadyHave ? "have" : "new", pfrom->GetId());
if (inv.type == MSG_TX) {
inv.type |= nFetchFlags;
@@ -1577,14 +1575,14 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// 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));
- LogPrint(BCLog::NET, "getheaders (%d) %s to peer=%d\n", pindexBestHeader->nHeight, inv.hash.ToString(), pfrom->id);
+ LogPrint(BCLog::NET, "getheaders (%d) %s to peer=%d\n", pindexBestHeader->nHeight, inv.hash.ToString(), pfrom->GetId());
}
}
else
{
pfrom->AddInventoryKnown(inv);
if (fBlocksOnly) {
- LogPrint(BCLog::NET, "transaction (%s) inv sent in violation of protocol peer=%d\n", inv.hash.ToString(), pfrom->id);
+ LogPrint(BCLog::NET, "transaction (%s) inv sent in violation of protocol peer=%d\n", inv.hash.ToString(), pfrom->GetId());
} else if (!fAlreadyHave && !fImporting && !fReindex && !IsInitialBlockDownload()) {
pfrom->AskFor(inv);
}
@@ -1593,9 +1591,6 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// Track requests for our stuff
GetMainSignals().Inventory(inv.hash);
}
-
- if (!vToFetch.empty())
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, vToFetch));
}
@@ -1610,10 +1605,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return error("message getdata size() = %u", vInv.size());
}
- LogPrint(BCLog::NET, "received getdata (%u invsz) peer=%d\n", vInv.size(), pfrom->id);
+ LogPrint(BCLog::NET, "received getdata (%u invsz) peer=%d\n", vInv.size(), pfrom->GetId());
if (vInv.size() > 0) {
- LogPrint(BCLog::NET, "received getdata for: %s peer=%d\n", vInv[0].ToString(), pfrom->id);
+ LogPrint(BCLog::NET, "received getdata for: %s peer=%d\n", vInv[0].ToString(), pfrom->GetId());
}
pfrom->vRecvGetData.insert(pfrom->vRecvGetData.end(), vInv.begin(), vInv.end());
@@ -1653,7 +1648,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (pindex)
pindex = chainActive.Next(pindex);
int nLimit = 500;
- LogPrint(BCLog::NET, "getblocks %d to %s limit %d from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), nLimit, pfrom->id);
+ LogPrint(BCLog::NET, "getblocks %d to %s limit %d from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), nLimit, pfrom->GetId());
for (; pindex; pindex = chainActive.Next(pindex))
{
if (pindex->GetBlockHash() == hashStop)
@@ -1703,7 +1698,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
BlockMap::iterator it = mapBlockIndex.find(req.blockhash);
if (it == mapBlockIndex.end() || !(it->second->nStatus & BLOCK_HAVE_DATA)) {
- LogPrintf("Peer %d sent us a getblocktxn for a block we don't have", pfrom->id);
+ LogPrintf("Peer %d sent us a getblocktxn for a block we don't have", pfrom->GetId());
return true;
}
@@ -1715,7 +1710,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// might maliciously send lots of getblocktxn requests to trigger
// expensive disk reads, because it will require the peer to
// actually receive all the data read from disk over the network.
- LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block > %i deep", pfrom->id, MAX_BLOCKTXN_DEPTH);
+ LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block > %i deep", pfrom->GetId(), MAX_BLOCKTXN_DEPTH);
CInv inv;
inv.type = State(pfrom->GetId())->fWantsCmpctWitness ? MSG_WITNESS_BLOCK : MSG_BLOCK;
inv.hash = req.blockhash;
@@ -1740,7 +1735,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
LOCK(cs_main);
if (IsInitialBlockDownload() && !pfrom->fWhitelisted) {
- LogPrint(BCLog::NET, "Ignoring getheaders from peer=%d because node is in initial block download\n", pfrom->id);
+ LogPrint(BCLog::NET, "Ignoring getheaders from peer=%d because node is in initial block download\n", pfrom->GetId());
return true;
}
@@ -1765,7 +1760,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// we must use CBlocks, as CBlockHeaders won't include the 0x00 nTx count at the end
std::vector<CBlock> vHeaders;
int nLimit = MAX_HEADERS_RESULTS;
- LogPrint(BCLog::NET, "getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), pfrom->id);
+ LogPrint(BCLog::NET, "getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), pfrom->GetId());
for (; pindex; pindex = chainActive.Next(pindex))
{
vHeaders.push_back(pindex->GetBlockHeader());
@@ -1795,7 +1790,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// We are in blocks only mode and peer is either not whitelisted or whitelistrelay is off
if (!fRelayTxes && (!pfrom->fWhitelisted || !GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY)))
{
- LogPrint(BCLog::NET, "transaction sent in violation of protocol peer=%d\n", pfrom->id);
+ LogPrint(BCLog::NET, "transaction sent in violation of protocol peer=%d\n", pfrom->GetId());
return true;
}
@@ -1828,7 +1823,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
pfrom->nLastTXTime = GetTime();
LogPrint(BCLog::MEMPOOL, "AcceptToMemoryPool: peer=%d: accepted %s (poolsz %u txn, %u kB)\n",
- pfrom->id,
+ pfrom->GetId(),
tx.GetHash().ToString(),
mempool.size(), mempool.DynamicMemoryUsage() / 1000);
@@ -1903,7 +1898,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
}
}
if (!fRejectedParents) {
- uint32_t nFetchFlags = GetFetchFlags(pfrom, chainActive.Tip(), chainparams.GetConsensus());
+ uint32_t nFetchFlags = GetFetchFlags(pfrom);
BOOST_FOREACH(const CTxIn& txin, tx.vin) {
CInv _inv(MSG_TX | nFetchFlags, txin.prevout.hash);
pfrom->AddInventoryKnown(_inv);
@@ -1948,10 +1943,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// case.
int nDoS = 0;
if (!state.IsInvalid(nDoS) || nDoS == 0) {
- LogPrintf("Force relaying tx %s from whitelisted peer=%d\n", tx.GetHash().ToString(), pfrom->id);
+ LogPrintf("Force relaying tx %s from whitelisted peer=%d\n", tx.GetHash().ToString(), pfrom->GetId());
RelayTransaction(tx, connman);
} else {
- LogPrintf("Not relaying invalid transaction %s from whitelisted peer=%d (%s)\n", tx.GetHash().ToString(), pfrom->id, FormatStateMessage(state));
+ LogPrintf("Not relaying invalid transaction %s from whitelisted peer=%d (%s)\n", tx.GetHash().ToString(), pfrom->GetId(), FormatStateMessage(state));
}
}
}
@@ -1963,7 +1958,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (state.IsInvalid(nDoS))
{
LogPrint(BCLog::MEMPOOLREJ, "%s from peer=%d was not accepted: %s\n", tx.GetHash().ToString(),
- pfrom->id,
+ 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(),
@@ -2000,7 +1995,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
LOCK(cs_main);
Misbehaving(pfrom->GetId(), nDoS);
}
- LogPrintf("Peer %d sent us invalid header via cmpctblock\n", pfrom->id);
+ LogPrintf("Peer %d sent us invalid header via cmpctblock\n", pfrom->GetId());
return true;
}
}
@@ -2040,7 +2035,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// We requested this block for some reason, but our mempool will probably be useless
// so we just grab the block via normal getdata
std::vector<CInv> vInv(1);
- vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(pfrom, pindex->pprev, chainparams.GetConsensus()), cmpctblock.header.GetHash());
+ vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(pfrom), cmpctblock.header.GetHash());
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv));
}
return true;
@@ -2079,12 +2074,12 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (status == READ_STATUS_INVALID) {
MarkBlockAsReceived(pindex->GetBlockHash()); // Reset in-flight state in case of whitelist
Misbehaving(pfrom->GetId(), 100);
- LogPrintf("Peer %d sent us invalid compact block\n", pfrom->id);
+ LogPrintf("Peer %d sent us invalid compact block\n", pfrom->GetId());
return true;
} else if (status == READ_STATUS_FAILED) {
// Duplicate txindexes, the block is now in-flight, so just request it
std::vector<CInv> vInv(1);
- vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(pfrom, pindex->pprev, chainparams.GetConsensus()), cmpctblock.header.GetHash());
+ vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(pfrom), cmpctblock.header.GetHash());
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv));
return true;
}
@@ -2127,7 +2122,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// We requested this block, but its far into the future, so our
// mempool will probably be useless - request the block normally
std::vector<CInv> vInv(1);
- vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(pfrom, pindex->pprev, chainparams.GetConsensus()), cmpctblock.header.GetHash());
+ vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(pfrom), cmpctblock.header.GetHash());
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv));
return true;
} else {
@@ -2184,7 +2179,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator> >::iterator it = mapBlocksInFlight.find(resp.blockhash);
if (it == mapBlocksInFlight.end() || !it->second.second->partialBlock ||
it->second.first != pfrom->GetId()) {
- LogPrint(BCLog::NET, "Peer %d sent us block transactions for block we weren't expecting\n", pfrom->id);
+ LogPrint(BCLog::NET, "Peer %d sent us block transactions for block we weren't expecting\n", pfrom->GetId());
return true;
}
@@ -2193,12 +2188,12 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (status == READ_STATUS_INVALID) {
MarkBlockAsReceived(resp.blockhash); // Reset in-flight state in case of whitelist
Misbehaving(pfrom->GetId(), 100);
- LogPrintf("Peer %d sent us invalid compact block/non-matching block transactions\n", pfrom->id);
+ LogPrintf("Peer %d sent us invalid compact block/non-matching block transactions\n", pfrom->GetId());
return true;
} else if (status == READ_STATUS_FAILED) {
// Might have collided, fall back to getdata now :(
std::vector<CInv> invs;
- invs.push_back(CInv(MSG_BLOCK | GetFetchFlags(pfrom, chainActive.Tip(), chainparams.GetConsensus()), resp.blockhash));
+ invs.push_back(CInv(MSG_BLOCK | GetFetchFlags(pfrom), resp.blockhash));
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, invs));
} else {
// Block is either okay, or possibly we received
@@ -2281,7 +2276,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
headers[0].GetHash().ToString(),
headers[0].hashPrevBlock.ToString(),
pindexBestHeader->nHeight,
- pfrom->id, nodestate->nUnconnectingHeaders);
+ pfrom->GetId(), nodestate->nUnconnectingHeaders);
// Set hashLastUnknownBlock for this peer, so that if we
// eventually get the headers - even from a different peer -
// we can use this peer to download.
@@ -2319,7 +2314,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
LOCK(cs_main);
CNodeState *nodestate = State(pfrom->GetId());
if (nodestate->nUnconnectingHeaders > 0) {
- LogPrint(BCLog::NET, "peer=%d: resetting nUnconnectingHeaders (%d -> 0)\n", pfrom->id, nodestate->nUnconnectingHeaders);
+ LogPrint(BCLog::NET, "peer=%d: resetting nUnconnectingHeaders (%d -> 0)\n", pfrom->GetId(), nodestate->nUnconnectingHeaders);
}
nodestate->nUnconnectingHeaders = 0;
@@ -2330,7 +2325,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// Headers message had its maximum size; the peer may have more headers.
// 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->id, pfrom->nStartingHeight);
+ 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()));
}
@@ -2366,11 +2361,11 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// Can't download any more from this peer
break;
}
- uint32_t nFetchFlags = GetFetchFlags(pfrom, pindex->pprev, chainparams.GetConsensus());
+ uint32_t nFetchFlags = GetFetchFlags(pfrom);
vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash()));
MarkBlockAsInFlight(pfrom->GetId(), pindex->GetBlockHash(), chainparams.GetConsensus(), pindex);
LogPrint(BCLog::NET, "Requesting block %s from peer=%d\n",
- pindex->GetBlockHash().ToString(), pfrom->id);
+ pindex->GetBlockHash().ToString(), pfrom->GetId());
}
if (vGetData.size() > 1) {
LogPrint(BCLog::NET, "Downloading blocks toward %s (%d) via headers direct fetch\n",
@@ -2393,7 +2388,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
vRecv >> *pblock;
- LogPrint(BCLog::NET, "received block %s peer=%d\n", pblock->GetHash().ToString(), pfrom->id);
+ LogPrint(BCLog::NET, "received block %s peer=%d\n", pblock->GetHash().ToString(), pfrom->GetId());
// Process all blocks from whitelisted peers, even if not requested,
// unless we're still syncing with the network.
@@ -2425,14 +2420,14 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// Making nodes which are behind NAT and can only make outgoing connections ignore
// the getaddr message mitigates the attack.
if (!pfrom->fInbound) {
- LogPrint(BCLog::NET, "Ignoring \"getaddr\" from outbound connection. peer=%d\n", pfrom->id);
+ LogPrint(BCLog::NET, "Ignoring \"getaddr\" from outbound connection. peer=%d\n", pfrom->GetId());
return true;
}
// Only send one GetAddr response per connection to reduce resource waste
// and discourage addr stamping of INV announcements.
if (pfrom->fSentAddr) {
- LogPrint(BCLog::NET, "Ignoring repeated \"getaddr\". peer=%d\n", pfrom->id);
+ LogPrint(BCLog::NET, "Ignoring repeated \"getaddr\". peer=%d\n", pfrom->GetId());
return true;
}
pfrom->fSentAddr = true;
@@ -2533,7 +2528,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (!(sProblem.empty())) {
LogPrint(BCLog::NET, "pong peer=%d: %s, %x expected, %x received, %u bytes\n",
- pfrom->id,
+ pfrom->GetId(),
sProblem,
pfrom->nPingNonceSent,
nonce,
@@ -2610,7 +2605,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
LOCK(pfrom->cs_feeFilter);
pfrom->minFeeFilter = newFeeFilter;
}
- LogPrint(BCLog::NET, "received: feefilter of %s from peer=%d\n", CFeeRate(newFeeFilter).ToString(), pfrom->id);
+ LogPrint(BCLog::NET, "received: feefilter of %s from peer=%d\n", CFeeRate(newFeeFilter).ToString(), pfrom->GetId());
}
}
@@ -2621,7 +2616,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
else {
// Ignore unknown commands for extensibility
- LogPrint(BCLog::NET, "Unknown command \"%s\" from peer=%d\n", SanitizeString(strCommand), pfrom->id);
+ LogPrint(BCLog::NET, "Unknown command \"%s\" from peer=%d\n", SanitizeString(strCommand), pfrom->GetId());
}
@@ -2701,7 +2696,7 @@ bool ProcessMessages(CNode* pfrom, CConnman& connman, const std::atomic<bool>& i
msg.SetVersion(pfrom->GetRecvVersion());
// Scan for message start
if (memcmp(msg.hdr.pchMessageStart, chainparams.MessageStart(), CMessageHeader::MESSAGE_START_SIZE) != 0) {
- LogPrintf("PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n", SanitizeString(msg.hdr.GetCommand()), pfrom->id);
+ LogPrintf("PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n", SanitizeString(msg.hdr.GetCommand()), pfrom->GetId());
pfrom->fDisconnect = true;
return false;
}
@@ -2710,7 +2705,7 @@ bool ProcessMessages(CNode* pfrom, CConnman& connman, const std::atomic<bool>& i
CMessageHeader& hdr = msg.hdr;
if (!hdr.IsValid(chainparams.MessageStart()))
{
- LogPrintf("PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->id);
+ LogPrintf("PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->GetId());
return fMoreWork;
}
std::string strCommand = hdr.GetCommand();
@@ -2770,7 +2765,7 @@ bool ProcessMessages(CNode* pfrom, CConnman& connman, const std::atomic<bool>& i
}
if (!fRet) {
- LogPrintf("%s(%s, %u bytes) FAILED peer=%d\n", __func__, SanitizeString(strCommand), nMessageSize, pfrom->id);
+ LogPrintf("%s(%s, %u bytes) FAILED peer=%d\n", __func__, SanitizeString(strCommand), nMessageSize, pfrom->GetId());
}
LOCK(cs_main);
@@ -2899,7 +2894,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
got back an empty response. */
if (pindexStart->pprev)
pindexStart = pindexStart->pprev;
- LogPrint(BCLog::NET, "initial getheaders (%d) to peer=%d (startheight:%d)\n", pindexStart->nHeight, pto->id, pto->nStartingHeight);
+ 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()));
}
}
@@ -2929,7 +2924,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
(!state.fPreferHeaderAndIDs || pto->vBlockHashesToAnnounce.size() > 1)) ||
pto->vBlockHashesToAnnounce.size() > MAX_BLOCKS_TO_ANNOUNCE);
const CBlockIndex *pBestIndex = NULL; // last header queued for delivery
- ProcessBlockAvailability(pto->id); // ensure pindexBestKnownBlock is up-to-date
+ ProcessBlockAvailability(pto->GetId()); // ensure pindexBestKnownBlock is up-to-date
if (!fRevertToInv) {
bool fFoundStartingHeader = false;
@@ -2984,7 +2979,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
// We only send up to 1 block as header-and-ids, as otherwise
// probably means we're doing an initial-ish-sync or they're slow
LogPrint(BCLog::NET, "%s sending header-and-ids %s to peer=%d\n", __func__,
- vHeaders.front().GetHash().ToString(), pto->id);
+ vHeaders.front().GetHash().ToString(), pto->GetId());
int nSendFlags = state.fWantsCmpctWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS;
@@ -3014,10 +3009,10 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
LogPrint(BCLog::NET, "%s: %u headers, range (%s, %s), to peer=%d\n", __func__,
vHeaders.size(),
vHeaders.front().GetHash().ToString(),
- vHeaders.back().GetHash().ToString(), pto->id);
+ vHeaders.back().GetHash().ToString(), pto->GetId());
} else {
LogPrint(BCLog::NET, "%s: sending header %s to peer=%d\n", __func__,
- vHeaders.front().GetHash().ToString(), pto->id);
+ vHeaders.front().GetHash().ToString(), pto->GetId());
}
connman.PushMessage(pto, msgMaker.Make(NetMsgType::HEADERS, vHeaders));
state.pindexBestHeaderSent = pBestIndex;
@@ -3046,7 +3041,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
if (!PeerHasHeader(&state, pindex)) {
pto->PushInventory(CInv(MSG_BLOCK, hashToAnnounce));
LogPrint(BCLog::NET, "%s: sending inv peer=%d hash=%s\n", __func__,
- pto->id, hashToAnnounce.ToString());
+ pto->GetId(), hashToAnnounce.ToString());
}
}
}
@@ -3193,7 +3188,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
// Stalling only triggers when the block download window cannot move. During normal steady state,
// the download window should be much larger than the to-be-downloaded set of blocks, so disconnection
// should only happen during initial block download.
- LogPrintf("Peer=%d is stalling block download, disconnecting\n", pto->id);
+ LogPrintf("Peer=%d is stalling block download, disconnecting\n", pto->GetId());
pto->fDisconnect = true;
return true;
}
@@ -3206,7 +3201,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
int nOtherPeersWithValidatedDownloads = nPeersWithValidatedDownloads - (state.nBlocksInFlightValidHeaders > 0);
if (nNow > state.nDownloadingSince + consensusParams.nPowTargetSpacing * (BLOCK_DOWNLOAD_TIMEOUT_BASE + BLOCK_DOWNLOAD_TIMEOUT_PER_PEER * nOtherPeersWithValidatedDownloads)) {
- LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", queuedBlock.hash.ToString(), pto->id);
+ LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", queuedBlock.hash.ToString(), pto->GetId());
pto->fDisconnect = true;
return true;
}
@@ -3221,11 +3216,11 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
NodeId staller = -1;
FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller, consensusParams);
BOOST_FOREACH(const CBlockIndex *pindex, vToDownload) {
- uint32_t nFetchFlags = GetFetchFlags(pto, pindex->pprev, consensusParams);
+ uint32_t nFetchFlags = GetFetchFlags(pto);
vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash()));
MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), consensusParams, pindex);
LogPrint(BCLog::NET, "Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(),
- pindex->nHeight, pto->id);
+ pindex->nHeight, pto->GetId());
}
if (state.nBlocksInFlight == 0 && staller != -1) {
if (State(staller)->nStallingSince == 0) {
@@ -3243,7 +3238,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
const CInv& inv = (*pto->mapAskFor.begin()).second;
if (!AlreadyHave(inv))
{
- LogPrint(BCLog::NET, "Requesting %s peer=%d\n", inv.ToString(), pto->id);
+ LogPrint(BCLog::NET, "Requesting %s peer=%d\n", inv.ToString(), pto->GetId());
vGetData.push_back(inv);
if (vGetData.size() >= 1000)
{
diff --git a/src/netaddress.cpp b/src/netaddress.cpp
index ab07270f3f..34a7029862 100644
--- a/src/netaddress.cpp
+++ b/src/netaddress.cpp
@@ -179,12 +179,6 @@ bool CNetAddr::IsLocal() const
return false;
}
-bool CNetAddr::IsMulticast() const
-{
- return (IsIPv4() && (GetByte(3) & 0xF0) == 0xE0)
- || (GetByte(15) == 0xFF);
-}
-
bool CNetAddr::IsValid() const
{
// Cleanup 3-byte shifted addresses caused by garbage in size field
diff --git a/src/netaddress.h b/src/netaddress.h
index a85c2b7452..fbc4d1a65f 100644
--- a/src/netaddress.h
+++ b/src/netaddress.h
@@ -65,7 +65,6 @@ class CNetAddr
bool IsLocal() const;
bool IsRoutable() const;
bool IsValid() const;
- bool IsMulticast() const;
enum Network GetNetwork() const;
std::string ToString() const;
std::string ToStringIP() const;
diff --git a/src/amount.cpp b/src/policy/feerate.cpp
index a5f6bc3cd9..a089c02284 100644
--- a/src/amount.cpp
+++ b/src/policy/feerate.cpp
@@ -3,7 +3,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "amount.h"
+#include "feerate.h"
#include "tinyformat.h"
diff --git a/src/policy/feerate.h b/src/policy/feerate.h
new file mode 100644
index 0000000000..e82268b095
--- /dev/null
+++ b/src/policy/feerate.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2015 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_POLICY_FEERATE_H
+#define BITCOIN_POLICY_FEERATE_H
+
+#include "amount.h"
+#include "serialize.h"
+
+#include <string>
+
+extern const std::string CURRENCY_UNIT;
+
+/**
+ * Fee rate in satoshis per kilobyte: CAmount / kB
+ */
+class CFeeRate
+{
+private:
+ CAmount nSatoshisPerK; // unit is satoshis-per-1,000-bytes
+public:
+ /** Fee rate of 0 satoshis per kB */
+ CFeeRate() : nSatoshisPerK(0) { }
+ explicit CFeeRate(const CAmount& _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) { }
+ /** Constructor for a fee rate in satoshis per kB. The size in bytes must not exceed (2^63 - 1)*/
+ CFeeRate(const CAmount& nFeePaid, size_t nBytes);
+ CFeeRate(const CFeeRate& other) { nSatoshisPerK = other.nSatoshisPerK; }
+ /**
+ * Return the fee in satoshis for the given size in bytes.
+ */
+ CAmount GetFee(size_t nBytes) const;
+ /**
+ * Return the fee in satoshis for a size of 1000 bytes
+ */
+ CAmount GetFeePerK() const { return GetFee(1000); }
+ friend bool operator<(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK < b.nSatoshisPerK; }
+ friend bool operator>(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK > b.nSatoshisPerK; }
+ friend bool operator==(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK == b.nSatoshisPerK; }
+ friend bool operator<=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK <= b.nSatoshisPerK; }
+ friend bool operator>=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK >= b.nSatoshisPerK; }
+ CFeeRate& operator+=(const CFeeRate& a) { nSatoshisPerK += a.nSatoshisPerK; return *this; }
+ std::string ToString() const;
+
+ ADD_SERIALIZE_METHODS;
+
+ template <typename Stream, typename Operation>
+ inline void SerializationOp(Stream& s, Operation ser_action) {
+ READWRITE(nSatoshisPerK);
+ }
+};
+
+#endif // BITCOIN_POLICY_FEERATE_H
diff --git a/src/policy/fees.h b/src/policy/fees.h
index 34f07c7270..15876574d2 100644
--- a/src/policy/fees.h
+++ b/src/policy/fees.h
@@ -6,6 +6,7 @@
#define BITCOIN_POLICYESTIMATOR_H
#include "amount.h"
+#include "feerate.h"
#include "uint256.h"
#include "random.h"
#include "sync.h"
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
index 6f8b6c2953..2b19a6714b 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -15,6 +15,43 @@
#include <boost/foreach.hpp>
+CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee)
+{
+ // "Dust" is defined in terms of dustRelayFee,
+ // which has units satoshis-per-kilobyte.
+ // If you'd pay more than 1/3 in fees
+ // to spend something, then we consider it dust.
+ // A typical spendable non-segwit txout is 34 bytes big, and will
+ // need a CTxIn of at least 148 bytes to spend:
+ // so dust is a spendable txout less than
+ // 546*dustRelayFee/1000 (in satoshis).
+ // A typical spendable segwit txout is 31 bytes big, and will
+ // need a CTxIn of at least 67 bytes to spend:
+ // so dust is a spendable txout less than
+ // 294*dustRelayFee/1000 (in satoshis).
+ if (txout.scriptPubKey.IsUnspendable())
+ return 0;
+
+ size_t nSize = GetSerializeSize(txout, SER_DISK, 0);
+ int witnessversion = 0;
+ std::vector<unsigned char> witnessprogram;
+
+ if (txout.scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
+ // sum the sizes of the parts of a transaction input
+ // with 75% segwit discount applied to the script size.
+ nSize += (32 + 4 + 1 + (107 / WITNESS_SCALE_FACTOR) + 4);
+ } else {
+ nSize += (32 + 4 + 1 + 107 + 4); // the 148 mentioned above
+ }
+
+ return 3 * dustRelayFee.GetFee(nSize);
+}
+
+bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFee)
+{
+ return (txout.nValue < GetDustThreshold(txout, dustRelayFee));
+}
+
/**
* Check transaction inputs to mitigate two
* potential denial-of-service attacks:
@@ -106,7 +143,7 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason, const bool witnes
else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) {
reason = "bare-multisig";
return false;
- } else if (txout.IsDust(dustRelayFee)) {
+ } else if (IsDust(txout, ::dustRelayFee)) {
reason = "dust";
return false;
}
diff --git a/src/policy/policy.h b/src/policy/policy.h
index 6df541bc0f..2c2ea9d5b8 100644
--- a/src/policy/policy.h
+++ b/src/policy/policy.h
@@ -7,12 +7,14 @@
#define BITCOIN_POLICY_POLICY_H
#include "consensus/consensus.h"
+#include "feerate.h"
#include "script/interpreter.h"
#include "script/standard.h"
#include <string>
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;
@@ -72,6 +74,10 @@ static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_
static const unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS = LOCKTIME_VERIFY_SEQUENCE |
LOCKTIME_MEDIAN_TIME_PAST;
+CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee);
+
+bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFee);
+
bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType, const bool witnessEnabled = false);
/**
* Check for standard transaction types
diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h
index d413e8b087..00ac0b92b5 100644
--- a/src/primitives/transaction.h
+++ b/src/primitives/transaction.h
@@ -22,8 +22,8 @@ public:
uint256 hash;
uint32_t n;
- COutPoint() { SetNull(); }
- COutPoint(uint256 hashIn, uint32_t nIn) { hash = hashIn; n = nIn; }
+ COutPoint(): n((uint32_t) -1) { }
+ COutPoint(const uint256& hashIn, uint32_t nIn): hash(hashIn), n(nIn) { }
ADD_SERIALIZE_METHODS;
@@ -161,43 +161,6 @@ public:
return (nValue == -1);
}
- CAmount GetDustThreshold(const CFeeRate &minRelayTxFee) const
- {
- // "Dust" is defined in terms of CTransaction::minRelayTxFee,
- // which has units satoshis-per-kilobyte.
- // If you'd pay more than 1/3 in fees
- // to spend something, then we consider it dust.
- // A typical spendable non-segwit txout is 34 bytes big, and will
- // need a CTxIn of at least 148 bytes to spend:
- // so dust is a spendable txout less than
- // 546*minRelayTxFee/1000 (in satoshis).
- // A typical spendable segwit txout is 31 bytes big, and will
- // need a CTxIn of at least 67 bytes to spend:
- // so dust is a spendable txout less than
- // 294*minRelayTxFee/1000 (in satoshis).
- if (scriptPubKey.IsUnspendable())
- return 0;
-
- size_t nSize = GetSerializeSize(*this, SER_DISK, 0);
- int witnessversion = 0;
- std::vector<unsigned char> witnessprogram;
-
- if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
- // sum the sizes of the parts of a transaction input
- // with 75% segwit discount applied to the script size.
- nSize += (32 + 4 + 1 + (107 / WITNESS_SCALE_FACTOR) + 4);
- } else {
- nSize += (32 + 4 + 1 + 107 + 4); // the 148 mentioned above
- }
-
- return 3 * minRelayTxFee.GetFee(nSize);
- }
-
- bool IsDust(const CFeeRate &minRelayTxFee) const
- {
- return (nValue < GetDustThreshold(minRelayTxFee));
- }
-
friend bool operator==(const CTxOut& a, const CTxOut& b)
{
return (a.nValue == b.nValue &&
diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp
index 4b34e73eb7..f8a99506c1 100644
--- a/src/qt/bantablemodel.cpp
+++ b/src/qt/bantablemodel.cpp
@@ -181,7 +181,5 @@ void BanTableModel::sort(int column, Qt::SortOrder order)
bool BanTableModel::shouldShow()
{
- if (priv->size() > 0)
- return true;
- return false;
+ return priv->size() > 0;
}
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index 38ad6e9aab..2a331d4fae 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -434,8 +434,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
{
CTxOut txout(amount, (CScript)std::vector<unsigned char>(24, 0));
txDummy.vout.push_back(txout);
- if (txout.IsDust(dustRelayFee))
- fDust = true;
+ fDust |= IsDust(txout, ::dustRelayFee);
}
}
@@ -527,10 +526,10 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
if (nChange > 0 && nChange < MIN_CHANGE)
{
CTxOut txout(nChange, (CScript)std::vector<unsigned char>(24, 0));
- if (txout.IsDust(dustRelayFee))
+ if (IsDust(txout, ::dustRelayFee))
{
if (CoinControlDialog::fSubtractFeeFromAmount) // dust-change will be raised until no dust
- nChange = txout.GetDustThreshold(dustRelayFee);
+ nChange = GetDustThreshold(txout, ::dustRelayFee);
else
{
nPayFee += nChange;
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 3f3f9b9ccb..bffa81137b 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -251,7 +251,7 @@ bool isDust(const QString& address, const CAmount& amount)
CTxDestination dest = CBitcoinAddress(address.toStdString()).Get();
CScript script = GetScriptForDestination(dest);
CTxOut txOut(amount, script);
- return txOut.IsDust(dustRelayFee);
+ return IsDust(txOut, ::dustRelayFee);
}
QString HtmlEscape(const QString& str, bool fMultiLine)
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index dd75f12076..c31a7a478d 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -219,14 +219,16 @@ void PaymentServer::ipcParseCommandLine(int argc, char* argv[])
if (GUIUtil::parseBitcoinURI(arg, &r) && !r.address.isEmpty())
{
CBitcoinAddress address(r.address.toStdString());
+ auto tempChainParams = CreateChainParams(CBaseChainParams::MAIN);
- if (address.IsValid(Params(CBaseChainParams::MAIN)))
+ if (address.IsValid(*tempChainParams))
{
SelectParams(CBaseChainParams::MAIN);
}
- else if (address.IsValid(Params(CBaseChainParams::TESTNET)))
- {
- SelectParams(CBaseChainParams::TESTNET);
+ else {
+ tempChainParams = CreateChainParams(CBaseChainParams::TESTNET);
+ if (address.IsValid(*tempChainParams))
+ SelectParams(CBaseChainParams::TESTNET);
}
}
}
@@ -580,7 +582,7 @@ bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, Sen
// Extract and check amounts
CTxOut txOut(sendingTo.second, sendingTo.first);
- if (txOut.IsDust(dustRelayFee)) {
+ if (IsDust(txOut, ::dustRelayFee)) {
Q_EMIT message(tr("Payment request error"), tr("Requested payment amount of %1 is too small (considered dust).")
.arg(BitcoinUnits::formatWithUnit(optionsModel->getDisplayUnit(), sendingTo.second)),
CClientUIInterface::MSG_ERROR);
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index bb8aa23de8..7f2f83d9f7 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -829,7 +829,7 @@ void RPCConsole::on_lineEdit_returnPressed()
cmdBeforeBrowsing = QString();
- message(CMD_REQUEST, cmd);
+ message(CMD_REQUEST, QString::fromStdString(strFilteredCmd));
Q_EMIT cmdRequest(cmd);
cmd = QString::fromStdString(strFilteredCmd);
diff --git a/src/random.cpp b/src/random.cpp
index 6187f16290..3b9df3edaa 100644
--- a/src/random.cpp
+++ b/src/random.cpp
@@ -16,6 +16,8 @@
#include <stdlib.h>
#include <limits>
+#include <chrono>
+#include <thread>
#ifndef WIN32
#include <sys/time.h>
@@ -32,6 +34,8 @@
#include <sys/sysctl.h>
#endif
+#include <mutex>
+
#include <openssl/err.h>
#include <openssl/rand.h>
@@ -43,15 +47,22 @@ static void RandFailure()
static inline int64_t GetPerformanceCounter()
{
- int64_t nCounter = 0;
-#ifdef WIN32
- QueryPerformanceCounter((LARGE_INTEGER*)&nCounter);
+ // Read the hardware time stamp counter when available.
+ // See https://en.wikipedia.org/wiki/Time_Stamp_Counter for more information.
+#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
+ return __rdtsc();
+#elif !defined(_MSC_VER) && defined(__i386__)
+ uint64_t r = 0;
+ __asm__ volatile ("rdtsc" : "=A"(r)); // Constrain the r variable to the eax:edx pair.
+ return r;
+#elif !defined(_MSC_VER) && (defined(__x86_64__) || defined(__amd64__))
+ uint64_t r1 = 0, r2 = 0;
+ __asm__ volatile ("rdtsc" : "=a"(r1), "=d"(r2)); // Constrain r1 to rax and r2 to rdx.
+ return (r2 << 32) | r1;
#else
- timeval t;
- gettimeofday(&t, NULL);
- nCounter = (int64_t)(t.tv_sec * 1000000 + t.tv_usec);
+ // Fall back to using C++11 clock (usually microsecond or nanosecond precision)
+ return std::chrono::high_resolution_clock::now().time_since_epoch().count();
#endif
- return nCounter;
}
void RandAddSeed()
@@ -192,6 +203,10 @@ void GetRandBytes(unsigned char* buf, int num)
}
}
+static std::mutex cs_rng_state;
+static unsigned char rng_state[32] = {0};
+static uint64_t rng_counter = 0;
+
void GetStrongRandBytes(unsigned char* out, int num)
{
assert(num <= 32);
@@ -207,8 +222,17 @@ void GetStrongRandBytes(unsigned char* out, int num)
GetOSRand(buf);
hasher.Write(buf, 32);
+ // Combine with and update state
+ {
+ std::unique_lock<std::mutex> lock(cs_rng_state);
+ hasher.Write(rng_state, sizeof(rng_state));
+ hasher.Write((const unsigned char*)&rng_counter, sizeof(rng_counter));
+ ++rng_counter;
+ hasher.Finalize(buf);
+ memcpy(rng_state, buf + 32, 32);
+ }
+
// Produce output
- hasher.Finalize(buf);
memcpy(out, buf, num);
memory_cleanse(buf, 64);
}
@@ -254,6 +278,8 @@ FastRandomContext::FastRandomContext(const uint256& seed) : requires_seed(false)
bool Random_SanityCheck()
{
+ uint64_t start = GetPerformanceCounter();
+
/* This does not measure the quality of randomness, but it does test that
* OSRandom() overwrites all 32 bytes of the output given a maximum
* number of tries.
@@ -280,7 +306,18 @@ bool Random_SanityCheck()
tries += 1;
} while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES);
- return (num_overwritten == NUM_OS_RANDOM_BYTES); /* If this failed, bailed out after too many tries */
+ if (num_overwritten != NUM_OS_RANDOM_BYTES) return false; /* If this failed, bailed out after too many tries */
+
+ // Check that GetPerformanceCounter increases at least during a GetOSRand() call + 1ms sleep.
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
+ uint64_t stop = GetPerformanceCounter();
+ if (stop == start) return false;
+
+ // We called GetPerformanceCounter. Use it as entropy.
+ RAND_add((const unsigned char*)&start, sizeof(start), 1);
+ RAND_add((const unsigned char*)&stop, sizeof(stop), 1);
+
+ return true;
}
FastRandomContext::FastRandomContext(bool fDeterministic) : requires_seed(!fDeterministic), bytebuf_size(0), bitbuf_size(0)
diff --git a/src/rest.cpp b/src/rest.cpp
index 9dcaf269d6..7537ed4502 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -5,6 +5,7 @@
#include "chain.h"
#include "chainparams.h"
+#include "core_io.h"
#include "primitives/block.h"
#include "primitives/transaction.h"
#include "validation.h"
@@ -56,10 +57,6 @@ struct CCoin {
}
};
-/* Defined in rawtransaction.cpp */
-void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry);
-void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
-
static bool RESTERR(HTTPRequest* req, enum HTTPStatusCode status, std::string message)
{
req->WriteHeader("Content-Type", "text/plain");
@@ -383,7 +380,7 @@ static bool rest_tx(HTTPRequest* req, const std::string& strURIPart)
case RF_JSON: {
UniValue objTx(UniValue::VOBJ);
- TxToJSON(*tx, hashBlock, objTx);
+ TxToUniv(*tx, hashBlock, objTx);
std::string strJSON = objTx.write() + "\n";
req->WriteHeader("Content-Type", "application/json");
req->WriteReply(HTTP_OK, strJSON);
@@ -577,7 +574,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
// include the script in a json output
UniValue o(UniValue::VOBJ);
- ScriptPubKeyToJSON(coin.out.scriptPubKey, o, true);
+ ScriptPubKeyToUniv(coin.out.scriptPubKey, o, true);
utxo.push_back(Pair("scriptPubKey", o));
utxos.push_back(utxo);
}
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 01066d0eb2..df424d4a41 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -12,6 +12,8 @@
#include "coins.h"
#include "consensus/validation.h"
#include "validation.h"
+#include "core_io.h"
+#include "policy/feerate.h"
#include "policy/policy.h"
#include "primitives/transaction.h"
#include "rpc/server.h"
@@ -42,7 +44,6 @@ static std::condition_variable cond_blockchange;
static CUpdatedBlock latestblock;
extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry);
-void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
double GetDifficulty(const CBlockIndex* blockindex)
{
@@ -123,7 +124,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx
if(txDetails)
{
UniValue objTx(UniValue::VOBJ);
- TxToJSON(*tx, uint256(), objTx);
+ TxToUniv(*tx, uint256(), objTx);
txs.push_back(objTx);
}
else
@@ -412,6 +413,7 @@ UniValue getrawmempool(const JSONRPCRequest& request)
throw std::runtime_error(
"getrawmempool ( verbose )\n"
"\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n"
+ "\nHint: use getmempoolentry to fetch a specific transaction from the mempool.\n"
"\nArguments:\n"
"1. verbose (boolean, optional, default=false) True for a json object, false for array of transaction ids\n"
"\nResult: (for verbose = false):\n"
@@ -975,7 +977,7 @@ UniValue gettxout(const JSONRPCRequest& request)
ret.push_back(Pair("confirmations", pindex->nHeight - coins.nHeight + 1));
ret.push_back(Pair("value", ValueFromAmount(coins.vout[n].nValue)));
UniValue o(UniValue::VOBJ);
- ScriptPubKeyToJSON(coins.vout[n].scriptPubKey, o, true);
+ ScriptPubKeyToUniv(coins.vout[n].scriptPubKey, o, true);
ret.push_back(Pair("scriptPubKey", o));
ret.push_back(Pair("version", coins.nVersion));
ret.push_back(Pair("coinbase", coins.fCoinBase));
@@ -1415,10 +1417,76 @@ UniValue reconsiderblock(const JSONRPCRequest& request)
return NullUniValue;
}
+UniValue getchaintxstats(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.size() > 2)
+ throw std::runtime_error(
+ "getchaintxstats ( nblocks blockhash )\n"
+ "\nCompute statistics about the total number and rate of transactions in the chain.\n"
+ "\nArguments:\n"
+ "1. nblocks (numeric, optional) Size of the window in number of blocks (default: one month).\n"
+ "2. \"blockhash\" (string, optional) The hash of the block that ends the window.\n"
+ "\nResult:\n"
+ "{\n"
+ " \"time\": xxxxx, (numeric) The timestamp for the statistics in UNIX format.\n"
+ " \"txcount\": xxxxx, (numeric) The total number of transactions in the chain up to that point.\n"
+ " \"txrate\": x.xx, (numeric) The average rate of transactions per second in the window.\n"
+ "}\n"
+ "\nExamples:\n"
+ + HelpExampleCli("getchaintxstats", "")
+ + HelpExampleRpc("getchaintxstats", "2016")
+ );
+
+ const CBlockIndex* pindex;
+ int blockcount = 30 * 24 * 60 * 60 / Params().GetConsensus().nPowTargetSpacing; // By default: 1 month
+
+ if (request.params.size() > 0 && !request.params[0].isNull()) {
+ blockcount = request.params[0].get_int();
+ }
+
+ bool havehash = request.params.size() > 1 && !request.params[1].isNull();
+ uint256 hash;
+ if (havehash) {
+ hash = uint256S(request.params[1].get_str());
+ }
+
+ {
+ LOCK(cs_main);
+ if (havehash) {
+ auto it = mapBlockIndex.find(hash);
+ if (it == mapBlockIndex.end()) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
+ }
+ pindex = it->second;
+ if (!chainActive.Contains(pindex)) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Block is not in main chain");
+ }
+ } else {
+ pindex = chainActive.Tip();
+ }
+ }
+
+ if (blockcount < 1 || blockcount >= pindex->nHeight) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block count: should be between 1 and the block's height");
+ }
+
+ const CBlockIndex* pindexPast = pindex->GetAncestor(pindex->nHeight - blockcount);
+ int nTimeDiff = pindex->GetMedianTimePast() - pindexPast->GetMedianTimePast();
+ int nTxDiff = pindex->nChainTx - pindexPast->nChainTx;
+
+ UniValue ret(UniValue::VOBJ);
+ ret.push_back(Pair("time", (int64_t)pindex->nTime));
+ ret.push_back(Pair("txcount", (int64_t)pindex->nChainTx));
+ ret.push_back(Pair("txrate", ((double)nTxDiff) / nTimeDiff));
+
+ return ret;
+}
+
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","verbose"} },
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index 941bdd9379..8454e99d3c 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -79,6 +79,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "listunspent", 2, "addresses" },
{ "getblock", 1, "verbose" },
{ "getblockheader", 1, "verbose" },
+ { "getchaintxstats", 0, "nblocks" },
{ "gettransaction", 1, "include_watchonly" },
{ "getrawtransaction", 1, "verbose" },
{ "createrawtransaction", 0, "inputs" },
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 717e9d75f3..3947fb3f7d 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -34,77 +34,15 @@
#include <univalue.h>
-void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex)
-{
- txnouttype type;
- std::vector<CTxDestination> addresses;
- int nRequired;
-
- out.push_back(Pair("asm", ScriptToAsmStr(scriptPubKey)));
- if (fIncludeHex)
- out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
-
- if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired)) {
- out.push_back(Pair("type", GetTxnOutputType(type)));
- return;
- }
-
- out.push_back(Pair("reqSigs", nRequired));
- out.push_back(Pair("type", GetTxnOutputType(type)));
-
- UniValue a(UniValue::VARR);
- BOOST_FOREACH(const CTxDestination& addr, addresses)
- a.push_back(CBitcoinAddress(addr).ToString());
- out.push_back(Pair("addresses", a));
-}
void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
{
- entry.push_back(Pair("txid", tx.GetHash().GetHex()));
- entry.push_back(Pair("hash", tx.GetWitnessHash().GetHex()));
- entry.push_back(Pair("size", (int)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION)));
- entry.push_back(Pair("vsize", (int)::GetVirtualTransactionSize(tx)));
- entry.push_back(Pair("version", tx.nVersion));
- entry.push_back(Pair("locktime", (int64_t)tx.nLockTime));
-
- UniValue vin(UniValue::VARR);
- for (unsigned int i = 0; i < tx.vin.size(); i++) {
- const CTxIn& txin = tx.vin[i];
- UniValue in(UniValue::VOBJ);
- if (tx.IsCoinBase())
- in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
- else {
- in.push_back(Pair("txid", txin.prevout.hash.GetHex()));
- in.push_back(Pair("vout", (int64_t)txin.prevout.n));
- UniValue o(UniValue::VOBJ);
- o.push_back(Pair("asm", ScriptToAsmStr(txin.scriptSig, true)));
- o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
- in.push_back(Pair("scriptSig", o));
- }
- if (tx.HasWitness()) {
- UniValue txinwitness(UniValue::VARR);
- for (unsigned int j = 0; j < tx.vin[i].scriptWitness.stack.size(); j++) {
- std::vector<unsigned char> item = tx.vin[i].scriptWitness.stack[j];
- txinwitness.push_back(HexStr(item.begin(), item.end()));
- }
- in.push_back(Pair("txinwitness", txinwitness));
- }
- in.push_back(Pair("sequence", (int64_t)txin.nSequence));
- vin.push_back(in);
- }
- entry.push_back(Pair("vin", vin));
- UniValue vout(UniValue::VARR);
- for (unsigned int i = 0; i < tx.vout.size(); i++) {
- const CTxOut& txout = tx.vout[i];
- UniValue out(UniValue::VOBJ);
- out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
- out.push_back(Pair("n", (int64_t)i));
- UniValue o(UniValue::VOBJ);
- ScriptPubKeyToJSON(txout.scriptPubKey, o, true);
- out.push_back(Pair("scriptPubKey", o));
- vout.push_back(out);
- }
- entry.push_back(Pair("vout", vout));
+ // Call into TxToUniv() in bitcoin-common to decode the transaction hex.
+ //
+ // Blockchain contextual information (confirmations and blocktime) is not
+ // available to code in bitcoin-common, so we query them here and push the
+ // data into the returned UniValue.
+ TxToUniv(tx, uint256(), entry);
if (!hashBlock.IsNull()) {
entry.push_back(Pair("blockhash", hashBlock.GetHex()));
@@ -525,7 +463,7 @@ UniValue decoderawtransaction(const JSONRPCRequest& request)
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
UniValue result(UniValue::VOBJ);
- TxToJSON(CTransaction(std::move(mtx)), uint256(), result);
+ TxToUniv(CTransaction(std::move(mtx)), uint256(), result);
return result;
}
@@ -565,7 +503,7 @@ UniValue decodescript(const JSONRPCRequest& request)
} else {
// Empty scripts are valid
}
- ScriptPubKeyToJSON(script, r, false);
+ ScriptPubKeyToUniv(script, r, false);
UniValue type;
type = find_value(r, "type");
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index 8ecf0bbdac..f4e5313a78 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -247,10 +247,10 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
{
static const CScriptNum bnZero(0);
static const CScriptNum bnOne(1);
- static const CScriptNum bnFalse(0);
- static const CScriptNum bnTrue(1);
+ // static const CScriptNum bnFalse(0);
+ // static const CScriptNum bnTrue(1);
static const valtype vchFalse(0);
- static const valtype vchZero(0);
+ // static const valtype vchZero(0);
static const valtype vchTrue(1, 1);
CScript::const_iterator pc = script.begin();
diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp
index 39fa381dd0..3812490ec0 100644
--- a/src/test/addrman_tests.cpp
+++ b/src/test/addrman_tests.cpp
@@ -84,36 +84,43 @@ BOOST_AUTO_TEST_CASE(addrman_simple)
CNetAddr source = ResolveIP("252.2.2.2");
- // Test 1: Does Addrman respond correctly when empty.
- BOOST_CHECK(addrman.size() == 0);
+ // Test: Does Addrman respond correctly when empty.
+ BOOST_CHECK_EQUAL(addrman.size(), 0);
CAddrInfo addr_null = addrman.Select();
- BOOST_CHECK(addr_null.ToString() == "[::]:0");
+ BOOST_CHECK_EQUAL(addr_null.ToString(), "[::]:0");
- // Test 2: Does Addrman::Add work as expected.
+ // Test: Does Addrman::Add work as expected.
CService addr1 = ResolveService("250.1.1.1", 8333);
- addrman.Add(CAddress(addr1, NODE_NONE), source);
- BOOST_CHECK(addrman.size() == 1);
+ BOOST_CHECK(addrman.Add(CAddress(addr1, NODE_NONE), source));
+ BOOST_CHECK_EQUAL(addrman.size(), 1);
CAddrInfo addr_ret1 = addrman.Select();
- BOOST_CHECK(addr_ret1.ToString() == "250.1.1.1:8333");
+ BOOST_CHECK_EQUAL(addr_ret1.ToString(), "250.1.1.1:8333");
- // Test 3: Does IP address deduplication work correctly.
+ // Test: Does IP address deduplication work correctly.
// Expected dup IP should not be added.
CService addr1_dup = ResolveService("250.1.1.1", 8333);
- addrman.Add(CAddress(addr1_dup, NODE_NONE), source);
- BOOST_CHECK(addrman.size() == 1);
+ BOOST_CHECK(!addrman.Add(CAddress(addr1_dup, NODE_NONE), source));
+ BOOST_CHECK_EQUAL(addrman.size(), 1);
- // Test 5: New table has one addr and we add a diff addr we should
+ // Test: New table has one addr and we add a diff addr we should
// have two addrs.
CService addr2 = ResolveService("250.1.1.2", 8333);
- addrman.Add(CAddress(addr2, NODE_NONE), source);
- BOOST_CHECK(addrman.size() == 2);
+ BOOST_CHECK(addrman.Add(CAddress(addr2, NODE_NONE), source));
+ BOOST_CHECK_EQUAL(addrman.size(), 2);
- // Test 6: AddrMan::Clear() should empty the new table.
+ // Test: AddrMan::Clear() should empty the new table.
addrman.Clear();
- BOOST_CHECK(addrman.size() == 0);
+ BOOST_CHECK_EQUAL(addrman.size(), 0);
CAddrInfo addr_null2 = addrman.Select();
- BOOST_CHECK(addr_null2.ToString() == "[::]:0");
+ BOOST_CHECK_EQUAL(addr_null2.ToString(), "[::]:0");
+
+ // Test: AddrMan::Add multiple addresses works as expected
+ std::vector<CAddress> vAddr;
+ vAddr.push_back(CAddress(ResolveService("250.1.1.3", 8333), NODE_NONE));
+ vAddr.push_back(CAddress(ResolveService("250.1.1.4", 8333), NODE_NONE));
+ BOOST_CHECK(addrman.Add(vAddr, source));
+ BOOST_CHECK_EQUAL(addrman.size(), 2);
}
BOOST_AUTO_TEST_CASE(addrman_ports)
@@ -125,26 +132,26 @@ BOOST_AUTO_TEST_CASE(addrman_ports)
CNetAddr source = ResolveIP("252.2.2.2");
- BOOST_CHECK(addrman.size() == 0);
+ BOOST_CHECK_EQUAL(addrman.size(), 0);
// Test 7; Addr with same IP but diff port does not replace existing addr.
CService addr1 = ResolveService("250.1.1.1", 8333);
addrman.Add(CAddress(addr1, NODE_NONE), source);
- BOOST_CHECK(addrman.size() == 1);
+ BOOST_CHECK_EQUAL(addrman.size(), 1);
CService addr1_port = ResolveService("250.1.1.1", 8334);
addrman.Add(CAddress(addr1_port, NODE_NONE), source);
- BOOST_CHECK(addrman.size() == 1);
+ BOOST_CHECK_EQUAL(addrman.size(), 1);
CAddrInfo addr_ret2 = addrman.Select();
- BOOST_CHECK(addr_ret2.ToString() == "250.1.1.1:8333");
+ BOOST_CHECK_EQUAL(addr_ret2.ToString(), "250.1.1.1:8333");
- // Test 8: Add same IP but diff port to tried table, it doesn't get added.
+ // Test: Add same IP but diff port to tried table, it doesn't get added.
// Perhaps this is not ideal behavior but it is the current behavior.
addrman.Good(CAddress(addr1_port, NODE_NONE));
- BOOST_CHECK(addrman.size() == 1);
+ BOOST_CHECK_EQUAL(addrman.size(), 1);
bool newOnly = true;
CAddrInfo addr_ret3 = addrman.Select(newOnly);
- BOOST_CHECK(addr_ret3.ToString() == "250.1.1.1:8333");
+ BOOST_CHECK_EQUAL(addr_ret3.ToString(), "250.1.1.1:8333");
}
@@ -157,25 +164,25 @@ BOOST_AUTO_TEST_CASE(addrman_select)
CNetAddr source = ResolveIP("252.2.2.2");
- // Test 9: Select from new with 1 addr in new.
+ // Test: Select from new with 1 addr in new.
CService addr1 = ResolveService("250.1.1.1", 8333);
addrman.Add(CAddress(addr1, NODE_NONE), source);
- BOOST_CHECK(addrman.size() == 1);
+ BOOST_CHECK_EQUAL(addrman.size(), 1);
bool newOnly = true;
CAddrInfo addr_ret1 = addrman.Select(newOnly);
- BOOST_CHECK(addr_ret1.ToString() == "250.1.1.1:8333");
+ BOOST_CHECK_EQUAL(addr_ret1.ToString(), "250.1.1.1:8333");
- // Test 10: move addr to tried, select from new expected nothing returned.
+ // Test: move addr to tried, select from new expected nothing returned.
addrman.Good(CAddress(addr1, NODE_NONE));
- BOOST_CHECK(addrman.size() == 1);
+ BOOST_CHECK_EQUAL(addrman.size(), 1);
CAddrInfo addr_ret2 = addrman.Select(newOnly);
- BOOST_CHECK(addr_ret2.ToString() == "[::]:0");
+ BOOST_CHECK_EQUAL(addr_ret2.ToString(), "[::]:0");
CAddrInfo addr_ret3 = addrman.Select();
- BOOST_CHECK(addr_ret3.ToString() == "250.1.1.1:8333");
+ BOOST_CHECK_EQUAL(addr_ret3.ToString(), "250.1.1.1:8333");
- BOOST_CHECK(addrman.size() == 1);
+ BOOST_CHECK_EQUAL(addrman.size(), 1);
// Add three addresses to new table.
@@ -199,10 +206,10 @@ BOOST_AUTO_TEST_CASE(addrman_select)
addrman.Add(CAddress(addr7, NODE_NONE), ResolveService("250.1.1.3", 8333));
addrman.Good(CAddress(addr7, NODE_NONE));
- // Test 11: 6 addrs + 1 addr from last test = 7.
- BOOST_CHECK(addrman.size() == 7);
+ // Test: 6 addrs + 1 addr from last test = 7.
+ BOOST_CHECK_EQUAL(addrman.size(), 7);
- // Test 12: Select pulls from new and tried regardless of port number.
+ // Test: Select pulls from new and tried regardless of port number.
std::set<uint16_t> ports;
for (int i = 0; i < 20; ++i) {
ports.insert(addrman.Select().GetPort());
@@ -219,24 +226,24 @@ BOOST_AUTO_TEST_CASE(addrman_new_collisions)
CNetAddr source = ResolveIP("252.2.2.2");
- BOOST_CHECK(addrman.size() == 0);
+ BOOST_CHECK_EQUAL(addrman.size(), 0);
for (unsigned int i = 1; i < 18; i++) {
CService addr = ResolveService("250.1.1." + boost::to_string(i));
addrman.Add(CAddress(addr, NODE_NONE), source);
- //Test 13: No collision in new table yet.
- BOOST_CHECK(addrman.size() == i);
+ //Test: No collision in new table yet.
+ BOOST_CHECK_EQUAL(addrman.size(), i);
}
- //Test 14: new table collision!
+ //Test: new table collision!
CService addr1 = ResolveService("250.1.1.18");
addrman.Add(CAddress(addr1, NODE_NONE), source);
- BOOST_CHECK(addrman.size() == 17);
+ BOOST_CHECK_EQUAL(addrman.size(), 17);
CService addr2 = ResolveService("250.1.1.19");
addrman.Add(CAddress(addr2, NODE_NONE), source);
- BOOST_CHECK(addrman.size() == 18);
+ BOOST_CHECK_EQUAL(addrman.size(), 18);
}
BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
@@ -248,25 +255,25 @@ BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
CNetAddr source = ResolveIP("252.2.2.2");
- BOOST_CHECK(addrman.size() == 0);
+ BOOST_CHECK_EQUAL(addrman.size(), 0);
for (unsigned int i = 1; i < 80; i++) {
CService addr = ResolveService("250.1.1." + boost::to_string(i));
addrman.Add(CAddress(addr, NODE_NONE), source);
addrman.Good(CAddress(addr, NODE_NONE));
- //Test 15: No collision in tried table yet.
+ //Test: No collision in tried table yet.
BOOST_CHECK_EQUAL(addrman.size(), i);
}
- //Test 16: tried table collision!
+ //Test: tried table collision!
CService addr1 = ResolveService("250.1.1.80");
addrman.Add(CAddress(addr1, NODE_NONE), source);
- BOOST_CHECK(addrman.size() == 79);
+ BOOST_CHECK_EQUAL(addrman.size(), 79);
CService addr2 = ResolveService("250.1.1.81");
addrman.Add(CAddress(addr2, NODE_NONE), source);
- BOOST_CHECK(addrman.size() == 80);
+ BOOST_CHECK_EQUAL(addrman.size(), 80);
}
BOOST_AUTO_TEST_CASE(addrman_find)
@@ -276,7 +283,7 @@ BOOST_AUTO_TEST_CASE(addrman_find)
// Set addrman addr placement to be deterministic.
addrman.MakeDeterministic();
- BOOST_CHECK(addrman.size() == 0);
+ BOOST_CHECK_EQUAL(addrman.size(), 0);
CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
CAddress addr2 = CAddress(ResolveService("250.1.2.1", 9999), NODE_NONE);
@@ -289,23 +296,20 @@ BOOST_AUTO_TEST_CASE(addrman_find)
addrman.Add(addr2, source2);
addrman.Add(addr3, source1);
- // Test 17: ensure Find returns an IP matching what we searched on.
+ // Test: ensure Find returns an IP matching what we searched on.
CAddrInfo* info1 = addrman.Find(addr1);
- BOOST_CHECK(info1);
- if (info1)
- BOOST_CHECK(info1->ToString() == "250.1.2.1:8333");
+ BOOST_REQUIRE(info1);
+ BOOST_CHECK_EQUAL(info1->ToString(), "250.1.2.1:8333");
// Test 18; Find does not discriminate by port number.
CAddrInfo* info2 = addrman.Find(addr2);
- BOOST_CHECK(info2);
- if (info2 && info1)
- BOOST_CHECK(info2->ToString() == info1->ToString());
+ BOOST_REQUIRE(info2);
+ BOOST_CHECK_EQUAL(info2->ToString(), info1->ToString());
- // Test 19: Find returns another IP matching what we searched on.
+ // Test: Find returns another IP matching what we searched on.
CAddrInfo* info3 = addrman.Find(addr3);
- BOOST_CHECK(info3);
- if (info3)
- BOOST_CHECK(info3->ToString() == "251.255.2.1:8333");
+ BOOST_REQUIRE(info3);
+ BOOST_CHECK_EQUAL(info3->ToString(), "251.255.2.1:8333");
}
BOOST_AUTO_TEST_CASE(addrman_create)
@@ -315,7 +319,7 @@ BOOST_AUTO_TEST_CASE(addrman_create)
// Set addrman addr placement to be deterministic.
addrman.MakeDeterministic();
- BOOST_CHECK(addrman.size() == 0);
+ BOOST_CHECK_EQUAL(addrman.size(), 0);
CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
CNetAddr source1 = ResolveIP("250.1.2.1");
@@ -323,11 +327,11 @@ BOOST_AUTO_TEST_CASE(addrman_create)
int nId;
CAddrInfo* pinfo = addrman.Create(addr1, source1, &nId);
- // Test 20: The result should be the same as the input addr.
- BOOST_CHECK(pinfo->ToString() == "250.1.2.1:8333");
+ // Test: The result should be the same as the input addr.
+ BOOST_CHECK_EQUAL(pinfo->ToString(), "250.1.2.1:8333");
CAddrInfo* info2 = addrman.Find(addr1);
- BOOST_CHECK(info2->ToString() == "250.1.2.1:8333");
+ BOOST_CHECK_EQUAL(info2->ToString(), "250.1.2.1:8333");
}
@@ -338,7 +342,7 @@ BOOST_AUTO_TEST_CASE(addrman_delete)
// Set addrman addr placement to be deterministic.
addrman.MakeDeterministic();
- BOOST_CHECK(addrman.size() == 0);
+ BOOST_CHECK_EQUAL(addrman.size(), 0);
CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
CNetAddr source1 = ResolveIP("250.1.2.1");
@@ -346,10 +350,10 @@ BOOST_AUTO_TEST_CASE(addrman_delete)
int nId;
addrman.Create(addr1, source1, &nId);
- // Test 21: Delete should actually delete the addr.
- BOOST_CHECK(addrman.size() == 1);
+ // Test: Delete should actually delete the addr.
+ BOOST_CHECK_EQUAL(addrman.size(), 1);
addrman.Delete(nId);
- BOOST_CHECK(addrman.size() == 0);
+ BOOST_CHECK_EQUAL(addrman.size(), 0);
CAddrInfo* info2 = addrman.Find(addr1);
BOOST_CHECK(info2 == NULL);
}
@@ -361,11 +365,11 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr)
// Set addrman addr placement to be deterministic.
addrman.MakeDeterministic();
- // Test 22: Sanity check, GetAddr should never return anything if addrman
+ // Test: Sanity check, GetAddr should never return anything if addrman
// is empty.
- BOOST_CHECK(addrman.size() == 0);
+ BOOST_CHECK_EQUAL(addrman.size(), 0);
std::vector<CAddress> vAddr1 = addrman.GetAddr();
- BOOST_CHECK(vAddr1.size() == 0);
+ BOOST_CHECK_EQUAL(vAddr1.size(), 0);
CAddress addr1 = CAddress(ResolveService("250.250.2.1", 8333), NODE_NONE);
addr1.nTime = GetAdjustedTime(); // Set time so isTerrible = false
@@ -380,7 +384,7 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr)
CNetAddr source1 = ResolveIP("250.1.2.1");
CNetAddr source2 = ResolveIP("250.2.3.3");
- // Test 23: Ensure GetAddr works with new addresses.
+ // Test: Ensure GetAddr works with new addresses.
addrman.Add(addr1, source1);
addrman.Add(addr2, source2);
addrman.Add(addr3, source1);
@@ -388,21 +392,20 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr)
addrman.Add(addr5, source1);
// GetAddr returns 23% of addresses, 23% of 5 is 1 rounded down.
- BOOST_CHECK(addrman.GetAddr().size() == 1);
+ BOOST_CHECK_EQUAL(addrman.GetAddr().size(), 1);
- // Test 24: Ensure GetAddr works with new and tried addresses.
+ // Test: Ensure GetAddr works with new and tried addresses.
addrman.Good(CAddress(addr1, NODE_NONE));
addrman.Good(CAddress(addr2, NODE_NONE));
- BOOST_CHECK(addrman.GetAddr().size() == 1);
+ BOOST_CHECK_EQUAL(addrman.GetAddr().size(), 1);
- // Test 25: Ensure GetAddr still returns 23% when addrman has many addrs.
+ // Test: Ensure GetAddr still returns 23% when addrman has many addrs.
for (unsigned int i = 1; i < (8 * 256); i++) {
int octet1 = i % 256;
- int octet2 = (i / 256) % 256;
- int octet3 = (i / (256 * 2)) % 256;
- std::string strAddr = boost::to_string(octet1) + "." + boost::to_string(octet2) + "." + boost::to_string(octet3) + ".23";
+ int octet2 = i >> 8 % 256;
+ std::string strAddr = boost::to_string(octet1) + "." + boost::to_string(octet2) + ".1.23";
CAddress addr = CAddress(ResolveService(strAddr), NODE_NONE);
-
+
// Ensure that for all addrs in addrman, isTerrible == false.
addr.nTime = GetAdjustedTime();
addrman.Add(addr, ResolveIP(strAddr));
@@ -412,10 +415,10 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr)
std::vector<CAddress> vAddr = addrman.GetAddr();
size_t percent23 = (addrman.size() * 23) / 100;
- BOOST_CHECK(vAddr.size() == percent23);
- BOOST_CHECK(vAddr.size() == 461);
+ BOOST_CHECK_EQUAL(vAddr.size(), percent23);
+ BOOST_CHECK_EQUAL(vAddr.size(), 461);
// (Addrman.size() < number of addresses added) due to address collisions.
- BOOST_CHECK(addrman.size() == 2007);
+ BOOST_CHECK_EQUAL(addrman.size(), 2006);
}
@@ -438,13 +441,13 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket)
uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash();
- BOOST_CHECK(info1.GetTriedBucket(nKey1) == 40);
+ BOOST_CHECK_EQUAL(info1.GetTriedBucket(nKey1), 40);
- // Test 26: Make sure key actually randomizes bucket placement. A fail on
+ // Test: Make sure key actually randomizes bucket placement. A fail on
// this test could be a security issue.
BOOST_CHECK(info1.GetTriedBucket(nKey1) != info1.GetTriedBucket(nKey2));
- // Test 27: Two addresses with same IP but different ports can map to
+ // Test: Two addresses with same IP but different ports can map to
// different buckets because they have different keys.
CAddrInfo info2 = CAddrInfo(addr2, source1);
@@ -459,9 +462,9 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket)
int bucket = infoi.GetTriedBucket(nKey1);
buckets.insert(bucket);
}
- // Test 28: IP addresses in the same group (\16 prefix for IPv4) should
+ // Test: IP addresses in the same group (\16 prefix for IPv4) should
// never get more than 8 buckets
- BOOST_CHECK(buckets.size() == 8);
+ BOOST_CHECK_EQUAL(buckets.size(), 8);
buckets.clear();
for (int j = 0; j < 255; j++) {
@@ -471,9 +474,9 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket)
int bucket = infoj.GetTriedBucket(nKey1);
buckets.insert(bucket);
}
- // Test 29: IP addresses in the different groups should map to more than
+ // Test: IP addresses in the different groups should map to more than
// 8 buckets.
- BOOST_CHECK(buckets.size() == 160);
+ BOOST_CHECK_EQUAL(buckets.size(), 160);
}
BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
@@ -493,16 +496,18 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
uint256 nKey1 = (uint256)(CHashWriter(SER_GETHASH, 0) << 1).GetHash();
uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash();
- BOOST_CHECK(info1.GetNewBucket(nKey1) == 786);
+ // Test: Make sure the buckets are what we expect
+ BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1), 786);
+ BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, source1), 786);
- // Test 30: Make sure key actually randomizes bucket placement. A fail on
+ // Test: Make sure key actually randomizes bucket placement. A fail on
// this test could be a security issue.
BOOST_CHECK(info1.GetNewBucket(nKey1) != info1.GetNewBucket(nKey2));
- // Test 31: Ports should not effect bucket placement in the addr
+ // Test: Ports should not effect bucket placement in the addr
CAddrInfo info2 = CAddrInfo(addr2, source1);
BOOST_CHECK(info1.GetKey() != info2.GetKey());
- BOOST_CHECK(info1.GetNewBucket(nKey1) == info2.GetNewBucket(nKey1));
+ BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1), info2.GetNewBucket(nKey1));
std::set<int> buckets;
for (int i = 0; i < 255; i++) {
@@ -512,9 +517,9 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
int bucket = infoi.GetNewBucket(nKey1);
buckets.insert(bucket);
}
- // Test 32: IP addresses in the same group (\16 prefix for IPv4) should
+ // Test: IP addresses in the same group (\16 prefix for IPv4) should
// always map to the same bucket.
- BOOST_CHECK(buckets.size() == 1);
+ BOOST_CHECK_EQUAL(buckets.size(), 1);
buckets.clear();
for (int j = 0; j < 4 * 255; j++) {
@@ -525,7 +530,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
int bucket = infoj.GetNewBucket(nKey1);
buckets.insert(bucket);
}
- // Test 33: IP addresses in the same source groups should map to no more
+ // Test: IP addresses in the same source groups should map to no more
// than 64 buckets.
BOOST_CHECK(buckets.size() <= 64);
@@ -537,7 +542,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
int bucket = infoj.GetNewBucket(nKey1);
buckets.insert(bucket);
}
- // Test 34: IP addresses in the different source groups should map to more
+ // Test: IP addresses in the different source groups should map to more
// than 64 buckets.
BOOST_CHECK(buckets.size() > 64);
}
diff --git a/src/test/amount_tests.cpp b/src/test/amount_tests.cpp
index fd6f88b366..952cf901f0 100644
--- a/src/test/amount_tests.cpp
+++ b/src/test/amount_tests.cpp
@@ -3,15 +3,23 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "amount.h"
+#include "policy/feerate.h"
#include "test/test_bitcoin.h"
#include <boost/test/unit_test.hpp>
BOOST_FIXTURE_TEST_SUITE(amount_tests, BasicTestingSetup)
+BOOST_AUTO_TEST_CASE(MoneyRangeTest)
+{
+ BOOST_CHECK_EQUAL(MoneyRange(CAmount(-1)), false);
+ BOOST_CHECK_EQUAL(MoneyRange(MAX_MONEY + CAmount(1)), false);
+ BOOST_CHECK_EQUAL(MoneyRange(CAmount(1)), true);
+}
+
BOOST_AUTO_TEST_CASE(GetFeeTest)
{
- CFeeRate feeRate;
+ CFeeRate feeRate, altFeeRate;
feeRate = CFeeRate(0);
// Must always return 0
@@ -53,6 +61,11 @@ BOOST_AUTO_TEST_CASE(GetFeeTest)
BOOST_CHECK_EQUAL(feeRate.GetFee(8), -1); // Special case: returns -1 instead of 0
BOOST_CHECK_EQUAL(feeRate.GetFee(9), -1);
+ // check alternate constructor
+ feeRate = CFeeRate(1000);
+ altFeeRate = CFeeRate(feeRate);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(100), altFeeRate.GetFee(100));
+
// Check full constructor
// default value
BOOST_CHECK(CFeeRate(CAmount(-1), 1000) == CFeeRate(-1));
@@ -68,4 +81,28 @@ BOOST_AUTO_TEST_CASE(GetFeeTest)
CFeeRate(MAX_MONEY, std::numeric_limits<size_t>::max() >> 1).GetFeePerK();
}
+BOOST_AUTO_TEST_CASE(BinaryOperatorTest)
+{
+ CFeeRate a, b;
+ a = CFeeRate(1);
+ b = CFeeRate(2);
+ BOOST_CHECK(a < b);
+ BOOST_CHECK(b > a);
+ BOOST_CHECK(a == a);
+ BOOST_CHECK(a <= b);
+ BOOST_CHECK(a <= a);
+ BOOST_CHECK(b >= a);
+ BOOST_CHECK(b >= b);
+ // a should be 0.00000002 BTC/kB now
+ a += a;
+ BOOST_CHECK(a == b);
+}
+
+BOOST_AUTO_TEST_CASE(ToStringTest)
+{
+ CFeeRate feeRate;
+ feeRate = CFeeRate(1);
+ BOOST_CHECK_EQUAL(feeRate.ToString(), "0.00000001 BTC/kB");
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/main_tests.cpp b/src/test/main_tests.cpp
index d52104b4cc..656aec606b 100644
--- a/src/test/main_tests.cpp
+++ b/src/test/main_tests.cpp
@@ -39,17 +39,18 @@ static void TestBlockSubsidyHalvings(int nSubsidyHalvingInterval)
BOOST_AUTO_TEST_CASE(block_subsidy_test)
{
- TestBlockSubsidyHalvings(Params(CBaseChainParams::MAIN).GetConsensus()); // As in main
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
+ TestBlockSubsidyHalvings(chainParams->GetConsensus()); // As in main
TestBlockSubsidyHalvings(150); // As in regtest
TestBlockSubsidyHalvings(1000); // Just another interval
}
BOOST_AUTO_TEST_CASE(subsidy_limit_test)
{
- const Consensus::Params& consensusParams = Params(CBaseChainParams::MAIN).GetConsensus();
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
CAmount nSum = 0;
for (int nHeight = 0; nHeight < 14000000; nHeight += 1000) {
- CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams);
+ CAmount nSubsidy = GetBlockSubsidy(nHeight, chainParams->GetConsensus());
BOOST_CHECK(nSubsidy <= 50 * COIN);
nSum += nSubsidy * 1000;
BOOST_CHECK(MoneyRange(nSum));
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index 41f42c7b88..fadff612d4 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -194,7 +194,8 @@ void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey,
BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
{
// Note that by default, these tests run with size accounting enabled.
- const CChainParams& chainparams = Params(CBaseChainParams::MAIN);
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
+ const CChainParams& chainparams = *chainParams;
CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
std::unique_ptr<CBlockTemplate> pblocktemplate;
CMutableTransaction tx,tx2;
diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp
index 4ca6f1caf0..3b79f8000d 100644
--- a/src/test/pow_tests.cpp
+++ b/src/test/pow_tests.cpp
@@ -16,69 +16,59 @@ BOOST_FIXTURE_TEST_SUITE(pow_tests, BasicTestingSetup)
/* Test calculation of next difficulty target with no constraints applying */
BOOST_AUTO_TEST_CASE(get_next_work)
{
- SelectParams(CBaseChainParams::MAIN);
- const Consensus::Params& params = Params().GetConsensus();
-
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
int64_t nLastRetargetTime = 1261130161; // Block #30240
CBlockIndex pindexLast;
pindexLast.nHeight = 32255;
pindexLast.nTime = 1262152739; // Block #32255
pindexLast.nBits = 0x1d00ffff;
- BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, params), 0x1d00d86a);
+ BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1d00d86a);
}
/* Test the constraint on the upper bound for next work */
BOOST_AUTO_TEST_CASE(get_next_work_pow_limit)
{
- SelectParams(CBaseChainParams::MAIN);
- const Consensus::Params& params = Params().GetConsensus();
-
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
int64_t nLastRetargetTime = 1231006505; // Block #0
CBlockIndex pindexLast;
pindexLast.nHeight = 2015;
pindexLast.nTime = 1233061996; // Block #2015
pindexLast.nBits = 0x1d00ffff;
- BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, params), 0x1d00ffff);
+ BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1d00ffff);
}
/* Test the constraint on the lower bound for actual time taken */
BOOST_AUTO_TEST_CASE(get_next_work_lower_limit_actual)
{
- SelectParams(CBaseChainParams::MAIN);
- const Consensus::Params& params = Params().GetConsensus();
-
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
int64_t nLastRetargetTime = 1279008237; // Block #66528
CBlockIndex pindexLast;
pindexLast.nHeight = 68543;
pindexLast.nTime = 1279297671; // Block #68543
pindexLast.nBits = 0x1c05a3f4;
- BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, params), 0x1c0168fd);
+ BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1c0168fd);
}
/* Test the constraint on the upper bound for actual time taken */
BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual)
{
- SelectParams(CBaseChainParams::MAIN);
- const Consensus::Params& params = Params().GetConsensus();
-
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
int64_t nLastRetargetTime = 1263163443; // NOTE: Not an actual block time
CBlockIndex pindexLast;
pindexLast.nHeight = 46367;
pindexLast.nTime = 1269211443; // Block #46367
pindexLast.nBits = 0x1c387f6f;
- BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, params), 0x1d00e1fd);
+ BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1d00e1fd);
}
BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test)
{
- SelectParams(CBaseChainParams::MAIN);
- const Consensus::Params& params = Params().GetConsensus();
-
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
std::vector<CBlockIndex> blocks(10000);
for (int i = 0; i < 10000; i++) {
blocks[i].pprev = i ? &blocks[i - 1] : NULL;
blocks[i].nHeight = i;
- blocks[i].nTime = 1269211443 + i * params.nPowTargetSpacing;
+ blocks[i].nTime = 1269211443 + i * chainParams->GetConsensus().nPowTargetSpacing;
blocks[i].nBits = 0x207fffff; /* target 0x7fffff000... */
blocks[i].nChainWork = i ? blocks[i - 1].nChainWork + GetBlockProof(blocks[i - 1]) : arith_uint256(0);
}
@@ -88,7 +78,7 @@ BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test)
CBlockIndex *p2 = &blocks[GetRand(10000)];
CBlockIndex *p3 = &blocks[GetRand(10000)];
- int64_t tdiff = GetBlockProofEquivalentTime(*p1, *p2, *p3, params);
+ int64_t tdiff = GetBlockProofEquivalentTime(*p1, *p2, *p3, chainParams->GetConsensus());
BOOST_CHECK_EQUAL(tdiff, p1->GetBlockTime() - p2->GetBlockTime());
}
}
diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp
index e2b5573abd..79405ec4d1 100644
--- a/src/test/versionbits_tests.cpp
+++ b/src/test/versionbits_tests.cpp
@@ -209,7 +209,8 @@ BOOST_AUTO_TEST_CASE(versionbits_test)
}
// Sanity checks of version bit deployments
- const Consensus::Params &mainnetParams = Params(CBaseChainParams::MAIN).GetConsensus();
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
+ const Consensus::Params &mainnetParams = chainParams->GetConsensus();
for (int i=0; i<(int) Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) {
uint32_t bitmask = VersionBitsMask(mainnetParams, (Consensus::DeploymentPos)i);
// Make sure that no deployment tries to set an invalid bit.
@@ -235,7 +236,8 @@ BOOST_AUTO_TEST_CASE(versionbits_computeblockversion)
{
// Check that ComputeBlockVersion will set the appropriate bit correctly
// on mainnet.
- const Consensus::Params &mainnetParams = Params(CBaseChainParams::MAIN).GetConsensus();
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
+ const Consensus::Params &mainnetParams = chainParams->GetConsensus();
// Use the TESTDUMMY deployment for testing purposes.
int64_t bit = mainnetParams.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit;
diff --git a/src/txmempool.h b/src/txmempool.h
index 92c4d9f9d4..94987ef4d1 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -16,6 +16,7 @@
#include "amount.h"
#include "coins.h"
#include "indirectmap.h"
+#include "policy/feerate.h"
#include "primitives/transaction.h"
#include "sync.h"
#include "random.h"
diff --git a/src/utiltime.cpp b/src/utiltime.cpp
index a9936a645a..510f540b1d 100644
--- a/src/utiltime.cpp
+++ b/src/utiltime.cpp
@@ -9,14 +9,17 @@
#include "utiltime.h"
+#include <atomic>
+
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/thread.hpp>
-static int64_t nMockTime = 0; //!< For unit testing
+static std::atomic<int64_t> nMockTime(0); //!< For unit testing
int64_t GetTime()
{
- if (nMockTime) return nMockTime;
+ int64_t mocktime = nMockTime.load(std::memory_order_relaxed);
+ if (mocktime) return mocktime;
time_t now = time(NULL);
assert(now > 0);
@@ -25,7 +28,7 @@ int64_t GetTime()
void SetMockTime(int64_t nMockTimeIn)
{
- nMockTime = nMockTimeIn;
+ nMockTime.store(nMockTimeIn, std::memory_order_relaxed);
}
int64_t GetTimeMillis()
@@ -52,7 +55,8 @@ int64_t GetSystemTimeInSeconds()
/** Return a time useful for the debug log */
int64_t GetLogTimeMicros()
{
- if (nMockTime) return nMockTime*1000000;
+ int64_t mocktime = nMockTime.load(std::memory_order_relaxed);
+ if (mocktime) return mocktime*1000000;
return GetTimeMicros();
}
diff --git a/src/validation.cpp b/src/validation.cpp
index 6c60be45a1..75a35756d4 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -1299,10 +1299,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;
- if (!VerifyScript(scriptSig, scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore, *txdata), &error)) {
- return false;
- }
- return true;
+ return VerifyScript(scriptSig, scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore, *txdata), &error);
}
int GetSpendHeight(const CCoinsViewCache& inputs)
@@ -1526,28 +1523,36 @@ bool ApplyTxInUndo(const CTxInUndo& undo, CCoinsViewCache& view, const COutPoint
return fClean;
}
+enum DisconnectResult
+{
+ DISCONNECT_OK, // All good.
+ DISCONNECT_UNCLEAN, // Rolled back, but UTXO set was inconsistent with block.
+ DISCONNECT_FAILED // Something else went wrong.
+};
+
/** Undo the effects of this block (with given index) on the UTXO set represented by coins.
- * In case pfClean is provided, operation will try to be tolerant about errors, and *pfClean
- * will be true if no problems were found. Otherwise, the return value will be false in case
- * of problems. Note that in any case, coins may be modified. */
-static bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockIndex* pindex, CCoinsViewCache& view, bool* pfClean = NULL)
+ * When UNCLEAN or FAILED is returned, view is left in an indeterminate state. */
+static DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view)
{
assert(pindex->GetBlockHash() == view.GetBestBlock());
- if (pfClean)
- *pfClean = false;
-
bool fClean = true;
CBlockUndo blockUndo;
CDiskBlockPos pos = pindex->GetUndoPos();
- if (pos.IsNull())
- return error("DisconnectBlock(): no undo data available");
- if (!UndoReadFromDisk(blockUndo, pos, pindex->pprev->GetBlockHash()))
- return error("DisconnectBlock(): failure reading undo data");
+ if (pos.IsNull()) {
+ error("DisconnectBlock(): no undo data available");
+ return DISCONNECT_FAILED;
+ }
+ if (!UndoReadFromDisk(blockUndo, pos, pindex->pprev->GetBlockHash())) {
+ error("DisconnectBlock(): failure reading undo data");
+ return DISCONNECT_FAILED;
+ }
- if (blockUndo.vtxundo.size() + 1 != block.vtx.size())
- return error("DisconnectBlock(): block and undo data inconsistent");
+ if (blockUndo.vtxundo.size() + 1 != block.vtx.size()) {
+ error("DisconnectBlock(): block and undo data inconsistent");
+ return DISCONNECT_FAILED;
+ }
// undo transactions in reverse order
for (int i = block.vtx.size() - 1; i >= 0; i--) {
@@ -1576,8 +1581,10 @@ static bool DisconnectBlock(const CBlock& block, CValidationState& state, const
// restore inputs
if (i > 0) { // not coinbases
const CTxUndo &txundo = blockUndo.vtxundo[i-1];
- if (txundo.vprevout.size() != tx.vin.size())
- return error("DisconnectBlock(): transaction and undo data inconsistent");
+ if (txundo.vprevout.size() != tx.vin.size()) {
+ error("DisconnectBlock(): transaction and undo data inconsistent");
+ return DISCONNECT_FAILED;
+ }
for (unsigned int j = tx.vin.size(); j-- > 0;) {
const COutPoint &out = tx.vin[j].prevout;
const CTxInUndo &undo = txundo.vprevout[j];
@@ -1590,12 +1597,7 @@ static bool DisconnectBlock(const CBlock& block, CValidationState& state, const
// move best block pointer to prevout block
view.SetBestBlock(pindex->pprev->GetBlockHash());
- if (pfClean) {
- *pfClean = fClean;
- return true;
- }
-
- return fClean;
+ return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN;
}
void static FlushBlockFile(bool fFinalize = false)
@@ -2131,7 +2133,7 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara
int64_t nStart = GetTimeMicros();
{
CCoinsViewCache view(pcoinsTip);
- if (!DisconnectBlock(block, state, pindexDelete, view))
+ if (DisconnectBlock(block, pindexDelete, view) != DISCONNECT_OK)
return error("DisconnectTip(): DisconnectBlock %s failed", pindexDelete->GetBlockHash().ToString());
bool flushed = view.Flush();
assert(flushed);
@@ -2537,6 +2539,9 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
return false;
}
+ int nStopAtHeight = GetArg("-stopatheight", DEFAULT_STOPATHEIGHT);
+ if (nStopAtHeight && pindexNewTip && pindexNewTip->nHeight >= nStopAtHeight) StartShutdown();
+
return true;
}
@@ -3656,15 +3661,17 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
}
// check level 3: check for inconsistencies during memory-only disconnect of tip blocks
if (nCheckLevel >= 3 && pindex == pindexState && (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) <= nCoinCacheUsage) {
- bool fClean = true;
- if (!DisconnectBlock(block, state, pindex, coins, &fClean))
+ DisconnectResult res = DisconnectBlock(block, pindex, coins);
+ if (res == DISCONNECT_FAILED) {
return error("VerifyDB(): *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
+ }
pindexState = pindex->pprev;
- if (!fClean) {
+ if (res == DISCONNECT_UNCLEAN) {
nGoodTransactions = 0;
pindexFailure = pindex;
- } else
+ } else {
nGoodTransactions += block.vtx.size();
+ }
}
if (ShutdownRequested())
return true;
diff --git a/src/validation.h b/src/validation.h
index c0f9b6d513..8ddceb2306 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -14,6 +14,7 @@
#include "coins.h"
#include "fs.h"
#include "protocol.h" // For CMessageHeader::MessageStartChars
+#include "policy/feerate.h"
#include "script/script_error.h"
#include "sync.h"
#include "versionbits.h"
@@ -131,7 +132,8 @@ static const bool DEFAULT_PERMIT_BAREMULTISIG = true;
static const bool DEFAULT_CHECKPOINTS_ENABLED = true;
static const bool DEFAULT_TXINDEX = false;
static const unsigned int DEFAULT_BANSCORE_THRESHOLD = 100;
-
+/** Default for -persistmempool */
+static const bool DEFAULT_PERSIST_MEMPOOL = true;
/** Default for -mempoolreplacement */
static const bool DEFAULT_ENABLE_REPLACEMENT = true;
/** Default for using fee filter */
@@ -145,6 +147,9 @@ static const int MAX_UNCONNECTING_HEADERS = 10;
static const bool DEFAULT_PEERBLOOMFILTERS = true;
+/** Default for -stopatheight */
+static const int DEFAULT_STOPATHEIGHT = 0;
+
struct BlockHasher
{
size_t operator()(const uint256& hash) const { return hash.GetCheapHash(); }
diff --git a/src/wallet/coincontrol.h b/src/wallet/coincontrol.h
index 4e93e929be..2aa26fb00a 100644
--- a/src/wallet/coincontrol.h
+++ b/src/wallet/coincontrol.h
@@ -5,6 +5,7 @@
#ifndef BITCOIN_WALLET_COINCONTROL_H
#define BITCOIN_WALLET_COINCONTROL_H
+#include "policy/feerate.h"
#include "primitives/transaction.h"
#include "wallet/wallet.h"
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
index c810476f96..25f6bdd9d9 100644
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -466,15 +466,6 @@ void CDBEnv::CloseDb(const std::string& strFile)
}
}
-bool CDBEnv::RemoveDb(const std::string& strFile)
-{
- this->CloseDb(strFile);
-
- LOCK(cs_db);
- int rc = dbenv->dbremove(NULL, strFile.c_str(), NULL, DB_AUTO_COMMIT);
- return (rc == 0);
-}
-
bool CDB::Rewrite(CWalletDBWrapper& dbw, const char* pszSkip)
{
if (dbw.IsDummy()) {
diff --git a/src/wallet/db.h b/src/wallet/db.h
index a0719820ac..1a46448cc7 100644
--- a/src/wallet/db.h
+++ b/src/wallet/db.h
@@ -72,7 +72,6 @@ public:
void CheckpointLSN(const std::string& strFile);
void CloseDb(const std::string& strFile);
- bool RemoveDb(const std::string& strFile);
DbTxn* TxnBegin(int flags = DB_TXN_WRITE_NOSYNC)
{
diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp
index 82e5974065..b3cb6a718c 100644
--- a/src/wallet/feebumper.cpp
+++ b/src/wallet/feebumper.cpp
@@ -160,7 +160,7 @@ CFeeBumper::CFeeBumper(const CWallet *pWallet, const uint256 txidIn, int newConf
} else {
// if user specified a confirm target then don't consider any global payTxFee
if (specifiedConfirmTarget) {
- nNewFee = CWallet::GetMinimumFee(maxNewTxSize, newConfirmTarget, mempool, ::feeEstimator, CAmount(0));
+ nNewFee = CWallet::GetMinimumFee(maxNewTxSize, newConfirmTarget, mempool, ::feeEstimator, true);
}
// otherwise use the regular wallet logic to select payTxFee or default confirm target
else {
@@ -214,7 +214,7 @@ CFeeBumper::CFeeBumper(const CWallet *pWallet, const uint256 txidIn, int newConf
// If the output would become dust, discard it (converting the dust to fee)
poutput->nValue -= nDelta;
- if (poutput->nValue <= poutput->GetDustThreshold(::dustRelayFee)) {
+ if (poutput->nValue <= GetDustThreshold(*poutput, ::dustRelayFee)) {
LogPrint(BCLog::RPC, "Bumping fee and discarding dust output\n");
nNewFee += poutput->nValue;
mtx.vout.erase(mtx.vout.begin() + nOutput);
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index ea325a2627..fa67964ce8 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -12,6 +12,7 @@
#include "wallet/coincontrol.h"
#include "validation.h"
#include "net.h"
+#include "policy/feerate.h"
#include "policy/fees.h"
#include "policy/policy.h"
#include "policy/rbf.h"
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 03659f50b2..ea329d6ebe 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -621,12 +621,9 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
// if we are using HD, replace the HD master key (seed) with a new one
if (IsHDEnabled()) {
- CKey key;
- CPubKey masterPubKey = GenerateNewHDMasterKey();
- // preserve the old chains version to not break backward compatibility
- CHDChain oldChain = GetHDChain();
- if (!SetHDMasterKey(masterPubKey, &oldChain))
+ if (!SetHDMasterKey(GenerateNewHDMasterKey())) {
return false;
+ }
}
NewKeyPool();
@@ -1124,12 +1121,12 @@ void CWallet::TransactionAddedToMempool(const CTransactionRef& ptx) {
void CWallet::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex *pindex, const std::vector<CTransactionRef>& vtxConflicted) {
LOCK2(cs_main, cs_wallet);
- // TODO: Tempoarily ensure that mempool removals are notified before
+ // TODO: Temporarily ensure that mempool removals are notified before
// connected transactions. This shouldn't matter, but the abandoned
// state of transactions in our wallet is currently cleared when we
// receive another notification and there is a race condition where
// notification of a connected conflict might cause an outside process
- // to abandon a transaction and then have it inadvertantly cleared by
+ // to abandon a transaction and then have it inadvertently cleared by
// the notification that the conflicted transaction was evicted.
for (const CTransactionRef& ptx : vtxConflicted) {
@@ -1324,17 +1321,14 @@ CPubKey CWallet::GenerateNewHDMasterKey()
return pubkey;
}
-bool CWallet::SetHDMasterKey(const CPubKey& pubkey, CHDChain *possibleOldChain)
+bool CWallet::SetHDMasterKey(const CPubKey& pubkey)
{
LOCK(cs_wallet);
// store the keyid (hash160) together with
// the child index counter in the database
// as a hdchain object
CHDChain newHdChain;
- if (possibleOldChain) {
- // preserve the old chains version
- newHdChain.nVersion = possibleOldChain->nVersion;
- }
+ newHdChain.nVersion = CanSupportFeature(FEATURE_HD_SPLIT) ? CHDChain::VERSION_HD_CHAIN_SPLIT : CHDChain::VERSION_HD_BASE;
newHdChain.masterKeyID = pubkey.GetID();
SetHDChain(newHdChain, false);
@@ -2455,7 +2449,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
}
}
- if (txout.IsDust(dustRelayFee))
+ if (IsDust(txout, ::dustRelayFee))
{
if (recipient.fSubtractFeeFromAmount && nFeeRet > 0)
{
@@ -2520,16 +2514,16 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
// We do not move dust-change to fees, because the sender would end up paying more than requested.
// This would be against the purpose of the all-inclusive feature.
// So instead we raise the change and deduct from the recipient.
- if (nSubtractFeeFromAmount > 0 && newTxOut.IsDust(dustRelayFee))
+ if (nSubtractFeeFromAmount > 0 && IsDust(newTxOut, ::dustRelayFee))
{
- CAmount nDust = newTxOut.GetDustThreshold(dustRelayFee) - newTxOut.nValue;
+ CAmount nDust = GetDustThreshold(newTxOut, ::dustRelayFee) - newTxOut.nValue;
newTxOut.nValue += nDust; // raise change until no more dust
for (unsigned int i = 0; i < vecSend.size(); i++) // subtract from first recipient
{
if (vecSend[i].fSubtractFeeFromAmount)
{
txNew.vout[i].nValue -= nDust;
- if (txNew.vout[i].IsDust(dustRelayFee))
+ if (IsDust(txNew.vout[i], ::dustRelayFee))
{
strFailReason = _("The transaction amount is too small to send after the fee has been deducted");
return false;
@@ -2541,7 +2535,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
// Never create dust outputs; if we would, just
// add the dust to the fee.
- if (newTxOut.IsDust(dustRelayFee))
+ if (IsDust(newTxOut, ::dustRelayFee))
{
nChangePosInOut = -1;
nFeeRet += nChange;
@@ -2563,9 +2557,10 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
std::vector<CTxOut>::iterator position = txNew.vout.begin()+nChangePosInOut;
txNew.vout.insert(position, newTxOut);
}
- }
- else
+ } else {
reservekey.ReturnKey();
+ nChangePosInOut = -1;
+ }
// Fill vin
//
@@ -2777,17 +2772,12 @@ CAmount CWallet::GetRequiredFee(unsigned int nTxBytes)
return std::max(minTxFee.GetFee(nTxBytes), ::minRelayTxFee.GetFee(nTxBytes));
}
-CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator)
+CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, bool ignoreUserSetFee)
{
// payTxFee is the user-set global for desired feerate
- return GetMinimumFee(nTxBytes, nConfirmTarget, pool, estimator, payTxFee.GetFee(nTxBytes));
-}
-
-CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, CAmount targetFee)
-{
- CAmount nFeeNeeded = targetFee;
+ CAmount nFeeNeeded = payTxFee.GetFee(nTxBytes);
// User didn't set: use -txconfirmtarget to estimate...
- if (nFeeNeeded == 0) {
+ if (nFeeNeeded == 0 || ignoreUserSetFee) {
int estimateFoundTarget = nConfirmTarget;
nFeeNeeded = estimator.estimateSmartFee(nConfirmTarget, &estimateFoundTarget, pool).GetFee(nTxBytes);
// ... unless we don't have enough mempool data for estimatefee, then use fallbackFee
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 6710c39ce2..179ea1b7ad 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -7,6 +7,7 @@
#define BITCOIN_WALLET_WALLET_H
#include "amount.h"
+#include "policy/feerate.h"
#include "streams.h"
#include "tinyformat.h"
#include "ui_interface.h"
@@ -945,12 +946,7 @@ public:
* Estimate the minimum fee considering user set parameters
* and the required fee
*/
- static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator);
- /**
- * Estimate the minimum fee considering required fee and targetFee or if 0
- * then fee estimation for nConfirmTarget
- */
- static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, CAmount targetFee);
+ static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, bool ignoreUserSetFee = false);
/**
* Return the minimum required fee taking into account the
* floating relay fee and user set minimum transaction fee
@@ -1105,9 +1101,10 @@ public:
CPubKey GenerateNewHDMasterKey();
/* Set the current HD master key (will reset the chain child index counters)
- If possibleOldChain is provided, the parameters from the old chain (version)
- will be preserved. */
- bool SetHDMasterKey(const CPubKey& key, CHDChain *possibleOldChain = nullptr);
+ Sets the master key's version based on the current wallet version (so the
+ caller must ensure the current wallet version is correct before calling
+ this function). */
+ bool SetHDMasterKey(const CPubKey& key);
};
/** A key allocated from the key pool. */