[WIP] [wallet] keypool restore #10830

Closed
wants to merge 9 commits into
from
View
@@ -466,6 +466,8 @@ void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<con
// Make sure pindexBestKnownBlock is up to date, we'll need it.
ProcessBlockAvailability(nodeid);
+ if (isBlockRequestsPaused()) return;
+
if (state->pindexBestKnownBlock == NULL || state->pindexBestKnownBlock->nChainWork < chainActive.Tip()->nChainWork || state->pindexBestKnownBlock->nChainWork < UintToArith256(consensusParams.nMinimumChainWork)) {
// This peer has nothing interesting.
return;
@@ -730,7 +732,7 @@ PeerLogicValidation::PeerLogicValidation(CConnman* connmanIn) : connman(connmanI
recentRejects.reset(new CRollingBloomFilter(120000, 0.000001));
}
-void PeerLogicValidation::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindex, const std::vector<CTransactionRef>& vtxConflicted) {
+void PeerLogicValidation::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindex, const std::vector<CTransactionRef>& vtxConflicted, bool &requestPause) {
LOCK(cs_main);
std::vector<uint256> vOrphanErase;
View
@@ -34,7 +34,7 @@ class PeerLogicValidation : public CValidationInterface {
public:
PeerLogicValidation(CConnman* connmanIn);
- void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected, const std::vector<CTransactionRef>& vtxConflicted) override;
+ void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected, const std::vector<CTransactionRef>& vtxConflicted, bool &requestPause) override;
void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override;
void BlockChecked(const CBlock& block, const CValidationState& state) override;
void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr<const CBlock>& pblock) override;
View
@@ -93,6 +93,14 @@ CScript COINBASE_FLAGS;
const std::string strMessageMagic = "Bitcoin Signed Message:\n";
+/** if enable, blocks will not be requested automatically */
+static const bool DEFAULT_BLOCK_REQUESTS_PAUSED = false;
+std::atomic<bool> fPauseBlockRequests(DEFAULT_BLOCK_REQUESTS_PAUSED);
+
+/** if enable, ActiveBestChain will ignore/refuse to do tip updates */
+static const bool DEFAULT_TIP_UPDATE_PAUSED = false;
+std::atomic<bool> fPauseTipUpdates(DEFAULT_TIP_UPDATE_PAUSED);
+
// Internal stuff
namespace {
@@ -2417,6 +2425,12 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
// us in the middle of ProcessNewBlock - do not assume pblock is set
// sanely for performance or correctness!
+ if (isTipUpdatesPaused()) {
+ LogPrintf("%s: ignore ActivateBestChain, tip update are disabled\n", std::string(__func__));
+
+ // we will abort with a return value of true to not trigger error routines/shutdown
+ return true;
+ }
CBlockIndex *pindexMostWork = NULL;
CBlockIndex *pindexNewTip = NULL;
int nStopAtHeight = GetArg("-stopatheight", DEFAULT_STOPATHEIGHT);
@@ -2453,9 +2467,18 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
pindexFork = chainActive.FindFork(pindexOldTip);
fInitialDownload = IsInitialBlockDownload();
+ bool requestPause = false;
for (const PerBlockConnectTrace& trace : connectTrace.GetBlocksConnected()) {
assert(trace.pblock && trace.pindex);
- GetMainSignals().BlockConnected(trace.pblock, trace.pindex, *trace.conflictedTxs);
+ GetMainSignals().BlockConnected(trace.pblock, trace.pindex, *trace.conflictedTxs, requestPause);
+ if (requestPause) {
+ // in case we are in pruned mode, we have to halt verification and block requests
+ // to ensure the signal listener can keep up with the updates
+ if (fPruneMode) {
+ setBlockRequestsPaused(true);
+ setTipUpdatesPaused(true);
+ }
+ }
}
}
// When we reach this point, we switched to a new tip (stored in pindexNewTip).
@@ -2471,7 +2494,7 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
}
if (nStopAtHeight && pindexNewTip && pindexNewTip->nHeight >= nStopAtHeight) StartShutdown();
- } while (pindexNewTip != pindexMostWork);
+ } while (pindexNewTip != pindexMostWork && !isTipUpdatesPaused());
CheckBlockIndex(chainparams.GetConsensus());
// Write changes periodically to disk, after relay.
@@ -4353,6 +4376,24 @@ void DumpMempool(void)
}
}
+bool isBlockRequestsPaused() {
+ return fPauseBlockRequests;
+}
+
+void setBlockRequestsPaused(bool state) {
+ LogPrintf("%s Block Requests\n", (state ? "Pause" : "Resume"));
+ fPauseBlockRequests = state;
+}
+
+bool isTipUpdatesPaused() {
+ return fPauseTipUpdates;
+}
+
+void setTipUpdatesPaused(bool state) {
+ LogPrintf("%s Tip Updates\n", (state ? "Pause" : "Resume"));
+ fPauseTipUpdates = state;
+}
+
//! Guess how far we are in the verification process at the given block index
double GuessVerificationProgress(const ChainTxData& data, CBlockIndex *pindex) {
if (pindex == NULL)
View
@@ -286,6 +286,20 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams);
double GuessVerificationProgress(const ChainTxData& data, CBlockIndex* pindex);
/**
+ * Pausing block requests will temporarily pause the verification process.
+ * Pausing won't prevent ActivateBestChain from connecting blocks (that are in flight or already on disk)
+ */
+bool isBlockRequestsPaused();
+void setBlockRequestsPaused(bool state);
+
+/**
+ * Pausing tip updates temporarily pauses connecting new blocks
+ * Pausing won't prevent the net logic from requesting more blocks for download (up to BLOCK_DOWNLOAD_WINDOW)
+ */
+bool isTipUpdatesPaused();
+void setTipUpdatesPaused(bool state);
+
+/**
* Mark one block file as pruned.
*/
void PruneOneBlockFile(const int fileNumber);
@@ -17,7 +17,7 @@
struct MainSignalsInstance {
boost::signals2::signal<void (const CBlockIndex *, const CBlockIndex *, bool fInitialDownload)> UpdatedBlockTip;
boost::signals2::signal<void (const CTransactionRef &)> TransactionAddedToMempool;
- boost::signals2::signal<void (const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::vector<CTransactionRef>&)> BlockConnected;
+ boost::signals2::signal<void (const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::vector<CTransactionRef>&, bool &)> BlockConnected;
boost::signals2::signal<void (const std::shared_ptr<const CBlock> &)> BlockDisconnected;
boost::signals2::signal<void (const CBlockLocator &)> SetBestChain;
boost::signals2::signal<void (const uint256 &)> Inventory;
@@ -56,7 +56,7 @@ CMainSignals& GetMainSignals()
void RegisterValidationInterface(CValidationInterface* pwalletIn) {
g_signals.m_internals->UpdatedBlockTip.connect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3));
g_signals.m_internals->TransactionAddedToMempool.connect(boost::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1));
- g_signals.m_internals->BlockConnected.connect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3));
+ g_signals.m_internals->BlockConnected.connect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3, _4));
g_signals.m_internals->BlockDisconnected.connect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1));
g_signals.m_internals->SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
g_signals.m_internals->Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
@@ -71,7 +71,7 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
g_signals.m_internals->Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
g_signals.m_internals->SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
g_signals.m_internals->TransactionAddedToMempool.disconnect(boost::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1));
- g_signals.m_internals->BlockConnected.disconnect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3));
+ g_signals.m_internals->BlockConnected.disconnect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3, _4));
g_signals.m_internals->BlockDisconnected.disconnect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1));
g_signals.m_internals->UpdatedBlockTip.disconnect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3));
g_signals.m_internals->NewPoWValidBlock.disconnect(boost::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2));
@@ -97,8 +97,8 @@ void CMainSignals::TransactionAddedToMempool(const CTransactionRef &ptx) {
m_internals->TransactionAddedToMempool(ptx);
}
-void CMainSignals::BlockConnected(const std::shared_ptr<const CBlock> &pblock, const CBlockIndex *pindex, const std::vector<CTransactionRef>& vtxConflicted) {
- m_internals->BlockConnected(pblock, pindex, vtxConflicted);
+void CMainSignals::BlockConnected(const std::shared_ptr<const CBlock> &pblock, const CBlockIndex *pindex, const std::vector<CTransactionRef>& vtxConflicted, bool &requestPause) {
+ m_internals->BlockConnected(pblock, pindex, vtxConflicted, requestPause);
}
void CMainSignals::BlockDisconnected(const std::shared_ptr<const CBlock> &pblock) {
@@ -40,7 +40,7 @@ class CValidationInterface {
* Notifies listeners of a block being connected.
* Provides a vector of transactions evicted from the mempool as a result.
*/
- virtual void BlockConnected(const std::shared_ptr<const CBlock> &block, const CBlockIndex *pindex, const std::vector<CTransactionRef> &txnConflicted) {}
+ virtual void BlockConnected(const std::shared_ptr<const CBlock> &block, const CBlockIndex *pindex, const std::vector<CTransactionRef> &txnConflicted, bool &requestPause) {}
/** Notifies listeners of a block being disconnected */
virtual void BlockDisconnected(const std::shared_ptr<const CBlock> &block) {}
/** Notifies listeners of the new active block chain on-disk. */
@@ -84,7 +84,7 @@ class CMainSignals {
void UpdatedBlockTip(const CBlockIndex *, const CBlockIndex *, bool fInitialDownload);
void TransactionAddedToMempool(const CTransactionRef &);
- void BlockConnected(const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::vector<CTransactionRef> &);
+ void BlockConnected(const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::vector<CTransactionRef> &, bool &);
void BlockDisconnected(const std::shared_ptr<const CBlock> &);
void UpdatedTransaction(const uint256 &);
void SetBestChain(const CBlockLocator &);
View
@@ -2089,6 +2089,10 @@ UniValue walletpassphrase(const JSONRPCRequest& request)
pwallet->TopUpKeyPool();
+ // Give a hint to the wallet in case we have paused sync (we may have fall bellow the keypool min size limit).
+ // This runs synchronous, at least during the resync, we can be sure the keypool can be topped up.
+ pwallet->EventuallyRescanAfterKeypoolTopUp();
+
int64_t nSleepTime = request.params[1].get_int64();
pwallet->nRelockTime = GetTime() + nSleepTime;
RPCRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), boost::bind(LockWallet, pwallet), nSleepTime);
Oops, something went wrong.