diff --git a/Makefile b/Makefile index 5b1617ccf..e0cf6d2c8 100644 --- a/Makefile +++ b/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. diff --git a/anchor.c b/anchor.c index 839b19d48..a0184144a 100644 --- a/anchor.c +++ b/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 diff --git a/bitcoin/signature.c b/bitcoin/signature.c index fc9f47139..160be9500 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -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. */ diff --git a/bitcoin/tx.c b/bitcoin/tx.c index 5e41c80ca..5c07d3f03 100644 --- a/bitcoin/tx.c +++ b/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(input->script, input->script_length, addp); - add_le32(input->sequence_number, 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, 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); - input->script_length = pull_varint(cursor, max); - input->script = tal_arr(ctx, u8, input->script_length); - pull(cursor, max, input->script, input->script_length); + 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++) diff --git a/bitcoin/tx.h b/bitcoin/tx.h index 5e08fae45..a2cb78576 100644 --- a/bitcoin/tx.h +++ b/bitcoin/tx.h @@ -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); diff --git a/commit_tx.c b/commit_tx.c index ca29e12c3..d850ac9be 100644 --- a/commit_tx.c +++ b/commit_tx.c @@ -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; }