Skip to content

Commit 5ee3172

Browse files
committed
Add CWallet::BlockUntilSyncedToCurrentChain()
This blocks until the wallet has synced up to the current height.
1 parent 0b2f42d commit 5ee3172

File tree

2 files changed

+57
-2
lines changed

2 files changed

+57
-2
lines changed

src/wallet/wallet.cpp

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "wallet/fees.h"
3434

3535
#include <assert.h>
36+
#include <future>
3637

3738
#include <boost/algorithm/string/replace.hpp>
3839
#include <boost/thread.hpp>
@@ -1232,6 +1233,8 @@ void CWallet::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const
12321233
for (size_t i = 0; i < pblock->vtx.size(); i++) {
12331234
SyncTransaction(pblock->vtx[i], pindex, i);
12341235
}
1236+
1237+
m_last_block_processed = pindex;
12351238
}
12361239

12371240
void CWallet::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock) {
@@ -1244,6 +1247,36 @@ void CWallet::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock) {
12441247

12451248

12461249

1250+
void CWallet::BlockUntilSyncedToCurrentChain() {
1251+
AssertLockNotHeld(cs_main);
1252+
AssertLockNotHeld(cs_wallet);
1253+
1254+
{
1255+
// Skip the queue-draining stuff if we know we're caught up with
1256+
// chainActive.Tip()...
1257+
// We could also take cs_wallet here, and call m_last_block_processed
1258+
// protected by cs_wallet instead of cs_main, but as long as we need
1259+
// cs_main here anyway, its easier to just call it cs_main-protected.
1260+
LOCK(cs_main);
1261+
const CBlockIndex* initialChainTip = chainActive.Tip();
1262+
1263+
if (m_last_block_processed->GetAncestor(initialChainTip->nHeight) == initialChainTip) {
1264+
return;
1265+
}
1266+
}
1267+
1268+
// ...otherwise put a callback in the validation interface queue and wait
1269+
// for the queue to drain enough to execute it (indicating we are caught up
1270+
// at least with the time we entered this function).
1271+
1272+
std::promise<void> promise;
1273+
CallFunctionInValidationInterfaceQueue([&promise] {
1274+
promise.set_value();
1275+
});
1276+
promise.get_future().wait();
1277+
}
1278+
1279+
12471280
isminetype CWallet::IsMine(const CTxIn &txin) const
12481281
{
12491282
{
@@ -3900,8 +3933,6 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile)
39003933

39013934
LogPrintf(" wallet %15dms\n", GetTimeMillis() - nStart);
39023935

3903-
RegisterValidationInterface(walletInstance);
3904-
39053936
// Try to top up keypool. No-op if the wallet is locked.
39063937
walletInstance->TopUpKeyPool();
39073938

@@ -3913,6 +3944,10 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile)
39133944
if (walletdb.ReadBestBlock(locator))
39143945
pindexRescan = FindForkInGlobalIndex(chainActive, locator);
39153946
}
3947+
3948+
walletInstance->m_last_block_processed = chainActive.Tip();
3949+
RegisterValidationInterface(walletInstance);
3950+
39163951
if (chainActive.Tip() && chainActive.Tip() != pindexRescan)
39173952
{
39183953
//We can't rescan beyond non-pruned blocks, stop and throw an error

src/wallet/wallet.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,18 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
722722

723723
std::unique_ptr<CWalletDBWrapper> dbw;
724724

725+
/**
726+
* The following is used to keep track of how far behind the wallet is
727+
* from the chain sync, and to allow clients to block on us being caught up.
728+
*
729+
* Note that this is *not* how far we've processed, we may need some rescan
730+
* to have seen all transactions in the chain, but is only used to track
731+
* live BlockConnected callbacks.
732+
*
733+
* Protected by cs_main (see BlockUntilSyncedToCurrentChain)
734+
*/
735+
const CBlockIndex* m_last_block_processed;
736+
725737
public:
726738
/*
727739
* Main wallet lock.
@@ -1106,6 +1118,14 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
11061118
caller must ensure the current wallet version is correct before calling
11071119
this function). */
11081120
bool SetHDMasterKey(const CPubKey& key);
1121+
1122+
/**
1123+
* Blocks until the wallet state is up-to-date to /at least/ the current
1124+
* chain at the time this function is entered
1125+
* Obviously holding cs_main/cs_wallet when going into this call may cause
1126+
* deadlock
1127+
*/
1128+
void BlockUntilSyncedToCurrentChain();
11091129
};
11101130

11111131
/** A key allocated from the key pool. */

0 commit comments

Comments
 (0)