#include #include #include #include #include static const char *mvt_types[] = { "chain_mvt", "channel_mvt" }; const char *mvt_type_str(enum mvt_type type) { return mvt_types[type]; } static const char *mvt_tags[] = { "deposit", "withdrawal", "chain_fees", "penalty", "invoice", "routed", "journal_entry", "onchain_htlc", "pushed", "spend_track", }; const char *mvt_tag_str(enum mvt_tag tag) { return mvt_tags[tag]; } struct channel_coin_mvt *new_channel_coin_mvt(const tal_t *ctx, const struct channel_id *cid, struct sha256 payment_hash, u64 *part_id, struct amount_msat amount, enum mvt_tag tag, bool is_credit) { struct channel_coin_mvt *mvt = tal(ctx, struct channel_coin_mvt); mvt->chan_id = *cid; mvt->payment_hash = tal_dup(mvt, struct sha256, &payment_hash); mvt->part_id = part_id; mvt->tag = tag; if (is_credit) { mvt->credit = amount; mvt->debit = AMOUNT_MSAT(0); } else { mvt->debit = amount; mvt->credit = AMOUNT_MSAT(0); } return mvt; } static struct chain_coin_mvt *new_chain_coin_mvt(const tal_t *ctx, const char *account_name, const struct bitcoin_txid *tx_txid, const struct bitcoin_txid *output_txid, u32 vout, const struct sha256 *payment_hash TAKES, u32 blockheight, enum mvt_tag tag, struct amount_msat amount, bool is_credit) { struct chain_coin_mvt *mvt = tal(ctx, struct chain_coin_mvt); if (account_name) mvt->account_name = tal_strndup(mvt, account_name, strlen(account_name)); else mvt->account_name = NULL; mvt->tx_txid = tx_txid; mvt->output_txid = output_txid; mvt->vout = vout; /* for htlc's that are filled onchain, we also have a * preimage, NULL otherwise */ if (payment_hash) mvt->payment_hash = tal_dup(mvt, struct sha256, payment_hash); else mvt->payment_hash = NULL; mvt->blockheight = blockheight; mvt->tag = tag; if (is_credit) { mvt->credit = amount; mvt->debit = AMOUNT_MSAT(0); } else { mvt->debit = amount; mvt->credit = AMOUNT_MSAT(0); } return mvt; } static struct chain_coin_mvt *new_chain_coin_mvt_sat(const tal_t *ctx, const char *account_name, const struct bitcoin_txid *tx_txid, const struct bitcoin_txid *output_txid, u32 vout, const struct sha256 *payment_hash TAKES, u32 blockheight, enum mvt_tag tag, struct amount_sat amt_sat, bool is_credit) { struct amount_msat amt_msat; bool ok; ok = amount_sat_to_msat(&amt_msat, amt_sat); assert(ok); return new_chain_coin_mvt(ctx, account_name, tx_txid, output_txid, vout, payment_hash, blockheight, tag, amt_msat, is_credit); } struct chain_coin_mvt *new_coin_withdrawal(const tal_t *ctx, const char *account_name, const struct bitcoin_txid *tx_txid, const struct bitcoin_txid *out_txid, u32 vout, u32 blockheight, struct amount_msat amount) { return new_chain_coin_mvt(ctx, account_name, tx_txid, out_txid, vout, NULL, blockheight, WITHDRAWAL, amount, false); } struct chain_coin_mvt *new_coin_withdrawal_sat(const tal_t *ctx, const char *account_name, const struct bitcoin_txid *tx_txid, const struct bitcoin_txid *out_txid, u32 vout, u32 blockheight, struct amount_sat amount) { struct amount_msat amt_msat; bool ok; ok = amount_sat_to_msat(&amt_msat, amount); assert(ok); return new_coin_withdrawal(ctx, account_name, tx_txid, out_txid, vout, blockheight, amt_msat); } struct chain_coin_mvt *new_coin_chain_fees(const tal_t *ctx, const char *account_name, const struct bitcoin_txid *tx_txid, u32 blockheight, struct amount_msat amount) { return new_chain_coin_mvt(ctx, account_name, tx_txid, NULL, 0, NULL, blockheight, CHAIN_FEES, amount, false); } struct chain_coin_mvt *new_coin_chain_fees_sat(const tal_t *ctx, const char *account_name, const struct bitcoin_txid *tx_txid, u32 blockheight, struct amount_sat amount) { struct amount_msat amt_msat; bool ok; ok = amount_sat_to_msat(&amt_msat, amount); assert(ok); return new_coin_chain_fees(ctx, account_name, tx_txid, blockheight, amt_msat); } struct chain_coin_mvt *new_coin_journal_entry(const tal_t *ctx, const char *account_name, const struct bitcoin_txid *txid, const struct bitcoin_txid *out_txid, u32 vout, u32 blockheight, struct amount_msat amount, bool is_credit) { return new_chain_coin_mvt(ctx, account_name, txid, out_txid, vout, NULL, blockheight, JOURNAL, amount, is_credit); } struct chain_coin_mvt *new_coin_deposit(const tal_t *ctx, const char *account_name, const struct bitcoin_txid *txid, u32 vout, u32 blockheight, struct amount_msat amount) { return new_chain_coin_mvt(ctx, account_name, txid, txid, vout, NULL, blockheight, DEPOSIT, amount, true); } struct chain_coin_mvt *new_coin_deposit_sat(const tal_t *ctx, const char *account_name, const struct bitcoin_txid *txid, u32 vout, u32 blockheight, struct amount_sat amount) { struct amount_msat amt_msat; bool ok; ok = amount_sat_to_msat(&amt_msat, amount); assert(ok); return new_coin_deposit(ctx, account_name, txid, vout, blockheight, amt_msat); } struct chain_coin_mvt *new_coin_penalty_sat(const tal_t *ctx, const char *account_name, const struct bitcoin_txid *txid, const struct bitcoin_txid *out_txid, u32 vout, u32 blockheight, struct amount_sat amount) { struct amount_msat amt_msat; bool ok; ok = amount_sat_to_msat(&amt_msat, amount); assert(ok); return new_chain_coin_mvt(ctx, account_name, txid, out_txid, vout, NULL, blockheight, PENALTY, amt_msat, false); } struct chain_coin_mvt *new_coin_onchain_htlc_sat(const tal_t *ctx, const char *account_name, const struct bitcoin_txid *txid, const struct bitcoin_txid *out_txid, u32 vout, struct sha256 payment_hash, u32 blockheight, struct amount_sat amount, bool is_credit) { return new_chain_coin_mvt_sat(ctx, account_name, txid, out_txid, vout, take(tal_dup(NULL, struct sha256, &payment_hash)), blockheight, ONCHAIN_HTLC, amount, is_credit); } struct chain_coin_mvt *new_coin_pushed(const tal_t *ctx, const char *account_name, const struct bitcoin_txid *txid, u32 blockheight, struct amount_msat amount) { return new_chain_coin_mvt(ctx, account_name, txid, NULL, 0, NULL, blockheight, PUSHED, amount, false); } struct chain_coin_mvt *new_coin_spend_track(const tal_t *ctx, const struct bitcoin_txid *txid, const struct bitcoin_txid *out_txid, u32 vout, u32 blockheight) { return new_chain_coin_mvt_sat(ctx, "wallet", txid, out_txid, vout, NULL, blockheight, SPEND_TRACK, AMOUNT_SAT(0), false); } struct coin_mvt *finalize_chain_mvt(const tal_t *ctx, const struct chain_coin_mvt *chain_mvt, const char *bip173_name, u32 timestamp, struct node_id *node_id, s64 count) { struct coin_mvt *mvt = tal(ctx, struct coin_mvt); mvt->account_id = tal_strndup(mvt, chain_mvt->account_name, strlen(chain_mvt->account_name)); mvt->bip173_name = tal_strndup(mvt, bip173_name, strlen(bip173_name)); mvt->type = CHAIN_MVT; mvt->id.tx_txid = chain_mvt->tx_txid; mvt->id.output_txid = chain_mvt->output_txid; mvt->id.vout = chain_mvt->vout; mvt->id.payment_hash = chain_mvt->payment_hash; mvt->tag = chain_mvt->tag; mvt->credit = chain_mvt->credit; mvt->debit = chain_mvt->debit; mvt->timestamp = timestamp; mvt->blockheight = chain_mvt->blockheight; mvt->version = COIN_MVT_VERSION; mvt->node_id = node_id; mvt->counter = count; return mvt; } struct coin_mvt *finalize_channel_mvt(const tal_t *ctx, const struct channel_coin_mvt *chan_mvt, const char *bip173_name, u32 timestamp, struct node_id *node_id, s64 count) { struct coin_mvt *mvt = tal(ctx, struct coin_mvt); mvt->account_id = type_to_string(mvt, struct channel_id, &chan_mvt->chan_id); mvt->bip173_name = tal_strndup(mvt, bip173_name, strlen(bip173_name)); mvt->type = CHANNEL_MVT; mvt->id.payment_hash = chan_mvt->payment_hash; mvt->id.part_id = chan_mvt->part_id; mvt->id.tx_txid = NULL; mvt->id.output_txid = NULL; mvt->id.vout = 0; mvt->tag = chan_mvt->tag; mvt->credit = chan_mvt->credit; mvt->debit = chan_mvt->debit; mvt->timestamp = timestamp; /* channel movements don't have a blockheight */ mvt->blockheight = 0; mvt->version = COIN_MVT_VERSION; mvt->node_id = node_id; mvt->counter = count; return mvt; } void towire_chain_coin_mvt(u8 **pptr, const struct chain_coin_mvt *mvt) { if (mvt->account_name) { towire_u16(pptr, strlen(mvt->account_name)); towire_u8_array(pptr, (u8 *)mvt->account_name, strlen(mvt->account_name)); } else towire_u16(pptr, 0); towire_bitcoin_txid(pptr, cast_const(struct bitcoin_txid *, mvt->tx_txid)); if (mvt->output_txid) { towire_bool(pptr, true); towire_bitcoin_txid(pptr, cast_const(struct bitcoin_txid *, mvt->output_txid)); } else towire_bool(pptr, false); towire_u32(pptr, mvt->vout); if (mvt->payment_hash) { towire_bool(pptr, true); towire_sha256(pptr, mvt->payment_hash); } else towire_bool(pptr, false); towire_u32(pptr, mvt->blockheight); towire_u8(pptr, mvt->tag); towire_amount_msat(pptr, mvt->credit); towire_amount_msat(pptr, mvt->debit); } void fromwire_chain_coin_mvt(const u8 **cursor, size_t *max, struct chain_coin_mvt *mvt) { u16 account_name_len; account_name_len = fromwire_u16(cursor, max); if (account_name_len) { mvt->account_name = tal_arr(mvt, char, account_name_len); fromwire_u8_array(cursor, max, (u8 *)mvt->account_name, account_name_len); } else mvt->account_name = NULL; mvt->tx_txid = tal(mvt, struct bitcoin_txid); fromwire_bitcoin_txid(cursor, max, cast_const(struct bitcoin_txid *, mvt->tx_txid)); if (fromwire_bool(cursor, max)) { mvt->output_txid = tal(mvt, struct bitcoin_txid); fromwire_bitcoin_txid(cursor, max, cast_const(struct bitcoin_txid *, mvt->output_txid)); } else mvt->output_txid = NULL; mvt->vout = fromwire_u32(cursor, max); if (fromwire_bool(cursor, max)) { mvt->payment_hash = tal(mvt, struct sha256); fromwire_sha256(cursor, max, mvt->payment_hash); } else mvt->payment_hash = NULL; mvt->blockheight = fromwire_u32(cursor, max); mvt->tag = fromwire_u8(cursor, max); mvt->credit = fromwire_amount_msat(cursor, max); mvt->debit = fromwire_amount_msat(cursor, max); }