Skip to content

Commit

Permalink
coin moves: persist the coin movement index counter to disk
Browse files Browse the repository at this point in the history
Should make it easier to track when coin moves in the plugin are
disjoint from what c-lightning says it's broadcast already.
  • Loading branch information
niftynei committed Apr 4, 2020
1 parent b9471a3 commit 9fe8217
Show file tree
Hide file tree
Showing 11 changed files with 88 additions and 15 deletions.
12 changes: 6 additions & 6 deletions common/coin_mvt.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ const char *mvt_unit_str(enum mvt_unit_type unit)
return mvt_units[unit];
}

static u64 mvt_count = 0;

struct channel_coin_mvt *new_channel_coin_mvt(const tal_t *ctx,
struct bitcoin_txid *funding_txid,
u32 funding_outnum,
Expand Down Expand Up @@ -131,7 +129,8 @@ struct chain_coin_mvt *new_chain_coin_mvt_sat(const tal_t *ctx,
struct coin_mvt *finalize_chain_mvt(const tal_t *ctx,
const struct chain_coin_mvt *chain_mvt,
u32 timestamp,
struct node_id *node_id)
struct node_id *node_id,
s64 count)
{
struct coin_mvt *mvt = tal(ctx, struct coin_mvt);

Expand All @@ -151,14 +150,15 @@ struct coin_mvt *finalize_chain_mvt(const tal_t *ctx,
mvt->blockheight = chain_mvt->blockheight;
mvt->version = COIN_MVT_VERSION;
mvt->node_id = node_id;
mvt->counter = mvt_count++;
mvt->counter = count;

return mvt;
}

struct coin_mvt *finalize_channel_mvt(const tal_t *ctx,
const struct channel_coin_mvt *chan_mvt,
u32 timestamp, struct node_id *node_id)
u32 timestamp, struct node_id *node_id,
s64 count)
{
struct coin_mvt *mvt = tal(ctx, struct coin_mvt);

Expand All @@ -179,7 +179,7 @@ struct coin_mvt *finalize_channel_mvt(const tal_t *ctx,
mvt->blockheight = 0;
mvt->version = COIN_MVT_VERSION;
mvt->node_id = node_id;
mvt->counter = mvt_count++;
mvt->counter = count;

return mvt;
}
Expand Down
6 changes: 4 additions & 2 deletions common/coin_mvt.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,12 @@ struct chain_coin_mvt *new_chain_coin_mvt_sat(const tal_t *ctx,
struct coin_mvt *finalize_chain_mvt(const tal_t *ctx,
const struct chain_coin_mvt *chain_mvt,
u32 timestamp,
struct node_id *node_id);
struct node_id *node_id,
s64 mvt_count);
struct coin_mvt *finalize_channel_mvt(const tal_t *ctx,
const struct channel_coin_mvt *chan_mvt,
u32 timestamp, struct node_id *node_id);
u32 timestamp, struct node_id *node_id,
s64 mvt_count);

const char *mvt_type_str(enum mvt_type type);
const char *mvt_tag_str(enum mvt_tag tag);
Expand Down
41 changes: 39 additions & 2 deletions lightningd/coin_mvts.c
Original file line number Diff line number Diff line change
@@ -1,24 +1,61 @@
#include <lightningd/coin_mvts.h>
#include <lightningd/notification.h>

static s64 update_count(struct lightningd *ld)
{
s64 count;
bool db_in_tx;
db_in_tx = db_in_transaction(ld->wallet->db);
if (!db_in_tx)
db_begin_transaction(ld->wallet->db);
/* This could be written more concisely as
* count = ++ld->coin_moves_count;
* however I believe that's contra-code conventions */
ld->coin_moves_count++;
count = ld->coin_moves_count;
db_set_intvar(ld->wallet->db, "coin_moves_count",
count);
if (!db_in_tx)
db_commit_transaction(ld->wallet->db);
return count;
}

void notify_channel_mvt(struct lightningd *ld, const struct channel_coin_mvt *mvt)
{
const struct coin_mvt *cm;
u32 timestamp;
s64 count;

timestamp = time_now().ts.tv_sec;
count = update_count(ld);
cm = finalize_channel_mvt(mvt, mvt, timestamp,
&ld->id);
&ld->id, count);
notify_coin_mvt(ld, cm);
}

void notify_chain_mvt(struct lightningd *ld, const struct chain_coin_mvt *mvt)
{
const struct coin_mvt *cm;
u32 timestamp;
s64 count;

timestamp = time_now().ts.tv_sec;
count = update_count(ld);
cm = finalize_chain_mvt(mvt, mvt, timestamp,
&ld->id);
&ld->id, count);
notify_coin_mvt(ld, cm);
}

void coin_mvts_init_count(struct lightningd *ld)
{
s64 count;
db_begin_transaction(ld->wallet->db);
count = db_get_intvar(ld->wallet->db,
"coin_moves_count", -1);
db_commit_transaction(ld->wallet->db);
if (count == -1)
fatal("Something went wrong attmepting to fetch"
"the latest `coin_moves_count` from the intvars "
"table");
ld->coin_moves_count = count;
}
3 changes: 3 additions & 0 deletions lightningd/coin_mvts.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,7 @@

void notify_channel_mvt(struct lightningd *ld, const struct channel_coin_mvt *mvt);
void notify_chain_mvt(struct lightningd *ld, const struct chain_coin_mvt *mvt);

