aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/bitcoind.cpp6
-rw-r--r--src/chainparams.cpp1
-rw-r--r--src/policy/fees.cpp5
-rw-r--r--src/rpc/mining.cpp2
-rw-r--r--src/rpc/rawtransaction.cpp1
-rw-r--r--src/test/test_bitcoin.cpp4
-rw-r--r--src/txmempool.cpp4
-rw-r--r--src/txmempool.h2
-rw-r--r--src/validation.cpp11
-rw-r--r--src/validation.h10
-rw-r--r--src/wallet/rpcdump.cpp25
-rw-r--r--src/wallet/test/wallet_tests.cpp60
-rw-r--r--src/wallet/wallet.cpp23
-rw-r--r--src/wallet/wallet.h2
15 files changed, 128 insertions, 30 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index a2072865a3..e8d22313dc 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -5,7 +5,7 @@
DIST_SUBDIRS = secp256k1 univalue
AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) $(HARDENED_LDFLAGS)
-AM_CXXFLAGS = $(HARDENED_CXXFLAGS)
+AM_CXXFLAGS = $(HARDENED_CXXFLAGS) $(ERROR_CXXFLAGS)
AM_CPPFLAGS = $(HARDENED_CPPFLAGS)
EXTRA_LIBRARIES =
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index 9bab3a2026..a3d02afcdb 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -136,17 +136,17 @@ bool AppInit(int argc, char* argv[])
if (!AppInitBasicSetup())
{
// InitError will have been called with detailed error, which ends up on console
- exit(1);
+ exit(EXIT_FAILURE);
}
if (!AppInitParameterInteraction())
{
// InitError will have been called with detailed error, which ends up on console
- exit(1);
+ exit(EXIT_FAILURE);
}
if (!AppInitSanityChecks())
{
// InitError will have been called with detailed error, which ends up on console
- exit(1);
+ exit(EXIT_FAILURE);
}
if (GetBoolArg("-daemon", false))
{
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index 383d9849af..8c38558829 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -125,6 +125,7 @@ public:
vSeeds.push_back(CDNSSeedData("dashjr.org", "dnsseed.bitcoin.dashjr.org")); // Luke Dashjr
vSeeds.push_back(CDNSSeedData("bitcoinstats.com", "seed.bitcoinstats.com", true)); // Christian Decker, supports x1 - xf
vSeeds.push_back(CDNSSeedData("bitcoin.jonasschnelli.ch", "seed.bitcoin.jonasschnelli.ch", true)); // Jonas Schnelli, only supports x1, x5, x9, and xd
+ vSeeds.push_back(CDNSSeedData("petertodd.org", "seed.btc.petertodd.org", true)); // Peter Todd, only supports x1, x5, x9, and xd
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,0);
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,5);
diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp
index 5407aefb45..8f6a1e60f4 100644
--- a/src/policy/fees.cpp
+++ b/src/policy/fees.cpp
@@ -482,10 +482,7 @@ void CBlockPolicyEstimator::Read(CAutoFile& filein, int nFileVersion)
filein >> nFileBestSeenHeight;
feeStats.Read(filein);
nBestSeenHeight = nFileBestSeenHeight;
- if (nFileVersion < 139900) {
- TxConfirmStats priStats;
- priStats.Read(filein);
- }
+ // if nVersionThatWrote < 139900 then another TxConfirmStats (for priority) follows but can be ignored.
}
FeeFilterRounder::FeeFilterRounder(const CFeeRate& minIncrementalFee)
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 77cd282a3d..7708771d00 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -282,7 +282,7 @@ UniValue prioritisetransaction(const JSONRPCRequest& request)
uint256 hash = ParseHashStr(request.params[0].get_str(), "txid");
CAmount nAmount = request.params[2].get_int64();
- mempool.PrioritiseTransaction(hash, request.params[0].get_str(), request.params[1].get_real(), nAmount);
+ mempool.PrioritiseTransaction(hash, request.params[1].get_real(), nAmount);
return true;
}
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 21396ebb09..bf16f27498 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -245,7 +245,6 @@ UniValue gettxoutproof(const JSONRPCRequest& request)
"unspent output in the utxo for this transaction. To make it always work,\n"
"you need to maintain a transaction index, using the -txindex command line option or\n"
"specify the block in which the transaction is included manually (by blockhash).\n"
- "\nReturn the raw transaction data.\n"
"\nArguments:\n"
"1. \"txids\" (string) A json array of txids to filter\n"
" [\n"
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index 4785415e3c..51fc6ae0ba 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -156,12 +156,12 @@ CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CTransaction &txn, CTxMemPo
void Shutdown(void* parg)
{
- exit(0);
+ exit(EXIT_SUCCESS);
}
void StartShutdown()
{
- exit(0);
+ exit(EXIT_SUCCESS);
}
bool ShutdownRequested()
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 5842dd88d8..942a6fcce7 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -920,7 +920,7 @@ CTxMemPool::ReadFeeEstimates(CAutoFile& filein)
return true;
}
-void CTxMemPool::PrioritiseTransaction(const uint256 hash, const std::string strHash, double dPriorityDelta, const CAmount& nFeeDelta)
+void CTxMemPool::PrioritiseTransaction(const uint256& hash, double dPriorityDelta, const CAmount& nFeeDelta)
{
{
LOCK(cs);
@@ -940,7 +940,7 @@ void CTxMemPool::PrioritiseTransaction(const uint256 hash, const std::string str
}
}
}
- LogPrintf("PrioritiseTransaction: %s priority += %f, fee += %d\n", strHash, dPriorityDelta, FormatMoney(nFeeDelta));
+ LogPrintf("PrioritiseTransaction: %s priority += %f, fee += %d\n", hash.ToString(), dPriorityDelta, FormatMoney(nFeeDelta));
}
void CTxMemPool::ApplyDeltas(const uint256 hash, double &dPriorityDelta, CAmount &nFeeDelta) const
diff --git a/src/txmempool.h b/src/txmempool.h
index db1a02455f..a7ecb64390 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -555,7 +555,7 @@ public:
bool HasNoInputsOf(const CTransaction& tx) const;
/** Affect CreateNewBlock prioritisation of transactions */
- void PrioritiseTransaction(const uint256 hash, const std::string strHash, double dPriorityDelta, const CAmount& nFeeDelta);
+ void PrioritiseTransaction(const uint256& hash, double dPriorityDelta, const CAmount& nFeeDelta);
void ApplyDeltas(const uint256 hash, double &dPriorityDelta, CAmount &nFeeDelta) const;
void ClearPrioritisation(const uint256 hash);
diff --git a/src/validation.cpp b/src/validation.cpp
index cad1c9c160..e84b1a7281 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -3331,7 +3331,7 @@ void PruneOneBlockFile(const int fileNumber)
}
-void UnlinkPrunedFiles(std::set<int>& setFilesToPrune)
+void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune)
{
for (std::set<int>::iterator it = setFilesToPrune.begin(); it != setFilesToPrune.end(); ++it) {
CDiskBlockPos pos(*it, 0);
@@ -4163,6 +4163,11 @@ std::string CBlockFileInfo::ToString() const
return strprintf("CBlockFileInfo(blocks=%u, size=%u, heights=%u...%u, time=%s...%s)", nBlocks, nSize, nHeightFirst, nHeightLast, DateTimeStrFormat("%Y-%m-%d", nTimeFirst), DateTimeStrFormat("%Y-%m-%d", nTimeLast));
}
+CBlockFileInfo* GetBlockFileInfo(size_t n)
+{
+ return &vinfoBlockFile.at(n);
+}
+
ThresholdState VersionBitsTipState(const Consensus::Params& params, Consensus::DeploymentPos pos)
{
LOCK(cs_main);
@@ -4211,7 +4216,7 @@ bool LoadMempool(void)
CAmount amountdelta = nFeeDelta;
if (amountdelta) {
- mempool.PrioritiseTransaction(tx->GetHash(), tx->GetHash().ToString(), prioritydummy, amountdelta);
+ mempool.PrioritiseTransaction(tx->GetHash(), prioritydummy, amountdelta);
}
CValidationState state;
if (nTime + nExpiryTimeout > nNow) {
@@ -4232,7 +4237,7 @@ bool LoadMempool(void)
file >> mapDeltas;
for (const auto& i : mapDeltas) {
- mempool.PrioritiseTransaction(i.first, i.first.ToString(), prioritydummy, i.second);
+ mempool.PrioritiseTransaction(i.first, prioritydummy, i.second);
}
} catch (const std::exception& e) {
LogPrintf("Failed to deserialize mempool data on disk: %s. Continuing anyway.\n", e.what());
diff --git a/src/validation.h b/src/validation.h
index 6fcbb1c108..9c606f2419 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -300,9 +300,14 @@ double GuessVerificationProgress(const ChainTxData& data, CBlockIndex* pindex);
void FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfterHeight);
/**
+ * Mark one block file as pruned.
+ */
+void PruneOneBlockFile(const int fileNumber);
+
+/**
* Actually unlink the specified files
*/
-void UnlinkPrunedFiles(std::set<int>& setFilesToPrune);
+void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune);
/** Create a new block index entry for a given block hash */
CBlockIndex * InsertBlockIndex(uint256 hash);
@@ -562,6 +567,9 @@ static const unsigned int REJECT_ALREADY_KNOWN = 0x101;
/** Transaction conflicts with a transaction already known */
static const unsigned int REJECT_CONFLICT = 0x102;
+/** Get block file info entry for one block file */
+CBlockFileInfo* GetBlockFileInfo(size_t n);
+
/** Dump the mempool to disk. */
void DumpMempool();
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index e95c71ac8a..8a9e7d1444 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -1074,11 +1074,32 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
if (fRescan && fRunScan && requests.size()) {
CBlockIndex* pindex = nLowestTimestamp > minimumTimestamp ? chainActive.FindEarliestAtLeast(std::max<int64_t>(nLowestTimestamp - 7200, 0)) : chainActive.Genesis();
-
+ CBlockIndex* scannedRange = nullptr;
if (pindex) {
- pwalletMain->ScanForWalletTransactions(pindex, true);
+ scannedRange = pwalletMain->ScanForWalletTransactions(pindex, true);
pwalletMain->ReacceptWalletTransactions();
}
+
+ if (!scannedRange || scannedRange->nHeight > pindex->nHeight) {
+ std::vector<UniValue> results = response.getValues();
+ response.clear();
+ response.setArray();
+ size_t i = 0;
+ for (const UniValue& request : requests.getValues()) {
+ // If key creation date is within the successfully scanned
+ // range, or if the import result already has an error set, let
+ // the result stand unmodified. Otherwise replace the result
+ // with an error message.
+ if (GetImportTimestamp(request, now) - 7200 >= scannedRange->GetBlockTimeMax() || results.at(i).exists("error")) {
+ response.push_back(results.at(i));
+ } else {
+ UniValue result = UniValue(UniValue::VOBJ);
+ result.pushKV("success", UniValue(false));
+ result.pushKV("error", JSONRPCError(RPC_MISC_ERROR, strprintf("Failed to rescan before time %d, transactions may be missing.", scannedRange->GetBlockTimeMax())));
+ response.push_back(std::move(result));
+ }
+ }
+ }
}
return response;
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index ca086c86a8..d32e8ba06a 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -9,10 +9,16 @@
#include <utility>
#include <vector>
+#include "rpc/server.h"
+#include "test/test_bitcoin.h"
+#include "validation.h"
#include "wallet/test/wallet_test_fixture.h"
#include <boost/foreach.hpp>
#include <boost/test/unit_test.hpp>
+#include <univalue.h>
+
+extern UniValue importmulti(const JSONRPCRequest& request);
// how many times to run all the tests to have a chance to catch errors that only show up with particular random shuffles
#define RUN_TESTS 100
@@ -355,4 +361,58 @@ BOOST_AUTO_TEST_CASE(ApproximateBestSubset)
empty_wallet();
}
+BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
+{
+ LOCK(cs_main);
+
+ // Cap last block file size, and mine new block in a new block file.
+ CBlockIndex* oldTip = chainActive.Tip();
+ GetBlockFileInfo(oldTip->GetBlockPos().nFile)->nSize = MAX_BLOCKFILE_SIZE;
+ CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
+ CBlockIndex* newTip = chainActive.Tip();
+
+ // Verify ScanForWalletTransactions picks up transactions in both the old
+ // and new block files.
+ {
+ CWallet wallet;
+ LOCK(wallet.cs_wallet);
+ wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
+ BOOST_CHECK_EQUAL(oldTip, wallet.ScanForWalletTransactions(oldTip));
+ BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 100 * COIN);
+ }
+
+ // Prune the older block file.
+ PruneOneBlockFile(oldTip->GetBlockPos().nFile);
+ UnlinkPrunedFiles({oldTip->GetBlockPos().nFile});
+
+ // Verify ScanForWalletTransactions only picks transactions in the new block
+ // file.
+ {
+ CWallet wallet;
+ LOCK(wallet.cs_wallet);
+ wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
+ BOOST_CHECK_EQUAL(newTip, wallet.ScanForWalletTransactions(oldTip));
+ BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 50 * COIN);
+ }
+
+ {
+ CWallet wallet;
+ ::pwalletMain = &wallet;
+ UniValue key;
+ key.setObject();
+ key.pushKV("scriptPubKey", HexStr(GetScriptForRawPubKey(coinbaseKey.GetPubKey())));
+ key.pushKV("timestamp", 0);
+ key.pushKV("internal", UniValue(true));
+ UniValue keys;
+ keys.setArray();
+ keys.push_back(key);
+ JSONRPCRequest request;
+ request.params.setArray();
+ request.params.push_back(keys);
+
+ UniValue response = importmulti(request);
+ BOOST_CHECK_EQUAL(response.write(), strprintf("[{\"success\":false,\"error\":{\"code\":-1,\"message\":\"Failed to rescan before time %d, transactions may be missing.\"}}]", newTip->GetBlockTimeMax()));
+ }
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 8df15a060e..63501b04be 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -1545,10 +1545,14 @@ void CWalletTx::GetAccountAmounts(const string& strAccount, CAmount& nReceived,
* Scan the block chain (starting in pindexStart) for transactions
* from or to us. If fUpdate is true, found transactions that already
* exist in the wallet will be updated.
+ *
+ * Returns pointer to the first block in the last contiguous range that was
+ * successfully scanned.
+ *
*/
-int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
+CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
{
- int ret = 0;
+ CBlockIndex* ret = nullptr;
int64_t nNow = GetTime();
const CChainParams& chainParams = Params();
@@ -1570,12 +1574,15 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((GuessVerificationProgress(chainParams.TxData(), pindex) - dProgressStart) / (dProgressTip - dProgressStart) * 100))));
CBlock block;
- ReadBlockFromDisk(block, pindex, Params().GetConsensus());
- int posInBlock;
- for (posInBlock = 0; posInBlock < (int)block.vtx.size(); posInBlock++)
- {
- if (AddToWalletIfInvolvingMe(*block.vtx[posInBlock], pindex, posInBlock, fUpdate))
- ret++;
+ if (ReadBlockFromDisk(block, pindex, Params().GetConsensus())) {
+ for (size_t posInBlock = 0; posInBlock < block.vtx.size(); ++posInBlock) {
+ AddToWalletIfInvolvingMe(*block.vtx[posInBlock], pindex, posInBlock, fUpdate);
+ }
+ if (!ret) {
+ ret = pindex;
+ }
+ } else {
+ ret = nullptr;
}
pindex = chainActive.Next(pindex);
if (GetTime() >= nNow + 60) {
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index a7b15a8441..98e4fb87b9 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -788,7 +788,7 @@ public:
bool LoadToWallet(const CWalletTx& wtxIn);
void SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, int posInBlock) override;
bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate);
- int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
+ CBlockIndex* ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
void ReacceptWalletTransactions();
void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) override;
std::vector<uint256> ResendWalletTransactionsBefore(int64_t nTime, CConnman* connman);