Skip to content

Conversation

@jonasschnelli
Copy link
Contributor

@jonasschnelli jonasschnelli commented Apr 20, 2017

This PR ensures that we always check the keypool during SyncTransaction and, that the lookup window for HD restore is large enough (currently +20 keys).
Once the keypool size falls below the min gap limit (currently 20 keys) and the keypool can't be extended (locked wallet), the wallet then temporary pauses synchronisation.

unencrypted wallets

For unencrypted wallets, the key pool will always be topped up. During sync (SyncTransaction), we check for used keypool keys and mark all keys up to the matched key as used. Additionally we topup the keypool to ensure we not fall below the gap limit (20 keys).

encrypted wallets in non pruning mode

Same as above, but, If we hit the gap limit with an encrypted wallet, we can't topup the keypool. In that case, we just pause the sync (not the node, only the wallet).
Once the user unlocks the wallet over walletpassphrase, we rescan down to the point where we have stopped previously to ensure we don't miss possible funds.

encrypted wallets in pruned mode

Same as above, but, we also stop requesting and connecting blocks. The full node will "pause" in this case until the user did unlock his wallet (== topup, rescan, etc.).

This has a little bit of complexity and requires careful reviews.

@jonasschnelli jonasschnelli force-pushed the 2017/04/hd_rescan branch 2 times, most recently from 4efffdf to 427ea2f Compare April 20, 2017 19:59
@ryanofsky
Copy link
Contributor

I know there was discussion about this in IRC last week, but I didn't follow closely. Would it be better to review this PR now, or hold off for more changes?

@jonasschnelli
Copy link
Contributor Author

I'm currently implementing the changes we discussed in last weeks RIC meeting. A review makes more sense after the overhaul.

@jonasschnelli jonasschnelli force-pushed the 2017/04/hd_rescan branch 2 times, most recently from fa2ed74 to 3a7dbb6 Compare May 3, 2017 15:10
@jonasschnelli
Copy link
Contributor Author

jonasschnelli commented May 3, 2017

Completely rewrote this PR. Keeping the WIP tag for now.
The current implementation takes care of encrypted and unencrypted wallets (also in conjunction with pruning).

unencrypted wallets

For unencrypted wallets, the key pool will always be topped up. During sync (SyncTransaction), we check for used keypool keys and mark all keys up to the matched key as used. Additionally we topup the keypool to ensure we not fall below the gap limit (20 keys).

encrypted wallets in non pruning mode

Same as above, but, If we hit the gap limit with an encrypted wallet, we can't topup the keypool. In that case, we just pause the sync (not the node, only the wallet).
Once the user unlocks the wallet over walletpassphrase, we rescan down to the point where we have stopped previously to ensure we don't miss possible funds.

encrypted wallets in pruned mode

Same as above, but, we also stop requesting and connecting blocks. The full node will "pause" in this case until the user did unlock his wallet (== topup, rescan, etc.).

This has a little bit of complexity and requires careful reviews.
Thanks for early feedback.

@jonasschnelli jonasschnelli force-pushed the 2017/04/hd_rescan branch 4 times, most recently from 7ceb728 to cada726 Compare May 4, 2017 12:49
@jonasschnelli jonasschnelli changed the title [WIP] Add basic HD wallet restore functionality Add basic HD wallet restore functionality May 4, 2017
@jonasschnelli
Copy link
Contributor Author

All tests are passing now.
Removed WIP tag.
Overhauled PR description

