mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-12-27 09:04:40 +01:00
685fa25756
Only affects comments. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
434 lines
13 KiB
C
434 lines
13 KiB
C
#include "config.h"
|
|
#include <bitcoin/script.h>
|
|
#include <channeld/commit_tx.h>
|
|
#include <common/htlc_trim.h>
|
|
#include <common/htlc_tx.h>
|
|
#include <common/keyset.h>
|
|
#include <common/permute_tx.h>
|
|
|
|
#ifndef SUPERVERBOSE
|
|
#define SUPERVERBOSE(...)
|
|
#endif
|
|
|
|
static bool trim(const struct htlc *htlc,
|
|
u32 feerate_per_kw,
|
|
struct amount_sat dust_limit,
|
|
bool option_anchor_outputs,
|
|
enum side side)
|
|
{
|
|
return htlc_is_trimmed(htlc_owner(htlc), htlc->amount,
|
|
feerate_per_kw, dust_limit, side,
|
|
option_anchor_outputs);
|
|
}
|
|
|
|
size_t commit_tx_num_untrimmed(const struct htlc **htlcs,
|
|
u32 feerate_per_kw,
|
|
struct amount_sat dust_limit,
|
|
bool option_anchor_outputs,
|
|
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,
|
|
option_anchor_outputs, side);
|
|
|
|
return n;
|
|
}
|
|
|
|
bool commit_tx_amount_trimmed(const struct htlc **htlcs,
|
|
u32 feerate_per_kw,
|
|
struct amount_sat dust_limit,
|
|
bool option_anchor_outputs,
|
|
enum side side,
|
|
struct amount_msat *amt)
|
|
{
|
|
for (size_t i = 0; i < tal_count(htlcs); i++) {
|
|
if (trim(htlcs[i], feerate_per_kw, dust_limit,
|
|
option_anchor_outputs, side))
|
|
if (!amount_msat_add(amt, *amt, htlcs[i]->amount))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static void add_offered_htlc_out(struct bitcoin_tx *tx, size_t n,
|
|
const struct htlc *htlc,
|
|
const struct keyset *keyset,
|
|
bool option_anchor_outputs)
|
|
{
|
|
struct ripemd160 ripemd;
|
|
u8 *wscript, *p2wsh;
|
|
struct amount_sat amount = amount_msat_to_sat_round_down(htlc->amount);
|
|
|
|
ripemd160(&ripemd, htlc->rhash.u.u8, sizeof(htlc->rhash.u.u8));
|
|
wscript = htlc_offered_wscript(tx, &ripemd, keyset,
|
|
option_anchor_outputs);
|
|
p2wsh = scriptpubkey_p2wsh(tx, wscript);
|
|
bitcoin_tx_add_output(tx, p2wsh, wscript, amount);
|
|
SUPERVERBOSE("# HTLC #%" PRIu64 " offered amount %"PRIu64" wscript %s\n", htlc->id,
|
|
amount.satoshis, /* Raw: BOLT 3 output match */
|
|
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 keyset *keyset,
|
|
bool option_anchor_outputs)
|
|
{
|
|
struct ripemd160 ripemd;
|
|
u8 *wscript, *p2wsh;
|
|
struct amount_sat amount;
|
|
|
|
ripemd160(&ripemd, htlc->rhash.u.u8, sizeof(htlc->rhash.u.u8));
|
|
wscript = htlc_received_wscript(tx, &ripemd, &htlc->expiry, keyset,
|
|
option_anchor_outputs);
|
|
p2wsh = scriptpubkey_p2wsh(tx, wscript);
|
|
amount = amount_msat_to_sat_round_down(htlc->amount);
|
|
|
|
bitcoin_tx_add_output(tx, p2wsh, wscript, amount);
|
|
|
|
SUPERVERBOSE("# HTLC #%"PRIu64" received amount %"PRIu64" wscript %s\n",
|
|
htlc->id,
|
|
amount.satoshis, /* Raw: BOLT 3 output match */
|
|
tal_hex(wscript, wscript));
|
|
tal_free(wscript);
|
|
}
|
|
|
|
struct bitcoin_tx *commit_tx(const tal_t *ctx,
|
|
const struct bitcoin_outpoint *funding,
|
|
struct amount_sat funding_sats,
|
|
const struct pubkey *local_funding_key,
|
|
const struct pubkey *remote_funding_key,
|
|
enum side opener,
|
|
u16 to_self_delay,
|
|
u32 lease_expiry,
|
|
u32 blockheight,
|
|
const struct keyset *keyset,
|
|
u32 feerate_per_kw,
|
|
struct amount_sat dust_limit,
|
|
struct amount_msat self_pay,
|
|
struct amount_msat other_pay,
|
|
const struct htlc **htlcs,
|
|
const struct htlc ***htlcmap,
|
|
struct wally_tx_output *direct_outputs[NUM_SIDES],
|
|
u64 obscured_commitment_number,
|
|
bool option_anchor_outputs,
|
|
enum side side)
|
|
{
|
|
struct amount_sat base_fee;
|
|
struct amount_msat total_pay;
|
|
struct bitcoin_tx *tx;
|
|
size_t i, n, untrimmed;
|
|
/* Is this the lessor ? */
|
|
enum side lessor = !opener;
|
|
u32 *cltvs;
|
|
bool to_local, to_remote;
|
|
struct htlc *dummy_to_local = (struct htlc *)0x01,
|
|
*dummy_to_remote = (struct htlc *)0x02;
|
|
const u8 *funding_wscript = bitcoin_redeem_2of2(tmpctx,
|
|
local_funding_key,
|
|
remote_funding_key);
|
|
u32 csv_lock = lease_expiry > blockheight ?
|
|
lease_expiry - blockheight : 1;
|
|
|
|
if (!amount_msat_add(&total_pay, self_pay, other_pay))
|
|
abort();
|
|
assert(!amount_msat_greater_sat(total_pay, funding_sats));
|
|
|
|
/* BOLT #3:
|
|
*
|
|
* 1. Calculate which committed HTLCs need to be trimmed (see
|
|
* [Trimmed Outputs](#trimmed-outputs)).
|
|
*/
|
|
untrimmed = commit_tx_num_untrimmed(htlcs,
|
|
feerate_per_kw,
|
|
dust_limit,
|
|
option_anchor_outputs,
|
|
side);
|
|
|
|
/* BOLT #3:
|
|
*
|
|
* 2. Calculate the base [commitment transaction
|
|
* fee](#fee-calculation).
|
|
*/
|
|
base_fee = commit_tx_base_fee(feerate_per_kw, untrimmed,
|
|
option_anchor_outputs);
|
|
|
|
SUPERVERBOSE("# base commitment transaction fee = %"PRIu64"\n",
|
|
base_fee.satoshis /* Raw: spec uses raw numbers */);
|
|
|
|
/* BOLT #3:
|
|
* If `option_anchors` applies to the commitment
|
|
* transaction, also subtract two times the fixed anchor size
|
|
* of 330 sats from the funder (either `to_local` or
|
|
* `to_remote`).
|
|
*/
|
|
if (option_anchor_outputs
|
|
&& !amount_sat_add(&base_fee, base_fee, AMOUNT_SAT(660)))
|
|
/* Can't overflow: feerate is u32. */
|
|
abort();
|
|
|
|
/* BOLT #3:
|
|
*
|
|
* 3. Subtract this base fee from the funder (either `to_local` or
|
|
* `to_remote`).
|
|
*/
|
|
try_subtract_fee(opener, side, base_fee, &self_pay, &other_pay);
|
|
|
|
#ifdef PRINT_ACTUAL_FEE
|
|
{
|
|
struct amount_sat out = AMOUNT_SAT(0);
|
|
bool ok = true;
|
|
for (i = 0; i < tal_count(htlcs); i++) {
|
|
if (!trim(htlcs[i], feerate_per_kw, dust_limit,
|
|
option_anchor_outputs, side))
|
|
ok &= amount_sat_add(&out, out, amount_msat_to_sat_round_down(htlcs[i]->amount));
|
|
}
|
|
if (amount_msat_greater_eq_sat(self_pay, dust_limit))
|
|
ok &= amount_sat_add(&out, out, amount_msat_to_sat_round_down(self_pay));
|
|
if (amount_msat_greater_eq_sat(other_pay, dust_limit))
|
|
ok &= amount_sat_add(&out, out, amount_msat_to_sat_round_down(other_pay));
|
|
assert(ok);
|
|
SUPERVERBOSE("# actual commitment transaction fee = %"PRIu64"\n",
|
|
funding_sats.satoshis - out.satoshis); /* Raw: test output */
|
|
}
|
|
#endif
|
|
|
|
/* Worst-case sizing: both to-local and to-remote outputs, and anchors. */
|
|
tx = bitcoin_tx(ctx, chainparams, 1, untrimmed + 2 + 2, 0);
|
|
|
|
/* We keep track of which outputs have which HTLCs */
|
|
*htlcmap = tal_arr(tx, const struct htlc *, tx->wtx->outputs_allocation_len);
|
|
|
|
/* We keep cltvs for tie-breaking HTLC outputs; we use the same order
|
|
* for sending the htlc txs, so it may matter. */
|
|
cltvs = tal_arr(tmpctx, u32, tx->wtx->outputs_allocation_len);
|
|
|
|
/* 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:
|
|
*
|
|
* 4. For every offered HTLC, if it is not trimmed, add an
|
|
* [offered HTLC output](#offered-htlc-outputs).
|
|
*/
|
|
for (i = 0; i < tal_count(htlcs); i++) {
|
|
if (htlc_owner(htlcs[i]) != side)
|
|
continue;
|
|
if (trim(htlcs[i], feerate_per_kw, dust_limit,
|
|
option_anchor_outputs, side))
|
|
continue;
|
|
add_offered_htlc_out(tx, n, htlcs[i], keyset,
|
|
option_anchor_outputs);
|
|
(*htlcmap)[n] = htlcs[i];
|
|
cltvs[n] = abs_locktime_to_blocks(&htlcs[i]->expiry);
|
|
n++;
|
|
}
|
|
|
|
/* BOLT #3:
|
|
*
|
|
* 5. For every received HTLC, if it is not trimmed, add an
|
|
* [received HTLC output](#received-htlc-outputs).
|
|
*/
|
|
for (i = 0; i < tal_count(htlcs); i++) {
|
|
if (htlc_owner(htlcs[i]) == side)
|
|
continue;
|
|
if (trim(htlcs[i], feerate_per_kw, dust_limit,
|
|
option_anchor_outputs, side))
|
|
continue;
|
|
add_received_htlc_out(tx, n, htlcs[i], keyset,
|
|
option_anchor_outputs);
|
|
(*htlcmap)[n] = htlcs[i];
|
|
cltvs[n] = abs_locktime_to_blocks(&htlcs[i]->expiry);
|
|
n++;
|
|
}
|
|
|
|
/* BOLT #3:
|
|
*
|
|
* 6. If the `to_local` amount is greater or equal to
|
|
* `dust_limit_satoshis`, add a [`to_local`
|
|
* output](#to_local-output).
|
|
*/
|
|
if (amount_msat_greater_eq_sat(self_pay, dust_limit)) {
|
|
/* BOLT- #3:
|
|
* In a leased channel, the `to_local` output that
|
|
* pays the `accepter` node is modified so that its
|
|
* CSV is equal to the greater of the
|
|
* `to_self_delay` or the `lease_end` - `blockheight`.
|
|
*/
|
|
u8 *wscript = to_self_wscript(tmpctx,
|
|
to_self_delay,
|
|
side == lessor ? csv_lock : 0,
|
|
keyset);
|
|
u8 *p2wsh = scriptpubkey_p2wsh(tx, wscript);
|
|
struct amount_sat amount = amount_msat_to_sat_round_down(self_pay);
|
|
|
|
bitcoin_tx_add_output(tx, p2wsh, wscript, amount);
|
|
/* Add a dummy entry to the htlcmap so we can recognize it later */
|
|
(*htlcmap)[n] = direct_outputs ? dummy_to_local : NULL;
|
|
/* We don't assign cltvs[n]: if we use it, order doesn't matter.
|
|
* However, valgrind will warn us something wierd is happening */
|
|
SUPERVERBOSE("# to_local amount %"PRIu64" wscript %s\n",
|
|
amount.satoshis, /* Raw: BOLT 3 output match */
|
|
tal_hex(tmpctx, wscript));
|
|
n++;
|
|
to_local = true;
|
|
} else
|
|
to_local = false;
|
|
|
|
/* BOLT #3:
|
|
*
|
|
* 7. If the `to_remote` amount is greater or equal to
|
|
* `dust_limit_satoshis`, add a [`to_remote`
|
|
* output](#to_remote-output).
|
|
*/
|
|
u8 *redeem;
|
|
if (amount_msat_greater_eq_sat(other_pay, dust_limit)) {
|
|
struct amount_sat amount = amount_msat_to_sat_round_down(other_pay);
|
|
u8 *scriptpubkey;
|
|
int pos;
|
|
|
|
/* BOLT #3:
|
|
*
|
|
* #### `to_remote` Output
|
|
*
|
|
* If `option_anchors` applies to the commitment
|
|
* transaction, the `to_remote` output is encumbered by a one
|
|
* block csv lock.
|
|
* <remotepubkey> OP_CHECKSIGVERIFY 1 OP_CHECKSEQUENCEVERIFY
|
|
*
|
|
*...
|
|
* Otherwise, this output is a simple P2WPKH to `remotepubkey`.
|
|
*/
|
|
if (option_anchor_outputs) {
|
|
redeem = anchor_to_remote_redeem(tmpctx,
|
|
&keyset->other_payment_key,
|
|
(!side) == lessor ?
|
|
csv_lock : 1);
|
|
/* BOLT- #3:
|
|
* ##### Leased channel (`option_will_fund`)
|
|
*
|
|
* If a `lease` applies to the channel, the
|
|
* `to_remote` output of the `initiator`
|
|
* ensures the `leasor` funds are not
|
|
* spendable until the lease expires.
|
|
*
|
|
* <remote_pubkey> OP_CHECKSIGVERIFY
|
|
* MAX(1, lease_end - blockheight)
|
|
* OP_CHECKSEQUENCEVERIFY
|
|
*/
|
|
scriptpubkey = scriptpubkey_p2wsh(tmpctx, redeem);
|
|
} else {
|
|
redeem = NULL;
|
|
scriptpubkey = scriptpubkey_p2wpkh(tmpctx,
|
|
&keyset->other_payment_key);
|
|
}
|
|
pos = bitcoin_tx_add_output(tx, scriptpubkey, redeem, amount);
|
|
assert(pos == n);
|
|
(*htlcmap)[n] = direct_outputs ? dummy_to_remote : NULL;
|
|
/* We don't assign cltvs[n]: if we use it, order doesn't matter.
|
|
* However, valgrind will warn us something wierd is happening */
|
|
SUPERVERBOSE("# to_remote amount %"PRIu64" P2WPKH(%s)\n",
|
|
amount.satoshis, /* Raw: BOLT 3 output match */
|
|
type_to_string(tmpctx, struct pubkey,
|
|
&keyset->other_payment_key));
|
|
n++;
|
|
|
|
to_remote = true;
|
|
} else {
|
|
to_remote = false;
|
|
redeem = NULL;
|
|
}
|
|
|
|
/* BOLT #3:
|
|
*
|
|
* 8. If `option_anchors` applies to the commitment transaction:
|
|
* * if `to_local` exists or there are untrimmed HTLCs, add a
|
|
* [`to_local_anchor` output]...
|
|
* * if `to_remote` exists or there are untrimmed HTLCs, add a
|
|
* [`to_remote_anchor` output]
|
|
*/
|
|
if (option_anchor_outputs) {
|
|
if (to_local || untrimmed != 0) {
|
|
tx_add_anchor_output(tx, local_funding_key);
|
|
(*htlcmap)[n] = NULL;
|
|
n++;
|
|
}
|
|
|
|
if (to_remote || untrimmed != 0) {
|
|
tx_add_anchor_output(tx, remote_funding_key);
|
|
(*htlcmap)[n] = NULL;
|
|
n++;
|
|
}
|
|
}
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* - MUST set `channel_reserve_satoshis` greater than or equal to
|
|
* `dust_limit_satoshis`.
|
|
*/
|
|
/* This means there must be at least one output. */
|
|
assert(n > 0);
|
|
|
|
assert(n <= tx->wtx->outputs_allocation_len);
|
|
tal_resize(htlcmap, n);
|
|
|
|
/* BOLT #3:
|
|
*
|
|
* 9. Sort the outputs into [BIP 69+CLTV
|
|
* order](#transaction-output-ordering)
|
|
*/
|
|
permute_outputs(tx, cltvs, (const void **)*htlcmap);
|
|
|
|
/* BOLT #3:
|
|
*
|
|
* ## Commitment Transaction
|
|
*
|
|
* * version: 2
|
|
*/
|
|
assert(tx->wtx->version == 2);
|
|
|
|
/* BOLT #3:
|
|
*
|
|
* * locktime: upper 8 bits are 0x20, lower 24 bits are the lower 24 bits of the obscured commitment number
|
|
*/
|
|
bitcoin_tx_set_locktime(tx,
|
|
(0x20000000 | (obscured_commitment_number & 0xFFFFFF)));
|
|
|
|
/* BOLT #3:
|
|
*
|
|
* * txin count: 1
|
|
* * `txin[0]` outpoint: `txid` and `output_index` from
|
|
* `funding_created` message
|
|
*/
|
|
/* BOLT #3:
|
|
*
|
|
* * `txin[0]` sequence: upper 8 bits are 0x80, lower 24 bits are upper 24 bits of the obscured commitment number
|
|
*/
|
|
u32 sequence = (0x80000000 | ((obscured_commitment_number>>24) & 0xFFFFFF));
|
|
bitcoin_tx_add_input(tx, funding,
|
|
sequence, NULL, funding_sats, NULL, funding_wscript);
|
|
|
|
/* Identify the direct outputs (to_us, to_them). */
|
|
if (direct_outputs != NULL) {
|
|
direct_outputs[LOCAL] = direct_outputs[REMOTE] = NULL;
|
|
for (size_t i = 0; i < tx->wtx->num_outputs; i++) {
|
|
if ((*htlcmap)[i] == dummy_to_local) {
|
|
(*htlcmap)[i] = NULL;
|
|
direct_outputs[LOCAL] = tx->wtx->outputs + i;
|
|
} else if ((*htlcmap)[i] == dummy_to_remote) {
|
|
(*htlcmap)[i] = NULL;
|
|
direct_outputs[REMOTE] = tx->wtx->outputs + i;
|
|
}
|
|
}
|
|
}
|
|
|
|
bitcoin_tx_finalize(tx);
|
|
assert(bitcoin_tx_check(tx));
|
|
|
|
return tx;
|
|
}
|