mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
change fees: more accurate rounding for change amount
We were getting off-by-one for the total amount that the change is for, since it rounds the fee *down*, independent of the total weight of the entire tx. We fix this by using the diff btw the fee of the total weight (w/ and w/o the change output)
This commit is contained in:
parent
914e3dd082
commit
04b6ad06cb
14
bitcoin/tx.c
14
bitcoin/tx.c
@ -899,14 +899,22 @@ size_t bitcoin_tx_simple_input_weight(bool p2sh)
|
|||||||
bitcoin_tx_simple_input_witness_weight());
|
bitcoin_tx_simple_input_witness_weight());
|
||||||
}
|
}
|
||||||
|
|
||||||
struct amount_sat change_amount(struct amount_sat excess, u32 feerate_perkw)
|
struct amount_sat change_amount(struct amount_sat excess, u32 feerate_perkw,
|
||||||
|
size_t total_weight)
|
||||||
{
|
{
|
||||||
size_t outweight;
|
size_t outweight;
|
||||||
|
struct amount_sat change_fee;
|
||||||
|
|
||||||
/* Must be able to pay for its own additional weight */
|
/* Must be able to pay for its own additional weight */
|
||||||
outweight = bitcoin_tx_output_weight(BITCOIN_SCRIPTPUBKEY_P2WPKH_LEN);
|
outweight = bitcoin_tx_output_weight(BITCOIN_SCRIPTPUBKEY_P2WPKH_LEN);
|
||||||
if (!amount_sat_sub(&excess,
|
|
||||||
excess, amount_tx_fee(feerate_perkw, outweight)))
|
/* Rounding can cause off by one errors, so we do this */
|
||||||
|
if (!amount_sat_sub(&change_fee,
|
||||||
|
amount_tx_fee(feerate_perkw, outweight + total_weight),
|
||||||
|
amount_tx_fee(feerate_perkw, total_weight)))
|
||||||
|
return AMOUNT_SAT(0);
|
||||||
|
|
||||||
|
if (!amount_sat_sub(&excess, excess, change_fee))
|
||||||
return AMOUNT_SAT(0);
|
return AMOUNT_SAT(0);
|
||||||
|
|
||||||
/* Must be non-dust */
|
/* Must be non-dust */
|
||||||
|
@ -289,7 +289,11 @@ size_t bitcoin_tx_simple_input_weight(bool p2sh);
|
|||||||
* If it's not worth (or possible) to make change, returns AMOUNT_SAT(0).
|
* If it's not worth (or possible) to make change, returns AMOUNT_SAT(0).
|
||||||
* Otherwise returns the amount of the change output to add (@excess minus
|
* Otherwise returns the amount of the change output to add (@excess minus
|
||||||
* the additional fee for the change output itself).
|
* the additional fee for the change output itself).
|
||||||
|
*
|
||||||
|
* We pass in the total_weight of the tx (up until this point) so as
|
||||||
|
* to avoid any off-by-one errors with rounding the change fee (down)
|
||||||
*/
|
*/
|
||||||
struct amount_sat change_amount(struct amount_sat excess, u32 feerate_perkw);
|
struct amount_sat change_amount(struct amount_sat excess, u32 feerate_perkw,
|
||||||
|
size_t total_weight);
|
||||||
|
|
||||||
#endif /* LIGHTNING_BITCOIN_TX_H */
|
#endif /* LIGHTNING_BITCOIN_TX_H */
|
||||||
|
@ -474,7 +474,8 @@ mw_after_fundpsbt(struct command *cmd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Handle any change output. */
|
/* Handle any change output. */
|
||||||
mw->change_amount = change_amount(excess_sat, feerate_per_kw);
|
mw->change_amount = change_amount(excess_sat, feerate_per_kw,
|
||||||
|
estimated_final_weight);
|
||||||
mw->change_needed = !amount_sat_eq(mw->change_amount, AMOUNT_SAT(0));
|
mw->change_needed = !amount_sat_eq(mw->change_amount, AMOUNT_SAT(0));
|
||||||
|
|
||||||
if (mw->change_needed)
|
if (mw->change_needed)
|
||||||
|
@ -277,6 +277,7 @@ static struct command_result *psbt_created(struct command *cmd,
|
|||||||
const jsmntok_t *psbttok;
|
const jsmntok_t *psbttok;
|
||||||
struct out_req *req;
|
struct out_req *req;
|
||||||
struct amount_sat excess;
|
struct amount_sat excess;
|
||||||
|
u32 weight;
|
||||||
|
|
||||||
psbttok = json_get_member(buf, result, "psbt");
|
psbttok = json_get_member(buf, result, "psbt");
|
||||||
txp->psbt = json_tok_psbt(txp, buf, psbttok);
|
txp->psbt = json_tok_psbt(txp, buf, psbttok);
|
||||||
@ -300,6 +301,14 @@ static struct command_result *psbt_created(struct command *cmd,
|
|||||||
result->end - result->start,
|
result->end - result->start,
|
||||||
buf + result->start);
|
buf + result->start);
|
||||||
|
|
||||||
|
if (!json_to_number(buf, json_get_member(buf, result,
|
||||||
|
"estimated_final_weight"),
|
||||||
|
&weight))
|
||||||
|
return command_fail(cmd, LIGHTNINGD,
|
||||||
|
"Unparsable estimated_final_weight: '%.*s'",
|
||||||
|
result->end - result->start,
|
||||||
|
buf + result->start);
|
||||||
|
|
||||||
/* If we have an "all" output, now we can derive its value: excess
|
/* If we have an "all" output, now we can derive its value: excess
|
||||||
* in this case will be total value after inputs paid for themselves. */
|
* in this case will be total value after inputs paid for themselves. */
|
||||||
if (txp->all_output_idx != -1) {
|
if (txp->all_output_idx != -1) {
|
||||||
@ -313,7 +322,7 @@ static struct command_result *psbt_created(struct command *cmd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* So, do we need change? */
|
/* So, do we need change? */
|
||||||
txp->change_amount = change_amount(excess, txp->feerate);
|
txp->change_amount = change_amount(excess, txp->feerate, weight);
|
||||||
if (amount_sat_eq(txp->change_amount, AMOUNT_SAT(0)))
|
if (amount_sat_eq(txp->change_amount, AMOUNT_SAT(0)))
|
||||||
return finish_txprepare(cmd, txp);
|
return finish_txprepare(cmd, txp);
|
||||||
|
|
||||||
|
@ -369,7 +369,7 @@ static struct command_result *finish_psbt(struct command *cmd,
|
|||||||
u8 *b32script;
|
u8 *b32script;
|
||||||
|
|
||||||
/* Checks for dust, returns 0sat if below dust */
|
/* Checks for dust, returns 0sat if below dust */
|
||||||
change = change_amount(excess, feerate_per_kw);
|
change = change_amount(excess, feerate_per_kw, weight);
|
||||||
if (!amount_sat_greater(change, AMOUNT_SAT(0))) {
|
if (!amount_sat_greater(change, AMOUNT_SAT(0))) {
|
||||||
excess_as_change = false;
|
excess_as_change = false;
|
||||||
goto fee_calc;
|
goto fee_calc;
|
||||||
|
Loading…
Reference in New Issue
Block a user