mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-19 05:44:12 +01:00
commit_tx: expose more internal functions.
without having to build it, which is needed for limit enforcement. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
e8e96e67d0
commit
9284819f68
@ -73,13 +73,11 @@ u64 htlc_success_fee(u64 feerate_per_kw)
|
|||||||
return feerate_per_kw * 673 / 1000;
|
return feerate_per_kw * 673 / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct htlc **untrimmed(const tal_t *ctx,
|
static bool trim(const struct htlc *htlc,
|
||||||
const struct htlc **htlcs,
|
u64 feerate_per_kw, u64 dust_limit_satoshis,
|
||||||
enum side side,
|
enum side side)
|
||||||
u64 htlc_fee, u64 dust_limit_satoshis)
|
|
||||||
{
|
{
|
||||||
const struct htlc **arr;
|
u64 htlc_fee;
|
||||||
size_t i, n;
|
|
||||||
|
|
||||||
/* BOLT #3:
|
/* BOLT #3:
|
||||||
*
|
*
|
||||||
@ -88,6 +86,10 @@ static const struct htlc **untrimmed(const tal_t *ctx,
|
|||||||
* owner, the commitment transaction MUST NOT contain that output,
|
* owner, the commitment transaction MUST NOT contain that output,
|
||||||
* otherwise it MUST be generated as specified in [Offered HTLC
|
* otherwise it MUST be generated as specified in [Offered HTLC
|
||||||
* Outputs](#offered-htlc-outputs).
|
* 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
|
* For every received HTLC, if the HTLC amount minus the HTLC-success
|
||||||
* fee would be less than `dust-limit-satoshis` set by the transaction
|
* 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
|
* otherwise it MUST be generated as specified in [Received HTLC
|
||||||
* Outputs](#received-htlc-outputs).
|
* Outputs](#received-htlc-outputs).
|
||||||
*/
|
*/
|
||||||
arr = tal_arr(ctx, const struct htlc *, tal_count(htlcs));
|
else
|
||||||
for (i = n = 0; i < tal_count(htlcs); i++) {
|
htlc_fee = htlc_success_fee(feerate_per_kw);
|
||||||
if (htlc_owner(htlcs[i]) != side)
|
|
||||||
continue;
|
|
||||||
if (htlcs[i]->msatoshi / 1000 < dust_limit_satoshis + htlc_fee)
|
|
||||||
continue;
|
|
||||||
arr[n++] = htlcs[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(n <= tal_count(arr));
|
return htlc->msatoshi / 1000 < dust_limit_satoshis + htlc_fee;
|
||||||
tal_resize(&arr, n);
|
|
||||||
|
|
||||||
return arr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static u64 commit_tx_base_fee(u64 feerate_per_kw, size_t num_untrimmed_htlcs)
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 commit_tx_base_fee(u64 feerate_per_kw, size_t num_untrimmed_htlcs)
|
||||||
{
|
{
|
||||||
u64 weight;
|
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;
|
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,
|
struct bitcoin_tx *commit_tx(const tal_t *ctx,
|
||||||
const struct sha256_double *funding_txid,
|
const struct sha256_double *funding_txid,
|
||||||
unsigned int funding_txout,
|
unsigned int funding_txout,
|
||||||
@ -159,10 +196,9 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx,
|
|||||||
enum side side)
|
enum side side)
|
||||||
{
|
{
|
||||||
const tal_t *tmpctx = tal_tmpctx(ctx);
|
const tal_t *tmpctx = tal_tmpctx(ctx);
|
||||||
const struct htlc **offered, **received;
|
|
||||||
u64 base_fee_msat;
|
u64 base_fee_msat;
|
||||||
struct bitcoin_tx *tx;
|
struct bitcoin_tx *tx;
|
||||||
size_t i, n;
|
size_t i, n, untrimmed;
|
||||||
|
|
||||||
assert(self_pay_msat + other_pay_msat <= funding_satoshis * 1000);
|
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
|
* 1. Calculate which committed HTLCs need to be trimmed (see
|
||||||
* [Trimmed Outputs](#trimmed-outputs)).
|
* [Trimmed Outputs](#trimmed-outputs)).
|
||||||
*/
|
*/
|
||||||
offered = untrimmed(tmpctx, htlcs, side,
|
untrimmed = commit_tx_num_untrimmed(htlcs,
|
||||||
htlc_timeout_fee(feerate_per_kw),
|
feerate_per_kw,
|
||||||
dust_limit_satoshis);
|
dust_limit_satoshis, side);
|
||||||
received = untrimmed(tmpctx, htlcs, !side,
|
|
||||||
htlc_success_fee(feerate_per_kw),
|
|
||||||
dust_limit_satoshis);
|
|
||||||
|
|
||||||
/* BOLT #3:
|
/* BOLT #3:
|
||||||
*
|
*
|
||||||
* 2. Calculate the base [commitment transaction
|
* 2. Calculate the base [commitment transaction
|
||||||
* fee](#fee-calculation).
|
* fee](#fee-calculation).
|
||||||
*/
|
*/
|
||||||
base_fee_msat = commit_tx_base_fee(feerate_per_kw,
|
base_fee_msat = commit_tx_base_fee(feerate_per_kw, untrimmed) * 1000;
|
||||||
tal_count(offered)
|
|
||||||
+ tal_count(received))
|
|
||||||
* 1000;
|
|
||||||
|
|
||||||
SUPERVERBOSE("# base commitment transaction fee = %"PRIu64"\n",
|
SUPERVERBOSE("# base commitment transaction fee = %"PRIu64"\n",
|
||||||
base_fee_msat / 1000);
|
base_fee_msat / 1000);
|
||||||
@ -200,45 +230,41 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx,
|
|||||||
&self_pay_msat, &other_pay_msat);
|
&self_pay_msat, &other_pay_msat);
|
||||||
|
|
||||||
/* Worst-case sizing: both to-local and to-remote outputs. */
|
/* 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 */
|
/* We keep track of which outputs have which HTLCs */
|
||||||
*htlcmap = tal_arr(tx, const struct htlc *, tal_count(tx->output));
|
*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:
|
/* BOLT #3:
|
||||||
*
|
*
|
||||||
* 3. For every offered HTLC, if it is not trimmed, add an [offered
|
* 3. For every offered HTLC, if it is not trimmed, add an
|
||||||
* HTLC output](#offered-htlc-outputs).
|
* [offered HTLC output](#offered-htlc-outputs).
|
||||||
*/
|
*/
|
||||||
n = 0;
|
for (i = 0; i < tal_count(htlcs); i++) {
|
||||||
for (i = 0; i < tal_count(offered); i++, n++) {
|
if (htlc_owner(htlcs[i]) != side)
|
||||||
u8 *wscript = bitcoin_wscript_htlc_offer(tmpctx,
|
continue;
|
||||||
selfkey, otherkey,
|
if (trim(htlcs[i], feerate_per_kw, dust_limit_satoshis, side))
|
||||||
&offered[i]->rhash);
|
continue;
|
||||||
tx->output[n].amount = offered[i]->msatoshi / 1000;
|
add_offered_htlc_out(tx, n, htlcs[i], selfkey, otherkey);
|
||||||
tx->output[n].script = scriptpubkey_p2wsh(tx, wscript);
|
(*htlcmap)[n++] = htlcs[i];
|
||||||
(*htlcmap)[n] = offered[i];
|
|
||||||
SUPERVERBOSE("# HTLC offered amount %"PRIu64" wscript %s\n",
|
|
||||||
tx->output[n].amount,
|
|
||||||
tal_hex(tmpctx, wscript));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BOLT #3:
|
/* BOLT #3:
|
||||||
*
|
*
|
||||||
* 4. For every received HTLC, if it is not trimmed, add an [received
|
* 4. For every received HTLC, if it is not trimmed, add an
|
||||||
* HTLC output](#received-htlc-outputs).
|
* [received HTLC output](#received-htlc-outputs).
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < tal_count(received); i++, n++) {
|
for (i = 0; i < tal_count(htlcs); i++) {
|
||||||
u8 *wscript = bitcoin_wscript_htlc_receive(tmpctx,
|
if (htlc_owner(htlcs[i]) == side)
|
||||||
&received[i]->expiry,
|
continue;
|
||||||
selfkey, otherkey,
|
if (trim(htlcs[i], feerate_per_kw, dust_limit_satoshis, side))
|
||||||
&received[i]->rhash);
|
continue;
|
||||||
tx->output[n].amount = received[i]->msatoshi / 1000;
|
add_received_htlc_out(tx, n, htlcs[i],selfkey, otherkey);
|
||||||
tx->output[n].script = scriptpubkey_p2wsh(tx, wscript);
|
(*htlcmap)[n++] = htlcs[i];
|
||||||
(*htlcmap)[n] = received[i];
|
|
||||||
SUPERVERBOSE("# HTLC received amount %"PRIu64" wscript %s\n",
|
|
||||||
tx->output[n].amount,
|
|
||||||
tal_hex(tmpctx, wscript));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BOLT #3:
|
/* BOLT #3:
|
||||||
|
@ -20,6 +20,23 @@ u64 commit_number_obscurer(const struct pubkey *opener_payment_basepoint,
|
|||||||
u64 htlc_success_fee(u64 feerate_per_kw);
|
u64 htlc_success_fee(u64 feerate_per_kw);
|
||||||
u64 htlc_timeout_fee(u64 feerate_per_kw);
|
u64 htlc_timeout_fee(u64 feerate_per_kw);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* commit_tx_num_untrimmed: how many of these htlc outputs will commit tx have?
|
||||||
|
* @htlcs: tal_arr of HTLCs
|
||||||
|
* @feerate_per_kw: feerate to use
|
||||||
|
* @dust_limit_satoshis: dust limit below which to trim outputs.
|
||||||
|
* @side: from which side's point of view
|
||||||
|
*
|
||||||
|
* We need @side because HTLC fees are different for offered and
|
||||||
|
* received HTLCs.
|
||||||
|
*/
|
||||||
|
size_t commit_tx_num_untrimmed(const struct htlc **htlcs,
|
||||||
|
u64 feerate_per_kw, u64 dust_limit_satoshis,
|
||||||
|
enum side side);
|
||||||
|
|
||||||
|
/* Helper to calculate the base fee if we add this extra htlc */
|
||||||
|
u64 commit_tx_base_fee(u64 feerate_per_kw, size_t num_untrimmed_htlcs);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* commit_tx: create (unsigned) commitment tx to spend the funding tx output
|
* commit_tx: create (unsigned) commitment tx to spend the funding tx output
|
||||||
* @ctx: context to allocate transaction and @htlc_map from.
|
* @ctx: context to allocate transaction and @htlc_map from.
|
||||||
|
@ -10,7 +10,7 @@ update-mocks: $(LIGHTNINGD_TEST_SRC:%=update-mocks/%)
|
|||||||
|
|
||||||
$(LIGHTNINGD_TEST_PROGRAMS): $(CCAN_OBJS) $(CORE_OBJS) $(CORE_TX_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS) $(LIBBASE58_OBJS) $(LIGHTNINGD_OLD_LIB_OBJS) utils.o libsecp256k1.a libsodium.a
|
$(LIGHTNINGD_TEST_PROGRAMS): $(CCAN_OBJS) $(CORE_OBJS) $(CORE_TX_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS) $(LIBBASE58_OBJS) $(LIGHTNINGD_OLD_LIB_OBJS) utils.o libsecp256k1.a libsodium.a
|
||||||
|
|
||||||
$(LIGHTNINGD_TEST_OBJS): $(LIGHTNINGD_HEADERS)
|
$(LIGHTNINGD_TEST_OBJS): $(LIGHTNINGD_HEADERS) $(LIGHTNINGD_SRC) $(LIGHTNINGD_LIB_SRC)
|
||||||
|
|
||||||
lightningd/tests: $(LIGHTNINGD_TEST_PROGRAMS:%=unittest/%)
|
lightningd/tests: $(LIGHTNINGD_TEST_PROGRAMS:%=unittest/%)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user