Browse Source

protocol: switch to single-funder anchor model.

Most complex change was gather_updates(), which handles all the "what
is the current state of the channel" logic for our dumb test utils.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 10 years ago
parent
commit
eac3af06f1
  1. 4
      Makefile
  2. 159
      anchor.c
  3. 31
      anchor.h
  4. 27
      close_tx.c
  5. 6
      close_tx.h
  6. 54
      commit_tx.c
  7. 7
      commit_tx.h
  8. 58
      funding.c
  9. 39
      funding.h
  10. 588
      lightning.pb-c.c
  11. 271
      lightning.pb-c.h
  12. 75
      lightning.proto
  13. 50
      pkt.c
  14. 27
      pkt.h
  15. 61
      test-cli/check-anchor-scriptsigs.c
  16. 82
      test-cli/check-commit-sig.c
  17. 40
      test-cli/close-channel.c
  18. 189
      test-cli/create-anchor-tx.c
  19. 31
      test-cli/create-close-tx.c
  20. 31
      test-cli/create-commit-spend-tx.c
  21. 63
      test-cli/create-commit-tx.c
  22. 1
      test-cli/create-steal-tx.c
  23. 149
      test-cli/gather_updates.c
  24. 16
      test-cli/gather_updates.h
  25. 3
      test-cli/get-anchor-depth.c
  26. 98
      test-cli/open-anchor-scriptsigs.c
  27. 124
      test-cli/open-channel.c
  28. 42
      test-cli/open-commit-sig.c
  29. 23
      test-cli/scripts/getinput.sh
  30. 7
      test-cli/scripts/setup.sh
  31. 119
      test-cli/scripts/test.sh
  32. 42
      test-cli/update-channel-accept.c
  33. 79
      test-cli/update-channel-complete.c
  34. 61
      test-cli/update-channel-signature.c
  35. 15
      test-cli/update-channel.c

4
Makefile

@ -8,11 +8,11 @@ FEATURES := -DHAS_CSV=1 -DALPHA_TXSTYLE=1 -DUSE_SCHNORR=1
# Bitcoin uses DER for signatures
#FEATURES := -DSCRIPTS_USE_DER
PROGRAMS := test-cli/open-channel test-cli/open-anchor-scriptsigs 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 test-cli/txid-of
PROGRAMS := test-cli/open-channel test-cli/create-anchor-tx test-cli/open-commit-sig test-cli/check-commit-sig 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 test-cli/txid-of test-cli/open-anchor
BITCOIN_OBJS := bitcoin/address.o bitcoin/base58.o bitcoin/pubkey.o bitcoin/script.o bitcoin/shadouble.o bitcoin/signature.o bitcoin/tx.o
HELPER_OBJS := lightning.pb-c.o pkt.o permute_tx.o anchor.o commit_tx.o opt_bits.o close_tx.o find_p2sh_out.o protobuf_convert.o
HELPER_OBJS := lightning.pb-c.o pkt.o permute_tx.o commit_tx.o opt_bits.o close_tx.o find_p2sh_out.o protobuf_convert.o funding.o test-cli/gather_updates.o
CCAN_OBJS := ccan-crypto-sha256.o ccan-crypto-shachain.o ccan-err.o ccan-tal.o ccan-tal-str.o ccan-take.o ccan-list.o ccan-str.o ccan-opt-helpers.o ccan-opt.o ccan-opt-parse.o ccan-opt-usage.o ccan-read_write_all.o ccan-str-hex.o ccan-tal-grab_file.o ccan-noerr.o ccan-crypto-ripemd160.o

159
anchor.c

@ -1,159 +0,0 @@
#include <ccan/err/err.h>
#include "anchor.h"
#include "bitcoin/pubkey.h"
#include "bitcoin/script.h"
#include "bitcoin/tx.h"
#include "overflows.h"
#include "permute_tx.h"
#include "pkt.h"
#include "protobuf_convert.h"
struct bitcoin_tx *anchor_tx_create(const tal_t *ctx,
const OpenChannel *o1,
const OpenChannel *o2,
size_t **inmapp, size_t **outmapp)
{
uint64_t i, n_out;
struct bitcoin_tx *tx;
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;
n_out = 1 + !!o1->anchor->change + !!o2->anchor->change;
tx = bitcoin_tx(ctx, o1->anchor->n_inputs+o2->anchor->n_inputs, n_out);
/* Populate inputs. */
for (i = 0; i < o1->anchor->n_inputs; i++) {
BitcoinInput *pb = o1->anchor->inputs[i];
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++) {
BitcoinInput *pb = o2->anchor->inputs[i];
struct bitcoin_tx_input *in
= &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. */
}
/* Populate outputs. */
if (add_overflows_u64(o1->anchor->total, o2->anchor->total))
return tal_free(tx);
/* Pubkeys both valid, right? */
if (!proto_to_pubkey(o1->commit_key, &key1)
|| !proto_to_pubkey(o2->commit_key, &key2))
return tal_free(tx);
/* Make the 2 of 2 payment for the commitment txs. */
redeemscript = bitcoin_redeem_2of2(tx, &key1, &key2);
tx->output[0].amount = o1->anchor->total + o2->anchor->total;
tx->output[0].script = scriptpubkey_p2sh(tx, redeemscript);
tx->output[0].script_length = tal_count(tx->output[0].script);
/* Add change transactions (if any) */
n_out = 1;
if (o1->anchor->change) {
struct bitcoin_tx_output *out = &tx->output[n_out++];
struct pubkey key;
if (!proto_to_pubkey(o1->anchor->change->pubkey, &key))
return tal_free(tx);
out->amount = o1->anchor->change->amount;
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++];
struct pubkey key;
if (!proto_to_pubkey(o2->anchor->change->pubkey, &key))
return tal_free(tx);
out->amount = o2->anchor->change->amount;
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
inmap = NULL;
if (outmapp)
outmap = *outmapp = tal_arr(ctx, size_t, tx->output_count);
else
outmap = NULL;
permute_inputs(tx->input, tx->input_count, inmap);
permute_outputs(tx->output, tx->output_count, outmap);
return tx;
}
/* This may create an invalid anchor. That's actually OK, as the bitcoin
* network won't accept it and we'll ds our way out. */
bool anchor_add_scriptsigs(struct bitcoin_tx *anchor,
OpenAnchorScriptsigs *ssigs1,
OpenAnchorScriptsigs *ssigs2,
const size_t *inmap)
{
size_t i;
if (ssigs1->n_script + ssigs2->n_script != anchor->input_count)
return NULL;
for (i = 0; i < ssigs1->n_script; i++) {
size_t n = inmap[i];
anchor->input[n].script = ssigs1->script[i].data;
anchor->input[n].script_length = ssigs1->script[i].len;
}
for (i = 0; i < ssigs2->n_script; i++) {
size_t n = inmap[ssigs1->n_script + i];
anchor->input[n].script = ssigs2->script[i].data;
anchor->input[n].script_length = ssigs2->script[i].len;
}
return true;
}
void anchor_txid(struct bitcoin_tx *anchor, struct sha256_double *txid)
{
bitcoin_txid(anchor, txid);
}

31
anchor.h

@ -1,31 +0,0 @@
#ifndef LIGHTNING_ANCHOR_H
#define LIGHTNING_ANCHOR_H
#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.
*
* Allocate an input and output map (if non-NULL); the first
* o1->anchor->n_inputs of inmap are the location of o1's inputs, the
* next o2->anchor->n_inputs are o2's. outmap[0] is the location of
* output for the commitment tx, then o1's change (if
* o1->anchor->change), then o2's change if o2->anchor->change.
*/
struct bitcoin_tx *anchor_tx_create(const tal_t *ctx,
const OpenChannel *o1,
const OpenChannel *o2,
size_t **inmap, size_t **outmap);
/* Add these scriptsigs to the anchor transaction. */
bool anchor_add_scriptsigs(struct bitcoin_tx *anchor,
OpenAnchorScriptsigs *ssigs1,
OpenAnchorScriptsigs *ssigs2,
const size_t *inmap);
/* We wouldn't need the leak files if we had normalized txids! */
void anchor_txid(struct bitcoin_tx *anchor,
struct sha256_double *txid);
#endif /* LIGHTNING_ANCHOR_H */

27
close_tx.c

@ -10,10 +10,8 @@
struct bitcoin_tx *create_close_tx(const tal_t *ctx,
OpenChannel *ours,
OpenChannel *theirs,
int64_t delta,
const struct sha256_double *anchor_txid,
uint64_t input_amount,
unsigned int anchor_output)
OpenAnchor *anchor,
uint64_t to_us, uint64_t to_them)
{
struct bitcoin_tx *tx;
const u8 *redeemscript;
@ -24,9 +22,9 @@ struct bitcoin_tx *create_close_tx(const tal_t *ctx,
tx = bitcoin_tx(ctx, 1, 2);
/* Our input spends the anchor tx output. */
tx->input[0].txid = *anchor_txid;
tx->input[0].index = anchor_output;
tx->input[0].input_amount = input_amount;
proto_to_sha256(anchor->txid, &tx->input[0].txid.sha);
tx->input[0].index = anchor->output_index;
tx->input[0].input_amount = anchor->amount;
/* Outputs goes to final pubkey */
if (!proto_to_pubkey(ours->final_key, &ourkey))
@ -34,27 +32,26 @@ struct bitcoin_tx *create_close_tx(const tal_t *ctx,
if (!proto_to_pubkey(theirs->final_key, &theirkey))
return tal_free(tx);
/* delta must make sense. */
if (delta < 0 && ours->anchor->total - ours->commitment_fee < -delta)
return tal_free(tx);
if (delta > 0 && theirs->anchor->total - theirs->commitment_fee < delta)
return tal_free(tx);
proto_to_sha256(ours->revocation_hash, &redeem);
/* One output is to us. */
tx->output[0].amount = ours->anchor->total - ours->commitment_fee + delta;
tx->output[0].amount = to_us;
redeemscript = bitcoin_redeem_single(tx, &ourkey);
tx->output[0].script = scriptpubkey_p2sh(tx, redeemscript);
tx->output[0].script_length = tal_count(tx->output[0].script);
/* Other output is to them. */
tx->output[1].amount = theirs->anchor->total - theirs->commitment_fee - delta;
tx->output[1].amount = to_them;
redeemscript = bitcoin_redeem_single(tx, &theirkey);
tx->output[1].script = scriptpubkey_p2sh(tx, redeemscript);
tx->output[1].script_length = tal_count(tx->output[1].script);
tx->fee = ours->commitment_fee + theirs->commitment_fee;
assert(tx->output[0].amount + tx->output[1].amount
<= tx->input[0].input_amount);
tx->fee = tx->input[0].input_amount
- (tx->output[0].amount + tx->output[1].amount);
permute_outputs(tx->output, 2, NULL);
return tx;
}

6
close_tx.h

@ -10,8 +10,6 @@ struct sha256_double;
struct bitcoin_tx *create_close_tx(const tal_t *ctx,
OpenChannel *ours,
OpenChannel *theirs,
int64_t delta,
const struct sha256_double *anchor_txid,
uint64_t input_amount,
unsigned int anchor_output);
OpenAnchor *anchor,
uint64_t to_us, uint64_t to_them);
#endif

54
commit_tx.c

@ -8,13 +8,13 @@
#include "pkt.h"
#include "protobuf_convert.h"
#include <stdio.h>
struct bitcoin_tx *create_commit_tx(const tal_t *ctx,
OpenChannel *ours,
OpenChannel *theirs,
OpenAnchor *anchor,
const struct sha256 *rhash,
int64_t delta,
const struct sha256_double *anchor_txid,
unsigned int anchor_output)
uint64_t to_us, uint64_t to_them)
{
struct bitcoin_tx *tx;
const u8 *redeemscript;
@ -25,11 +25,9 @@ struct bitcoin_tx *create_commit_tx(const tal_t *ctx,
tx = bitcoin_tx(ctx, 1, 2);
/* 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;
proto_to_sha256(anchor->txid, &tx->input[0].txid.sha);
tx->input[0].index = anchor->output_index;
tx->input[0].input_amount = anchor->amount;
/* Output goes to our final pubkeys */
if (!proto_to_pubkey(ours->final_key, &ourkey))
@ -47,15 +45,8 @@ struct bitcoin_tx *create_commit_tx(const tal_t *ctx,
rhash);
tx->output[0].script = scriptpubkey_p2sh(tx, redeemscript);
tx->output[0].script_length = tal_count(tx->output[0].script);
tx->output[0].amount = to_us;
if (ours->anchor->total < ours->commitment_fee)
return tal_free(tx);
tx->output[0].amount = ours->anchor->total - ours->commitment_fee;
/* Asking for more than we have? */
if (delta < 0 && -delta > tx->output[0].amount)
return tal_free(tx);
tx->output[0].amount += delta;
/* Second output is a P2SH payment to them. */
if (!proto_to_pubkey(theirs->final_key, &to_me))
return tal_free(tx);
@ -63,19 +54,32 @@ struct bitcoin_tx *create_commit_tx(const tal_t *ctx,
bitcoin_redeem_single(ctx,
&to_me));
tx->output[1].script_length = tal_count(tx->output[1].script);
if (theirs->anchor->total < theirs->commitment_fee)
return tal_free(tx);
tx->output[1].amount = theirs->anchor->total - theirs->commitment_fee;
/* Asking for more than they have? */
if (delta > 0 && delta > tx->output[1].amount)
return tal_free(tx);
tx->output[0].amount -= delta;
tx->output[1].amount = to_them;
/* Calculate fee; difference of inputs and outputs. */
assert(tx->output[0].amount + tx->output[1].amount
<= tx->input[0].input_amount);
tx->fee = tx->input[0].input_amount
- (tx->output[0].amount + tx->output[1].amount);
fprintf(stderr, "Created commit tx: anchor=%02x%02x%02x%02x/%u/%llu,"
" out0=%02x%02x%02x%02x/%u/%02x%02x%02x%02x/%02x%02x%02x%02x/%llu, "
" out1=%02x%02x%02x%02x/%llu, fee=%llu\n",
tx->input[0].txid.sha.u.u8[0],
tx->input[0].txid.sha.u.u8[1],
tx->input[0].txid.sha.u.u8[2],
tx->input[0].txid.sha.u.u8[3],
tx->input[0].index,
(long long)tx->input[0].input_amount,
ourkey.key[0], ourkey.key[1], ourkey.key[2], ourkey.key[3],
locktime,
theirkey.key[0], theirkey.key[1], theirkey.key[2], theirkey.key[3],
rhash->u.u8[0], rhash->u.u8[1], rhash->u.u8[2], rhash->u.u8[3],
(long long)tx->output[0].amount,
to_me.key[0], to_me.key[1], to_me.key[2], to_me.key[3],
(long long)tx->output[1].amount,
(long long)tx->fee);
permute_outputs(tx->output, 2, NULL);
return tx;
}

7
commit_tx.h

@ -11,8 +11,7 @@ struct sha256;
struct bitcoin_tx *create_commit_tx(const tal_t *ctx,
OpenChannel *ours,
OpenChannel *theirs,
const struct sha256 *revocation_hash,
int64_t delta,
const struct sha256_double *anchor_txid,
unsigned int anchor_output);
OpenAnchor *anchor,
const struct sha256 *rhash,
uint64_t to_us, uint64_t to_them);
#endif

58
funding.c

@ -0,0 +1,58 @@
#include "funding.h"
#include <assert.h>
/* FIXME: Fees! */
bool funding_delta(const OpenChannel *a,
const OpenChannel *b,
const OpenAnchor *anchor,
uint64_t *channel_delta,
int64_t delta_a_to_b,
uint64_t *a_amount,
uint64_t *b_amount)
{
uint64_t *funder_amount, *non_funder_amount;
int64_t delta_to_funder;
assert(*channel_delta <= anchor->amount);
if (a->anch == OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR) {
if (b->anch != OPEN_CHANNEL__ANCHOR_OFFER__WONT_CREATE_ANCHOR)
return false;
funder_amount = a_amount;
non_funder_amount = b_amount;
delta_to_funder = delta_a_to_b;
} else {
if (a->anch != OPEN_CHANNEL__ANCHOR_OFFER__WONT_CREATE_ANCHOR)
return false;
if (b->anch != OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR)
return false;
funder_amount = b_amount;
non_funder_amount = a_amount;
delta_to_funder = -delta_a_to_b;
}
/* Trying to spend more than non-funder has? */
if (delta_to_funder > 0) {
if (delta_to_funder > *channel_delta)
return false;
/* Trying to spend more than funder has? */
} else if (-delta_to_funder > anchor->amount - *channel_delta)
return false;
*channel_delta -= delta_to_funder;
*funder_amount = anchor->amount - *channel_delta;
*non_funder_amount = *channel_delta;
return true;
}
bool initial_funding(const OpenChannel *a,
const OpenChannel *b,
const OpenAnchor *anchor,
uint64_t *a_amount,
uint64_t *b_amount)
{
uint64_t channel_delta = 0;
return funding_delta(a, b, anchor, &channel_delta, 0,
a_amount, b_amount);
}

39
funding.h

