mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
tx: prepare for Elements Alpha.
They sign, hash, and serialize differently. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
27e7c7b986
commit
20624c049f
5
Makefile
5
Makefile
@ -3,6 +3,9 @@
|
||||
# Needs to have oneof support: Ubuntu vivid's is too old :(
|
||||
PROTOCC:=protoc-c
|
||||
|
||||
# Alpha has segregated witness, checksequenceverify
|
||||
#FEATURES := -DHAS_CSV=1 -DALPHA_TXSTYLE=1
|
||||
|
||||
PROGRAMS := test-cli/open-channel test-cli/open-anchor-scriptsigs test-cli/leak-anchor-sigs test-cli/open-commit-sig test-cli/check-commit-sig test-cli/check-anchor-scriptsigs test-cli/get-anchor-depth test-cli/create-steal-tx test-cli/create-commit-spend-tx test-cli/close-channel test-cli/create-close-tx test-cli/update-channel test-cli/update-channel-accept test-cli/update-channel-signature test-cli/update-channel-complete test-cli/create-commit-tx
|
||||
|
||||
BITCOIN_OBJS := bitcoin/address.o bitcoin/base58.o bitcoin/pubkey.o bitcoin/script.o bitcoin/shadouble.o bitcoin/signature.o bitcoin/tx.o
|
||||
@ -14,7 +17,7 @@ CCAN_OBJS := ccan-crypto-sha256.o ccan-crypto-shachain.o ccan-err.o ccan-tal.o c
|
||||
HEADERS := $(wildcard *.h)
|
||||
|
||||
CCANDIR := ccan/
|
||||
CFLAGS := -g -Wall -I $(CCANDIR) -DVALGRIND_HEADERS=1
|
||||
CFLAGS := -g -Wall -I $(CCANDIR) -DVALGRIND_HEADERS=1 $(FEATURES)
|
||||
LDLIBS := -lcrypto -lprotobuf-c
|
||||
$(PROGRAMS): CFLAGS+=-I.
|
||||
|
||||
|
26
anchor.c
26
anchor.c
@ -18,6 +18,7 @@ struct bitcoin_tx *anchor_tx_create(const tal_t *ctx,
|
||||
u8 *redeemscript;
|
||||
size_t *inmap, *outmap;
|
||||
struct pubkey key1, key2;
|
||||
uint64_t total_in = 0, total_change = 0;
|
||||
|
||||
if (add_overflows_size_t(o1->anchor->n_inputs, o2->anchor->n_inputs))
|
||||
return NULL;
|
||||
@ -37,6 +38,10 @@ struct bitcoin_tx *anchor_tx_create(const tal_t *ctx,
|
||||
struct bitcoin_tx_input *in = &tx->input[i];
|
||||
proto_to_sha256(pb->txid, &in->txid.sha);
|
||||
in->index = pb->output;
|
||||
in->input_amount = pb->amount;
|
||||
if (add_overflows_u64(total_in, in->input_amount))
|
||||
return tal_free(tx);
|
||||
total_in += in->input_amount;
|
||||
/* Leave inputs as stubs for now, for signing. */
|
||||
}
|
||||
for (i = 0; i < o2->anchor->n_inputs; i++) {
|
||||
@ -45,6 +50,10 @@ struct bitcoin_tx *anchor_tx_create(const tal_t *ctx,
|
||||
= &tx->input[o1->anchor->n_inputs + i];
|
||||
proto_to_sha256(pb->txid, &in->txid.sha);
|
||||
in->index = pb->output;
|
||||
in->input_amount = pb->amount;
|
||||
if (add_overflows_u64(total_in, in->input_amount))
|
||||
return tal_free(tx);
|
||||
total_in += in->input_amount;
|
||||
/* Leave inputs as stubs for now, for signing. */
|
||||
}
|
||||
|
||||
@ -76,6 +85,7 @@ struct bitcoin_tx *anchor_tx_create(const tal_t *ctx,
|
||||
out->script = scriptpubkey_p2sh(tx,
|
||||
bitcoin_redeem_single(tx, &key));
|
||||
out->script_length = tal_count(out->script);
|
||||
total_change += out->amount;
|
||||
}
|
||||
if (o2->anchor->change) {
|
||||
struct bitcoin_tx_output *out = &tx->output[n_out++];
|
||||
@ -88,9 +98,25 @@ struct bitcoin_tx *anchor_tx_create(const tal_t *ctx,
|
||||
out->script = scriptpubkey_p2sh(tx,
|
||||
bitcoin_redeem_single(tx, &key));
|
||||
out->script_length = tal_count(out->script);
|
||||
if (add_overflows_u64(total_change, out->amount))
|
||||
return tal_free(tx);
|
||||
total_change += out->amount;
|
||||
}
|
||||
assert(n_out == tx->output_count);
|
||||
|
||||
/* Figure out fee we're paying; check for over and underflow */
|
||||
if (add_overflows_u64(total_change, tx->output[0].amount))
|
||||
return tal_free(tx);
|
||||
if (total_in < total_change + tx->output[0].amount)
|
||||
return tal_free(tx);
|
||||
tx->fee = total_in - (total_change + tx->output[0].amount);
|
||||
|
||||
/* Check that the fees add up correctly. */
|
||||
if (add_overflows_u64(o1->anchor->fee, o2->anchor->fee))
|
||||
return tal_free(tx);
|
||||
if (tx->fee != o1->anchor->fee + o2->anchor->fee)
|
||||
return tal_free(tx);
|
||||
|
||||
if (inmapp)
|
||||
inmap = *inmapp = tal_arr(ctx, size_t, tx->input_count);
|
||||
else
|
||||
|
@ -125,8 +125,9 @@ static void sha256_tx_one_input(struct bitcoin_tx *tx,
|
||||
tx->input[input_num].script = cast_const(u8 *, script);
|
||||
|
||||
sha256_init(&ctx);
|
||||
sha256_tx(&ctx, tx);
|
||||
sha256_tx_for_sig(&ctx, tx);
|
||||
sha256_le32(&ctx, SIGHASH_ALL);
|
||||
|
||||
sha256_double_done(&ctx, hash);
|
||||
|
||||
/* Reset it for next time. */
|
||||
|
195
bitcoin/tx.c
195
bitcoin/tx.c
@ -7,8 +7,50 @@
|
||||
#include "tx.h"
|
||||
#include "valgrind.h"
|
||||
|
||||
enum styles {
|
||||
/* Add the CT padding stuff to amount. */
|
||||
TX_AMOUNT_CT_STYLE = 1,
|
||||
/* Whether to process CT rangeproof and noncecommitment. */
|
||||
TX_AMOUNT_INCLUDE_CT = 2,
|
||||
/* Process the txfee field. */
|
||||
TX_FEE = 4,
|
||||
/* Process the input script sig. */
|
||||
TX_INPUT_SCRIPTSIG = 8,
|
||||
/* Process the amounts for each input. */
|
||||
TX_INPUT_AMOUNT = 16,
|
||||
/* Process hash of rangeproof and noncecommitment in *output* amount,
|
||||
* instead of rangeproof and noncecommitment themselves. */
|
||||
TX_OUTPUT_AMOUNT_HASHPROOF = 32
|
||||
};
|
||||
|
||||
#ifdef ALPHA_TXSTYLE
|
||||
/* Linearizing has everything, except input amount (which is implied) */
|
||||
#define LINEARIZE_STYLE (TX_AMOUNT_CT_STYLE | TX_AMOUNT_INCLUDE_CT | TX_FEE | TX_INPUT_SCRIPTSIG)
|
||||
|
||||
/* Alpha txids don't include input scripts, or rangeproof/txcommit in output */
|
||||
#define TXID_STYLE (TX_AMOUNT_CT_STYLE | TX_FEE)
|
||||
|
||||
/* Alpha signatures sign the input script (assuming others are set to
|
||||
* 0-len), as well as the input fee.
|
||||
|
||||
* They sign a hash of the rangeproof and noncecommitment for inputs,
|
||||
* rather than the non rangeproof and noncecommitment themselves.
|
||||
*
|
||||
* For some reason they skip the txfee. */
|
||||
#define SIG_STYLE (TX_AMOUNT_CT_STYLE | TX_AMOUNT_INCLUDE_CT | TX_INPUT_SCRIPTSIG | TX_INPUT_AMOUNT | TX_OUTPUT_AMOUNT_HASHPROOF)
|
||||
|
||||
#else /* BITCOIN */
|
||||
|
||||
/* Process all the bitcoin fields. Works for txid, serialization and signing */
|
||||
#define LINEARIZE_STYLE (TX_INPUT_SCRIPTSIG)
|
||||
#define TXID_STYLE (TX_INPUT_SCRIPTSIG)
|
||||
#define SIG_STYLE (TX_INPUT_SCRIPTSIG)
|
||||
|
||||
#endif
|
||||
|
||||
static void add_varint(varint_t v,
|
||||
void (*add)(const void *, size_t, void *), void *addp)
|
||||
void (*add)(const void *, size_t, void *), void *addp,
|
||||
enum styles style)
|
||||
{
|
||||
u8 buf[9], *p = buf;
|
||||
|
||||
@ -39,50 +81,109 @@ static void add_varint(varint_t v,
|
||||
}
|
||||
|
||||
static void add_le32(u32 v,
|
||||
void (*add)(const void *, size_t, void *), void *addp)
|
||||
void (*add)(const void *, size_t, void *), void *addp,
|
||||
enum styles style)
|
||||
{
|
||||
le32 l = cpu_to_le32(v);
|
||||
add(&l, sizeof(l), addp);
|
||||
}
|
||||
|
||||
static void add_le64(u64 v,
|
||||
void (*add)(const void *, size_t, void *), void *addp)
|
||||
void (*add)(const void *, size_t, void *), void *addp,
|
||||
enum styles style)
|
||||
{
|
||||
le64 l = cpu_to_le64(v);
|
||||
add(&l, sizeof(l), addp);
|
||||
}
|
||||
|
||||
static void add_value(u64 amount,
|
||||
void (*add)(const void *, size_t, void *),
|
||||
void *addp,
|
||||
bool output,
|
||||
enum styles style)
|
||||
{
|
||||
if (style & TX_AMOUNT_CT_STYLE) {
|
||||
/* The input is hashed as a 33 byte value (for CT); 25 0, then
|
||||
* the big-endian value. */
|
||||
static u8 zeroes[25];
|
||||
be64 b = cpu_to_be64(amount);
|
||||
add(zeroes, sizeof(zeroes), addp);
|
||||
add(&b, sizeof(b), addp);
|
||||
if (style & TX_AMOUNT_INCLUDE_CT) {
|
||||
/* Two more zeroes: Rangeproof and Noncecommitment */
|
||||
if (output && (style & TX_OUTPUT_AMOUNT_HASHPROOF)) {
|
||||
struct sha256_double h;
|
||||
sha256_double(&h, zeroes, 2);
|
||||
add(&h, sizeof(h), addp);
|
||||
} else {
|
||||
add_varint(0, add, addp, style);
|
||||
add_varint(0, add, addp, style);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
add_le64(amount, add, addp, style);
|
||||
}
|
||||
}
|
||||
|
||||
static void add_input_value(u64 amount,
|
||||
void (*add)(const void *, size_t, void *),
|
||||
void *addp,
|
||||
enum styles style)
|
||||
{
|
||||
return add_value(amount, add, addp, false, style);
|
||||
}
|
||||
|
||||
static void add_output_value(u64 amount,
|
||||
void (*add)(const void *, size_t, void *),
|
||||
void *addp,
|
||||
enum styles style)
|
||||
{
|
||||
return add_value(amount, add, addp, true, style);
|
||||
}
|
||||
|
||||
static void add_tx_input(const struct bitcoin_tx_input *input,
|
||||
void (*add)(const void *, size_t, void *), void *addp)
|
||||
void (*add)(const void *, size_t, void *), void *addp,
|
||||
enum styles style)
|
||||
{
|
||||
add(&input->txid, sizeof(input->txid), addp);
|
||||
add_le32(input->index, add, addp);
|
||||
add_varint(input->script_length, add, addp);
|
||||
add_le32(input->index, add, addp, style);
|
||||
if (style & TX_INPUT_AMOUNT) {
|
||||
add_input_value(input->input_amount, add, addp, style);
|
||||
}
|
||||
if (style & TX_INPUT_SCRIPTSIG) {
|
||||
add_varint(input->script_length, add, addp, style);
|
||||
add(input->script, input->script_length, addp);
|
||||
add_le32(input->sequence_number, add, addp);
|
||||
}
|
||||
add_le32(input->sequence_number, add, addp, style);
|
||||
}
|
||||
|
||||
static void add_tx_output(const struct bitcoin_tx_output *output,
|
||||
void (*add)(const void *, size_t, void *), void *addp)
|
||||
void (*add)(const void *, size_t, void *), void *addp,
|
||||
enum styles style)
|
||||
{
|
||||
add_le64(output->amount, add, addp);
|
||||
add_varint(output->script_length, add, addp);
|
||||
add_output_value(output->amount, add, addp, style);
|
||||
add_varint(output->script_length, add, addp, style);
|
||||
add(output->script, output->script_length, addp);
|
||||
}
|
||||
|
||||
static void add_tx(const struct bitcoin_tx *tx,
|
||||
void (*add)(const void *, size_t, void *), void *addp)
|
||||
void (*add)(const void *, size_t, void *), void *addp,
|
||||
enum styles style)
|
||||
{
|
||||
varint_t i;
|
||||
|
||||
add_le32(tx->version, add, addp);
|
||||
add_varint(tx->input_count, add, addp);
|
||||
add_le32(tx->version, add, addp, style);
|
||||
add_varint(tx->input_count, add, addp, style);
|
||||
for (i = 0; i < tx->input_count; i++)
|
||||
add_tx_input(&tx->input[i], add, addp);
|
||||
add_varint(tx->output_count, add, addp);
|
||||
add_tx_input(&tx->input[i], add, addp, style);
|
||||
|
||||
if (style & TX_FEE)
|
||||
add_le64(tx->fee, add, addp, style);
|
||||
|
||||
add_varint(tx->output_count, add, addp, style);
|
||||
for (i = 0; i < tx->output_count; i++)
|
||||
add_tx_output(&tx->output[i], add, addp);
|
||||
add_le32(tx->lock_time, add, addp);
|
||||
add_tx_output(&tx->output[i], add, addp, style);
|
||||
add_le32(tx->lock_time, add, addp, style);
|
||||
}
|
||||
|
||||
static void add_sha(const void *data, size_t len, void *shactx_)
|
||||
@ -91,9 +192,9 @@ static void add_sha(const void *data, size_t len, void *shactx_)
|
||||
sha256_update(ctx, check_mem(data, len), len);
|
||||
}
|
||||
|
||||
void sha256_tx(struct sha256_ctx *ctx, const struct bitcoin_tx *tx)
|
||||
void sha256_tx_for_sig(struct sha256_ctx *ctx, const struct bitcoin_tx *tx)
|
||||
{
|
||||
add_tx(tx, add_sha, ctx);
|
||||
add_tx(tx, add_sha, ctx, SIG_STYLE);
|
||||
}
|
||||
|
||||
static void add_linearize(const void *data, size_t len, void *pptr_)
|
||||
@ -108,7 +209,7 @@ static void add_linearize(const void *data, size_t len, void *pptr_)
|
||||
u8 *linearize_tx(const tal_t *ctx, const struct bitcoin_tx *tx)
|
||||
{
|
||||
u8 *arr = tal_arr(ctx, u8, 0);
|
||||
add_tx(tx, add_linearize, &arr);
|
||||
add_tx(tx, add_linearize, &arr, LINEARIZE_STYLE);
|
||||
return arr;
|
||||
}
|
||||
|
||||
@ -116,7 +217,7 @@ void bitcoin_txid(const struct bitcoin_tx *tx, struct sha256_double *txid)
|
||||
{
|
||||
struct sha256_ctx ctx = SHA256_INIT;
|
||||
|
||||
sha256_tx(&ctx, tx);
|
||||
add_tx(tx, add_sha, &ctx, TXID_STYLE);
|
||||
sha256_double_done(&ctx, txid);
|
||||
}
|
||||
|
||||
@ -219,21 +320,67 @@ static bool pull_sha256_double(const u8 **cursor, size_t *max,
|
||||
return pull(cursor, max, h, sizeof(*h));
|
||||
}
|
||||
|
||||
static u64 pull_value(const u8 **cursor, size_t *max)
|
||||
{
|
||||
u64 amount;
|
||||
|
||||
if (LINEARIZE_STYLE & TX_AMOUNT_CT_STYLE) {
|
||||
/* The input is hashed as a 33 byte value (for CT); 25 0, then
|
||||
* the big-endian value. */
|
||||
u8 zeroes[25];
|
||||
be64 b;
|
||||
|
||||
if (!pull(cursor, max, zeroes, sizeof(zeroes)))
|
||||
return 0;
|
||||
|
||||
/* We don't handle CT amounts. */
|
||||
if (zeroes[0] != 0)
|
||||
goto fail;
|
||||
|
||||
if (!pull(cursor, max, &b, sizeof(b)))
|
||||
return 0;
|
||||
|
||||
amount = be64_to_cpu(b);
|
||||
if (LINEARIZE_STYLE & TX_AMOUNT_INCLUDE_CT) {
|
||||
varint_t rp, nc;
|
||||
|
||||
rp = pull_varint(cursor, max);
|
||||
nc = pull_varint(cursor, max);
|
||||
if (rp != 0 || nc != 0)
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
amount = pull_le64(cursor, max);
|
||||
}
|
||||
return amount;
|
||||
|
||||
fail:
|
||||
/* Simulate EOF */
|
||||
*cursor = NULL;
|
||||
*max = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pull_input(const tal_t *ctx, const u8 **cursor, size_t *max,
|
||||
struct bitcoin_tx_input *input)
|
||||
{
|
||||
pull_sha256_double(cursor, max, &input->txid);
|
||||
input->index = pull_le32(cursor, max);
|
||||
if (LINEARIZE_STYLE & TX_INPUT_AMOUNT) {
|
||||
input->input_amount = pull_value(cursor, max);
|
||||
}
|
||||
if (LINEARIZE_STYLE & TX_INPUT_SCRIPTSIG) {
|
||||
input->script_length = pull_varint(cursor, max);
|
||||
input->script = tal_arr(ctx, u8, input->script_length);
|
||||
pull(cursor, max, input->script, input->script_length);
|
||||
}
|
||||
input->sequence_number = pull_le32(cursor, max);
|
||||
}
|
||||
|
||||
static void pull_output(const tal_t *ctx, const u8 **cursor, size_t *max,
|
||||
struct bitcoin_tx_output *output)
|
||||
{
|
||||
output->amount = pull_le64(cursor, max);
|
||||
output->amount = pull_value(cursor, max);
|
||||
output->script_length = pull_varint(cursor, max);
|
||||
output->script = tal_arr(ctx, u8, output->script_length);
|
||||
pull(cursor, max, output->script, output->script_length);
|
||||
@ -250,6 +397,10 @@ static struct bitcoin_tx *pull_bitcoin_tx(const tal_t *ctx,
|
||||
tx->input = tal_arr(tx, struct bitcoin_tx_input, tx->input_count);
|
||||
for (i = 0; i < tx->input_count; i++)
|
||||
pull_input(tx, cursor, max, tx->input + i);
|
||||
|
||||
if (LINEARIZE_STYLE & TX_FEE)
|
||||
tx->fee = pull_le64(cursor, max);
|
||||
|
||||
tx->output_count = pull_varint(cursor, max);
|
||||
tx->output = tal_arr(ctx, struct bitcoin_tx_output, tx->output_count);
|
||||
for (i = 0; i < tx->output_count; i++)
|
||||
|
@ -13,6 +13,10 @@ struct bitcoin_tx {
|
||||
u32 version;
|
||||
varint_t input_count;
|
||||
struct bitcoin_tx_input *input;
|
||||
|
||||
/* Only in alpha. */
|
||||
u64 fee;
|
||||
|
||||
varint_t output_count;
|
||||
struct bitcoin_tx_output *output;
|
||||
u32 lock_time;
|
||||
@ -25,6 +29,9 @@ struct bitcoin_tx_output {
|
||||
};
|
||||
|
||||
struct bitcoin_tx_input {
|
||||
/* In alpha, this is hashed for signature */
|
||||
u64 input_amount;
|
||||
|
||||
struct sha256_double txid;
|
||||
u32 index; /* output number referred to by above */
|
||||
varint_t script_length;
|
||||
@ -37,7 +44,7 @@ struct bitcoin_tx_input {
|
||||
void bitcoin_txid(const struct bitcoin_tx *tx, struct sha256_double *txid);
|
||||
|
||||
/* Useful for signature code. */
|
||||
void sha256_tx(struct sha256_ctx *ctx, const struct bitcoin_tx *tx);
|
||||
void sha256_tx_for_sig(struct sha256_ctx *ctx, const struct bitcoin_tx *tx);
|
||||
|
||||
/* Linear bytes of tx. */
|
||||
u8 *linearize_tx(const tal_t *ctx, const struct bitcoin_tx *tx);
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "bitcoin/shadouble.h"
|
||||
#include "bitcoin/tx.h"
|
||||
#include "commit_tx.h"
|
||||
#include "overflows.h"
|
||||
#include "permute_tx.h"
|
||||
#include "pkt.h"
|
||||
#include "protobuf_convert.h"
|
||||
@ -26,6 +27,9 @@ struct bitcoin_tx *create_commit_tx(const tal_t *ctx,
|
||||
/* Our input spends the anchor tx output. */
|
||||
tx->input[0].txid = *anchor_txid;
|
||||
tx->input[0].index = anchor_output;
|
||||
if (add_overflows_u64(ours->anchor->total, theirs->anchor->total))
|
||||
return tal_free(tx);
|
||||
tx->input[0].input_amount = ours->anchor->total + theirs->anchor->total;
|
||||
|
||||
/* Output goes to our final pubkeys */
|
||||
if (!proto_to_pubkey(ours->final, &ourkey))
|
||||
@ -68,6 +72,10 @@ struct bitcoin_tx *create_commit_tx(const tal_t *ctx,
|
||||
return tal_free(tx);
|
||||
tx->output[0].amount -= delta;
|
||||
|
||||
/* Calculate fee; difference of inputs and outputs. */
|
||||
tx->fee = tx->input[0].input_amount
|
||||
- (tx->output[0].amount + tx->output[1].amount);
|
||||
|
||||
permute_outputs(ours->seed, theirs->seed, 1, tx->output, 2, NULL);
|
||||
return tx;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user