mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
open-commit-sig: create signature for commit tx.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
63986e5b2d
commit
bf38ca052e
8
Makefile
8
Makefile
@ -3,7 +3,7 @@
|
||||
# Needs to have oneof support: Ubuntu vivid's is too old :(
|
||||
PROTOCC:=protoc-c
|
||||
|
||||
PROGRAMS := open-channel open-anchor-sig leak-anchor-sigs
|
||||
PROGRAMS := open-channel open-anchor-sig leak-anchor-sigs open-commit-sig
|
||||
|
||||
HELPER_OBJS := base58.o lightning.pb-c.o shadouble.o pkt.o bitcoin_script.o permute_tx.o signature.o bitcoin_tx.o bitcoin_address.o anchor.o
|
||||
|
||||
@ -12,6 +12,7 @@ CCAN_OBJS := ccan-crypto-sha256.o ccan-crypto-shachain.o ccan-err.o ccan-tal.o c
|
||||
OPEN_CHANNEL_OBJS := open-channel.o
|
||||
OPEN_ANCHOR_SIG_OBJS := open-anchor-sig.o
|
||||
LEAK_ANCHOR_SIGS_OBJS := leak-anchor-sigs.o
|
||||
OPEN_COMMIT_SIG_OBJS := open-commit-sig.o
|
||||
|
||||
HEADERS := $(wildcard *.h)
|
||||
|
||||
@ -33,12 +34,15 @@ $(OPEN_ANCHOR_SIG_OBJS): $(HEADERS)
|
||||
leak-anchor-sigs: $(LEAK_ANCHOR_SIGS_OBJS) $(HELPER_OBJS) $(CCAN_OBJS)
|
||||
$(LEAK_ANCHOR_SIGS_OBJS): $(HEADERS)
|
||||
|
||||
open-commit-sig: $(OPEN_COMMIT_SIG_OBJS) $(HELPER_OBJS) $(CCAN_OBJS)
|
||||
$(OPEN_COMMIT_SIG_OBJS): $(HEADERS)
|
||||
|
||||
distclean: clean
|
||||
$(RM) lightning.pb-c.c lightning.pb-c.h
|
||||
|
||||
clean:
|
||||
$(RM) $(PROGRAMS)
|
||||
$(RM) $(OPEN_CHANNEL_OBJS) $(OPEN_ANCHOR_SIG_OBJS) $(LEAK_ANCHOR_SIGS_OBJS) $(HELPER_OBJS) $(CCAN_OBJS)
|
||||
$(RM) $(OPEN_CHANNEL_OBJS) $(OPEN_ANCHOR_SIG_OBJS) $(LEAK_ANCHOR_SIGS_OBJS) $(OPEN_COMMIT_SIG_OBJS) $(HELPER_OBJS) $(CCAN_OBJS)
|
||||
|
||||
ccan-tal.o: $(CCANDIR)/ccan/tal/tal.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
41
anchor.c
41
anchor.c
@ -4,6 +4,7 @@
|
||||
#include "pkt.h"
|
||||
#include "permute_tx.h"
|
||||
#include "bitcoin_script.h"
|
||||
#include <ccan/err/err.h>
|
||||
|
||||
struct bitcoin_tx *anchor_tx_create(const tal_t *ctx,
|
||||
const OpenChannel *o1,
|
||||
@ -16,7 +17,7 @@ struct bitcoin_tx *anchor_tx_create(const tal_t *ctx,
|
||||
size_t *inmap, *outmap;
|
||||
|
||||
if (add_overflows_size_t(o1->anchor->n_inputs, o2->anchor->n_inputs))
|
||||
return tal_free(tx);
|
||||
return NULL;
|
||||
|
||||
n_out = 1 + !!o1->anchor->change + !!o2->anchor->change;
|
||||
tx = bitcoin_tx(ctx, o1->anchor->n_inputs+o2->anchor->n_inputs, n_out);
|
||||
@ -88,4 +89,42 @@ struct bitcoin_tx *anchor_tx_create(const tal_t *ctx,
|
||||
return tx;
|
||||
}
|
||||
|
||||
void anchor_txid(struct bitcoin_tx *anchor,
|
||||
const char *leakfile1, const char *leakfile2,
|
||||
const size_t *inmap,
|
||||
struct sha256_double *txid)
|
||||
{
|
||||
Pkt *p1, *p2;
|
||||
LeakAnchorSigsAndPretendWeDidnt *leak1, *leak2;
|
||||
size_t i;
|
||||
struct sha256_ctx shactx;
|
||||
|
||||
p1 = pkt_from_file(leakfile1, PKT__PKT_OMG_FAIL);
|
||||
p2 = pkt_from_file(leakfile2, PKT__PKT_OMG_FAIL);
|
||||
leak1 = p1->omg_fail;
|
||||
leak2 = p2->omg_fail;
|
||||
|
||||
if (leak1->sigs->n_script + leak2->sigs->n_script != anchor->input_count)
|
||||
errx(1, "Expected %llu total inputs, not %zu + %zu",
|
||||
(long long)anchor->input_count,
|
||||
leak1->sigs->n_script, leak2->sigs->n_script);
|
||||
|
||||
for (i = 0; i < leak1->sigs->n_script; i++) {
|
||||
anchor->input[i].script = leak1->sigs->script[i].data;
|
||||
anchor->input[i].script_length = leak1->sigs->script[i].len;
|
||||
}
|
||||
|
||||
for (i = 0; i < leak2->sigs->n_script; i++) {
|
||||
anchor->input[leak1->sigs->n_script + i].script
|
||||
= leak2->sigs->script[i].data;
|
||||
anchor->input[leak1->sigs->n_script + i].script_length
|
||||
= leak2->sigs->script[i].len;
|
||||
}
|
||||
|
||||
sha256_init(&shactx);
|
||||
sha256_tx(&shactx, anchor);
|
||||
sha256_double_done(&shactx, txid);
|
||||
|
||||
pkt__free_unpacked(p1, NULL);
|
||||
pkt__free_unpacked(p2, NULL);
|
||||
}
|
||||
|
8
anchor.h
8
anchor.h
@ -3,6 +3,8 @@
|
||||
#include <ccan/tal/tal.h>
|
||||
#include "lightning.pb-c.h"
|
||||
|
||||
struct sha256_double;
|
||||
|
||||
/* Create an anchor transaction based on both sides' requests.
|
||||
* The scriptSigs are left empty.
|
||||
*
|
||||
@ -16,4 +18,10 @@ struct bitcoin_tx *anchor_tx_create(const tal_t *ctx,
|
||||
const OpenChannel *o1,
|
||||
const OpenChannel *o2,
|
||||
size_t **inmap, size_t **outmap);
|
||||
|
||||
/* We wouldn't need the leak files if we had normalized txids! */
|
||||
void anchor_txid(struct bitcoin_tx *anchor,
|
||||
const char *leakfile1, const char *leakfile2,
|
||||
const size_t *inmap,
|
||||
struct sha256_double *txid);
|
||||
#endif /* LIGHTNING_ANCHOR_H */
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "bitcoin_script.h"
|
||||
#include "bitcoin_address.h"
|
||||
#include "pkt.h"
|
||||
#include <openssl/ripemd.h>
|
||||
#include <ccan/endian/endian.h>
|
||||
#include <ccan/crypto/sha256/sha256.h>
|
||||
@ -11,12 +12,19 @@
|
||||
#define OP_PUSHDATA2 0x4D
|
||||
#define OP_PUSHDATA4 0x4E
|
||||
#define OP_NOP 0x61
|
||||
#define OP_IF 0x63
|
||||
#define OP_ELSE 0x67
|
||||
#define OP_ENDIF 0x68
|
||||
#define OP_DEPTH 0x74
|
||||
#define OP_DUP 0x76
|
||||
#define OP_EQUAL 0x87
|
||||
#define OP_EQUALVERIFY 0x88
|
||||
#define OP_SIZE 0x82
|
||||
#define OP_1SUB 0x8C
|
||||
#define OP_CHECKSIG 0xAC
|
||||
#define OP_CHECKMULTISIG 0xAE
|
||||
#define OP_HASH160 0xA9
|
||||
#define OP_CHECKSEQUENCEVERIFY 0xB2
|
||||
|
||||
static void add(u8 **scriptp, const void *mem, size_t len)
|
||||
{
|
||||
@ -160,3 +168,66 @@ bool is_pay_to_pubkey_hash(const ProtobufCBinaryData *script)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* One of:
|
||||
* mysig and theirsig, OR
|
||||
* mysig and relative locktime passed, OR
|
||||
* theirsig and hash preimage. */
|
||||
u8 *bitcoin_redeem_revocable(const tal_t *ctx,
|
||||
const BitcoinPubkey *mykey,
|
||||
u32 locktime,
|
||||
const BitcoinPubkey *theirkey,
|
||||
const Sha256Hash *revocation_hash)
|
||||
{
|
||||
u8 *script = tal_arr(ctx, u8, 0);
|
||||
struct sha256 rhash;
|
||||
u8 rhash_ripemd[RIPEMD160_DIGEST_LENGTH];
|
||||
le32 locktime_le = cpu_to_le32(locktime);
|
||||
|
||||
proto_to_sha256(revocation_hash, &rhash);
|
||||
|
||||
/* If there are two args: */
|
||||
add_op(&script, OP_DEPTH);
|
||||
add_op(&script, OP_1SUB);
|
||||
add_op(&script, OP_IF);
|
||||
|
||||
/* If the top arg is a hashpreimage. */
|
||||
add_op(&script, OP_SIZE);
|
||||
add_op(&script, OP_LITERAL(32));
|
||||
add_op(&script, OP_EQUAL);
|
||||
add_op(&script, OP_IF);
|
||||
|
||||
/* Must hash to revocation_hash, and be signed by them. */
|
||||
RIPEMD160(rhash.u.u8, sizeof(rhash.u), rhash_ripemd);
|
||||
add_op(&script, OP_HASH160);
|
||||
add_push_bytes(&script, rhash_ripemd, sizeof(rhash_ripemd));
|
||||
add_op(&script, OP_EQUALVERIFY);
|
||||
add_push_bytes(&script, theirkey->key.data, theirkey->key.len);
|
||||
add_op(&script, OP_CHECKSIG);
|
||||
|
||||
/* Otherwise, it should be both our sigs. */
|
||||
add_op(&script, OP_ELSE);
|
||||
|
||||
add_op(&script, OP_LITERAL(2));
|
||||
/* This obscures whose key is whose. Probably unnecessary? */
|
||||
if (key_less(mykey, theirkey)) {
|
||||
add_push_bytes(&script, mykey->key.data, mykey->key.len);
|
||||
add_push_bytes(&script, theirkey->key.data, theirkey->key.len);
|
||||
} else {
|
||||
add_push_bytes(&script, theirkey->key.data, theirkey->key.len);
|
||||
add_push_bytes(&script, mykey->key.data, mykey->key.len);
|
||||
}
|
||||
add_op(&script, OP_LITERAL(2));
|
||||
add_op(&script, OP_CHECKMULTISIG);
|
||||
add_op(&script, OP_ENDIF);
|
||||
|
||||
/* Not two args? Must be us using timeout. */
|
||||
add_op(&script, OP_ELSE);
|
||||
add_push_bytes(&script, &locktime_le, sizeof(locktime_le));
|
||||
add_op(&script, OP_CHECKSEQUENCEVERIFY);
|
||||
add_push_bytes(&script, mykey->key.data, mykey->key.len);
|
||||
add_op(&script, OP_CHECKSIG);
|
||||
add_op(&script, OP_ENDIF);
|
||||
|
||||
return script;
|
||||
}
|
||||
|
@ -15,6 +15,16 @@ u8 *bitcoin_redeem_2of2(const tal_t *ctx,
|
||||
/* tal_count() gives the length of the script. */
|
||||
u8 *bitcoin_redeem_single(const tal_t *ctx, const u8 *key, size_t keylen);
|
||||
|
||||
/* One of:
|
||||
* mysig and theirsig, OR
|
||||
* mysig and relative locktime passed, OR
|
||||
* theirsig and hash preimage. */
|
||||
u8 *bitcoin_redeem_revocable(const tal_t *ctx,
|
||||
const BitcoinPubkey *mykey,
|
||||
u32 locktime,
|
||||
const BitcoinPubkey *theirkey,
|
||||
const Sha256Hash *revocation_hash);
|
||||
|
||||
/* Create an output script using p2sh for this redeem script. */
|
||||
u8 *scriptpubkey_p2sh(const tal_t *ctx, const u8 *redeemscript);
|
||||
|
||||
|
@ -1579,12 +1579,12 @@ const ProtobufCMessageDescriptor open_anchor_sig__descriptor =
|
||||
static const ProtobufCFieldDescriptor leak_anchor_sigs_and_pretend_we_didnt__field_descriptors[1] =
|
||||
{
|
||||
{
|
||||
"anchor_scriptsigs",
|
||||
"sigs",
|
||||
1,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(LeakAnchorSigsAndPretendWeDidnt, anchor_scriptsigs),
|
||||
offsetof(LeakAnchorSigsAndPretendWeDidnt, sigs),
|
||||
&open_anchor_sig__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
@ -1592,7 +1592,7 @@ static const ProtobufCFieldDescriptor leak_anchor_sigs_and_pretend_we_didnt__fie
|
||||
},
|
||||
};
|
||||
static const unsigned leak_anchor_sigs_and_pretend_we_didnt__field_indices_by_name[] = {
|
||||
0, /* field[0] = anchor_scriptsigs */
|
||||
0, /* field[0] = sigs */
|
||||
};
|
||||
static const ProtobufCIntRange leak_anchor_sigs_and_pretend_we_didnt__number_ranges[1 + 1] =
|
||||
{
|
||||
|
@ -248,7 +248,7 @@ struct _OpenAnchorSig
|
||||
struct _LeakAnchorSigsAndPretendWeDidnt
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
OpenAnchorSig *anchor_scriptsigs;
|
||||
OpenAnchorSig *sigs;
|
||||
};
|
||||
#define LEAK_ANCHOR_SIGS_AND_PRETEND_WE_DIDNT__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&leak_anchor_sigs_and_pretend_we_didnt__descriptor) \
|
||||
|
@ -99,7 +99,7 @@ message open_anchor_sig {
|
||||
// malleability anyway). So for testing, we send the scriptsigs for the
|
||||
// anchor transaction's inputs immediately.
|
||||
message leak_anchor_sigs_and_pretend_we_didnt {
|
||||
required open_anchor_sig anchor_scriptsigs = 1;
|
||||
required open_anchor_sig sigs = 1;
|
||||
}
|
||||
|
||||
// Indicates we've seen transaction reach min-depth.
|
||||
|
@ -18,33 +18,19 @@
|
||||
#include <unistd.h>
|
||||
|
||||
/* All the input scripts are already set to 0. We just need to make this one. */
|
||||
static u8 *sign_tx_input(const tal_t *ctx,
|
||||
struct bitcoin_tx *tx,
|
||||
unsigned int i,
|
||||
const BitcoinInput *input,
|
||||
EC_KEY *privkey,
|
||||
const struct bitcoin_compressed_pubkey *pubkey)
|
||||
static u8 *tx_scriptsig(const tal_t *ctx,
|
||||
struct bitcoin_tx *tx,
|
||||
unsigned int i,
|
||||
const BitcoinInput *input,
|
||||
EC_KEY *privkey,
|
||||
const struct bitcoin_compressed_pubkey *pubkey)
|
||||
{
|
||||
struct sha256_double hash;
|
||||
struct sha256_ctx shactx;
|
||||
struct bitcoin_address addr;
|
||||
u8 *sig;
|
||||
struct bitcoin_address addr;
|
||||
|
||||
/* Transaction gets signed as if the output subscript is the
|
||||
* only input script. */
|
||||
tx->input[i].script_length = input->subscript.len;
|
||||
tx->input[i].script = input->subscript.data;
|
||||
|
||||
sha256_init(&shactx);
|
||||
sha256_tx(&shactx, tx);
|
||||
sha256_le32(&shactx, SIGHASH_ALL);
|
||||
sha256_double_done(&shactx, &hash);
|
||||
|
||||
/* Reset it for next time. */
|
||||
tx->input[i].script_length = 0;
|
||||
tx->input[i].script = NULL;
|
||||
|
||||
sig = sign_hash(ctx, privkey, &hash);
|
||||
sig = sign_tx_input(ctx, tx, i,
|
||||
input->subscript.data, input->subscript.len,
|
||||
privkey);
|
||||
if (!sig)
|
||||
return NULL;
|
||||
|
||||
@ -102,9 +88,9 @@ int main(int argc, char *argv[])
|
||||
if (!testnet)
|
||||
errx(1, "Private key '%s' not on testnet!", argv[3+i]);
|
||||
|
||||
sigs[i] = sign_tx_input(sigs, anchor, map[i],
|
||||
o1->anchor->inputs[i],
|
||||
privkey, &pubkey);
|
||||
sigs[i] = tx_scriptsig(sigs, anchor, map[i],
|
||||
o1->anchor->inputs[i],
|
||||
privkey, &pubkey);
|
||||
}
|
||||
|
||||
pkt = open_anchor_sig_pkt(ctx, sigs, o1->anchor->n_inputs);
|
||||
|
108
open-commit-sig.c
Normal file
108
open-commit-sig.c
Normal file
@ -0,0 +1,108 @@
|
||||
/* My example:
|
||||
* ./open-commit-sig A-open.pb B-open.pb cUBCjrdJu8tfvM7FT8So6aqs6G6bZS1Cax6Rc9rFzYL6nYG4XNEC A-leak-anchor-sigs.pb B-leak-anchor-sigs.pb > A-commit-sig.pb
|
||||
* ./open-commit-sig B-open.pb A-open.pb cQXhbUnNRsFcdzTQwjbCrud5yVskHTEas7tZPUWoJYNk5htGQrpi B-leak-anchor-sigs.pb A-leak-anchor-sigs.pb > B-commit-sig.pb
|
||||
*/
|
||||
#include <ccan/crypto/shachain/shachain.h>
|
||||
#include <ccan/short_types/short_types.h>
|
||||
#include <ccan/tal/tal.h>
|
||||
#include <ccan/opt/opt.h>
|
||||
#include <ccan/str/hex/hex.h>
|
||||
#include <ccan/err/err.h>
|
||||
#include <ccan/read_write_all/read_write_all.h>
|
||||
#include "lightning.pb-c.h"
|
||||
#include "anchor.h"
|
||||
#include "base58.h"
|
||||
#include "pkt.h"
|
||||
#include "bitcoin_script.h"
|
||||
#include "permute_tx.h"
|
||||
#include "signature.h"
|
||||
#include <openssl/ec.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const tal_t *ctx = tal_arr(NULL, char, 0);
|
||||
OpenChannel *o1, *o2;
|
||||
struct bitcoin_tx *anchor, *commit;
|
||||
struct sha256_double txid;
|
||||
struct pkt *pkt;
|
||||
u8 *redeemscript, *sig;
|
||||
size_t *inmap, *outmap;
|
||||
EC_KEY *privkey;
|
||||
bool testnet;
|
||||
struct bitcoin_compressed_pubkey pubkey;
|
||||
|
||||
err_set_progname(argv[0]);
|
||||
|
||||
opt_register_noarg("--help|-h", opt_usage_and_exit,
|
||||
"<open-channel-file1> <open-channel-file2> <commit-privkey> <leak-anchor-sigs1> <leak-anchor-sigs2>\n"
|
||||
"Create the signature needed for the commit transaction",
|
||||
"Print this message.");
|
||||
|
||||
opt_parse(&argc, argv, opt_log_stderr_exit);
|
||||
|
||||
if (argc != 6)
|
||||
opt_usage_and_exit(NULL);
|
||||
|
||||
o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open;
|
||||
o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open;
|
||||
|
||||
privkey = key_from_base58(argv[3], strlen(argv[3]), &testnet, &pubkey);
|
||||
if (!privkey)
|
||||
errx(1, "Invalid private key '%s'", argv[3]);
|
||||
if (!testnet)
|
||||
errx(1, "Private key '%s' not on testnet!", argv[3]);
|
||||
|
||||
/* Create merged anchor transaction */
|
||||
anchor = anchor_tx_create(ctx, o1, o2, &inmap, &outmap);
|
||||
if (!anchor)
|
||||
errx(1, "Failed transaction merge");
|
||||
|
||||
/* Get the transaction ID of the anchor. */
|
||||
anchor_txid(anchor, argv[4], argv[5], inmap, &txid);
|
||||
|
||||
/* Now create commitment tx: one input, two outputs. */
|
||||
commit = bitcoin_tx(ctx, 1, 2);
|
||||
|
||||
/* Our input spends the anchor tx output. */
|
||||
commit->input[0].txid = txid;
|
||||
commit->input[0].index = outmap[0];
|
||||
|
||||
/* First output is a P2SH to a complex redeem script */
|
||||
redeemscript = bitcoin_redeem_revocable(ctx, o1->anchor->pubkey,
|
||||
o1->locktime_seconds,
|
||||
o2->anchor->pubkey,
|
||||
o1->revocation_hash);
|
||||
commit->output[0].script = scriptpubkey_p2sh(ctx, redeemscript);
|
||||
commit->output[0].script_length = tal_count(commit->output[0].script);
|
||||
|
||||
if (o1->anchor->total < o1->commitment_fee)
|
||||
errx(1, "Our contribution to channel %llu < fee %llu",
|
||||
(long long)o1->anchor->total,
|
||||
(long long)o1->commitment_fee);
|
||||
commit->output[0].amount = o1->anchor->total - o1->commitment_fee;
|
||||
|
||||
/* Second output is a simple payment to them. */
|
||||
commit->output[1].script = o2->script_to_me.data;
|
||||
commit->output[1].script_length = o2->script_to_me.len;
|
||||
|
||||
if (o2->anchor->total < o2->commitment_fee)
|
||||
errx(1, "Their contribution to channel %llu < fee %llu",
|
||||
(long long)o2->anchor->total,
|
||||
(long long)o2->commitment_fee);
|
||||
commit->output[1].amount = o2->anchor->total - o2->commitment_fee;
|
||||
|
||||
permute_outputs(o1->seed, o2->seed, 1, commit->output, 2, NULL);
|
||||
|
||||
sig = sign_tx_input(ctx, commit, 0, anchor->output[outmap[0]].script,
|
||||
anchor->output[outmap[0]].script_length, privkey);
|
||||
|
||||
pkt = open_commit_sig_pkt(ctx, sig, tal_count(sig));
|
||||
if (!write_all(STDOUT_FILENO, pkt,
|
||||
sizeof(pkt->len) + le32_to_cpu(pkt->len)))
|
||||
err(1, "Writing out packet");
|
||||
|
||||
tal_free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
15
pkt.c
15
pkt.c
@ -1,6 +1,7 @@
|
||||
#include <ccan/crypto/sha256/sha256.h>
|
||||
#include <ccan/tal/grab_file/grab_file.h>
|
||||
#include <ccan/err/err.h>
|
||||
#include <ccan/cast/cast.h>
|
||||
#include "pkt.h"
|
||||
#include "bitcoin_tx.h"
|
||||
#include "bitcoin_address.h"
|
||||
@ -137,6 +138,18 @@ struct pkt *leak_anchor_sigs_and_pretend_we_didnt_pkt(const tal_t *ctx,
|
||||
LeakAnchorSigsAndPretendWeDidnt omg_fail
|
||||
= LEAK_ANCHOR_SIGS_AND_PRETEND_WE_DIDNT__INIT;
|
||||
|
||||
omg_fail.anchor_scriptsigs = s;
|
||||
omg_fail.sigs = s;
|
||||
return to_pkt(ctx, PKT__PKT_OMG_FAIL, &omg_fail);
|
||||
}
|
||||
|
||||
struct pkt *open_commit_sig_pkt(const tal_t *ctx, const u8 *sig, size_t siglen)
|
||||
{
|
||||
OpenCommitSig o = OPEN_COMMIT_SIG__INIT;
|
||||
BitcoinSignature s = BITCOIN_SIGNATURE__INIT;
|
||||
|
||||
o.sig = &s;
|
||||
s.der_then_sigtype.len = siglen;
|
||||
s.der_then_sigtype.data = cast_const(u8 *, sig);
|
||||
|
||||
return to_pkt(ctx, PKT__PKT_OPEN_COMMIT_SIG, &o);
|
||||
}
|
||||
|
8
pkt.h
8
pkt.h
@ -58,6 +58,14 @@ struct pkt *leak_anchor_sigs_and_pretend_we_didnt_pkt(const tal_t *ctx,
|
||||
OpenAnchorSig *s);
|
||||
|
||||
|
||||
/**
|
||||
* open_commit_sig_pkt - create an open_commit_sig message
|
||||
* @ctx: tal context to allocate off.
|
||||
* @sig: the der-encoded signature for the commit transaction input.
|
||||
* @siglen: the length of @sig.
|
||||
*/
|
||||
struct pkt *open_commit_sig_pkt(const tal_t *ctx, const u8 *sig, size_t siglen);
|
||||
|
||||
/* Useful helper for allocating & populating a protobuf Sha256Hash */
|
||||
Sha256Hash *sha256_to_proto(const tal_t *ctx, const struct sha256 *hash);
|
||||
void proto_to_sha256(const Sha256Hash *pb, struct sha256 *hash);
|
||||
|
25
signature.c
25
signature.c
@ -1,8 +1,10 @@
|
||||
#include "signature.h"
|
||||
#include "shadouble.h"
|
||||
#include "bitcoin_tx.h"
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/obj_mac.h>
|
||||
#include <assert.h>
|
||||
#include <ccan/cast/cast.h>
|
||||
|
||||
u8 *sign_hash(const tal_t *ctx, EC_KEY *private_key,
|
||||
const struct sha256_double *h)
|
||||
@ -43,3 +45,26 @@ u8 *sign_hash(const tal_t *ctx, EC_KEY *private_key,
|
||||
OPENSSL_free(der);
|
||||
return ret;
|
||||
}
|
||||
|
||||
u8 *sign_tx_input(const tal_t *ctx, struct bitcoin_tx *tx, unsigned int in,
|
||||
const u8 *subscript, size_t subscript_len, EC_KEY *privkey)
|
||||
{
|
||||
struct sha256_double hash;
|
||||
struct sha256_ctx shactx;
|
||||
|
||||
/* Transaction gets signed as if the output subscript is the
|
||||
* only input script. */
|
||||
tx->input[in].script_length = subscript_len;
|
||||
tx->input[in].script = cast_const(u8 *, subscript);
|
||||
|
||||
sha256_init(&shactx);
|
||||
sha256_tx(&shactx, tx);
|
||||
sha256_le32(&shactx, SIGHASH_ALL);
|
||||
sha256_double_done(&shactx, &hash);
|
||||
|
||||
/* Reset it for next time. */
|
||||
tx->input[in].script_length = 0;
|
||||
tx->input[in].script = NULL;
|
||||
|
||||
return sign_hash(ctx, privkey, &hash);
|
||||
}
|
||||
|
@ -12,8 +12,13 @@ enum sighash_type {
|
||||
};
|
||||
|
||||
struct sha256_double;
|
||||
struct bitcoin_tx;
|
||||
|
||||
u8 *sign_hash(const tal_t *ctx, EC_KEY *private_key,
|
||||
const struct sha256_double *h);
|
||||
|
||||
/* All tx input scripts must be set to 0 len. */
|
||||
u8 *sign_tx_input(const tal_t *ctx, struct bitcoin_tx *tx, unsigned int in,
|
||||
const u8 *subscript, size_t subscript_len, EC_KEY *privkey);
|
||||
|
||||
#endif /* LIGHTNING_SIGNATURE_H */
|
||||
|
Loading…
Reference in New Issue
Block a user