Skip to content

Commit 9ba995c

Browse files
committed
common/close_tx: add create_simple_close_tx() for option_simple_close
Adds the BOLT3 simple closing transaction builder: - sequence 0xFFFFFFFD (RBF-signalling) - locktime from closing_complete - closer pays fee (their output is reduced) - dust outputs are omitted and a zero-value OP_RETURN is used when both outputs would be dust.
1 parent 8e858fc commit 9ba995c

2 files changed

Lines changed: 112 additions & 0 deletions

File tree

common/close_tx.c

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#include <common/close_tx.h>
55
#include <common/permute_tx.h>
66
#include <common/psbt_keypath.h>
7+
#include <common/utils.h>
8+
#include <wally_script.h>
79

810
struct bitcoin_tx *create_close_tx(const tal_t *ctx,
911
const struct chainparams *chainparams,
@@ -91,3 +93,98 @@ struct bitcoin_tx *create_close_tx(const tal_t *ctx,
9193
assert(bitcoin_tx_check(tx));
9294
return tx;
9395
}
96+
97+
/* BOLT #3:
98+
*
99+
* ## Closing Transaction
100+
*
101+
* This variant is used for `closing_complete` and `closing_sig` messages
102+
* (i.e. where `option_simple_close` is negotiated).
103+
* ...
104+
* The side with lesser funds can opt to omit their own output.
105+
* * version: 2
106+
* * locktime: `locktime` from the `closing_complete` message
107+
* * txin count: 1
108+
* * `txin[0]` outpoint: `txid` and `output_index` of the channel output
109+
* * `txin[0]` sequence: 0xFFFFFFFD
110+
* * `txin[0]` script bytes: 0
111+
* * `txin[0]` witness: `0 <signature_for_pubkey1> <signature_for_pubkey2>`
112+
*/
113+
struct bitcoin_tx *create_simple_close_tx(const tal_t *ctx,
114+
u32 *local_wallet_index,
115+
const struct ext_key *local_wallet_ext_key,
116+
const u8 *closer_script,
117+
const u8 *closee_script,
118+
const u8 *funding_wscript,
119+
const struct bitcoin_outpoint *funding,
120+
struct amount_sat funding_sats,
121+
struct amount_sat closer_amount,
122+
struct amount_sat closee_amount,
123+
u32 locktime)
124+
{
125+
struct bitcoin_tx *tx;
126+
size_t num_outputs = 0;
127+
u8 *script;
128+
129+
/* Sequence 0xFFFFFFFD signals RBF and satisfies the nSequence
130+
* requirement for nLockTime. */
131+
tx = bitcoin_tx(ctx, chainparams, 1, 2, locktime);
132+
133+
bitcoin_tx_add_input(tx, funding,
134+
/* RBF-enabled, not final */
135+
0xFFFFFFFD,
136+
NULL, funding_sats, NULL, funding_wscript);
137+
138+
/* BOLT #3:
139+
* * The closer output: * `txout` amount:
140+
* * 0 if the `scriptpubkey` starts with `OP_RETURN`
141+
* * otherwise the final balance for the closer, minus `closing_complete.fee_satoshis`, rounded down to whole satoshis
142+
* * `txout` script: as specified in `closer_scriptpubkey` from the `closing_complete` message
143+
*/
144+
if (closer_script) {
145+
struct amount_sat amt = closer_amount;
146+
/* OP_RETURN output must have zero value */
147+
if (tal_count(closer_script) > 0
148+
&& closer_script[0] == OP_RETURN)
149+
amt = AMOUNT_SAT(0);
150+
151+
script = tal_dup_talarr(tx, u8, closer_script);
152+
bitcoin_tx_add_output(tx, script, NULL, amt);
153+
assert((local_wallet_index == NULL) == (local_wallet_ext_key == NULL));
154+
if (local_wallet_index) {
155+
size_t script_len = tal_bytelen(script);
156+
if (!psbt_add_keypath_to_last_output(
157+
tx, *local_wallet_index, local_wallet_ext_key,
158+
is_p2tr(script, script_len, NULL)))
159+
return tal_free(tx);
160+
}
161+
num_outputs++;
162+
}
163+
164+
/* BOLT #3:
165+
* * The closee output:
166+
* * `txout` amount:
167+
* * 0 if the `scriptpubkey` starts with `OP_RETURN`
168+
* * otherwise the final balance for the closee, rounded down to whole satoshis
169+
* * `txout` script: as specified in `closee_scriptpubkey` from the `closing_complete` message
170+
*/
171+
if (closee_script) {
172+
struct amount_sat amt = closee_amount;
173+
if (tal_count(closee_script) > 0
174+
&& closee_script[0] == OP_RETURN)
175+
amt = AMOUNT_SAT(0);
176+
177+
script = tal_dup_talarr(tx, u8, closee_script);
178+
bitcoin_tx_add_output(tx, script, NULL, amt);
179+
num_outputs++;
180+
}
181+
182+
if (num_outputs == 0)
183+
return tal_free(tx);
184+
185+
permute_outputs(tx, NULL, NULL);
186+
187+
bitcoin_tx_finalize(tx);
188+
assert(bitcoin_tx_check(tx));
189+
return tx;
190+
}

common/close_tx.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,19 @@ struct bitcoin_tx *create_close_tx(const tal_t *ctx,
1919
struct amount_sat to_us,
2020
struct amount_sat to_them,
2121
struct amount_sat dust_limit);
22+
/* Create simple close tx (option_simple_close) to spend the anchor tx output.
23+
* The closer pays the fee; closee output is omitted if closee_script is NULL.
24+
* Closer output is omitted if closer_script is NULL (or OP_RETURN with amount 0).
25+
* Uses sequence 0xFFFFFFFD (RBF) and the specified locktime. */
26+
struct bitcoin_tx *create_simple_close_tx(const tal_t *ctx,
27+
u32 *local_wallet_index,
28+
const struct ext_key *local_wallet_ext_key,
29+
const u8 *closer_script,
30+
const u8 *closee_script,
31+
const u8 *funding_wscript,
32+
const struct bitcoin_outpoint *funding,
33+
struct amount_sat funding_sats,
34+
struct amount_sat closer_amount,
35+
struct amount_sat closee_amount,
36+
u32 locktime);
2237
#endif /* LIGHTNING_COMMON_CLOSE_TX_H */

0 commit comments

Comments
 (0)