{
// check if we need to flag used keypool keys
std::set<CKeyID> setKeyPool;
GetAllReserveKeys(setKeyPool);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is very inefficient and something like #10235 should allow to speed up things.

@jonasschnelli jonasschnelli changed the title Add basic HD wallet restore functionality Add HD wallet auto-restore functionality May 4, 2017
Copy link
Contributor

@ryanofsky ryanofsky May 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In commit "Add basic HD wallet restore functionality"

Maybe rename this variable. (It shadows CWallet::setKeyPool, which makes that variable more annoying to grep for.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe rename this variable. (It shadows CWallet::setKeyPool, which makes that variable more annoying to grep for.)

Done in 2a203b7

Copy link
Contributor

@ryanofsky ryanofsky May 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In commit "Add basic HD wallet restore functionality"

Maybe avoid BOOST_FOREACH here and below.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe avoid BOOST_FOREACH here and below.

Done in 2a203b7

if (!walletdb.ReadPool(id, keypool))
throw std::runtime_error(std::string(__func__) + ": read failed");

if (keypool.vchPubKey.GetID() == keyId) {
Copy link
Contributor

@ryanofsky ryanofsky May 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In commit "Add basic HD wallet restore functionality"

It seems like this for-loop could be eliminated if you just changed GetAllReserveKeys to return map<CKeyID, int64_t> instead of set<CKeyID>. I think making this change would add less code than is written here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would also require to keep the fInternal flags in memory (for the address book internal/external change flagging). This is independently addresses in #10238.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would also require to keep the fInternal flags in memory (for the address book internal/external change flagging). This is independently addresses in #10238.

Yeah probably not worth simplifying this if it will be obsoleted by #10238.

{
LOCK(cs_wallet);
CWalletDB walletdb(*dbw);
auto it = std::begin(setKeyPool);
Copy link
Contributor

@ryanofsky ryanofsky May 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In commit "Add basic HD wallet restore functionality"

Should move this declaration closer to where it's actually used way below.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should move this declaration closer to where it's actually used way below.

(unchanged)

throw std::runtime_error(std::string(__func__) + ": read failed");

// only mark keys on the corresponding chain
if (keypool.fInternal == foundInternal) {
Copy link
Contributor

@ryanofsky ryanofsky May 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In commit "Add basic HD wallet restore functionality"

Shouldn't it be an error if this condition is not true?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't it be an error if this condition is not true?

(unchanged)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In commit "Make sure we pause immediately if we receive a pause-request"

Would squash this commit into the commit "Add request-halt flag to BlockConnected signal" (along with the other change I suggest moving there) so this is understandable in the correct context.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would squash this commit into the commit "Add request-halt flag to BlockConnected signal" (along with the other change I suggest moving there) so this is understandable in the correct context.

(unchanged)

strUsage += HelpMessageOpt("-flushwallet", strprintf("Run a thread to flush wallet periodically (default: %u)", DEFAULT_FLUSHWALLET));
strUsage += HelpMessageOpt("-privdb", strprintf("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)", DEFAULT_WALLET_PRIVDB));
strUsage += HelpMessageOpt("-walletrejectlongchains", strprintf(_("Wallet will not create transactions that violate mempool chain limits (default: %u)"), DEFAULT_WALLET_REJECT_LONG_CHAINS));
strUsage += HelpMessageOpt("-hdignoregaplimit", strprintf(_("Ignores the minimum keypool-size warning for HD restore (default: %u)"), DEFAULT_IGNORE_HD_MIN_KEYPOOL_SIZE));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In commit "SetSoftArg the keypool always to the minimum gap limit if HD is enabled"

It seems like it would be a lot harder to for someone to understand what this "ignore gap limit" option does than the PAUSE_SYNC_WHEN_KEYPOOL_SMALLER_THAN option I suggested in another comment. Would be curious to know what you think about it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The -hdignoregaplimit is for debug purposes only. Our tests run with a keypool size of 1 and therefor would cause troubles running post this PR without a "ignore" option, and I don't think it matter how we "ignore" the gap limit and over a startup argument seems the be the simplest way.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The -hdignoregaplimit is for debug purposes only

Maybe it's not worth fixing, but even as a developer I think "pause sync when keypool is smaller than" is clearer than "ignore hd gap limit" because one name tells you literally what the option does, while the other refers obliquely to what the option doesn't do.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think "pause sync when keypool is smaller than" is clearer than "ignore hd gap limit"

👍

nit: place this argument in the correct alphabetic order.

walletInstance->TopUpKeyPool();
}
if (!walletInstance->CheckKeypoolMinSize()) {
if (!walletInstance->CheckKeypoolMinSize() && !GetBoolArg("-hdignoregaplimit", DEFAULT_IGNORE_HD_MIN_KEYPOOL_SIZE)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In commit "SetSoftArg the keypool always to the minimum gap limit if HD is enabled"

This seems broken. It's still pausing but just no longer warning that the pause took place?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems broken. It's still pausing but just no longer warning that the pause took place?

On second look, this seems ok because CWallet::CheckKeypoolMinSize now checks for "-hdignoregaplimit" and disables the pause.

self.stop_node(1)
os.remove(self.options.tmpdir + "/node1/regtest/wallet.dat")
# we need to delete the complete regtest directory
# otherwise node1 would auto-recover all funds in flag the keypool keys as used
Copy link
Contributor

@ryanofsky ryanofsky May 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In commit "SetSoftArg the keypool always to the minimum gap limit if HD is enabled"

Is this change meant to be part of this commit? I don't think there's an interaction with hdignoregaplimit here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change meant to be part of this commit? I don't think there's an interaction with hdignoregaplimit here.

(unchanged)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also confused about why wallet-hd.py needs to be updated.


// for now, enable block requests and tip updates via the states
// this will only be sufficient as long as only a single wallet adjusts these stats
// otherwise the net-/validation-logic needs to poll the state over a signal (or similar)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In commit "Ensure we pause wallet sync when the keypool requires extension"

It should be possible to handle this without any polling or notifications by making fPauseBlockRequests and fPauseTipUpdates counters instead of bools. The counters would need to be incremented whenever fSyncPausedUntilKeypoolExt changed from false to true in any wallet, and decremented when it changed from true to false. Block requesting or tip updating would be paused whenever its respective counter was greater than 0.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Thats a good idea. Do you think this should be done in this PR or can we tackle this once we have multiple places where the sync may get paused?
Counters may also introduce the risk of unwillingly increasing it twice (while only decrease it once).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think this should be done in this PR or can we tackle this once we have multiple places where the sync may get paused?

Maybe, this PR is already pretty complicated, so I wouldn't want to tack this on in extra commits, but it could be nice if implemented to replace the existing "Add option to pause..." commits.

@laanwj laanwj added this to the 0.15.0 milestone May 11, 2017
@jonasschnelli
Copy link
Contributor Author

jonasschnelli commented May 12, 2017

Needed rebase.
Addressed most of @ryanofsky points.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would squash this commit into the commit "Add request-halt flag to BlockConnected signal" (along with the other change I suggest moving there) so this is understandable in the correct context.

(unchanged)

SyncTransaction(pblock->vtx[i], pindex, i);
}
if (fSyncPausedUntilKeypoolExt) {
requestPause = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you mention, it would be much simpler to call setBlockRequestsPaused(), but, wouldn't it be a massive layer violation? Communicating through the signals doesn't require that the wallet needs to know what the full node parts is really doing. But maybe im overcomplicating things here.

I don't see why it would be a problem to call setBlockRequestsPaused(true) from CWallet::MarkReserveKeysAsUsed, especially if it isn't a problem to call setBlockRequestsPaused(false) from CWallet::EventuallyRescanAfterKeypoolTopUp which the current code already does. It seems like it would just make pausing simpler, and more consistent with unpausing.

if (pindexRescan != block) {
const static std::string pruneError = "Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)";
uiInterface.ThreadSafeMessageBox(pruneError, "", CClientUIInterface::MSG_ERROR);
StartShutdown();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But there is no guarantee that we won't prune bellow the wallets best block,.. this why this shutdown/protection is here.

Wouldn't just staying paused in this case offer as much protection as briefly unpausing and then shutting down?

{
LOCK(cs_wallet);
CWalletDB walletdb(*dbw);
auto it = std::begin(setKeyPool);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should move this declaration closer to where it's actually used way below.

(unchanged)

if (!walletdb.ReadPool(id, keypool))
throw std::runtime_error(std::string(__func__) + ": read failed");

if (keypool.vchPubKey.GetID() == keyId) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would also require to keep the fInternal flags in memory (for the address book internal/external change flagging). This is independently addresses in #10238.

Yeah probably not worth simplifying this if it will be obsoleted by #10238.

size_t extKeypoolSize = KeypoolCountExternalKeys();
if (IsHDEnabled() && (extKeypoolSize < HD_RESTORE_KEYPOOL_SIZE_MIN || (setKeyPool.size()-extKeypoolSize) < HD_RESTORE_KEYPOOL_SIZE_MIN)) {
// if the remaining keypool size is below the gap limit, refuse to continue with the sync
fSyncPausedUntilKeypoolExt = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pausing behavior seems like it should be optional

The "-hdignoregaplimit" argument added in the next commit does make this optional (commit "SetSoftArg the keypool always to the minimum gap limit"), though I still think a single "pause sync when keypool smaller than" check would be a little cleaner than separate "keypool size min" and "ignore gap limit" checks.

}

if (!walletInstance->CheckKeypoolMinSize()) {
InitWarning(_("Your keypool size is below the required limit for HD rescans. Wallet synchronisation is now paused until you have refilled the keypool."));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning should suggest how to fix the problem, and also ideally also include more background information (maybe consider using my previous suggestion for the -keypool limit warning).

(unchanged)

walletInstance->TopUpKeyPool();
}
if (!walletInstance->CheckKeypoolMinSize()) {
if (!walletInstance->CheckKeypoolMinSize() && !GetBoolArg("-hdignoregaplimit", DEFAULT_IGNORE_HD_MIN_KEYPOOL_SIZE)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems broken. It's still pausing but just no longer warning that the pause took place?

On second look, this seems ok because CWallet::CheckKeypoolMinSize now checks for "-hdignoregaplimit" and disables the pause.

// HD Restore: Make sure we always have a reasonable keypool size if HD is enabled
if (walletInstance->IsHDEnabled()) {
if (walletInstance->IsCrypted()) {
InitWarning(_("Your are using an encrypted HD wallet. In case you recover a HD wallet, you may miss incomming or outgoing funds."));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In commit "SetSoftArg the keypool always to the minimum gap limit if HD is enabled"

It might be a good idea to keep the warning about missing funds in the case where IsCrypted && size < KEYPOOL_SIZE_MIN && GetBool("-hdignoregaplimit"). I also had a suggestion about this warning in
#10240 (comment)

}
else {
if (GetArg("-keypool", DEFAULT_KEYPOOL_SIZE) < HD_RESTORE_KEYPOOL_SIZE_MIN ) {
InitWarning(_("Your keypool size is below the recommended limit for HD rescans. In case you recover a HD wallet, you may miss incomming or outgoing funds."));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In commit "Make sure we check the keypool min size during startup"

Why drop this warning? It still seems useful to warn about the "-keypool" being too small even if KeypoolCountExternalKeys() is momentarily returning a high number of keys. (I also had another suggestion about this warning at #10240 (comment))

@sipa
Copy link
Member

sipa commented Jun 12, 2017

Needs rebase.

Copy link
Contributor

@jnewbery jnewbery left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs rebase. I've added a lot of mainly nitty comments. The most important thing to address is to make this compatible with multiwallet.


for (const CTransactionRef& ptx : vtxConflicted) {
SyncTransaction(ptx);
void CWallet::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex *pindex, const std::vector<CTransactionRef>& vtxConflicted, bool &requestPause) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not going to comment on @ryanofsky's other comments regarding commit order (although they all sound sensible). This one should definitely be fixed in commit "Add request-halt flag to BlockConnected signal" since it breaks the build and so breaks git bisect.

// Make sure pindexBestKnownBlock is up to date, we'll need it.
ProcessBlockAvailability(nodeid);

if (isBlockRequestsPaused())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: braces

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please address.

/** Guess verification progress (as a fraction between 0.0=genesis and 1.0=current tip). */
double GuessVerificationProgress(const ChainTxData& data, CBlockIndex* pindex);

/**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: s/will allow to temporary/will temporarily

bool isBlockRequestsPaused();
void setBlockRequestsPaused(bool state);

/**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: s/will temporary/will temporarily

pwallet->TopUpKeyPool();

// give a hint to the wallet in case we have paused sync (we may have fall bellow the hd gap limit)
// this runs synchronous, at least during the resync, we can be sure the keypool can be topped up
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

// Give a hint to the wallet in case we have paused sync (we may have fallen bellow the hd gap limit).
// This runs synchronously, at least during the resync, we can be sure the keypool can be topped up

def run_test (self):
tmpdir = self.options.tmpdir

print("Initialize wallet including backups of unencrypted and encrypted wallet")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use self.log.info() instead of print for logging.

addr_enc_oldpool = self.nodes[1].getnewaddress()

# now make sure we retrive an address in the extended pool
self.nodes[1].walletpassphrase("test", 10)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest you set the timeout higher, perhaps to 60 seconds. Tests should be robust to bitcoind hanging for several seconds, especially if running in parallel on Travis.


print("Testing with unencrypted wallet")
self.stop_node(1)
shutil.rmtree(tmpdir + "/node1/regtest")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please don't do this! It erases the debug.log file. Are you able to be more targeted in what you're erasing?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please address.

assert_equal(self.nodes[1].validateaddress(addr)['hdkeypath'], "m/0'/0'/11'")

rawch = self.nodes[1].getrawchangeaddress()
txid = self.nodes[0].sendtoaddress(addr, 1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

txid isn't used. No need to assign it here or below.

self.stop_node(1)
os.remove(self.options.tmpdir + "/node1/regtest/wallet.dat")
# we need to delete the complete regtest directory
# otherwise node1 would auto-recover all funds in flag the keypool keys as used
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also confused about why wallet-hd.py needs to be updated.

@gmaxwell
Copy link
Contributor

Will begin code review post rebase.

Question about the parameters-- Why 20? that is very small, I am not aware of any reason to not have it be more like-- say-- 10,000. With a large number the pause is hopefully seldom/never hit. Electrum uses a very small number because its a single user wallet and has to send all these addresses for processing to a remote server. In a commercial application getting reordering beyond 20 would be very easy. (e.g hand out 30 keys to different users and only the first one makes a payment).

@jonasschnelli
Copy link
Contributor Author

Agree that 20 is probably way to low.
It's just a single constant and I worry more about getting the PR on a level where everything works as expected. Changing the 20 to 1000 then is simple... once the PR is stable, we can also test performance better (maybe between 20 and 10k).

Copy link
Member

@sipa sipa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some comments already.

Overall question: why is any of this conditional on HD being enabled? I think we want to mark user and topup any key seen on the network at any time.

# Copyright (c) 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.
"""Test Hierarchical Deterministic wallet function."""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please address.


print("Testing with unencrypted wallet")
self.stop_node(1)
shutil.rmtree(tmpdir + "/node1/regtest")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please address.

if (walletInstance->IsCrypted()) {
InitWarning(_("Your are using an encrypted HD wallet. In case you recover a HD wallet, you may miss incomming or outgoing funds."));
}
else {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: else on the same line as }

// Make sure pindexBestKnownBlock is up to date, we'll need it.
ProcessBlockAvailability(nodeid);

if (isBlockRequestsPaused())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please address.

@jnewbery jnewbery mentioned this pull request Jul 14, 2017
3 tasks
@jonasschnelli
Copy link
Contributor Author

Closing in favor of #10830

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants