From 6f3803aae7392d33177004f75b71f6248739d0a3 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 7 Feb 2017 12:14:21 +1030 Subject: [PATCH] bitcoin/script: BOLT 3 commitment transaction support. This is a step away from the previous more generic script types into specific helpers for each transaction type we need. Signed-off-by: Rusty Russell --- bitcoin/script.c | 222 +++++++++++++++++++++++++++++++++++++++++++++++ bitcoin/script.h | 33 +++++++ 2 files changed, 255 insertions(+) diff --git a/bitcoin/script.c b/bitcoin/script.c index 32f7ff849..63daca606 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -1,5 +1,6 @@ #include "address.h" #include "locktime.h" +#include "preimage.h" #include "pubkey.h" #include "script.h" #include "signature.h" @@ -139,6 +140,11 @@ static u8 *stack_sig(const tal_t *ctx, const secp256k1_ecdsa_signature *sig) return tal_dup_arr(ctx, u8, der, len, 0); } +static u8 *stack_preimage(const tal_t *ctx, const struct preimage *preimage) +{ + return tal_dup_arr(ctx, u8, preimage->r, sizeof(preimage->r), 0); +} + /* Bitcoin script stack values are a special, special snowflake. * * They're little endian values, but 0 is an empty value. We only @@ -592,6 +598,222 @@ u8 **bitcoin_witness_htlc(const tal_t *ctx, 32, sig, witnessscript); } +/* BOLT #3: + * + * This output sends funds back to the owner of this commitment transaction, + * thus must be timelocked using `OP_CSV`. It can be claimed, without delay, + * by the other party if they know the revocation key. The output is a version + * 0 P2WSH, with a witness script: + * + * OP_IF + * # Penalty transaction + * + * OP_ELSE + * `to-self-delay` + * OP_CSV + * OP_DROP + * + * OP_ENDIF + * OP_CHECKSIG + */ +u8 *bitcoin_wscript_to_local(const tal_t *ctx, u16 to_self_delay, + const struct pubkey *revocation_pubkey, + const struct pubkey *local_delayedkey) +{ + u8 *script = tal_arr(ctx, u8, 0); + add_op(&script, OP_IF); + add_push_key(&script, revocation_pubkey); + add_op(&script, OP_ELSE); + add_number(&script, to_self_delay); + add_op(&script, OP_CHECKSEQUENCEVERIFY); + add_op(&script, OP_DROP); + add_push_key(&script, local_delayedkey); + add_op(&script, OP_ENDIF); + add_op(&script, OP_CHECKSIG); + return script; +} + +u8 **bitcoin_to_local_spend_delayedkey(const tal_t *ctx, + const secp256k1_ecdsa_signature *local_delayedsig, + const u8 *wscript) +{ + /* BOLT #3: + * + * It is spent by a transaction with `nSequence` field set to + * `to-self-delay` (which can only be valid after that duration has + * passed), and witness: + * + * 0 + */ + u8 **witness = tal_arr(ctx, u8 *, 3); + + witness[0] = stack_sig(witness, local_delayedsig); + witness[1] = stack_number(witness, 0); + witness[2] = tal_dup_arr(witness, u8, wscript, tal_len(wscript), 0); + return witness; +} + +u8 **bitcoin_to_local_spend_revocation(const tal_t *ctx, + const secp256k1_ecdsa_signature *revocation_sig, + const u8 *wscript) +{ + /* BOLT #3: + * + * If a revoked commitment transaction is published, the other party + * can spend this output immediately with the following witness: + * + * 1 + */ + u8 **witness = tal_arr(ctx, u8 *, 3); + + witness[0] = stack_sig(witness, revocation_sig); + witness[1] = stack_number(witness, 1); + witness[2] = tal_dup_arr(witness, u8, wscript, tal_len(wscript), 0); + + return witness; +} + +/* BOLT #3: + * + * This output sends funds to a HTLC-timeout transaction after the + * HTLC timeout, or to the remote peer on successful payment preimage. + * The output is a P2WSH, with a witness script: + * + * OP_SWAP + * OP_SIZE 32 OP_EQUAL + * OP_NOTIF + * # To me via HTLC-timeout transaction (timelocked). + * OP_DROP 2 OP_SWAP 2 OP_CHECKMULTISIG + * OP_ELSE + * # To you with preimage. + * OP_HASH160 OP_EQUALVERIFY + * OP_CHECKSIG + * OP_ENDIF + */ +u8 *bitcoin_wscript_htlc_offer(const tal_t *ctx, + const struct pubkey *localkey, + const struct pubkey *remotekey, + const struct sha256 *payment_hash) +{ + u8 *script = tal_arr(ctx, u8, 0); + struct ripemd160 ripemd; + + add_push_key(&script, remotekey); + add_op(&script, OP_SWAP); + add_op(&script, OP_SIZE); + add_number(&script, 32); + add_op(&script, OP_EQUAL); + add_op(&script, OP_NOTIF); + add_op(&script, OP_DROP); + add_number(&script, 2); + add_op(&script, OP_SWAP); + add_push_key(&script, localkey); + add_number(&script, 2); + add_op(&script, OP_CHECKMULTISIG); + add_op(&script, OP_ELSE); + add_op(&script, OP_HASH160); + ripemd160(&ripemd, payment_hash->u.u8, sizeof(payment_hash->u)); + add_push_bytes(&script, ripemd.u.u8, sizeof(ripemd.u.u8)); + add_op(&script, OP_EQUALVERIFY); + add_op(&script, OP_CHECKSIG); + add_op(&script, OP_ENDIF); + + return script; +} + +/* BOLT #3: + * + * This output sends funds to the remote peer after the HTLC timeout, + * or to an HTLC-success transaction with a successful payment + * preimage. The output is a P2WSH, with a witness script: + * + * OP_SWAP + * OP_SIZE 32 OP_EQUAL + * OP_IF + * # To me via HTLC-success transaction. + * OP_HASH160 OP_EQUALVERIFY + * 2 OP_SWAP 2 OP_CHECKMULTISIG + * OP_ELSE + * # To you after timeout. + * OP_DROP OP_CHECKLOCKTIMEVERIFY OP_DROP + * OP_CHECKSIG + * OP_ENDIF + */ +u8 *bitcoin_wscript_htlc_receive(const tal_t *ctx, + const struct abs_locktime *htlc_abstimeout, + const struct pubkey *localkey, + const struct pubkey *remotekey, + const struct sha256 *payment_hash) +{ + u8 *script = tal_arr(ctx, u8, 0); + struct ripemd160 ripemd; + + add_push_key(&script, remotekey); + add_op(&script, OP_SWAP); + add_op(&script, OP_SIZE); + add_number(&script, 32); + add_op(&script, OP_EQUAL); + add_op(&script, OP_IF); + add_op(&script, OP_HASH160); + ripemd160(&ripemd, payment_hash->u.u8, sizeof(payment_hash->u)); + add_push_bytes(&script, ripemd.u.u8, sizeof(ripemd.u.u8)); + add_op(&script, OP_EQUALVERIFY); + add_number(&script, 2); + add_op(&script, OP_SWAP); + add_push_key(&script, localkey); + add_number(&script, 2); + add_op(&script, OP_CHECKMULTISIG); + add_op(&script, OP_ELSE); + add_op(&script, OP_DROP); + add_number(&script, htlc_abstimeout->locktime); + add_op(&script, OP_CHECKLOCKTIMEVERIFY); + add_op(&script, OP_DROP); + add_op(&script, OP_CHECKSIG); + add_op(&script, OP_ENDIF); + + return script; +} + +/* BOLT #3: + * + * ## HTLC-Timeout and HTLC-Success Transactions + * + *... + * * `txin[0]` witness stack: `0 ` for HTLC-Success, `0 0` for HTLC-Timeout. + */ +u8 **bitcoin_htlc_offer_spend_timeout(const tal_t *ctx, + const secp256k1_ecdsa_signature *localsig, + const secp256k1_ecdsa_signature *remotesig, + const u8 *wscript) +{ + u8 **witness = tal_arr(ctx, u8 *, 5); + + witness[0] = stack_number(witness, 0); + witness[1] = stack_sig(witness, remotesig); + witness[2] = stack_sig(witness, localsig); + witness[3] = stack_number(witness, 0); + witness[4] = tal_dup_arr(witness, u8, wscript, tal_len(wscript), 0); + + return witness; +} + +u8 **bitcoin_htlc_receive_spend_preimage(const tal_t *ctx, + const secp256k1_ecdsa_signature *localsig, + const secp256k1_ecdsa_signature *remotesig, + const struct preimage *preimage, + const u8 *wscript) +{ + u8 **witness = tal_arr(ctx, u8 *, 5); + + witness[0] = stack_number(witness, 0); + witness[1] = stack_sig(witness, remotesig); + witness[2] = stack_sig(witness, localsig); + witness[3] = stack_preimage(witness, preimage); + witness[4] = tal_dup_arr(witness, u8, wscript, tal_len(wscript), 0); + + return witness; +} + bool scripteq(const tal_t *s1, const tal_t *s2) { memcheck(s1, tal_len(s1)); diff --git a/bitcoin/script.h b/bitcoin/script.h index c8de05abd..e1e412bbb 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -8,6 +8,7 @@ struct bitcoin_address; struct bitcoin_tx_input; +struct preimage; struct pubkey; struct sha256; struct rel_locktime; @@ -96,6 +97,38 @@ u8 **bitcoin_witness_htlc(const tal_t *ctx, const secp256k1_ecdsa_signature *sig, const u8 *witnessscript); +/* BOLT #3 to-local output */ +u8 *bitcoin_wscript_to_local(const tal_t *ctx, + u16 to_self_delay, + const struct pubkey *revocation_pubkey, + const struct pubkey *local_delayedkey); +u8 **bitcoin_to_local_spend_delayedkey(const tal_t *ctx, + const secp256k1_ecdsa_signature *local_delayedsig, + const u8 *wscript); +u8 **bitcoin_to_local_spend_revocation(const tal_t *ctx, + const secp256k1_ecdsa_signature *revocation_sig, + const u8 *wscript); + +/* BOLT #3 offered/accepted HTLC outputs */ +u8 *bitcoin_wscript_htlc_offer(const tal_t *ctx, + const struct pubkey *localkey, + const struct pubkey *remotekey, + const struct sha256 *payment_hash); +u8 **bitcoin_htlc_offer_spend_timeout(const tal_t *ctx, + const secp256k1_ecdsa_signature *localsig, + const secp256k1_ecdsa_signature *remotesig, + const u8 *wscript); +u8 *bitcoin_wscript_htlc_receive(const tal_t *ctx, + const struct abs_locktime *htlc_abstimeout, + const struct pubkey *localkey, + const struct pubkey *remotekey, + const struct sha256 *payment_hash); +u8 **bitcoin_htlc_receive_spend_preimage(const tal_t *ctx, + const secp256k1_ecdsa_signature *localsig, + const secp256k1_ecdsa_signature *remotesig, + const struct preimage *preimage, + const u8 *wscript); + /* Is this a pay to pubkeu hash? */ bool is_p2pkh(const u8 *script);