mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-20 07:34:24 +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:
2
Makefile
2
Makefile
@@ -3,7 +3,7 @@
|
|||||||
# Needs to have oneof support: Ubuntu vivid's is too old :(
|
# Needs to have oneof support: Ubuntu vivid's is too old :(
|
||||||
PROTOCC:=protoc-c
|
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
|
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);
|
anchor_txid(anchor, argv[5], argv[6], inmap, &txid);
|
||||||
|
|
||||||
/* Now create our commitment tx. */
|
/* 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]);
|
commit = create_commit_tx(ctx, o1, o2, &rhash, 0, &txid, outmap[0]);
|
||||||
|
|
||||||
/* If contributions don't exceed fees, this fails. */
|
/* If contributions don't exceed fees, this fails. */
|
||||||
@@ -87,7 +87,7 @@ int main(int argc, char *argv[])
|
|||||||
sig1.stype = SIGHASH_ALL;
|
sig1.stype = SIGHASH_ALL;
|
||||||
subscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
|
subscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
|
||||||
sign_tx_input(ctx, commit, 0, subscript, tal_count(subscript),
|
sign_tx_input(ctx, commit, 0, subscript, tal_count(subscript),
|
||||||
privkey, &sig1.sig);
|
privkey, &pubkey1, &sig1.sig);
|
||||||
|
|
||||||
/* Signatures well-formed? */
|
/* Signatures well-formed? */
|
||||||
if (!proto_to_signature(cs2->sig, &sig2.sig))
|
if (!proto_to_signature(cs2->sig, &sig2.sig))
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
/* Sign it for them. */
|
/* Sign it for them. */
|
||||||
sign_tx_input(ctx, close_tx, 0, redeemscript, tal_count(redeemscript),
|
sign_tx_input(ctx, close_tx, 0, redeemscript, tal_count(redeemscript),
|
||||||
privkey, &sig);
|
privkey, &pubkey1, &sig);
|
||||||
|
|
||||||
if (complete)
|
if (complete)
|
||||||
pkt = close_channel_complete_pkt(ctx, &sig);
|
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. */
|
/* Now get signature, to set up input script. */
|
||||||
if (!sign_tx_input(tx, tx, 0, redeemscript, tal_count(redeemscript),
|
if (!sign_tx_input(tx, tx, 0, redeemscript, tal_count(redeemscript),
|
||||||
privkey, &sig.sig))
|
privkey, &pubkey1, &sig.sig))
|
||||||
errx(1, "Could not sign tx");
|
errx(1, "Could not sign tx");
|
||||||
sig.stype = SIGHASH_ALL;
|
sig.stype = SIGHASH_ALL;
|
||||||
tx->input[0].script = scriptsig_p2sh_single_sig(tx, redeemscript,
|
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. */
|
/* Now get signature, to set up input script. */
|
||||||
if (!sign_tx_input(tx, tx, 0, redeemscript, tal_count(redeemscript),
|
if (!sign_tx_input(tx, tx, 0, redeemscript, tal_count(redeemscript),
|
||||||
privkey, &sig.sig))
|
privkey, &pubkey1, &sig.sig))
|
||||||
errx(1, "Could not sign tx");
|
errx(1, "Could not sign tx");
|
||||||
sig.stype = SIGHASH_ALL;
|
sig.stype = SIGHASH_ALL;
|
||||||
tx->input[0].script = scriptsig_p2sh_revoke(tx, &revoke, &sig,
|
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);
|
assert(message->base.descriptor == &update_accept__descriptor);
|
||||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
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
|
void update_complete__init
|
||||||
(UpdateComplete *message)
|
(UpdateComplete *message)
|
||||||
{
|
{
|
||||||
@@ -1743,7 +1786,7 @@ const ProtobufCMessageDescriptor open_complete__descriptor =
|
|||||||
(ProtobufCMessageInit) open_complete__init,
|
(ProtobufCMessageInit) open_complete__init,
|
||||||
NULL,NULL,NULL /* reserved[123] */
|
NULL,NULL,NULL /* reserved[123] */
|
||||||
};
|
};
|
||||||
static const ProtobufCFieldDescriptor update__field_descriptors[4] =
|
static const ProtobufCFieldDescriptor update__field_descriptors[2] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
"revocation_hash",
|
"revocation_hash",
|
||||||
@@ -1769,41 +1812,15 @@ static const ProtobufCFieldDescriptor update__field_descriptors[4] =
|
|||||||
0, /* flags */
|
0, /* flags */
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
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[] = {
|
static const unsigned update__field_indices_by_name[] = {
|
||||||
1, /* field[1] = delta */
|
1, /* field[1] = delta */
|
||||||
3, /* field[3] = old_anchor_sig */
|
|
||||||
0, /* field[0] = revocation_hash */
|
0, /* field[0] = revocation_hash */
|
||||||
2, /* field[2] = sig */
|
|
||||||
};
|
};
|
||||||
static const ProtobufCIntRange update__number_ranges[1 + 1] =
|
static const ProtobufCIntRange update__number_ranges[1 + 1] =
|
||||||
{
|
{
|
||||||
{ 1, 0 },
|
{ 1, 0 },
|
||||||
{ 0, 4 }
|
{ 0, 2 }
|
||||||
};
|
};
|
||||||
const ProtobufCMessageDescriptor update__descriptor =
|
const ProtobufCMessageDescriptor update__descriptor =
|
||||||
{
|
{
|
||||||
@@ -1813,14 +1830,14 @@ const ProtobufCMessageDescriptor update__descriptor =
|
|||||||
"Update",
|
"Update",
|
||||||
"",
|
"",
|
||||||
sizeof(Update),
|
sizeof(Update),
|
||||||
4,
|
2,
|
||||||
update__field_descriptors,
|
update__field_descriptors,
|
||||||
update__field_indices_by_name,
|
update__field_indices_by_name,
|
||||||
1, update__number_ranges,
|
1, update__number_ranges,
|
||||||
(ProtobufCMessageInit) update__init,
|
(ProtobufCMessageInit) update__init,
|
||||||
NULL,NULL,NULL /* reserved[123] */
|
NULL,NULL,NULL /* reserved[123] */
|
||||||
};
|
};
|
||||||
static const ProtobufCFieldDescriptor update_accept__field_descriptors[4] =
|
static const ProtobufCFieldDescriptor update_accept__field_descriptors[3] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
"sig",
|
"sig",
|
||||||
@@ -1858,29 +1875,16 @@ static const ProtobufCFieldDescriptor update_accept__field_descriptors[4] =
|
|||||||
0, /* flags */
|
0, /* flags */
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
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[] = {
|
static const unsigned update_accept__field_indices_by_name[] = {
|
||||||
1, /* field[1] = old_anchor_sig */
|
1, /* field[1] = old_anchor_sig */
|
||||||
2, /* field[2] = revocation_hash */
|
2, /* field[2] = revocation_hash */
|
||||||
3, /* field[3] = revocation_preimage */
|
|
||||||
0, /* field[0] = sig */
|
0, /* field[0] = sig */
|
||||||
};
|
};
|
||||||
static const ProtobufCIntRange update_accept__number_ranges[1 + 1] =
|
static const ProtobufCIntRange update_accept__number_ranges[1 + 1] =
|
||||||
{
|
{
|
||||||
{ 1, 0 },
|
{ 1, 0 },
|
||||||
{ 0, 4 }
|
{ 0, 3 }
|
||||||
};
|
};
|
||||||
const ProtobufCMessageDescriptor update_accept__descriptor =
|
const ProtobufCMessageDescriptor update_accept__descriptor =
|
||||||
{
|
{
|
||||||
@@ -1890,13 +1894,64 @@ const ProtobufCMessageDescriptor update_accept__descriptor =
|
|||||||
"UpdateAccept",
|
"UpdateAccept",
|
||||||
"",
|
"",
|
||||||
sizeof(UpdateAccept),
|
sizeof(UpdateAccept),
|
||||||
4,
|
3,
|
||||||
update_accept__field_descriptors,
|
update_accept__field_descriptors,
|
||||||
update_accept__field_indices_by_name,
|
update_accept__field_indices_by_name,
|
||||||
1, update_accept__number_ranges,
|
1, update_accept__number_ranges,
|
||||||
(ProtobufCMessageInit) update_accept__init,
|
(ProtobufCMessageInit) update_accept__init,
|
||||||
NULL,NULL,NULL /* reserved[123] */
|
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] =
|
static const ProtobufCFieldDescriptor update_complete__field_descriptors[1] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -2239,7 +2294,7 @@ const ProtobufCMessageDescriptor error__descriptor =
|
|||||||
(ProtobufCMessageInit) error__init,
|
(ProtobufCMessageInit) error__init,
|
||||||
NULL,NULL,NULL /* reserved[123] */
|
NULL,NULL,NULL /* reserved[123] */
|
||||||
};
|
};
|
||||||
static const ProtobufCFieldDescriptor pkt__field_descriptors[15] =
|
static const ProtobufCFieldDescriptor pkt__field_descriptors[16] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
"update",
|
"update",
|
||||||
@@ -2266,11 +2321,23 @@ static const ProtobufCFieldDescriptor pkt__field_descriptors[15] =
|
|||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"update_complete",
|
"update_signature",
|
||||||
3,
|
3,
|
||||||
PROTOBUF_C_LABEL_OPTIONAL,
|
PROTOBUF_C_LABEL_OPTIONAL,
|
||||||
PROTOBUF_C_TYPE_MESSAGE,
|
PROTOBUF_C_TYPE_MESSAGE,
|
||||||
offsetof(Pkt, pkt_case),
|
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),
|
offsetof(Pkt, update_complete),
|
||||||
&update_complete__descriptor,
|
&update_complete__descriptor,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -2423,30 +2490,31 @@ static const ProtobufCFieldDescriptor pkt__field_descriptors[15] =
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
static const unsigned pkt__field_indices_by_name[] = {
|
static const unsigned pkt__field_indices_by_name[] = {
|
||||||
12, /* field[12] = close */
|
13, /* field[13] = close */
|
||||||
13, /* field[13] = close_complete */
|
14, /* field[14] = close_complete */
|
||||||
14, /* field[14] = error */
|
15, /* field[15] = error */
|
||||||
8, /* field[8] = new_anchor */
|
9, /* field[9] = new_anchor */
|
||||||
10, /* field[10] = new_anchor_accept */
|
11, /* field[11] = new_anchor_accept */
|
||||||
9, /* field[9] = new_anchor_ack */
|
10, /* field[10] = new_anchor_ack */
|
||||||
11, /* field[11] = new_anchor_complete */
|
12, /* field[12] = new_anchor_complete */
|
||||||
7, /* field[7] = omg_fail */
|
8, /* field[8] = omg_fail */
|
||||||
3, /* field[3] = open */
|
4, /* field[4] = open */
|
||||||
5, /* field[5] = open_anchor_scriptsigs */
|
6, /* field[6] = open_anchor_scriptsigs */
|
||||||
4, /* field[4] = open_commit_sig */
|
5, /* field[5] = open_commit_sig */
|
||||||
6, /* field[6] = open_complete */
|
7, /* field[7] = open_complete */
|
||||||
0, /* field[0] = update */
|
0, /* field[0] = update */
|
||||||
1, /* field[1] = update_accept */
|
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] =
|
static const ProtobufCIntRange pkt__number_ranges[5 + 1] =
|
||||||
{
|
{
|
||||||
{ 1, 0 },
|
{ 1, 0 },
|
||||||
{ 201, 3 },
|
{ 201, 4 },
|
||||||
{ 301, 8 },
|
{ 301, 9 },
|
||||||
{ 401, 12 },
|
{ 401, 13 },
|
||||||
{ 1000, 14 },
|
{ 1000, 15 },
|
||||||
{ 0, 15 }
|
{ 0, 16 }
|
||||||
};
|
};
|
||||||
const ProtobufCMessageDescriptor pkt__descriptor =
|
const ProtobufCMessageDescriptor pkt__descriptor =
|
||||||
{
|
{
|
||||||
@@ -2456,7 +2524,7 @@ const ProtobufCMessageDescriptor pkt__descriptor =
|
|||||||
"Pkt",
|
"Pkt",
|
||||||
"",
|
"",
|
||||||
sizeof(Pkt),
|
sizeof(Pkt),
|
||||||
15,
|
16,
|
||||||
pkt__field_descriptors,
|
pkt__field_descriptors,
|
||||||
pkt__field_indices_by_name,
|
pkt__field_indices_by_name,
|
||||||
5, pkt__number_ranges,
|
5, pkt__number_ranges,
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ typedef struct _LeakAnchorSigsAndPretendWeDidnt LeakAnchorSigsAndPretendWeDidnt;
|
|||||||
typedef struct _OpenComplete OpenComplete;
|
typedef struct _OpenComplete OpenComplete;
|
||||||
typedef struct _Update Update;
|
typedef struct _Update Update;
|
||||||
typedef struct _UpdateAccept UpdateAccept;
|
typedef struct _UpdateAccept UpdateAccept;
|
||||||
|
typedef struct _UpdateSignature UpdateSignature;
|
||||||
typedef struct _UpdateComplete UpdateComplete;
|
typedef struct _UpdateComplete UpdateComplete;
|
||||||
typedef struct _NewAnchor NewAnchor;
|
typedef struct _NewAnchor NewAnchor;
|
||||||
typedef struct _NewAnchorAck NewAnchorAck;
|
typedef struct _NewAnchorAck NewAnchorAck;
|
||||||
@@ -291,32 +292,24 @@ struct _Update
|
|||||||
/*
|
/*
|
||||||
* Change in current payment to-me (implies reverse to-you).
|
* 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.
|
* FIXME: optional HTLC ops.
|
||||||
*/
|
*/
|
||||||
Signature *old_anchor_sig;
|
int64_t delta;
|
||||||
};
|
};
|
||||||
#define UPDATE__INIT \
|
#define UPDATE__INIT \
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&update__descriptor) \
|
{ 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
|
struct _UpdateAccept
|
||||||
{
|
{
|
||||||
ProtobufCMessage base;
|
ProtobufCMessage base;
|
||||||
/*
|
/*
|
||||||
* Signature for new commitment tx.
|
* Signature for your new commitment tx.
|
||||||
*/
|
*/
|
||||||
Signature *sig;
|
Signature *sig;
|
||||||
/*
|
/*
|
||||||
@@ -327,14 +320,30 @@ struct _UpdateAccept
|
|||||||
* Hash for which I will supply preimage to revoke this new commit tx.
|
* Hash for which I will supply preimage to revoke this new commit tx.
|
||||||
*/
|
*/
|
||||||
Sha256Hash *revocation_hash;
|
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.
|
* Hash preimage which revokes old commitment tx.
|
||||||
*/
|
*/
|
||||||
Sha256Hash *revocation_preimage;
|
Sha256Hash *revocation_preimage;
|
||||||
};
|
};
|
||||||
#define UPDATE_ACCEPT__INIT \
|
#define UPDATE_SIGNATURE__INIT \
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&update_accept__descriptor) \
|
{ PROTOBUF_C_MESSAGE_INIT (&update_signature__descriptor) \
|
||||||
, NULL, NULL, NULL, NULL }
|
, NULL, NULL }
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -479,7 +488,8 @@ typedef enum {
|
|||||||
PKT__PKT_OPEN_COMPLETE = 204,
|
PKT__PKT_OPEN_COMPLETE = 204,
|
||||||
PKT__PKT_UPDATE = 1,
|
PKT__PKT_UPDATE = 1,
|
||||||
PKT__PKT_UPDATE_ACCEPT = 2,
|
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 = 301,
|
||||||
PKT__PKT_NEW_ANCHOR_ACK = 302,
|
PKT__PKT_NEW_ANCHOR_ACK = 302,
|
||||||
PKT__PKT_NEW_ANCHOR_ACCEPT = 303,
|
PKT__PKT_NEW_ANCHOR_ACCEPT = 303,
|
||||||
@@ -510,6 +520,7 @@ struct _Pkt
|
|||||||
*/
|
*/
|
||||||
Update *update;
|
Update *update;
|
||||||
UpdateAccept *update_accept;
|
UpdateAccept *update_accept;
|
||||||
|
UpdateSignature *update_signature;
|
||||||
UpdateComplete *update_complete;
|
UpdateComplete *update_complete;
|
||||||
/*
|
/*
|
||||||
* Topping up
|
* Topping up
|
||||||
@@ -781,6 +792,25 @@ UpdateAccept *
|
|||||||
void update_accept__free_unpacked
|
void update_accept__free_unpacked
|
||||||
(UpdateAccept *message,
|
(UpdateAccept *message,
|
||||||
ProtobufCAllocator *allocator);
|
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 */
|
/* UpdateComplete methods */
|
||||||
void update_complete__init
|
void update_complete__init
|
||||||
(UpdateComplete *message);
|
(UpdateComplete *message);
|
||||||
@@ -1012,6 +1042,9 @@ typedef void (*Update_Closure)
|
|||||||
typedef void (*UpdateAccept_Closure)
|
typedef void (*UpdateAccept_Closure)
|
||||||
(const UpdateAccept *message,
|
(const UpdateAccept *message,
|
||||||
void *closure_data);
|
void *closure_data);
|
||||||
|
typedef void (*UpdateSignature_Closure)
|
||||||
|
(const UpdateSignature *message,
|
||||||
|
void *closure_data);
|
||||||
typedef void (*UpdateComplete_Closure)
|
typedef void (*UpdateComplete_Closure)
|
||||||
(const UpdateComplete *message,
|
(const UpdateComplete *message,
|
||||||
void *closure_data);
|
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 open_complete__descriptor;
|
||||||
extern const ProtobufCMessageDescriptor update__descriptor;
|
extern const ProtobufCMessageDescriptor update__descriptor;
|
||||||
extern const ProtobufCMessageDescriptor update_accept__descriptor;
|
extern const ProtobufCMessageDescriptor update_accept__descriptor;
|
||||||
|
extern const ProtobufCMessageDescriptor update_signature__descriptor;
|
||||||
extern const ProtobufCMessageDescriptor update_complete__descriptor;
|
extern const ProtobufCMessageDescriptor update_complete__descriptor;
|
||||||
extern const ProtobufCMessageDescriptor new_anchor__descriptor;
|
extern const ProtobufCMessageDescriptor new_anchor__descriptor;
|
||||||
extern const ProtobufCMessageDescriptor new_anchor_ack__descriptor;
|
extern const ProtobufCMessageDescriptor new_anchor_ack__descriptor;
|
||||||
|
|||||||
@@ -121,23 +121,25 @@ message update {
|
|||||||
required sha256_hash revocation_hash = 1;
|
required sha256_hash revocation_hash = 1;
|
||||||
// Change in current payment to-me (implies reverse to-you).
|
// Change in current payment to-me (implies reverse to-you).
|
||||||
required sint64 delta = 2;
|
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.
|
// FIXME: optional HTLC ops.
|
||||||
}
|
}
|
||||||
|
|
||||||
// OK, I accept that update.
|
// OK, I accept that update; here's your signature.
|
||||||
message update_accept {
|
message update_accept {
|
||||||
// Signature for new commitment tx.
|
// Signature for your new commitment tx.
|
||||||
required signature sig = 1;
|
required signature sig = 1;
|
||||||
// Signature for old anchor (if any)
|
// Signature for old anchor (if any)
|
||||||
optional signature old_anchor_sig = 2;
|
optional signature old_anchor_sig = 2;
|
||||||
// Hash for which I will supply preimage to revoke this new commit tx.
|
// Hash for which I will supply preimage to revoke this new commit tx.
|
||||||
required sha256_hash revocation_hash = 3;
|
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.
|
// Hash preimage which revokes old commitment tx.
|
||||||
required sha256_hash revocation_preimage = 4;
|
required sha256_hash revocation_preimage = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Complete the update.
|
// Complete the update.
|
||||||
@@ -204,7 +206,8 @@ message pkt {
|
|||||||
// Updating (most common)
|
// Updating (most common)
|
||||||
update update = 1;
|
update update = 1;
|
||||||
update_accept update_accept = 2;
|
update_accept update_accept = 2;
|
||||||
update_complete update_complete = 3;
|
update_signature update_signature = 3;
|
||||||
|
update_complete update_complete = 4;
|
||||||
// Topping up
|
// Topping up
|
||||||
new_anchor new_anchor = 301;
|
new_anchor new_anchor = 301;
|
||||||
new_anchor_ack new_anchor_ack = 302;
|
new_anchor_ack new_anchor_ack = 302;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ static u8 *tx_scriptsig(const tal_t *ctx,
|
|||||||
sig.stype = SIGHASH_ALL;
|
sig.stype = SIGHASH_ALL;
|
||||||
if (!sign_tx_input(ctx, tx, i,
|
if (!sign_tx_input(ctx, tx, i,
|
||||||
input->subscript.data, input->subscript.len,
|
input->subscript.data, input->subscript.len,
|
||||||
privkey, &sig.sig))
|
privkey, pubkey, &sig.sig))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!is_pay_to_pubkey_hash(input->subscript.data, input->subscript.len))
|
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);
|
anchor_txid(anchor, argv[4], argv[5], inmap, &txid);
|
||||||
|
|
||||||
/* Now create THEIR commitment tx to spend 2/2 output of anchor. */
|
/* 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]);
|
commit = create_commit_tx(ctx, o2, o1, &rhash, 0, &txid, outmap[0]);
|
||||||
|
|
||||||
/* If contributions don't exceed fees, this fails. */
|
/* If contributions don't exceed fees, this fails. */
|
||||||
@@ -84,7 +84,7 @@ int main(int argc, char *argv[])
|
|||||||
/* Sign it for them. */
|
/* Sign it for them. */
|
||||||
subscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
|
subscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
|
||||||
sign_tx_input(ctx, commit, 0, subscript, tal_count(subscript),
|
sign_tx_input(ctx, commit, 0, subscript, tal_count(subscript),
|
||||||
privkey, &sig);
|
privkey, &pubkey1, &sig);
|
||||||
|
|
||||||
pkt = open_commit_sig_pkt(ctx, &sig);
|
pkt = open_commit_sig_pkt(ctx, &sig);
|
||||||
if (!write_all(STDOUT_FILENO, pkt,
|
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,
|
struct pkt *update_pkt(const tal_t *ctx,
|
||||||
const struct sha256 *revocation_hash,
|
const struct sha256 *revocation_hash,
|
||||||
s64 delta, struct signature *sig)
|
s64 delta)
|
||||||
{
|
{
|
||||||
Update u = UPDATE__INIT;
|
Update u = UPDATE__INIT;
|
||||||
u.revocation_hash = sha256_to_proto(ctx, revocation_hash);
|
u.revocation_hash = sha256_to_proto(ctx, revocation_hash);
|
||||||
u.delta = delta;
|
u.delta = delta;
|
||||||
u.sig = signature_to_proto(ctx, sig);
|
|
||||||
return to_pkt(ctx, PKT__PKT_UPDATE, &u);
|
return to_pkt(ctx, PKT__PKT_UPDATE, &u);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pkt *update_accept_pkt(const tal_t *ctx,
|
struct pkt *update_accept_pkt(const tal_t *ctx,
|
||||||
struct signature *sig,
|
struct signature *sig,
|
||||||
const struct sha256 *revocation_hash,
|
const struct sha256 *revocation_hash)
|
||||||
const struct sha256 *revocation_preimage)
|
|
||||||
{
|
{
|
||||||
UpdateAccept ua = UPDATE_ACCEPT__INIT;
|
UpdateAccept ua = UPDATE_ACCEPT__INIT;
|
||||||
ua.sig = signature_to_proto(ctx, sig);
|
ua.sig = signature_to_proto(ctx, sig);
|
||||||
ua.revocation_hash = sha256_to_proto(ctx, revocation_hash);
|
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);
|
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,
|
struct pkt *update_complete_pkt(const tal_t *ctx,
|
||||||
const struct sha256 *revocation_preimage)
|
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.
|
* @ctx: tal context to allocate off.
|
||||||
* @revocation_hash: the revocation hash for the next tx.
|
* @revocation_hash: the revocation hash for the next tx.
|
||||||
* @delta: the change in satoshis (to me).
|
* @delta: the change in satoshis (to me).
|
||||||
* @sig: the signature for the close transaction input.
|
|
||||||
*/
|
*/
|
||||||
struct pkt *update_pkt(const tal_t *ctx,
|
struct pkt *update_pkt(const tal_t *ctx,
|
||||||
const struct sha256 *revocation_hash,
|
const struct sha256 *revocation_hash,
|
||||||
s64 delta, struct signature *sig);
|
s64 delta);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* update_accept_pkt - create an update_accept message
|
* update_accept_pkt - create an update_accept message
|
||||||
* @ctx: tal context to allocate off.
|
* @ctx: tal context to allocate off.
|
||||||
* @sig: the signature for the close transaction input.
|
* @sig: the signature for the close transaction input.
|
||||||
* @revocation_hash: hash to revoke the next tx.
|
* @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 pkt *update_accept_pkt(const tal_t *ctx,
|
||||||
struct signature *sig,
|
struct signature *sig,
|
||||||
const struct sha256 *revocation_hash,
|
const struct sha256 *revocation_hash);
|
||||||
const struct sha256 *revocation_preimage);
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
* update_complete_pkt - create an update_accept message
|
||||||
* @ctx: tal context to allocate off.
|
* @ctx: tal context to allocate off.
|
||||||
|
|||||||
68
signature.c
68
signature.c
@@ -8,6 +8,62 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ccan/cast/cast.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,
|
bool sign_hash(const tal_t *ctx, EC_KEY *private_key,
|
||||||
const struct sha256_double *h,
|
const struct sha256_double *h,
|
||||||
struct signature *s)
|
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,
|
bool sign_tx_input(const tal_t *ctx, struct bitcoin_tx *tx,
|
||||||
unsigned int in,
|
unsigned int in,
|
||||||
const u8 *subscript, size_t subscript_len,
|
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;
|
struct sha256_double hash;
|
||||||
|
|
||||||
sha256_tx_one_input(tx, in, subscript, subscript_len, &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);
|
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)
|
const struct bitcoin_signature *sig)
|
||||||
{
|
{
|
||||||
struct sha256_double hash;
|
struct sha256_double hash;
|
||||||
|
bool ret;
|
||||||
|
|
||||||
assert(input_num < tx->input_count);
|
assert(input_num < tx->input_count);
|
||||||
|
|
||||||
sha256_tx_one_input(tx, input_num, redeemscript, redeemscript_len,
|
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)
|
if (sig->stype != SIGHASH_ALL)
|
||||||
return false;
|
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,
|
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,
|
bool sign_tx_input(const tal_t *ctx, struct bitcoin_tx *tx,
|
||||||
unsigned int in,
|
unsigned int in,
|
||||||
const u8 *subscript, size_t subscript_len,
|
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. */
|
/* Does this sig sign the tx with this input for this pubkey. */
|
||||||
bool check_tx_sig(struct bitcoin_tx *tx, size_t input_num,
|
bool check_tx_sig(struct bitcoin_tx *tx, size_t input_num,
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
const tal_t *ctx = tal_arr(NULL, char, 0);
|
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;
|
OpenChannel *o1, *o2;
|
||||||
Update *update;
|
Update *update;
|
||||||
struct bitcoin_tx *anchor, *commit;
|
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;
|
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. */
|
/* Figure out cumulative delta since anchor. */
|
||||||
delta = update->delta;
|
delta = update->delta;
|
||||||
for (i = 7; i < argc; i++) {
|
for (i = 7; i < argc; i++) {
|
||||||
@@ -95,20 +91,9 @@ int main(int argc, char *argv[])
|
|||||||
redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
|
redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
|
||||||
p2sh_out = find_p2sh_out(anchor, redeemscript);
|
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. */
|
/* 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);
|
&anchor_txid, p2sh_out);
|
||||||
|
|
||||||
/* If contributions don't exceed fees, this fails. */
|
/* If contributions don't exceed fees, this fails. */
|
||||||
@@ -117,13 +102,9 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
/* Sign it for them. */
|
/* Sign it for them. */
|
||||||
sign_tx_input(ctx, commit, 0, redeemscript, tal_count(redeemscript),
|
sign_tx_input(ctx, commit, 0, redeemscript, tal_count(redeemscript),
|
||||||
privkey, &sig.sig);
|
privkey, &pubkey1, &sig.sig);
|
||||||
|
|
||||||
/* Give up revocation preimage for old tx. */
|
pkt = update_accept_pkt(ctx, &sig.sig, &revocation_hash);
|
||||||
shachain_from_seed(&seed, argc - 6 - 1, &revocation_preimage);
|
|
||||||
|
|
||||||
pkt = update_accept_pkt(ctx, &sig.sig,
|
|
||||||
&revocation_hash, &revocation_preimage);
|
|
||||||
if (!write_all(STDOUT_FILENO, pkt,
|
if (!write_all(STDOUT_FILENO, pkt,
|
||||||
sizeof(pkt->len) + le32_to_cpu(pkt->len)))
|
sizeof(pkt->len) + le32_to_cpu(pkt->len)))
|
||||||
err(1, "Writing out packet");
|
err(1, "Writing out packet");
|
||||||
|
|||||||
@@ -25,9 +25,10 @@
|
|||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
const tal_t *ctx = tal_arr(NULL, char, 0);
|
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;
|
OpenChannel *o1, *o2;
|
||||||
UpdateAccept *ua;
|
UpdateSignature *us;
|
||||||
|
Update *update;
|
||||||
struct pkt *pkt;
|
struct pkt *pkt;
|
||||||
struct bitcoin_tx *anchor, *commit;
|
struct bitcoin_tx *anchor, *commit;
|
||||||
struct pubkey pubkey1, pubkey2;
|
struct pubkey pubkey1, pubkey2;
|
||||||
@@ -40,14 +41,14 @@ int main(int argc, char *argv[])
|
|||||||
err_set_progname(argv[0]);
|
err_set_progname(argv[0]);
|
||||||
|
|
||||||
opt_register_noarg("--help|-h", opt_usage_and_exit,
|
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",
|
"Create a new update-complete message",
|
||||||
"Print this message.");
|
"Print this message.");
|
||||||
|
|
||||||
opt_parse(&argc, argv, opt_log_stderr_exit);
|
opt_parse(&argc, argv, opt_log_stderr_exit);
|
||||||
|
|
||||||
if (argc < 6)
|
if (argc < 7)
|
||||||
opt_usage_exit_fail("Expected 5+ arguments");
|
opt_usage_exit_fail("Expected 6+ arguments");
|
||||||
|
|
||||||
if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed)))
|
if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed)))
|
||||||
errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]);
|
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);
|
bitcoin_txid(anchor, &anchor_txid);
|
||||||
o1 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open;
|
o1 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open;
|
||||||
o2 = pkt_from_file(argv[4], 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;
|
update = pkt_from_file(argv[5], PKT__PKT_UPDATE)->update;
|
||||||
proto_to_sha256(ua->revocation_preimage, &preimage);
|
us = pkt_from_file(argv[6], PKT__PKT_UPDATE_SIGNATURE)->update_signature;
|
||||||
|
|
||||||
/* We need last revocation hash (either in update or update-accept),
|
/* We need last revocation hash (either in update or update-accept),
|
||||||
* and the delta */
|
* and the delta */
|
||||||
proto_to_sha256(o2->revocation_hash, &revocation_hash);
|
proto_to_sha256(o2->revocation_hash, &revocation_hash);
|
||||||
num_updates = 0;
|
num_updates = 0;
|
||||||
delta = 0;
|
delta = update->delta;
|
||||||
for (i = 6; i < argc; i++) {
|
for (i = 7; i < argc; i++) {
|
||||||
Pkt *p = any_pkt_from_file(argv[i]);
|
Pkt *p = any_pkt_from_file(argv[i]);
|
||||||
switch (p->pkt_case) {
|
switch (p->pkt_case) {
|
||||||
case PKT__PKT_UPDATE:
|
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));
|
sha256(&their_rhash, preimage.u.u8, sizeof(preimage.u.u8));
|
||||||
if (!structeq(&their_rhash, &revocation_hash))
|
if (!structeq(&their_rhash, &revocation_hash))
|
||||||
errx(1, "Their preimage was incorrect");
|
errx(1, "Their preimage was incorrect");
|
||||||
@@ -100,15 +102,16 @@ int main(int argc, char *argv[])
|
|||||||
p2sh_out = find_p2sh_out(anchor, redeemscript);
|
p2sh_out = find_p2sh_out(anchor, redeemscript);
|
||||||
|
|
||||||
/* Check their signature signs our new commit tx correctly. */
|
/* Check their signature signs our new commit tx correctly. */
|
||||||
proto_to_sha256(ua->revocation_hash, &their_rhash);
|
shachain_from_seed(&seed, num_updates + 1, &preimage);
|
||||||
commit = create_commit_tx(ctx, o1, o2, &their_rhash, delta,
|
sha256(&our_rhash, &preimage, sizeof(preimage));
|
||||||
|
commit = create_commit_tx(ctx, o1, o2, &our_rhash, delta,
|
||||||
&anchor_txid, p2sh_out);
|
&anchor_txid, p2sh_out);
|
||||||
if (!commit)
|
if (!commit)
|
||||||
errx(1, "Delta too large");
|
errx(1, "Delta too large");
|
||||||
|
|
||||||
sig.stype = SIGHASH_ALL;
|
sig.stype = SIGHASH_ALL;
|
||||||
if (!proto_to_signature(ua->sig, &sig.sig))
|
if (!proto_to_signature(us->sig, &sig.sig))
|
||||||
errx(1, "Invalid update signature");
|
errx(1, "Invalid update-signature signature");
|
||||||
|
|
||||||
if (!check_tx_sig(commit, 0, redeemscript, tal_count(redeemscript),
|
if (!check_tx_sig(commit, 0, redeemscript, tal_count(redeemscript),
|
||||||
&pubkey2, &sig))
|
&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);
|
const tal_t *ctx = tal_arr(NULL, char, 0);
|
||||||
struct sha256 seed, revocation_hash;
|
struct sha256 seed, revocation_hash;
|
||||||
OpenChannel *o1, *o2;
|
|
||||||
struct bitcoin_tx *anchor, *commit;
|
|
||||||
struct sha256_double anchor_txid;
|
|
||||||
struct pkt *pkt;
|
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;
|
unsigned long long to_them = 0, from_them = 0;
|
||||||
int64_t delta, this_delta;
|
int64_t this_delta;
|
||||||
size_t i;
|
|
||||||
|
|
||||||
err_set_progname(argv[0]);
|
err_set_progname(argv[0]);
|
||||||
|
|
||||||
opt_register_noarg("--help|-h", opt_usage_and_exit,
|
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",
|
"Create a new update message",
|
||||||
"Print this message.");
|
"Print this message.");
|
||||||
opt_register_arg("--to-them=<satoshi>",
|
opt_register_arg("--to-them=<satoshi>",
|
||||||
@@ -56,8 +47,8 @@ int main(int argc, char *argv[])
|
|||||||
if (!from_them && !to_them)
|
if (!from_them && !to_them)
|
||||||
opt_usage_exit_fail("Must use --to-them or --from-them");
|
opt_usage_exit_fail("Must use --to-them or --from-them");
|
||||||
|
|
||||||
if (argc < 5)
|
if (argc < 2)
|
||||||
opt_usage_exit_fail("Expected 4+ arguments");
|
opt_usage_exit_fail("Expected 1+ arguments");
|
||||||
|
|
||||||
if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed)))
|
if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed)))
|
||||||
errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]);
|
errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]);
|
||||||
@@ -66,59 +57,12 @@ int main(int argc, char *argv[])
|
|||||||
if (!this_delta)
|
if (!this_delta)
|
||||||
errx(1, "Delta must not be zero");
|
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. */
|
/* Get next revocation hash. */
|
||||||
shachain_from_seed(&seed, argc - 5, &revocation_hash);
|
shachain_from_seed(&seed, argc - 2 + 1, &revocation_hash);
|
||||||
sha256(&revocation_hash,
|
sha256(&revocation_hash,
|
||||||
revocation_hash.u.u8, sizeof(revocation_hash.u.u8));
|
revocation_hash.u.u8, sizeof(revocation_hash.u.u8));
|
||||||
|
|
||||||
/* Get pubkeys */
|
pkt = update_pkt(ctx, &revocation_hash, this_delta);
|
||||||
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);
|
|
||||||
if (!write_all(STDOUT_FILENO, pkt,
|
if (!write_all(STDOUT_FILENO, pkt,
|
||||||
sizeof(pkt->len) + le32_to_cpu(pkt->len)))
|
sizeof(pkt->len) + le32_to_cpu(pkt->len)))
|
||||||
err(1, "Writing out packet");
|
err(1, "Writing out packet");
|
||||||
|
|||||||
Reference in New Issue
Block a user