Browse Source

chaintopology: Simplify rescan offset computation

Simplification of the offset calculation to use the rescan parameter, and rename
of `wallet_first_blocknum`. We now use either relative rescan from our last
known location, or absolute if a negative rescan was given. It's all handled in
a single location (except the case in which the blockcount is below our
precomputed offset), so this should reduce surprises.

Signed-off-by: Christian Decker <decker.christian@gmail.com>
ppa-0.6.1
Christian Decker 7 years ago
parent
commit
96352858d6
  1. 23
      lightningd/chaintopology.c
  2. 22
      lightningd/lightningd.c
  3. 6
      lightningd/test/run-find_my_path.c
  4. 1
      tests/test_lightningd.py
  5. 11
      wallet/wallet.c
  6. 9
      wallet/wallet.h

23
lightningd/chaintopology.c

@ -519,17 +519,18 @@ static void get_init_block(struct bitcoind *bitcoind,
static void get_init_blockhash(struct bitcoind *bitcoind, u32 blockcount,
struct chain_topology *topo)
{
/* This can happen if bitcoind still syncing, or first_blocknum is MAX */
if (blockcount < topo->first_blocknum)
topo->first_blocknum = blockcount;
/* For fork protection (esp. because we don't handle our own first
* block getting reorged out), we always go 100 blocks further back
* than we need. */
if (topo->first_blocknum < 100)
topo->first_blocknum = 0;
else
topo->first_blocknum -= 100;
/* If bitcoind's current blockheight is below the requested height, just
* go back to that height. This might be a new node catching up, or
* bitcoind is processing a reorg. */
if (blockcount < topo->first_blocknum) {
if (bitcoind->ld->config.rescan < 0) {
/* Absolute blockheight, but bitcoind's blockheight isn't there yet */
topo->first_blocknum = blockcount - 1;
} else if (topo->first_blocknum == UINT32_MAX) {
/* Relative rescan, but we didn't know the blockheight */
topo->first_blocknum = blockcount - bitcoind->ld->config.rescan;
}
}
/* Rollback to the given blockheight, so we start track
* correctly again */

22
lightningd/lightningd.c

@ -282,7 +282,7 @@ int main(int argc, char *argv[])
{
struct lightningd *ld;
bool newdir;
u32 first_blocknum;
u32 blockheight;
daemon_setup(argv[0], log_backtrace_print, log_backtrace_exit);
ld = new_lightningd(NULL);
@ -357,10 +357,20 @@ int main(int argc, char *argv[])
if (!wallet_htlcs_reconnect(ld->wallet, &ld->htlcs_in, &ld->htlcs_out))
fatal("could not reconnect htlcs loaded from wallet, wallet may be inconsistent.");
/* Worst case, scan back to the first lightning deployment */
first_blocknum = wallet_first_blocknum(ld->wallet,
get_chainparams(ld)
->when_lightning_became_cool);
/* Get the blockheight we are currently at, UINT32_MAX is used to signal
* an unitialized wallet and that we should start off of bitcoind's
* current height */
blockheight = wallet_blocks_height(ld->wallet, UINT32_MAX);
/* If we were asked to rescan from an absolute height (--rescan < 0)
* then just go there. Otherwise take compute the diff to our current
* height, lowerbounded by 0. */
if (ld->config.rescan < 0)
blockheight = -ld->config.rescan;
else if (blockheight < (u32)ld->config.rescan)
blockheight = 0;
else if (blockheight != UINT32_MAX)
blockheight -= ld->config.rescan;
db_commit_transaction(ld->wallet->db);
@ -368,7 +378,7 @@ int main(int argc, char *argv[])
setup_topology(ld->topology,
&ld->timers,
ld->config.poll_time,
first_blocknum);
blockheight);
/* Replay transactions for all running onchainds */
onchaind_replay_channels(ld);

6
lightningd/test/run-find_my_path.c

@ -107,12 +107,12 @@ struct txfilter *txfilter_new(const tal_t *ctx UNNEEDED)
/* Generated stub for version */
const char *version(void)
{ fprintf(stderr, "version called!\n"); abort(); }
/* Generated stub for wallet_blocks_height */
u32 wallet_blocks_height(struct wallet *w UNNEEDED, u32 def UNNEEDED)
{ fprintf(stderr, "wallet_blocks_height called!\n"); abort(); }
/* Generated stub for wallet_channels_load_active */
bool wallet_channels_load_active(const tal_t *ctx UNNEEDED, struct wallet *w UNNEEDED)
{ fprintf(stderr, "wallet_channels_load_active called!\n"); abort(); }
/* Generated stub for wallet_first_blocknum */
u32 wallet_first_blocknum(struct wallet *w UNNEEDED, u32 first_possible UNNEEDED)
{ fprintf(stderr, "wallet_first_blocknum called!\n"); abort(); }
/* Generated stub for wallet_htlcs_load_for_channel */
bool wallet_htlcs_load_for_channel(struct wallet *wallet UNNEEDED,
struct channel *chan UNNEEDED,

1
tests/test_lightningd.py

@ -3607,6 +3607,7 @@ class LightningDTests(BaseLightningDTests):
def test_funding_while_offline(self):
l1 = self.node_factory.get_node()
addr = l1.rpc.newaddr()['address']
sync_blockheight([l1])
# l1 goes down.
l1.stop()

11
wallet/wallet.c

@ -767,14 +767,7 @@ void wallet_channel_stats_load(struct wallet *w,
stats->out_msatoshi_fulfilled = sqlite3_column_int64(stmt, 7);
}
/* We want the earlier of either:
* 1. The first channel we're still watching (it might have closed),
* 2. The last block we scanned for UTXO (might have new incoming payments)
*
* chaintopology actually subtracts another 100 blocks to make sure we
* catch chain forks.
*/
u32 wallet_first_blocknum(struct wallet *w, u32 first_possible)
u32 wallet_blocks_height(struct wallet *w, u32 def)
{
u32 blockheight;
sqlite3_stmt *stmt = db_prepare(w->db, "SELECT MAX(height) FROM blocks;");
@ -785,7 +778,7 @@ u32 wallet_first_blocknum(struct wallet *w, u32 first_possible)
sqlite3_finalize(stmt);
return blockheight;
} else
return first_possible;
return def;
}
static void wallet_channel_config_insert(struct wallet *w,

9
wallet/wallet.h

@ -314,12 +314,15 @@ void wallet_channel_stats_incr_out_fulfilled(struct wallet *w, u64 cdbid, u64 ms
void wallet_channel_stats_load(struct wallet *w, u64 cdbid, struct channel_stats *stats);
/**
* wallet_first_blocknum - get first block we're interested in.
* Retrieve the blockheight of the last block processed by lightningd.
*
* Will return either the maximal blockheight or the default value if the wallet
* was never used before.
*
* @w: wallet to load from.
* @first_possible: when c-lightning may have been active from
* @def: the default value to return if we've never used the wallet before
*/
u32 wallet_first_blocknum(struct wallet *w, u32 first_possible);
u32 wallet_blocks_height(struct wallet *w, u32 def);
/**
* wallet_extract_owned_outputs - given a tx, extract all of our outputs

Loading…
Cancel
Save