core-lightning/anchor.c

201 lines
6.6 KiB
C
Raw Normal View History

#include "anchor.h"
#include "bitcoin/script.h"
#include "protobuf_convert.h"
#undef DEBUG
#ifdef DEBUG
#include <stdio.h>
#include "bitcoin/pubkey.h"
static void dump_anchor_spend(const char *what,
size_t input,
const struct pubkey *commitkey1,
const struct pubkey *commitkey2,
const struct pubkey *finalkey,
const struct sha256 *escapehash,
const struct pubkey *signingkey,
const struct signature *sig)
{
size_t i;
fprintf(stderr, "%s input %zu:", what, input);
fprintf(stderr, " commitkey1=");
for (i = 0; i < pubkey_len(commitkey1); i++)
fprintf(stderr, "%02x", commitkey1->key[i]);
fprintf(stderr, " commitkey2=");
for (i = 0; i < pubkey_len(commitkey2); i++)
fprintf(stderr, "%02x", commitkey2->key[i]);
fprintf(stderr, " finalkey=");
for (i = 0; i < pubkey_len(finalkey); i++)
fprintf(stderr, "%02x", finalkey->key[i]);
fprintf(stderr, " escapehash=");
for (i = 0; i < sizeof(escapehash->u.u8); i++)
fprintf(stderr, "%02x", escapehash->u.u8[i]);
fprintf(stderr, " signingkey=");
for (i = 0; i < pubkey_len(signingkey); i++)
fprintf(stderr, "%02x", signingkey->key[i]);
fprintf(stderr, " -> sig {r=");
for (i = 0; i < sizeof(sig->r); i++)
fprintf(stderr, "%02x", sig->r[i]);
fprintf(stderr, ", s=");
for (i = 0; i < sizeof(sig->s); i++)
fprintf(stderr, "%02x", sig->s[i]);
fprintf(stderr, "}\n");
}
#else
static void dump_anchor_spend(const char *what,
size_t input,
const struct pubkey *commitkey1,
const struct pubkey *commitkey2,
const struct pubkey *finalkey,
const struct sha256 *escapehash,
const struct pubkey *signingkey,
const struct signature *sig)
{
}
#endif
bool sign_anchor_spend(struct bitcoin_tx *tx,
const size_t inmap[2],
const struct pubkey *my_commitkey,
const struct pubkey *my_finalkey,
const struct sha256 *my_escapehash,
const struct pubkey *their_commitkey,
const struct pubkey *their_finalkey,
const struct sha256 *their_escapehash,
const struct pubkey *signing_pubkey,
const struct privkey *signing_privkey,
struct signature sig[2])
{
const tal_t *ctx = tal(NULL, char);
u8 *redeemscript;
bool ret;
/* Sign input for our anchor. */
redeemscript = bitcoin_redeem_anchor(ctx, my_commitkey, their_commitkey,
their_finalkey, my_escapehash);
ret = sign_tx_input(ctx, tx, inmap[0],
redeemscript, tal_count(redeemscript),
signing_privkey, signing_pubkey, &sig[inmap[0]]);
dump_anchor_spend("signed from_mine", inmap[0],
my_commitkey, their_commitkey, their_finalkey,
my_escapehash, signing_pubkey, &sig[inmap[0]]);
/* Sign input for their anchor. */
redeemscript = bitcoin_redeem_anchor(ctx, their_commitkey, my_commitkey,
my_finalkey, their_escapehash);
ret &= sign_tx_input(ctx, tx, inmap[1],
redeemscript, tal_count(redeemscript),
signing_privkey, signing_pubkey, &sig[inmap[1]]);
dump_anchor_spend("signed from_yours", inmap[1],
their_commitkey, my_commitkey, my_finalkey,
their_escapehash, signing_pubkey, &sig[inmap[1]]);
tal_free(ctx);
return ret;
}
/* Check that their sigs sign this tx as expected. */
bool check_anchor_spend(struct bitcoin_tx *tx,
const size_t inmap[2],
const struct pubkey *my_commitkey,
const struct pubkey *my_finalkey,
const struct sha256 *my_escapehash,
const struct pubkey *their_commitkey,
const struct pubkey *their_finalkey,
const struct sha256 *their_escapehash,
const struct pubkey *signing_pubkey,
const AnchorSpend *their_sigs)
{
const tal_t *ctx;
u8 *redeemscript;
bool ret;
struct bitcoin_signature sigs[2];
sigs[0].stype = sigs[1].stype = SIGHASH_ALL;
if (!proto_to_signature(their_sigs->sig0, &sigs[0].sig)
|| !proto_to_signature(their_sigs->sig1, &sigs[1].sig))
return false;
ctx = tal(NULL, char);
/* Input for our anchor. */
redeemscript = bitcoin_redeem_anchor(ctx, my_commitkey, their_commitkey,
their_finalkey, my_escapehash);
ret = check_tx_sig(tx, inmap[0], redeemscript, tal_count(redeemscript),
signing_pubkey, &sigs[inmap[0]]);
dump_anchor_spend("checking from_mine", inmap[0],
my_commitkey, their_commitkey, their_finalkey,
my_escapehash, signing_pubkey, &sigs[inmap[0]].sig);
/* Input for their anchor. */
redeemscript = bitcoin_redeem_anchor(ctx, their_commitkey, my_commitkey,
my_finalkey, their_escapehash);
ret &= check_tx_sig(tx, inmap[1], redeemscript, tal_count(redeemscript),
signing_pubkey, &sigs[inmap[1]]);
dump_anchor_spend("checking from_yours", inmap[1],
their_commitkey, my_commitkey, my_finalkey,
their_escapehash, signing_pubkey, &sigs[inmap[1]].sig);
tal_free(ctx);
return ret;
}
/* Set up input scriptsigs for this transaction. */
bool populate_anchor_inscripts(const tal_t *ctx,
struct bitcoin_tx *tx,
const size_t inmap[2],
const struct pubkey *my_commitkey,
const struct pubkey *my_finalkey,
const struct sha256 *my_escapehash,
const struct pubkey *their_commitkey,
const struct pubkey *their_finalkey,
const struct sha256 *their_escapehash,
const AnchorSpend *my_sigs,
const AnchorSpend *their_sigs)
{
u8 *redeemscript;
struct bitcoin_signature theirs[2], mine[2];
theirs[0].stype = theirs[1].stype = mine[0].stype = mine[1].stype
= SIGHASH_ALL;
if (!proto_to_signature(their_sigs->sig0, &theirs[0].sig)
|| !proto_to_signature(their_sigs->sig1, &theirs[1].sig)
|| !proto_to_signature(my_sigs->sig0, &mine[0].sig)
|| !proto_to_signature(my_sigs->sig1, &mine[1].sig))
return false;
/* Input for our anchor. */
redeemscript = bitcoin_redeem_anchor(ctx, my_commitkey, their_commitkey,
their_finalkey, my_escapehash);
tx->input[inmap[0]].script
= scriptsig_p2sh_anchor_commit(ctx,
&theirs[inmap[0]],
&mine[inmap[0]],
redeemscript,
tal_count(redeemscript));
tal_free(redeemscript);
/* Input for their anchor. */
redeemscript = bitcoin_redeem_anchor(ctx, their_commitkey, my_commitkey,
my_finalkey, their_escapehash);
/* They created their anchor to expect sigs in other order. */
tx->input[inmap[1]].script
= scriptsig_p2sh_anchor_commit(ctx,
&mine[inmap[1]],
&theirs[inmap[1]],
redeemscript,
tal_count(redeemscript));
tal_free(redeemscript);
/* Set up lengths. */
tx->input[0].script_length = tal_count(tx->input[0].script);
tx->input[1].script_length = tal_count(tx->input[1].script);
return true;
}