@ -0,0 +1,39 @@
#ifndef LIGHTNING_FUNDING_H
#define LIGHTNING_FUNDING_H
#include <stdbool.h>
#include "lightning.pb-c.h"
/**
* initial_funding: Given A, B, and anchor, what is initial state?
* @a: A's openchannel offer
* @b: B's openchannel offer
* @anchor: The anchor offer (A or B)
* @a_amount: amount commit tx will output to A.
* @b_amount: amount commit tx will output to B.
*/
bool initial_funding(const OpenChannel *a,
const OpenChannel *b,
const OpenAnchor *anchor,
uint64_t *a_amount,
uint64_t *b_amount);
/**
* funding_delta: With this change, what's the new state?
* @a: A's openchannel offer
* @b: B's openchannel offer
* @anchor: The anchor offer (A or B)
* @channel_delta: In/out amount funder pays to non-funder (channel state)
* @delta_a_to_b: How much A pays to B (satoshi).
* @a_amount: amount commit tx will output to A.
* @b_amount: amount commit tx will output to B.
*/
bool funding_delta(const OpenChannel *a,
const OpenChannel *b,
const OpenAnchor *anchor,
uint64_t *channel_delta,
int64_t delta_a_to_b,
uint64_t *a_amount,
uint64_t *b_amount);
#endif /* LIGHTNING_FUNDING_H */

588
lightning.pb-c.c

