coin moves: record onchain movements after they've been resolved

We pass them back to lightningd who sends out a notification for them
This commit is contained in:
lisa neigut 2020-04-01 21:16:32 -05:00 committed by Rusty Russell
parent 175515b914
commit e8d10edbe5
6 changed files with 189 additions and 0 deletions

View File

@ -178,6 +178,24 @@ static void watch_tx_and_outputs(struct channel *channel,
onchain_txo_watched);
}
static void handle_onchain_log_coin_move(struct channel *channel, const u8 *msg)
{
struct channel_id channel_id;
struct chain_coin_mvt *mvt = tal(NULL, struct chain_coin_mvt);
if (!fromwire_onchain_notify_coin_mvt(msg, mvt)) {
channel_internal_error(channel, "Invalid onchain notify_coin_mvt");
return;
}
derive_channel_id(&channel_id, &channel->funding_txid,
channel->funding_outnum);
mvt->account_name =
type_to_string(mvt, struct channel_id, &channel_id);
notify_chain_mvt(channel->peer->ld, mvt);
tal_free(mvt);
}
static void handle_onchain_broadcast_tx(struct channel *channel, const u8 *msg)
{
struct bitcoin_tx *tx;
@ -384,6 +402,10 @@ static unsigned int onchain_msg(struct subd *sd, const u8 *msg, const int *fds U
onchain_annotate_txout(sd->channel, msg);
break;
case WIRE_ONCHAIN_NOTIFY_COIN_MVT:
handle_onchain_log_coin_move(sd->channel, msg);
break;
/* We send these, not receive them */
case WIRE_ONCHAIN_INIT:
case WIRE_ONCHAIN_SPENT:

View File

@ -50,6 +50,7 @@ ONCHAIND_COMMON_OBJS := \
common/amount.o \
common/bigsize.o \
common/bip32.o \
common/coin_mvt.o \
common/daemon.o \
common/daemon_conn.o \
common/derive_basepoints.o \

View File

@ -1,3 +1,4 @@
#include <common/coin_mvt.h>
#include <common/derive_basepoints.h>
#include <common/htlc_wire.h>
#include <common/wallet.h>
@ -120,3 +121,5 @@ msgdata,onchain_annotate_txin,txid,bitcoin_txid,
msgdata,onchain_annotate_txin,innum,u32,
msgdata,onchain_annotate_txin,type,enum wallet_tx_type,
msgtype,onchain_notify_coin_mvt,5037
msgdata,onchain_notify_coin_mvt,mvt,chain_coin_mvt,

1 #include <common/derive_basepoints.h> #include <common/coin_mvt.h>
1 #include <common/coin_mvt.h>
2 #include <common/derive_basepoints.h> #include <common/derive_basepoints.h>
3 #include <common/htlc_wire.h> #include <common/htlc_wire.h>
4 #include <common/wallet.h> #include <common/wallet.h>
121
122
123
124
125

View File

@ -4,6 +4,7 @@
#include <ccan/mem/mem.h>
#include <ccan/tal/str/str.h>
#include <common/amount.h>
#include <common/coin_mvt.h>
#include <common/derive_basepoints.h>
#include <common/htlc_tx.h>
#include <common/initial_commit_tx.h>
@ -122,6 +123,136 @@ struct tracked_output {
struct sha256 *payment_hash;
};
static void send_coin_mvt(struct chain_coin_mvt *mvt TAKES)
{
wire_sync_write(REQ_FD,
take(towire_onchain_notify_coin_mvt(NULL, mvt)));
if (taken(mvt))
tal_free(mvt);
}
static void record_htlc_fulfilled(const struct bitcoin_txid *txid,
struct tracked_output *out,
bool we_fulfilled)
{
struct chain_coin_mvt *mvt;
/* we're recording the *deposit* of a utxo which contained channel
* funds (htlc).
*
* since we really don't know if this was a 'routed' or 'destination'
* htlc here, we record it as a 'deposit/withdrawal' type */
mvt = new_chain_coin_mvt_sat(NULL, NULL,
txid, &out->txid,
out->outnum,
out->payment_hash,
ONCHAIN_HTLC,
out->sat, we_fulfilled,
BTC);
send_coin_mvt(take(mvt));
}
static void update_ledger_chain_fees(const struct bitcoin_txid *txid,
struct amount_sat fees)
{
struct chain_coin_mvt *mvt;
mvt = new_chain_coin_mvt_sat(NULL, NULL,
txid, NULL, 0, NULL,
CHAIN_FEES, fees,
false, BTC);
if (!mvt)
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"unable to convert %s to msat",
type_to_string(tmpctx, struct amount_sat,
&fees));
send_coin_mvt(take(mvt));
}
/* Log the fees paid on this transaction as 'chain fees'. note that
* you *cannot* pass a chaintopology-originated tx to this method,
* as they don't have the input_amounts populated */
static struct amount_sat record_chain_fees_tx(const struct bitcoin_txid *txid,
const struct bitcoin_tx *tx)
{
struct amount_sat fees;
fees = bitcoin_tx_compute_fee(tx);
status_debug("recording chain fees for tx %s",
type_to_string(tmpctx, struct bitcoin_txid, txid));
update_ledger_chain_fees(txid, fees);
return fees;
}
static void record_channel_withdrawal_minus_fees(const struct bitcoin_txid *tx_txid,
struct tracked_output *out,
struct amount_sat fees)
{
struct chain_coin_mvt *mvt;
struct amount_sat emitted_amt;
if (!amount_sat_sub(&emitted_amt, out->sat, fees))
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"unable to subtract %s from %s",
type_to_string(tmpctx, struct amount_sat,
&fees),
type_to_string(tmpctx, struct amount_sat,
&out->sat));
mvt = new_chain_coin_mvt_sat(NULL, NULL,
tx_txid, &out->txid,
out->outnum, NULL, WITHDRAWAL,
emitted_amt, false,
BTC);
if (!mvt)
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"unable to convert %s to msat",
type_to_string(tmpctx, struct amount_sat,
&out->sat));
send_coin_mvt(take(mvt));
}
static bool is_our_htlc_tx(struct tracked_output *out)
{
return out->resolved &&
(out->resolved->tx_type == OUR_HTLC_TIMEOUT_TX
|| out->resolved->tx_type == OUR_HTLC_SUCCESS_TX);
}
static bool is_channel_deposit(struct tracked_output *out)
{
return out->resolved &&
(out->resolved->tx_type == THEIR_HTLC_FULFILL_TO_US
|| out->resolved->tx_type == OUR_HTLC_SUCCESS_TX);
}
static void record_coin_movements(struct tracked_output *out,
const struct bitcoin_tx *tx,
const struct bitcoin_txid *txid)
{
struct amount_sat fees;
/* there is a case where we've fulfilled an htlc onchain,
* in which case we log a deposit to the channel */
if (is_channel_deposit(out))
record_htlc_fulfilled(txid, out, true);
/* record fees paid for the tx here */
/* FIXME: for now, every resolution generates its own tx,
* this will need to be updated if we switch to batching */
fees = record_chain_fees_tx(txid, tx);
/* we don't record a channel withdrawal until we get to
* the 'exit' utxo, which for local commitment htlc txs
* is the child htlc_tx's output */
if (!is_our_htlc_tx(out))
record_channel_withdrawal_minus_fees(txid, out, fees);
}
/* We vary feerate until signature they offered matches. */
static bool grind_htlc_tx_fee(struct amount_sat *fee,
struct bitcoin_tx *tx,
@ -1064,6 +1195,8 @@ static void output_spent(const struct chainparams *chainparams,
|| out->resolved->tx_type == OUR_HTLC_TIMEOUT_TX)
resolve_htlc_tx(chainparams, outs, i, tx, &txid,
tx_blockheight);
record_coin_movements(out, out->proposal->tx, &txid);
return;
}

