mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-03-01 17:47:30 +01:00
coin_moves: update withdrawal logic to account for 'variable owner' txs
Our existing coin_moves tracking logic assumed that any tx we had an input in belonged to *all* of our wallet (not a bad assumption as long as there was no way to update a tx that spends our wallets) Now that we've got `signpsbt` implemented, however, we need to be careful about how we account for withdrawals. For now we do a best guess at what the feerate is, and lump all of our spent outputs as a 'withdrawal' when it's impossible to disambiguate
This commit is contained in:
parent
ee549a2af9
commit
2e9c387f45
19 changed files with 152 additions and 46 deletions
|
@ -22,6 +22,9 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED)
|
||||||
/* Generated stub for amount_sat_eq */
|
/* Generated stub for amount_sat_eq */
|
||||||
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
||||||
|
/* Generated stub for amount_sat_less */
|
||||||
|
bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
|
{ fprintf(stderr, "amount_sat_less called!\n"); abort(); }
|
||||||
/* Generated stub for amount_sat_sub */
|
/* Generated stub for amount_sat_sub */
|
||||||
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
||||||
struct amount_sat a UNNEEDED,
|
struct amount_sat a UNNEEDED,
|
||||||
|
|
|
@ -23,6 +23,9 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED)
|
||||||
/* Generated stub for amount_sat_eq */
|
/* Generated stub for amount_sat_eq */
|
||||||
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
||||||
|
/* Generated stub for amount_sat_less */
|
||||||
|
bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
|
{ fprintf(stderr, "amount_sat_less called!\n"); abort(); }
|
||||||
/* Generated stub for amount_sat_sub */
|
/* Generated stub for amount_sat_sub */
|
||||||
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
||||||
struct amount_sat a UNNEEDED,
|
struct amount_sat a UNNEEDED,
|
||||||
|
|
|
@ -47,6 +47,9 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED)
|
||||||
/* Generated stub for amount_sat_eq */
|
/* Generated stub for amount_sat_eq */
|
||||||
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
||||||
|
/* Generated stub for amount_sat_less */
|
||||||
|
bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
|
{ fprintf(stderr, "amount_sat_less called!\n"); abort(); }
|
||||||
/* Generated stub for amount_sat_sub */
|
/* Generated stub for amount_sat_sub */
|
||||||
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
||||||
struct amount_sat a UNNEEDED,
|
struct amount_sat a UNNEEDED,
|
||||||
|
|
|
@ -50,6 +50,9 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED)
|
||||||
/* Generated stub for amount_sat_eq */
|
/* Generated stub for amount_sat_eq */
|
||||||
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
||||||
|
/* Generated stub for amount_sat_less */
|
||||||
|
bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
|
{ fprintf(stderr, "amount_sat_less called!\n"); abort(); }
|
||||||
/* Generated stub for amount_sat_sub */
|
/* Generated stub for amount_sat_sub */
|
||||||
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
||||||
struct amount_sat a UNNEEDED,
|
struct amount_sat a UNNEEDED,
|
||||||
|
|
|
@ -27,6 +27,9 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED)
|
||||||
/* Generated stub for amount_sat_eq */
|
/* Generated stub for amount_sat_eq */
|
||||||
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
||||||
|
/* Generated stub for amount_sat_less */
|
||||||
|
bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
|
{ fprintf(stderr, "amount_sat_less called!\n"); abort(); }
|
||||||
/* Generated stub for amount_sat_sub */
|
/* Generated stub for amount_sat_sub */
|
||||||
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
||||||
struct amount_sat a UNNEEDED,
|
struct amount_sat a UNNEEDED,
|
||||||
|
|
|
@ -22,6 +22,9 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED)
|
||||||
/* Generated stub for amount_sat_eq */
|
/* Generated stub for amount_sat_eq */
|
||||||
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
||||||
|
/* Generated stub for amount_sat_less */
|
||||||
|
bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
|
{ fprintf(stderr, "amount_sat_less called!\n"); abort(); }
|
||||||
/* Generated stub for amount_sat_sub */
|
/* Generated stub for amount_sat_sub */
|
||||||
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
||||||
struct amount_sat a UNNEEDED,
|
struct amount_sat a UNNEEDED,
|
||||||
|
|
|
@ -23,6 +23,9 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED)
|
||||||
/* Generated stub for amount_sat_eq */
|
/* Generated stub for amount_sat_eq */
|
||||||
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
||||||
|
/* Generated stub for amount_sat_less */
|
||||||
|
bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
|
{ fprintf(stderr, "amount_sat_less called!\n"); abort(); }
|
||||||
/* Generated stub for amount_sat_sub */
|
/* Generated stub for amount_sat_sub */
|
||||||
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
||||||
struct amount_sat a UNNEEDED,
|
struct amount_sat a UNNEEDED,
|
||||||
|
|
|
@ -22,6 +22,9 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED)
|
||||||
/* Generated stub for amount_sat_eq */
|
/* Generated stub for amount_sat_eq */
|
||||||
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
||||||
|
/* Generated stub for amount_sat_less */
|
||||||
|
bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
|
{ fprintf(stderr, "amount_sat_less called!\n"); abort(); }
|
||||||
/* Generated stub for amount_sat_sub */
|
/* Generated stub for amount_sat_sub */
|
||||||
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
||||||
struct amount_sat a UNNEEDED,
|
struct amount_sat a UNNEEDED,
|
||||||
|
|
|
@ -19,6 +19,9 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED)
|
||||||
/* Generated stub for amount_sat_eq */
|
/* Generated stub for amount_sat_eq */
|
||||||
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
||||||
|
/* Generated stub for amount_sat_less */
|
||||||
|
bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
|
{ fprintf(stderr, "amount_sat_less called!\n"); abort(); }
|
||||||
/* Generated stub for amount_sat_sub */
|
/* Generated stub for amount_sat_sub */
|
||||||
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
||||||
struct amount_sat a UNNEEDED,
|
struct amount_sat a UNNEEDED,
|
||||||
|
|
|
@ -21,6 +21,9 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED)
|
||||||
/* Generated stub for amount_sat_eq */
|
/* Generated stub for amount_sat_eq */
|
||||||
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
||||||
|
/* Generated stub for amount_sat_less */
|
||||||
|
bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
|
{ fprintf(stderr, "amount_sat_less called!\n"); abort(); }
|
||||||
/* Generated stub for amount_sat_sub */
|
/* Generated stub for amount_sat_sub */
|
||||||
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
||||||
struct amount_sat a UNNEEDED,
|
struct amount_sat a UNNEEDED,
|
||||||
|
|
|
@ -19,6 +19,9 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED)
|
||||||
/* Generated stub for amount_sat_eq */
|
/* Generated stub for amount_sat_eq */
|
||||||
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
||||||
|
/* Generated stub for amount_sat_less */
|
||||||
|
bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
|
{ fprintf(stderr, "amount_sat_less called!\n"); abort(); }
|
||||||
/* Generated stub for amount_sat_sub */
|
/* Generated stub for amount_sat_sub */
|
||||||
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
||||||
struct amount_sat a UNNEEDED,
|
struct amount_sat a UNNEEDED,
|
||||||
|
|
|
@ -24,6 +24,9 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED)
|
||||||
/* Generated stub for amount_sat_eq */
|
/* Generated stub for amount_sat_eq */
|
||||||
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
||||||
|
/* Generated stub for amount_sat_less */
|
||||||
|
bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
|
{ fprintf(stderr, "amount_sat_less called!\n"); abort(); }
|
||||||
/* Generated stub for amount_sat_sub */
|
/* Generated stub for amount_sat_sub */
|
||||||
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
||||||
struct amount_sat a UNNEEDED,
|
struct amount_sat a UNNEEDED,
|
||||||
|
|
|
@ -23,6 +23,9 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED)
|
||||||
/* Generated stub for amount_sat_eq */
|
/* Generated stub for amount_sat_eq */
|
||||||
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
||||||
|
/* Generated stub for amount_sat_less */
|
||||||
|
bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
|
{ fprintf(stderr, "amount_sat_less called!\n"); abort(); }
|
||||||
/* Generated stub for amount_sat_sub */
|
/* Generated stub for amount_sat_sub */
|
||||||
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
||||||
struct amount_sat a UNNEEDED,
|
struct amount_sat a UNNEEDED,
|
||||||
|
|
|
@ -20,6 +20,9 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED)
|
||||||
/* Generated stub for amount_sat_eq */
|
/* Generated stub for amount_sat_eq */
|
||||||
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
||||||
|
/* Generated stub for amount_sat_less */
|
||||||
|
bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
|
{ fprintf(stderr, "amount_sat_less called!\n"); abort(); }
|
||||||
/* Generated stub for amount_sat_sub */
|
/* Generated stub for amount_sat_sub */
|
||||||
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
||||||
struct amount_sat a UNNEEDED,
|
struct amount_sat a UNNEEDED,
|
||||||
|
|
|
@ -36,6 +36,9 @@ void amount_msat_from_u64(struct amount_msat *msat UNNEEDED, u64 millisatoshis U
|
||||||
/* Generated stub for amount_sat_eq */
|
/* Generated stub for amount_sat_eq */
|
||||||
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
||||||
|
/* Generated stub for amount_sat_less */
|
||||||
|
bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
|
{ fprintf(stderr, "amount_sat_less called!\n"); abort(); }
|
||||||
/* Generated stub for amount_sat_sub */
|
/* Generated stub for amount_sat_sub */
|
||||||
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
||||||
struct amount_sat a UNNEEDED,
|
struct amount_sat a UNNEEDED,
|
||||||
|
|
|
@ -26,6 +26,9 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED)
|
||||||
/* Generated stub for amount_sat_eq */
|
/* Generated stub for amount_sat_eq */
|
||||||
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
||||||
|
/* Generated stub for amount_sat_less */
|
||||||
|
bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
|
{ fprintf(stderr, "amount_sat_less called!\n"); abort(); }
|
||||||
/* Generated stub for amount_sat_sub */
|
/* Generated stub for amount_sat_sub */
|
||||||
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
||||||
struct amount_sat a UNNEEDED,
|
struct amount_sat a UNNEEDED,
|
||||||
|
|
|
@ -26,6 +26,9 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED)
|
||||||
/* Generated stub for amount_sat_eq */
|
/* Generated stub for amount_sat_eq */
|
||||||
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
||||||
|
/* Generated stub for amount_sat_less */
|
||||||
|
bool amount_sat_less(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
||||||
|
{ fprintf(stderr, "amount_sat_less called!\n"); abort(); }
|
||||||
/* Generated stub for amount_sat_sub */
|
/* Generated stub for amount_sat_sub */
|
||||||
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
||||||
struct amount_sat a UNNEEDED,
|
struct amount_sat a UNNEEDED,
|
||||||
|
|
|
@ -662,7 +662,7 @@ static void updates_complete(struct chain_topology *topo)
|
||||||
next_topology_timer(topo);
|
next_topology_timer(topo);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void record_output_spend(struct lightningd *ld,
|
static void record_utxo_spent(struct lightningd *ld,
|
||||||
const struct bitcoin_txid *txid,
|
const struct bitcoin_txid *txid,
|
||||||
const struct bitcoin_txid *utxo_txid,
|
const struct bitcoin_txid *utxo_txid,
|
||||||
u32 vout, u32 blockheight,
|
u32 vout, u32 blockheight,
|
||||||
|
@ -673,11 +673,13 @@ static void record_output_spend(struct lightningd *ld,
|
||||||
u8 *ctx = tal(NULL, u8);
|
u8 *ctx = tal(NULL, u8);
|
||||||
|
|
||||||
utxo = wallet_utxo_get(ctx, ld->wallet, utxo_txid, vout);
|
utxo = wallet_utxo_get(ctx, ld->wallet, utxo_txid, vout);
|
||||||
if (!utxo)
|
if (!utxo) {
|
||||||
log_broken(ld->log, "No record of utxo %s:%d",
|
log_broken(ld->log, "No record of utxo %s:%d",
|
||||||
type_to_string(tmpctx, struct bitcoin_txid,
|
type_to_string(tmpctx, struct bitcoin_txid,
|
||||||
utxo_txid),
|
utxo_txid),
|
||||||
vout);
|
vout);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
*input_amt = utxo->amount;
|
*input_amt = utxo->amount;
|
||||||
mvt = new_coin_spend_track(ctx, txid, utxo_txid, vout, blockheight);
|
mvt = new_coin_spend_track(ctx, txid, utxo_txid, vout, blockheight);
|
||||||
|
@ -685,23 +687,14 @@ static void record_output_spend(struct lightningd *ld,
|
||||||
tal_free(ctx);
|
tal_free(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void record_tx_outs_and_fees(struct lightningd *ld, const struct bitcoin_tx *tx,
|
static void record_outputs_as_withdraws(const tal_t *ctx,
|
||||||
struct bitcoin_txid *txid, u32 blockheight,
|
struct lightningd *ld,
|
||||||
struct amount_sat inputs_total)
|
const struct bitcoin_tx *tx,
|
||||||
|
struct bitcoin_txid *txid,
|
||||||
|
u32 blockheight)
|
||||||
{
|
{
|
||||||
struct amount_sat fee;
|
|
||||||
struct chain_coin_mvt *mvt;
|
struct chain_coin_mvt *mvt;
|
||||||
size_t i;
|
for (size_t i = 0; i < tx->wtx->num_outputs; i++) {
|
||||||
u8 *ctx = tal(NULL, u8);
|
|
||||||
|
|
||||||
if (!tx)
|
|
||||||
log_broken(ld->log, "We have no record of transaction %s",
|
|
||||||
type_to_string(ctx, struct bitcoin_txid, txid));
|
|
||||||
|
|
||||||
/* We record every output on this transaction as a withdraw */
|
|
||||||
/* FIXME: collaborative tx will need to keep track of which
|
|
||||||
* outputs are ours */
|
|
||||||
for (i = 0; i < tx->wtx->num_outputs; i++) {
|
|
||||||
struct amount_asset asset;
|
struct amount_asset asset;
|
||||||
struct amount_sat outval;
|
struct amount_sat outval;
|
||||||
if (elements_tx_output_is_fee(tx, i))
|
if (elements_tx_output_is_fee(tx, i))
|
||||||
|
@ -709,18 +702,55 @@ static void record_tx_outs_and_fees(struct lightningd *ld, const struct bitcoin_
|
||||||
asset = bitcoin_tx_output_get_amount(tx, i);
|
asset = bitcoin_tx_output_get_amount(tx, i);
|
||||||
assert(amount_asset_is_main(&asset));
|
assert(amount_asset_is_main(&asset));
|
||||||
outval = amount_asset_to_sat(&asset);
|
outval = amount_asset_to_sat(&asset);
|
||||||
mvt = new_coin_withdrawal_sat(ctx, "wallet", txid, txid,
|
mvt = new_coin_withdrawal_sat(ctx, "wallet", txid,
|
||||||
i, blockheight, outval);
|
txid, i, blockheight,
|
||||||
|
outval);
|
||||||
notify_chain_mvt(ld, mvt);
|
notify_chain_mvt(ld, mvt);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void record_tx_outs_and_fees(struct lightningd *ld,
|
||||||
|
const struct bitcoin_tx *tx,
|
||||||
|
struct bitcoin_txid *txid,
|
||||||
|
u32 blockheight,
|
||||||
|
struct amount_sat inputs_total,
|
||||||
|
bool our_tx)
|
||||||
|
{
|
||||||
|
struct amount_sat fee, out_val;
|
||||||
|
struct chain_coin_mvt *mvt;
|
||||||
|
bool ok;
|
||||||
|
struct wally_psbt *psbt = NULL;
|
||||||
|
u8 *ctx = tal(NULL, u8);
|
||||||
|
|
||||||
|
/* We own every input on this tx, so track withdrawals precisely */
|
||||||
|
if (our_tx) {
|
||||||
|
record_outputs_as_withdraws(ctx, ld, tx, txid, blockheight);
|
||||||
fee = bitcoin_tx_compute_fee_w_inputs(tx, inputs_total);
|
fee = bitcoin_tx_compute_fee_w_inputs(tx, inputs_total);
|
||||||
|
goto log_fee;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: look up stashed psbt! */
|
||||||
|
if (!psbt) {
|
||||||
|
fee = bitcoin_tx_compute_fee_w_inputs(tx, inputs_total);
|
||||||
|
ok = amount_sat_sub(&out_val, inputs_total, fee);
|
||||||
|
assert(ok);
|
||||||
|
|
||||||
|
/* We don't have detailed withdrawal info for this tx,
|
||||||
|
* so we log the wallet withdrawal as a single entry */
|
||||||
|
mvt = new_coin_withdrawal_sat(ctx, "wallet", txid, NULL,
|
||||||
|
0, blockheight, out_val);
|
||||||
|
notify_chain_mvt(ld, mvt);
|
||||||
|
goto log_fee;
|
||||||
|
}
|
||||||
|
|
||||||
|
fee = AMOUNT_SAT(0);
|
||||||
|
|
||||||
/* Note that to figure out the *total* 'onchain'
|
/* Note that to figure out the *total* 'onchain'
|
||||||
* cost of a channel, you'll want to also include
|
* cost of a channel, you'll want to also include
|
||||||
* fees logged here, to the 'wallet' account (for funding tx).
|
* fees logged here, to the 'wallet' account (for funding tx).
|
||||||
* You can do this in post by accounting for any 'chain_fees' logged for
|
* You can do this in post by accounting for any 'chain_fees' logged for
|
||||||
* the funding txid when looking at a channel. */
|
* the funding txid when looking at a channel. */
|
||||||
|
log_fee:
|
||||||
notify_chain_mvt(ld,
|
notify_chain_mvt(ld,
|
||||||
new_coin_chain_fees_sat(ctx, "wallet", txid,
|
new_coin_chain_fees_sat(ctx, "wallet", txid,
|
||||||
blockheight, fee));
|
blockheight, fee));
|
||||||
|
@ -736,7 +766,7 @@ static void topo_update_spends(struct chain_topology *topo, struct block *b)
|
||||||
const struct short_channel_id *scid;
|
const struct short_channel_id *scid;
|
||||||
for (size_t i = 0; i < tal_count(b->full_txs); i++) {
|
for (size_t i = 0; i < tal_count(b->full_txs); i++) {
|
||||||
const struct bitcoin_tx *tx = b->full_txs[i];
|
const struct bitcoin_tx *tx = b->full_txs[i];
|
||||||
bool our_tx = false;
|
bool our_tx = true, includes_our_spend = false;
|
||||||
struct bitcoin_txid txid;
|
struct bitcoin_txid txid;
|
||||||
struct amount_sat inputs_total = AMOUNT_SAT(0);
|
struct amount_sat inputs_total = AMOUNT_SAT(0);
|
||||||
|
|
||||||
|
@ -758,34 +788,22 @@ static void topo_update_spends(struct chain_topology *topo, struct block *b)
|
||||||
tal_free(scid);
|
tal_free(scid);
|
||||||
}
|
}
|
||||||
|
|
||||||
our_tx |= our_spend;
|
our_tx &= our_spend;
|
||||||
|
includes_our_spend |= our_spend;
|
||||||
if (our_spend) {
|
if (our_spend) {
|
||||||
struct amount_sat input_amt;
|
struct amount_sat input_amt;
|
||||||
bool ok;
|
bool ok;
|
||||||
|
|
||||||
record_output_spend(topo->ld, &txid, &outpoint_txid,
|
record_utxo_spent(topo->ld, &txid, &outpoint_txid,
|
||||||
input->index, b->height, &input_amt);
|
input->index, b->height, &input_amt);
|
||||||
ok = amount_sat_add(&inputs_total, inputs_total, input_amt);
|
ok = amount_sat_add(&inputs_total, inputs_total, input_amt);
|
||||||
assert(ok);
|
assert(ok);
|
||||||
} else if (our_tx)
|
}
|
||||||
log_broken(topo->ld->log, "Recording fee spend for tx %s but "
|
|
||||||
"our wallet did not contribute input %s:%d",
|
|
||||||
type_to_string(tmpctx, struct bitcoin_txid,
|
|
||||||
&txid),
|
|
||||||
type_to_string(tmpctx, struct bitcoin_txid,
|
|
||||||
&outpoint_txid),
|
|
||||||
input->index);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For now we assume that if one of the spent utxos
|
if (includes_our_spend)
|
||||||
* in this tx is 'ours', that we own all of the
|
|
||||||
* utxos and therefore paid all of the fees
|
|
||||||
* FIXME: update once interactive tx construction
|
|
||||||
* is a reality */
|
|
||||||
if (our_tx)
|
|
||||||
record_tx_outs_and_fees(topo->ld, tx, &txid,
|
record_tx_outs_and_fees(topo->ld, tx, &txid,
|
||||||
b->height, inputs_total);
|
b->height, inputs_total, our_tx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ from flaky import flaky # noqa: F401
|
||||||
from pyln.client import RpcError, Millisatoshi
|
from pyln.client import RpcError, Millisatoshi
|
||||||
from utils import (
|
from utils import (
|
||||||
only_one, wait_for, sync_blockheight, EXPERIMENTAL_FEATURES, COMPAT,
|
only_one, wait_for, sync_blockheight, EXPERIMENTAL_FEATURES, COMPAT,
|
||||||
VALGRIND
|
VALGRIND, check_coin_moves
|
||||||
)
|
)
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
@ -568,7 +568,9 @@ def test_sign_and_send_psbt(node_factory, bitcoind, chainparams):
|
||||||
"""
|
"""
|
||||||
amount = 1000000
|
amount = 1000000
|
||||||
total_outs = 12
|
total_outs = 12
|
||||||
l1 = node_factory.get_node(feerates=(7500, 7500, 7500, 7500))
|
coin_mvt_plugin = os.path.join(os.getcwd(), 'tests/plugins/coin_movements.py')
|
||||||
|
l1 = node_factory.get_node(options={'plugin': coin_mvt_plugin},
|
||||||
|
feerates=(7500, 7500, 7500, 7500))
|
||||||
l2 = node_factory.get_node()
|
l2 = node_factory.get_node()
|
||||||
addr = chainparams['example_addr']
|
addr = chainparams['example_addr']
|
||||||
|
|
||||||
|
@ -677,6 +679,41 @@ def test_sign_and_send_psbt(node_factory, bitcoind, chainparams):
|
||||||
with pytest.raises(RpcError, match=r"should be a PSBT, not"):
|
with pytest.raises(RpcError, match=r"should be a PSBT, not"):
|
||||||
l1.rpc.signpsbt(modded_psbt)
|
l1.rpc.signpsbt(modded_psbt)
|
||||||
|
|
||||||
|
wallet_coin_mvts = [
|
||||||
|
{'type': 'chain_mvt', 'credit': 1000000000, 'debit': 0, 'tag': 'deposit'},
|
||||||
|
{'type': 'chain_mvt', 'credit': 1000000000, 'debit': 0, 'tag': 'deposit'},
|
||||||
|
{'type': 'chain_mvt', 'credit': 1000000000, 'debit': 0, 'tag': 'deposit'},
|
||||||
|
{'type': 'chain_mvt', 'credit': 1000000000, 'debit': 0, 'tag': 'deposit'},
|
||||||
|
{'type': 'chain_mvt', 'credit': 1000000000, 'debit': 0, 'tag': 'deposit'},
|
||||||
|
{'type': 'chain_mvt', 'credit': 1000000000, 'debit': 0, 'tag': 'deposit'},
|
||||||
|
{'type': 'chain_mvt', 'credit': 1000000000, 'debit': 0, 'tag': 'deposit'},
|
||||||
|
{'type': 'chain_mvt', 'credit': 1000000000, 'debit': 0, 'tag': 'deposit'},
|
||||||
|
{'type': 'chain_mvt', 'credit': 1000000000, 'debit': 0, 'tag': 'deposit'},
|
||||||
|
{'type': 'chain_mvt', 'credit': 1000000000, 'debit': 0, 'tag': 'deposit'},
|
||||||
|
{'type': 'chain_mvt', 'credit': 1000000000, 'debit': 0, 'tag': 'deposit'},
|
||||||
|
{'type': 'chain_mvt', 'credit': 1000000000, 'debit': 0, 'tag': 'deposit'},
|
||||||
|
{'type': 'chain_mvt', 'credit': 0, 'debit': 0, 'tag': 'spend_track'},
|
||||||
|
{'type': 'chain_mvt', 'credit': 0, 'debit': 0, 'tag': 'spend_track'},
|
||||||
|
{'type': 'chain_mvt', 'credit': 0, 'debit': 0, 'tag': 'spend_track'},
|
||||||
|
{'type': 'chain_mvt', 'credit': 0, 'debit': 0, 'tag': 'spend_track'},
|
||||||
|
# Nicely splits out withdrawals and chain fees, because it's all our tx
|
||||||
|
{'type': 'chain_mvt', 'credit': 0, 'debit': 988255000, 'tag': 'withdrawal'},
|
||||||
|
{'type': 'chain_mvt', 'credit': 0, 'debit': 3000000000, 'tag': 'withdrawal'},
|
||||||
|
{'type': 'chain_mvt', 'credit': 0, 'debit': 11745000, 'tag': 'chain_fees'},
|
||||||
|
{'type': 'chain_mvt', 'credit': 988255000, 'debit': 0, 'tag': 'deposit'},
|
||||||
|
{'type': 'chain_mvt', 'credit': 0, 'debit': 0, 'tag': 'spend_track'},
|
||||||
|
{'type': 'chain_mvt', 'credit': 0, 'debit': 0, 'tag': 'spend_track'},
|
||||||
|
{'type': 'chain_mvt', 'credit': 0, 'debit': 0, 'tag': 'spend_track'},
|
||||||
|
{'type': 'chain_mvt', 'credit': 0, 'debit': 0, 'tag': 'spend_track'},
|
||||||
|
# Note that this is technically wrong since we paid 11745sat in fees
|
||||||
|
# but since it includes inputs / outputs from a second node, we can't
|
||||||
|
# do proper acccounting for it.
|
||||||
|
{'type': 'chain_mvt', 'credit': 0, 'debit': 4000000000, 'tag': 'withdrawal'},
|
||||||
|
{'type': 'chain_mvt', 'credit': 0, 'debit': 0, 'tag': 'chain_fees'},
|
||||||
|
{'type': 'chain_mvt', 'credit': 988255000, 'debit': 0, 'tag': 'deposit'},
|
||||||
|
]
|
||||||
|
check_coin_moves(l1, 'wallet', wallet_coin_mvts)
|
||||||
|
|
||||||
|
|
||||||
def test_txsend(node_factory, bitcoind, chainparams):
|
def test_txsend(node_factory, bitcoind, chainparams):
|
||||||
amount = 1000000
|
amount = 1000000
|
||||||
|
|
Loading…
Add table
Reference in a new issue