@ -93,49 +93,6 @@ void signature__free_unpacked
assert(message->base.descriptor == &signature__descriptor);
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}
void bitcoin_input__init
(BitcoinInput *message)
{
static BitcoinInput init_value = BITCOIN_INPUT__INIT;
*message = init_value;
}
size_t bitcoin_input__get_packed_size
(const BitcoinInput *message)
{
assert(message->base.descriptor == &bitcoin_input__descriptor);
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
}
size_t bitcoin_input__pack
(const BitcoinInput *message,
uint8_t *out)
{
assert(message->base.descriptor == &bitcoin_input__descriptor);
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
}
size_t bitcoin_input__pack_to_buffer
(const BitcoinInput *message,
ProtobufCBuffer *buffer)
{
assert(message->base.descriptor == &bitcoin_input__descriptor);
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
}
BitcoinInput *
bitcoin_input__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data)
{
return (BitcoinInput *)
protobuf_c_message_unpack (&bitcoin_input__descriptor,
allocator, len, data);
}
void bitcoin_input__free_unpacked
(BitcoinInput *message,
ProtobufCAllocator *allocator)
{
assert(message->base.descriptor == &bitcoin_input__descriptor);
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}
void bitcoin_pubkey__init
(BitcoinPubkey *message)
{
@ -179,92 +136,6 @@ void bitcoin_pubkey__free_unpacked
assert(message->base.descriptor == &bitcoin_pubkey__descriptor);
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}
void change__init
(Change *message)
{
static Change init_value = CHANGE__INIT;
*message = init_value;
}
size_t change__get_packed_size
(const Change *message)
{
assert(message->base.descriptor == &change__descriptor);
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
}
size_t change__pack
(const Change *message,
uint8_t *out)
{
assert(message->base.descriptor == &change__descriptor);
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
}
size_t change__pack_to_buffer
(const Change *message,
ProtobufCBuffer *buffer)
{
assert(message->base.descriptor == &change__descriptor);
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
}
Change *
change__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data)
{
return (Change *)
protobuf_c_message_unpack (&change__descriptor,
allocator, len, data);
}
void change__free_unpacked
(Change *message,
ProtobufCAllocator *allocator)
{
assert(message->base.descriptor == &change__descriptor);
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}
void anchor__init
(Anchor *message)
{
static Anchor init_value = ANCHOR__INIT;
*message = init_value;
}
size_t anchor__get_packed_size
(const Anchor *message)
{
assert(message->base.descriptor == &anchor__descriptor);
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
}
size_t anchor__pack
(const Anchor *message,
uint8_t *out)
{
assert(message->base.descriptor == &anchor__descriptor);
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
}
size_t anchor__pack_to_buffer
(const Anchor *message,
ProtobufCBuffer *buffer)
{
assert(message->base.descriptor == &anchor__descriptor);
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
}
Anchor *
anchor__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data)
{
return (Anchor *)
protobuf_c_message_unpack (&anchor__descriptor,
allocator, len, data);
}
void anchor__free_unpacked
(Anchor *message,
ProtobufCAllocator *allocator)
{
assert(message->base.descriptor == &anchor__descriptor);
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}
void open_channel__init
(OpenChannel *message)
{
@ -308,90 +179,90 @@ void open_channel__free_unpacked
assert(message->base.descriptor == &open_channel__descriptor);
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}
void open_commit_sig__init
(OpenCommitSig *message)
void open_anchor__init
(OpenAnchor *message)
{
static OpenCommitSig init_value = OPEN_COMMIT_SIG__INIT;
static OpenAnchor init_value = OPEN_ANCHOR__INIT;
*message = init_value;
}
size_t open_commit_sig__get_packed_size
(const OpenCommitSig *message)
size_t open_anchor__get_packed_size
(const OpenAnchor *message)
{
assert(message->base.descriptor == &open_commit_sig__descriptor);
assert(message->base.descriptor == &open_anchor__descriptor);
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
}
size_t open_commit_sig__pack
(const OpenCommitSig *message,
size_t open_anchor__pack
(const OpenAnchor *message,
uint8_t *out)
{
assert(message->base.descriptor == &open_commit_sig__descriptor);
assert(message->base.descriptor == &open_anchor__descriptor);
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
}
size_t open_commit_sig__pack_to_buffer
(const OpenCommitSig *message,
size_t open_anchor__pack_to_buffer
(const OpenAnchor *message,
ProtobufCBuffer *buffer)
{
assert(message->base.descriptor == &open_commit_sig__descriptor);
assert(message->base.descriptor == &open_anchor__descriptor);
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
}
OpenCommitSig *
open_commit_sig__unpack
OpenAnchor *
open_anchor__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data)
{
return (OpenCommitSig *)
protobuf_c_message_unpack (&open_commit_sig__descriptor,
return (OpenAnchor *)
protobuf_c_message_unpack (&open_anchor__descriptor,
allocator, len, data);
}
void open_commit_sig__free_unpacked
(OpenCommitSig *message,
void open_anchor__free_unpacked
(OpenAnchor *message,
ProtobufCAllocator *allocator)
{
assert(message->base.descriptor == &open_commit_sig__descriptor);
assert(message->base.descriptor == &open_anchor__descriptor);
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}
void open_anchor_scriptsigs__init
(OpenAnchorScriptsigs *message)
void open_commit_sig__init
(OpenCommitSig *message)
{
static OpenAnchorScriptsigs init_value = OPEN_ANCHOR_SCRIPTSIGS__INIT;
static OpenCommitSig init_value = OPEN_COMMIT_SIG__INIT;
*message = init_value;
}
size_t open_anchor_scriptsigs__get_packed_size
(const OpenAnchorScriptsigs *message)
size_t open_commit_sig__get_packed_size
(const OpenCommitSig *message)
{
assert(message->base.descriptor == &open_anchor_scriptsigs__descriptor);
assert(message->base.descriptor == &open_commit_sig__descriptor);
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
}
size_t open_anchor_scriptsigs__pack
(const OpenAnchorScriptsigs *message,
size_t open_commit_sig__pack
(const OpenCommitSig *message,
uint8_t *out)
{
assert(message->base.descriptor == &open_anchor_scriptsigs__descriptor);
assert(message->base.descriptor == &open_commit_sig__descriptor);
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
}
size_t open_anchor_scriptsigs__pack_to_buffer
(const OpenAnchorScriptsigs *message,
size_t open_commit_sig__pack_to_buffer
(const OpenCommitSig *message,
ProtobufCBuffer *buffer)
{
assert(message->base.descriptor == &open_anchor_scriptsigs__descriptor);
assert(message->base.descriptor == &open_commit_sig__descriptor);
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
}
OpenAnchorScriptsigs *
open_anchor_scriptsigs__unpack
OpenCommitSig *
open_commit_sig__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data)
{
return (OpenAnchorScriptsigs *)
protobuf_c_message_unpack (&open_anchor_scriptsigs__descriptor,
return (OpenCommitSig *)
protobuf_c_message_unpack (&open_commit_sig__descriptor,
allocator, len, data);
}
void open_anchor_scriptsigs__free_unpacked
(OpenAnchorScriptsigs *message,
void open_commit_sig__free_unpacked
(OpenCommitSig *message,
ProtobufCAllocator *allocator)
{
assert(message->base.descriptor == &open_anchor_scriptsigs__descriptor);
assert(message->base.descriptor == &open_commit_sig__descriptor);
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}
void open_complete__init
@ -987,83 +858,6 @@ const ProtobufCMessageDescriptor signature__descriptor =
(ProtobufCMessageInit) signature__init,
NULL,NULL,NULL /* reserved[123] */
};
static const ProtobufCFieldDescriptor bitcoin_input__field_descriptors[4] =
{
{
"txid",
1,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_MESSAGE,
0, /* quantifier_offset */
offsetof(BitcoinInput, txid),
&sha256_hash__descriptor,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"output",
2,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_UINT32,
0, /* quantifier_offset */
offsetof(BitcoinInput, output),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"subscript",
3,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_BYTES,
0, /* quantifier_offset */
offsetof(BitcoinInput, subscript),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"amount",
4,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_UINT64,
0, /* quantifier_offset */
offsetof(BitcoinInput, amount),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
};
static const unsigned bitcoin_input__field_indices_by_name[] = {
3, /* field[3] = amount */
1, /* field[1] = output */
2, /* field[2] = subscript */
0, /* field[0] = txid */
};
static const ProtobufCIntRange bitcoin_input__number_ranges[1 + 1] =
{
{ 1, 0 },
{ 0, 4 }
};
const ProtobufCMessageDescriptor bitcoin_input__descriptor =
{
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
"bitcoin_input",
"BitcoinInput",
"BitcoinInput",
"",
sizeof(BitcoinInput),
4,
bitcoin_input__field_descriptors,
bitcoin_input__field_indices_by_name,
1, bitcoin_input__number_ranges,
(ProtobufCMessageInit) bitcoin_input__init,
NULL,NULL,NULL /* reserved[123] */
};
static const ProtobufCFieldDescriptor bitcoin_pubkey__field_descriptors[1] =
{
{
@ -1102,150 +896,35 @@ const ProtobufCMessageDescriptor bitcoin_pubkey__descriptor =
(ProtobufCMessageInit) bitcoin_pubkey__init,
NULL,NULL,NULL /* reserved[123] */
};
static const ProtobufCFieldDescriptor change__field_descriptors[2] =
static const ProtobufCEnumValue open_channel__anchor_offer__enum_values_by_number[2] =
{
{
"amount",
1,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_UINT64,
0, /* quantifier_offset */
offsetof(Change, amount),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"pubkey",
2,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_MESSAGE,
0, /* quantifier_offset */
offsetof(Change, pubkey),
&bitcoin_pubkey__descriptor,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{ "WILL_CREATE_ANCHOR", "OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR", 1 },
{ "WONT_CREATE_ANCHOR", "OPEN_CHANNEL__ANCHOR_OFFER__WONT_CREATE_ANCHOR", 2 },
};
static const unsigned change__field_indices_by_name[] = {
0, /* field[0] = amount */
1, /* field[1] = pubkey */
static const ProtobufCIntRange open_channel__anchor_offer__value_ranges[] = {
{1, 0},{0, 2}
};
static const ProtobufCIntRange change__number_ranges[1 + 1] =
static const ProtobufCEnumValueIndex open_channel__anchor_offer__enum_values_by_name[2] =
{
{ 1, 0 },
{ 0, 2 }
{ "WILL_CREATE_ANCHOR", 0 },
{ "WONT_CREATE_ANCHOR", 1 },
};
const ProtobufCMessageDescriptor change__descriptor =
const ProtobufCEnumDescriptor open_channel__anchor_offer__descriptor =
{
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
"change",
"Change",
"Change",
PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC,
"open_channel.anchor_offer",
"anchor_offer",
"OpenChannel__AnchorOffer",
"",
sizeof(Change),
2,
change__field_descriptors,
change__field_indices_by_name,
1, change__number_ranges,
(ProtobufCMessageInit) change__init,
NULL,NULL,NULL /* reserved[123] */
};
static const ProtobufCFieldDescriptor anchor__field_descriptors[5] =
{
{
"inputs",
1,
PROTOBUF_C_LABEL_REPEATED,
PROTOBUF_C_TYPE_MESSAGE,
offsetof(Anchor, n_inputs),
offsetof(Anchor, inputs),
&bitcoin_input__descriptor,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"change",
2,
PROTOBUF_C_LABEL_OPTIONAL,
PROTOBUF_C_TYPE_MESSAGE,
0, /* quantifier_offset */
offsetof(Anchor, change),
&change__descriptor,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"total",
4,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_UINT64,
0, /* quantifier_offset */
offsetof(Anchor, total),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"fee",
8,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_UINT64,
0, /* quantifier_offset */
offsetof(Anchor, fee),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"min_confirms",
10,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_UINT32,
0, /* quantifier_offset */
offsetof(Anchor, min_confirms),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
};
static const unsigned anchor__field_indices_by_name[] = {
1, /* field[1] = change */
3, /* field[3] = fee */
0, /* field[0] = inputs */
4, /* field[4] = min_confirms */
2, /* field[2] = total */
};
static const ProtobufCIntRange anchor__number_ranges[4 + 1] =
{
{ 1, 0 },
{ 4, 2 },
{ 8, 3 },
{ 10, 4 },
{ 0, 5 }
};
const ProtobufCMessageDescriptor anchor__descriptor =
{
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
"anchor",
"Anchor",
"Anchor",
"",
sizeof(Anchor),
5,
anchor__field_descriptors,
anchor__field_indices_by_name,
4, anchor__number_ranges,
(ProtobufCMessageInit) anchor__init,
NULL,NULL,NULL /* reserved[123] */
open_channel__anchor_offer__enum_values_by_number,
2,
open_channel__anchor_offer__enum_values_by_name,
1,
open_channel__anchor_offer__value_ranges,
NULL,NULL,NULL,NULL /* reserved[1234] */
};
static const uint32_t open_channel__min_depth__default_value = 0u;
static const ProtobufCFieldDescriptor open_channel__field_descriptors[7] =
{
{
@ -1309,37 +988,37 @@ static const ProtobufCFieldDescriptor open_channel__field_descriptors[7] =
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"commitment_fee",
"anch",
6,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_UINT64,
PROTOBUF_C_TYPE_ENUM,
0, /* quantifier_offset */
offsetof(OpenChannel, commitment_fee),
NULL,
offsetof(OpenChannel, anch),
&open_channel__anchor_offer__descriptor,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"anchor",
"min_depth",
7,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_MESSAGE,
0, /* quantifier_offset */
offsetof(OpenChannel, anchor),
&anchor__descriptor,
PROTOBUF_C_LABEL_OPTIONAL,
PROTOBUF_C_TYPE_UINT32,
offsetof(OpenChannel, has_min_depth),
offsetof(OpenChannel, min_depth),
NULL,
&open_channel__min_depth__default_value,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
};
static const unsigned open_channel__field_indices_by_name[] = {
6, /* field[6] = anchor */
5, /* field[5] = anch */
4, /* field[4] = commit_key */
5, /* field[5] = commitment_fee */
0, /* field[0] = final_key */
2, /* field[2] = locktime_blocks */
1, /* field[1] = locktime_seconds */
6, /* field[6] = min_depth */
3, /* field[3] = revocation_hash */
};
static const ProtobufCIntRange open_channel__number_ranges[1 + 1] =
@ -1362,80 +1041,119 @@ const ProtobufCMessageDescriptor open_channel__descriptor =
(ProtobufCMessageInit) open_channel__init,
NULL,NULL,NULL /* reserved[123] */
};
static const ProtobufCFieldDescriptor open_commit_sig__field_descriptors[1] =
static const ProtobufCFieldDescriptor open_anchor__field_descriptors[4] =
{
{
"sig",
"txid",
1,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_MESSAGE,
0, /* quantifier_offset */
offsetof(OpenCommitSig, sig),
offsetof(OpenAnchor, txid),
&sha256_hash__descriptor,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"output_index",
2,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_UINT32,
0, /* quantifier_offset */
offsetof(OpenAnchor, output_index),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"amount",
3,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_UINT64,
0, /* quantifier_offset */
offsetof(OpenAnchor, amount),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"commit_sig",
4,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_MESSAGE,
0, /* quantifier_offset */
offsetof(OpenAnchor, commit_sig),
&signature__descriptor,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
};
static const unsigned open_commit_sig__field_indices_by_name[] = {
0, /* field[0] = sig */
static const unsigned open_anchor__field_indices_by_name[] = {
2, /* field[2] = amount */
3, /* field[3] = commit_sig */
1, /* field[1] = output_index */
0, /* field[0] = txid */
};
static const ProtobufCIntRange open_commit_sig__number_ranges[1 + 1] =
static const ProtobufCIntRange open_anchor__number_ranges[1 + 1] =
{
{ 1, 0 },
{ 0, 1 }
{ 0, 4 }
};
const ProtobufCMessageDescriptor open_commit_sig__descriptor =
const ProtobufCMessageDescriptor open_anchor__descriptor =
{
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
"open_commit_sig",
"OpenCommitSig",
"OpenCommitSig",
"open_anchor",
"OpenAnchor",
"OpenAnchor",
"",
sizeof(OpenCommitSig),
1,
open_commit_sig__field_descriptors,
open_commit_sig__field_indices_by_name,
1, open_commit_sig__number_ranges,
(ProtobufCMessageInit) open_commit_sig__init,
sizeof(OpenAnchor),
4,
open_anchor__field_descriptors,
open_anchor__field_indices_by_name,
1, open_anchor__number_ranges,
(ProtobufCMessageInit) open_anchor__init,
NULL,NULL,NULL /* reserved[123] */
};
static const ProtobufCFieldDescriptor open_anchor_scriptsigs__field_descriptors[1] =
static const ProtobufCFieldDescriptor open_commit_sig__field_descriptors[1] =
{
{
"script",
"sig",
1,
PROTOBUF_C_LABEL_REPEATED,
PROTOBUF_C_TYPE_BYTES,
offsetof(OpenAnchorScriptsigs, n_script),
offsetof(OpenAnchorScriptsigs, script),
NULL,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_MESSAGE,
0, /* quantifier_offset */
offsetof(OpenCommitSig, sig),
&signature__descriptor,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
};
static const unsigned open_anchor_scriptsigs__field_indices_by_name[] = {
0, /* field[0] = script */
static const unsigned open_commit_sig__field_indices_by_name[] = {
0, /* field[0] = sig */
};
static const ProtobufCIntRange open_anchor_scriptsigs__number_ranges[1 + 1] =
static const ProtobufCIntRange open_commit_sig__number_ranges[1 + 1] =
{
{ 1, 0 },
{ 0, 1 }
};
const ProtobufCMessageDescriptor open_anchor_scriptsigs__descriptor =
const ProtobufCMessageDescriptor open_commit_sig__descriptor =
{
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
"open_anchor_scriptsigs",
"OpenAnchorScriptsigs",
"OpenAnchorScriptsigs",
"open_commit_sig",
"OpenCommitSig",
"OpenCommitSig",
"",
sizeof(OpenAnchorScriptsigs),
sizeof(OpenCommitSig),
1,
open_anchor_scriptsigs__field_descriptors,
open_anchor_scriptsigs__field_indices_by_name,
1, open_anchor_scriptsigs__number_ranges,
(ProtobufCMessageInit) open_anchor_scriptsigs__init,
open_commit_sig__field_descriptors,
open_commit_sig__field_indices_by_name,
1, open_commit_sig__number_ranges,
(ProtobufCMessageInit) open_commit_sig__init,
NULL,NULL,NULL /* reserved[123] */
};
static const ProtobufCFieldDescriptor open_complete__field_descriptors[1] =
@ -1845,25 +1563,25 @@ static const ProtobufCFieldDescriptor pkt__field_descriptors[11] =
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"open_commit_sig",
"open_anchor",
202,
PROTOBUF_C_LABEL_OPTIONAL,
PROTOBUF_C_TYPE_MESSAGE,
offsetof(Pkt, pkt_case),
offsetof(Pkt, open_commit_sig),
&open_commit_sig__descriptor,
offsetof(Pkt, open_anchor),
&open_anchor__descriptor,
NULL,
0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"open_anchor_scriptsigs",
"open_commit_sig",
203,
PROTOBUF_C_LABEL_OPTIONAL,
PROTOBUF_C_TYPE_MESSAGE,
offsetof(Pkt, pkt_case),
offsetof(Pkt, open_anchor_scriptsigs),
&open_anchor_scriptsigs__descriptor,
offsetof(Pkt, open_commit_sig),
&open_commit_sig__descriptor,
NULL,
0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
@ -1922,8 +1640,8 @@ static const unsigned pkt__field_indices_by_name[] = {
9, /* field[9] = close_complete */
10, /* field[10] = error */
4, /* field[4] = open */
6, /* field[6] = open_anchor_scriptsigs */
5, /* field[5] = open_commit_sig */
5, /* field[5] = open_anchor */
6, /* field[6] = open_commit_sig */
7, /* field[7] = open_complete */
0, /* field[0] = update */
1, /* field[1] = update_accept */

271
lightning.pb-c.h

@ -17,13 +17,10 @@ PROTOBUF_C__BEGIN_DECLS
typedef struct _Sha256Hash Sha256Hash;
typedef struct _Signature Signature;
typedef struct _BitcoinInput BitcoinInput;
typedef struct _BitcoinPubkey BitcoinPubkey;
typedef struct _Change Change;
typedef struct _Anchor Anchor;
typedef struct _OpenChannel OpenChannel;
typedef struct _OpenAnchor OpenAnchor;
typedef struct _OpenCommitSig OpenCommitSig;
typedef struct _OpenAnchorScriptsigs OpenAnchorScriptsigs;
typedef struct _OpenComplete OpenComplete;
typedef struct _Update Update;
typedef struct _UpdateAccept UpdateAccept;
@ -37,6 +34,17 @@ typedef struct _Pkt Pkt;
/* --- enums --- */
typedef enum _OpenChannel__AnchorOffer {
/*
* I will create the anchor
*/
OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR = 1,
/*
* I won't create the anchor
*/
OPEN_CHANNEL__ANCHOR_OFFER__WONT_CREATE_ANCHOR = 2
PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(OPEN_CHANNEL__ANCHOR_OFFER)
} OpenChannel__AnchorOffer;
/* --- messages --- */
@ -73,34 +81,6 @@ struct _Signature
, 0, 0, 0, 0, 0, 0, 0, 0 }
/*
* Identifies consumption of a bitcoin output.
*/
struct _BitcoinInput
{
ProtobufCMessage base;
/*
* This is the transaction ID.
*/
Sha256Hash *txid;
/*
* This is the output number.
*/
uint32_t output;
/*
* And the subscript we're signing.
*/
ProtobufCBinaryData subscript;
/*
* The amount this input is worth.
*/
uint64_t amount;
};
#define BITCOIN_INPUT__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&bitcoin_input__descriptor) \
, NULL, 0, {0,NULL}, 0 }
/*
* Pubkey for commitment transaction input.
*/
@ -117,53 +97,6 @@ struct _BitcoinPubkey
, {0,NULL} }
/*
* Change, if we want any.
*/
struct _Change
{
ProtobufCMessage base;
uint64_t amount;
BitcoinPubkey *pubkey;
};
#define CHANGE__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&change__descriptor) \
, 0, NULL }
/*
* All about an anchor transaction.
*/
struct _Anchor
{
ProtobufCMessage base;
/*
* 0 or more unspent inputs we want to use for anchor.
*/
size_t n_inputs;
BitcoinInput **inputs;
/*
* Any change from anchor (in case we don't want to use them all)
*/
Change *change;
/*
* How much transaction fee we'll pay in the anchor tx.
*/
uint64_t fee;
/*
* How much we'll be putting into channel (== sum(inputs) - change - fee)
*/
uint64_t total;
/*
* How many confirmations on anchor before we'll use channel.
*/
uint32_t min_confirms;
};
#define ANCHOR__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&anchor__descriptor) \
, 0,NULL, NULL, 0, 0, 0 }
typedef enum {
OPEN_CHANNEL__LOCKTIME__NOT_SET = 0,
OPEN_CHANNEL__LOCKTIME_LOCKTIME_SECONDS = 2,
@ -177,25 +110,23 @@ struct _OpenChannel
{
ProtobufCMessage base;
/*
* Hash seed for revoking commitment transactions.
* Hash for revoking first commitment transaction.
*/
Sha256Hash *revocation_hash;
/*
* Pubkey for anchor to pay to for commitment tx (p2sh)
* Pubkey for anchor to pay into commitment tx.
*/
BitcoinPubkey *commit_key;
/*
* How to pay money to us from commit_tx.
*/
BitcoinPubkey *final_key;
OpenChannel__AnchorOffer anch;
/*
* How much transaction fee we'll pay for commitment txs.
* How far must anchor be buried before we consider channel live?
*/
uint64_t commitment_fee;
/*
* The anchor transaction details.
*/
Anchor *anchor;
protobuf_c_boolean has_min_depth;
uint32_t min_depth;
OpenChannel__LocktimeCase locktime_case;
union {
uint32_t locktime_seconds;
@ -204,38 +135,52 @@ struct _OpenChannel
};
#define OPEN_CHANNEL__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&open_channel__descriptor) \
, NULL, NULL, NULL, 0, NULL, OPEN_CHANNEL__LOCKTIME__NOT_SET, {} }
, NULL, NULL, NULL, 0, 0,0u, OPEN_CHANNEL__LOCKTIME__NOT_SET, {} }
/*
* Supply signature for commitment tx
* Whoever is supplying anchor sends this.
*/
struct _OpenCommitSig
struct _OpenAnchor
{
ProtobufCMessage base;
Signature *sig;
/*
* Transaction ID of anchor.
*/
Sha256Hash *txid;
/*
* Which output is going to the 2 of 2.
*/
uint32_t output_index;
/*
* Amount of anchor output.
*/
uint64_t amount;
/*
* Signature for your initial commitment tx.
*/
Signature *commit_sig;
};
#define OPEN_COMMIT_SIG__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&open_commit_sig__descriptor) \
, NULL }
#define OPEN_ANCHOR__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&open_anchor__descriptor) \
, NULL, 0, 0, NULL }
/*
* Supply ScriptSig for each anchor tx inputs.
* Reply: signature for your initial commitment tx
*/
struct _OpenAnchorScriptsigs
struct _OpenCommitSig
{
ProtobufCMessage base;
size_t n_script;
ProtobufCBinaryData *script;
Signature *sig;
};
#define OPEN_ANCHOR_SCRIPTSIGS__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&open_anchor_scriptsigs__descriptor) \
, 0,NULL }
#define OPEN_COMMIT_SIG__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&open_commit_sig__descriptor) \
, NULL }
/*
* Indicates we've seen transaction reach min-depth.
* Indicates we've seen anchor reach min-depth.
*/
struct _OpenComplete
{
@ -382,8 +327,8 @@ struct _Error
typedef enum {
PKT__PKT__NOT_SET = 0,
PKT__PKT_OPEN = 201,
PKT__PKT_OPEN_COMMIT_SIG = 202,
PKT__PKT_OPEN_ANCHOR_SCRIPTSIGS = 203,
PKT__PKT_OPEN_ANCHOR = 202,
PKT__PKT_OPEN_COMMIT_SIG = 203,
PKT__PKT_OPEN_COMPLETE = 204,
PKT__PKT_UPDATE = 1,
PKT__PKT_UPDATE_ACCEPT = 2,
@ -406,8 +351,8 @@ struct _Pkt
* Opening
*/
OpenChannel *open;
OpenAnchor *open_anchor;
OpenCommitSig *open_commit_sig;
OpenAnchorScriptsigs *open_anchor_scriptsigs;
OpenComplete *open_complete;
/*
* Updating (most common)
@ -470,25 +415,6 @@ Signature *
void signature__free_unpacked
(Signature *message,
ProtobufCAllocator *allocator);
/* BitcoinInput methods */
void bitcoin_input__init
(BitcoinInput *message);
size_t bitcoin_input__get_packed_size
(const BitcoinInput *message);
size_t bitcoin_input__pack
(const BitcoinInput *message,
uint8_t *out);
size_t bitcoin_input__pack_to_buffer
(const BitcoinInput *message,
ProtobufCBuffer *buffer);
BitcoinInput *
bitcoin_input__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data);
void bitcoin_input__free_unpacked
(BitcoinInput *message,
ProtobufCAllocator *allocator);
/* BitcoinPubkey methods */
void bitcoin_pubkey__init
(BitcoinPubkey *message);
@ -508,44 +434,6 @@ BitcoinPubkey *
void bitcoin_pubkey__free_unpacked
(BitcoinPubkey *message,
ProtobufCAllocator *allocator);
/* Change methods */
void change__init
(Change *message);
size_t change__get_packed_size
(const Change *message);
size_t change__pack
(const Change *message,
uint8_t *out);
size_t change__pack_to_buffer
(const Change *message,
ProtobufCBuffer *buffer);
Change *
change__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data);
void change__free_unpacked
(Change *message,
ProtobufCAllocator *allocator);
/* Anchor methods */
void anchor__init
(Anchor *message);
size_t anchor__get_packed_size
(const Anchor *message);
size_t anchor__pack
(const Anchor *message,
uint8_t *out);
size_t anchor__pack_to_buffer
(const Anchor *message,
ProtobufCBuffer *buffer);
Anchor *
anchor__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data);
void anchor__free_unpacked
(Anchor *message,
ProtobufCAllocator *allocator);
/* OpenChannel methods */
void open_channel__init
(OpenChannel *message);
@ -565,6 +453,25 @@ OpenChannel *
void open_channel__free_unpacked
(OpenChannel *message,
ProtobufCAllocator *allocator);
/* OpenAnchor methods */
void open_anchor__init
(OpenAnchor *message);
size_t open_anchor__get_packed_size
(const OpenAnchor *message);
size_t open_anchor__pack
(const OpenAnchor *message,
uint8_t *out);
size_t open_anchor__pack_to_buffer
(const OpenAnchor *message,
ProtobufCBuffer *buffer);
OpenAnchor *
open_anchor__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data);
void open_anchor__free_unpacked
(OpenAnchor *message,
ProtobufCAllocator *allocator);
/* OpenCommitSig methods */
void open_commit_sig__init
(OpenCommitSig *message);
@ -584,25 +491,6 @@ OpenCommitSig *
void open_commit_sig__free_unpacked
(OpenCommitSig *message,
ProtobufCAllocator *allocator);
/* OpenAnchorScriptsigs methods */
void open_anchor_scriptsigs__init
(OpenAnchorScriptsigs *message);
size_t open_anchor_scriptsigs__get_packed_size
(const OpenAnchorScriptsigs *message);
size_t open_anchor_scriptsigs__pack
(const OpenAnchorScriptsigs *message,
uint8_t *out);
size_t open_anchor_scriptsigs__pack_to_buffer
(const OpenAnchorScriptsigs *message,
ProtobufCBuffer *buffer);
OpenAnchorScriptsigs *
open_anchor_scriptsigs__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data);
void open_anchor_scriptsigs__free_unpacked
(OpenAnchorScriptsigs *message,
ProtobufCAllocator *allocator);
/* OpenComplete methods */
void open_complete__init
(OpenComplete *message);
@ -782,27 +670,18 @@ typedef void (*Sha256Hash_Closure)
typedef void (*Signature_Closure)
(const Signature *message,
void *closure_data);
typedef void (*BitcoinInput_Closure)
(const BitcoinInput *message,
void *closure_data);
typedef void (*BitcoinPubkey_Closure)
(const BitcoinPubkey *message,
void *closure_data);
typedef void (*Change_Closure)
(const Change *message,
void *closure_data);
typedef void (*Anchor_Closure)
(const Anchor *message,
void *closure_data);
typedef void (*OpenChannel_Closure)
(const OpenChannel *message,
void *closure_data);
typedef void (*OpenAnchor_Closure)
(const OpenAnchor *message,
void *closure_data);
typedef void (*OpenCommitSig_Closure)
(const OpenCommitSig *message,
void *closure_data);
typedef void (*OpenAnchorScriptsigs_Closure)
(const OpenAnchorScriptsigs *message,
void *closure_data);
typedef void (*OpenComplete_Closure)
(const OpenComplete *message,
void *closure_data);
@ -838,13 +717,11 @@ typedef void (*Pkt_Closure)
extern const ProtobufCMessageDescriptor sha256_hash__descriptor;
extern const ProtobufCMessageDescriptor signature__descriptor;
extern const ProtobufCMessageDescriptor bitcoin_input__descriptor;
extern const ProtobufCMessageDescriptor bitcoin_pubkey__descriptor;
extern const ProtobufCMessageDescriptor change__descriptor;
extern const ProtobufCMessageDescriptor anchor__descriptor;
extern const ProtobufCMessageDescriptor open_channel__descriptor;
extern const ProtobufCEnumDescriptor open_channel__anchor_offer__descriptor;
extern const ProtobufCMessageDescriptor open_anchor__descriptor;
extern const ProtobufCMessageDescriptor open_commit_sig__descriptor;
extern const ProtobufCMessageDescriptor open_anchor_scriptsigs__descriptor;
extern const ProtobufCMessageDescriptor open_complete__descriptor;
extern const ProtobufCMessageDescriptor update__descriptor;
extern const ProtobufCMessageDescriptor update_accept__descriptor;

75
lightning.proto

@ -24,44 +24,12 @@ message signature {
required fixed64 s4 = 8;
}
// Identifies consumption of a bitcoin output.
message bitcoin_input {
// This is the transaction ID.
required sha256_hash txid = 1;
// This is the output number.
required uint32 output = 2;
// And the subscript we're signing.
required bytes subscript = 3;
// The amount this input is worth.
required uint64 amount = 4;
}
// Pubkey for commitment transaction input.
message bitcoin_pubkey {
// Either 65 or 33 bytes.
required bytes key = 1;
};
// Change, if we want any.
message change {
required uint64 amount = 1;
required bitcoin_pubkey pubkey = 2;
}
// All about an anchor transaction.
message anchor {
// 0 or more unspent inputs we want to use for anchor.
repeated bitcoin_input inputs = 1;
// Any change from anchor (in case we don't want to use them all)
optional change change = 2;
// How much transaction fee we'll pay in the anchor tx.
required uint64 fee = 8;
// How much we'll be putting into channel (== sum(inputs) - change - fee)
required uint64 total = 4;
// How many confirmations on anchor before we'll use channel.
required uint32 min_confirms = 10;
}
//
// Packet Types
//
@ -73,29 +41,44 @@ message open_channel {
uint32 locktime_seconds = 2;
uint32 locktime_blocks = 3;
}
// Hash seed for revoking commitment transactions.
// Hash for revoking first commitment transaction.
required sha256_hash revocation_hash = 4;
// Pubkey for anchor to pay into commitment tx.
required bitcoin_pubkey commit_key = 5;
// How to pay money to us from commit_tx.
required bitcoin_pubkey final_key = 1;
// How much transaction fee we'll pay for commitment txs.
required uint64 commitment_fee = 6;
// The anchor transaction details.
required anchor anchor = 7;
enum anchor_offer {
// I will create the anchor
WILL_CREATE_ANCHOR = 1;
// I won't create the anchor
WONT_CREATE_ANCHOR = 2;
}
required anchor_offer anch = 6;
// How far must anchor be buried before we consider channel live?
optional uint32 min_depth = 7 [ default = 0 ];
}
// Supply signature for commitment tx
message open_commit_sig {
required signature sig = 1;
// Whoever is supplying anchor sends this.
message open_anchor {
// Transaction ID of anchor.
required sha256_hash txid = 1;
// Which output is going to the 2 of 2.
required uint32 output_index = 2;
// Amount of anchor output.
required uint64 amount = 3;
// Signature for your initial commitment tx.
required signature commit_sig = 4;
}
// Supply ScriptSig for each anchor tx inputs.
message open_anchor_scriptsigs {
repeated bytes script = 1;
// Reply: signature for your initial commitment tx
message open_commit_sig {
required signature sig = 1;
}
// Indicates we've seen transaction reach min-depth.
// Indicates we've seen anchor reach min-depth.
message open_complete {
// Block it went into.
optional sha256_hash blockid = 1;
@ -157,8 +140,8 @@ message pkt {
oneof pkt {
// Opening
open_channel open = 201;
open_commit_sig open_commit_sig = 202;
open_anchor_scriptsigs open_anchor_scriptsigs = 203;
open_anchor open_anchor = 202;
open_commit_sig open_commit_sig = 203;
open_complete open_complete = 204;
// Updating (most common)
update update = 1;

50
pkt.c

@ -13,7 +13,7 @@ size_t pkt_totlen(const struct pkt *pkt)
return sizeof(pkt->len) + le32_to_cpu(pkt->len);
}
static struct pkt *to_pkt(const tal_t *ctx, Pkt__PktCase type, void *msg)
static struct pkt *to_pkt(const tal_t *ctx, Pkt__PktCase type, const void *msg)
{
struct pkt *ret;
size_t len;
@ -21,7 +21,7 @@ static struct pkt *to_pkt(const tal_t *ctx, Pkt__PktCase type, void *msg)
p.pkt_case = type;
/* This is a union, so doesn't matter which we assign. */
p.error = msg;
p.error = (Error *)msg;
len = pkt__get_packed_size(&p);
ret = (struct pkt *)tal_arr(ctx, u8, sizeof(ret->len) + len);
@ -31,37 +31,44 @@ static struct pkt *to_pkt(const tal_t *ctx, Pkt__PktCase type, void *msg)
return ret;
}
struct pkt *openchannel_pkt(const tal_t *ctx,
const struct sha256 *revocation_hash,
const struct pubkey *commit,
const struct pubkey *final,
u64 commitment_fee,
u32 rel_locktime_seconds,
Anchor *anchor)
struct pkt *open_channel_pkt(const tal_t *ctx,
const struct sha256 *revocation_hash,
const struct pubkey *commit,
const struct pubkey *final,
u32 rel_locktime_seconds,
bool offer_anchor,
u32 min_depth)
{
OpenChannel o = OPEN_CHANNEL__INIT;
/* Required fields must be set: pack functions don't check! */
assert(anchor->inputs);
o.revocation_hash = sha256_to_proto(ctx, revocation_hash);
o.commit_key = pubkey_to_proto(ctx, commit);
o.final_key = pubkey_to_proto(ctx, final);
o.commitment_fee = commitment_fee;
o.anchor = anchor;
o.locktime_case = OPEN_CHANNEL__LOCKTIME_LOCKTIME_SECONDS;
o.locktime_seconds = rel_locktime_seconds;
if (offer_anchor)
o.anch = OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR;
else
o.anch = OPEN_CHANNEL__ANCHOR_OFFER__WONT_CREATE_ANCHOR;
o.min_depth = min_depth;
{
size_t len = open_channel__get_packed_size(&o);
unsigned char *pb = malloc(len);
open_channel__pack(&o, pb);
assert(open_channel__unpack(NULL, len, pb));
free(pb);
}
return to_pkt(ctx, PKT__PKT_OPEN, &o);
}
struct pkt *open_anchor_pkt(const tal_t *ctx, const OpenAnchor *oa_msg)
{
return to_pkt(ctx, PKT__PKT_OPEN_ANCHOR, oa_msg);
}
Pkt *any_pkt_from_file(const char *filename)
{
struct pkt *pkt;
@ -93,21 +100,6 @@ Pkt *pkt_from_file(const char *filename, Pkt__PktCase expect)
return ret;
}
struct pkt *open_anchor_sig_pkt(const tal_t *ctx, u8 **sigs, size_t num_sigs)
{
OpenAnchorScriptsigs o = OPEN_ANCHOR_SCRIPTSIGS__INIT;
size_t i;
o.n_script = num_sigs;
o.script = tal_arr(ctx, ProtobufCBinaryData, num_sigs);
for (i = 0; i < num_sigs; i++) {
o.script[i].data = sigs[i];
o.script[i].len = tal_count(sigs[i]);
}
return to_pkt(ctx, PKT__PKT_OPEN_ANCHOR_SCRIPTSIGS, &o);
}
struct pkt *open_commit_sig_pkt(const tal_t *ctx, const struct signature *sig)
{
OpenCommitSig o = OPEN_COMMIT_SIG__INIT;

27
pkt.h

@ -29,30 +29,29 @@ struct signature;
struct pubkey;
/**
* openchannel_pkt - create an openchannel message
* open_channel_pkt - create an openchannel message
* @ctx: tal context to allocate off.
* @revocation_hash: first hash value generated from seed.
* @commit: the pubkey for the anchor transactions' P2SH output.
* @final: the pubkey for the commit transactions' P2SH output.
* @commitment_fee: the fee to use for commitment tx.
* @rel_locktime_seconds: relative seconds for commitment locktime.
* @anchor: the anchor transaction details.
* @offer_anchor: whether we will offer anchor.
* @min_depth: minimum depth to insist on (if non-zero)
*/
struct pkt *openchannel_pkt(const tal_t *ctx,
const struct sha256 *revocation_hash,
const struct pubkey *commit,
const struct pubkey *final,
u64 commitment_fee,
u32 rel_locktime_seconds,
Anchor *anchor);
struct pkt *open_channel_pkt(const tal_t *ctx,
const struct sha256 *revocation_hash,
const struct pubkey *commit,
const struct pubkey *final,
u32 rel_locktime_seconds,
bool offer_anchor,
u32 min_depth);
/**
* open_anchor_sig_pkt - create an open_anchor_sig message
* open_anchor_pkt - create an open_anchor message packet
* @ctx: tal context to allocate off.
* @sigs: the der-encoded signatures (tal_count() gives len).
* @num_sigs: the number of sigs.
* @oa_msg: the OpenAnchor message.
*/
struct pkt *open_anchor_sig_pkt(const tal_t *ctx, u8 **sigs, size_t num_sigs);
struct pkt *open_anchor_pkt(const tal_t *ctx, const OpenAnchor *oa_msg);
/**
* open_commit_sig_pkt - create an open_commit_sig message

61
test-cli/check-anchor-scriptsigs.c

@ -1,61 +0,0 @@
#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/structeq/structeq.h>
#include "lightning.pb-c.h"
#include "anchor.h"
#include "bitcoin/base58.h"
#include "pkt.h"
#include "bitcoin/script.h"
#include "permute_tx.h"
#include "bitcoin/signature.h"
#include "commit_tx.h"
#include "bitcoin/pubkey.h"
#include <unistd.h>
int main(int argc, char *argv[])
{
const tal_t *ctx = tal_arr(NULL, char, 0);
OpenChannel *o1, *o2;
OpenAnchorScriptsigs *ss1, *ss2;
struct bitcoin_tx *anchor;
struct sha256_double txid;
size_t *inmap, *outmap;
err_set_progname(argv[0]);
opt_register_noarg("--help|-h", opt_usage_and_exit,
"<open-channel-file1> <open-channel-file2> <anchor-sig2-1> <anchor-sigs2>\n"
"Output the anchor transaction by merging the scriptsigs",
"Print this message.");
opt_parse(&argc, argv, opt_log_stderr_exit);
if (argc != 5)
opt_usage_exit_fail("Expected 6 arguments");
o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open;
o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open;
ss1 = pkt_from_file(argv[3], PKT__PKT_OPEN_ANCHOR_SCRIPTSIGS)
->open_anchor_scriptsigs;
ss2 = pkt_from_file(argv[4], PKT__PKT_OPEN_ANCHOR_SCRIPTSIGS)
->open_anchor_scriptsigs;
anchor = anchor_tx_create(ctx, o1, o2, &inmap, &outmap);
if (!anchor)
errx(1, "Failed transaction merge");
if (!anchor_add_scriptsigs(anchor, ss1, ss2, inmap))
errx(1, "Wrong number of scriptsigs");
bitcoin_txid(anchor, &txid);
if (!bitcoin_tx_write(STDOUT_FILENO, anchor))
err(1, "Writing out anchor transaction");
tal_free(ctx);
return 0;
}

82
test-cli/check-commit-sig.c

@ -5,7 +5,6 @@
#include <ccan/str/hex/hex.h>
#include <ccan/err/err.h>
#include "lightning.pb-c.h"
#include "anchor.h"
#include "bitcoin/base58.h"
#include "pkt.h"
#include "bitcoin/script.h"
@ -15,92 +14,73 @@
#include "bitcoin/pubkey.h"
#include "bitcoin/privkey.h"
#include "protobuf_convert.h"
#include "funding.h"
#include <unistd.h>
int main(int argc, char *argv[])
{
const tal_t *ctx = tal_arr(NULL, char, 0);
OpenChannel *o1, *o2;
OpenCommitSig *cs2;
struct bitcoin_tx *anchor, *commit;
struct sha256_double txid;
OpenAnchor *a;
struct bitcoin_tx *commit;
u8 *subscript;
size_t *inmap, *outmap;
struct pubkey pubkey1, pubkey2;
struct bitcoin_signature sig1, sig2;
struct bitcoin_signature sig;
struct privkey privkey;
bool testnet;
struct sha256 rhash;
u64 our_amount, their_amount;
err_set_progname(argv[0]);
opt_register_noarg("--help|-h", opt_usage_and_exit,
"<open-channel-file1> <open-channel-file2> <commit-sig-2> <commit-key1>\n"
"Output the commitment transaction if both signatures are valid",
"<open-channel-file1> <open-channel-file2> <open-anchor-file1> <commit-key1> [<commit-sig>]\n"
"Check the commit sig is valid (either in open-anchor or commit-sig packet)",
"Print this message.");
opt_parse(&argc, argv, opt_log_stderr_exit);
if (argc != 5)
opt_usage_exit_fail("Expected 4 arguments");
if (argc != 5 && argc != 6)
opt_usage_exit_fail("Expected 4 or 5 arguments");
o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open;
o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open;
cs2 = pkt_from_file(argv[3], PKT__PKT_OPEN_COMMIT_SIG)->open_commit_sig;
a = pkt_from_file(argv[3], PKT__PKT_OPEN_ANCHOR)->open_anchor;
if (!key_from_base58(argv[4], strlen(argv[4]), &testnet, &privkey, &pubkey1))
errx(1, "Invalid private key '%s'", argv[4]);
if (!testnet)
errx(1, "Private key '%s' not on testnet!", argv[4]);
sig.stype = SIGHASH_ALL;
if (argc == 6) {
OpenCommitSig *cs = pkt_from_file(argv[5],
PKT__PKT_OPEN_COMMIT_SIG)
->open_commit_sig;
if (!proto_to_signature(cs->sig, &sig.sig))
errx(1, "Bad signature in %s", argv[5]);
} else {
if (!proto_to_signature(a->commit_sig, &sig.sig))
errx(1, "Bad signature in %s", argv[3]);
}
/* Pubkey well-formed? */
if (!proto_to_pubkey(o2->commit_key, &pubkey2))
errx(1, "Invalid o2 commit_key");
/* Get the transaction ID of the anchor. */
anchor = anchor_tx_create(ctx, o1, o2, &inmap, &outmap);
if (!anchor)
errx(1, "Failed transaction merge");
anchor_txid(anchor, &txid);
if (!initial_funding(o1, o2, a, &our_amount, &their_amount))
errx(1, "Invalid open combination (need 1 anchor offer)");
/* Now create our commitment tx. */
proto_to_sha256(o1->revocation_hash, &rhash);
commit = create_commit_tx(ctx, o1, o2, &rhash, 0, &txid, outmap[0]);
commit = create_commit_tx(ctx, o1, o2, a, &rhash,
our_amount, their_amount);
/* If contributions don't exceed fees, this fails. */
if (!commit)
errx(1, "Contributions %llu & %llu vs fees %llu & %llu",
(long long)o1->anchor->total,
(long long)o2->anchor->total,
(long long)o1->commitment_fee,
(long long)o2->commitment_fee);
/* FIXME: Creating out signature just to check the script we create
* is overkill: if their signature and pubkey signed the commit txin,
* we're happy. */
sig1.stype = SIGHASH_ALL;
/* Check signature. */
subscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
sign_tx_input(ctx, commit, 0, subscript, tal_count(subscript),
&privkey, &pubkey1, &sig1.sig);
/* Signatures well-formed? */
if (!proto_to_signature(cs2->sig, &sig2.sig))
errx(1, "Invalid commit-sig-2");
sig2.stype = SIGHASH_ALL;
/* Combined signatures must validate correctly. */
if (!check_2of2_sig(commit, 0, subscript, tal_count(subscript),
&pubkey1, &pubkey2, &sig1, &sig2))
errx(1, "Signature failed");
/* Create p2sh input for commit */
commit->input[0].script = scriptsig_p2sh_2of2(commit, &sig1, &sig2,
&pubkey1, &pubkey2);
commit->input[0].script_length = tal_count(commit->input[0].script);
/* Print it out in hex. */
if (!bitcoin_tx_write(STDOUT_FILENO, commit))
err(1, "Writing out transaction");
if (!check_tx_sig(commit, 0, subscript, tal_count(subscript),
&pubkey2, &sig))
errx(1, "Their signature invalid");
tal_free(ctx);
return 0;

40
test-cli/close-channel.c

@ -6,41 +6,40 @@
#include <ccan/err/err.h>
#include <ccan/read_write_all/read_write_all.h>
#include "lightning.pb-c.h"
#include "anchor.h"
#include "bitcoin/base58.h"
#include "pkt.h"
#include "bitcoin/script.h"
#include "permute_tx.h"
#include "funding.h"
#include "bitcoin/signature.h"
#include "bitcoin/pubkey.h"
#include "bitcoin/privkey.h"
#include "close_tx.h"
#include "find_p2sh_out.h"
#include "protobuf_convert.h"
#include "gather_updates.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, *close_tx;
struct sha256_double anchor_txid;
OpenAnchor *a;
struct bitcoin_tx *close_tx;
struct pkt *pkt;
struct signature sig;
struct privkey privkey;
bool testnet, complete = false;
struct pubkey pubkey1, pubkey2;
u8 *redeemscript;
int64_t delta;
size_t i, anchor_out;
uint64_t our_amount, their_amount;
err_set_progname(argv[0]);
/* FIXME: Take update.pbs to adjust channel */
opt_register_noarg("--complete", opt_set_bool, &complete,
"Create a close_transaction_complete msg instead");
opt_register_noarg("--help|-h", opt_usage_and_exit,
"<anchor-tx> <open-channel-file1> <open-channel-file2> <commit-privkey> [update-protobuf]...\n"
"<open-channel-file1> <open-channel-file2> <anchor-file> <commit-privkey> [{+/-}update-protobuf]...\n"
"Create the signature needed for the close transaction",
"Print this message.");
@ -49,23 +48,17 @@ int main(int argc, char *argv[])
if (argc < 5)
opt_usage_exit_fail("Expected 4+ arguments");
anchor = bitcoin_tx_from_file(ctx, argv[1]);
o1 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open;
o2 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open;
o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open;
o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open;
a = pkt_from_file(argv[3], PKT__PKT_OPEN_ANCHOR)->open_anchor;
if (!key_from_base58(argv[4], strlen(argv[4]), &testnet, &privkey, &pubkey1))
errx(1, "Invalid private key '%s'", argv[4]);
if (!testnet)
errx(1, "Private key '%s' not on testnet!", argv[4]);
bitcoin_txid(anchor, &anchor_txid);
/* Get delta by accumulting all the updates. */
delta = 0;
for (i = 5; i < argc; i++) {
Update *u = pkt_from_file(argv[i], PKT__PKT_UPDATE)->update;
delta += u->delta;
}
gather_updates(o1, o2, a, argv + 5, &our_amount, &their_amount,
NULL, NULL, NULL);
/* Get pubkeys */
if (!proto_to_pubkey(o1->commit_key, &pubkey2))
@ -76,16 +69,11 @@ int main(int argc, char *argv[])
if (!proto_to_pubkey(o2->commit_key, &pubkey2))
errx(1, "Invalid o2 commit pubkey");
/* This is what the anchor pays to; figure out whick output. */
/* This is what the anchor pays to. */
redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
/* Now create the close tx to spend 2/2 output of anchor. */
/* Assumes that updates are all from closer -> closee */
anchor_out = find_p2sh_out(anchor, redeemscript);
close_tx = create_close_tx(ctx, o1, o2, complete ? -delta : delta,
&anchor_txid,
anchor->output[anchor_out].amount,
anchor_out);
/* FIXME: Add fee! */
close_tx = create_close_tx(ctx, o1, o2, a, our_amount, their_amount);
/* Sign it for them. */
sign_tx_input(ctx, close_tx, 0, redeemscript, tal_count(redeemscript),

189
test-cli/create-anchor-tx.c

@ -0,0 +1,189 @@
#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 "bitcoin/base58.h"
#include "pkt.h"
#include "bitcoin/script.h"
#include "bitcoin/address.h"
#include "bitcoin/tx.h"
#include "bitcoin/pubkey.h"
#include "bitcoin/privkey.h"
#include "bitcoin/shadouble.h"
#include "protobuf_convert.h"
#include <unistd.h>
#include <time.h>
#include "opt_bits.h"
/* Bitcoin nodes are allowed to be 2 hours in the future. */
#define LOCKTIME_MIN (2 * 60 * 60)
struct input {
struct bitcoin_tx_input in;
struct privkey privkey;
struct pubkey pubkey;
struct bitcoin_signature sig;
};
static void parse_anchor_input(const char *spec, struct input *in)
{
const char *slash;
char *end;
long l;
bool testnet;
slash = strchr(spec, '/');
if (!slash)
errx(1, "Expected / in <txid>/<num>/<satoshis>/<hexscript>/<privkey>");
if (!bitcoin_txid_from_hex(spec, slash - spec, &in->in.txid))
errx(1, "Expected 256-bit hex txid before /");
in->in.index = l = strtol(slash + 1, &end, 10);
if (end == slash + 1 || *end != '/' || (int64_t)in->in.index != (int64_t)l)
errx(1, "Expected <outputnum> after /");
slash = end;
in->in.input_amount = l = strtol(slash + 1, &end, 10);
if (end == slash + 1 || *end != '/' || (int64_t)in->in.input_amount != (int64_t)l)
errx(1, "Expected <satoshis> after second /");
slash = end;
end = (char *)slash + 1 + strcspn(slash + 1, "/");
in->in.script_length = hex_data_size(end - (slash + 1));
in->in.script = tal_arr(in, u8, in->in.script_length);
if (!hex_decode(slash + 1, end - (slash + 1),
in->in.script, in->in.script_length))
errx(1, "Expected hex string after third /");
if (*end != '/')
errx(1, "Expected / after hexscript");
if (!key_from_base58(end+1, strlen(end + 1), &testnet,
&in->privkey, &in->pubkey))
errx(1, "Invalid private key '%s'", end+1);
if (!testnet)
errx(1, "Private key '%s' not on testnet!", end+1);
}
int main(int argc, char *argv[])
{
OpenChannel *o1, *o2;
struct bitcoin_tx *anchor;
const tal_t *ctx = tal_arr(NULL, char, 0);
u64 anchor_fee, amount, total_in, change;
struct input *in;
u8 *redeemscript;
size_t i;
struct pubkey pubkey1, pubkey2;
err_set_progname(argv[0]);
anchor_fee = 10000;
opt_register_noarg("--help|-h", opt_usage_and_exit,
"<open-channel-file1> <open-channel-file2> <amount> <changepubkey> <txid>/<outnum>/<satoshis>/<script-in-hex>/<privkey>...\n"
"A test program to create an anchor tx on stdout.",
"Print this message.");
opt_register_arg("--anchor-fee=<bits>",
opt_set_bits, opt_show_bits, &anchor_fee,
"100's of satoshi to pay for anchor");
opt_parse(&argc, argv, opt_log_stderr_exit);
if (argc < 6)
opt_usage_exit_fail("Expected 5 or more arguments");
o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open;
o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open;
if (!proto_to_pubkey(o1->commit_key, &pubkey1))
errx(1, "Invalid o1 commit_key");
if (!proto_to_pubkey(o2->commit_key, &pubkey2))
errx(1, "Invalid o2 commit_key");
amount = atol(argv[3]);
if (!amount)
errx(1, "Invalid total: must be > 0");
in = tal_arr(ctx, struct input, argc - 5);
total_in = 0;
for (i = 0; i < tal_count(in); i++) {
parse_anchor_input(argv[5+i], &in[i]);
total_in += in[i].in.input_amount;
}
if (total_in < amount + anchor_fee)
errx(1, "Only %llu satoshi in, and %llu out (+%llu fee)",
(unsigned long long)total_in,
(unsigned long long)amount,
(unsigned long long)anchor_fee);
change = total_in - (amount + anchor_fee);
/* If there's change, we have an extra output. */
anchor = bitcoin_tx(ctx, tal_count(in), change ? 2 : 1);
anchor->fee = anchor_fee;
/* Commitment redeems this via 2 of 2 payment. */
redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
/* Set up outputs. */
anchor->output[0].amount = amount;
anchor->output[0].script = scriptpubkey_p2sh(anchor, redeemscript);
anchor->output[0].script_length = tal_count(anchor->output[0].script);
if (change) {
struct pubkey change_key;
if (!pubkey_from_hexstr(argv[4], &change_key))
errx(1, "Invalid change key %s", argv[3]);
redeemscript = bitcoin_redeem_single(anchor, &change_key);
anchor->output[1].amount = change;
anchor->output[1].script = scriptpubkey_p2sh(anchor,
redeemscript);
anchor->output[1].script_length
= tal_count(anchor->output[1].script);
}
/* Set up inputs (leaving scripts empty for signing) */
for (i = 0; i < tal_count(in); i++) {
anchor->input[i].input_amount = in[i].in.input_amount;
anchor->input[i].txid = in[i].in.txid;
anchor->input[i].index = in[i].in.index;
}
/* Now, sign each input. */
for (i = 0; i < tal_count(in); i++) {
in[i].sig.stype = SIGHASH_ALL;
if (!sign_tx_input(ctx, anchor, i, in[i].in.script,
in[i].in.script_length,
&in[i].privkey, &in[i].pubkey,
&in[i].sig.sig))
errx(1, "Error signing input %zi", i);
}
/* Finally, complete inputs using signatures. */
for (i = 0; i < tal_count(in); i++) {
if (!is_pay_to_pubkey_hash(in[i].in.script,
in[i].in.script_length))
errx(1, "FIXME: Don't know how to handle input %zi", i);
anchor->input[i].script
= scriptsig_pay_to_pubkeyhash(anchor, &in[i].pubkey,
&in[i].sig);
anchor->input[i].script_length
= tal_count(anchor->input[i].script);
}
/* Print it out in hex. */
if (!bitcoin_tx_write(STDOUT_FILENO, anchor))
err(1, "Writing out transaction");
tal_free(ctx);
return 0;
}

31
test-cli/create-close-tx.c

@ -5,7 +5,6 @@
#include <ccan/str/hex/hex.h>
#include <ccan/err/err.h>
#include "lightning.pb-c.h"
#include "anchor.h"
#include "bitcoin/base58.h"
#include "pkt.h"
#include "bitcoin/script.h"
@ -15,27 +14,27 @@
#include "close_tx.h"
#include "find_p2sh_out.h"
#include "protobuf_convert.h"
#include "gather_updates.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, *close_tx;
struct sha256_double anchor_txid;
OpenAnchor *a;
struct bitcoin_tx *close_tx;
struct bitcoin_signature sig1, sig2;
struct pubkey pubkey1, pubkey2;
u8 *redeemscript;
CloseChannel *close;
CloseChannelComplete *closecomplete;
size_t i, anchor_out;
int64_t delta;
uint64_t our_amount, their_amount;
err_set_progname(argv[0]);
/* FIXME: Take update.pbs to adjust channel */
opt_register_noarg("--help|-h", opt_usage_and_exit,
"<anchor-tx> <open-channel-file1> <open-channel-file2> <close-protobuf> <close-complete-protobuf> [update-protobuf]...\n"
"<open-channel-file1> <open-channel-file2> <open-anchor-file> <close-protobuf> <close-complete-protobuf> [update-protobuf]...\n"
"Create the close transaction from the signatures",
"Print this message.");
@ -44,14 +43,12 @@ int main(int argc, char *argv[])
if (argc < 6)
opt_usage_exit_fail("Expected 5+ arguments");
anchor = bitcoin_tx_from_file(ctx, argv[1]);
o1 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open;
o2 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open;
o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open;
o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open;
a = pkt_from_file(argv[3], PKT__PKT_OPEN_ANCHOR)->open_anchor;
close = pkt_from_file(argv[4], PKT__PKT_CLOSE)->close;
closecomplete = pkt_from_file(argv[5], PKT__PKT_CLOSE_COMPLETE)->close_complete;
bitcoin_txid(anchor, &anchor_txid);
/* Pubkeys well-formed? */
if (!proto_to_pubkey(o1->commit_key, &pubkey1))
errx(1, "Invalid o1 commit_key");
@ -59,20 +56,14 @@ int main(int argc, char *argv[])
errx(1, "Invalid o2 commit_key");
/* Get delta by accumulting all the updates. */
delta = 0;
for (i = 6; i < argc; i++) {
Update *u = pkt_from_file(argv[i], PKT__PKT_UPDATE)->update;
delta += u->delta;
}
gather_updates(o1, o2, a, argv + 6, &our_amount, &their_amount,
NULL, NULL, NULL);
/* This is what the anchor pays to; figure out which output. */
redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
/* Now create the close tx to spend 2/2 output of anchor. */
anchor_out = find_p2sh_out(anchor, redeemscript);
close_tx = create_close_tx(ctx, o1, o2, delta, &anchor_txid,
anchor->output[anchor_out].amount,
anchor_out);
close_tx = create_close_tx(ctx, o1, o2, a, our_amount, their_amount);
/* Signatures well-formed? */
sig1.stype = sig2.stype = SIGHASH_ALL;

31
test-cli/create-commit-spend-tx.c

@ -6,7 +6,6 @@
#include <ccan/err/err.h>
#include <ccan/structeq/structeq.h>
#include "lightning.pb-c.h"
#include "anchor.h"
#include "bitcoin/base58.h"
#include "pkt.h"
#include "bitcoin/script.h"
@ -19,12 +18,14 @@
#include "opt_bits.h"
#include "find_p2sh_out.h"
#include "protobuf_convert.h"
#include "test-cli/gather_updates.h"
#include <unistd.h>
int main(int argc, char *argv[])
{
const tal_t *ctx = tal_arr(NULL, char, 0);
OpenChannel *o1, *o2;
OpenAnchor *a;
struct bitcoin_tx *commit, *tx;
struct bitcoin_signature sig;
struct privkey privkey;
@ -32,8 +33,8 @@ int main(int argc, char *argv[])
struct pubkey pubkey1, pubkey2, outpubkey;
u8 *redeemscript;
struct sha256 rhash;
size_t i, p2sh_out;
u64 fee = 10000;
size_t p2sh_out;
u64 fee = 10000, our_amount, their_amount;
u32 locktime;
err_set_progname(argv[0]);
@ -41,7 +42,7 @@ int main(int argc, char *argv[])
/* FIXME: If we've updated channel since, we need the final
* revocation hash we sent (either update_accept or update_complete) */
opt_register_noarg("--help|-h", opt_usage_and_exit,
"<commitment-tx> <open-channel-file1> <open-channel-file2> <my-privoutkey> <someaddress> [previous-updates]\n"
"<commitment-tx> <open-channel-file1> <open-channel-file2> <open-anchor-file> <my-privoutkey> <someaddress> [previous-updates]\n"
"Create the transaction to spend our commit transaction",
"Print this message.");
opt_register_arg("--fee=<bits>",
@ -57,17 +58,18 @@ int main(int argc, char *argv[])
o1 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open;
o2 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open;
a = pkt_from_file(argv[4], PKT__PKT_OPEN_ANCHOR)->open_anchor;
if (!proto_to_locktime(o2, &locktime))
errx(1, "Invalid locktime in o2");
/* We need our private key to spend commit output. */
if (!key_from_base58(argv[4], strlen(argv[4]), &testnet, &privkey, &pubkey1))
errx(1, "Invalid private key '%s'", argv[4]);
if (!key_from_base58(argv[5], strlen(argv[5]), &testnet, &privkey, &pubkey1))
errx(1, "Invalid private key '%s'", argv[5]);
if (!testnet)
errx(1, "Private key '%s' not on testnet!", argv[4]);
errx(1, "Private key '%s' not on testnet!", argv[5]);
if (!pubkey_from_hexstr(argv[5], &outpubkey))
errx(1, "Invalid bitcoin pubkey '%s'", argv[5]);
if (!pubkey_from_hexstr(argv[6], &outpubkey))
errx(1, "Invalid bitcoin pubkey '%s'", argv[6]);
/* Get pubkeys */
if (!proto_to_pubkey(o1->final_key, &pubkey2))
@ -78,14 +80,9 @@ int main(int argc, char *argv[])
if (!proto_to_pubkey(o2->final_key, &pubkey2))
errx(1, "Invalid o2 final pubkey");
/* o1 gives us the revocation hash */
proto_to_sha256(o1->revocation_hash, &rhash);
/* Latest revocation hash comes from last update. */
for (i = 6; i < argc; i++) {
Update *u = pkt_from_file(argv[i], PKT__PKT_UPDATE)->update;
proto_to_sha256(u->revocation_hash, &rhash);
}
/* We use this simply to get final revocation hash. */
gather_updates(o1, o2, a, argv + 7, &our_amount, &their_amount,
&rhash, NULL, NULL);
/* Create redeem script */
redeemscript = bitcoin_redeem_secret_or_delay(ctx, &pubkey1, locktime,

63
test-cli/create-commit-tx.c

@ -5,7 +5,6 @@
#include <ccan/str/hex/hex.h>
#include <ccan/err/err.h>
#include "lightning.pb-c.h"
#include "anchor.h"
#include "bitcoin/base58.h"
#include "pkt.h"
#include "bitcoin/script.h"
@ -16,6 +15,7 @@
#include "bitcoin/privkey.h"
#include "find_p2sh_out.h"
#include "protobuf_convert.h"
#include "gather_updates.h"
#include <unistd.h>
/* FIXME: this code doesn't work if we're not the ones proposing the delta */
@ -23,34 +23,31 @@ int main(int argc, char *argv[])
{
const tal_t *ctx = tal_arr(NULL, char, 0);
OpenChannel *o1, *o2;
Pkt *pkt;
struct bitcoin_tx *anchor, *commit;
struct sha256_double anchor_txid;
OpenAnchor *a;
struct bitcoin_tx *commit;
struct privkey privkey;
bool testnet;
struct bitcoin_signature sig1, sig2;
size_t i;
struct pubkey pubkey1, pubkey2;
u8 *redeemscript;
int64_t delta;
uint64_t our_amount, their_amount;
struct sha256 rhash;
err_set_progname(argv[0]);
opt_register_noarg("--help|-h", opt_usage_and_exit,
"<anchor-tx> <open-channel-file1> <open-channel-file2> <commit-privkey> [final-update-accept|open-commit-sig] [<updates>]\n"
"<open-channel-file1> <open-channel-file2> <open-anchor-file> <commit-privkey> [<updates>]\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_exit_fail("Expected 5+ arguments");
if (argc < 5)
opt_usage_exit_fail("Expected 4+ arguments");
anchor = bitcoin_tx_from_file(ctx, argv[1]);
bitcoin_txid(anchor, &anchor_txid);
o1 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open;
o2 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open;
o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open;
o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open;
a = pkt_from_file(argv[3], PKT__PKT_OPEN_ANCHOR)->open_anchor;
if (!key_from_base58(argv[4], strlen(argv[4]), &testnet, &privkey, &pubkey1))
errx(1, "Invalid private key '%s'", argv[4]);
@ -66,49 +63,27 @@ int main(int argc, char *argv[])
if (!proto_to_pubkey(o2->commit_key, &pubkey2))
errx(1, "Invalid o2 commit pubkey");
/* Their signature comes from open-commit or from update-accept. */
sig2.stype = SIGHASH_ALL;
pkt = any_pkt_from_file(argv[5]);
switch (pkt->pkt_case) {
case PKT__PKT_UPDATE_ACCEPT:
if (!proto_to_signature(pkt->update_accept->sig, &sig2.sig))
errx(1, "Invalid update-accept sig");
break;
case PKT__PKT_OPEN_COMMIT_SIG:
if (!proto_to_signature(pkt->open_commit_sig->sig, &sig2.sig))
errx(1, "Invalid open-commit-sig sig");
break;
default:
errx(1, "Unexpected packet type %u in %s",
pkt->pkt_case, argv[5]);
}
/* Initial revocation hash comes from open. */
proto_to_sha256(o1->revocation_hash, &rhash);
delta = 0;
/* Figure out cumulative delta since anchor, update revocation hash */
for (i = 6; i < argc; i++) {
Update *u = pkt_from_file(argv[i], PKT__PKT_UPDATE)->update;
delta += u->delta;
proto_to_sha256(u->revocation_hash, &rhash);
}
gather_updates(o1, o2, a, argv + 5, &our_amount, &their_amount,
&rhash, NULL, &sig2.sig);
redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
/* Now create commitment tx to spend 2/2 output of anchor. */
commit = create_commit_tx(ctx, o1, o2, &rhash, delta, &anchor_txid,
find_p2sh_out(anchor, redeemscript));
commit = create_commit_tx(ctx, o1, o2, a, &rhash,
our_amount, their_amount);
/* If contributions don't exceed fees, this fails. */
/* This only fails on malformed packets */
if (!commit)
errx(1, "Bad commit amounts");
errx(1, "Malformed packets");
/* We generate our signature. */
sig1.stype = SIGHASH_ALL;
sign_tx_input(ctx, commit, 0, redeemscript, tal_count(redeemscript),
&privkey, &pubkey1, &sig1.sig);
/* Check it works with theirs... */
if (!check_2of2_sig(commit, 0, redeemscript, tal_count(redeemscript),
&pubkey1, &pubkey2, &sig1, &sig2))
errx(1, "Signature failed");

1
test-cli/create-steal-tx.c

@ -5,7 +5,6 @@
#include <ccan/str/hex/hex.h>
#include <ccan/err/err.h>
#include "lightning.pb-c.h"
#include "anchor.h"
#include "bitcoin/base58.h"
#include "pkt.h"
#include "bitcoin/script.h"

149
test-cli/gather_updates.c

@ -0,0 +1,149 @@
#include <ccan/err/err.h>
#include <ccan/crypto/sha256/sha256.h>
#include <ccan/structeq/structeq.h>
#include "test-cli/gather_updates.h"
#include "funding.h"
#include "pkt.h"
#include "protobuf_convert.h"
static void check_preimage(const Sha256Hash *preimage,
const struct sha256 *old,
const struct sha256 *h,
const char *file)
{
struct sha256 sha;
if (!h)
return;
proto_to_sha256(preimage, &sha);
sha256(&sha, &sha, sizeof(sha));
if (!structeq(&sha, old))
errx(1, "Invalid preimage in %s!", file);
}
static void get_rhash(const Sha256Hash *rhash, struct sha256 *old,
struct sha256 *new)
{
if (new) {
*old = *new;
proto_to_sha256(rhash, new);
}
}
/* Takes complete update history, gets summary of last state. */
uint64_t gather_updates(const OpenChannel *o1, const OpenChannel *o2,
const OpenAnchor *oa,
char **argv,
uint64_t *our_amount, uint64_t *their_amount,
struct sha256 *our_rhash,
struct sha256 *their_rhash,
struct signature *their_commit_sig)
{
uint64_t cdelta = 0;
uint64_t num_updates = 0;
Signature *sig = NULL;
struct sha256 old_our_rhash, old_their_rhash;
/* Start sanity check. */
if (!initial_funding(o1, o2, oa, our_amount, their_amount))
errx(1, "Invalid open combination (need 1 anchor offer)");
if (our_rhash)
proto_to_sha256(o1->revocation_hash, our_rhash);
if (their_rhash)
proto_to_sha256(o2->revocation_hash, their_rhash);
/* If o2 sent anchor, it contains their commit sig. */
if (o2->anch == OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR)
sig = oa->commit_sig;
while (*argv) {
int64_t delta;
bool received;
Pkt *pkt;
/* + marks messages sent by us, - for messages from them */
if (strstarts(*argv, "+")) {
received = false;
} else if (strstarts(*argv, "-")) {
received = true;
} else
errx(1, "%s does not start with +/-", *argv);
pkt = any_pkt_from_file(*argv + 1);
switch (pkt->pkt_case) {
case PKT__PKT_OPEN_COMMIT_SIG:
if (received)
sig = pkt->open_commit_sig->sig;
break;
case PKT__PKT_UPDATE: {
if (received) {
delta = -pkt->update->delta;
get_rhash(pkt->update->revocation_hash,
&old_their_rhash, their_rhash);
} else {
delta = pkt->update->delta;
get_rhash(pkt->update->revocation_hash,
&old_our_rhash, our_rhash);
}
if (!funding_delta(o1, o2, oa, &cdelta, delta,
our_amount, their_amount))
errx(1, "Impossible funding update %lli %s",
(long long)delta, *argv);
num_updates++;
break;
}
case PKT__PKT_UPDATE_ACCEPT:
if (received) {
sig = pkt->update_accept->sig;
get_rhash(pkt->update_accept->revocation_hash,
&old_their_rhash, their_rhash);
} else {
get_rhash(pkt->update_accept->revocation_hash,
&old_our_rhash, our_rhash);
}
break;
case PKT__PKT_UPDATE_SIGNATURE:
if (received) {
sig = pkt->update_signature->sig;
check_preimage(pkt->update_signature
->revocation_preimage,
&old_their_rhash, their_rhash,
*argv);
} else {
check_preimage(pkt->update_signature
->revocation_preimage,
&old_our_rhash, our_rhash,
*argv);
}
break;
case PKT__PKT_UPDATE_COMPLETE:
if (received) {
check_preimage(pkt->update_complete
->revocation_preimage,
&old_their_rhash, their_rhash,
*argv);
} else {
check_preimage(pkt->update_complete
->revocation_preimage,
&old_our_rhash, our_rhash,
*argv);
}
break;
default:
errx(1, "Unexpected packet type %u", pkt->pkt_case);
}
argv++;
}
if (their_commit_sig) {
if (!sig)
errx(1, "No commit signature message found");
if (!proto_to_signature(sig, their_commit_sig))
errx(1, "Invalid signature");
}
return num_updates;
}

16
test-cli/gather_updates.h

@ -0,0 +1,16 @@
#ifndef GATHER_UPDATES_H
#define GATHER_UPDATES_H
#include "lightning.pb-c.h"
struct signature;
struct sha256;
uint64_t gather_updates(const OpenChannel *o1, const OpenChannel *o2,
const OpenAnchor *oa,
char **argv,
uint64_t *our_amount, uint64_t *their_amount,
struct sha256 *our_rhash,
struct sha256 *their_rhash,
struct signature *their_commit_sig);
#endif /* GATHER_UPDATES_H */

3
test-cli/get-anchor-depth.c

@ -5,7 +5,6 @@
#include <ccan/str/hex/hex.h>
#include <ccan/err/err.h>
#include "lightning.pb-c.h"
#include "anchor.h"
#include "bitcoin/base58.h"
#include "pkt.h"
#include "bitcoin/script.h"
@ -33,7 +32,7 @@ int main(int argc, char *argv[])
opt_usage_exit_fail("Expected one argument");
o = pkt_from_file(argv[1], PKT__PKT_OPEN)->open;
printf("%u\n", o->anchor->min_confirms);
printf("%u\n", o->min_depth);
tal_free(ctx);
return 0;

98
test-cli/open-anchor-scriptsigs.c

@ -1,98 +0,0 @@
#include <ccan/err/err.h>
#include <ccan/opt/opt.h>
#include <ccan/read_write_all/read_write_all.h>
#include "bitcoin/tx.h"
#include "bitcoin/signature.h"
#include "lightning.pb-c.h"
#include "pkt.h"
#include "bitcoin/script.h"
#include "bitcoin/address.h"
#include "bitcoin/base58.h"
#include "anchor.h"
#include "bitcoin/pubkey.h"
#include "bitcoin/privkey.h"
#include <unistd.h>
/* All the input scripts are already set to 0. We just need to make this one. */
static u8 *tx_scriptsig(const tal_t *ctx,
struct bitcoin_tx *tx,
unsigned int i,
const BitcoinInput *input,
struct privkey *privkey,
const struct pubkey *pubkey)
{
struct bitcoin_signature sig;
sig.stype = SIGHASH_ALL;
if (!sign_tx_input(ctx, tx, i,
input->subscript.data, input->subscript.len,
privkey, pubkey, &sig.sig))
return NULL;
if (!is_pay_to_pubkey_hash(input->subscript.data, input->subscript.len))
errx(1, "FIXME: Don't know how to handle input");
return scriptsig_pay_to_pubkeyhash(ctx, pubkey, &sig);
}
int main(int argc, char *argv[])
{
OpenChannel *o1, *o2;
const tal_t *ctx = tal_arr(NULL, char, 0);
struct bitcoin_tx *anchor;
struct pkt *pkt;
size_t i;
u8 **sigs;
size_t *map;
err_set_progname(argv[0]);
opt_register_noarg("--help|-h", opt_usage_and_exit,
"<open-channel-file1> <open-channel-file2> <privkey>...\n"
"Create signatures for transactions, and output to stdout",
"Print this message.");
opt_parse(&argc, argv, opt_log_stderr_exit);
if (argc < 3)
opt_usage_exit_fail("Expected 2 or more arguments");
o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open;
o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open;
/* FIXME: We should check that their locktime is sane here,
* since we're bound to it. Also min_confirms, etc. */
/* Create merged transaction */
anchor = anchor_tx_create(ctx, o1, o2, &map, NULL);
if (!anchor)
errx(1, "Failed transaction merge");
/* Sign our inputs. */
if (o1->anchor->n_inputs != argc - 3)
errx(1, "Expected %zu private keys", o1->anchor->n_inputs);
sigs = tal_arr(ctx, u8 *, o1->anchor->n_inputs);
for (i = 0; i < o1->anchor->n_inputs; i++) {
struct pubkey pubkey;
struct privkey privkey;
bool testnet;
if (!key_from_base58(argv[3+i], strlen(argv[3+i]),
&testnet, &privkey, &pubkey))
errx(1, "Invalid private key '%s'", argv[3+i]);
if (!testnet)
errx(1, "Private key '%s' not on testnet!", argv[3+i]);
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);
if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt)))
err(1, "Writing out packet");
tal_free(ctx);
return 0;
}

124
test-cli/open-channel.c

@ -22,145 +22,61 @@
/* Bitcoin nodes are allowed to be 2 hours in the future. */
#define LOCKTIME_MIN (2 * 60 * 60)
static BitcoinInput *parse_anchor_input(const tal_t *ctx, const char *spec)
{
BitcoinInput *in = tal(ctx, BitcoinInput);
struct sha256_double txid;
const char *slash;
char *end;
long l;
bitcoin_input__init(in);
slash = strchr(spec, '/');
if (!slash)
errx(1, "Expected / in <txid>/<num>/<satoshis>/<hexscript>");
if (!bitcoin_txid_from_hex(spec, slash - spec, &txid))
errx(1, "Expected 256-bit hex txid before /");
in->txid = sha256_to_proto(in, &txid.sha);
in->output = l = strtol(slash + 1, &end, 10);
if (end == slash + 1 || *end != '/' || (int64_t)in->output != (int64_t)l)
errx(1, "Expected <outputnum> after /");
slash = end;
in->amount = l = strtol(slash + 1, &end, 10);
if (end == slash + 1 || *end != '/' || (int64_t)in->amount != (int64_t)l)
errx(1, "Expected <satoshis> after second /");
slash = end;
in->subscript.len = strlen(slash + 1) / 2;
in->subscript.data = tal_arr(in, u8, in->subscript.len);
if (!hex_decode(slash + 1, strlen(slash + 1),
in->subscript.data, in->subscript.len))
errx(1, "Expected hex string after third /");
return in;
}
/* Simple helper to open a channel. */
int main(int argc, char *argv[])
{
struct sha256 seed, revocation_hash;
struct pkt *pkt;
const tal_t *ctx = tal_arr(NULL, char, 0);
Anchor anchor = ANCHOR__INIT;
u64 commit_tx_fee, total_in;
unsigned int locktime_seconds;
bool testnet;
size_t i;
struct pubkey commitkey, outkey, changekey;
struct privkey commitprivkey, outprivkey;
unsigned int locktime_seconds, min_confirms;
bool offer_anchor = false;
struct pubkey commitkey, finalkey;
err_set_progname(argv[0]);
/* Default values. */
anchor.min_confirms = 3;
/* Remember, other side contributes to fee, too. */
anchor.fee = 5000;
/* We only need this for involuntary close, so make it larger. */
commit_tx_fee = 100000;
/* This means we have ~1 day before they can steal our money. */
locktime_seconds = LOCKTIME_MIN + 24 * 60 * 60;
/* Zero, unless they set --offer-anchor or --min-anchor-confirms */
min_confirms = 0;
opt_register_noarg("--help|-h", opt_usage_and_exit,
"<seed> <amount> <changepubkey> <commitprivkey> <outprivkey> <txid>/<outnum>/<satoshis>/<script-in-hex>...\n"
"<seed> <commitpubkey> <finalpubkey>\n"
"A test program to output openchannel on stdout.",
"Print this message.");
opt_register_arg("--min-anchor-confirms",
opt_set_uintval, opt_show_uintval, &anchor.min_confirms,
opt_set_uintval, opt_show_uintval, &min_confirms,
"Number of anchor confirmations before channel is active");
opt_register_arg("--anchor-fee=<bits>",
opt_set_bits, opt_show_bits, &anchor.fee,
"100's of satoshi to pay for anchor");
opt_register_arg("--commitment-fee=<bits>",
opt_set_bits, opt_show_bits, &commit_tx_fee,
"100's of satoshi to pay for commitment");
opt_register_arg("--locktime=<seconds>",
opt_set_uintval, opt_show_uintval, &locktime_seconds,
"Seconds to lock out our transaction redemption");
opt_register_noarg("--offer-anchor",
opt_set_bool, &offer_anchor,
"Offer to create anchor transaction");
opt_parse(&argc, argv, opt_log_stderr_exit);
if (argc < 7)
opt_usage_exit_fail("Expected 6 or more arguments");
if (argc != 4)
opt_usage_exit_fail("Expected 3 arguments");
if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed)))
errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]);
anchor.total = atol(argv[2]);
if (!anchor.total)
errx(1, "Invalid total: must be > 0");
if (!pubkey_from_hexstr(argv[3], &changekey))
errx(1, "Invalid bitcoin pubkey '%s'", argv[3]);
/* We don't really need the privkey here, but it's the most
* convenient way to get the pubkey from bitcoind. */
if (!key_from_base58(argv[4], strlen(argv[4]), &testnet,
&commitprivkey, &commitkey))
errx(1, "Invalid private key '%s'", argv[4]);
if (!testnet)
errx(1, "Private key '%s' not on testnet!", argv[4]);
if (!key_from_base58(argv[5], strlen(argv[5]), &testnet,
&outprivkey, &outkey))
errx(1, "Invalid private key '%s'", argv[5]);
if (!testnet)
errx(1, "Private key '%s' not on testnet!", argv[5]);
anchor.n_inputs = (argc - 6);
anchor.inputs = tal_arr(ctx, BitcoinInput *, anchor.n_inputs);
total_in = 0;
for (i = 0; i < anchor.n_inputs; i++) {
anchor.inputs[i] = parse_anchor_input(anchor.inputs, argv[i+6]);
total_in += anchor.inputs[i]->amount;
}
if (!pubkey_from_hexstr(argv[2], &commitkey))
errx(1, "Invalid commit key '%s'", argv[2]);
if (total_in < anchor.total + anchor.fee)
errx(1, "Only %llu satoshi in, and %llu out (+%llu fee)",
(unsigned long long)total_in,
(unsigned long long)anchor.total,
(unsigned long long)anchor.fee);
if (!pubkey_from_hexstr(argv[3], &finalkey))
errx(1, "Invalid final key '%s'", argv[3]);
/* If there's change, say where to send it. */
if (total_in != anchor.total + anchor.fee) {
anchor.change = tal(ctx, Change);
change__init(anchor.change);
anchor.change->pubkey = pubkey_to_proto(anchor.change,
&changekey);
anchor.change->amount = total_in - (anchor.total + anchor.fee);
}
if (offer_anchor && min_confirms == 0)
min_confirms = 3;
/* Get first revocation hash. */
shachain_from_seed(&seed, 0, &revocation_hash);
sha256(&revocation_hash,
revocation_hash.u.u8, sizeof(revocation_hash.u.u8));
pkt = openchannel_pkt(ctx, &revocation_hash, &commitkey, &outkey,
commit_tx_fee, locktime_seconds, &anchor);
pkt = open_channel_pkt(ctx, &revocation_hash, &commitkey, &finalkey,
locktime_seconds, offer_anchor, min_confirms);
if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt)))
err(1, "Writing out packet");

42
test-cli/open-commit-sig.c

@ -6,7 +6,6 @@
#include <ccan/err/err.h>
#include <ccan/read_write_all/read_write_all.h>
#include "lightning.pb-c.h"
#include "anchor.h"
#include "bitcoin/base58.h"
#include "pkt.h"
#include "bitcoin/script.h"
@ -16,62 +15,55 @@
#include "bitcoin/pubkey.h"
#include "bitcoin/privkey.h"
#include "protobuf_convert.h"
#include "funding.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;
OpenAnchor *a;
struct bitcoin_tx *commit;
struct pkt *pkt;
struct signature sig;
size_t *inmap, *outmap;
struct privkey privkey;
bool testnet;
struct pubkey pubkey1, pubkey2;
u8 *subscript;
struct sha256 rhash;
uint64_t to_them, to_us;
err_set_progname(argv[0]);
opt_register_noarg("--help|-h", opt_usage_and_exit,
"<open-channel-file1> <open-channel-file2> <commit-privkey>\n"
"<open-channel-file1> <open-channel-file2> <open-anchor-file1> <commit-privkey>\n"
"Create the signature needed for the commit transaction",
"Print this message.");
opt_parse(&argc, argv, opt_log_stderr_exit);
if (argc != 4)
opt_usage_exit_fail("Expected 3 arguments");
if (argc != 5)
opt_usage_exit_fail("Expected 4 arguments");
o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open;
o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open;
if (!key_from_base58(argv[3], strlen(argv[3]), &testnet, &privkey, &pubkey1))
errx(1, "Invalid private key '%s'", argv[3]);
a = pkt_from_file(argv[3], PKT__PKT_OPEN_ANCHOR)->open_anchor;
if (!key_from_base58(argv[4], strlen(argv[4]), &testnet, &privkey, &pubkey1))
errx(1, "Invalid private key '%s'", argv[4]);
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, &txid);
errx(1, "Private key '%s' not on testnet!", argv[4]);
/* Now create THEIR commitment tx to spend 2/2 output of anchor. */
if (!initial_funding(o1, o2, a, &to_us, &to_them))
errx(1, "Invalid open combination (need 1 anchor offer)");
proto_to_sha256(o2->revocation_hash, &rhash);
commit = create_commit_tx(ctx, o2, o1, &rhash, 0, &txid, outmap[0]);
commit = create_commit_tx(ctx, o2, o1, a, &rhash, to_them, to_us);
/* If contributions don't exceed fees, this fails. */
if (!commit)
errx(1, "Contributions %llu & %llu vs fees %llu & %llu",
(long long)o1->anchor->total,
(long long)o2->anchor->total,
(long long)o1->commitment_fee,
(long long)o2->commitment_fee);
errx(1, "Invalid packets?");
/* Their pubkey must be valid */
if (!proto_to_pubkey(o2->commit_key, &pubkey2))

23
test-cli/scripts/getinput.sh

@ -8,10 +8,6 @@ set -e
. `dirname $0`/vars.sh
if [ n"$1" = n--privkey ]; then
KEY=1
shift
fi
NUM=1
if [ $# = 1 ]; then
NUM=$1
@ -19,18 +15,15 @@ if [ $# = 1 ]; then
fi
if [ $# -gt 0 ]; then
echo "Usage: getinput.sh [--privkey] [INPUT-INDEX]"
echo "Usage: getinput.sh [INPUT-INDEX]"
exit 1
fi
if [ -n "$KEY" ]; then
ADDR=`$CLI listunspent | sed -n 's/^ *"address" *: *"\([0-9a-zA-Z]*\)",$/\1/p' | tail -n +$NUM | head -n1`
$CLI dumpprivkey $ADDR
else
TXID=`$CLI listunspent | sed -n 's/^ *"txid" *: *"\([0-9a-f]*\)",$/\1/p' | tail -n +$NUM | head -n1`
OUTNUM=`$CLI listunspent | sed -n 's/^ *"vout" *: *\([0-9]*\),$/\1/p' | tail -n +$NUM | head -n1`
AMOUNT=`$CLI listunspent | sed -n 's/^ *"amount" *: *\([0-9.]*\),$/\1/p' | tail -n +$NUM | head -n1 | tr -d . | sed 's/^0*//'`
SCRIPT=`$CLI listunspent | sed -n 's/^ *"scriptPubKey" *: *"\([0-9a-f]*\)",$/\1/p' | tail -n +$NUM | head -n1`
TXID=`$CLI listunspent | sed -n 's/^ *"txid" *: *"\([0-9a-f]*\)",$/\1/p' | tail -n +$NUM | head -n1`
OUTNUM=`$CLI listunspent | sed -n 's/^ *"vout" *: *\([0-9]*\),$/\1/p' | tail -n +$NUM | head -n1`
AMOUNT=`$CLI listunspent | sed -n 's/^ *"amount" *: *\([0-9.]*\),$/\1/p' | tail -n +$NUM | head -n1 | tr -d . | sed 's/^0*//'`
SCRIPT=`$CLI listunspent | sed -n 's/^ *"scriptPubKey" *: *"\([0-9a-f]*\)",$/\1/p' | tail -n +$NUM | head -n1`
ADDR=`$CLI listunspent | sed -n 's/^ *"address" *: *"\([0-9a-zA-Z]*\)",$/\1/p' | tail -n +$NUM | head -n1`
PRIVKEY=`$CLI dumpprivkey $ADDR`
echo $TXID/$OUTNUM/$AMOUNT/$SCRIPT
fi
echo $TXID/$OUTNUM/$AMOUNT/$SCRIPT/$PRIVKEY

7
test-cli/scripts/setup.sh

@ -24,11 +24,10 @@ done
scripts/generate-block.sh init
A1=`scripts/get-new-address.sh`
A2=`scripts/get-new-address.sh`
TX=`$CLI sendmany "" "{ \"$A1\":10, \"$A2\":10 }"`
TX=`$CLI sendmany "" "{ \"$A1\":10 }"`
scripts/generate-block.sh
# Find the inputs numbers corresponding to those 10 btc outs
echo "Arguments to test.sh:"
# Find the inputs number corresponding to that 10 btc out
echo "Argument to test.sh:"
for i in $(seq 1 $($CLI listunspent | grep -c txid) ); do scripts/getinput.sh $i | grep -q "$TX.*/1000000000/" && echo -n "$i "; done
echo

119
test-cli/scripts/test.sh

@ -36,18 +36,16 @@ send_after_delay()
$CLI sendrawtransaction $1
}
if [ $# -lt 2 ]; then
echo Usage: "INPUT1" "INPUT2" "[--steal|--unilateral]" >&2
if [ $# = 0 ]; then
echo Usage: "INPUT" "[--steal|--unilateral]" >&2
exit 1
fi
A_INPUTNUM=$1
B_INPUTNUM=$2
shift 2
shift
#A_INPUTNUM=4
#B_INPUTNUM=1
A_AMOUNT=100000000
B_AMOUNT=200000000
A_CHANGEADDR=`scripts/get-new-address.sh`
A_TMPADDR=`scripts/get-new-address.sh`
@ -66,79 +64,104 @@ B_FINALADDR=`scripts/get-new-address.sh`
#B_FINALADDR=mvQgfEX4iMSEYqD31524jASQviPwPwpvuv
A_TXIN=`scripts/getinput.sh $A_INPUTNUM`
A_TXINKEY=`scripts/getinput.sh --privkey $A_INPUTNUM`
B_TXIN=`scripts/getinput.sh $B_INPUTNUM`
B_TXINKEY=`scripts/getinput.sh --privkey $B_INPUTNUM`
A_SEED=00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff
B_SEED=112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00
A_CHANGEPUBKEY=`getpubkey $A_CHANGEADDR`
A_TMPKEY=`getprivkey $A_TMPADDR`
A_TMPPUBKEY=`getpubkey $A_TMPADDR`
A_FINALKEY=`getprivkey $A_FINALADDR`
A_FINALPUBKEY=`getpubkey $A_FINALADDR`
B_CHANGEPUBKEY=`getpubkey $B_CHANGEADDR`
B_TMPKEY=`getprivkey $B_TMPADDR`
B_TMPPUBKEY=`getpubkey $B_TMPADDR`
B_FINALKEY=`getprivkey $B_FINALADDR`
B_FINALPUBKEY=`getpubkey $B_FINALADDR`
# Both sides say what they want from channel
$PREFIX ./open-channel $A_SEED $A_AMOUNT $A_CHANGEPUBKEY $A_TMPKEY $A_FINALKEY $A_TXIN > A-open.pb
# Both sides say what they want from channel (A offers anchor)
$PREFIX ./open-channel --offer-anchor $A_SEED $A_TMPPUBKEY $A_FINALPUBKEY > A-open.pb
# B asks for a (dangerously) short locktime, for testing unilateral close.
$PREFIX ./open-channel --locktime=60 $B_SEED $B_AMOUNT $B_CHANGEPUBKEY $B_TMPKEY $B_FINALKEY $B_TXIN > B-open.pb
$PREFIX ./open-channel --locktime=60 $B_SEED $B_TMPPUBKEY $B_FINALPUBKEY > B-open.pb
# Now sign anchor.
$PREFIX ./open-anchor-scriptsigs A-open.pb B-open.pb $A_TXINKEY > A-anchor-scriptsigs.pb
$PREFIX ./open-anchor-scriptsigs B-open.pb A-open.pb $B_TXINKEY > B-anchor-scriptsigs.pb
# Now A creates anchor (does not broadcast!)
$PREFIX ./create-anchor-tx A-open.pb B-open.pb $A_AMOUNT $A_CHANGEPUBKEY $A_TXIN > A-anchor.tx
# Now create commit signature
$PREFIX ./open-commit-sig A-open.pb B-open.pb $A_TMPKEY > A-commit-sig.pb
# Now A sends info about anchor output, and signature for commit tx.
$PREFIX ./open-anchor A-open.pb B-open.pb A-anchor.tx $A_TMPKEY > A-anchor.pb
$PREFIX ./open-commit-sig B-open.pb A-open.pb $B_TMPKEY > B-commit-sig.pb
# Now B signs commit sig for anchor.
$PREFIX ./open-commit-sig B-open.pb A-open.pb A-anchor.pb $B_TMPKEY > B-commit-sig.pb
# Now check it.
$PREFIX ./check-commit-sig A-open.pb B-open.pb B-commit-sig.pb $A_TMPKEY > A-commit.tx
$PREFIX ./check-commit-sig B-open.pb A-open.pb A-commit-sig.pb $B_TMPKEY > B-commit.tx
# Now check sigs.
$PREFIX ./check-commit-sig A-open.pb B-open.pb A-anchor.pb $A_TMPKEY B-commit-sig.pb
$PREFIX ./check-commit-sig B-open.pb A-open.pb A-anchor.pb $B_TMPKEY
# Now check anchor sigs and make sure they're the same.
$PREFIX ./check-anchor-scriptsigs A-open.pb B-open.pb A-anchor-scriptsigs.pb B-anchor-scriptsigs.pb > A-anchor.tx
$PREFIX ./check-anchor-scriptsigs B-open.pb A-open.pb B-anchor-scriptsigs.pb A-anchor-scriptsigs.pb > B-anchor.tx
cmp A-anchor.tx B-anchor.tx
# A broadcasts anchor
$CLI sendrawtransaction `cut -d: -f1 A-anchor.tx` > A-anchor.txid
# Broadcast
$CLI sendrawtransaction `cut -d: -f1 A-anchor.tx` > anchor.txid
# Wait for confirms
while [ 0$($CLI getrawtransaction $(cat A-anchor.txid) 1 | sed -n 's/.*"confirmations" : \([0-9]*\),/\1/p') -lt $($PREFIX ./get-anchor-depth A-open.pb) ]; do scripts/generate-block.sh; done
# # Wait for confirms
# while [ 0$($CLI getrawtransaction $(cat anchor.txid) 1 | sed -n 's/.*"confirmations" : \([0-9]*\),/\1/p') -lt $($PREFIX ./get-anchor-depth A-open.pb) ]; do scripts/generate-block.sh; done
while [ 0$($CLI getrawtransaction $(cat A-anchor.txid) 1 | sed -n 's/.*"confirmations" : \([0-9]*\),/\1/p') -lt $($PREFIX ./get-anchor-depth B-open.pb) ]; do scripts/generate-block.sh; done
# while [ 0$($CLI getrawtransaction $(cat anchor.txid) 1 | sed -n 's/.*"confirmations" : \([0-9]*\),/\1/p') -lt $($PREFIX ./get-anchor-depth B-open.pb) ]; do scripts/generate-block.sh; done
# Update traffic sent so far.
A_UPDATE_PKTS="-- -B-commit-sig.pb"
B_UPDATE_PKTS="-- +B-commit-sig.pb"
# Just for testing, generate the first transaction.
$PREFIX ./create-commit-tx A-anchor.tx A-open.pb B-open.pb $A_TMPKEY B-commit-sig.pb > A-commit-0.tx
# Just for testing, generate the first commit transactions.
$PREFIX ./create-commit-tx A-open.pb B-open.pb A-anchor.pb $A_TMPKEY $A_UPDATE_PKTS > A-commit-0.tx
$PREFIX ./create-commit-tx B-open.pb A-open.pb A-anchor.pb $B_TMPKEY $B_UPDATE_PKTS > B-commit-0.tx
# Now, update the channel, so I pay you 500 satoshi.
$PREFIX ./update-channel --to-them=500 $A_SEED > A-update-1.pb
$PREFIX ./update-channel-accept $B_SEED B-anchor.tx B-open.pb A-open.pb $B_TMPKEY A-update-1.pb > B-update-accept-1.pb
$PREFIX ./update-channel-signature $A_SEED A-anchor.tx A-open.pb B-open.pb $A_TMPKEY A-update-1.pb B-update-accept-1.pb > A-update-sig-1.pb
$PREFIX ./update-channel-complete $B_SEED B-anchor.tx B-open.pb A-open.pb A-update-1.pb A-update-sig-1.pb > B-update-complete-1.pb
$PREFIX ./update-channel --to-them=500 $A_SEED 1 > A-update-1.pb
A_UPDATE_PKTS="$A_UPDATE_PKTS +A-update-1.pb"
B_UPDATE_PKTS="$B_UPDATE_PKTS -A-update-1.pb"
$PREFIX ./update-channel-accept $B_SEED B-open.pb A-open.pb A-anchor.pb $B_TMPKEY $B_UPDATE_PKTS > B-update-accept-1.pb
A_UPDATE_PKTS="$A_UPDATE_PKTS -B-update-accept-1.pb"
B_UPDATE_PKTS="$B_UPDATE_PKTS +B-update-accept-1.pb"
$PREFIX ./update-channel-signature $A_SEED A-open.pb B-open.pb A-anchor.pb $A_TMPKEY $A_UPDATE_PKTS > A-update-sig-1.pb
A_UPDATE_PKTS="$A_UPDATE_PKTS +A-update-sig-1.pb"
B_UPDATE_PKTS="$B_UPDATE_PKTS -A-update-sig-1.pb"
$PREFIX ./update-channel-complete $B_SEED B-open.pb A-open.pb A-anchor.pb $B_UPDATE_PKTS > B-update-complete-1.pb
A_UPDATE_PKTS="$A_UPDATE_PKTS -B-update-complete-1.pb"
B_UPDATE_PKTS="$B_UPDATE_PKTS +B-update-complete-1.pb"
# Just for testing, generate second transaction
$PREFIX ./create-commit-tx A-anchor.tx A-open.pb B-open.pb $A_TMPKEY B-update-accept-1.pb A-update-1.pb > A-commit-1.tx
$PREFIX ./create-commit-tx A-open.pb B-open.pb A-anchor.pb $A_TMPKEY $A_UPDATE_PKTS > A-commit-1.tx
$PREFIX ./create-commit-tx B-open.pb A-open.pb A-anchor.pb $B_TMPKEY $B_UPDATE_PKTS > B-commit-1.tx
# Now you pay me 250.
$PREFIX ./update-channel --to-them=250 $B_SEED 2 > B-update-2.pb
A_UPDATE_PKTS="$A_UPDATE_PKTS -B-update-2.pb"
B_UPDATE_PKTS="$B_UPDATE_PKTS +B-update-2.pb"
$PREFIX ./update-channel-accept $A_SEED A-open.pb B-open.pb A-anchor.pb $A_TMPKEY $A_UPDATE_PKTS > A-update-accept-2.pb
A_UPDATE_PKTS="$A_UPDATE_PKTS +A-update-accept-2.pb"
B_UPDATE_PKTS="$B_UPDATE_PKTS -A-update-accept-2.pb"
$PREFIX ./update-channel-signature $B_SEED B-open.pb A-open.pb A-anchor.pb $B_TMPKEY $B_UPDATE_PKTS > B-update-sig-2.pb
A_UPDATE_PKTS="$A_UPDATE_PKTS -B-update-sig-2.pb"
B_UPDATE_PKTS="$B_UPDATE_PKTS +B-update-sig-2.pb"
# Now you pay me 1000.
$PREFIX ./update-channel --from-them=1000 $A_SEED A-update-1.pb > A-update-2.pb
$PREFIX ./update-channel-accept $B_SEED B-anchor.tx B-open.pb A-open.pb $B_TMPKEY A-update-2.pb A-update-1.pb > B-update-accept-2.pb 2>/dev/null
$PREFIX ./update-channel-signature $A_SEED A-anchor.tx A-open.pb B-open.pb $A_TMPKEY A-update-2.pb B-update-accept-2.pb A-update-1.pb > A-update-sig-2.pb
$PREFIX ./update-channel-complete $B_SEED B-anchor.tx B-open.pb A-open.pb A-update-2.pb A-update-sig-2.pb A-update-1.pb > B-update-complete-2.pb
$PREFIX ./update-channel-complete $A_SEED A-open.pb B-open.pb A-anchor.pb $A_UPDATE_PKTS > A-update-complete-2.pb
A_UPDATE_PKTS="$A_UPDATE_PKTS +A-update-complete-2.pb"
B_UPDATE_PKTS="$B_UPDATE_PKTS -A-update-complete-2.pb"
# Just for testing, generate third transaction
$PREFIX ./create-commit-tx A-anchor.tx A-open.pb B-open.pb $A_TMPKEY B-update-accept-2.pb A-update-1.pb A-update-2.pb > A-commit-2.tx
$PREFIX ./create-commit-tx A-open.pb B-open.pb A-anchor.pb $A_TMPKEY $A_UPDATE_PKTS > A-commit-2.tx
$PREFIX ./create-commit-tx B-open.pb A-open.pb A-anchor.pb $B_TMPKEY $B_UPDATE_PKTS > B-commit-2.tx
if [ x"$1" = x--steal ]; then
# A stupidly broadcasts a revoked transaction.
$CLI sendrawtransaction `cut -d: -f1 A-commit-1.tx` > A-commit-1.txid
# B uses the preimage from A-update-sig-2 to cash in.
$PREFIX ./create-steal-tx A-commit-1.tx A-update-sig-2.pb $B_FINALKEY B-open.pb A-open.pb $B_CHANGEPUBKEY > B-commit-steal.tx
# B uses the preimage from A-update-complete-2 to cash in.
$PREFIX ./create-steal-tx A-commit-1.tx A-update-complete-2.pb $B_FINALKEY B-open.pb A-open.pb $B_CHANGEPUBKEY > B-commit-steal.tx
$CLI sendrawtransaction `cut -d: -f1 B-commit-steal.tx` > B-commit-steal.txid
exit 0
@ -146,14 +169,14 @@ fi
if [ x"$1" = x--unilateral ]; then
$CLI sendrawtransaction `cut -d: -f1 A-commit-2.tx` > A-commit-2.txid
$PREFIX ./create-commit-spend-tx A-commit-2.tx A-open.pb B-open.pb $A_FINALKEY $A_CHANGEPUBKEY A-update-1.pb A-update-2.pb > A-spend.tx
$PREFIX ./create-commit-spend-tx A-commit-2.tx A-open.pb B-open.pb A-anchor.pb $A_FINALKEY $A_CHANGEPUBKEY $A_UPDATE_PKTS > A-spend.tx
send_after_delay `cut -d: -f1 A-spend.tx` > A-spend.txid
exit 0
fi
# Now close channel by mutual consent.
$PREFIX ./close-channel A-anchor.tx A-open.pb B-open.pb $A_TMPKEY A-update-1.pb A-update-2.pb > A-close.pb
$PREFIX ./close-channel --complete B-anchor.tx B-open.pb A-open.pb $B_TMPKEY A-update-1.pb A-update-2.pb > B-close-complete.pb
$PREFIX ./create-close-tx A-anchor.tx A-open.pb B-open.pb A-close.pb B-close-complete.pb A-update-1.pb A-update-2.pb > A-close.tx
$PREFIX ./close-channel A-open.pb B-open.pb A-anchor.pb $A_TMPKEY $A_UPDATE_PKTS > A-close.pb
$PREFIX ./close-channel --complete B-open.pb A-open.pb A-anchor.pb $B_TMPKEY $B_UPDATE_PKTS > B-close-complete.pb
$PREFIX ./create-close-tx A-open.pb B-open.pb A-anchor.pb A-close.pb B-close-complete.pb $A_UPDATE_PKTS > A-close.tx
$CLI sendrawtransaction `cut -d: -f1 A-close.tx` > close.txid

42
test-cli/update-channel-accept.c

@ -6,7 +6,6 @@
#include <ccan/err/err.h>
#include <ccan/read_write_all/read_write_all.h>
#include "lightning.pb-c.h"
#include "anchor.h"
#include "bitcoin/base58.h"
#include "pkt.h"
#include "bitcoin/script.h"
@ -17,6 +16,7 @@
#include "bitcoin/privkey.h"
#include "find_p2sh_out.h"
#include "protobuf_convert.h"
#include "gather_updates.h"
#include <unistd.h>
int main(int argc, char *argv[])
@ -24,54 +24,48 @@ int main(int argc, char *argv[])
const tal_t *ctx = tal_arr(NULL, char, 0);
struct sha256 seed, revocation_hash, their_rhash;
OpenChannel *o1, *o2;
Update *update;
struct bitcoin_tx *anchor, *commit;
struct sha256_double anchor_txid;
OpenAnchor *a;
struct bitcoin_tx *commit;
struct pkt *pkt;
struct bitcoin_signature sig;
struct privkey privkey;
bool testnet;
uint64_t num_updates;
struct pubkey pubkey1, pubkey2;
u8 *redeemscript;
int64_t delta;
size_t i, p2sh_out;
uint64_t our_amount, their_amount;
err_set_progname(argv[0]);
opt_register_noarg("--help|-h", opt_usage_and_exit,
"<seed> <anchor-tx> <open-channel-file1> <open-channel-file2> <commit-privkey> <update-protobuf> [previous-updates]\n"
"<seed> <open-channel-file1> <open-channel-file2> <open-anchor-file> <commit-privkey> <all-updates...>\n"
"Accept a new update message",
"Print this message.");
opt_parse(&argc, argv, opt_log_stderr_exit);
if (argc < 6)
opt_usage_exit_fail("Expected 5+ arguments");
if (argc < 7)
opt_usage_exit_fail("Expected 6+ arguments");
if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed)))
errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]);
anchor = bitcoin_tx_from_file(ctx, argv[2]);
bitcoin_txid(anchor, &anchor_txid);
o1 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open;
o2 = pkt_from_file(argv[4], PKT__PKT_OPEN)->open;
o1 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open;
o2 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open;
a = pkt_from_file(argv[4], PKT__PKT_OPEN_ANCHOR)->open_anchor;
if (!key_from_base58(argv[5], strlen(argv[5]), &testnet, &privkey, &pubkey1))
errx(1, "Invalid private key '%s'", argv[5]);
if (!testnet)
errx(1, "Private key '%s' not on testnet!", argv[5]);
update = pkt_from_file(argv[6], PKT__PKT_UPDATE)->update;
/* Figure out cumulative delta since anchor. */
delta = update->delta;
for (i = 7; i < argc; i++) {
Update *u = pkt_from_file(argv[i], PKT__PKT_UPDATE)->update;
delta += u->delta;
}
num_updates = gather_updates(o1, o2, a, argv + 6,
&our_amount, &their_amount,
NULL, &their_rhash, NULL);
/* Get next revocation hash. */
shachain_from_seed(&seed, argc - 6, &revocation_hash);
shachain_from_seed(&seed, num_updates, &revocation_hash);
sha256(&revocation_hash,
revocation_hash.u.u8, sizeof(revocation_hash.u.u8));
@ -86,12 +80,10 @@ int main(int argc, char *argv[])
/* This is what the anchor pays to; figure out whick output. */
redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
p2sh_out = find_p2sh_out(anchor, redeemscript);
/* Now create THEIR new commitment tx to spend 2/2 output of anchor. */
proto_to_sha256(update->revocation_hash, &their_rhash);
commit = create_commit_tx(ctx, o2, o1, &their_rhash, delta,
&anchor_txid, p2sh_out);
commit = create_commit_tx(ctx, o2, o1, a, &their_rhash,
their_amount, our_amount);
/* If contributions don't exceed fees, this fails. */
if (!commit)

79
test-cli/update-channel-complete.c

@ -7,7 +7,6 @@
#include <ccan/read_write_all/read_write_all.h>
#include <ccan/structeq/structeq.h>
#include "lightning.pb-c.h"
#include "anchor.h"
#include "bitcoin/base58.h"
#include "pkt.h"
#include "bitcoin/script.h"
@ -17,28 +16,28 @@
#include "bitcoin/pubkey.h"
#include "find_p2sh_out.h"
#include "protobuf_convert.h"
#include "gather_updates.h"
#include "funding.h"
#include <unistd.h>
int main(int argc, char *argv[])
{
const tal_t *ctx = tal_arr(NULL, char, 0);
struct sha256 seed, revocation_hash, our_rhash, their_rhash, preimage;
struct sha256 seed, our_rhash, their_rhash, preimage;
OpenChannel *o1, *o2;
UpdateSignature *us;
Update *update;
OpenAnchor *a;
struct pkt *pkt;
struct bitcoin_tx *anchor, *commit;
struct bitcoin_tx *commit;
struct pubkey pubkey1, pubkey2;
size_t i, num_updates, p2sh_out;
struct sha256_double anchor_txid;
size_t num_updates;
struct bitcoin_signature sig;
int64_t delta;
uint64_t our_amount, their_amount;
u8 *redeemscript;
err_set_progname(argv[0]);
opt_register_noarg("--help|-h", opt_usage_and_exit,
"<seed> <anchor-tx> <open-channel-file1> <open-channel-file2> <update-protobuf> <update-signature-protobuf> [previous-updates]\n"
"<seed> <open-channel-file1> <open-channel-file2> <open-anchor-file> <all-previous-updates>\n"
"Create a new update-complete message",
"Print this message.");
@ -50,43 +49,18 @@ int main(int argc, char *argv[])
if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed)))
errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]);
anchor = bitcoin_tx_from_file(ctx, argv[2]);
bitcoin_txid(anchor, &anchor_txid);
o1 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open;
o2 = pkt_from_file(argv[4], PKT__PKT_OPEN)->open;
update = pkt_from_file(argv[5], PKT__PKT_UPDATE)->update;
us = pkt_from_file(argv[6], PKT__PKT_UPDATE_SIGNATURE)->update_signature;
/* We need last revocation hash (either in update or update-accept),
* and the delta */
proto_to_sha256(o2->revocation_hash, &revocation_hash);
num_updates = 0;
delta = update->delta;
for (i = 7; i < argc; i++) {
Pkt *p = any_pkt_from_file(argv[i]);
switch (p->pkt_case) {
case PKT__PKT_UPDATE:
proto_to_sha256(p->update->revocation_hash,
&revocation_hash);
delta += p->update->delta;
num_updates++;
break;
case PKT__PKT_UPDATE_ACCEPT:
if (i != argc - 1)
errx(1, "Only need last update_accept");
proto_to_sha256(p->update_accept->revocation_hash,
&revocation_hash);
break;
default:
errx(1, "Expected update/update-accept in %s", argv[i]);
}
}
o1 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open;
o2 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open;
a = pkt_from_file(argv[4], PKT__PKT_OPEN_ANCHOR)->open_anchor;
sig.stype = SIGHASH_ALL;
/* They gave us right preimage to match rhash of previous commit tx? */
proto_to_sha256(us->revocation_preimage, &preimage);
sha256(&their_rhash, preimage.u.u8, sizeof(preimage.u.u8));
if (!structeq(&their_rhash, &revocation_hash))
errx(1, "Their preimage was incorrect");
/* This also checks that preimage is correct! */
num_updates = gather_updates(o1, o2, a, argv + 5,
&our_amount, &their_amount,
&our_rhash, &their_rhash, &sig.sig);
if (num_updates < 1)
errx(1, "Expected at least one update!");
/* Get pubkeys */
if (!proto_to_pubkey(o1->commit_key, &pubkey1))
@ -94,28 +68,21 @@ int main(int argc, char *argv[])
if (!proto_to_pubkey(o2->commit_key, &pubkey2))
errx(1, "Invalid o2 commit pubkey");
/* This is what the anchor pays to; figure out whick output. */
/* This is what the anchor pays to. */
redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
p2sh_out = find_p2sh_out(anchor, redeemscript);
/* Check their signature signs our new commit tx correctly. */
shachain_from_seed(&seed, num_updates + 1, &preimage);
sha256(&our_rhash, &preimage, sizeof(preimage));
commit = create_commit_tx(ctx, o1, o2, &our_rhash, delta,
&anchor_txid, p2sh_out);
commit = create_commit_tx(ctx, o1, o2, a, &our_rhash,
our_amount, their_amount);
if (!commit)
errx(1, "Delta too large");
sig.stype = SIGHASH_ALL;
if (!proto_to_signature(us->sig, &sig.sig))
errx(1, "Invalid update-signature signature");
if (!check_tx_sig(commit, 0, redeemscript, tal_count(redeemscript),
&pubkey2, &sig))
errx(1, "Invalid signature.");
/* Hand over our preimage for previous tx. */
shachain_from_seed(&seed, num_updates, &preimage);
shachain_from_seed(&seed, num_updates - 1, &preimage);
pkt = update_complete_pkt(ctx, &preimage);
if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt)))
err(1, "Writing out packet");

