mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 18:11:28 +01:00
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:
parent
175515b914
commit
e8d10edbe5
@ -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:
|
||||
|
@ -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 \
|
||||
|
@ -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,
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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(); }
|
||||
|
@ -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(); }
|
||||
|
Loading…
Reference in New Issue
Block a user