|
|
@ -73,13 +73,11 @@ u64 htlc_success_fee(u64 feerate_per_kw) |
|
|
|
return feerate_per_kw * 673 / 1000; |
|
|
|
} |
|
|
|
|
|
|
|
static const struct htlc **untrimmed(const tal_t *ctx, |
|
|
|
const struct htlc **htlcs, |
|
|
|
enum side side, |
|
|
|
u64 htlc_fee, u64 dust_limit_satoshis) |
|
|
|
static bool trim(const struct htlc *htlc, |
|
|
|
u64 feerate_per_kw, u64 dust_limit_satoshis, |
|
|
|
enum side side) |
|
|
|
{ |
|
|
|
const struct htlc **arr; |
|
|
|
size_t i, n; |
|
|
|
u64 htlc_fee; |
|
|
|
|
|
|
|
/* BOLT #3:
|
|
|
|
* |
|
|
@ -88,6 +86,10 @@ static const struct htlc **untrimmed(const tal_t *ctx, |
|
|
|
* owner, the commitment transaction MUST NOT contain that output, |
|
|
|
* otherwise it MUST be generated as specified in [Offered HTLC |
|
|
|
* Outputs](#offered-htlc-outputs). |
|
|
|
*/ |
|
|
|
if (htlc_owner(htlc) == side) |
|
|
|
htlc_fee = htlc_timeout_fee(feerate_per_kw); |
|
|
|
/* BOLT #3:
|
|
|
|
* |
|
|
|
* For every received HTLC, if the HTLC amount minus the HTLC-success |
|
|
|
* fee would be less than `dust-limit-satoshis` set by the transaction |
|
|
@ -95,22 +97,25 @@ static const struct htlc **untrimmed(const tal_t *ctx, |
|
|
|
* otherwise it MUST be generated as specified in [Received HTLC |
|
|
|
* Outputs](#received-htlc-outputs). |
|
|
|
*/ |
|
|
|
arr = tal_arr(ctx, const struct htlc *, tal_count(htlcs)); |
|
|
|
for (i = n = 0; i < tal_count(htlcs); i++) { |
|
|
|
if (htlc_owner(htlcs[i]) != side) |
|
|
|
continue; |
|
|
|
if (htlcs[i]->msatoshi / 1000 < dust_limit_satoshis + htlc_fee) |
|
|
|
continue; |
|
|
|
arr[n++] = htlcs[i]; |
|
|
|
} |
|
|
|
else |
|
|
|
htlc_fee = htlc_success_fee(feerate_per_kw); |
|
|
|
|
|
|
|
assert(n <= tal_count(arr)); |
|
|
|
tal_resize(&arr, n); |
|
|
|
return htlc->msatoshi / 1000 < dust_limit_satoshis + htlc_fee; |
|
|
|
} |
|
|
|
|
|
|
|
return arr; |
|
|
|
size_t commit_tx_num_untrimmed(const struct htlc **htlcs, |
|
|
|
u64 feerate_per_kw, u64 dust_limit_satoshis, |
|
|
|
enum side side) |
|
|
|
{ |
|
|
|
size_t i, n; |
|
|
|
|
|
|
|
for (i = n = 0; i < tal_count(htlcs); i++) |
|
|
|
n += !trim(htlcs[i], feerate_per_kw, dust_limit_satoshis, side); |
|
|
|
|
|
|
|
return n; |
|
|
|
} |
|
|
|
|
|
|
|
static u64 commit_tx_base_fee(u64 feerate_per_kw, size_t num_untrimmed_htlcs) |
|
|
|
u64 commit_tx_base_fee(u64 feerate_per_kw, size_t num_untrimmed_htlcs) |
|
|
|
{ |
|
|
|
u64 weight; |
|
|
|
|
|
|
@ -139,6 +144,38 @@ static u64 commit_tx_base_fee(u64 feerate_per_kw, size_t num_untrimmed_htlcs) |
|
|
|
return feerate_per_kw * weight / 1000; |
|
|
|
} |
|
|
|
|
|
|
|
static void add_offered_htlc_out(struct bitcoin_tx *tx, size_t n, |
|
|
|
const struct htlc *htlc, |
|
|
|
const struct pubkey *selfkey, |
|
|
|
const struct pubkey *otherkey) |
|
|
|
{ |
|
|
|
u8 *wscript = bitcoin_wscript_htlc_offer(tx, |
|
|
|
selfkey, otherkey, |
|
|
|
&htlc->rhash); |
|
|
|
tx->output[n].amount = htlc->msatoshi / 1000; |
|
|
|
tx->output[n].script = scriptpubkey_p2wsh(tx, wscript); |
|
|
|
SUPERVERBOSE("# HTLC offered amount %"PRIu64" wscript %s\n", |
|
|
|
tx->output[n].amount, tal_hex(wscript, wscript)); |
|
|
|
tal_free(wscript); |
|
|
|
} |
|
|
|
|
|
|
|
static void add_received_htlc_out(struct bitcoin_tx *tx, size_t n, |
|
|
|
const struct htlc *htlc, |
|
|
|
const struct pubkey *selfkey, |
|
|
|
const struct pubkey *otherkey) |
|
|
|
{ |
|
|
|
u8 *wscript = bitcoin_wscript_htlc_receive(tx, |
|
|
|
&htlc->expiry, |
|
|
|
selfkey, otherkey, |
|
|
|
&htlc->rhash); |
|
|
|
tx->output[n].amount = htlc->msatoshi / 1000; |
|
|
|
tx->output[n].script = scriptpubkey_p2wsh(tx->output, wscript); |
|
|
|
SUPERVERBOSE("# HTLC received amount %"PRIu64" wscript %s\n", |
|
|
|
tx->output[n].amount, |
|
|
|
tal_hex(wscript, wscript)); |
|
|
|
tal_free(wscript); |
|
|
|
} |
|
|
|
|
|
|
|
struct bitcoin_tx *commit_tx(const tal_t *ctx, |
|
|
|
const struct sha256_double *funding_txid, |
|
|
|
unsigned int funding_txout, |
|
|
@ -159,10 +196,9 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx, |
|
|
|
enum side side) |
|
|
|
{ |
|
|
|
const tal_t *tmpctx = tal_tmpctx(ctx); |
|
|
|
const struct htlc **offered, **received; |
|
|
|
u64 base_fee_msat; |
|
|
|
struct bitcoin_tx *tx; |
|
|
|
size_t i, n; |
|
|
|
size_t i, n, untrimmed; |
|
|
|
|
|
|
|
assert(self_pay_msat + other_pay_msat <= funding_satoshis * 1000); |
|
|
|
|
|
|
@ -171,22 +207,16 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx, |
|
|
|
* 1. Calculate which committed HTLCs need to be trimmed (see |
|
|
|
* [Trimmed Outputs](#trimmed-outputs)). |
|
|
|
*/ |
|
|
|
offered = untrimmed(tmpctx, htlcs, side, |
|
|
|
htlc_timeout_fee(feerate_per_kw), |
|
|
|
dust_limit_satoshis); |
|
|
|
received = untrimmed(tmpctx, htlcs, !side, |
|
|
|
htlc_success_fee(feerate_per_kw), |
|
|
|
dust_limit_satoshis); |
|
|
|
untrimmed = commit_tx_num_untrimmed(htlcs, |
|
|
|
feerate_per_kw, |
|
|
|
dust_limit_satoshis, side); |
|
|
|
|
|
|
|
/* BOLT #3:
|
|
|
|
* |
|
|
|
* 2. Calculate the base [commitment transaction |
|
|
|
* fee](#fee-calculation). |
|
|
|
*/ |
|
|
|
base_fee_msat = commit_tx_base_fee(feerate_per_kw, |
|
|
|
tal_count(offered) |
|
|
|
+ tal_count(received)) |
|
|
|
* 1000; |
|
|
|
base_fee_msat = commit_tx_base_fee(feerate_per_kw, untrimmed) * 1000; |
|
|
|
|
|
|
|
SUPERVERBOSE("# base commitment transaction fee = %"PRIu64"\n", |
|
|
|
base_fee_msat / 1000); |
|
|
@ -200,45 +230,41 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx, |
|
|
|
&self_pay_msat, &other_pay_msat); |
|
|
|
|
|
|
|
/* Worst-case sizing: both to-local and to-remote outputs. */ |
|
|
|
tx = bitcoin_tx(ctx, 1, tal_count(offered) + tal_count(received) + 2); |
|
|
|
tx = bitcoin_tx(ctx, 1, untrimmed + 2); |
|
|
|
|
|
|
|
/* We keep track of which outputs have which HTLCs */ |
|
|
|
*htlcmap = tal_arr(tx, const struct htlc *, tal_count(tx->output)); |
|
|
|
|
|
|
|
/* This could be done in a single loop, but we follow the BOLT
|
|
|
|
* literally to make comments in test vectors clearer. */ |
|
|
|
|
|
|
|
n = 0; |
|
|
|
/* BOLT #3:
|
|
|
|
* |
|
|
|
* 3. For every offered HTLC, if it is not trimmed, add an [offered |
|
|
|
* HTLC output](#offered-htlc-outputs). |
|
|
|
* 3. For every offered HTLC, if it is not trimmed, add an |
|
|
|
* [offered HTLC output](#offered-htlc-outputs). |
|
|
|
*/ |
|
|
|
n = 0; |
|
|
|
for (i = 0; i < tal_count(offered); i++, n++) { |
|
|
|
u8 *wscript = bitcoin_wscript_htlc_offer(tmpctx, |
|
|
|
selfkey, otherkey, |
|
|
|
&offered[i]->rhash); |
|
|
|
tx->output[n].amount = offered[i]->msatoshi / 1000; |
|
|
|
tx->output[n].script = scriptpubkey_p2wsh(tx, wscript); |
|
|
|
(*htlcmap)[n] = offered[i]; |
|
|
|
SUPERVERBOSE("# HTLC offered amount %"PRIu64" wscript %s\n", |
|
|
|
tx->output[n].amount, |
|
|
|
tal_hex(tmpctx, wscript)); |
|
|
|
for (i = 0; i < tal_count(htlcs); i++) { |
|
|
|
if (htlc_owner(htlcs[i]) != side) |
|
|
|
continue; |
|
|
|
if (trim(htlcs[i], feerate_per_kw, dust_limit_satoshis, side)) |
|
|
|
continue; |
|
|
|
add_offered_htlc_out(tx, n, htlcs[i], selfkey, otherkey); |
|
|
|
(*htlcmap)[n++] = htlcs[i]; |
|
|
|
} |
|
|
|
|
|
|
|
/* BOLT #3:
|
|
|
|
* |
|
|
|
* 4. For every received HTLC, if it is not trimmed, add an [received |
|
|
|
* HTLC output](#received-htlc-outputs). |
|
|
|
* 4. For every received HTLC, if it is not trimmed, add an |
|
|
|
* [received HTLC output](#received-htlc-outputs). |
|
|
|
*/ |
|
|
|
for (i = 0; i < tal_count(received); i++, n++) { |
|
|
|
u8 *wscript = bitcoin_wscript_htlc_receive(tmpctx, |
|
|
|
&received[i]->expiry, |
|
|
|
selfkey, otherkey, |
|
|
|
&received[i]->rhash); |
|
|
|
tx->output[n].amount = received[i]->msatoshi / 1000; |
|
|
|
tx->output[n].script = scriptpubkey_p2wsh(tx, wscript); |
|
|
|
(*htlcmap)[n] = received[i]; |
|
|
|
SUPERVERBOSE("# HTLC received amount %"PRIu64" wscript %s\n", |
|
|
|
tx->output[n].amount, |
|
|
|
tal_hex(tmpctx, wscript)); |
|
|
|
for (i = 0; i < tal_count(htlcs); i++) { |
|
|
|
if (htlc_owner(htlcs[i]) == side) |
|
|
|
continue; |
|
|
|
if (trim(htlcs[i], feerate_per_kw, dust_limit_satoshis, side)) |
|
|
|
continue; |
|
|
|
add_received_htlc_out(tx, n, htlcs[i],selfkey, otherkey); |
|
|
|
(*htlcmap)[n++] = htlcs[i]; |
|
|
|
} |
|
|
|
|
|
|
|
/* BOLT #3:
|
|
|
|