2016-01-21 21:11:49 +01:00
|
|
|
/* Code to talk to bitcoind to watch for various events.
|
|
|
|
*
|
|
|
|
* Here's what we want to know:
|
|
|
|
*
|
|
|
|
* - An anchor tx:
|
|
|
|
* - Reached given depth
|
|
|
|
* - Times out.
|
|
|
|
* - Is unspent after reaching given depth.
|
|
|
|
*
|
|
|
|
* - Our own commitment tx:
|
|
|
|
* - Reached a given depth.
|
|
|
|
*
|
|
|
|
* - HTLC spend tx:
|
|
|
|
* - Reached a given depth.
|
2016-11-11 00:02:04 +01:00
|
|
|
*
|
2016-01-21 21:11:49 +01:00
|
|
|
* - Anchor tx output:
|
|
|
|
* - Is spent by their current tx.
|
|
|
|
* - Is spent by a revoked tx.
|
|
|
|
*
|
|
|
|
* - Commitment tx HTLC outputs:
|
|
|
|
* - HTLC timed out
|
|
|
|
* - HTLC spent
|
|
|
|
*
|
|
|
|
* We do this by adding the P2SH address to the wallet, and then querying
|
|
|
|
* that using listtransactions.
|
|
|
|
*
|
|
|
|
* WE ASSUME NO MALLEABILITY! This requires segregated witness.
|
|
|
|
*/
|
2017-09-16 01:35:06 +02:00
|
|
|
#include <bitcoin/script.h>
|
|
|
|
#include <bitcoin/tx.h>
|
2016-06-28 23:19:20 +02:00
|
|
|
#include <ccan/crypto/siphash24/siphash24.h>
|
2016-04-24 12:20:35 +02:00
|
|
|
#include <ccan/ptrint/ptrint.h>
|
2016-01-21 21:11:49 +01:00
|
|
|
#include <ccan/structeq/structeq.h>
|
2017-08-28 18:04:01 +02:00
|
|
|
#include <common/pseudorand.h>
|
|
|
|
#include <common/timeout.h>
|
2017-09-16 01:35:06 +02:00
|
|
|
#include <lightningd/bitcoind.h>
|
|
|
|
#include <lightningd/chaintopology.h>
|
|
|
|
#include <lightningd/lightningd.h>
|
|
|
|
#include <lightningd/log.h>
|
|
|
|
#include <lightningd/peer_control.h>
|
|
|
|
#include <lightningd/watch.h>
|
2016-01-21 21:11:49 +01:00
|
|
|
|
|
|
|
const struct txwatch_output *txowatch_keyof(const struct txowatch *w)
|
|
|
|
{
|
|
|
|
return &w->out;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t txo_hash(const struct txwatch_output *out)
|
|
|
|
{
|
2016-06-28 23:19:20 +02:00
|
|
|
/* This hash-in-one-go trick only works if they're consecutive. */
|
|
|
|
BUILD_ASSERT(offsetof(struct txwatch_output, index)
|
|
|
|
== sizeof(((struct txwatch_output *)NULL)->txid));
|
|
|
|
return siphash24(siphash_seed(), &out->txid,
|
|
|
|
sizeof(out->txid) + sizeof(out->index));
|
2016-01-21 21:11:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool txowatch_eq(const struct txowatch *w, const struct txwatch_output *out)
|
|
|
|
{
|
|
|
|
return structeq(&w->out.txid, &out->txid)
|
|
|
|
&& w->out.index == out->index;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void destroy_txowatch(struct txowatch *w)
|
|
|
|
{
|
2017-03-02 13:21:49 +01:00
|
|
|
txowatch_hash_del(&w->topo->txowatches, w);
|
2016-01-21 21:11:49 +01:00
|
|
|
}
|
|
|
|
|
2017-12-18 07:41:52 +01:00
|
|
|
const struct bitcoin_txid *txwatch_keyof(const struct txwatch *w)
|
2016-01-21 21:11:49 +01:00
|
|
|
{
|
|
|
|
return &w->txid;
|
|
|
|
}
|
|
|
|
|
2017-12-18 07:41:52 +01:00
|
|
|
size_t txid_hash(const struct bitcoin_txid *txid)
|
2016-01-21 21:11:49 +01:00
|
|
|
{
|
2017-12-18 07:41:52 +01:00
|
|
|
return siphash24(siphash_seed(),
|
|
|
|
txid->shad.sha.u.u8, sizeof(txid->shad.sha.u.u8));
|
2016-01-21 21:11:49 +01:00
|
|
|
}
|
|
|
|
|
2017-12-18 07:41:52 +01:00
|
|
|
bool txwatch_eq(const struct txwatch *w, const struct bitcoin_txid *txid)
|
2016-01-21 21:11:49 +01:00
|
|
|
{
|
|
|
|
return structeq(&w->txid, txid);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void destroy_txwatch(struct txwatch *w)
|
|
|
|
{
|
2017-03-02 13:21:49 +01:00
|
|
|
txwatch_hash_del(&w->topo->txwatches, w);
|
2016-01-21 21:11:49 +01:00
|
|
|
}
|
|
|
|
|
2016-04-24 12:09:21 +02:00
|
|
|
struct txwatch *watch_txid_(const tal_t *ctx,
|
2017-03-02 13:21:49 +01:00
|
|
|
struct chain_topology *topo,
|
2018-02-12 11:13:04 +01:00
|
|
|
struct channel *channel,
|
2017-12-18 07:41:52 +01:00
|
|
|
const struct bitcoin_txid *txid,
|
2018-02-12 11:13:04 +01:00
|
|
|
enum watch_result (*cb)(struct channel *channel,
|
2017-08-18 06:43:53 +02:00
|
|
|
const struct bitcoin_tx *,
|
2016-06-30 01:40:11 +02:00
|
|
|
unsigned int depth,
|
|
|
|
void *arg),
|
2016-04-24 12:09:21 +02:00
|
|
|
void *cb_arg)
|
2016-01-21 21:11:49 +01:00
|
|
|
{
|
|
|
|
struct txwatch *w;
|
|
|
|
|
|
|
|
w = tal(ctx, struct txwatch);
|
2017-03-02 13:21:49 +01:00
|
|
|
w->topo = topo;
|
2016-05-04 08:40:37 +02:00
|
|
|
w->depth = 0;
|
2016-01-21 21:11:49 +01:00
|
|
|
w->txid = *txid;
|
2018-02-12 11:13:04 +01:00
|
|
|
w->channel = channel;
|
2016-01-21 21:11:49 +01:00
|
|
|
w->cb = cb;
|
2016-04-24 12:09:21 +02:00
|
|
|
w->cbdata = cb_arg;
|
2016-01-21 21:11:49 +01:00
|
|
|
|
2017-03-02 13:21:49 +01:00
|
|
|
txwatch_hash_add(&w->topo->txwatches, w);
|
2016-01-21 21:11:49 +01:00
|
|
|
tal_add_destructor(w, destroy_txwatch);
|
|
|
|
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
2018-01-29 03:21:18 +01:00
|
|
|
struct txwatch *find_txwatch(struct chain_topology *topo,
|
|
|
|
const struct bitcoin_txid *txid,
|
2018-02-12 11:13:04 +01:00
|
|
|
const struct channel *channel)
|
2018-01-29 03:21:18 +01:00
|
|
|
{
|
|
|
|
struct txwatch_hash_iter i;
|
|
|
|
struct txwatch *w;
|
|
|
|
|
2018-02-12 11:13:04 +01:00
|
|
|
/* We could have more than one channel watching same txid, though we
|
2018-01-29 03:21:18 +01:00
|
|
|
* don't for onchaind. */
|
|
|
|
for (w = txwatch_hash_getfirst(&topo->txwatches, txid, &i);
|
|
|
|
w;
|
|
|
|
w = txwatch_hash_getnext(&topo->txwatches, txid, &i)) {
|
2018-02-12 11:13:04 +01:00
|
|
|
if (w->channel == channel)
|
2018-01-29 03:21:18 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
2017-03-02 13:21:49 +01:00
|
|
|
bool watching_txid(const struct chain_topology *topo,
|
2017-12-18 07:41:52 +01:00
|
|
|
const struct bitcoin_txid *txid)
|
2016-05-04 08:40:37 +02:00
|
|
|
{
|
2017-03-02 13:21:49 +01:00
|
|
|
return txwatch_hash_get(&topo->txwatches, txid) != NULL;
|
2016-05-04 08:40:37 +02:00
|
|
|
}
|
2016-11-11 00:02:04 +01:00
|
|
|
|
2016-04-24 12:09:21 +02:00
|
|
|
struct txwatch *watch_tx_(const tal_t *ctx,
|
2017-03-02 13:21:49 +01:00
|
|
|
struct chain_topology *topo,
|
2018-02-12 11:13:04 +01:00
|
|
|
struct channel *channel,
|
2016-05-04 08:40:39 +02:00
|
|
|
const struct bitcoin_tx *tx,
|
2018-02-12 11:13:04 +01:00
|
|
|
enum watch_result (*cb)(struct channel *channel,
|
2017-08-18 06:43:53 +02:00
|
|
|
const struct bitcoin_tx *,
|
2016-06-30 01:40:11 +02:00
|
|
|
unsigned int depth,
|
|
|
|
void *arg),
|
2016-04-24 12:09:21 +02:00
|
|
|
void *cb_arg)
|
|
|
|
{
|
2017-12-18 07:41:52 +01:00
|
|
|
struct bitcoin_txid txid;
|
2016-04-24 12:09:21 +02:00
|
|
|
|
2016-04-24 12:31:52 +02:00
|
|
|
bitcoin_txid(tx, &txid);
|
2018-02-12 11:13:04 +01:00
|
|
|
return watch_txid(ctx, topo, channel, &txid, cb, cb_arg);
|
2016-04-24 12:09:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
struct txowatch *watch_txo_(const tal_t *ctx,
|
2017-03-02 13:21:49 +01:00
|
|
|
struct chain_topology *topo,
|
2018-02-12 11:13:04 +01:00
|
|
|
struct channel *channel,
|
2017-12-18 07:41:52 +01:00
|
|
|
const struct bitcoin_txid *txid,
|
2016-04-24 12:09:21 +02:00
|
|
|
unsigned int output,
|
2018-02-12 11:13:04 +01:00
|
|
|
enum watch_result (*cb)(struct channel *channel,
|
2016-06-30 01:40:11 +02:00
|
|
|
const struct bitcoin_tx *tx,
|
|
|
|
size_t input_num,
|
2017-08-23 02:58:44 +02:00
|
|
|
const struct block *block,
|
2016-06-30 01:40:11 +02:00
|
|
|
void *),
|
2016-04-24 12:09:21 +02:00
|
|
|
void *cbdata)
|
|
|
|
{
|
|
|
|
struct txowatch *w = tal(ctx, struct txowatch);
|
|
|
|
|
2017-03-02 13:21:49 +01:00
|
|
|
w->topo = topo;
|
2016-04-24 12:09:21 +02:00
|
|
|
w->out.txid = *txid;
|
|
|
|
w->out.index = output;
|
2018-02-12 11:13:04 +01:00
|
|
|
w->channel = channel;
|
2016-04-24 12:09:21 +02:00
|
|
|
w->cb = cb;
|
|
|
|
w->cbdata = cbdata;
|
|
|
|
|
2017-03-02 13:21:49 +01:00
|
|
|
txowatch_hash_add(&w->topo->txowatches, w);
|
2016-04-24 12:09:21 +02:00
|
|
|
tal_add_destructor(w, destroy_txowatch);
|
|
|
|
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
2017-08-18 06:43:53 +02:00
|
|
|
/* Returns true if we fired a callback */
|
|
|
|
static bool txw_fire(struct chain_topology *topo,
|
|
|
|
struct txwatch *txw,
|
|
|
|
const struct bitcoin_tx *tx,
|
|
|
|
unsigned int depth)
|
|
|
|
{
|
|
|
|
enum watch_result r;
|
|
|
|
|
|
|
|
if (depth == txw->depth)
|
|
|
|
return false;
|
2018-02-12 11:13:04 +01:00
|
|
|
log_debug(txw->channel->log,
|
2017-09-16 01:35:06 +02:00
|
|
|
"Got depth change %u->%u for %s",
|
|
|
|
txw->depth, depth,
|
2017-12-18 07:41:52 +01:00
|
|
|
type_to_string(ltmp, struct bitcoin_txid, &txw->txid));
|
2017-08-18 06:43:53 +02:00
|
|
|
txw->depth = depth;
|
2018-02-12 11:13:04 +01:00
|
|
|
r = txw->cb(txw->channel, tx, txw->depth, txw->cbdata);
|
2017-08-18 06:43:53 +02:00
|
|
|
switch (r) {
|
|
|
|
case DELETE_WATCH:
|
|
|
|
tal_free(txw);
|
|
|
|
return true;
|
|
|
|
case KEEP_WATCHING:
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
fatal("txwatch callback %p returned %i\n", txw->cb, r);
|
|
|
|
}
|
|
|
|
|
2017-03-02 13:21:49 +01:00
|
|
|
void txwatch_fire(struct chain_topology *topo,
|
2017-08-18 06:43:53 +02:00
|
|
|
const struct bitcoin_tx *tx,
|
2016-04-24 12:20:35 +02:00
|
|
|
unsigned int depth)
|
2016-01-21 21:15:28 +01:00
|
|
|
{
|
2017-12-18 07:41:52 +01:00
|
|
|
struct bitcoin_txid txid;
|
2017-08-18 06:43:53 +02:00
|
|
|
struct txwatch *txw;
|
|
|
|
|
|
|
|
bitcoin_txid(tx, &txid);
|
|
|
|
txw = txwatch_hash_get(&topo->txwatches, &txid);
|
|
|
|
|
|
|
|
if (txw)
|
|
|
|
txw_fire(topo, txw, tx, depth);
|
2016-01-21 21:15:28 +01:00
|
|
|
}
|
|
|
|
|
2017-03-02 13:21:49 +01:00
|
|
|
void txowatch_fire(struct chain_topology *topo,
|
2016-04-24 12:18:35 +02:00
|
|
|
const struct txowatch *txow,
|
2016-05-03 03:30:20 +02:00
|
|
|
const struct bitcoin_tx *tx,
|
2017-08-23 02:58:44 +02:00
|
|
|
size_t input_num,
|
|
|
|
const struct block *block)
|
2016-01-21 21:15:28 +01:00
|
|
|
{
|
2017-12-18 07:41:52 +01:00
|
|
|
struct bitcoin_txid txid;
|
2016-06-30 01:40:11 +02:00
|
|
|
enum watch_result r;
|
2016-01-21 21:15:28 +01:00
|
|
|
|
2016-04-24 12:09:21 +02:00
|
|
|
bitcoin_txid(tx, &txid);
|
2018-02-12 11:13:04 +01:00
|
|
|
log_debug(txow->channel->log,
|
2017-09-16 01:35:06 +02:00
|
|
|
"Got UTXO spend for %s:%u: %s",
|
2017-12-18 07:41:52 +01:00
|
|
|
type_to_string(ltmp, struct bitcoin_txid, &txow->out.txid),
|
2016-04-24 12:18:35 +02:00
|
|
|
txow->out.index,
|
2017-12-18 07:41:52 +01:00
|
|
|
type_to_string(ltmp, struct bitcoin_txid, &txid));
|
2017-09-16 01:35:06 +02:00
|
|
|
|
2018-02-12 11:13:04 +01:00
|
|
|
r = txow->cb(txow->channel, tx, input_num, block, txow->cbdata);
|
2016-06-30 01:40:11 +02:00
|
|
|
switch (r) {
|
|
|
|
case DELETE_WATCH:
|
|
|
|
tal_free(txow);
|
|
|
|
return;
|
|
|
|
case KEEP_WATCHING:
|
|
|
|
return;
|
|
|
|
}
|
2017-09-16 01:35:06 +02:00
|
|
|
fatal("txowatch callback %p returned %i", txow->cb, r);
|
2016-01-21 21:11:49 +01:00
|
|
|
}
|
|
|
|
|
2017-03-02 13:21:49 +01:00
|
|
|
void watch_topology_changed(struct chain_topology *topo)
|
2016-01-21 21:11:49 +01:00
|
|
|
{
|
2016-04-24 12:18:35 +02:00
|
|
|
struct txwatch_hash_iter i;
|
|
|
|
struct txwatch *w;
|
|
|
|
bool needs_rerun;
|
|
|
|
|
|
|
|
again:
|
|
|
|
/* Iterating a htable during deletes is safe, but might skip entries. */
|
|
|
|
needs_rerun = false;
|
2017-03-02 13:21:49 +01:00
|
|
|
for (w = txwatch_hash_first(&topo->txwatches, &i);
|
2016-04-24 12:18:35 +02:00
|
|
|
w;
|
2017-03-02 13:21:49 +01:00
|
|
|
w = txwatch_hash_next(&topo->txwatches, &i)) {
|
2017-08-18 06:43:53 +02:00
|
|
|
u32 depth;
|
|
|
|
const struct bitcoin_tx *tx;
|
|
|
|
|
|
|
|
depth = get_tx_depth(topo, &w->txid, &tx);
|
|
|
|
if (depth)
|
|
|
|
needs_rerun |= txw_fire(topo, w, tx, depth);
|
2016-01-21 21:11:49 +01:00
|
|
|
}
|
2016-04-24 12:18:35 +02:00
|
|
|
if (needs_rerun)
|
|
|
|
goto again;
|
2016-01-21 21:11:49 +01:00
|
|
|
}
|