mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-17 19:03:42 +01:00
c03c878afc
This is a major change; instead of creating a mutual anchor (funding) transaction, each side creates its own. We use escape transactions in case anything goes wrong; these will be revoked later. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
201 lines
6.6 KiB
C
201 lines
6.6 KiB
C
#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;
|
|
}
|