From 043224a1b1dcb91d02461ab6c0a86f6ff924c67c Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Wed, 18 Mar 2020 18:32:33 -0500 Subject: [PATCH] coin_mvt: initial commit for coin movement structs and helpers Fleshes out coin movement structs etc --- common/Makefile | 1 + common/coin_mvt.c | 182 ++++++++++++++++++++++++++++++++++++++++++++++ common/coin_mvt.h | 168 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 351 insertions(+) create mode 100644 common/coin_mvt.c create mode 100644 common/coin_mvt.h diff --git a/common/Makefile b/common/Makefile index 5fe1e9fe3..cf77ce064 100644 --- a/common/Makefile +++ b/common/Makefile @@ -10,6 +10,7 @@ COMMON_SRC_NOGEN := \ common/blinding.c \ common/bolt11.c \ common/channel_config.c \ + common/coin_mvt.c \ common/close_tx.c \ common/configdir.c \ common/crypto_state.c \ diff --git a/common/coin_mvt.c b/common/coin_mvt.c new file mode 100644 index 000000000..5b8ede958 --- /dev/null +++ b/common/coin_mvt.c @@ -0,0 +1,182 @@ +#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", +}; +const char *mvt_tag_str(enum mvt_tag tag) +{ + return mvt_tags[tag]; +} + +static const char *mvt_units[] = { "btc", }; +const char *mvt_unit_str(enum mvt_unit_type unit) +{ + return mvt_units[unit]; +} + +static u64 mvt_count = 0; + +struct channel_coin_mvt *new_channel_coin_mvt(const tal_t *ctx, + struct bitcoin_txid *funding_txid, + u32 funding_outnum, + struct sha256 payment_hash, + u32 part_id, + struct amount_msat amount, + enum mvt_tag tag, + bool is_credit, + enum mvt_unit_type unit) +{ + struct channel_coin_mvt *mvt = tal(ctx, struct channel_coin_mvt); + + derive_channel_id(&mvt->chan_id, funding_txid, funding_outnum); + 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); + } + + mvt->unit = unit; + + return mvt; +} + +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, + struct sha256 *payment_hash, + enum mvt_tag tag, + struct amount_msat amount, + bool is_credit, + enum mvt_unit_type unit) +{ + 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 */ + mvt->payment_hash = payment_hash; + + mvt->tag = tag; + if (is_credit) { + mvt->credit = amount; + mvt->debit = AMOUNT_MSAT(0); + } else { + mvt->debit = amount; + mvt->credit = AMOUNT_MSAT(0); + } + mvt->unit = unit; + + return mvt; +} + +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, + struct sha256 *payment_hash, + enum mvt_tag tag, + struct amount_sat amt_sat, + bool is_credit, + enum mvt_unit_type unit) +{ + struct amount_msat amt_msat; + if (!amount_sat_to_msat(&amt_msat, amt_sat)) + return NULL; + + return new_chain_coin_mvt(ctx, account_name, tx_txid, + output_txid, vout, payment_hash, + tag, amt_msat, is_credit, + unit); +} + +struct coin_mvt *finalize_chain_mvt(const tal_t *ctx, + const struct chain_coin_mvt *chain_mvt, + u32 timestamp, + u32 blockheight, + struct node_id *node_id) +{ + 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->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->unit = chain_mvt->unit; + mvt->timestamp = timestamp; + mvt->blockheight = blockheight; + mvt->version = COIN_MVT_VERSION; + mvt->node_id = node_id; + mvt->counter = mvt_count++; + + return mvt; +} + +struct coin_mvt *finalize_channel_mvt(const tal_t *ctx, + const struct channel_coin_mvt *chan_mvt, + u32 timestamp, u32 blockheight, + struct node_id *node_id) +{ + struct coin_mvt *mvt = tal(ctx, struct coin_mvt); + + mvt->account_id = type_to_string(mvt, struct channel_id, + &chan_mvt->chan_id); + 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->unit = chan_mvt->unit; + mvt->timestamp = timestamp; + mvt->blockheight = blockheight; + mvt->version = COIN_MVT_VERSION; + mvt->node_id = node_id; + mvt->counter = mvt_count++; + + return mvt; +} diff --git a/common/coin_mvt.h b/common/coin_mvt.h new file mode 100644 index 000000000..ef1ee1a78 --- /dev/null +++ b/common/coin_mvt.h @@ -0,0 +1,168 @@ +#ifndef LIGHTNING_COMMON_COIN_MVT_H +#define LIGHTNING_COMMON_COIN_MVT_H +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#define COIN_MVT_VERSION 1 + +#define COIN_MVT_ACCT_WALLET "wallet" + +enum mvt_type { + CHAIN_MVT = 0, + CHANNEL_MVT = 1, +}; + +enum mvt_tag { + DEPOSIT = 0, + WITHDRAWAL = 1, + CHAIN_FEES = 2, + PENALTY = 3, + INVOICE = 4, + ROUTED = 5, + JOURNAL = 6, + ONCHAIN_HTLC = 7, + PUSHED = 8, +}; + +enum mvt_unit_type { + BTC = 0, +}; + +struct channel_coin_mvt { + /* account_id */ + struct channel_id chan_id; + + /* identifier */ + struct sha256 *payment_hash; + + /* mutlti-part payments may share a payment hash, + * so we should also record a 'part-id' for them */ + u32 part_id; + + /* label / tag */ + enum mvt_tag tag; + + /* only one or the other */ + struct amount_msat credit; + struct amount_msat debit; + + /* what currency is this coin denominated in? */ + enum mvt_unit_type unit; +}; + +struct chain_coin_mvt { + /* account_id */ + const char *account_name; + const struct bitcoin_txid *tx_txid; + const struct bitcoin_txid *output_txid; + u32 vout; + + /* some on-chain movements have a payment hash */ + struct sha256 *payment_hash; + + /* label / tag */ + enum mvt_tag tag; + + /* only one or the other */ + struct amount_msat credit; + struct amount_msat debit; + + /* what currency is this coin denominated in? */ + enum mvt_unit_type unit; +}; + +/* differs depending on type!? */ +struct mvt_id { + struct sha256 *payment_hash; + u32 part_id; + const struct bitcoin_txid *tx_txid; + const struct bitcoin_txid *output_txid; + u32 vout; +}; + +struct coin_mvt { + /* name of 'account': wallet, external, */ + const char *account_id; + + /* type of movement: channel or chain */ + enum mvt_type type; + + /* identifier */ + struct mvt_id id; + + /* label / tag */ + enum mvt_tag tag; + + /* only one or the other */ + struct amount_msat credit; + struct amount_msat debit; + + /* what currency is this coin denominated in? */ + enum mvt_unit_type unit; + + u32 timestamp; + u32 blockheight; + + /* version is a counter of the format of the data payload that + * makes up a coin movement */ + u8 version; + + /* node originating this movement */ + struct node_id *node_id; + + /* id of this movement (on this node) */ + // FIXME: what if node restarts? + u64 counter; +}; + +struct channel_coin_mvt *new_channel_coin_mvt(const tal_t *ctx, + struct bitcoin_txid *funding_txid, + u32 funding_outnum, + struct sha256 payment_hash, + u32 part_id, + struct amount_msat amount, + enum mvt_tag tag, + bool is_credit, + enum mvt_unit_type unit); +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, + struct sha256 *payment_hash, + enum mvt_tag tag, + struct amount_msat amount, + bool is_credit, + enum mvt_unit_type unit); +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, + struct sha256 *payment_hash, + enum mvt_tag tag, + struct amount_sat amt_sat, + bool is_credit, + enum mvt_unit_type unit); +struct coin_mvt *finalize_chain_mvt(const tal_t *ctx, + const struct chain_coin_mvt *chain_mvt, + u32 timestamp, + u32 blockheight, + struct node_id *node_id); +struct coin_mvt *finalize_channel_mvt(const tal_t *ctx, + const struct channel_coin_mvt *chan_mvt, + u32 timestamp, u32 blockheight, + struct node_id *node_id); + +const char *mvt_type_str(enum mvt_type type); +const char *mvt_tag_str(enum mvt_tag tag); +const char *mvt_unit_str(enum mvt_unit_type unit); + +#endif /* LIGHTNING_COMMON_COIN_MVT_H */