61
test-cli/update-channel-signature.c

@ -6,7 +6,6 @@
#include <ccan/err/err.h>
#include <ccan/read_write_all/read_write_all.h>
#include "lightning.pb-c.h"
#include "anchor.h"
#include "bitcoin/base58.h"
#include "pkt.h"
#include "bitcoin/script.h"
@ -17,30 +16,29 @@
#include "bitcoin/privkey.h"
#include "find_p2sh_out.h"
#include "protobuf_convert.h"
#include "gather_updates.h"
#include <unistd.h>
int main(int argc, char *argv[])
{
const tal_t *ctx = tal_arr(NULL, char, 0);
struct sha256 seed, revocation_hash, preimage;
struct sha256 seed, preimage, our_rhash, their_rhash;
OpenChannel *o1, *o2;
UpdateAccept *ua;
Update *update;
struct bitcoin_tx *anchor, *commit;
struct sha256_double anchor_txid;
OpenAnchor *a;
struct bitcoin_tx *commit;
struct pkt *pkt;
struct bitcoin_signature sig;
struct privkey privkey;
bool testnet;
struct pubkey pubkey1, pubkey2;
u8 *redeemscript;
int64_t delta;
size_t i, p2sh_out;
uint64_t our_amount, their_amount;
uint64_t num_updates;
err_set_progname(argv[0]);
opt_register_noarg("--help|-h", opt_usage_and_exit,
"<seed> <anchor-tx> <open-channel-file1> <open-channel-file2> <commit-privkey> <update-protobuf> <update-accept-protobuf> [previous-updates]...\n"
"<seed> <open-channel-file1> <open-channel-file2> <open-anchor-file> <commit-privkey> <all-previous-updates>...\n"
"Create a new update-channel-signature message",
"Print this message.");
@ -52,32 +50,27 @@ int main(int argc, char *argv[])
if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed)))
errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]);
anchor = bitcoin_tx_from_file(ctx, argv[2]);
bitcoin_txid(anchor, &anchor_txid);
o1 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open;
o2 = pkt_from_file(argv[4], PKT__PKT_OPEN)->open;
o1 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open;
o2 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open;
a = pkt_from_file(argv[4], PKT__PKT_OPEN_ANCHOR)->open_anchor;
if (!key_from_base58(argv[5], strlen(argv[5]), &testnet, &privkey, &pubkey1))
errx(1, "Invalid private key '%s'", argv[5]);
if (!testnet)
errx(1, "Private key '%s' not on testnet!", argv[5]);
update = pkt_from_file(argv[6], PKT__PKT_UPDATE)->update;
ua = pkt_from_file(argv[7], PKT__PKT_UPDATE_ACCEPT)->update_accept;
sig.stype = SIGHASH_ALL;
if (!proto_to_signature(ua->sig, &sig.sig))
errx(1, "Invalid update signature");
/* Figure out cumulative delta since anchor. */
delta = 0;
for (i = 8; i < argc; i++) {
Update *u = pkt_from_file(argv[i], PKT__PKT_UPDATE)->update;
delta += u->delta;
}
num_updates = gather_updates(o1, o2, a, argv + 6,
&our_amount, &their_amount,
&our_rhash, &their_rhash, &sig.sig);
if (num_updates < 1)
errx(1, "Expected at least one update!");
/* Give up revocation preimage for old tx. */
shachain_from_seed(&seed, argc - 7 - 1, &preimage);
fprintf(stderr, "Giving up preimage %u\n", (unsigned)num_updates - 1);
shachain_from_seed(&seed, num_updates - 1, &preimage);
/* Get pubkeys */
if (!proto_to_pubkey(o1->commit_key, &pubkey2))
@ -88,16 +81,14 @@ int main(int argc, char *argv[])
if (!proto_to_pubkey(o2->commit_key, &pubkey2))
errx(1, "Invalid o2 commit pubkey");
/* This is what the anchor pays to; figure out whick output. */
/* This is what the anchor pays to. */
redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
p2sh_out = find_p2sh_out(anchor, redeemscript);
/* Check our new commit is signed correctly by them. */
proto_to_sha256(update->revocation_hash, &revocation_hash);
commit = create_commit_tx(ctx, o1, o2, &revocation_hash, delta,
&anchor_txid, p2sh_out);
commit = create_commit_tx(ctx, o1, o2, a, &our_rhash,
our_amount, their_amount);
if (!commit)
errx(1, "Delta too large");
errx(1, "Invalid packets");
/* Check their signature signs this input correctly. */
if (!check_tx_sig(commit, 0, redeemscript, tal_count(redeemscript),
@ -105,14 +96,10 @@ int main(int argc, char *argv[])
errx(1, "Invalid signature.");
/* Now create THEIR new commitment tx to spend 2/2 output of anchor. */
proto_to_sha256(ua->revocation_hash, &revocation_hash);
commit = create_commit_tx(ctx, o2, o1, &revocation_hash, -delta,
&anchor_txid,
find_p2sh_out(anchor, redeemscript));
/* If contributions don't exceed fees, this fails. */
commit = create_commit_tx(ctx, o2, o1, a, &their_rhash,
their_amount, our_amount);
if (!commit)
errx(1, "Delta too large");
errx(1, "Invalid packets");
/* Their pubkey must be valid */
if (!proto_to_pubkey(o2->commit_key, &pubkey2))

15
test-cli/update-channel.c

@ -6,7 +6,6 @@
#include <ccan/err/err.h>
#include <ccan/read_write_all/read_write_all.h>
#include "lightning.pb-c.h"
#include "anchor.h"
#include "bitcoin/base58.h"
#include "pkt.h"
#include "bitcoin/script.h"
@ -24,11 +23,12 @@ int main(int argc, char *argv[])
struct pkt *pkt;
unsigned long long to_them = 0, from_them = 0;
int64_t this_delta;
unsigned update_num;
err_set_progname(argv[0]);
opt_register_noarg("--help|-h", opt_usage_and_exit,
"<seed> [previous-updates]\n"
"<seed> <update-number>\n"
"Create a new update message",
"Print this message.");
opt_register_arg("--to-them=<satoshi>",
@ -43,18 +43,21 @@ int main(int argc, char *argv[])
if (!from_them && !to_them)
opt_usage_exit_fail("Must use --to-them or --from-them");
if (argc < 2)
opt_usage_exit_fail("Expected 1+ arguments");
if (argc != 3)
opt_usage_exit_fail("Expected 2 arguments");
if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed)))
errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]);
update_num = atoi(argv[2]);
if (!update_num)
errx(1, "Update number %s invalid", argv[2]);
this_delta = from_them - to_them;
if (!this_delta)
errx(1, "Delta must not be zero");
/* Get next revocation hash. */
shachain_from_seed(&seed, argc - 2 + 1, &revocation_hash);
shachain_from_seed(&seed, update_num, &revocation_hash);
sha256(&revocation_hash,
revocation_hash.u.u8, sizeof(revocation_hash.u.u8));

Loading…
Cancel
Save