/* Initialize the coin movement counter on lightningd */
void coin_mvts_init_count(struct lightningd *ld);
#endif /* LIGHTNING_LIGHTNINGD_COIN_MVTS_H */
5 changes: 5 additions & 0 deletions lightningd/lightningd.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
#include <lightningd/bitcoind.h>
#include <lightningd/chaintopology.h>
#include <lightningd/channel_control.h>
#include <lightningd/coin_mvts.h>
#include <lightningd/connect_control.h>
#include <lightningd/invoice.h>
#include <lightningd/io_loop_with_timers.h>
Expand Down Expand Up @@ -813,6 +814,10 @@ int main(int argc, char *argv[])
* states, invoices, payments, blocks and bitcoin transactions. */
ld->wallet = wallet_new(ld, ld->timers);

/*~ We keep track of how many 'coin moves' we've ever made.
* Initialize the starting value from the database here. */
coin_mvts_init_count(ld);

/*~ We keep a filter of scriptpubkeys we're interested in. */
ld->owned_txfilter = txfilter_new(ld);

Expand Down
4 changes: 4 additions & 0 deletions lightningd/lightningd.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,10 @@ struct lightningd {
alt_subdaemon_map alt_subdaemons;

enum lightningd_state state;

/* Total number of coin moves we've seen, since
* coin move tracking was cool */
s64 coin_moves_count;
};

/* Turning this on allows a tal allocation to return NULL, rather than aborting.
Expand Down
3 changes: 3 additions & 0 deletions lightningd/test/run-find_my_abspath.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ size_t bigsize_put(u8 buf[BIGSIZE_MAX_LEN] UNNEEDED, bigsize_t v UNNEEDED)
void channel_notify_new_block(struct lightningd *ld UNNEEDED,
u32 block_height UNNEEDED)
{ fprintf(stderr, "channel_notify_new_block called!\n"); abort(); }
/* Generated stub for coin_mvts_init_count */
void coin_mvts_init_count(struct lightningd *ld UNNEEDED)
{ fprintf(stderr, "coin_mvts_init_count called!\n"); abort(); }
/* Generated stub for connectd_activate */
void connectd_activate(struct lightningd *ld UNNEEDED)
{ fprintf(stderr, "connectd_activate called!\n"); abort(); }
Expand Down
2 changes: 1 addition & 1 deletion tests/test_closing.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from shutil import copyfile
from utils import (
only_one, sync_blockheight, wait_for, DEVELOPER, TIMEOUT, VALGRIND,
SLOW_MACHINE, account_balance, first_channel_id
SLOW_MACHINE, account_balance, first_channel_id, check_coin_moves_idx
)

import os
Expand Down
12 changes: 8 additions & 4 deletions tests/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from pyln.proto import Invoice
from utils import (
DEVELOPER, only_one, sync_blockheight, TIMEOUT, wait_for, TEST_NETWORK, expected_features,
account_balance, check_coin_moves, first_channel_id
account_balance, check_coin_moves, first_channel_id, check_coin_moves_idx
)

import json
Expand Down Expand Up @@ -1200,9 +1200,9 @@ def test_coin_movement_notices(node_factory, bitcoind):
]

l1, l2, l3 = node_factory.line_graph(3, opts=[
{},
{'plugin': os.path.join(os.getcwd(), 'tests/plugins/coin_movements.py')},
{}
{'may_reconnect': True},
{'may_reconnect': True, 'plugin': os.path.join(os.getcwd(), 'tests/plugins/coin_movements.py')},
{'may_reconnect': True},
], wait_for_announce=True)

bitcoind.generate_block(5)
Expand Down Expand Up @@ -1241,6 +1241,9 @@ def test_coin_movement_notices(node_factory, bitcoind):
l2.rpc.sendpay(route, payment_hash21)
l2.rpc.waitsendpay(payment_hash21)

# restart to test index
l2.restart()

# close the channel down
chan1 = l2.get_channel_scid(l1)
chan3 = l2.get_channel_scid(l3)
Expand All @@ -1267,3 +1270,4 @@ def test_coin_movement_notices(node_factory, bitcoind):
check_coin_moves(l2, chanid_1, l1_l2_mvts)
check_coin_moves(l2, chanid_3, l2_l3_mvts)
check_coin_moves(l2, 'wallet', l2_wallet_mvts)
check_coin_moves_idx(l2)
13 changes: 13 additions & 0 deletions tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,19 @@ def check_coin_moves(n, account_id, expected_moves):
assert mv['blockheight'] is not None


def check_coin_moves_idx(n):
""" Just check that the counter increments smoothly"""
moves = n.rpc.call('listcoinmoves_plugin')['coin_moves']
idx = 0
for m in moves:
c_idx = m['movement_idx']
# verify that the index count increments smoothly here, also
if c_idx == 0 and idx == 0:
continue
assert c_idx == idx + 1
idx = c_idx


def account_balance(n, account_id):
moves = n.rpc.call('listcoinmoves_plugin')['coin_moves']
chan_moves = [m for m in moves if m['account_id'] == account_id]
Expand Down
2 changes: 2 additions & 0 deletions wallet/db.c
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,8 @@ static struct migration dbmigrations[] = {
/* For incoming HTLCs, we now keep track of whether or not we provided
* the preimage for it, or not. */
{SQL("ALTER TABLE channel_htlcs ADD we_filled INT;"), NULL},
/* We track the counter for coin_moves, as a convenience for notification consumers */
{SQL("INSERT INTO vars (name, intval) VALUES ('coin_moves_count', 0);"), NULL},
};

/* Leak tracking. */
Expand Down

0 comments on commit 9fe8217

Please sign in to comment.