Browse Source

daemon/output_to_htlc: routines to map outputs for HTLCs for a given commit_num.

And use this to resolve old transactions by comparing outputs with
HTLCs.

Rather than remembering the output ordering for every one of their
previous commitment transactions, we just remember the commitment
number for each commitment txid, and when we see it, derive all the
HTLC scriptpubkeys and the to-us and to-them scriptpubkeys, and figure
out which is which.

This avoids us having to save information on disk, except for the
txid->commitment-number mapping (and the shachain).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 9 years ago
parent
commit
ec3344ce6e
  1. 11
      bitcoin/script.c
  2. 3
      bitcoin/script.h
  3. 2
      daemon/Makefile
  4. 79
      daemon/output_to_htlc.c
  5. 21
      daemon/output_to_htlc.h
  6. 472
      daemon/peer.c
  7. 2
      daemon/peer.h

11
bitcoin/script.c

@ -467,6 +467,17 @@ bool is_p2sh(const u8 *script, size_t script_len)
return true;
}
bool is_p2wsh(const u8 *script, size_t script_len)
{
if (script_len != 1 + 1 + sizeof(struct sha256))
return false;
if (script[0] != OP_0)
return false;
if (script[1] != OP_PUSHBYTES(sizeof(struct sha256)))
return false;
return true;
}
/* A common script pattern: A can have it with secret, or B can have
* it after delay. */
u8 *bitcoin_redeem_secret_or_delay(const tal_t *ctx,

3
bitcoin/script.h

@ -112,6 +112,9 @@ u8 **bitcoin_witness_htlc(const tal_t *ctx,
/* Is this a pay to script hash? */
bool is_p2sh(const u8 *script, size_t script_len);
/* Is this (version 0) pay to witness script hash? */
bool is_p2wsh(const u8 *script, size_t script_len);
/* Are these two scripts equal? */
bool scripteq(const u8 *s1, size_t s1len, const u8 *s2, size_t s2len);

2
daemon/Makefile

@ -27,6 +27,7 @@ DAEMON_SRC := \
daemon/netaddr.c \
daemon/onion.c \
daemon/opt_time.c \
daemon/output_to_htlc.c \
daemon/packets.c \
daemon/pay.c \
daemon/payment.c \
@ -67,6 +68,7 @@ DAEMON_HEADERS := \
daemon/netaddr.h \
daemon/onion.h \
daemon/opt_time.h \
daemon/output_to_htlc.h \
daemon/packets.h \
daemon/pay.h \
daemon/payment.h \

79
daemon/output_to_htlc.c

@ -0,0 +1,79 @@
#include "commit_tx.h"
#include "output_to_htlc.h"
#include "peer.h"
/* FIXME: Array makes this O(n^2). Use a hash table. */
struct wscript_by_wpkh {
struct htlc *h;
const u8 *wscript;
struct sha256 hash;
};
struct htlc_output_map {
struct wscript_by_wpkh *wpkh;
};
struct htlc_output_map *get_htlc_output_map(const tal_t *ctx,
const struct peer *peer,
const struct sha256 *rhash,
enum htlc_side side,
unsigned int commit_num)
{
struct htlc_map_iter it;
struct htlc *h;
size_t i;
struct htlc_output_map *omap = tal(ctx, struct htlc_output_map);
/* FIXME: use commit_num to filter htlcs. */
if (side == LOCAL)
assert(commit_num <= peer->local.commit->commit_num);
else
assert(commit_num <= peer->remote.commit->commit_num);
omap->wpkh = tal_arr(omap, struct wscript_by_wpkh,
htlc_map_count(&peer->htlcs));
for (i = 0, h = htlc_map_first(&peer->htlcs, &it);
h;
h = htlc_map_next(&peer->htlcs, &it)) {
omap->wpkh[i].h = h;
omap->wpkh[i].wscript = wscript_for_htlc(omap, peer, h, rhash,
side);
sha256(&omap->wpkh[i].hash,
omap->wpkh[i].wscript,
tal_count(omap->wpkh[i].wscript));
i++;
}
tal_resize(&omap->wpkh, i);
return omap;
}
static struct wscript_by_wpkh *get_wpkh(struct htlc_output_map *omap,
const u8 *script, size_t script_len)
{
size_t i;
if (!is_p2wsh(script, script_len))
return NULL;
for (i = 0; i < tal_count(omap->wpkh); i++) {
if (!memcmp(script + 2, omap->wpkh[i].hash.u.u8,
sizeof(omap->wpkh[i].hash)))
return &omap->wpkh[i];
}
return NULL;
}
/* Which wscript does this pay to? */
struct htlc *txout_get_htlc(struct htlc_output_map *omap,
const u8 *script, size_t script_len,
const u8 **wscript)
{
struct wscript_by_wpkh *wpkh = get_wpkh(omap, script, script_len);
if (wpkh) {
*wscript = wpkh->wscript;
return wpkh->h;
}
return NULL;
}

21
daemon/output_to_htlc.h

@ -0,0 +1,21 @@
#ifndef LIGHTNING_DAEMON_OUTPUT_TO_HTLC_H
#define LIGHTNING_DAEMON_OUTPUT_TO_HTLC_H
#include "config.h"
#include "htlc.h"
struct peer;
struct sha256;
/* Get a map of HTLCs (including at least those at the given commit_num). */
struct htlc_output_map *get_htlc_output_map(const tal_t *ctx,
const struct peer *peer,
const struct sha256 *rhash,
enum htlc_side side,
unsigned int commit_num);
/* If this scriptPubkey pays to a HTLC, get the full wscript */
struct htlc *txout_get_htlc(struct htlc_output_map *omap,
const u8 *script, size_t script_len,
const u8 **wscript);
#endif /* LIGHTNING_DAEMON_OUTPUT_TO_HTLC_H */

472
daemon/peer.c

@ -11,6 +11,7 @@
#include "log.h"
#include "names.h"
#include "onion.h"
#include "output_to_htlc.h"
#include "packets.h"
#include "pay.h"
#include "payment.h"
@ -1324,14 +1325,6 @@ static struct htlc *htlc_by_index(const struct commit_info *ci, size_t index)
return ci->cstate->side[THEIRS].htlcs[index];
}
static bool htlc_is_ours(const struct commit_info *ci, size_t index)
{
assert(index >= 2);
index -= 2;
return index < tal_count(ci->cstate->side[OURS].htlcs);
}
/* Create a HTLC fulfill transaction */
static const struct bitcoin_tx *htlc_fulfill_tx(const struct peer *peer,
const struct commit_info *ci,
@ -2198,16 +2191,77 @@ static enum watch_result anchor_depthchange(struct peer *peer,
return KEEP_WATCHING;
}
static struct commit_info *find_commit(struct commit_info *ci,
const struct sha256_double *txid)
static bool outputscript_eq(const struct bitcoin_tx_output *out,
size_t i, const u8 *script)
{
while (ci) {
/* Yay, segwit! We can just compare txids, even
* though we don't have both signatures. */
if (structeq(txid, &ci->txid))
return ci;
ci = ci->prev;
if (out[i].script_length != tal_count(script))
return false;
return memcmp(out[i].script, script, out[i].script_length) == 0;
}
/* This tx is their commitment; htlcs array points to NULL (in which case, it's
* to_them_idx or to_us_idx) or a valid HTLC. */
static struct htlc **tx_map_outputs(const struct peer *peer,
const struct sha256 *rhash,
const struct bitcoin_tx *tx,
enum htlc_side side,
unsigned int commit_num,
int *to_us_idx, int *to_them_idx,
const u8 ***wscripts)
{
u8 *to_us, *to_them, *to_them_wscript, *to_us_wscript;
struct htlc_output_map *hmap;
tal_t *tmpctx = tal(peer, char);
struct htlc **htlcs;
size_t i;
*to_us_idx = *to_them_idx = -1;
htlcs = tal_arr(tmpctx, struct htlc *, tx->output_count);
*wscripts = tal_arr(tmpctx, const u8 *, tx->output_count);
to_us = commit_output_to_us(tmpctx, peer, rhash, side, &to_us_wscript);
to_them = commit_output_to_them(tmpctx, peer, rhash, side,
&to_them_wscript);
/* Now generate the wscript hashes for every possible HTLC. */
hmap = get_htlc_output_map(tmpctx, peer, rhash, side, commit_num);
for (i = 0; i < tx->output_count; i++) {
log_debug(peer->log, "%s: output %zi", __func__, i);
if (*to_us_idx == -1 && outputscript_eq(tx->output, i, to_us)) {
log_add(peer->log, " -> to us");
htlcs[i] = NULL;
(*wscripts)[i] = tal_steal(*wscripts, to_us_wscript);
*to_us_idx = i;
continue;
}
if (*to_them_idx == -1 && outputscript_eq(tx->output, i, to_them)) {
log_add(peer->log, " -> to them");
htlcs[i] = NULL;
(*wscripts)[i] = tal_steal(*wscripts, to_them_wscript);
*to_them_idx = i;
continue;
}
/* Must be an HTLC output */
htlcs[i] = txout_get_htlc(hmap,
tx->output[i].script,
tx->output[i].script_length,
wscripts[i]);
if (!htlcs[i]) {
log_add(peer->log, "no HTLC found");
goto fail;
}
tal_steal(htlcs, htlcs[i]);
tal_steal(*wscripts, *wscripts[i]);
log_add(peer->log, "HTLC %"PRIu64, htlcs[i]->id);
}
tal_steal(peer, htlcs);
tal_steal(peer, *wscripts);
tal_free(tmpctx);
return htlcs;
fail:
tal_free(tmpctx);
return NULL;
}
@ -2327,149 +2381,6 @@ static const struct bitcoin_tx *irrevocably_resolved(struct peer *peer)
return peer->closing_onchain.tx;
}
static void connect_input(const struct commit_info *ci,
struct bitcoin_tx_input *input,
u32 index)
{
bitcoin_txid(ci->tx, &input->txid);
input->index = index;
input->amount = tal_dup(ci, u64, &ci->tx->output[index].amount);
}
static void resolve_cheating(struct peer *peer)
{
const struct bitcoin_tx *tx = peer->closing_onchain.tx;
const struct commit_info *ci = peer->closing_onchain.ci;
struct bitcoin_tx *steal_tx;
u8 **wscripts;
size_t i, n, num_to_steal;
int *map;
peer->closing_onchain.resolved
= tal_arrz(tx, const struct bitcoin_tx *, tal_count(ci->map));
/* BOLT #onchain:
*
* If a node sees a *commitment tx* for which it has a revocation
* preimage, it *resolves* the funding transaction output:
*
* 1. _A's main output_: No action is required; this is a
* simple P2WPKH output. This output is considered
* *resolved* by the *commitment tx*.
*/
/* Their commit tx, so our output is [1], theirs in [0]. */
peer->closing_onchain.resolved[1] = tx;
/* BOLT #onchain:
*
* 2. _B's main output_: The node MUST *resolve* this by
* spending using the revocation preimage.
*
* 3. _A's offered HTLCs_: The node MUST *resolve* this by
* spending using the revocation preimage.
*
* 4. _B's offered HTLCs_: The node MUST *resolve* this by
* spending using the revocation preimage. */
num_to_steal = 0;
if (ci->map[0] == -1)
peer->closing_onchain.resolved[0] = tx;
else
num_to_steal++;
for (i = 2; i < tal_count(ci->map); i++)
if (ci->map[i] == -1)
peer->closing_onchain.resolved[i] = tx;
else
num_to_steal++;
/* Nothing to steal? */
if (num_to_steal == 0)
return;
/* BOLT #onchain:
*
* The node MAY use a single transaction to *resolve* all the
* outputs; due to the 300 HTLC-per-party limit (See BOLT #2:
* 3.2. Adding an HTLC) this can be done within a standard
* transaction.
*/
steal_tx = bitcoin_tx(peer, num_to_steal, 1);
wscripts = tal_arr(steal_tx, u8 *, num_to_steal);
n = 0;
if (ci->map[0] != -1) {
connect_input(ci, &steal_tx->input[n], ci->map[0]);
peer->closing_onchain.resolved[0] = steal_tx;
wscripts[n++]
= bitcoin_redeem_secret_or_delay(wscripts,
peer->dstate->secpctx,
&peer->remote.finalkey,
&peer->local.locktime,
&peer->local.finalkey,
&ci->revocation_hash);
}
for (i = 2; i < tal_count(ci->map); i++) {
struct htlc *h;
if (ci->map[i] == -1)
continue;
peer->closing_onchain.resolved[i] = steal_tx;
connect_input(ci, &steal_tx->input[n], ci->map[i]);
h = htlc_by_index(ci, i);
if (!htlc_is_ours(ci, i)) {
wscripts[n]
= bitcoin_redeem_htlc_send(wscripts,
peer->dstate->secpctx,
&peer->remote.finalkey,
&peer->local.finalkey,
&h->expiry,
&peer->local.locktime,
&ci->revocation_hash,
&h->rhash);
} else {
wscripts[n]
= bitcoin_redeem_htlc_recv(wscripts,
peer->dstate->secpctx,
&peer->remote.finalkey,
&peer->local.finalkey,
&h->expiry,
&peer->local.locktime,
&ci->revocation_hash,
&h->rhash);
}
n++;
}
assert(n == num_to_steal);
/* This obscures the order in which HTLCs were received, at least. */
map = tal_arr(steal_tx, int, num_to_steal);
permute_inputs(steal_tx->input, steal_tx->input_count, map);
/* Now, we can sign them all (they're all of same form). */
for (n = 0; n < num_to_steal; n++) {
struct bitcoin_signature sig;
sig.stype = SIGHASH_ALL;
peer_sign_steal_input(peer, steal_tx, map[n], wscripts[n], &sig.sig);
steal_tx->input[map[n]].witness
= bitcoin_witness_secret(steal_tx,
peer->dstate->secpctx,
ci->revocation_preimage,
sizeof(*ci->revocation_preimage),
&sig,
wscripts[n]);
}
broadcast_tx(peer, steal_tx);
}
static enum watch_result our_htlc_spent(struct peer *peer,
const struct bitcoin_tx *tx,
size_t input_num,
@ -2772,9 +2683,9 @@ static enum watch_result our_unilateral_depth(struct peer *peer,
*
* When node A sees its own *commitment tx*:
*/
static void resolve_our_unilateral(struct peer *peer)
static void resolve_our_unilateral(struct peer *peer,
const struct bitcoin_tx *tx)
{
const struct bitcoin_tx *tx = peer->closing_onchain.tx;
const struct commit_info *ci = peer->closing_onchain.ci;
size_t num_ours, num_theirs;
@ -2828,9 +2739,9 @@ static void resolve_our_unilateral(struct peer *peer)
*
* Similarly, when node A sees a *commitment tx* from B:
*/
static void resolve_their_unilateral(struct peer *peer)
static void resolve_their_unilateral(struct peer *peer,
const struct bitcoin_tx *tx)
{
const struct bitcoin_tx *tx = peer->closing_onchain.tx;
const struct commit_info *ci = peer->closing_onchain.ci;
size_t num_ours, num_theirs;
@ -2939,7 +2850,151 @@ static enum watch_result check_for_resolution(struct peer *peer,
return DELETE_WATCH;
}
static bool find_their_old_tx(struct peer *peer,
const struct sha256_double *txid,
u64 *idx)
{
/* FIXME: Don't keep these in memory, search db here. */
struct their_commit *tc;
log_debug_struct(peer->log, "Finding txid %s", struct sha256_double,
txid);
list_for_each(&peer->their_commits, tc, list) {
if (structeq(&tc->txid, txid)) {
*idx = tc->commit_num;
return true;
}
}
return false;
}
static bool resolve_their_steal(struct peer *peer,
const struct bitcoin_tx *tx)
{
u64 commit_num;
struct sha256_double txid;
struct sha256 revocation_preimage, rhash;
int to_us_idx, to_them_idx, i, n;
struct htlc **htlcs;
const u8 **wscripts;
struct bitcoin_tx *steal_tx;
size_t wsize = 0;
u64 input_total = 0, fee;
bitcoin_txid(tx, &txid);
if (!find_their_old_tx(peer, &txid, &commit_num)) {
log_broken_struct(peer->log, "Could not find revoked txid %s",
struct sha256_double, &txid);
return false;
}
if (!shachain_get_hash(&peer->their_preimages,
0xFFFFFFFFFFFFFFFFL - commit_num,
&revocation_preimage)) {
log_broken(peer->log, "Could not get shachain for %"PRIu64,
commit_num);
return false;
}
sha256(&rhash, &revocation_preimage, sizeof(revocation_preimage));
htlcs = tx_map_outputs(peer, &rhash, tx, REMOTE, commit_num,
&to_us_idx, &to_them_idx, &wscripts);
if (!htlcs) {
log_broken(peer->log, "Could not map_htlcs for %"PRIu64,
commit_num);
return false;
}
/* FIXME: Caller should allocate this. */
peer->closing_onchain.resolved
= tal_arr(tx, const struct bitcoin_tx *, tx->output_count);
/* Create steal_tx: don't need to steal to_us output */
if (to_us_idx == -1)
steal_tx = bitcoin_tx(tx, tx->output_count, 1);
else
steal_tx = bitcoin_tx(tx, tx->output_count - 1, 1);
n = 0;
log_debug(peer->log, "Analyzing tx to steal:");
for (i = 0; i < tx->output_count; i++) {
/* BOLT #onchain:
* 1. _A's main output_: No action is required; this is a
* simple P2WPKH output. This output is considered
* *resolved* by the *commitment tx*.
*/
if (i == to_us_idx) {
log_debug(peer->log, "%i is to-us, ignoring", i);
peer->closing_onchain.resolved[i] = tx;
continue;
}
/* BOLT #onchain:
*
* 2. _B's main output_: The node MUST *resolve* this by
* spending using the revocation preimage.
*
* 3. _A's offered HTLCs_: The node MUST *resolve* this by
* spending using the revocation preimage.
*
* 4. _B's offered HTLCs_: The node MUST *resolve* this by
* spending using the revocation preimage.
*/
peer->closing_onchain.resolved[i] = steal_tx;
/* Connect it up. */
steal_tx->input[n].txid = txid;
steal_tx->input[n].index = i;
steal_tx->input[n].amount = tal_dup(steal_tx, u64,
&tx->output[i].amount);
/* Track witness size, for fee. */
wsize += tal_count(wscripts[n]);
input_total += tx->output[i].amount;
n++;
}
assert(n == steal_tx->input_count);
/* FIXME: Dynamic fees! */
fee = peer->dstate->config.closing_fee_rate
* (measure_tx_cost(steal_tx) + wsize) / 1000;
if (fee > input_total || is_dust_amount(input_total - fee)) {
log_unusual(peer->log, "Not worth stealing tiny amount %"PRIu64,
input_total);
/* Consider them all resolved by steal tx. */
for (i = 0; i < tal_count(peer->closing_onchain.resolved); i++)
peer->closing_onchain.resolved[i] = tx;
tal_free(steal_tx);
return true;
}
steal_tx->output[0].amount = input_total - fee;
steal_tx->output[0].script = scriptpubkey_p2sh(steal_tx,
bitcoin_redeem_single(steal_tx,
peer->dstate->secpctx,
&peer->local.finalkey));
steal_tx->output[0].script_length = tal_count(steal_tx->output[0].script);
/* Now, we can sign them all (they're all of same form). */
for (i = 0; i < n; i++) {
struct bitcoin_signature sig;
sig.stype = SIGHASH_ALL;
peer_sign_steal_input(peer, steal_tx, i, wscripts[i], &sig.sig);
steal_tx->input[i].witness
= bitcoin_witness_secret(steal_tx,
peer->dstate->secpctx,
&revocation_preimage,
sizeof(revocation_preimage),
&sig,
wscripts[i]);
}
broadcast_tx(peer, steal_tx);
return true;
}
/* We assume the tx is valid! Don't do a blockchain.info and feed this
* invalid transactions! */
static enum watch_result anchor_spent(struct peer *peer,
@ -2950,13 +3005,16 @@ static enum watch_result anchor_spent(struct peer *peer,
struct sha256_double txid;
Pkt *err;
enum state newstate;
size_t i;
struct htlc_map_iter it;
struct htlc *h;
assert(input_num < tx->input_count);
/* We only ever sign single-input txs. */
if (input_num != 0)
fatal("Anchor spend by non-single input tx");
if (input_num != 0) {
log_broken(peer->log, "Anchor spend by non-single input tx");
goto unknown_spend;
}
/* We may have been following a different spend. Forget it. */
reset_onchain_closing(peer);
@ -2965,50 +3023,47 @@ static enum watch_result anchor_spent(struct peer *peer,
bitcoin_txid(tx, &txid);
/* If we have any HTLCs we're not committed to yet, fail them now. */
for (i = 0; i < tal_count(peer->remote.commit->unacked_changes); i++) {
if (peer->remote.commit->unacked_changes[i].type != HTLC_ADD)
continue;
our_htlc_failed(peer,
peer->remote.commit->unacked_changes[i].add.htlc);
for (h = htlc_map_first(&peer->htlcs, &it);
h;
h = htlc_map_next(&peer->htlcs, &it)) {
if (h->state == SENT_ADD_HTLC) {
our_htlc_failed(peer, h);
}
}
peer->closing_onchain.ci = find_commit(peer->remote.commit, &txid);
if (peer->closing_onchain.ci) {
if (peer->closing_onchain.ci->revocation_preimage) {
newstate = STATE_CLOSE_ONCHAIN_CHEATED;
err = pkt_err(peer, "Revoked transaction seen");
resolve_cheating(peer);
} else {
newstate = STATE_CLOSE_ONCHAIN_THEIR_UNILATERAL;
err = pkt_err(peer, "Unilateral close tx seen");
resolve_their_unilateral(peer);
}
/* A mutual close tx. */
if (is_mutual_close(peer, tx)) {
newstate = STATE_CLOSE_ONCHAIN_MUTUAL;
err = NULL;
resolve_mutual_close(peer);
/* Our unilateral */
} else if (structeq(&peer->local.commit->txid, &txid)) {
newstate = STATE_CLOSE_ONCHAIN_OUR_UNILATERAL;
/* We're almost certainly closed to them by now. */
err = pkt_err(peer, "Our own unilateral close tx seen");
peer->closing_onchain.ci = peer->local.commit;
resolve_our_unilateral(peer);
} else if (is_mutual_close(peer, tx)) {
newstate = STATE_CLOSE_ONCHAIN_MUTUAL;
err = NULL;
resolve_mutual_close(peer);
resolve_our_unilateral(peer, tx);
/* Their unilateral */
} else if (structeq(&peer->remote.commit->txid, &txid)) {
newstate = STATE_CLOSE_ONCHAIN_THEIR_UNILATERAL;
peer->closing_onchain.ci = peer->remote.commit;
err = pkt_err(peer, "Unilateral close tx seen");
resolve_their_unilateral(peer, tx);
/* Their previous, unrevoked unilateral */
} else if (peer->remote.commit->prev
&& !peer->remote.commit->prev->revocation_preimage
&& structeq(&peer->remote.commit->prev->txid, &txid)) {
newstate = STATE_CLOSE_ONCHAIN_THEIR_UNILATERAL;
peer->closing_onchain.ci = peer->remote.commit->prev;
err = pkt_err(peer, "Unilateral close tx seen");
resolve_their_unilateral(peer, tx);
} else if (resolve_their_steal(peer, tx)) {
newstate = STATE_CLOSE_ONCHAIN_CHEATED;
err = pkt_err(peer, "Revoked transaction seen");
} else {
/* BOLT #onchain:
*
* A node SHOULD report an error to the operator if it
* sees a transaction spend the funding transaction
* output which does not fall into one of these
* categories (mutual close, unilateral close, or
* cheating attempt). Such a transaction implies its
* private key has leaked, and funds may be lost.
*/
/* FIXME: Log harder! */
log_broken(peer->log, "Unknown tx spend! Funds may be lost!");
set_peer_state(peer,
STATE_ERR_INFORMATION_LEAK,
"anchor_spent");
return DELETE_WATCH;
log_broken(peer->log, "Unknown anchor spend! Funds may be lost!");
goto unknown_spend;
}
/* BOLT #onchain:
@ -3034,6 +3089,19 @@ static enum watch_result anchor_spent(struct peer *peer,
watch_tx(tx, peer, tx, check_for_resolution, NULL);
return KEEP_WATCHING;
unknown_spend:
/* BOLT #onchain:
*
* A node SHOULD report an error to the operator if it
* sees a transaction spend the funding transaction
* output which does not fall into one of these
* categories (mutual close, unilateral close, or
* cheating attempt). Such a transaction implies its
* private key has leaked, and funds may be lost.
*/
set_peer_state(peer, STATE_ERR_INFORMATION_LEAK, "anchor_spent");
return DELETE_WATCH;
}
static void anchor_timeout(struct peer *peer)

2
daemon/peer.h

@ -195,6 +195,8 @@ struct peer {
struct {
/* Everything (watches, resolved[], etc) tal'ed off this */
const struct bitcoin_tx *tx;
/* Set for STATE_CLOSE_ONCHAIN_THEIR_UNILATERAL
* and STATE_CLOSE_ONCHAIN_OUR_UNILATERAL */
const struct commit_info *ci;
const struct bitcoin_tx **resolved;
} closing_onchain;

Loading…
Cancel
Save