mirror of
https://github.com/aljazceru/lightning.git
synced 2026-02-23 06:54:30 +01:00
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 <rusty@rustcorp.com.au>
This commit is contained in:
222
bitcoin/script.c
222
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
|
||||
* <revocation-pubkey>
|
||||
* OP_ELSE
|
||||
* `to-self-delay`
|
||||
* OP_CSV
|
||||
* OP_DROP
|
||||
* <local-delayedkey>
|
||||
* 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:
|
||||
*
|
||||
* <local-delayedsig> 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:
|
||||
*
|
||||
* <revocation-sig> 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:
|
||||
*
|
||||
* <remotekey> OP_SWAP
|
||||
* OP_SIZE 32 OP_EQUAL
|
||||
* OP_NOTIF
|
||||
* # To me via HTLC-timeout transaction (timelocked).
|
||||
* OP_DROP 2 OP_SWAP <localkey> 2 OP_CHECKMULTISIG
|
||||
* OP_ELSE
|
||||
* # To you with preimage.
|
||||
* OP_HASH160 <ripemd-of-payment-hash> 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:
|
||||
*
|
||||
* <remotekey> OP_SWAP
|
||||
* OP_SIZE 32 OP_EQUAL
|
||||
* OP_IF
|
||||
* # To me via HTLC-success transaction.
|
||||
* OP_HASH160 <ripemd-of-payment-hash> OP_EQUALVERIFY
|
||||
* 2 OP_SWAP <localkey> 2 OP_CHECKMULTISIG
|
||||
* OP_ELSE
|
||||
* # To you after timeout.
|
||||
* OP_DROP <locktime> 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 <remotesig> <localsig> <payment-preimage>` for HTLC-Success, `0 <remotesig> <localsig> 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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user