View File

@ -97,6 +97,18 @@ void memleak_remove_referenced(struct htable *memtable UNNEEDED, const void *roo
void memleak_scan_region(struct htable *memtable UNNEEDED,
const void *p UNNEEDED, size_t bytelen UNNEEDED)
{ fprintf(stderr, "memleak_scan_region called!\n"); abort(); }
/* Generated stub for new_chain_coin_mvt_sat */
struct chain_coin_mvt *new_chain_coin_mvt_sat(const tal_t *ctx UNNEEDED,
const char *account_name UNNEEDED,
const struct bitcoin_txid *tx_txid UNNEEDED,
const struct bitcoin_txid *output_txid UNNEEDED,
u32 vout UNNEEDED,
struct sha256 *payment_hash UNNEEDED,
enum mvt_tag tag UNNEEDED,
struct amount_sat amt_sat UNNEEDED,
bool is_credit UNNEEDED,
enum mvt_unit_type unit UNNEEDED)
{ fprintf(stderr, "new_chain_coin_mvt_sat called!\n"); abort(); }
/* Generated stub for notleak_ */
void *notleak_(const void *ptr UNNEEDED, bool plus_children UNNEEDED)
{ fprintf(stderr, "notleak_ called!\n"); abort(); }
@ -168,6 +180,9 @@ u8 *towire_onchain_init_reply(const tal_t *ctx UNNEEDED)
/* Generated stub for towire_onchain_missing_htlc_output */
u8 *towire_onchain_missing_htlc_output(const tal_t *ctx UNNEEDED, const struct htlc_stub *htlc UNNEEDED)
{ fprintf(stderr, "towire_onchain_missing_htlc_output called!\n"); abort(); }
/* Generated stub for towire_onchain_notify_coin_mvt */
u8 *towire_onchain_notify_coin_mvt(const tal_t *ctx UNNEEDED, const struct chain_coin_mvt *mvt UNNEEDED)
{ fprintf(stderr, "towire_onchain_notify_coin_mvt called!\n"); abort(); }
/* Generated stub for towire_onchain_unwatch_tx */
u8 *towire_onchain_unwatch_tx(const tal_t *ctx UNNEEDED, const struct bitcoin_txid *txid UNNEEDED)
{ fprintf(stderr, "towire_onchain_unwatch_tx called!\n"); abort(); }

View File

@ -109,6 +109,18 @@ void memleak_remove_referenced(struct htable *memtable UNNEEDED, const void *roo
void memleak_scan_region(struct htable *memtable UNNEEDED,
const void *p UNNEEDED, size_t bytelen UNNEEDED)
{ fprintf(stderr, "memleak_scan_region called!\n"); abort(); }
/* Generated stub for new_chain_coin_mvt_sat */
struct chain_coin_mvt *new_chain_coin_mvt_sat(const tal_t *ctx UNNEEDED,
const char *account_name UNNEEDED,
const struct bitcoin_txid *tx_txid UNNEEDED,
const struct bitcoin_txid *output_txid UNNEEDED,
u32 vout UNNEEDED,
struct sha256 *payment_hash UNNEEDED,
enum mvt_tag tag UNNEEDED,
struct amount_sat amt_sat UNNEEDED,
bool is_credit UNNEEDED,
enum mvt_unit_type unit UNNEEDED)
{ fprintf(stderr, "new_chain_coin_mvt_sat called!\n"); abort(); }
/* Generated stub for notleak_ */
void *notleak_(const void *ptr UNNEEDED, bool plus_children UNNEEDED)
{ fprintf(stderr, "notleak_ called!\n"); abort(); }
@ -186,6 +198,9 @@ u8 *towire_onchain_init_reply(const tal_t *ctx UNNEEDED)
/* Generated stub for towire_onchain_missing_htlc_output */
u8 *towire_onchain_missing_htlc_output(const tal_t *ctx UNNEEDED, const struct htlc_stub *htlc UNNEEDED)
{ fprintf(stderr, "towire_onchain_missing_htlc_output called!\n"); abort(); }
/* Generated stub for towire_onchain_notify_coin_mvt */
u8 *towire_onchain_notify_coin_mvt(const tal_t *ctx UNNEEDED, const struct chain_coin_mvt *mvt UNNEEDED)
{ fprintf(stderr, "towire_onchain_notify_coin_mvt called!\n"); abort(); }
/* Generated stub for towire_onchain_unwatch_tx */
u8 *towire_onchain_unwatch_tx(const tal_t *ctx UNNEEDED, const struct bitcoin_txid *txid UNNEEDED)
{ fprintf(stderr, "towire_onchain_unwatch_tx called!\n"); abort(); }