aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xcontrib/gitian-build.sh2
-rw-r--r--contrib/init/org.bitcoin.bitcoind.plist1
-rw-r--r--src/Makefile.test.include3
-rw-r--r--src/bench/bench.cpp6
-rw-r--r--src/bench/bench.h3
-rw-r--r--src/merkleblock.cpp35
-rw-r--r--src/merkleblock.h16
-rw-r--r--src/net_processing.cpp5
-rw-r--r--src/policy/feerate.h7
-rw-r--r--src/policy/fees.cpp6
-rw-r--r--src/qt/guiutil.cpp5
-rw-r--r--src/qt/test/wallettests.cpp73
-rw-r--r--src/rpc/blockchain.cpp32
-rw-r--r--src/rpc/net.cpp2
-rw-r--r--src/rpc/rawtransaction.cpp4
-rw-r--r--src/script/interpreter.cpp6
-rw-r--r--src/script/script.h1
-rw-r--r--src/script/script_error.cpp2
-rw-r--r--src/sync.cpp4
-rw-r--r--src/test/bloom_tests.cpp12
-rw-r--r--src/test/dbwrapper_tests.cpp16
-rw-r--r--src/test/mempool_tests.cpp6
-rw-r--r--src/test/merkleblock_tests.cpp78
-rw-r--r--src/test/script_tests.cpp17
-rw-r--r--src/test/test_bitcoin.cpp13
-rw-r--r--src/test/test_bitcoin.h5
-rw-r--r--src/test/txvalidationcache_tests.cpp3
-rw-r--r--src/txmempool.cpp4
-rw-r--r--src/txmempool.h2
-rw-r--r--src/validation.cpp40
-rw-r--r--src/validation.h6
-rw-r--r--src/wallet/wallet.cpp11
-rwxr-xr-xtest/functional/bip68-sequence.py9
-rwxr-xr-xtest/functional/blockchain.py22
-rwxr-xr-xtest/functional/p2p-segwit.py4
-rwxr-xr-xtest/functional/replace-by-fee.py17
-rwxr-xr-xtest/functional/test_framework/mininode.py14
-rw-r--r--test/functional/test_framework/util.py8
-rwxr-xr-xtest/functional/zmq_test.py52
-rwxr-xr-xtest/util/bitcoin-util-test.py13
40 files changed, 427 insertions, 138 deletions
diff --git a/contrib/gitian-build.sh b/contrib/gitian-build.sh
index d94c7f4f8e..8fdec21b0e 100755
--- a/contrib/gitian-build.sh
+++ b/contrib/gitian-build.sh
@@ -179,8 +179,6 @@ done
if [[ $lxc = true ]]
then
export USE_LXC=1
- export LXC_BRIDGE=lxcbr0
- sudo ifconfig lxcbr0 up 10.0.2.2
fi
# Check for OSX SDK
diff --git a/contrib/init/org.bitcoin.bitcoind.plist b/contrib/init/org.bitcoin.bitcoind.plist
index e94cd4466d..95b5342f1e 100644
--- a/contrib/init/org.bitcoin.bitcoind.plist
+++ b/contrib/init/org.bitcoin.bitcoind.plist
@@ -7,7 +7,6 @@
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/bitcoind</string>
- <string>-daemon</string>
</array>
<key>RunAtLoad</key>
<true/>
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index ed95f345b1..d3e7b5da12 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -50,6 +50,7 @@ BITCOIN_TESTS =\
test/main_tests.cpp \
test/mempool_tests.cpp \
test/merkle_tests.cpp \
+ test/merkleblock_tests.cpp \
test/miner_tests.cpp \
test/multisig_tests.cpp \
test/net_tests.cpp \
@@ -148,7 +149,7 @@ bitcoin_test_clean : FORCE
check-local:
@echo "Running test/util/bitcoin-util-test.py..."
- $(top_builddir)/test/util/bitcoin-util-test.py
+ $(PYTHON) $(top_builddir)/test/util/bitcoin-util-test.py
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C secp256k1 check
if EMBEDDED_UNIVALUE
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C univalue check
diff --git a/src/bench/bench.cpp b/src/bench/bench.cpp
index 849d924af2..7b307d6f42 100644
--- a/src/bench/bench.cpp
+++ b/src/bench/bench.cpp
@@ -55,13 +55,13 @@ bool benchmark::State::KeepRunning()
else {
now = gettimedouble();
double elapsed = now - lastTime;
- double elapsedOne = elapsed * countMaskInv;
+ double elapsedOne = elapsed / (countMask + 1);
if (elapsedOne < minTime) minTime = elapsedOne;
if (elapsedOne > maxTime) maxTime = elapsedOne;
// We only use relative values, so don't have to handle 64-bit wrap-around specially
nowCycles = perf_cpucycles();
- uint64_t elapsedOneCycles = (nowCycles - lastCycles) * countMaskInv;
+ uint64_t elapsedOneCycles = (nowCycles - lastCycles) / (countMask + 1);
if (elapsedOneCycles < minCycles) minCycles = elapsedOneCycles;
if (elapsedOneCycles > maxCycles) maxCycles = elapsedOneCycles;
@@ -69,7 +69,6 @@ bool benchmark::State::KeepRunning()
// If the execution was much too fast (1/128th of maxElapsed), increase the count mask by 8x and restart timing.
// The restart avoids including the overhead of this code in the measurement.
countMask = ((countMask<<3)|7) & ((1LL<<60)-1);
- countMaskInv = 1./(countMask+1);
count = 0;
minTime = std::numeric_limits<double>::max();
maxTime = std::numeric_limits<double>::min();
@@ -81,7 +80,6 @@ bool benchmark::State::KeepRunning()
uint64_t newCountMask = ((countMask<<1)|1) & ((1LL<<60)-1);
if ((count & newCountMask)==0) {
countMask = newCountMask;
- countMaskInv = 1./(countMask+1);
}
}
}
diff --git a/src/bench/bench.h b/src/bench/bench.h
index 1f36f2a4bc..79109eaa56 100644
--- a/src/bench/bench.h
+++ b/src/bench/bench.h
@@ -41,7 +41,7 @@ namespace benchmark {
std::string name;
double maxElapsed;
double beginTime;
- double lastTime, minTime, maxTime, countMaskInv;
+ double lastTime, minTime, maxTime;
uint64_t count;
uint64_t countMask;
uint64_t beginCycles;
@@ -55,7 +55,6 @@ namespace benchmark {
minCycles = std::numeric_limits<uint64_t>::max();
maxCycles = std::numeric_limits<uint64_t>::min();
countMask = 1;
- countMaskInv = 1./(countMask + 1);
}
bool KeepRunning();
};
diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp
index f0abea0611..3f07b4dac4 100644
--- a/src/merkleblock.cpp
+++ b/src/merkleblock.cpp
@@ -9,33 +9,8 @@
#include "consensus/consensus.h"
#include "utilstrencodings.h"
-CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter& filter)
-{
- header = block.GetBlockHeader();
- std::vector<bool> vMatch;
- std::vector<uint256> vHashes;
-
- vMatch.reserve(block.vtx.size());
- vHashes.reserve(block.vtx.size());
-
- for (unsigned int i = 0; i < block.vtx.size(); i++)
- {
- const uint256& hash = block.vtx[i]->GetHash();
- if (filter.IsRelevantAndUpdate(*block.vtx[i]))
- {
- vMatch.push_back(true);
- vMatchedTxn.push_back(std::make_pair(i, hash));
- }
- else
- vMatch.push_back(false);
- vHashes.push_back(hash);
- }
-
- txn = CPartialMerkleTree(vHashes, vMatch);
-}
-
-CMerkleBlock::CMerkleBlock(const CBlock& block, const std::set<uint256>& txids)
+CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter* filter, const std::set<uint256>* txids)
{
header = block.GetBlockHeader();
@@ -48,10 +23,14 @@ CMerkleBlock::CMerkleBlock(const CBlock& block, const std::set<uint256>& txids)
for (unsigned int i = 0; i < block.vtx.size(); i++)
{
const uint256& hash = block.vtx[i]->GetHash();
- if (txids.count(hash))
+ if (txids && txids->count(hash)) {
vMatch.push_back(true);
- else
+ } else if (filter && filter->IsRelevantAndUpdate(*block.vtx[i])) {
+ vMatch.push_back(true);
+ vMatchedTxn.emplace_back(i, hash);
+ } else {
vMatch.push_back(false);
+ }
vHashes.push_back(hash);
}
diff --git a/src/merkleblock.h b/src/merkleblock.h
index 20f2b36886..6c05f2c1f8 100644
--- a/src/merkleblock.h
+++ b/src/merkleblock.h
@@ -131,8 +131,12 @@ public:
CBlockHeader header;
CPartialMerkleTree txn;
-public:
- /** Public only for unit testing and relay testing (not relayed) */
+ /**
+ * Public only for unit testing and relay testing (not relayed).
+ *
+ * Used only when a bloom filter is specified to allow
+ * testing the transactions which matched the bloom filter.
+ */
std::vector<std::pair<unsigned int, uint256> > vMatchedTxn;
/**
@@ -140,10 +144,10 @@ public:
* Note that this will call IsRelevantAndUpdate on the filter for each transaction,
* thus the filter will likely be modified.
*/
- CMerkleBlock(const CBlock& block, CBloomFilter& filter);
+ CMerkleBlock(const CBlock& block, CBloomFilter& filter) : CMerkleBlock(block, &filter, nullptr) { }
// Create from a CBlock, matching the txids in the set
- CMerkleBlock(const CBlock& block, const std::set<uint256>& txids);
+ CMerkleBlock(const CBlock& block, const std::set<uint256>& txids) : CMerkleBlock(block, nullptr, &txids) { }
CMerkleBlock() {}
@@ -154,6 +158,10 @@ public:
READWRITE(header);
READWRITE(txn);
}
+
+private:
+ // Combined constructor to consolidate code
+ CMerkleBlock(const CBlock& block, CBloomFilter* filter, const std::set<uint256>* txids);
};
#endif // BITCOIN_MERKLEBLOCK_H
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index b8900d9888..7fced41d4f 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -1788,7 +1788,8 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
std::list<CTransactionRef> lRemovedTxn;
- if (!AlreadyHave(inv) && AcceptToMemoryPool(mempool, state, ptx, true, &fMissingInputs, &lRemovedTxn)) {
+ if (!AlreadyHave(inv) &&
+ AcceptToMemoryPool(mempool, state, ptx, &fMissingInputs, &lRemovedTxn, false /* bypass_limits */, 0 /* nAbsurdFee */)) {
mempool.check(pcoinsTip);
RelayTransaction(tx, connman);
for (unsigned int i = 0; i < tx.vout.size(); i++) {
@@ -1826,7 +1827,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (setMisbehaving.count(fromPeer))
continue;
- if (AcceptToMemoryPool(mempool, stateDummy, porphanTx, true, &fMissingInputs2, &lRemovedTxn)) {
+ if (AcceptToMemoryPool(mempool, stateDummy, porphanTx, &fMissingInputs2, &lRemovedTxn, false /* bypass_limits */, 0 /* nAbsurdFee */)) {
LogPrint(BCLog::MEMPOOL, " accepted orphan tx %s\n", orphanHash.ToString());
RelayTransaction(orphanTx, connman);
for (unsigned int i = 0; i < orphanTx.vout.size(); i++) {
diff --git a/src/policy/feerate.h b/src/policy/feerate.h
index 7e519e3efa..3449cdd699 100644
--- a/src/policy/feerate.h
+++ b/src/policy/feerate.h
@@ -20,10 +20,15 @@ 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) { }
+ template<typename I>
+ CFeeRate(const I _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) {
+ // We've previously had bugs creep in from silent double->int conversion...
+ static_assert(std::is_integral<I>::value, "CFeeRate should be used without floats");
+ }
/** 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);
/**
diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp
index b9476407cf..8056f385ab 100644
--- a/src/policy/fees.cpp
+++ b/src/policy/fees.cpp
@@ -714,7 +714,7 @@ CFeeRate CBlockPolicyEstimator::estimateRawFee(int confTarget, double successThr
if (median < 0)
return CFeeRate(0);
- return CFeeRate(median);
+ return CFeeRate(llround(median));
}
unsigned int CBlockPolicyEstimator::HighestTargetTracked(FeeEstimateHorizon horizon) const
@@ -901,7 +901,7 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, FeeCalculation
if (median < 0) return CFeeRate(0); // error condition
- return CFeeRate(median);
+ return CFeeRate(llround(median));
}
@@ -1043,5 +1043,5 @@ CAmount FeeFilterRounder::round(CAmount currentMinFee)
if ((it != feeset.begin() && insecure_rand.rand32() % 3 != 0) || it == feeset.end()) {
it--;
}
- return *it;
+ return static_cast<CAmount>(*it);
}
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index b916df69aa..d520d7d4be 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -744,9 +744,10 @@ bool SetStartOnSystemStartup(bool fAutoStart)
else
{
char pszExePath[MAX_PATH+1];
- memset(pszExePath, 0, sizeof(pszExePath));
- if (readlink("/proc/self/exe", pszExePath, sizeof(pszExePath)-1) == -1)
+ ssize_t r = readlink("/proc/self/exe", pszExePath, sizeof(pszExePath) - 1);
+ if (r == -1)
return false;
+ pszExePath[r] = '\0';
fs::create_directories(GetAutostartDir());
diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp
index 5031d7651d..eeae58bd05 100644
--- a/src/qt/test/wallettests.cpp
+++ b/src/qt/test/wallettests.cpp
@@ -13,6 +13,10 @@
#include "test/test_bitcoin.h"
#include "validation.h"
#include "wallet/wallet.h"
+#include "qt/overviewpage.h"
+#include "qt/receivecoinsdialog.h"
+#include "qt/recentrequeststablemodel.h"
+#include "qt/receiverequestdialog.h"
#include <QAbstractButton>
#include <QAction>
@@ -21,6 +25,9 @@
#include <QPushButton>
#include <QTimer>
#include <QVBoxLayout>
+#include <QTextEdit>
+#include <QListView>
+#include <QDialogButtonBox>
namespace
{
@@ -140,7 +147,7 @@ void BumpFee(TransactionView& view, const uint256& txid, bool expectDisabled, st
// src/qt/test/test_bitcoin-qt -platform xcb # Linux
// src/qt/test/test_bitcoin-qt -platform windows # Windows
// src/qt/test/test_bitcoin-qt -platform cocoa # macOS
-void TestSendCoins()
+void TestGUI()
{
// Set up wallet and chain with 105 blocks (5 mature blocks for spending).
TestChain100Setup test;
@@ -184,6 +191,68 @@ void TestSendCoins()
BumpFee(transactionView, txid2, false /* expect disabled */, {} /* expected error */, false /* cancel */);
BumpFee(transactionView, txid2, true /* expect disabled */, "already bumped" /* expected error */, false /* cancel */);
+ // Check current balance on OverviewPage
+ OverviewPage overviewPage(platformStyle.get());
+ overviewPage.setWalletModel(&walletModel);
+ QLabel* balanceLabel = overviewPage.findChild<QLabel*>("labelBalance");
+ QString balanceText = balanceLabel->text();
+ int unit = walletModel.getOptionsModel()->getDisplayUnit();
+ CAmount balance = walletModel.getBalance();
+ QString balanceComparison = BitcoinUnits::formatWithUnit(unit, balance, false, BitcoinUnits::separatorAlways);
+ QCOMPARE(balanceText, balanceComparison);
+
+ // Check Request Payment button
+ ReceiveCoinsDialog receiveCoinsDialog(platformStyle.get());
+ receiveCoinsDialog.setModel(&walletModel);
+ RecentRequestsTableModel* requestTableModel = walletModel.getRecentRequestsTableModel();
+
+ // Label input
+ QLineEdit* labelInput = receiveCoinsDialog.findChild<QLineEdit*>("reqLabel");
+ labelInput->setText("TEST_LABEL_1");
+
+ // Amount input
+ BitcoinAmountField* amountInput = receiveCoinsDialog.findChild<BitcoinAmountField*>("reqAmount");
+ amountInput->setValue(1);
+
+ // Message input
+ QLineEdit* messageInput = receiveCoinsDialog.findChild<QLineEdit*>("reqMessage");
+ messageInput->setText("TEST_MESSAGE_1");
+ int initialRowCount = requestTableModel->rowCount({});
+ QPushButton* requestPaymentButton = receiveCoinsDialog.findChild<QPushButton*>("receiveButton");
+ requestPaymentButton->click();
+ for (QWidget* widget : QApplication::topLevelWidgets()) {
+ if (widget->inherits("ReceiveRequestDialog")) {
+ ReceiveRequestDialog* receiveRequestDialog = qobject_cast<ReceiveRequestDialog*>(widget);
+ QTextEdit* rlist = receiveRequestDialog->QObject::findChild<QTextEdit*>("outUri");
+ QString paymentText = rlist->toPlainText();
+ QStringList paymentTextList = paymentText.split('\n');
+ QCOMPARE(paymentTextList.at(0), QString("Payment information"));
+ QVERIFY(paymentTextList.at(1).indexOf(QString("URI: bitcoin:")) != -1);
+ QVERIFY(paymentTextList.at(2).indexOf(QString("Address:")) != -1);
+ QCOMPARE(paymentTextList.at(3), QString("Amount: 0.00000001 ") + QString::fromStdString(CURRENCY_UNIT));
+ QCOMPARE(paymentTextList.at(4), QString("Label: TEST_LABEL_1"));
+ QCOMPARE(paymentTextList.at(5), QString("Message: TEST_MESSAGE_1"));
+ }
+ }
+
+ // Clear button
+ QPushButton* clearButton = receiveCoinsDialog.findChild<QPushButton*>("clearButton");
+ clearButton->click();
+ QCOMPARE(labelInput->text(), QString(""));
+ QCOMPARE(amountInput->value(), CAmount(0));
+ QCOMPARE(messageInput->text(), QString(""));
+
+ // Check addition to history
+ int currentRowCount = requestTableModel->rowCount({});
+ QCOMPARE(currentRowCount, initialRowCount+1);
+
+ // Check Remove button
+ QTableView* table = receiveCoinsDialog.findChild<QTableView*>("recentRequestsView");
+ table->selectRow(currentRowCount-1);
+ QPushButton* removeRequestButton = receiveCoinsDialog.findChild<QPushButton*>("removeRequestButton");
+ removeRequestButton->click();
+ QCOMPARE(requestTableModel->rowCount({}), currentRowCount-1);
+
bitdb.Flush(true);
bitdb.Reset();
}
@@ -192,5 +261,5 @@ void TestSendCoins()
void WalletTests::walletTests()
{
- TestSendCoins();
+ TestGUI();
}
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 8c0268e264..19074d3d95 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -1484,9 +1484,12 @@ UniValue getchaintxstats(const JSONRPCRequest& request)
"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"
+ " \"time\": xxxxx, (numeric) The timestamp for the final block in the window in UNIX format.\n"
+ " \"txcount\": xxxxx, (numeric) The total number of transactions in the chain up to that point.\n"
+ " \"window_block_count\": xxxxx, (numeric) Size of the window in number of blocks.\n"
+ " \"window_tx_count\": xxxxx, (numeric) The number of transactions in the window. Only returned if \"window_block_count\" is > 0.\n"
+ " \"window_interval\": xxxxx, (numeric) The elapsed time in the window in seconds. Only returned if \"window_block_count\" is > 0.\n"
+ " \"txrate\": x.xx, (numeric) The average rate of transactions per second in the window. Only returned if \"window_interval\" is > 0.\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("getchaintxstats", "")
@@ -1496,10 +1499,6 @@ UniValue getchaintxstats(const JSONRPCRequest& request)
const CBlockIndex* pindex;
int blockcount = 30 * 24 * 60 * 60 / Params().GetConsensus().nPowTargetSpacing; // By default: 1 month
- if (!request.params[0].isNull()) {
- blockcount = request.params[0].get_int();
- }
-
bool havehash = !request.params[1].isNull();
uint256 hash;
if (havehash) {
@@ -1524,8 +1523,14 @@ UniValue getchaintxstats(const JSONRPCRequest& request)
assert(pindex != nullptr);
- if (blockcount < 1 || blockcount >= pindex->nHeight) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block count: should be between 1 and the block's height");
+ if (request.params[0].isNull()) {
+ blockcount = std::max(0, std::min(blockcount, pindex->nHeight - 1));
+ } else {
+ blockcount = request.params[0].get_int();
+
+ if (blockcount < 0 || (blockcount > 0 && blockcount >= pindex->nHeight)) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block count: should be between 0 and the block's height - 1");
+ }
}
const CBlockIndex* pindexPast = pindex->GetAncestor(pindex->nHeight - blockcount);
@@ -1535,7 +1540,14 @@ UniValue getchaintxstats(const JSONRPCRequest& request)
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));
+ ret.push_back(Pair("window_block_count", blockcount));
+ if (blockcount > 0) {
+ ret.push_back(Pair("window_tx_count", nTxDiff));
+ ret.push_back(Pair("window_interval", nTimeDiff));
+ if (nTimeDiff > 0) {
+ ret.push_back(Pair("txrate", ((double)nTxDiff) / nTimeDiff));
+ }
+ }
return ret;
}
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index 0184448213..a3d3df26a3 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -146,7 +146,7 @@ UniValue getpeerinfo(const JSONRPCRequest& request)
obj.push_back(Pair("timeoffset", stats.nTimeOffset));
if (stats.dPingTime > 0.0)
obj.push_back(Pair("pingtime", stats.dPingTime));
- if (stats.dMinPing < std::numeric_limits<int64_t>::max()/1e6)
+ if (stats.dMinPing < static_cast<double>(std::numeric_limits<int64_t>::max())/1e6)
obj.push_back(Pair("minping", stats.dMinPing));
if (stats.dPingWait > 0.0)
obj.push_back(Pair("pingwait", stats.dPingWait));
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index b2fc6a357a..d860dbc244 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -942,8 +942,8 @@ UniValue sendrawtransaction(const JSONRPCRequest& request)
// push to local node and sync with wallets
CValidationState state;
bool fMissingInputs;
- bool fLimitFree = true;
- if (!AcceptToMemoryPool(mempool, state, std::move(tx), fLimitFree, &fMissingInputs, nullptr, false, nMaxRawTxFee)) {
+ if (!AcceptToMemoryPool(mempool, state, std::move(tx), &fMissingInputs,
+ nullptr /* plTxnReplaced */, false /* bypass_limits */, nMaxRawTxFee)) {
if (state.IsInvalid()) {
throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason()));
} else {
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index 7315500e3b..77314e8cb2 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -1175,6 +1175,8 @@ PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo)
uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache)
{
+ assert(nIn < txTo.vin.size());
+
if (sigversion == SIGVERSION_WITNESS_V0) {
uint256 hashPrevouts;
uint256 hashSequence;
@@ -1221,10 +1223,6 @@ uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsig
}
static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
- if (nIn >= txTo.vin.size()) {
- // nIn out of range
- return one;
- }
// Check for invalid use of SIGHASH_SINGLE
if ((nHashType & 0x1f) == SIGHASH_SINGLE) {
diff --git a/src/script/script.h b/src/script/script.h
index 587f2d26eb..2a92060543 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -420,6 +420,7 @@ public:
CScript& operator+=(const CScript& b)
{
+ reserve(size() + b.size());
insert(end(), b.begin(), b.end());
return *this;
}
diff --git a/src/script/script_error.cpp b/src/script/script_error.cpp
index c9d13c92a8..6c590f53e3 100644
--- a/src/script/script_error.cpp
+++ b/src/script/script_error.cpp
@@ -73,6 +73,8 @@ const char* ScriptErrorString(const ScriptError serror)
return "Witness version reserved for soft-fork upgrades";
case SCRIPT_ERR_PUBKEYTYPE:
return "Public key is neither compressed or uncompressed";
+ case SCRIPT_ERR_CLEANSTACK:
+ return "Extra items left on stack after execution";
case SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH:
return "Witness program has incorrect length";
case SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY:
diff --git a/src/sync.cpp b/src/sync.cpp
index 9c351ea487..87024ccdf2 100644
--- a/src/sync.cpp
+++ b/src/sync.cpp
@@ -98,7 +98,7 @@ static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch,
assert(false);
}
-static void push_lock(void* c, const CLockLocation& locklocation, bool fTry)
+static void push_lock(void* c, const CLockLocation& locklocation)
{
if (lockstack.get() == nullptr)
lockstack.reset(new LockStack);
@@ -130,7 +130,7 @@ static void pop_lock()
void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry)
{
- push_lock(cs, CLockLocation(pszName, pszFile, nLine, fTry), fTry);
+ push_lock(cs, CLockLocation(pszName, pszFile, nLine, fTry));
}
void LeaveCritical()
diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp
index 9274ceefcb..eac2c102a6 100644
--- a/src/test/bloom_tests.cpp
+++ b/src/test/bloom_tests.cpp
@@ -8,6 +8,7 @@
#include "clientversion.h"
#include "key.h"
#include "merkleblock.h"
+#include "primitives/block.h"
#include "random.h"
#include "serialize.h"
#include "streams.h"
@@ -179,20 +180,15 @@ BOOST_AUTO_TEST_CASE(bloom_match)
BOOST_AUTO_TEST_CASE(merkle_block_1)
{
- // Random real block (0000000000013b8ab2cd513b0261a14096412195a72a0c4827d229dcc7e0f7af)
- // With 9 txes
- CBlock block;
- CDataStream stream(ParseHex("0100000090f0a9f110702f808219ebea1173056042a714bad51b916cb6800000000000005275289558f51c9966699404ae2294730c3c9f9bda53523ce50e9b95e558da2fdb261b4d4c86041b1ab1bf930901000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07044c86041b0146ffffffff0100f2052a01000000434104e18f7afbe4721580e81e8414fc8c24d7cfacf254bb5c7b949450c3e997c2dc1242487a8169507b631eb3771f2b425483fb13102c4eb5d858eef260fe70fbfae0ac00000000010000000196608ccbafa16abada902780da4dc35dafd7af05fa0da08cf833575f8cf9e836000000004a493046022100dab24889213caf43ae6adc41cf1c9396c08240c199f5225acf45416330fd7dbd022100fe37900e0644bf574493a07fc5edba06dbc07c311b947520c2d514bc5725dcb401ffffffff0100f2052a010000001976a914f15d1921f52e4007b146dfa60f369ed2fc393ce288ac000000000100000001fb766c1288458c2bafcfec81e48b24d98ec706de6b8af7c4e3c29419bfacb56d000000008c493046022100f268ba165ce0ad2e6d93f089cfcd3785de5c963bb5ea6b8c1b23f1ce3e517b9f022100da7c0f21adc6c401887f2bfd1922f11d76159cbc597fbd756a23dcbb00f4d7290141042b4e8625a96127826915a5b109852636ad0da753c9e1d5606a50480cd0c40f1f8b8d898235e571fe9357d9ec842bc4bba1827daaf4de06d71844d0057707966affffffff0280969800000000001976a9146963907531db72d0ed1a0cfb471ccb63923446f388ac80d6e34c000000001976a914f0688ba1c0d1ce182c7af6741e02658c7d4dfcd388ac000000000100000002c40297f730dd7b5a99567eb8d27b78758f607507c52292d02d4031895b52f2ff010000008b483045022100f7edfd4b0aac404e5bab4fd3889e0c6c41aa8d0e6fa122316f68eddd0a65013902205b09cc8b2d56e1cd1f7f2fafd60a129ed94504c4ac7bdc67b56fe67512658b3e014104732012cb962afa90d31b25d8fb0e32c94e513ab7a17805c14ca4c3423e18b4fb5d0e676841733cb83abaf975845c9f6f2a8097b7d04f4908b18368d6fc2d68ecffffffffca5065ff9617cbcba45eb23726df6498a9b9cafed4f54cbab9d227b0035ddefb000000008a473044022068010362a13c7f9919fa832b2dee4e788f61f6f5d344a7c2a0da6ae740605658022006d1af525b9a14a35c003b78b72bd59738cd676f845d1ff3fc25049e01003614014104732012cb962afa90d31b25d8fb0e32c94e513ab7a17805c14ca4c3423e18b4fb5d0e676841733cb83abaf975845c9f6f2a8097b7d04f4908b18368d6fc2d68ecffffffff01001ec4110200000043410469ab4181eceb28985b9b4e895c13fa5e68d85761b7eee311db5addef76fa8621865134a221bd01f28ec9999ee3e021e60766e9d1f3458c115fb28650605f11c9ac000000000100000001cdaf2f758e91c514655e2dc50633d1e4c84989f8aa90a0dbc883f0d23ed5c2fa010000008b48304502207ab51be6f12a1962ba0aaaf24a20e0b69b27a94fac5adf45aa7d2d18ffd9236102210086ae728b370e5329eead9accd880d0cb070aea0c96255fae6c4f1ddcce1fd56e014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffff02404b4c00000000001976a9142b6ba7c9d796b75eef7942fc9288edd37c32f5c388ac002d3101000000001976a9141befba0cdc1ad56529371864d9f6cb042faa06b588ac000000000100000001b4a47603e71b61bc3326efd90111bf02d2f549b067f4c4a8fa183b57a0f800cb010000008a4730440220177c37f9a505c3f1a1f0ce2da777c339bd8339ffa02c7cb41f0a5804f473c9230220585b25a2ee80eb59292e52b987dad92acb0c64eced92ed9ee105ad153cdb12d001410443bd44f683467e549dae7d20d1d79cbdb6df985c6e9c029c8d0c6cb46cc1a4d3cf7923c5021b27f7a0b562ada113bc85d5fda5a1b41e87fe6e8802817cf69996ffffffff0280651406000000001976a9145505614859643ab7b547cd7f1f5e7e2a12322d3788ac00aa0271000000001976a914ea4720a7a52fc166c55ff2298e07baf70ae67e1b88ac00000000010000000586c62cd602d219bb60edb14a3e204de0705176f9022fe49a538054fb14abb49e010000008c493046022100f2bc2aba2534becbdf062eb993853a42bbbc282083d0daf9b4b585bd401aa8c9022100b1d7fd7ee0b95600db8535bbf331b19eed8d961f7a8e54159c53675d5f69df8c014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffff03ad0e58ccdac3df9dc28a218bcf6f1997b0a93306faaa4b3a28ae83447b2179010000008b483045022100be12b2937179da88599e27bb31c3525097a07cdb52422d165b3ca2f2020ffcf702200971b51f853a53d644ebae9ec8f3512e442b1bcb6c315a5b491d119d10624c83014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffff2acfcab629bbc8685792603762c921580030ba144af553d271716a95089e107b010000008b483045022100fa579a840ac258871365dd48cd7552f96c8eea69bd00d84f05b283a0dab311e102207e3c0ee9234814cfbb1b659b83671618f45abc1326b9edcc77d552a4f2a805c0014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffffdcdc6023bbc9944a658ddc588e61eacb737ddf0a3cd24f113b5a8634c517fcd2000000008b4830450221008d6df731df5d32267954bd7d2dda2302b74c6c2a6aa5c0ca64ecbabc1af03c75022010e55c571d65da7701ae2da1956c442df81bbf076cdbac25133f99d98a9ed34c014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffffe15557cd5ce258f479dfd6dc6514edf6d7ed5b21fcfa4a038fd69f06b83ac76e010000008b483045022023b3e0ab071eb11de2eb1cc3a67261b866f86bf6867d4558165f7c8c8aca2d86022100dc6e1f53a91de3efe8f63512850811f26284b62f850c70ca73ed5de8771fb451014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffff01404b4c00000000001976a9142b6ba7c9d796b75eef7942fc9288edd37c32f5c388ac00000000010000000166d7577163c932b4f9690ca6a80b6e4eb001f0a2fa9023df5595602aae96ed8d000000008a4730440220262b42546302dfb654a229cefc86432b89628ff259dc87edd1154535b16a67e102207b4634c020a97c3e7bbd0d4d19da6aa2269ad9dded4026e896b213d73ca4b63f014104979b82d02226b3a4597523845754d44f13639e3bf2df5e82c6aab2bdc79687368b01b1ab8b19875ae3c90d661a3d0a33161dab29934edeb36aa01976be3baf8affffffff02404b4c00000000001976a9144854e695a02af0aeacb823ccbc272134561e0a1688ac40420f00000000001976a914abee93376d6b37b5c2940655a6fcaf1c8e74237988ac0000000001000000014e3f8ef2e91349a9059cb4f01e54ab2597c1387161d3da89919f7ea6acdbb371010000008c49304602210081f3183471a5ca22307c0800226f3ef9c353069e0773ac76bb580654d56aa523022100d4c56465bdc069060846f4fbf2f6b20520b2a80b08b168b31e66ddb9c694e240014104976c79848e18251612f8940875b2b08d06e6dc73b9840e8860c066b7e87432c477e9a59a453e71e6d76d5fe34058b800a098fc1740ce3012e8fc8a00c96af966ffffffff02c0e1e400000000001976a9144134e75a6fcb6042034aab5e18570cf1f844f54788ac404b4c00000000001976a9142b6ba7c9d796b75eef7942fc9288edd37c32f5c388ac00000000"), SER_NETWORK, PROTOCOL_VERSION);
- stream >> block;
-
+ CBlock block = getBlock13b8a();
CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
// Match the last transaction
filter.insert(uint256S("0x74d681e0e03bafa802c8aa084379aa98d9fcd632ddc2ed9782b586ec87451f20"));
CMerkleBlock merkleBlock(block, filter);
- BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash());
+ BOOST_CHECK_EQUAL(merkleBlock.header.GetHash().GetHex(), block.GetHash().GetHex());
- BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 1);
+ BOOST_CHECK_EQUAL(merkleBlock.vMatchedTxn.size(), 1);
std::pair<unsigned int, uint256> pair = merkleBlock.vMatchedTxn[0];
BOOST_CHECK(merkleBlock.vMatchedTxn[0].second == uint256S("0x74d681e0e03bafa802c8aa084379aa98d9fcd632ddc2ed9782b586ec87451f20"));
diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp
index 251d5a7142..efddafe17e 100644
--- a/src/test/dbwrapper_tests.cpp
+++ b/src/test/dbwrapper_tests.cpp
@@ -204,19 +204,31 @@ BOOST_AUTO_TEST_CASE(iterator_ordering)
for (int x=0x00; x<256; ++x) {
uint8_t key = x;
uint32_t value = x*x;
- BOOST_CHECK(dbw.Write(key, value));
+ if (!(x & 1)) BOOST_CHECK(dbw.Write(key, value));
}
+ // Check that creating an iterator creates a snapshot
std::unique_ptr<CDBIterator> it(const_cast<CDBWrapper&>(dbw).NewIterator());
+
+ for (int x=0x00; x<256; ++x) {
+ uint8_t key = x;
+ uint32_t value = x*x;
+ if (x & 1) BOOST_CHECK(dbw.Write(key, value));
+ }
+
for (int seek_start : {0x00, 0x80}) {
it->Seek((uint8_t)seek_start);
- for (int x=seek_start; x<256; ++x) {
+ for (int x=seek_start; x<255; ++x) {
uint8_t key;
uint32_t value;
BOOST_CHECK(it->Valid());
if (!it->Valid()) // Avoid spurious errors about invalid iterator's key and value in case of failure
break;
BOOST_CHECK(it->GetKey(key));
+ if (x & 1) {
+ BOOST_CHECK_EQUAL(key, x + 1);
+ continue;
+ }
BOOST_CHECK(it->GetValue(value));
BOOST_CHECK_EQUAL(key, x);
BOOST_CHECK_EQUAL(value, x*x);
diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp
index 51b28d09fa..116210a297 100644
--- a/src/test/mempool_tests.cpp
+++ b/src/test/mempool_tests.cpp
@@ -559,15 +559,15 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
// ... we should keep the same min fee until we get a block
pool.removeForBlock(vtx, 1);
SetMockTime(42 + 2*CTxMemPool::ROLLING_FEE_HALFLIFE);
- BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), (maxFeeRateRemoved.GetFeePerK() + 1000)/2);
+ BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), llround((maxFeeRateRemoved.GetFeePerK() + 1000)/2.0));
// ... then feerate should drop 1/2 each halflife
SetMockTime(42 + 2*CTxMemPool::ROLLING_FEE_HALFLIFE + CTxMemPool::ROLLING_FEE_HALFLIFE/2);
- BOOST_CHECK_EQUAL(pool.GetMinFee(pool.DynamicMemoryUsage() * 5 / 2).GetFeePerK(), (maxFeeRateRemoved.GetFeePerK() + 1000)/4);
+ BOOST_CHECK_EQUAL(pool.GetMinFee(pool.DynamicMemoryUsage() * 5 / 2).GetFeePerK(), llround((maxFeeRateRemoved.GetFeePerK() + 1000)/4.0));
// ... with a 1/2 halflife when mempool is < 1/2 its target size
SetMockTime(42 + 2*CTxMemPool::ROLLING_FEE_HALFLIFE + CTxMemPool::ROLLING_FEE_HALFLIFE/2 + CTxMemPool::ROLLING_FEE_HALFLIFE/4);
- BOOST_CHECK_EQUAL(pool.GetMinFee(pool.DynamicMemoryUsage() * 9 / 2).GetFeePerK(), (maxFeeRateRemoved.GetFeePerK() + 1000)/8);
+ BOOST_CHECK_EQUAL(pool.GetMinFee(pool.DynamicMemoryUsage() * 9 / 2).GetFeePerK(), llround((maxFeeRateRemoved.GetFeePerK() + 1000)/8.0));
// ... with a 1/4 halflife when mempool is < 1/4 its target size
SetMockTime(42 + 7*CTxMemPool::ROLLING_FEE_HALFLIFE + CTxMemPool::ROLLING_FEE_HALFLIFE/2 + CTxMemPool::ROLLING_FEE_HALFLIFE/4);
diff --git a/src/test/merkleblock_tests.cpp b/src/test/merkleblock_tests.cpp
new file mode 100644
index 0000000000..3e66c6f2c6
--- /dev/null
+++ b/src/test/merkleblock_tests.cpp
@@ -0,0 +1,78 @@
+// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "merkleblock.h"
+#include "uint256.h"
+#include "test/test_bitcoin.h"
+
+#include <boost/test/unit_test.hpp>
+
+
+BOOST_FIXTURE_TEST_SUITE(merkleblock_tests, BasicTestingSetup)
+
+/**
+ * Create a CMerkleBlock using a list of txids which will be found in the
+ * given block.
+ */
+BOOST_AUTO_TEST_CASE(merkleblock_construct_from_txids_found)
+{
+ CBlock block = getBlock13b8a();
+
+ std::set<uint256> txids;
+
+ // Last txn in block.
+ uint256 txhash1 = uint256S("0x74d681e0e03bafa802c8aa084379aa98d9fcd632ddc2ed9782b586ec87451f20");
+
+ // Second txn in block.
+ uint256 txhash2 = uint256S("0xf9fc751cb7dc372406a9f8d738d5e6f8f63bab71986a39cf36ee70ee17036d07");
+
+ txids.insert(txhash1);
+ txids.insert(txhash2);
+
+ CMerkleBlock merkleBlock(block, txids);
+
+ BOOST_CHECK_EQUAL(merkleBlock.header.GetHash().GetHex(), block.GetHash().GetHex());
+
+ // vMatchedTxn is only used when bloom filter is specified.
+ BOOST_CHECK_EQUAL(merkleBlock.vMatchedTxn.size(), 0);
+
+ std::vector<uint256> vMatched;
+ std::vector<unsigned int> vIndex;
+
+ BOOST_CHECK_EQUAL(merkleBlock.txn.ExtractMatches(vMatched, vIndex).GetHex(), block.hashMerkleRoot.GetHex());
+ BOOST_CHECK_EQUAL(vMatched.size(), 2);
+
+ // Ordered by occurrence in depth-first tree traversal.
+ BOOST_CHECK_EQUAL(vMatched[0].ToString(), txhash2.ToString());
+ BOOST_CHECK_EQUAL(vIndex[0], 1);
+
+ BOOST_CHECK_EQUAL(vMatched[1].ToString(), txhash1.ToString());
+ BOOST_CHECK_EQUAL(vIndex[1], 8);
+}
+
+
+/**
+ * Create a CMerkleBlock using a list of txids which will not be found in the
+ * given block.
+ */
+BOOST_AUTO_TEST_CASE(merkleblock_construct_from_txids_not_found)
+{
+ CBlock block = getBlock13b8a();
+
+ std::set<uint256> txids2;
+ txids2.insert(uint256S("0xc0ffee00003bafa802c8aa084379aa98d9fcd632ddc2ed9782b586ec87451f20"));
+ CMerkleBlock merkleBlock(block, txids2);
+
+ BOOST_CHECK_EQUAL(merkleBlock.header.GetHash().GetHex(), block.GetHash().GetHex());
+ BOOST_CHECK_EQUAL(merkleBlock.vMatchedTxn.size(), 0);
+
+ std::vector<uint256> vMatched;
+ std::vector<unsigned int> vIndex;
+
+ BOOST_CHECK_EQUAL(merkleBlock.txn.ExtractMatches(vMatched, vIndex).GetHex(), block.hashMerkleRoot.GetHex());
+ BOOST_CHECK_EQUAL(vMatched.size(), 0);
+ BOOST_CHECK_EQUAL(vIndex.size(), 0);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 17374edcc4..011a5db795 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -1451,4 +1451,21 @@ BOOST_AUTO_TEST_CASE(script_HasValidOps)
BOOST_CHECK(!script.HasValidOps());
}
+BOOST_AUTO_TEST_CASE(script_can_append_self)
+{
+ CScript s, d;
+
+ s = ScriptFromHex("00");
+ s += s;
+ d = ScriptFromHex("0000");
+ BOOST_CHECK(s == d);
+
+ // check doubling a script that's large enough to require reallocation
+ static const char hex[] = "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f";
+ s = CScript() << ParseHex(hex) << OP_CHECKSIG;
+ d = CScript() << ParseHex(hex) << OP_CHECKSIG << ParseHex(hex) << OP_CHECKSIG;
+ s += s;
+ BOOST_CHECK(s == d);
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index 045655983c..79bc48a118 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -18,6 +18,7 @@
#include "txdb.h"
#include "txmempool.h"
#include "ui_interface.h"
+#include "streams.h"
#include "rpc/server.h"
#include "rpc/register.h"
#include "script/sigcache.h"
@@ -158,3 +159,15 @@ CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CTransaction &txn) {
return CTxMemPoolEntry(MakeTransactionRef(txn), nFee, nTime, nHeight,
spendsCoinbase, sigOpCost, lp);
}
+
+/**
+ * @returns a real block (0000000000013b8ab2cd513b0261a14096412195a72a0c4827d229dcc7e0f7af)
+ * with 9 txs.
+ */
+CBlock getBlock13b8a()
+{
+ CBlock block;
+ CDataStream stream(ParseHex("0100000090f0a9f110702f808219ebea1173056042a714bad51b916cb6800000000000005275289558f51c9966699404ae2294730c3c9f9bda53523ce50e9b95e558da2fdb261b4d4c86041b1ab1bf930901000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07044c86041b0146ffffffff0100f2052a01000000434104e18f7afbe4721580e81e8414fc8c24d7cfacf254bb5c7b949450c3e997c2dc1242487a8169507b631eb3771f2b425483fb13102c4eb5d858eef260fe70fbfae0ac00000000010000000196608ccbafa16abada902780da4dc35dafd7af05fa0da08cf833575f8cf9e836000000004a493046022100dab24889213caf43ae6adc41cf1c9396c08240c199f5225acf45416330fd7dbd022100fe37900e0644bf574493a07fc5edba06dbc07c311b947520c2d514bc5725dcb401ffffffff0100f2052a010000001976a914f15d1921f52e4007b146dfa60f369ed2fc393ce288ac000000000100000001fb766c1288458c2bafcfec81e48b24d98ec706de6b8af7c4e3c29419bfacb56d000000008c493046022100f268ba165ce0ad2e6d93f089cfcd3785de5c963bb5ea6b8c1b23f1ce3e517b9f022100da7c0f21adc6c401887f2bfd1922f11d76159cbc597fbd756a23dcbb00f4d7290141042b4e8625a96127826915a5b109852636ad0da753c9e1d5606a50480cd0c40f1f8b8d898235e571fe9357d9ec842bc4bba1827daaf4de06d71844d0057707966affffffff0280969800000000001976a9146963907531db72d0ed1a0cfb471ccb63923446f388ac80d6e34c000000001976a914f0688ba1c0d1ce182c7af6741e02658c7d4dfcd388ac000000000100000002c40297f730dd7b5a99567eb8d27b78758f607507c52292d02d4031895b52f2ff010000008b483045022100f7edfd4b0aac404e5bab4fd3889e0c6c41aa8d0e6fa122316f68eddd0a65013902205b09cc8b2d56e1cd1f7f2fafd60a129ed94504c4ac7bdc67b56fe67512658b3e014104732012cb962afa90d31b25d8fb0e32c94e513ab7a17805c14ca4c3423e18b4fb5d0e676841733cb83abaf975845c9f6f2a8097b7d04f4908b18368d6fc2d68ecffffffffca5065ff9617cbcba45eb23726df6498a9b9cafed4f54cbab9d227b0035ddefb000000008a473044022068010362a13c7f9919fa832b2dee4e788f61f6f5d344a7c2a0da6ae740605658022006d1af525b9a14a35c003b78b72bd59738cd676f845d1ff3fc25049e01003614014104732012cb962afa90d31b25d8fb0e32c94e513ab7a17805c14ca4c3423e18b4fb5d0e676841733cb83abaf975845c9f6f2a8097b7d04f4908b18368d6fc2d68ecffffffff01001ec4110200000043410469ab4181eceb28985b9b4e895c13fa5e68d85761b7eee311db5addef76fa8621865134a221bd01f28ec9999ee3e021e60766e9d1f3458c115fb28650605f11c9ac000000000100000001cdaf2f758e91c514655e2dc50633d1e4c84989f8aa90a0dbc883f0d23ed5c2fa010000008b48304502207ab51be6f12a1962ba0aaaf24a20e0b69b27a94fac5adf45aa7d2d18ffd9236102210086ae728b370e5329eead9accd880d0cb070aea0c96255fae6c4f1ddcce1fd56e014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffff02404b4c00000000001976a9142b6ba7c9d796b75eef7942fc9288edd37c32f5c388ac002d3101000000001976a9141befba0cdc1ad56529371864d9f6cb042faa06b588ac000000000100000001b4a47603e71b61bc3326efd90111bf02d2f549b067f4c4a8fa183b57a0f800cb010000008a4730440220177c37f9a505c3f1a1f0ce2da777c339bd8339ffa02c7cb41f0a5804f473c9230220585b25a2ee80eb59292e52b987dad92acb0c64eced92ed9ee105ad153cdb12d001410443bd44f683467e549dae7d20d1d79cbdb6df985c6e9c029c8d0c6cb46cc1a4d3cf7923c5021b27f7a0b562ada113bc85d5fda5a1b41e87fe6e8802817cf69996ffffffff0280651406000000001976a9145505614859643ab7b547cd7f1f5e7e2a12322d3788ac00aa0271000000001976a914ea4720a7a52fc166c55ff2298e07baf70ae67e1b88ac00000000010000000586c62cd602d219bb60edb14a3e204de0705176f9022fe49a538054fb14abb49e010000008c493046022100f2bc2aba2534becbdf062eb993853a42bbbc282083d0daf9b4b585bd401aa8c9022100b1d7fd7ee0b95600db8535bbf331b19eed8d961f7a8e54159c53675d5f69df8c014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffff03ad0e58ccdac3df9dc28a218bcf6f1997b0a93306faaa4b3a28ae83447b2179010000008b483045022100be12b2937179da88599e27bb31c3525097a07cdb52422d165b3ca2f2020ffcf702200971b51f853a53d644ebae9ec8f3512e442b1bcb6c315a5b491d119d10624c83014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffff2acfcab629bbc8685792603762c921580030ba144af553d271716a95089e107b010000008b483045022100fa579a840ac258871365dd48cd7552f96c8eea69bd00d84f05b283a0dab311e102207e3c0ee9234814cfbb1b659b83671618f45abc1326b9edcc77d552a4f2a805c0014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffffdcdc6023bbc9944a658ddc588e61eacb737ddf0a3cd24f113b5a8634c517fcd2000000008b4830450221008d6df731df5d32267954bd7d2dda2302b74c6c2a6aa5c0ca64ecbabc1af03c75022010e55c571d65da7701ae2da1956c442df81bbf076cdbac25133f99d98a9ed34c014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffffe15557cd5ce258f479dfd6dc6514edf6d7ed5b21fcfa4a038fd69f06b83ac76e010000008b483045022023b3e0ab071eb11de2eb1cc3a67261b866f86bf6867d4558165f7c8c8aca2d86022100dc6e1f53a91de3efe8f63512850811f26284b62f850c70ca73ed5de8771fb451014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffff01404b4c00000000001976a9142b6ba7c9d796b75eef7942fc9288edd37c32f5c388ac00000000010000000166d7577163c932b4f9690ca6a80b6e4eb001f0a2fa9023df5595602aae96ed8d000000008a4730440220262b42546302dfb654a229cefc86432b89628ff259dc87edd1154535b16a67e102207b4634c020a97c3e7bbd0d4d19da6aa2269ad9dded4026e896b213d73ca4b63f014104979b82d02226b3a4597523845754d44f13639e3bf2df5e82c6aab2bdc79687368b01b1ab8b19875ae3c90d661a3d0a33161dab29934edeb36aa01976be3baf8affffffff02404b4c00000000001976a9144854e695a02af0aeacb823ccbc272134561e0a1688ac40420f00000000001976a914abee93376d6b37b5c2940655a6fcaf1c8e74237988ac0000000001000000014e3f8ef2e91349a9059cb4f01e54ab2597c1387161d3da89919f7ea6acdbb371010000008c49304602210081f3183471a5ca22307c0800226f3ef9c353069e0773ac76bb580654d56aa523022100d4c56465bdc069060846f4fbf2f6b20520b2a80b08b168b31e66ddb9c694e240014104976c79848e18251612f8940875b2b08d06e6dc73b9840e8860c066b7e87432c477e9a59a453e71e6d76d5fe34058b800a098fc1740ce3012e8fc8a00c96af966ffffffff02c0e1e400000000001976a9144134e75a6fcb6042034aab5e18570cf1f844f54788ac404b4c00000000001976a9142b6ba7c9d796b75eef7942fc9288edd37c32f5c388ac00000000"), SER_NETWORK, PROTOCOL_VERSION);
+ stream >> block;
+ return block;
+}
diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h
index 6ada96f887..2390aca342 100644
--- a/src/test/test_bitcoin.h
+++ b/src/test/test_bitcoin.h
@@ -99,7 +99,7 @@ struct TestMemPoolEntryHelper
TestMemPoolEntryHelper() :
nFee(0), nTime(0), nHeight(1),
spendsCoinbase(false), sigOpCost(4) { }
-
+
CTxMemPoolEntry FromTx(const CMutableTransaction &tx);
CTxMemPoolEntry FromTx(const CTransaction &tx);
@@ -110,4 +110,7 @@ struct TestMemPoolEntryHelper
TestMemPoolEntryHelper &SpendsCoinbase(bool _flag) { spendsCoinbase = _flag; return *this; }
TestMemPoolEntryHelper &SigOpsCost(unsigned int _sigopsCost) { sigOpCost = _sigopsCost; return *this; }
};
+
+CBlock getBlock13b8a();
+
#endif
diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp
index 2d25cb96c8..82ca93e7da 100644
--- a/src/test/txvalidationcache_tests.cpp
+++ b/src/test/txvalidationcache_tests.cpp
@@ -29,7 +29,8 @@ ToMemPool(CMutableTransaction& tx)
LOCK(cs_main);
CValidationState state;
- return AcceptToMemoryPool(mempool, state, MakeTransactionRef(tx), false, nullptr, nullptr, true, 0);
+ return AcceptToMemoryPool(mempool, state, MakeTransactionRef(tx), nullptr /* pfMissingInputs */,
+ nullptr /* plTxnReplaced */, true /* bypass_limits */, 0 /* nAbsurdFee */);
}
BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index f68d677646..776d3f36ca 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -981,7 +981,7 @@ const CTxMemPool::setEntries & CTxMemPool::GetMemPoolChildren(txiter entry) cons
CFeeRate CTxMemPool::GetMinFee(size_t sizelimit) const {
LOCK(cs);
if (!blockSinceLastRollingFeeBump || rollingMinimumFeeRate == 0)
- return CFeeRate(rollingMinimumFeeRate);
+ return CFeeRate(llround(rollingMinimumFeeRate));
int64_t time = GetTime();
if (time > lastRollingFeeUpdate + 10) {
@@ -999,7 +999,7 @@ CFeeRate CTxMemPool::GetMinFee(size_t sizelimit) const {
return CFeeRate(0);
}
}
- return std::max(CFeeRate(rollingMinimumFeeRate), incrementalRelayFee);
+ return std::max(CFeeRate(llround(rollingMinimumFeeRate)), incrementalRelayFee);
}
void CTxMemPool::trackPackageRemoved(const CFeeRate& rate) {
diff --git a/src/txmempool.h b/src/txmempool.h
index b07886579c..929d223588 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -507,7 +507,7 @@ public:
* check does nothing.
*/
void check(const CCoinsViewCache *pcoins) const;
- void setSanityCheck(double dFrequency = 1.0) { nCheckFrequency = dFrequency * 4294967295.0; }
+ void setSanityCheck(double dFrequency = 1.0) { nCheckFrequency = static_cast<uint32_t>(dFrequency * 4294967295.0); }
// addUnchecked must updated state for all ancestors of a given transaction,
// to track size/count of descendant transactions. First version of
diff --git a/src/validation.cpp b/src/validation.cpp
index bd9640e749..a958afe84f 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -384,7 +384,9 @@ void UpdateMempoolForReorg(DisconnectedBlockTransactions &disconnectpool, bool f
while (it != disconnectpool.queuedTx.get<insertion_order>().rend()) {
// ignore validation errors in resurrected transactions
CValidationState stateDummy;
- if (!fAddToMempool || (*it)->IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, *it, false, nullptr, nullptr, true)) {
+ if (!fAddToMempool || (*it)->IsCoinBase() ||
+ !AcceptToMemoryPool(mempool, stateDummy, *it, nullptr /* pfMissingInputs */,
+ nullptr /* plTxnReplaced */, true /* bypass_limits */, 0 /* nAbsurdFee */)) {
// If the transaction doesn't make it in to the mempool, remove any
// transactions that depend on it (which would now be orphans).
mempool.removeRecursive(**it, MemPoolRemovalReason::REORG);
@@ -443,9 +445,9 @@ static bool CheckInputsFromMempoolAndCache(const CTransaction& tx, CValidationSt
return CheckInputs(tx, state, view, true, flags, cacheSigStore, true, txdata);
}
-static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool& pool, CValidationState& state, const CTransactionRef& ptx, bool fLimitFree,
+static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool& pool, CValidationState& state, const CTransactionRef& ptx,
bool* pfMissingInputs, int64_t nAcceptTime, std::list<CTransactionRef>* plTxnReplaced,
- bool fOverrideMempoolLimit, const CAmount& nAbsurdFee, std::vector<COutPoint>& coins_to_uncache)
+ bool bypass_limits, const CAmount& nAbsurdFee, std::vector<COutPoint>& coins_to_uncache)
{
const CTransaction& tx = *ptx;
const uint256 hash = tx.GetHash();
@@ -618,12 +620,12 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
strprintf("%d", nSigOpsCost));
CAmount mempoolRejectFee = pool.GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFee(nSize);
- if (mempoolRejectFee > 0 && nModifiedFees < mempoolRejectFee) {
+ if (!bypass_limits && mempoolRejectFee > 0 && nModifiedFees < mempoolRejectFee) {
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "mempool min fee not met", false, strprintf("%d < %d", nFees, mempoolRejectFee));
}
// No transactions are allowed below minRelayTxFee except from disconnected blocks
- if (fLimitFree && nModifiedFees < ::minRelayTxFee.GetFee(nSize)) {
+ if (!bypass_limits && nModifiedFees < ::minRelayTxFee.GetFee(nSize)) {
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "min relay fee not met");
}
@@ -855,17 +857,18 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
}
pool.RemoveStaged(allConflicting, false, MemPoolRemovalReason::REPLACED);
- // This transaction should only count for fee estimation if it isn't a
- // BIP 125 replacement transaction (may not be widely supported), the
- // node is not behind, and the transaction is not dependent on any other
- // transactions in the mempool.
- bool validForFeeEstimation = !fReplacementTransaction && IsCurrentForFeeEstimation() && pool.HasNoInputsOf(tx);
+ // This transaction should only count for fee estimation if:
+ // - it isn't a BIP 125 replacement transaction (may not be widely supported)
+ // - it's not being readded during a reorg which bypasses typical mempool fee limits
+ // - the node is not behind
+ // - the transaction is not dependent on any other transactions in the mempool
+ bool validForFeeEstimation = !fReplacementTransaction && !bypass_limits && IsCurrentForFeeEstimation() && pool.HasNoInputsOf(tx);
// Store transaction in memory
pool.addUnchecked(hash, entry, setAncestors, validForFeeEstimation);
// trim mempool and check if tx was trimmed
- if (!fOverrideMempoolLimit) {
+ if (!bypass_limits) {
LimitMempoolSize(pool, gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60);
if (!pool.exists(hash))
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "mempool full");
@@ -878,12 +881,12 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
}
/** (try to) add transaction to memory pool with a specified acceptance time **/
-static bool AcceptToMemoryPoolWithTime(const CChainParams& chainparams, CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree,
+static bool AcceptToMemoryPoolWithTime(const CChainParams& chainparams, CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx,
bool* pfMissingInputs, int64_t nAcceptTime, std::list<CTransactionRef>* plTxnReplaced,
- bool fOverrideMempoolLimit, const CAmount nAbsurdFee)
+ bool bypass_limits, const CAmount nAbsurdFee)
{
std::vector<COutPoint> coins_to_uncache;
- bool res = AcceptToMemoryPoolWorker(chainparams, pool, state, tx, fLimitFree, pfMissingInputs, nAcceptTime, plTxnReplaced, fOverrideMempoolLimit, nAbsurdFee, coins_to_uncache);
+ bool res = AcceptToMemoryPoolWorker(chainparams, pool, state, tx, pfMissingInputs, nAcceptTime, plTxnReplaced, bypass_limits, nAbsurdFee, coins_to_uncache);
if (!res) {
for (const COutPoint& hashTx : coins_to_uncache)
pcoinsTip->Uncache(hashTx);
@@ -894,12 +897,12 @@ static bool AcceptToMemoryPoolWithTime(const CChainParams& chainparams, CTxMemPo
return res;
}
-bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree,
+bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx,
bool* pfMissingInputs, std::list<CTransactionRef>* plTxnReplaced,
- bool fOverrideMempoolLimit, const CAmount nAbsurdFee)
+ bool bypass_limits, const CAmount nAbsurdFee)
{
const CChainParams& chainparams = Params();
- return AcceptToMemoryPoolWithTime(chainparams, pool, state, tx, fLimitFree, pfMissingInputs, GetTime(), plTxnReplaced, fOverrideMempoolLimit, nAbsurdFee);
+ return AcceptToMemoryPoolWithTime(chainparams, pool, state, tx, pfMissingInputs, GetTime(), plTxnReplaced, bypass_limits, nAbsurdFee);
}
/** Return transaction in txOut, and if it was found inside a block, its hash is placed in hashBlock */
@@ -4306,7 +4309,8 @@ bool LoadMempool(void)
CValidationState state;
if (nTime + nExpiryTimeout > nNow) {
LOCK(cs_main);
- AcceptToMemoryPoolWithTime(chainparams, mempool, state, tx, true, nullptr, nTime, nullptr, false, 0);
+ AcceptToMemoryPoolWithTime(chainparams, mempool, state, tx, nullptr /* pfMissingInputs */, nTime,
+ nullptr /* plTxnReplaced */, false /* bypass_limits */, 0 /* nAbsurdFee */);
if (state.IsValid()) {
++count;
} else {
diff --git a/src/validation.h b/src/validation.h
index bba621b84f..c7ef556b47 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -301,9 +301,9 @@ void PruneBlockFilesManual(int nManualPruneHeight);
/** (try to) add transaction to memory pool
* plTxnReplaced will be appended to with all transactions replaced from mempool **/
-bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree,
- bool* pfMissingInputs, std::list<CTransactionRef>* plTxnReplaced = nullptr,
- bool fOverrideMempoolLimit=false, const CAmount nAbsurdFee=0);
+bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx,
+ bool* pfMissingInputs, std::list<CTransactionRef>* plTxnReplaced,
+ bool bypass_limits, const CAmount nAbsurdFee);
/** Convert CValidationState to a human-readable message for logging */
std::string FormatStateMessage(const CValidationState &state);
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 6760d6ff84..f14278af3d 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -409,11 +409,11 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
{
int64_t nStartTime = GetTimeMillis();
crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
- pMasterKey.second.nDeriveIterations = pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime)));
+ pMasterKey.second.nDeriveIterations = static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime))));
nStartTime = GetTimeMillis();
crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
- pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
+ pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime)))) / 2;
if (pMasterKey.second.nDeriveIterations < 25000)
pMasterKey.second.nDeriveIterations = 25000;
@@ -615,11 +615,11 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
CCrypter crypter;
int64_t nStartTime = GetTimeMillis();
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
- kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime));
+ kMasterKey.nDeriveIterations = static_cast<unsigned int>(2500000 / ((double)(GetTimeMillis() - nStartTime)));
nStartTime = GetTimeMillis();
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
- kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
+ kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + static_cast<unsigned int>(kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime)))) / 2;
if (kMasterKey.nDeriveIterations < 25000)
kMasterKey.nDeriveIterations = 25000;
@@ -4047,5 +4047,6 @@ int CMerkleTx::GetBlocksToMaturity() const
bool CMerkleTx::AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& state)
{
- return ::AcceptToMemoryPool(mempool, state, tx, true, nullptr, nullptr, false, nAbsurdFee);
+ return ::AcceptToMemoryPool(mempool, state, tx, nullptr /* pfMissingInputs */,
+ nullptr /* plTxnReplaced */, false /* bypass_limits */, nAbsurdFee);
}
diff --git a/test/functional/bip68-sequence.py b/test/functional/bip68-sequence.py
index 3818287209..74f51d8cfb 100755
--- a/test/functional/bip68-sequence.py
+++ b/test/functional/bip68-sequence.py
@@ -369,11 +369,14 @@ class BIP68Test(BitcoinTestFramework):
def activateCSV(self):
# activation should happen at block height 432 (3 periods)
+ # getblockchaininfo will show CSV as active at block 431 (144 * 3 -1) since it's returning whether CSV is active for the next block.
min_activation_height = 432
height = self.nodes[0].getblockcount()
- assert(height < min_activation_height)
- self.nodes[0].generate(min_activation_height-height)
- assert(get_bip9_status(self.nodes[0], 'csv')['status'] == 'active')
+ assert_greater_than(min_activation_height - height, 2)
+ self.nodes[0].generate(min_activation_height - height - 2)
+ assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], "locked_in")
+ self.nodes[0].generate(1)
+ assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], "active")
sync_blocks(self.nodes)
# Use self.nodes[1] to test that version 2 transactions are standard.
diff --git a/test/functional/blockchain.py b/test/functional/blockchain.py
index c5967aa10b..5bd3bc8f83 100755
--- a/test/functional/blockchain.py
+++ b/test/functional/blockchain.py
@@ -81,6 +81,28 @@ class BlockchainTest(BitcoinTestFramework):
# we have to round because of binary math
assert_equal(round(chaintxstats['txrate'] * 600, 10), Decimal(1))
+ b1 = self.nodes[0].getblock(self.nodes[0].getblockhash(1))
+ b200 = self.nodes[0].getblock(self.nodes[0].getblockhash(200))
+ time_diff = b200['mediantime'] - b1['mediantime']
+
+ chaintxstats = self.nodes[0].getchaintxstats()
+ assert_equal(chaintxstats['time'], b200['time'])
+ assert_equal(chaintxstats['txcount'], 201)
+ assert_equal(chaintxstats['window_block_count'], 199)
+ assert_equal(chaintxstats['window_tx_count'], 199)
+ assert_equal(chaintxstats['window_interval'], time_diff)
+ assert_equal(round(chaintxstats['txrate'] * time_diff, 10), Decimal(199))
+
+ chaintxstats = self.nodes[0].getchaintxstats(blockhash=b1['hash'])
+ assert_equal(chaintxstats['time'], b1['time'])
+ assert_equal(chaintxstats['txcount'], 2)
+ assert_equal(chaintxstats['window_block_count'], 0)
+ assert('window_tx_count' not in chaintxstats)
+ assert('window_interval' not in chaintxstats)
+ assert('txrate' not in chaintxstats)
+
+ assert_raises_jsonrpc(-8, "Invalid block count: should be between 0 and the block's height - 1", self.nodes[0].getchaintxstats, 201)
+
def _test_gettxoutsetinfo(self):
node = self.nodes[0]
res = node.gettxoutsetinfo()
diff --git a/test/functional/p2p-segwit.py b/test/functional/p2p-segwit.py
index 943bc2c6d2..a9ef47559b 100755
--- a/test/functional/p2p-segwit.py
+++ b/test/functional/p2p-segwit.py
@@ -32,8 +32,8 @@ def get_virtual_size(witness_block):
return vsize
class TestNode(NodeConnCB):
- def set_test_params(self):
- self.num_nodes = 3
+ def __init__(self):
+ super().__init__()
self.getdataset = set()
def on_getdata(self, conn, message):
diff --git a/test/functional/replace-by-fee.py b/test/functional/replace-by-fee.py
index 1d6494fe41..75f3d77c13 100755
--- a/test/functional/replace-by-fee.py
+++ b/test/functional/replace-by-fee.py
@@ -62,13 +62,14 @@ def make_utxo(node, amount, confirmed=True, scriptPubKey=CScript([1])):
class ReplaceByFeeTest(BitcoinTestFramework):
def set_test_params(self):
- self.num_nodes = 1
+ self.num_nodes = 2
self.extra_args= [["-maxorphantx=1000",
"-whitelist=127.0.0.1",
"-limitancestorcount=50",
"-limitancestorsize=101",
"-limitdescendantcount=200",
- "-limitdescendantsize=101"]]
+ "-limitdescendantsize=101"],
+ ["-mempoolreplacement=0"]]
def run_test(self):
make_utxo(self.nodes[0], 1*COIN)
@@ -115,6 +116,8 @@ class ReplaceByFeeTest(BitcoinTestFramework):
tx1a_hex = txToHex(tx1a)
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
+ self.sync_all([self.nodes])
+
# Should fail because we haven't changed the fee
tx1b = CTransaction()
tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
@@ -123,12 +126,17 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# This will raise an exception due to insufficient fee
assert_raises_jsonrpc(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx1b_hex, True)
+ # This will raise an exception due to transaction replacement being disabled
+ assert_raises_jsonrpc(-26, "txn-mempool-conflict", self.nodes[1].sendrawtransaction, tx1b_hex, True)
# Extra 0.1 BTC fee
tx1b = CTransaction()
tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
tx1b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))]
tx1b_hex = txToHex(tx1b)
+ # Replacement still disabled even with "enough fee"
+ assert_raises_jsonrpc(-26, "txn-mempool-conflict", self.nodes[1].sendrawtransaction, tx1b_hex, True)
+ # Works when enabled
tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
mempool = self.nodes[0].getrawmempool()
@@ -138,6 +146,11 @@ class ReplaceByFeeTest(BitcoinTestFramework):
assert_equal(tx1b_hex, self.nodes[0].getrawtransaction(tx1b_txid))
+ # Second node is running mempoolreplacement=0, will not replace originally-seen txn
+ mempool = self.nodes[1].getrawmempool()
+ assert tx1a_txid in mempool
+ assert tx1b_txid not in mempool
+
def test_doublespend_chain(self):
"""Doublespend of a long chain"""
diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py
index abed661f37..d072969d7f 100755
--- a/test/functional/test_framework/mininode.py
+++ b/test/functional/test_framework/mininode.py
@@ -1502,6 +1502,7 @@ class NodeConnCB(object):
except:
print("ERROR delivering %s (%s)" % (repr(message),
sys.exc_info()[0]))
+ raise
def get_deliver_sleep_time(self):
with mininode_lock:
@@ -1702,13 +1703,10 @@ class NodeConn(asyncore.dispatcher):
self.cb.on_close(self)
def handle_read(self):
- try:
- t = self.recv(8192)
- if len(t) > 0:
- self.recvbuf += t
- self.got_data()
- except:
- pass
+ t = self.recv(8192)
+ if len(t) > 0:
+ self.recvbuf += t
+ self.got_data()
def readable(self):
return True
@@ -1774,8 +1772,10 @@ class NodeConn(asyncore.dispatcher):
self.got_message(t)
else:
logger.warning("Received unknown command from %s:%d: '%s' %s" % (self.dstaddr, self.dstport, command, repr(msg)))
+ raise ValueError("Unknown command: '%s'" % (command))
except Exception as e:
logger.exception('got_data:', repr(e))
+ raise
def send_message(self, message, pushbuf=False):
if self.state != "connected" and not pushbuf:
diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py
index b2d8199d12..64966adb97 100644
--- a/test/functional/test_framework/util.py
+++ b/test/functional/test_framework/util.py
@@ -7,6 +7,7 @@
from base64 import b64encode
from binascii import hexlify, unhexlify
from decimal import Decimal, ROUND_DOWN
+import hashlib
import json
import logging
import os
@@ -173,6 +174,13 @@ def count_bytes(hex_string):
def bytes_to_hex_str(byte_str):
return hexlify(byte_str).decode('ascii')
+def hash256(byte_str):
+ sha256 = hashlib.sha256()
+ sha256.update(byte_str)
+ sha256d = hashlib.sha256()
+ sha256d.update(sha256.digest())
+ return sha256d.digest()[::-1]
+
def hex_str_to_bytes(hex_str):
return unhexlify(hex_str.encode('ascii'))
diff --git a/test/functional/zmq_test.py b/test/functional/zmq_test.py
index 3f2668ee87..382ef5bae2 100755
--- a/test/functional/zmq_test.py
+++ b/test/functional/zmq_test.py
@@ -10,7 +10,8 @@ import struct
from test_framework.test_framework import BitcoinTestFramework, SkipTest
from test_framework.util import (assert_equal,
bytes_to_hex_str,
- )
+ hash256,
+ )
class ZMQTest (BitcoinTestFramework):
def set_test_params(self):
@@ -37,9 +38,12 @@ class ZMQTest (BitcoinTestFramework):
self.zmqSubSocket.set(zmq.RCVTIMEO, 60000)
self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashblock")
self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashtx")
+ self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"rawblock")
+ self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"rawtx")
ip_address = "tcp://127.0.0.1:28332"
self.zmqSubSocket.connect(ip_address)
- self.extra_args = [['-zmqpubhashtx=%s' % ip_address, '-zmqpubhashblock=%s' % ip_address], []]
+ self.extra_args = [['-zmqpubhashblock=%s' % ip_address, '-zmqpubhashtx=%s' % ip_address,
+ '-zmqpubrawblock=%s' % ip_address, '-zmqpubrawtx=%s' % ip_address], []]
self.add_nodes(self.num_nodes, self.extra_args)
self.start_nodes()
@@ -59,28 +63,51 @@ class ZMQTest (BitcoinTestFramework):
msg = self.zmqSubSocket.recv_multipart()
topic = msg[0]
assert_equal(topic, b"hashtx")
- body = msg[1]
+ txhash = msg[1]
msgSequence = struct.unpack('<I', msg[-1])[-1]
assert_equal(msgSequence, 0) # must be sequence 0 on hashtx
+ # rawtx
+ msg = self.zmqSubSocket.recv_multipart()
+ topic = msg[0]
+ assert_equal(topic, b"rawtx")
+ body = msg[1]
+ msgSequence = struct.unpack('<I', msg[-1])[-1]
+ assert_equal(msgSequence, 0) # must be sequence 0 on rawtx
+
+ # Check that the rawtx hashes to the hashtx
+ assert_equal(hash256(body), txhash)
+
self.log.info("Wait for block")
msg = self.zmqSubSocket.recv_multipart()
topic = msg[0]
+ assert_equal(topic, b"hashblock")
body = msg[1]
msgSequence = struct.unpack('<I', msg[-1])[-1]
assert_equal(msgSequence, 0) # must be sequence 0 on hashblock
blkhash = bytes_to_hex_str(body)
-
assert_equal(genhashes[0], blkhash) # blockhash from generate must be equal to the hash received over zmq
+ # rawblock
+ msg = self.zmqSubSocket.recv_multipart()
+ topic = msg[0]
+ assert_equal(topic, b"rawblock")
+ body = msg[1]
+ msgSequence = struct.unpack('<I', msg[-1])[-1]
+ assert_equal(msgSequence, 0) #must be sequence 0 on rawblock
+
+ # Check the hash of the rawblock's header matches generate
+ assert_equal(genhashes[0], bytes_to_hex_str(hash256(body[:80])))
+
self.log.info("Generate 10 blocks (and 10 coinbase txes)")
n = 10
genhashes = self.nodes[1].generate(n)
self.sync_all()
zmqHashes = []
+ zmqRawHashed = []
blockcount = 0
- for x in range(n * 2):
+ for x in range(n * 4):
msg = self.zmqSubSocket.recv_multipart()
topic = msg[0]
body = msg[1]
@@ -89,9 +116,14 @@ class ZMQTest (BitcoinTestFramework):
msgSequence = struct.unpack('<I', msg[-1])[-1]
assert_equal(msgSequence, blockcount + 1)
blockcount += 1
+ if topic == b"rawblock":
+ zmqRawHashed.append(bytes_to_hex_str(hash256(body[:80])))
+ msgSequence = struct.unpack('<I', msg[-1])[-1]
+ assert_equal(msgSequence, blockcount)
for x in range(n):
assert_equal(genhashes[x], zmqHashes[x]) # blockhash from generate must be equal to the hash received over zmq
+ assert_equal(genhashes[x], zmqRawHashed[x])
self.log.info("Wait for tx from second node")
# test tx from a second node
@@ -101,13 +133,21 @@ class ZMQTest (BitcoinTestFramework):
# now we should receive a zmq msg because the tx was broadcast
msg = self.zmqSubSocket.recv_multipart()
topic = msg[0]
- body = msg[1]
assert_equal(topic, b"hashtx")
+ body = msg[1]
hashZMQ = bytes_to_hex_str(body)
msgSequence = struct.unpack('<I', msg[-1])[-1]
assert_equal(msgSequence, blockcount + 1)
+ msg = self.zmqSubSocket.recv_multipart()
+ topic = msg[0]
+ assert_equal(topic, b"rawtx")
+ body = msg[1]
+ hashedZMQ = bytes_to_hex_str(hash256(body))
+ msgSequence = struct.unpack('<I', msg[-1])[-1]
+ assert_equal(msgSequence, blockcount+1)
assert_equal(hashRPC, hashZMQ) # txid from sendtoaddress must be equal to the hash received over zmq
+ assert_equal(hashRPC, hashedZMQ)
if __name__ == '__main__':
ZMQTest().main()
diff --git a/test/util/bitcoin-util-test.py b/test/util/bitcoin-util-test.py
index d15d6a6011..ef34955d90 100755
--- a/test/util/bitcoin-util-test.py
+++ b/test/util/bitcoin-util-test.py
@@ -9,9 +9,14 @@ Runs automatically during `make check`.
Can also be run manually."""
+from __future__ import division,print_function,unicode_literals
+
import argparse
import binascii
-import configparser
+try:
+ import configparser
+except ImportError:
+ import ConfigParser as configparser
import difflib
import json
import logging
@@ -22,7 +27,9 @@ import sys
def main():
config = configparser.ConfigParser()
- config.read_file(open(os.path.dirname(__file__) + "/../config.ini"))
+ config.optionxform = str
+ config.readfp(open(os.path.join(os.path.dirname(__file__), "../config.ini")))
+ env_conf = dict(config.items('environment'))
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('-v', '--verbose', action='store_true')
@@ -37,7 +44,7 @@ def main():
# Add the format/level to the logger
logging.basicConfig(format=formatter, level=level)
- bctester(config["environment"]["SRCDIR"] + "/test/util/data", "bitcoin-util-test.json", config["environment"])
+ bctester(os.path.join(env_conf["SRCDIR"], "test/util/data"), "bitcoin-util-test.json", env_conf)
def bctester(testDir, input_basename, buildenv):
""" Loads and parses the input file, runs all tests and reports results"""