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

22
lightningd/lightningd.c

@ -282,7 +282,7 @@ int main(int argc, char *argv[])
{ {
struct lightningd *ld; struct lightningd *ld;
bool newdir; bool newdir;
u32 first_blocknum; u32 blockheight;
daemon_setup(argv[0], log_backtrace_print, log_backtrace_exit); daemon_setup(argv[0], log_backtrace_print, log_backtrace_exit);
ld = new_lightningd(NULL); 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)) if (!wallet_htlcs_reconnect(ld->wallet, &ld->htlcs_in, &ld->htlcs_out))
fatal("could not reconnect htlcs loaded from wallet, wallet may be inconsistent."); fatal("could not reconnect htlcs loaded from wallet, wallet may be inconsistent.");
/* Worst case, scan back to the first lightning deployment */ /* Get the blockheight we are currently at, UINT32_MAX is used to signal
first_blocknum = wallet_first_blocknum(ld->wallet, * an unitialized wallet and that we should start off of bitcoind's
get_chainparams(ld) * current height */
->when_lightning_became_cool); 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); db_commit_transaction(ld->wallet->db);
@ -368,7 +378,7 @@ int main(int argc, char *argv[])
setup_topology(ld->topology, setup_topology(ld->topology,
&ld->timers, &ld->timers,
ld->config.poll_time, ld->config.poll_time,
first_blocknum); blockheight);
/* Replay transactions for all running onchainds */ /* Replay transactions for all running onchainds */
onchaind_replay_channels(ld); 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 */ /* Generated stub for version */
const char *version(void) const char *version(void)
{ fprintf(stderr, "version called!\n"); abort(); } { 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 */ /* Generated stub for wallet_channels_load_active */
bool wallet_channels_load_active(const tal_t *ctx UNNEEDED, struct wallet *w UNNEEDED) bool wallet_channels_load_active(const tal_t *ctx UNNEEDED, struct wallet *w UNNEEDED)
{ fprintf(stderr, "wallet_channels_load_active called!\n"); abort(); } { 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 */ /* Generated stub for wallet_htlcs_load_for_channel */
bool wallet_htlcs_load_for_channel(struct wallet *wallet UNNEEDED, bool wallet_htlcs_load_for_channel(struct wallet *wallet UNNEEDED,
struct channel *chan UNNEEDED, struct channel *chan UNNEEDED,

1
tests/test_lightningd.py

@ -3607,6 +3607,7 @@ class LightningDTests(BaseLightningDTests):
def test_funding_while_offline(self): def test_funding_while_offline(self):
l1 = self.node_factory.get_node() l1 = self.node_factory.get_node()
addr = l1.rpc.newaddr()['address'] addr = l1.rpc.newaddr()['address']
sync_blockheight([l1])
# l1 goes down. # l1 goes down.
l1.stop() 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); stats->out_msatoshi_fulfilled = sqlite3_column_int64(stmt, 7);
} }
/* We want the earlier of either: u32 wallet_blocks_height(struct wallet *w, u32 def)
* 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 blockheight; u32 blockheight;
sqlite3_stmt *stmt = db_prepare(w->db, "SELECT MAX(height) FROM blocks;"); 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); sqlite3_finalize(stmt);
return blockheight; return blockheight;
} else } else
return first_possible; return def;
} }
static void wallet_channel_config_insert(struct wallet *w, 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); 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. * @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 * wallet_extract_owned_outputs - given a tx, extract all of our outputs

Loading…
Cancel
Save