wallet: use last_processed_block to determine scan start.

With fallback depending on chainparams: this means the first upgrade
will be slow, but after that it'll be fast.

Fixes: #990
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2018-02-16 08:39:55 +10:30 committed by Christian Decker
parent 21849329dd
commit 6620305606
7 changed files with 39 additions and 25 deletions

View File

@ -12,6 +12,8 @@ const struct chainparams networks[] = {
.cli = "bitcoin-cli", .cli = "bitcoin-cli",
.cli_args = NULL, .cli_args = NULL,
.dust_limit = 546, .dust_limit = 546,
/* "Lightning Charge Powers Developers & Blockstream Store" */
.when_lightning_became_cool = 504500,
.testnet = false}, .testnet = false},
{.index = 1, {.index = 1,
.network_name = "regtest", .network_name = "regtest",
@ -21,6 +23,7 @@ const struct chainparams networks[] = {
.cli = "bitcoin-cli", .cli = "bitcoin-cli",
.cli_args = "-regtest", .cli_args = "-regtest",
.dust_limit = 546, .dust_limit = 546,
.when_lightning_became_cool = 1,
.testnet = true}, .testnet = true},
{.index = 2, {.index = 2,
.network_name = "testnet", .network_name = "testnet",
@ -39,6 +42,7 @@ const struct chainparams networks[] = {
.cli = "litecoin-cli", .cli = "litecoin-cli",
.cli_args = NULL, .cli_args = NULL,
.dust_limit = 100000, .dust_limit = 100000,
.when_lightning_became_cool = 1,
.testnet = false}, .testnet = false},
{.index = 4, {.index = 4,
.network_name = "litecoin-testnet", .network_name = "litecoin-testnet",
@ -48,6 +52,7 @@ const struct chainparams networks[] = {
.cli = "litecoin-cli", .cli = "litecoin-cli",
.cli_args = "-testnet", .cli_args = "-testnet",
.dust_limit = 100000, .dust_limit = 100000,
.when_lightning_became_cool = 1,
.testnet = true} .testnet = true}
}; };

View File

@ -15,6 +15,7 @@ struct chainparams {
const char *cli; const char *cli;
const char *cli_args; const char *cli_args;
const u64 dust_limit; const u64 dust_limit;
const u32 when_lightning_became_cool;
/* Whether this is a test network or not */ /* Whether this is a test network or not */
const bool testnet; const bool testnet;

View File

@ -470,17 +470,17 @@ 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)
{ {
/* FIXME: Because we don't handle our root disappearing, we go
* 100 blocks back */
if (blockcount < 100)
blockcount = 0;
else
blockcount -= 100;
/* This happens if first_blocknum is UINTMAX-1 */ /* This happens if first_blocknum is UINTMAX-1 */
if (blockcount < topo->first_blocknum) if (blockcount < topo->first_blocknum)
topo->first_blocknum = blockcount; topo->first_blocknum = blockcount;
/* FIXME: Because we don't handle our root disappearing, we go
* 100 blocks back */
if (topo->first_blocknum < 100)
topo->first_blocknum = 0;
else
topo->first_blocknum -= 100;
/* Get up to speed with topology. */ /* Get up to speed with topology. */
bitcoind_getblockhash(bitcoind, topo->first_blocknum, bitcoind_getblockhash(bitcoind, topo->first_blocknum,
get_init_block, topo); get_init_block, topo);
@ -714,14 +714,14 @@ struct chain_topology *new_topology(struct lightningd *ld, struct log *log)
void setup_topology(struct chain_topology *topo, void setup_topology(struct chain_topology *topo,
struct timers *timers, struct timers *timers,
struct timerel poll_time, u32 first_channel_block) struct timerel poll_time, u32 first_blocknum)
{ {
memset(&topo->feerate, 0, sizeof(topo->feerate)); memset(&topo->feerate, 0, sizeof(topo->feerate));
topo->timers = timers; topo->timers = timers;
topo->poll_time = poll_time; topo->poll_time = poll_time;
/* Start one before the block we are interested in (as we won't /* Start one before the block we are interested in (as we won't
* get notifications on txs in that block). */ * get notifications on txs in that block). */
topo->first_blocknum = first_channel_block - 1; topo->first_blocknum = first_blocknum - 1;
/* Make sure bitcoind is started, and ready */ /* Make sure bitcoind is started, and ready */
wait_for_bitcoind(topo->bitcoind); wait_for_bitcoind(topo->bitcoind);

View File

@ -256,7 +256,7 @@ int main(int argc, char *argv[])
struct log_book *log_book; struct log_book *log_book;
struct lightningd *ld; struct lightningd *ld;
bool newdir; bool newdir;
u32 peer_first_blocknum; u32 first_blocknum;
err_set_progname(argv[0]); err_set_progname(argv[0]);
@ -336,7 +336,10 @@ 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.");
peer_first_blocknum = wallet_channels_first_blocknum(ld->wallet); /* Worst case, scan back to the first lightning deployment */
first_blocknum = wallet_first_blocknum(ld->wallet,
get_chainparams(ld)
->when_lightning_became_cool);
db_commit_transaction(ld->wallet->db); db_commit_transaction(ld->wallet->db);
@ -344,7 +347,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,
peer_first_blocknum); first_blocknum);
/* Create RPC socket (if any) */ /* Create RPC socket (if any) */
setup_jsonrpc(ld, ld->rpc_filename); setup_jsonrpc(ld, ld->rpc_filename);

View File

@ -87,12 +87,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_channels_first_blocknum */
u32 wallet_channels_first_blocknum(struct wallet *w UNNEEDED)
{ fprintf(stderr, "wallet_channels_first_blocknum 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,

View File

@ -667,22 +667,28 @@ bool wallet_channels_load_active(const tal_t *ctx, struct wallet *w)
return ok; return ok;
} }
u32 wallet_channels_first_blocknum(struct wallet *w) u32 wallet_first_blocknum(struct wallet *w, u32 first_possible)
{ {
int err; int err;
u32 first_blocknum; u32 first_channel, first_utxo;
sqlite3_stmt *stmt = sqlite3_stmt *stmt =
db_query(__func__, w->db, db_query(__func__, w->db,
"SELECT MIN(first_blocknum) FROM channels;"); "SELECT MIN(first_blocknum) FROM channels;");
err = sqlite3_step(stmt); err = sqlite3_step(stmt);
if (err == SQLITE_ROW && sqlite3_column_type(stmt, 0) != SQLITE_NULL) if (err == SQLITE_ROW && sqlite3_column_type(stmt, 0) != SQLITE_NULL)
first_blocknum = sqlite3_column_int(stmt, 0); first_channel = sqlite3_column_int(stmt, 0);
else else
first_blocknum = UINT32_MAX; first_channel = UINT32_MAX;
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
return first_blocknum;
/* If it's an old database, go back to before c-lightning was cool */
first_utxo = db_get_intvar(w->db, "last_processed_block",
first_possible);
if (first_utxo < first_channel)
return first_utxo;
else
return first_channel;
} }
void wallet_channel_config_save(struct wallet *w, struct channel_config *cc) void wallet_channel_config_save(struct wallet *w, struct channel_config *cc)

View File

@ -260,13 +260,12 @@ bool wallet_peer_by_nodeid(struct wallet *w, const struct pubkey *nodeid,
bool wallet_channels_load_active(const tal_t *ctx, struct wallet *w); bool wallet_channels_load_active(const tal_t *ctx, struct wallet *w);
/** /**
* wallet_channels_first_blocknum - get first block we're interested in. * wallet_first_blocknum - get first block we're interested in.
* *
* @w: wallet to load from. * @w: wallet to load from.
* * @first_possible: when c-lightning may have been active from
* Returns UINT32_MAX if nothing interesting.
*/ */
u32 wallet_channels_first_blocknum(struct wallet *w); u32 wallet_first_blocknum(struct wallet *w, u32 first_possible);
/** /**
* wallet_extract_owned_outputs - given a tx, extract all of our outputs * wallet_extract_owned_outputs - given a tx, extract all of our outputs