lease_rates: add csv lock to modify anchor scripts

This commit is contained in:
niftynei 2021-06-16 12:44:51 -05:00 committed by neil saitug
parent e992b54410
commit c9d2748081
11 changed files with 72 additions and 22 deletions

View File

@ -14,6 +14,8 @@
/* To push 0-75 bytes onto stack. */ /* To push 0-75 bytes onto stack. */
#define OP_PUSHBYTES(val) (val) #define OP_PUSHBYTES(val) (val)
#define max(a, b) ((a) > (b) ? (a) : (b))
/* Bitcoin's OP_HASH160 is RIPEMD(SHA256()) */ /* Bitcoin's OP_HASH160 is RIPEMD(SHA256()) */
static void hash160(struct ripemd160 *redeemhash, const void *mem, size_t len) static void hash160(struct ripemd160 *redeemhash, const void *mem, size_t len)
{ {
@ -353,15 +355,21 @@ u8 *anchor_to_remote_redeem(const tal_t *ctx,
bool is_anchor_witness_script(const u8 *script, size_t script_len) bool is_anchor_witness_script(const u8 *script, size_t script_len)
{ {
if (script_len != 34 + 1 + 1 + 1) size_t len = 34 + 1 + 1 + 1;
/* With option_will_fund, the pushbytes can be up to 2 bytes more
*
* <remote_pubkey> OP_CHECKSIGVERIFY
* MAX(1, lease_end - blockheight)
* OP_CHECKSEQUENCEVERIFY
*/
if (script_len < len || script_len > len + 2)
return false; return false;
if (script[0] != OP_PUSHBYTES(33)) if (script[0] != OP_PUSHBYTES(33))
return false; return false;
if (script[34] != OP_CHECKSIGVERIFY) if (script[34] != OP_CHECKSIGVERIFY)
return false; return false;
if (script[35] != 0x51) /* FIXME: check for push value */
return false; if (script[script_len - 1] != OP_CHECKSEQUENCEVERIFY)
if (script[36] != OP_CHECKSEQUENCEVERIFY)
return false; return false;
return true; return true;
} }
@ -521,7 +529,28 @@ u8 **bitcoin_witness_sig_and_element(const tal_t *ctx,
* OP_ENDIF * OP_ENDIF
* OP_CHECKSIG * OP_CHECKSIG
*/ */
/* BOLT- #3
* ##### Leased channel (`option_will_fund`)
* If a `lease` applies to the channel, the `to_local` output of the `accepter`
* ensures the `leasor` funds are not spendable until the lease expires.
*
* 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`.
*
* OP_IF
* # Penalty transaction
* <revocationpubkey>
* OP_ELSE
* MAX(`to_self_delay`, `lease_end` - `blockheight`)
* OP_CHECKSEQUENCEVERIFY
* OP_DROP
* <local_delayedpubkey>
* OP_ENDIF
* OP_CHECKSIG
*/
u8 *bitcoin_wscript_to_local(const tal_t *ctx, u16 to_self_delay, u8 *bitcoin_wscript_to_local(const tal_t *ctx, u16 to_self_delay,
u32 lease_remaining,
const struct pubkey *revocation_pubkey, const struct pubkey *revocation_pubkey,
const struct pubkey *local_delayedkey) const struct pubkey *local_delayedkey)
{ {
@ -529,7 +558,7 @@ u8 *bitcoin_wscript_to_local(const tal_t *ctx, u16 to_self_delay,
add_op(&script, OP_IF); add_op(&script, OP_IF);
add_push_key(&script, revocation_pubkey); add_push_key(&script, revocation_pubkey);
add_op(&script, OP_ELSE); add_op(&script, OP_ELSE);
add_number(&script, to_self_delay); add_number(&script, max(lease_remaining, to_self_delay));
add_op(&script, OP_CHECKSEQUENCEVERIFY); add_op(&script, OP_CHECKSEQUENCEVERIFY);
add_op(&script, OP_DROP); add_op(&script, OP_DROP);
add_push_key(&script, local_delayedkey); add_push_key(&script, local_delayedkey);

View File

@ -67,7 +67,7 @@ u8 *scriptpubkey_p2wpkh_derkey(const tal_t *ctx, const u8 der[33]);
u8 *scriptpubkey_witness_raw(const tal_t *ctx, u8 version, u8 *scriptpubkey_witness_raw(const tal_t *ctx, u8 version,
const u8 *wprog, size_t wprog_size); const u8 *wprog, size_t wprog_size);
/* To-remotekey with csv 1 delay. */ /* To-remotekey with csv max(lease_expiry - blockheight, 1) delay. */
u8 *anchor_to_remote_redeem(const tal_t *ctx, u8 *anchor_to_remote_redeem(const tal_t *ctx,
const struct pubkey *remote_key, const struct pubkey *remote_key,
u32 csv_lock); u32 csv_lock);
@ -91,8 +91,8 @@ u8 **bitcoin_witness_sig_and_element(const tal_t *ctx,
const u8 *witnessscript); const u8 *witnessscript);
/* BOLT #3 to-local output */ /* BOLT #3 to-local output */
u8 *bitcoin_wscript_to_local(const tal_t *ctx, u8 *bitcoin_wscript_to_local(const tal_t *ctx, u16 to_self_delay,
u16 to_self_delay, u32 lease_remaining,
const struct pubkey *revocation_pubkey, const struct pubkey *revocation_pubkey,
const struct pubkey *local_delayedkey); const struct pubkey *local_delayedkey);

View File

@ -234,7 +234,10 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx,
* output](#to_local-output). * output](#to_local-output).
*/ */
if (amount_msat_greater_eq_sat(self_pay, dust_limit)) { if (amount_msat_greater_eq_sat(self_pay, dust_limit)) {
u8 *wscript = to_self_wscript(tmpctx, to_self_delay,keyset); u8 *wscript = to_self_wscript(tmpctx,
to_self_delay,
1, /* FIXME: csv_lock */
keyset);
u8 *p2wsh = scriptpubkey_p2wsh(tx, wscript); u8 *p2wsh = scriptpubkey_p2wsh(tx, wscript);
struct amount_sat amount = amount_msat_to_sat_round_down(self_pay); struct amount_sat amount = amount_msat_to_sat_round_down(self_pay);
@ -275,6 +278,7 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx,
* Otherwise, this output is a simple P2WPKH to `remotepubkey`. * Otherwise, this output is a simple P2WPKH to `remotepubkey`.
*/ */
if (option_anchor_outputs) { if (option_anchor_outputs) {
/* FIXME: use csv_lock */
scriptpubkey = scriptpubkey_p2wsh(tmpctx, scriptpubkey = scriptpubkey_p2wsh(tmpctx,
anchor_to_remote_redeem(tmpctx, &keyset->other_payment_key, 1)); anchor_to_remote_redeem(tmpctx, &keyset->other_payment_key, 1));
} else { } else {

View File

@ -63,7 +63,8 @@ penalty_tx_create(const tal_t *ctx,
status_failed(STATUS_FAIL_INTERNAL_ERROR, status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Failed deriving keyset"); "Failed deriving keyset");
wscript = bitcoin_wscript_to_local(tmpctx, remote_to_self_delay, /* FIXME: csv_lock */
wscript = bitcoin_wscript_to_local(tmpctx, remote_to_self_delay, 1,
&keyset.self_revocation_key, &keyset.self_revocation_key,
&keyset.self_delayed_payment_key); &keyset.self_delayed_payment_key);

View File

@ -120,6 +120,7 @@ struct bitcoin_tx *initial_channel_tx(const tal_t *ctx,
0 ^ channel->commitment_number_obscurer, 0 ^ channel->commitment_number_obscurer,
direct_outputs, direct_outputs,
side, side,
0, /* FIXME: csv lock? */
channel->option_anchor_outputs, channel->option_anchor_outputs,
err_reason); err_reason);

View File

@ -51,9 +51,10 @@ bool try_subtract_fee(enum side opener, enum side side,
u8 *to_self_wscript(const tal_t *ctx, u8 *to_self_wscript(const tal_t *ctx,
u16 to_self_delay, u16 to_self_delay,
u32 csv,
const struct keyset *keyset) const struct keyset *keyset)
{ {
return bitcoin_wscript_to_local(ctx, to_self_delay, return bitcoin_wscript_to_local(ctx, to_self_delay, csv,
&keyset->self_revocation_key, &keyset->self_revocation_key,
&keyset->self_delayed_payment_key); &keyset->self_delayed_payment_key);
} }
@ -87,6 +88,7 @@ struct bitcoin_tx *initial_commit_tx(const tal_t *ctx,
u64 obscured_commitment_number, u64 obscured_commitment_number,
struct wally_tx_output *direct_outputs[NUM_SIDES], struct wally_tx_output *direct_outputs[NUM_SIDES],
enum side side, enum side side,
u32 csv_lock,
bool option_anchor_outputs, bool option_anchor_outputs,
char** err_reason) char** err_reason)
{ {
@ -208,7 +210,9 @@ struct bitcoin_tx *initial_commit_tx(const tal_t *ctx,
* output](#to_local-output). * output](#to_local-output).
*/ */
if (amount_msat_greater_eq_sat(self_pay, dust_limit)) { if (amount_msat_greater_eq_sat(self_pay, dust_limit)) {
u8 *wscript = to_self_wscript(tmpctx, to_self_delay, keyset); u8 *wscript = to_self_wscript(tmpctx,
to_self_delay, csv_lock,
keyset);
amount = amount_msat_to_sat_round_down(self_pay); amount = amount_msat_to_sat_round_down(self_pay);
int pos = bitcoin_tx_add_output( int pos = bitcoin_tx_add_output(
tx, scriptpubkey_p2wsh(tx, wscript), wscript, amount); tx, scriptpubkey_p2wsh(tx, wscript), wscript, amount);
@ -242,7 +246,7 @@ struct bitcoin_tx *initial_commit_tx(const tal_t *ctx,
amount = amount_msat_to_sat_round_down(other_pay); amount = amount_msat_to_sat_round_down(other_pay);
if (option_anchor_outputs) { if (option_anchor_outputs) {
scriptpubkey = scriptpubkey_p2wsh(tmpctx, scriptpubkey = scriptpubkey_p2wsh(tmpctx,
anchor_to_remote_redeem(tmpctx, &keyset->other_payment_key, 1)); anchor_to_remote_redeem(tmpctx, &keyset->other_payment_key, csv_lock));
} else { } else {
scriptpubkey = scriptpubkey_p2wpkh(tmpctx, scriptpubkey = scriptpubkey_p2wpkh(tmpctx,
&keyset->other_payment_key); &keyset->other_payment_key);

View File

@ -121,6 +121,7 @@ struct bitcoin_tx *initial_commit_tx(const tal_t *ctx,
u64 obscured_commitment_number, u64 obscured_commitment_number,
struct wally_tx_output *direct_outputs[NUM_SIDES], struct wally_tx_output *direct_outputs[NUM_SIDES],
enum side side, enum side side,
u32 csv_lock,
bool option_anchor_outputs, bool option_anchor_outputs,
char** err_reason); char** err_reason);
@ -134,6 +135,7 @@ bool try_subtract_fee(enum side opener, enum side side,
* scriptpubkey_p2wsh(ctx, wscript) gives the scriptpubkey */ * scriptpubkey_p2wsh(ctx, wscript) gives the scriptpubkey */
u8 *to_self_wscript(const tal_t *ctx, u8 *to_self_wscript(const tal_t *ctx,
u16 to_self_delay, u16 to_self_delay,
u32 csv,
const struct keyset *keyset); const struct keyset *keyset);
/* To-other is simply: scriptpubkey_p2wpkh(tx, keyset->other_payment_key) */ /* To-other is simply: scriptpubkey_p2wpkh(tx, keyset->other_payment_key) */

View File

@ -388,7 +388,10 @@ static void sign_our_inputs(struct utxo **utxos, struct wally_psbt *psbt)
/* It's actually a P2WSH in this case. */ /* It's actually a P2WSH in this case. */
if (utxo->close_info && utxo->close_info->option_anchor_outputs) { if (utxo->close_info && utxo->close_info->option_anchor_outputs) {
const u8 *wscript = anchor_to_remote_redeem(tmpctx, &pubkey, 1); const u8 *wscript
= anchor_to_remote_redeem(tmpctx,
&pubkey,
1); /* FIXME: lease csv ? */
psbt_input_set_witscript(psbt, j, wscript); psbt_input_set_witscript(psbt, j, wscript);
psbt_input_set_wit_utxo(psbt, j, psbt_input_set_wit_utxo(psbt, j,
scriptpubkey_p2wsh(psbt, wscript), scriptpubkey_p2wsh(psbt, wscript),

View File

@ -12,6 +12,7 @@
#include <common/initial_commit_tx.h> #include <common/initial_commit_tx.h>
#include <common/key_derive.h> #include <common/key_derive.h>
#include <common/keyset.h> #include <common/keyset.h>
#include <common/lease_rates.h>
#include <common/memleak.h> #include <common/memleak.h>
#include <common/overflows.h> #include <common/overflows.h>
#include <common/peer_billboard.h> #include <common/peer_billboard.h>
@ -2644,15 +2645,15 @@ static void handle_our_unilateral(const struct tx_parts *tx,
type_to_string(tmpctx, struct pubkey, type_to_string(tmpctx, struct pubkey,
&keyset->other_htlc_key)); &keyset->other_htlc_key));
local_wscript = to_self_wscript(tmpctx, to_self_delay[LOCAL], keyset); local_wscript = to_self_wscript(tmpctx, to_self_delay[LOCAL],
1, keyset);
/* Figure out what to-us output looks like. */ /* Figure out what to-us output looks like. */
script[LOCAL] = scriptpubkey_p2wsh(tmpctx, local_wscript); script[LOCAL] = scriptpubkey_p2wsh(tmpctx, local_wscript);
/* Figure out what direct to-them output looks like. */ /* Figure out what direct to-them output looks like. */
script[REMOTE] = scriptpubkey_to_remote(tmpctx, script[REMOTE] = scriptpubkey_to_remote(tmpctx,
&keyset->other_payment_key, &keyset->other_payment_key, 1);
1);
/* Calculate all the HTLC scripts so we can match them */ /* Calculate all the HTLC scripts so we can match them */
htlc_scripts = derive_htlc_scripts(htlcs, LOCAL); htlc_scripts = derive_htlc_scripts(htlcs, LOCAL);
@ -2866,7 +2867,8 @@ static void handle_our_unilateral(const struct tx_parts *tx,
/* We produce individual penalty txs. It's less efficient, but avoids them /* We produce individual penalty txs. It's less efficient, but avoids them
* using HTLC txs to block our penalties for long enough to pass the CSV * using HTLC txs to block our penalties for long enough to pass the CSV
* delay */ * delay */
static void steal_to_them_output(struct tracked_output *out, bool is_replay) static void steal_to_them_output(struct tracked_output *out,
u32 csv, bool is_replay)
{ {
u8 *wscript; u8 *wscript;
struct bitcoin_tx *tx; struct bitcoin_tx *tx;
@ -2879,7 +2881,7 @@ static void steal_to_them_output(struct tracked_output *out, bool is_replay)
* *
* <revocation_sig> 1 * <revocation_sig> 1
*/ */
wscript = bitcoin_wscript_to_local(tmpctx, to_self_delay[REMOTE], wscript = bitcoin_wscript_to_local(tmpctx, to_self_delay[REMOTE], csv,
&keyset->self_revocation_key, &keyset->self_revocation_key,
&keyset->self_delayed_payment_key); &keyset->self_delayed_payment_key);
@ -3083,7 +3085,8 @@ static void handle_their_cheat(const struct tx_parts *tx,
static_remotekey_start[LOCAL], static_remotekey_start[LOCAL],
static_remotekey_start[REMOTE]); static_remotekey_start[REMOTE]);
remote_wscript = to_self_wscript(tmpctx, to_self_delay[REMOTE], keyset); remote_wscript = to_self_wscript(tmpctx, to_self_delay[REMOTE],
1, keyset);
/* Figure out what to-them output looks like. */ /* Figure out what to-them output looks like. */
script[REMOTE] = scriptpubkey_p2wsh(tmpctx, remote_wscript); script[REMOTE] = scriptpubkey_p2wsh(tmpctx, remote_wscript);
@ -3176,7 +3179,7 @@ static void handle_their_cheat(const struct tx_parts *tx,
amt, amt,
DELAYED_CHEAT_OUTPUT_TO_THEM, DELAYED_CHEAT_OUTPUT_TO_THEM,
NULL, NULL, NULL); NULL, NULL, NULL);
steal_to_them_output(out, is_replay); steal_to_them_output(out, 1, is_replay);
script[REMOTE] = NULL; script[REMOTE] = NULL;
add_amt(&total_outs, amt); add_amt(&total_outs, amt);
continue; continue;
@ -3365,7 +3368,8 @@ static void handle_their_unilateral(const struct tx_parts *tx,
type_to_string(tmpctx, struct pubkey, type_to_string(tmpctx, struct pubkey,
&keyset->other_htlc_key)); &keyset->other_htlc_key));
remote_wscript = to_self_wscript(tmpctx, to_self_delay[REMOTE], keyset); remote_wscript = to_self_wscript(tmpctx, to_self_delay[REMOTE],
1, keyset);
/* Figure out what to-them output looks like. */ /* Figure out what to-them output looks like. */
script[REMOTE] = scriptpubkey_p2wsh(tmpctx, remote_wscript); script[REMOTE] = scriptpubkey_p2wsh(tmpctx, remote_wscript);

View File

@ -213,6 +213,7 @@ void subdaemon_setup(int argc UNNEEDED, char *argv[])
/* Generated stub for to_self_wscript */ /* Generated stub for to_self_wscript */
u8 *to_self_wscript(const tal_t *ctx UNNEEDED, u8 *to_self_wscript(const tal_t *ctx UNNEEDED,
u16 to_self_delay UNNEEDED, u16 to_self_delay UNNEEDED,
u32 csv UNNEEDED,
const struct keyset *keyset UNNEEDED) const struct keyset *keyset UNNEEDED)
{ fprintf(stderr, "to_self_wscript called!\n"); abort(); } { fprintf(stderr, "to_self_wscript called!\n"); abort(); }
/* Generated stub for towire */ /* Generated stub for towire */

View File

@ -230,6 +230,7 @@ void subdaemon_setup(int argc UNNEEDED, char *argv[])
/* Generated stub for to_self_wscript */ /* Generated stub for to_self_wscript */
u8 *to_self_wscript(const tal_t *ctx UNNEEDED, u8 *to_self_wscript(const tal_t *ctx UNNEEDED,
u16 to_self_delay UNNEEDED, u16 to_self_delay UNNEEDED,
u32 csv UNNEEDED,
const struct keyset *keyset UNNEEDED) const struct keyset *keyset UNNEEDED)
{ fprintf(stderr, "to_self_wscript called!\n"); abort(); } { fprintf(stderr, "to_self_wscript called!\n"); abort(); }
/* Generated stub for towire */ /* Generated stub for towire */