mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-17 19:03:42 +01:00
protocol: fix horribly thinko, keep own secrets.
I had each side using the other side's hash secret. That's a very dumb idea, since it means you can steal from a unilateral close! A's secret applies to A's commit transaction: it needs the secret and B's final signature to steal funds, and that should never happen (since A doesn't have the B's final signature, and once A has given B the secret, they never broadcast the commit tx). This makes the update a 4 step dance, since you need the new revocation hash to make the other side's TX to sign. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
9caf2c71e8
commit
ed3f0115d6
2
Makefile
2
Makefile
@ -3,7 +3,7 @@
|
||||
# Needs to have oneof support: Ubuntu vivid's is too old :(
|
||||
PROTOCC:=protoc-c
|
||||
|
||||
PROGRAMS := open-channel open-anchor-scriptsigs leak-anchor-sigs open-commit-sig check-commit-sig check-anchor-scriptsigs get-anchor-depth create-steal-tx create-commit-spend-tx close-channel create-close-tx update-channel update-channel-accept update-channel-complete
|
||||
PROGRAMS := open-channel open-anchor-scriptsigs leak-anchor-sigs open-commit-sig check-commit-sig check-anchor-scriptsigs get-anchor-depth create-steal-tx create-commit-spend-tx close-channel create-close-tx update-channel update-channel-accept update-channel-signature update-channel-complete
|
||||
|
||||
HELPER_OBJS := base58.o lightning.pb-c.o shadouble.o pkt.o bitcoin_script.o permute_tx.o signature.o bitcoin_tx.o bitcoin_address.o anchor.o commit_tx.o pubkey.o opt_bits.o close_tx.o find_p2sh_out.o
|
||||
|
||||
|
@ -70,7 +70,7 @@ int main(int argc, char *argv[])
|
||||
anchor_txid(anchor, argv[5], argv[6], inmap, &txid);
|
||||
|
||||
/* Now create our commitment tx. */
|
||||
proto_to_sha256(o2->revocation_hash, &rhash);
|
||||
proto_to_sha256(o1->revocation_hash, &rhash);
|
||||
commit = create_commit_tx(ctx, o1, o2, &rhash, 0, &txid, outmap[0]);
|
||||
|
||||
/* If contributions don't exceed fees, this fails. */
|
||||
@ -87,7 +87,7 @@ int main(int argc, char *argv[])
|
||||
sig1.stype = SIGHASH_ALL;
|
||||
subscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
|
||||
sign_tx_input(ctx, commit, 0, subscript, tal_count(subscript),
|
||||
privkey, &sig1.sig);
|
||||
privkey, &pubkey1, &sig1.sig);
|
||||
|
||||
/* Signatures well-formed? */
|
||||
if (!proto_to_signature(cs2->sig, &sig2.sig))
|
||||
|
@ -91,7 +91,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
/* Sign it for them. */
|
||||
sign_tx_input(ctx, close_tx, 0, redeemscript, tal_count(redeemscript),
|
||||
privkey, &sig);
|
||||
privkey, &pubkey1, &sig);
|
||||
|
||||
if (complete)
|
||||
pkt = close_channel_complete_pkt(ctx, &sig);
|
||||
|
@ -105,7 +105,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
/* Now get signature, to set up input script. */
|
||||
if (!sign_tx_input(tx, tx, 0, redeemscript, tal_count(redeemscript),
|
||||
privkey, &sig.sig))
|
||||
privkey, &pubkey1, &sig.sig))
|
||||
errx(1, "Could not sign tx");
|
||||
sig.stype = SIGHASH_ALL;
|
||||
tx->input[0].script = scriptsig_p2sh_single_sig(tx, redeemscript,
|
||||
|
@ -94,7 +94,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
/* Now get signature, to set up input script. */
|
||||
if (!sign_tx_input(tx, tx, 0, redeemscript, tal_count(redeemscript),
|
||||
privkey, &sig.sig))
|
||||
privkey, &pubkey1, &sig.sig))
|
||||
errx(1, "Could not sign tx");
|
||||
sig.stype = SIGHASH_ALL;
|
||||
tx->input[0].script = scriptsig_p2sh_revoke(tx, &revoke, &sig,
|
||||
|
200
lightning.pb-c.c
200
lightning.pb-c.c
@ -566,6 +566,49 @@ void update_accept__free_unpacked
|
||||
assert(message->base.descriptor == &update_accept__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void update_signature__init
|
||||
(UpdateSignature *message)
|
||||
{
|
||||
static UpdateSignature init_value = UPDATE_SIGNATURE__INIT;
|
||||
*message = init_value;
|
||||
}
|
||||
size_t update_signature__get_packed_size
|
||||
(const UpdateSignature *message)
|
||||
{
|
||||
assert(message->base.descriptor == &update_signature__descriptor);
|
||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
||||
}
|
||||
size_t update_signature__pack
|
||||
(const UpdateSignature *message,
|
||||
uint8_t *out)
|
||||
{
|
||||
assert(message->base.descriptor == &update_signature__descriptor);
|
||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
||||
}
|
||||
size_t update_signature__pack_to_buffer
|
||||
(const UpdateSignature *message,
|
||||
ProtobufCBuffer *buffer)
|
||||
{
|
||||
assert(message->base.descriptor == &update_signature__descriptor);
|
||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
||||
}
|
||||
UpdateSignature *
|
||||
update_signature__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data)
|
||||
{
|
||||
return (UpdateSignature *)
|
||||
protobuf_c_message_unpack (&update_signature__descriptor,
|
||||
allocator, len, data);
|
||||
}
|
||||
void update_signature__free_unpacked
|
||||
(UpdateSignature *message,
|
||||
ProtobufCAllocator *allocator)
|
||||
{
|
||||
assert(message->base.descriptor == &update_signature__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void update_complete__init
|
||||
(UpdateComplete *message)
|
||||
{
|
||||
@ -1743,7 +1786,7 @@ const ProtobufCMessageDescriptor open_complete__descriptor =
|
||||
(ProtobufCMessageInit) open_complete__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor update__field_descriptors[4] =
|
||||
static const ProtobufCFieldDescriptor update__field_descriptors[2] =
|
||||
{
|
||||
{
|
||||
"revocation_hash",
|
||||
@ -1769,41 +1812,15 @@ static const ProtobufCFieldDescriptor update__field_descriptors[4] =
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"sig",
|
||||
3,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(Update, sig),
|
||||
&signature__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"old_anchor_sig",
|
||||
4,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(Update, old_anchor_sig),
|
||||
&signature__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned update__field_indices_by_name[] = {
|
||||
1, /* field[1] = delta */
|
||||
3, /* field[3] = old_anchor_sig */
|
||||
0, /* field[0] = revocation_hash */
|
||||
2, /* field[2] = sig */
|
||||
};
|
||||
static const ProtobufCIntRange update__number_ranges[1 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 0, 4 }
|
||||
{ 0, 2 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor update__descriptor =
|
||||
{
|
||||
@ -1813,14 +1830,14 @@ const ProtobufCMessageDescriptor update__descriptor =
|
||||
"Update",
|
||||
"",
|
||||
sizeof(Update),
|
||||
4,
|
||||
2,
|
||||
update__field_descriptors,
|
||||
update__field_indices_by_name,
|
||||
1, update__number_ranges,
|
||||
(ProtobufCMessageInit) update__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor update_accept__field_descriptors[4] =
|
||||
static const ProtobufCFieldDescriptor update_accept__field_descriptors[3] =
|
||||
{
|
||||
{
|
||||
"sig",
|
||||
@ -1858,29 +1875,16 @@ static const ProtobufCFieldDescriptor update_accept__field_descriptors[4] =
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"revocation_preimage",
|
||||
4,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(UpdateAccept, revocation_preimage),
|
||||
&sha256_hash__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned update_accept__field_indices_by_name[] = {
|
||||
1, /* field[1] = old_anchor_sig */
|
||||
2, /* field[2] = revocation_hash */
|
||||
3, /* field[3] = revocation_preimage */
|
||||
0, /* field[0] = sig */
|
||||
};
|
||||
static const ProtobufCIntRange update_accept__number_ranges[1 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 0, 4 }
|
||||
{ 0, 3 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor update_accept__descriptor =
|
||||
{
|
||||
@ -1890,13 +1894,64 @@ const ProtobufCMessageDescriptor update_accept__descriptor =
|
||||
"UpdateAccept",
|
||||
"",
|
||||
sizeof(UpdateAccept),
|
||||
4,
|
||||
3,
|
||||
update_accept__field_descriptors,
|
||||
update_accept__field_indices_by_name,
|
||||
1, update_accept__number_ranges,
|
||||
(ProtobufCMessageInit) update_accept__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor update_signature__field_descriptors[2] =
|
||||
{
|
||||
{
|
||||
"sig",
|
||||
1,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(UpdateSignature, sig),
|
||||
&signature__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"revocation_preimage",
|
||||
2,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(UpdateSignature, revocation_preimage),
|
||||
&sha256_hash__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned update_signature__field_indices_by_name[] = {
|
||||
1, /* field[1] = revocation_preimage */
|
||||
0, /* field[0] = sig */
|
||||
};
|
||||
static const ProtobufCIntRange update_signature__number_ranges[1 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 0, 2 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor update_signature__descriptor =
|
||||
{
|
||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||
"update_signature",
|
||||
"UpdateSignature",
|
||||
"UpdateSignature",
|
||||
"",
|
||||
sizeof(UpdateSignature),
|
||||
2,
|
||||
update_signature__field_descriptors,
|
||||
update_signature__field_indices_by_name,
|
||||
1, update_signature__number_ranges,
|
||||
(ProtobufCMessageInit) update_signature__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor update_complete__field_descriptors[1] =
|
||||
{
|
||||
{
|
||||
@ -2239,7 +2294,7 @@ const ProtobufCMessageDescriptor error__descriptor =
|
||||
(ProtobufCMessageInit) error__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor pkt__field_descriptors[15] =
|
||||
static const ProtobufCFieldDescriptor pkt__field_descriptors[16] =
|
||||
{
|
||||
{
|
||||
"update",
|
||||
@ -2266,11 +2321,23 @@ static const ProtobufCFieldDescriptor pkt__field_descriptors[15] =
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"update_complete",
|
||||
"update_signature",
|
||||
3,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
offsetof(Pkt, pkt_case),
|
||||
offsetof(Pkt, update_signature),
|
||||
&update_signature__descriptor,
|
||||
NULL,
|
||||
0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"update_complete",
|
||||
4,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
offsetof(Pkt, pkt_case),
|
||||
offsetof(Pkt, update_complete),
|
||||
&update_complete__descriptor,
|
||||
NULL,
|
||||
@ -2423,30 +2490,31 @@ static const ProtobufCFieldDescriptor pkt__field_descriptors[15] =
|
||||
},
|
||||
};
|
||||
static const unsigned pkt__field_indices_by_name[] = {
|
||||
12, /* field[12] = close */
|
||||
13, /* field[13] = close_complete */
|
||||
14, /* field[14] = error */
|
||||
8, /* field[8] = new_anchor */
|
||||
10, /* field[10] = new_anchor_accept */
|
||||
9, /* field[9] = new_anchor_ack */
|
||||
11, /* field[11] = new_anchor_complete */
|
||||
7, /* field[7] = omg_fail */
|
||||
3, /* field[3] = open */
|
||||
5, /* field[5] = open_anchor_scriptsigs */
|
||||
4, /* field[4] = open_commit_sig */
|
||||
6, /* field[6] = open_complete */
|
||||
13, /* field[13] = close */
|
||||
14, /* field[14] = close_complete */
|
||||
15, /* field[15] = error */
|
||||
9, /* field[9] = new_anchor */
|
||||
11, /* field[11] = new_anchor_accept */
|
||||
10, /* field[10] = new_anchor_ack */
|
||||
12, /* field[12] = new_anchor_complete */
|
||||
8, /* field[8] = omg_fail */
|
||||
4, /* field[4] = open */
|
||||
6, /* field[6] = open_anchor_scriptsigs */
|
||||
5, /* field[5] = open_commit_sig */
|
||||
7, /* field[7] = open_complete */
|
||||
0, /* field[0] = update */
|
||||
1, /* field[1] = update_accept */
|
||||
2, /* field[2] = update_complete */
|
||||
3, /* field[3] = update_complete */
|
||||
2, /* field[2] = update_signature */
|
||||
};
|
||||
static const ProtobufCIntRange pkt__number_ranges[5 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 201, 3 },
|
||||
{ 301, 8 },
|
||||
{ 401, 12 },
|
||||
{ 1000, 14 },
|
||||
{ 0, 15 }
|
||||
{ 201, 4 },
|
||||
{ 301, 9 },
|
||||
{ 401, 13 },
|
||||
{ 1000, 15 },
|
||||
{ 0, 16 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor pkt__descriptor =
|
||||
{
|
||||
@ -2456,7 +2524,7 @@ const ProtobufCMessageDescriptor pkt__descriptor =
|
||||
"Pkt",
|
||||
"",
|
||||
sizeof(Pkt),
|
||||
15,
|
||||
16,
|
||||
pkt__field_descriptors,
|
||||
pkt__field_indices_by_name,
|
||||
5, pkt__number_ranges,
|
||||
|
@ -28,6 +28,7 @@ typedef struct _LeakAnchorSigsAndPretendWeDidnt LeakAnchorSigsAndPretendWeDidnt;
|
||||
typedef struct _OpenComplete OpenComplete;
|
||||
typedef struct _Update Update;
|
||||
typedef struct _UpdateAccept UpdateAccept;
|
||||
typedef struct _UpdateSignature UpdateSignature;
|
||||
typedef struct _UpdateComplete UpdateComplete;
|
||||
typedef struct _NewAnchor NewAnchor;
|
||||
typedef struct _NewAnchorAck NewAnchorAck;
|
||||
@ -291,32 +292,24 @@ struct _Update
|
||||
/*
|
||||
* Change in current payment to-me (implies reverse to-you).
|
||||
*/
|
||||
int64_t delta;
|
||||
/*
|
||||
* Signature for new commitment tx.
|
||||
*/
|
||||
Signature *sig;
|
||||
/*
|
||||
* Signature for old anchor (if any)
|
||||
*/
|
||||
/*
|
||||
* FIXME: optional HTLC ops.
|
||||
*/
|
||||
Signature *old_anchor_sig;
|
||||
int64_t delta;
|
||||
};
|
||||
#define UPDATE__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&update__descriptor) \
|
||||
, NULL, 0, NULL, NULL }
|
||||
, NULL, 0 }
|
||||
|
||||
|
||||
/*
|
||||
* OK, I accept that update.
|
||||
* OK, I accept that update; here's your signature.
|
||||
*/
|
||||
struct _UpdateAccept
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
/*
|
||||
* Signature for new commitment tx.
|
||||
* Signature for your new commitment tx.
|
||||
*/
|
||||
Signature *sig;
|
||||
/*
|
||||
@ -327,14 +320,30 @@ struct _UpdateAccept
|
||||
* Hash for which I will supply preimage to revoke this new commit tx.
|
||||
*/
|
||||
Sha256Hash *revocation_hash;
|
||||
};
|
||||
#define UPDATE_ACCEPT__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&update_accept__descriptor) \
|
||||
, NULL, NULL, NULL }
|
||||
|
||||
|
||||
/*
|
||||
* Thanks for accepting, here's my last bit.
|
||||
*/
|
||||
struct _UpdateSignature
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
/*
|
||||
* Signature for your new commitment tx.
|
||||
*/
|
||||
Signature *sig;
|
||||
/*
|
||||
* Hash preimage which revokes old commitment tx.
|
||||
*/
|
||||
Sha256Hash *revocation_preimage;
|
||||
};
|
||||
#define UPDATE_ACCEPT__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&update_accept__descriptor) \
|
||||
, NULL, NULL, NULL, NULL }
|
||||
#define UPDATE_SIGNATURE__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&update_signature__descriptor) \
|
||||
, NULL, NULL }
|
||||
|
||||
|
||||
/*
|
||||
@ -479,7 +488,8 @@ typedef enum {
|
||||
PKT__PKT_OPEN_COMPLETE = 204,
|
||||
PKT__PKT_UPDATE = 1,
|
||||
PKT__PKT_UPDATE_ACCEPT = 2,
|
||||
PKT__PKT_UPDATE_COMPLETE = 3,
|
||||
PKT__PKT_UPDATE_SIGNATURE = 3,
|
||||
PKT__PKT_UPDATE_COMPLETE = 4,
|
||||
PKT__PKT_NEW_ANCHOR = 301,
|
||||
PKT__PKT_NEW_ANCHOR_ACK = 302,
|
||||
PKT__PKT_NEW_ANCHOR_ACCEPT = 303,
|
||||
@ -510,6 +520,7 @@ struct _Pkt
|
||||
*/
|
||||
Update *update;
|
||||
UpdateAccept *update_accept;
|
||||
UpdateSignature *update_signature;
|
||||
UpdateComplete *update_complete;
|
||||
/*
|
||||
* Topping up
|
||||
@ -781,6 +792,25 @@ UpdateAccept *
|
||||
void update_accept__free_unpacked
|
||||
(UpdateAccept *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* UpdateSignature methods */
|
||||
void update_signature__init
|
||||
(UpdateSignature *message);
|
||||
size_t update_signature__get_packed_size
|
||||
(const UpdateSignature *message);
|
||||
size_t update_signature__pack
|
||||
(const UpdateSignature *message,
|
||||
uint8_t *out);
|
||||
size_t update_signature__pack_to_buffer
|
||||
(const UpdateSignature *message,
|
||||
ProtobufCBuffer *buffer);
|
||||
UpdateSignature *
|
||||
update_signature__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data);
|
||||
void update_signature__free_unpacked
|
||||
(UpdateSignature *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* UpdateComplete methods */
|
||||
void update_complete__init
|
||||
(UpdateComplete *message);
|
||||
@ -1012,6 +1042,9 @@ typedef void (*Update_Closure)
|
||||
typedef void (*UpdateAccept_Closure)
|
||||
(const UpdateAccept *message,
|
||||
void *closure_data);
|
||||
typedef void (*UpdateSignature_Closure)
|
||||
(const UpdateSignature *message,
|
||||
void *closure_data);
|
||||
typedef void (*UpdateComplete_Closure)
|
||||
(const UpdateComplete *message,
|
||||
void *closure_data);
|
||||
@ -1061,6 +1094,7 @@ extern const ProtobufCMessageDescriptor leak_anchor_sigs_and_pretend_we_didnt__d
|
||||
extern const ProtobufCMessageDescriptor open_complete__descriptor;
|
||||
extern const ProtobufCMessageDescriptor update__descriptor;
|
||||
extern const ProtobufCMessageDescriptor update_accept__descriptor;
|
||||
extern const ProtobufCMessageDescriptor update_signature__descriptor;
|
||||
extern const ProtobufCMessageDescriptor update_complete__descriptor;
|
||||
extern const ProtobufCMessageDescriptor new_anchor__descriptor;
|
||||
extern const ProtobufCMessageDescriptor new_anchor_ack__descriptor;
|
||||
|
@ -121,23 +121,25 @@ message update {
|
||||
required sha256_hash revocation_hash = 1;
|
||||
// Change in current payment to-me (implies reverse to-you).
|
||||
required sint64 delta = 2;
|
||||
// Signature for new commitment tx.
|
||||
required signature sig = 3;
|
||||
// Signature for old anchor (if any)
|
||||
optional signature old_anchor_sig = 4;
|
||||
// FIXME: optional HTLC ops.
|
||||
}
|
||||
|
||||
// OK, I accept that update.
|
||||
// OK, I accept that update; here's your signature.
|
||||
message update_accept {
|
||||
// Signature for new commitment tx.
|
||||
// Signature for your new commitment tx.
|
||||
required signature sig = 1;
|
||||
// Signature for old anchor (if any)
|
||||
optional signature old_anchor_sig = 2;
|
||||
// Hash for which I will supply preimage to revoke this new commit tx.
|
||||
required sha256_hash revocation_hash = 3;
|
||||
}
|
||||
|
||||
// Thanks for accepting, here's my last bit.
|
||||
message update_signature {
|
||||
// Signature for your new commitment tx.
|
||||
required signature sig = 1;
|
||||
// Hash preimage which revokes old commitment tx.
|
||||
required sha256_hash revocation_preimage = 4;
|
||||
required sha256_hash revocation_preimage = 2;
|
||||
}
|
||||
|
||||
// Complete the update.
|
||||
@ -204,7 +206,8 @@ message pkt {
|
||||
// Updating (most common)
|
||||
update update = 1;
|
||||
update_accept update_accept = 2;
|
||||
update_complete update_complete = 3;
|
||||
update_signature update_signature = 3;
|
||||
update_complete update_complete = 4;
|
||||
// Topping up
|
||||
new_anchor new_anchor = 301;
|
||||
new_anchor_ack new_anchor_ack = 302;
|
||||
|
@ -31,7 +31,7 @@ static u8 *tx_scriptsig(const tal_t *ctx,
|
||||
sig.stype = SIGHASH_ALL;
|
||||
if (!sign_tx_input(ctx, tx, i,
|
||||
input->subscript.data, input->subscript.len,
|
||||
privkey, &sig.sig))
|
||||
privkey, pubkey, &sig.sig))
|
||||
return NULL;
|
||||
|
||||
if (!is_pay_to_pubkey_hash(input->subscript.data, input->subscript.len))
|
||||
|
@ -66,7 +66,7 @@ int main(int argc, char *argv[])
|
||||
anchor_txid(anchor, argv[4], argv[5], inmap, &txid);
|
||||
|
||||
/* Now create THEIR commitment tx to spend 2/2 output of anchor. */
|
||||
proto_to_sha256(o1->revocation_hash, &rhash);
|
||||
proto_to_sha256(o2->revocation_hash, &rhash);
|
||||
commit = create_commit_tx(ctx, o2, o1, &rhash, 0, &txid, outmap[0]);
|
||||
|
||||
/* If contributions don't exceed fees, this fails. */
|
||||
@ -84,7 +84,7 @@ int main(int argc, char *argv[])
|
||||
/* Sign it for them. */
|
||||
subscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
|
||||
sign_tx_input(ctx, commit, 0, subscript, tal_count(subscript),
|
||||
privkey, &sig);
|
||||
privkey, &pubkey1, &sig);
|
||||
|
||||
pkt = open_commit_sig_pkt(ctx, &sig);
|
||||
if (!write_all(STDOUT_FILENO, pkt,
|
||||
|
17
pkt.c
17
pkt.c
@ -161,27 +161,34 @@ struct pkt *close_channel_complete_pkt(const tal_t *ctx,
|
||||
|
||||
struct pkt *update_pkt(const tal_t *ctx,
|
||||
const struct sha256 *revocation_hash,
|
||||
s64 delta, struct signature *sig)
|
||||
s64 delta)
|
||||
{
|
||||
Update u = UPDATE__INIT;
|
||||
u.revocation_hash = sha256_to_proto(ctx, revocation_hash);
|
||||
u.delta = delta;
|
||||
u.sig = signature_to_proto(ctx, sig);
|
||||
return to_pkt(ctx, PKT__PKT_UPDATE, &u);
|
||||
}
|
||||
|
||||
struct pkt *update_accept_pkt(const tal_t *ctx,
|
||||
struct signature *sig,
|
||||
const struct sha256 *revocation_hash,
|
||||
const struct sha256 *revocation_preimage)
|
||||
const struct sha256 *revocation_hash)
|
||||
{
|
||||
UpdateAccept ua = UPDATE_ACCEPT__INIT;
|
||||
ua.sig = signature_to_proto(ctx, sig);
|
||||
ua.revocation_hash = sha256_to_proto(ctx, revocation_hash);
|
||||
ua.revocation_preimage = sha256_to_proto(ctx, revocation_preimage);
|
||||
return to_pkt(ctx, PKT__PKT_UPDATE_ACCEPT, &ua);
|
||||
}
|
||||
|
||||
struct pkt *update_signature_pkt(const tal_t *ctx,
|
||||
const struct signature *sig,
|
||||
const struct sha256 *revocation_preimage)
|
||||
{
|
||||
UpdateSignature us = UPDATE_SIGNATURE__INIT;
|
||||
us.sig = signature_to_proto(ctx, sig);
|
||||
us.revocation_preimage = sha256_to_proto(ctx, revocation_preimage);
|
||||
return to_pkt(ctx, PKT__PKT_UPDATE_SIGNATURE, &us);
|
||||
}
|
||||
|
||||
struct pkt *update_complete_pkt(const tal_t *ctx,
|
||||
const struct sha256 *revocation_preimage)
|
||||
{
|
||||
|
16
pkt.h
16
pkt.h
@ -87,24 +87,30 @@ struct pkt *close_channel_complete_pkt(const tal_t *ctx,
|
||||
* @ctx: tal context to allocate off.
|
||||
* @revocation_hash: the revocation hash for the next tx.
|
||||
* @delta: the change in satoshis (to me).
|
||||
* @sig: the signature for the close transaction input.
|
||||
*/
|
||||
struct pkt *update_pkt(const tal_t *ctx,
|
||||
const struct sha256 *revocation_hash,
|
||||
s64 delta, struct signature *sig);
|
||||
s64 delta);
|
||||
|
||||
/**
|
||||
* update_accept_pkt - create an update_accept message
|
||||
* @ctx: tal context to allocate off.
|
||||
* @sig: the signature for the close transaction input.
|
||||
* @revocation_hash: hash to revoke the next tx.
|
||||
* @revocation_preimage: preimage to revoke existing (now-obsolete) tx.
|
||||
*/
|
||||
struct pkt *update_accept_pkt(const tal_t *ctx,
|
||||
struct signature *sig,
|
||||
const struct sha256 *revocation_hash,
|
||||
const struct sha256 *revocation_preimage);
|
||||
const struct sha256 *revocation_hash);
|
||||
|
||||
/**
|
||||
* update_signature_pkt - create an update_signature message
|
||||
* @ctx: tal context to allocate off.
|
||||
* @sig: the signature for the close transaction input.
|
||||
* @revocation_preimage: preimage to revoke existing (now-obsolete) tx.
|
||||
*/
|
||||
struct pkt *update_signature_pkt(const tal_t *ctx,
|
||||
const struct signature *sig,
|
||||
const struct sha256 *revocation_preimage);
|
||||
/**
|
||||
* update_complete_pkt - create an update_accept message
|
||||
* @ctx: tal context to allocate off.
|
||||
|
68
signature.c
68
signature.c
@ -8,6 +8,62 @@
|
||||
#include <assert.h>
|
||||
#include <ccan/cast/cast.h>
|
||||
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
#include <ccan/err/err.h>
|
||||
#define SHA_FMT \
|
||||
"%02x%02x%02x%02x%02x%02x%02x%02x" \
|
||||
"%02x%02x%02x%02x%02x%02x%02x%02x" \
|
||||
"%02x%02x%02x%02x%02x%02x%02x%02x" \
|
||||
"%02x%02x%02x%02x%02x%02x%02x%02x"
|
||||
|
||||
#define SHA_VALS(e) \
|
||||
e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7], \
|
||||
e[8], e[9], e[10], e[11], e[12], e[13], e[14], e[15], \
|
||||
e[16], e[17], e[18], e[19], e[20], e[21], e[22], e[23], \
|
||||
e[24], e[25], e[25], e[26], e[28], e[29], e[30], e[31]
|
||||
|
||||
static void dump_tx(const char *msg,
|
||||
const struct bitcoin_tx *tx, size_t inputnum,
|
||||
const u8 *script, size_t script_len,
|
||||
const struct pubkey *key)
|
||||
{
|
||||
size_t i, j;
|
||||
warnx("%s tx version %u locktime %#x:",
|
||||
msg, tx->version, tx->lock_time);
|
||||
for (i = 0; i < tx->input_count; i++) {
|
||||
warnx("input[%zu].txid = "SHA_FMT, i,
|
||||
SHA_VALS(tx->input[i].txid.sha.u.u8));
|
||||
warnx("input[%zu].index = %u", i, tx->input[i].index);
|
||||
}
|
||||
for (i = 0; i < tx->output_count; i++) {
|
||||
warnx("output[%zu].amount = %llu",
|
||||
i, (long long)tx->output[i].amount);
|
||||
warnx("output[%zu].script = %llu",
|
||||
i, (long long)tx->output[i].script_length);
|
||||
for (j = 0; j < tx->output[i].script_length; j++)
|
||||
fprintf(stderr, "%02x", tx->output[i].script[j]);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
warnx("input[%zu].script = %zu", inputnum, script_len);
|
||||
for (i = 0; i < script_len; i++)
|
||||
fprintf(stderr, "%02x", script[i]);
|
||||
if (key) {
|
||||
fprintf(stderr, "\nPubkey: ");
|
||||
for (i = 0; i < pubkey_len(key); i++)
|
||||
fprintf(stderr, "%02x", key->key[i]);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void dump_tx(const char *msg,
|
||||
const struct bitcoin_tx *tx, size_t inputnum,
|
||||
const u8 *script, size_t script_len,
|
||||
const struct pubkey *key)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
bool sign_hash(const tal_t *ctx, EC_KEY *private_key,
|
||||
const struct sha256_double *h,
|
||||
struct signature *s)
|
||||
@ -82,11 +138,13 @@ static void sha256_tx_one_input(struct bitcoin_tx *tx,
|
||||
bool sign_tx_input(const tal_t *ctx, struct bitcoin_tx *tx,
|
||||
unsigned int in,
|
||||
const u8 *subscript, size_t subscript_len,
|
||||
EC_KEY *privkey, struct signature *sig)
|
||||
EC_KEY *privkey, const struct pubkey *key,
|
||||
struct signature *sig)
|
||||
{
|
||||
struct sha256_double hash;
|
||||
|
||||
sha256_tx_one_input(tx, in, subscript, subscript_len, &hash);
|
||||
dump_tx("Signing", tx, in, subscript, subscript_len, key);
|
||||
return sign_hash(ctx, privkey, &hash, sig);
|
||||
}
|
||||
|
||||
@ -142,6 +200,8 @@ bool check_tx_sig(struct bitcoin_tx *tx, size_t input_num,
|
||||
const struct bitcoin_signature *sig)
|
||||
{
|
||||
struct sha256_double hash;
|
||||
bool ret;
|
||||
|
||||
assert(input_num < tx->input_count);
|
||||
|
||||
sha256_tx_one_input(tx, input_num, redeemscript, redeemscript_len,
|
||||
@ -151,7 +211,11 @@ bool check_tx_sig(struct bitcoin_tx *tx, size_t input_num,
|
||||
if (sig->stype != SIGHASH_ALL)
|
||||
return false;
|
||||
|
||||
return check_signed_hash(&hash, &sig->sig, key);
|
||||
ret = check_signed_hash(&hash, &sig->sig, key);
|
||||
if (!ret)
|
||||
dump_tx("Sig failed", tx, input_num,
|
||||
redeemscript, redeemscript_len, key);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool check_2of2_sig(struct bitcoin_tx *tx, size_t input_num,
|
||||
|
@ -32,7 +32,8 @@ bool sign_hash(const tal_t *ctx, EC_KEY *private_key,
|
||||
bool sign_tx_input(const tal_t *ctx, struct bitcoin_tx *tx,
|
||||
unsigned int in,
|
||||
const u8 *subscript, size_t subscript_len,
|
||||
EC_KEY *privkey, struct signature *sig);
|
||||
EC_KEY *privkey, const struct pubkey *pubkey,
|
||||
struct signature *sig);
|
||||
|
||||
/* Does this sig sign the tx with this input for this pubkey. */
|
||||
bool check_tx_sig(struct bitcoin_tx *tx, size_t input_num,
|
||||
|
@ -24,7 +24,7 @@
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const tal_t *ctx = tal_arr(NULL, char, 0);
|
||||
struct sha256 seed, revocation_hash, revocation_preimage, their_rhash;
|
||||
struct sha256 seed, revocation_hash, their_rhash;
|
||||
OpenChannel *o1, *o2;
|
||||
Update *update;
|
||||
struct bitcoin_tx *anchor, *commit;
|
||||
@ -66,10 +66,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
update = pkt_from_file(argv[6], PKT__PKT_UPDATE)->update;
|
||||
|
||||
sig.stype = SIGHASH_ALL;
|
||||
if (!proto_to_signature(update->sig, &sig.sig))
|
||||
errx(1, "Invalid update signature");
|
||||
|
||||
/* Figure out cumulative delta since anchor. */
|
||||
delta = update->delta;
|
||||
for (i = 7; i < argc; i++) {
|
||||
@ -95,20 +91,9 @@ int main(int argc, char *argv[])
|
||||
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, &their_rhash);
|
||||
commit = create_commit_tx(ctx, o1, o2, &their_rhash, delta,
|
||||
&anchor_txid, p2sh_out);
|
||||
if (!commit)
|
||||
errx(1, "Delta too large");
|
||||
|
||||
/* Check their signature signs this input correctly. */
|
||||
if (!check_tx_sig(commit, 0, redeemscript, tal_count(redeemscript),
|
||||
&pubkey2, &sig))
|
||||
errx(1, "Invalid signature.");
|
||||
|
||||
/* Now create THEIR new commitment tx to spend 2/2 output of anchor. */
|
||||
commit = create_commit_tx(ctx, o2, o1, &revocation_hash, delta,
|
||||
proto_to_sha256(update->revocation_hash, &their_rhash);
|
||||
commit = create_commit_tx(ctx, o2, o1, &their_rhash, delta,
|
||||
&anchor_txid, p2sh_out);
|
||||
|
||||
/* If contributions don't exceed fees, this fails. */
|
||||
@ -117,13 +102,9 @@ int main(int argc, char *argv[])
|
||||
|
||||
/* Sign it for them. */
|
||||
sign_tx_input(ctx, commit, 0, redeemscript, tal_count(redeemscript),
|
||||
privkey, &sig.sig);
|
||||
privkey, &pubkey1, &sig.sig);
|
||||
|
||||
/* Give up revocation preimage for old tx. */
|
||||
shachain_from_seed(&seed, argc - 6 - 1, &revocation_preimage);
|
||||
|
||||
pkt = update_accept_pkt(ctx, &sig.sig,
|
||||
&revocation_hash, &revocation_preimage);
|
||||
pkt = update_accept_pkt(ctx, &sig.sig, &revocation_hash);
|
||||
if (!write_all(STDOUT_FILENO, pkt,
|
||||
sizeof(pkt->len) + le32_to_cpu(pkt->len)))
|
||||
err(1, "Writing out packet");
|
||||
|
@ -25,9 +25,10 @@
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const tal_t *ctx = tal_arr(NULL, char, 0);
|
||||
struct sha256 seed, revocation_hash, their_rhash, preimage;
|
||||
struct sha256 seed, revocation_hash, our_rhash, their_rhash, preimage;
|
||||
OpenChannel *o1, *o2;
|
||||
UpdateAccept *ua;
|
||||
UpdateSignature *us;
|
||||
Update *update;
|
||||
struct pkt *pkt;
|
||||
struct bitcoin_tx *anchor, *commit;
|
||||
struct pubkey pubkey1, pubkey2;
|
||||
@ -40,14 +41,14 @@ int main(int argc, char *argv[])
|
||||
err_set_progname(argv[0]);
|
||||
|
||||
opt_register_noarg("--help|-h", opt_usage_and_exit,
|
||||
"<seed> <anchor-tx> <open-channel-file1> <open-channel-file2> <update-accept> [previous-updates]\n"
|
||||
"<seed> <anchor-tx> <open-channel-file1> <open-channel-file2> <update-protobuf> <update-signature-protobuf> [previous-updates]\n"
|
||||
"Create a new update-complete 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]);
|
||||
@ -56,15 +57,15 @@ int main(int argc, char *argv[])
|
||||
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;
|
||||
ua = pkt_from_file(argv[5], PKT__PKT_UPDATE_ACCEPT)->update_accept;
|
||||
proto_to_sha256(ua->revocation_preimage, &preimage);
|
||||
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 = 0;
|
||||
for (i = 6; i < argc; i++) {
|
||||
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:
|
||||
@ -84,7 +85,8 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
/* They gave us right preimage? */
|
||||
/* 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");
|
||||
@ -100,15 +102,16 @@ int main(int argc, char *argv[])
|
||||
p2sh_out = find_p2sh_out(anchor, redeemscript);
|
||||
|
||||
/* Check their signature signs our new commit tx correctly. */
|
||||
proto_to_sha256(ua->revocation_hash, &their_rhash);
|
||||
commit = create_commit_tx(ctx, o1, o2, &their_rhash, delta,
|
||||
&anchor_txid, p2sh_out);
|
||||
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);
|
||||
if (!commit)
|
||||
errx(1, "Delta too large");
|
||||
|
||||
sig.stype = SIGHASH_ALL;
|
||||
if (!proto_to_signature(ua->sig, &sig.sig))
|
||||
errx(1, "Invalid update signature");
|
||||
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))
|
||||
|
133
update-channel-signature.c
Normal file
133
update-channel-signature.c
Normal file
@ -0,0 +1,133 @@
|
||||
#include <ccan/crypto/shachain/shachain.h>
|
||||
#include <ccan/short_types/short_types.h>
|
||||
#include <ccan/tal/tal.h>
|
||||
#include <ccan/opt/opt.h>
|
||||
#include <ccan/str/hex/hex.h>
|
||||
#include <ccan/err/err.h>
|
||||
#include <ccan/read_write_all/read_write_all.h>
|
||||
#include "lightning.pb-c.h"
|
||||
#include "anchor.h"
|
||||
#include "base58.h"
|
||||
#include "pkt.h"
|
||||
#include "bitcoin_script.h"
|
||||
#include "permute_tx.h"
|
||||
#include "signature.h"
|
||||
#include "commit_tx.h"
|
||||
#include "pubkey.h"
|
||||
#include "find_p2sh_out.h"
|
||||
#include <openssl/ec.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;
|
||||
OpenChannel *o1, *o2;
|
||||
UpdateAccept *ua;
|
||||
Update *update;
|
||||
struct bitcoin_tx *anchor, *commit;
|
||||
struct sha256_double anchor_txid;
|
||||
struct pkt *pkt;
|
||||
struct bitcoin_signature sig;
|
||||
EC_KEY *privkey;
|
||||
bool testnet;
|
||||
struct pubkey pubkey1, pubkey2;
|
||||
u8 *redeemscript;
|
||||
int64_t delta;
|
||||
size_t i, p2sh_out;
|
||||
|
||||
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"
|
||||
"Create a new update-channel-signature message",
|
||||
"Print this message.");
|
||||
|
||||
opt_parse(&argc, argv, opt_log_stderr_exit);
|
||||
|
||||
if (argc < 8)
|
||||
opt_usage_exit_fail("Expected 7+ 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;
|
||||
|
||||
privkey = key_from_base58(argv[5], strlen(argv[5]), &testnet, &pubkey1);
|
||||
if (!privkey)
|
||||
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;
|
||||
}
|
||||
|
||||
/* Give up revocation preimage for old tx. */
|
||||
shachain_from_seed(&seed, argc - 7 - 1, &preimage);
|
||||
|
||||
/* Get pubkeys */
|
||||
if (!proto_to_pubkey(o1->anchor->pubkey, &pubkey2))
|
||||
errx(1, "Invalid o1 commit pubkey");
|
||||
if (pubkey_len(&pubkey1) != pubkey_len(&pubkey2)
|
||||
|| memcmp(pubkey1.key, pubkey2.key, pubkey_len(&pubkey2)) != 0)
|
||||
errx(1, "o1 pubkey != this privkey");
|
||||
if (!proto_to_pubkey(o2->anchor->pubkey, &pubkey2))
|
||||
errx(1, "Invalid o2 final pubkey");
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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);
|
||||
if (!commit)
|
||||
errx(1, "Delta too large");
|
||||
|
||||
/* Check their signature signs this input correctly. */
|
||||
if (!check_tx_sig(commit, 0, redeemscript, tal_count(redeemscript),
|
||||
&pubkey2, &sig))
|
||||
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. */
|
||||
if (!commit)
|
||||
errx(1, "Delta too large");
|
||||
|
||||
/* Their pubkey must be valid */
|
||||
if (!proto_to_pubkey(o2->anchor->pubkey, &pubkey2))
|
||||
errx(1, "Invalid public open-channel-file2");
|
||||
|
||||
/* Sign it for them. */
|
||||
sign_tx_input(ctx, commit, 0, redeemscript, tal_count(redeemscript),
|
||||
privkey, &pubkey1, &sig.sig);
|
||||
|
||||
pkt = update_signature_pkt(ctx, &sig.sig, &preimage);
|
||||
if (!write_all(STDOUT_FILENO, pkt,
|
||||
sizeof(pkt->len) + le32_to_cpu(pkt->len)))
|
||||
err(1, "Writing out packet");
|
||||
|
||||
tal_free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
@ -25,23 +25,14 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
const tal_t *ctx = tal_arr(NULL, char, 0);
|
||||
struct sha256 seed, revocation_hash;
|
||||
OpenChannel *o1, *o2;
|
||||
struct bitcoin_tx *anchor, *commit;
|
||||
struct sha256_double anchor_txid;
|
||||
struct pkt *pkt;
|
||||
struct signature sig;
|
||||
EC_KEY *privkey;
|
||||
bool testnet;
|
||||
struct pubkey pubkey1, pubkey2;
|
||||
u8 *redeemscript;
|
||||
unsigned long long to_them = 0, from_them = 0;
|
||||
int64_t delta, this_delta;
|
||||
size_t i;
|
||||
int64_t this_delta;
|
||||
|
||||
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> [previous-updates]\n"
|
||||
"<seed> [previous-updates]\n"
|
||||
"Create a new update message",
|
||||
"Print this message.");
|
||||
opt_register_arg("--to-them=<satoshi>",
|
||||
@ -56,8 +47,8 @@ int main(int argc, char *argv[])
|
||||
if (!from_them && !to_them)
|
||||
opt_usage_exit_fail("Must use --to-them or --from-them");
|
||||
|
||||
if (argc < 5)
|
||||
opt_usage_exit_fail("Expected 4+ arguments");
|
||||
if (argc < 2)
|
||||
opt_usage_exit_fail("Expected 1+ arguments");
|
||||
|
||||
if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed)))
|
||||
errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]);
|
||||
@ -66,59 +57,12 @@ int main(int argc, char *argv[])
|
||||
if (!this_delta)
|
||||
errx(1, "Delta must not be zero");
|
||||
|
||||
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;
|
||||
|
||||
privkey = key_from_base58(argv[5], strlen(argv[5]), &testnet, &pubkey1);
|
||||
if (!privkey)
|
||||
errx(1, "Invalid private key '%s'", argv[5]);
|
||||
if (!testnet)
|
||||
errx(1, "Private key '%s' not on testnet!", argv[5]);
|
||||
|
||||
/* Figure out cumulative delta since anchor. */
|
||||
delta = this_delta;
|
||||
for (i = 6; i < argc; i++) {
|
||||
Update *u = pkt_from_file(argv[i], PKT__PKT_UPDATE)->update;
|
||||
delta += u->delta;
|
||||
}
|
||||
|
||||
/* Get next revocation hash. */
|
||||
shachain_from_seed(&seed, argc - 5, &revocation_hash);
|
||||
shachain_from_seed(&seed, argc - 2 + 1, &revocation_hash);
|
||||
sha256(&revocation_hash,
|
||||
revocation_hash.u.u8, sizeof(revocation_hash.u.u8));
|
||||
|
||||
/* Get pubkeys */
|
||||
if (!proto_to_pubkey(o1->anchor->pubkey, &pubkey2))
|
||||
errx(1, "Invalid o1 commit pubkey");
|
||||
if (pubkey_len(&pubkey1) != pubkey_len(&pubkey2)
|
||||
|| memcmp(pubkey1.key, pubkey2.key, pubkey_len(&pubkey2)) != 0)
|
||||
errx(1, "o1 pubkey != this privkey");
|
||||
if (!proto_to_pubkey(o2->anchor->pubkey, &pubkey2))
|
||||
errx(1, "Invalid o2 final pubkey");
|
||||
|
||||
/* This is what the anchor pays to; figure out whick output. */
|
||||
redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
|
||||
|
||||
/* Now create THEIR new commitment tx to spend 2/2 output of anchor. */
|
||||
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. */
|
||||
if (!commit)
|
||||
errx(1, "Delta too large");
|
||||
|
||||
/* Their pubkey must be valid */
|
||||
if (!proto_to_pubkey(o2->anchor->pubkey, &pubkey2))
|
||||
errx(1, "Invalid public open-channel-file2");
|
||||
|
||||
/* Sign it for them. */
|
||||
sign_tx_input(ctx, commit, 0, redeemscript, tal_count(redeemscript),
|
||||
privkey, &sig);
|
||||
|
||||
pkt = update_pkt(ctx, &revocation_hash, this_delta, &sig);
|
||||
pkt = update_pkt(ctx, &revocation_hash, this_delta);
|
||||
if (!write_all(STDOUT_FILENO, pkt,
|
||||
sizeof(pkt->len) + le32_to_cpu(pkt->len)))
|
||||
err(1, "Writing out packet");
|
||||
|
Loading…
Reference in New Issue
Block a user