Browse Source

lightningd: keep last valid tx, and its signature.

This avoids us having to reconstruct it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 7 years ago
parent
commit
dbfac68c3f
  1. 2
      lightningd/peer_control.c
  2. 4
      lightningd/peer_control.h
  3. 2
      wallet/db.c
  4. 33
      wallet/wallet.c
  5. 36
      wallet/wallet_tests.c

2
lightningd/peer_control.c

@ -489,6 +489,8 @@ void add_peer(struct lightningd *ld, u64 unique_id,
peer->our_msatoshi = NULL;
peer->state = UNINITIALIZED;
peer->channel_info = NULL;
peer->last_tx = NULL;
peer->last_sig = NULL;
peer->last_was_revoke = false;
peer->last_sent_commit = NULL;
peer->remote_shutdown_scriptpubkey = NULL;

4
lightningd/peer_control.h

@ -76,6 +76,10 @@ struct peer {
/* Amount going to us, not counting unfinished HTLCs; if we have one. */
u64 *our_msatoshi;
/* Last tx they gave us (if any). */
struct bitcoin_tx *last_tx;
secp256k1_ecdsa_signature *last_sig;
/* Keys for channel. */
struct channel_info *channel_info;

2
wallet/db.c

@ -72,6 +72,8 @@ char *dbmigrations[] = {
" shutdown_keyidx_local INTEGER,"
" last_sent_commit_state INTEGER,"
" last_sent_commit_id INTEGER,"
" last_tx BLOB,"
" last_sig BLOB,"
" closing_fee_received INTEGER,"
" closing_sig_received BLOB,"
" PRIMARY KEY (id)"

33
wallet/wallet.c

@ -377,6 +377,14 @@ static u8 *sqlite3_column_varhexblob(tal_t *ctx, sqlite3_stmt *stmt, int col)
return tal_hexdata(ctx, source, sourcelen);
}
static struct bitcoin_tx *sqlite3_column_tx(const tal_t *ctx,
sqlite3_stmt *stmt, int col)
{
return bitcoin_tx_from_hex(ctx,
sqlite3_column_blob(stmt, col),
sqlite3_column_bytes(stmt, col));
}
static bool wallet_peer_load(struct wallet *w, const u64 id, struct peer *peer)
{
bool ok = true;
@ -506,6 +514,17 @@ static bool wallet_stmt2channel(struct wallet *w, sqlite3_stmt *stmt,
col += 2;
}
/* Do we have last_tx? If so, populate. */
if (sqlite3_column_type(stmt, col) != SQLITE_NULL) {
chan->peer->last_tx = sqlite3_column_tx(chan->peer, stmt, col++);
chan->peer->last_sig = tal(chan->peer, secp256k1_ecdsa_signature);
sqlite3_column_sig(stmt, col++, chan->peer->last_sig);
} else {
chan->peer->last_tx = tal_free(chan->peer->last_tx);
chan->peer->last_sig = tal_free(chan->peer->last_sig);
col += 2;
}
chan->peer->closing_fee_received = sqlite3_column_int64(stmt, col++);
if (sqlite3_column_type(stmt, col) != SQLITE_NULL) {
if (!chan->peer->closing_sig_received) {
@ -515,7 +534,7 @@ static bool wallet_stmt2channel(struct wallet *w, sqlite3_stmt *stmt,
} else {
col++;
}
assert(col == 34);
assert(col == 36);
return ok;
}
@ -540,6 +559,7 @@ bool wallet_channel_load(struct wallet *w, const u64 id,
"old_per_commit_remote, feerate_per_kw, shachain_remote_id, "
"shutdown_scriptpubkey_remote, shutdown_keyidx_local, "
"last_sent_commit_state, last_sent_commit_id, "
"last_tx, last_sig, "
"closing_fee_received, closing_sig_received FROM channels WHERE "
"id=%" PRIu64 ";";
@ -573,6 +593,14 @@ static char* db_serialize_pubkey(const tal_t *ctx, struct pubkey *pk)
return tal_hex(ctx, der);
}
static char* db_serialize_tx(const tal_t *ctx, const struct bitcoin_tx *tx)
{
if (!tx)
return "NULL";
return tal_fmt(ctx, "'%s'", tal_hex(ctx, linearize_tx(ctx, tx)));
}
bool wallet_channel_config_save(struct wallet *w, struct channel_config *cc)
{
bool ok = true;
@ -674,6 +702,7 @@ bool wallet_channel_save(struct wallet *w, struct wallet_channel *chan){
" shutdown_scriptpubkey_remote='%s',"
" shutdown_keyidx_local=%"PRIu64","
" channel_config_local=%"PRIu64","
" last_tx=%s, last_sig=%s, "
" closing_fee_received=%"PRIu64","
" closing_sig_received=%s"
" WHERE id=%"PRIu64,
@ -696,6 +725,8 @@ bool wallet_channel_save(struct wallet *w, struct wallet_channel *chan){
p->remote_shutdown_scriptpubkey?tal_hex(tmpctx, p->remote_shutdown_scriptpubkey):"",
p->local_shutdown_idx,
p->our_config.id,
db_serialize_tx(tmpctx, p->last_tx),
db_serialize_signature(tmpctx, p->last_sig),
p->closing_fee_received,
db_serialize_signature(tmpctx, p->closing_sig_received),
chan->id);

36
wallet/wallet_tests.c

@ -113,6 +113,18 @@ static bool test_shachain_crud(void)
return true;
}
static bool bitcoin_tx_eq(const struct bitcoin_tx *tx1,
const struct bitcoin_tx *tx2)
{
u8 *lin1, *lin2;
bool eq;
lin1 = linearize_tx(NULL, tx1);
lin2 = linearize_tx(lin1, tx2);
eq = memeq(lin1, tal_len(lin1), lin2, tal_len(lin2));
tal_free(lin1);
return eq;
}
static bool channelseq(struct wallet_channel *c1, struct wallet_channel *c2)
{
struct peer *p1 = c1->peer, *p2 = c2->peer;
@ -154,6 +166,16 @@ static bool channelseq(struct wallet_channel *c1, struct wallet_channel *c2)
CHECK(lc1->id == lc2->id);
}
CHECK((p1->last_tx != NULL) == (p2->last_tx != NULL));
if(p1->last_tx) {
CHECK(bitcoin_tx_eq(p1->last_tx, p2->last_tx));
}
CHECK((p1->last_sig != NULL) == (p2->last_sig != NULL));
if(p1->last_sig) {
CHECK(memeq(p1->last_sig, sizeof(*p1->last_sig),
p2->last_sig, sizeof(*p2->last_sig)));
}
CHECK((p1->closing_sig_received != NULL) == (p2->closing_sig_received != NULL));
if(p1->closing_sig_received) {
CHECK(memeq(p1->closing_sig_received,
@ -192,6 +214,7 @@ static bool test_channel_crud(const tal_t *ctx)
p.id = pk;
p.unique_id = 42;
p.our_msatoshi = NULL;
p.last_tx = NULL;
memset(&ci.their_config, 0, sizeof(struct channel_config));
ci.remote_fundingkey = pk;
ci.theirbase.revocation = pk;
@ -200,7 +223,7 @@ static bool test_channel_crud(const tal_t *ctx)
ci.remote_per_commit = pk;
ci.old_remote_per_commit = pk;
/* Variant 1: insert with null for scid, funding_tx_id, and channel_info */
/* Variant 1: insert with null for scid, funding_tx_id, channel_info, last_tx */
CHECK_MSG(wallet_channel_save(w, &c1), tal_fmt(w, "Insert into DB: %s", w->db->err));
CHECK_MSG(wallet_channel_load(w, c1.id, c2), tal_fmt(w, "Load from DB: %s", w->db->err));
CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v1)");
@ -245,12 +268,19 @@ static bool test_channel_crud(const tal_t *ctx)
CHECK_MSG(wallet_channel_load(w, c1.id, c2), tal_fmt(w, "Load from DB: %s", w->db->err));
CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v6)");
/* Variant 7: update with closing_sig */
p.closing_sig_received = sig;
/* Variant 7: update with last_tx (taken from BOLT #3) */
p.last_tx = bitcoin_tx_from_hex(w, "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8003a00f0000000000002200208c48d15160397c9731df9bc3b236656efb6665fbfe92b4a6878e88a499f741c4c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de843110ae8f6a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e040047304402206a2679efa3c7aaffd2a447fd0df7aba8792858b589750f6a1203f9259173198a022008d52a0e77a99ab533c36206cb15ad7aeb2aa72b93d4b571e728cb5ec2f6fe260147304402206d6cb93969d39177a09d5d45b583f34966195b77c7e585cf47ac5cce0c90cefb022031d71ae4e33a4e80df7f981d696fbdee517337806a3c7138b7491e2cbb077a0e01475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220", strlen("02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8003a00f0000000000002200208c48d15160397c9731df9bc3b236656efb6665fbfe92b4a6878e88a499f741c4c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de843110ae8f6a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e040047304402206a2679efa3c7aaffd2a447fd0df7aba8792858b589750f6a1203f9259173198a022008d52a0e77a99ab533c36206cb15ad7aeb2aa72b93d4b571e728cb5ec2f6fe260147304402206d6cb93969d39177a09d5d45b583f34966195b77c7e585cf47ac5cce0c90cefb022031d71ae4e33a4e80df7f981d696fbdee517337806a3c7138b7491e2cbb077a0e01475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220"));
p.last_sig = sig;
CHECK_MSG(wallet_channel_save(w, &c1), tal_fmt(w, "Insert into DB: %s", w->db->err));
CHECK_MSG(wallet_channel_load(w, c1.id, c2), tal_fmt(w, "Load from DB: %s", w->db->err));
CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v7)");
/* Variant 8: update with closing_sig */
p.closing_sig_received = sig;
CHECK_MSG(wallet_channel_save(w, &c1), tal_fmt(w, "Insert into DB: %s", w->db->err));
CHECK_MSG(wallet_channel_load(w, c1.id, c2), tal_fmt(w, "Load from DB: %s", w->db->err));
CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v8)");
tal_free(w);
return true;
}

Loading…
Cancel
Save