diff --git a/commit_tx.c b/commit_tx.c index 98979cac6..ca29e12c3 100644 --- a/commit_tx.c +++ b/commit_tx.c @@ -18,6 +18,7 @@ struct bitcoin_tx *create_commit_tx(const tal_t *ctx, struct bitcoin_tx *tx; const u8 *redeemscript; struct pubkey ourkey, theirkey, to_me; + u32 locktime; /* Now create commitment tx: one input, two outputs. */ tx = bitcoin_tx(ctx, 1, 2); @@ -32,9 +33,12 @@ struct bitcoin_tx *create_commit_tx(const tal_t *ctx, if (!proto_to_pubkey(theirs->final, &theirkey)) return tal_free(tx); + if (!proto_to_locktime(ours, &locktime)) + return tal_free(tx); + /* First output is a P2SH to a complex redeem script (usu. for me) */ redeemscript = bitcoin_redeem_revocable(tx, &ourkey, - ours->locktime_seconds, + locktime, &theirkey, rhash); tx->output[0].script = scriptpubkey_p2sh(tx, redeemscript); diff --git a/lightning.pb-c.c b/lightning.pb-c.c index 1970eed12..7e1ab2faf 100644 --- a/lightning.pb-c.c +++ b/lightning.pb-c.c @@ -1517,7 +1517,7 @@ const ProtobufCMessageDescriptor anchor__descriptor = (ProtobufCMessageInit) anchor__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor open_channel__field_descriptors[7] = +static const ProtobufCFieldDescriptor open_channel__field_descriptors[8] = { { "seed", @@ -1534,13 +1534,25 @@ static const ProtobufCFieldDescriptor open_channel__field_descriptors[7] = { "locktime_seconds", 2, - PROTOBUF_C_LABEL_REQUIRED, + PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_UINT32, - 0, /* quantifier_offset */ + offsetof(OpenChannel, locktime_case), offsetof(OpenChannel, locktime_seconds), NULL, NULL, - 0, /* flags */ + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "locktime_blocks", + 3, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_UINT32, + offsetof(OpenChannel, locktime_case), + offsetof(OpenChannel, locktime_blocks), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { @@ -1605,19 +1617,19 @@ static const ProtobufCFieldDescriptor open_channel__field_descriptors[7] = }, }; static const unsigned open_channel__field_indices_by_name[] = { - 5, /* field[5] = anchor */ - 4, /* field[4] = commitment_fee */ - 3, /* field[3] = final */ + 6, /* field[6] = anchor */ + 5, /* field[5] = commitment_fee */ + 4, /* field[4] = final */ + 2, /* field[2] = locktime_blocks */ 1, /* field[1] = locktime_seconds */ - 2, /* field[2] = revocation_hash */ + 3, /* field[3] = revocation_hash */ 0, /* field[0] = seed */ - 6, /* field[6] = tx_version */ + 7, /* field[7] = tx_version */ }; -static const ProtobufCIntRange open_channel__number_ranges[2 + 1] = +static const ProtobufCIntRange open_channel__number_ranges[1 + 1] = { { 1, 0 }, - { 4, 2 }, - { 0, 7 } + { 0, 8 } }; const ProtobufCMessageDescriptor open_channel__descriptor = { @@ -1627,10 +1639,10 @@ const ProtobufCMessageDescriptor open_channel__descriptor = "OpenChannel", "", sizeof(OpenChannel), - 7, + 8, open_channel__field_descriptors, open_channel__field_indices_by_name, - 2, open_channel__number_ranges, + 1, open_channel__number_ranges, (ProtobufCMessageInit) open_channel__init, NULL,NULL,NULL /* reserved[123] */ }; diff --git a/lightning.pb-c.h b/lightning.pb-c.h index 95154e7ea..cb18af640 100644 --- a/lightning.pb-c.h +++ b/lightning.pb-c.h @@ -174,6 +174,12 @@ struct _Anchor , 0,NULL, NULL, NULL, 0, 0, 0 } +typedef enum { + OPEN_CHANNEL__LOCKTIME__NOT_SET = 0, + OPEN_CHANNEL__LOCKTIME_LOCKTIME_SECONDS = 2, + OPEN_CHANNEL__LOCKTIME_LOCKTIME_BLOCKS = 3, +} OpenChannel__LocktimeCase; + /* * Set channel params. */ @@ -184,10 +190,6 @@ struct _OpenChannel * Seed which sets order we create outputs for all transactions. */ uint64_t seed; - /* - * Relative locktime for outputs going to us. - */ - uint32_t locktime_seconds; /* * Hash seed for revoking commitment transactions. */ @@ -208,10 +210,15 @@ struct _OpenChannel * Maximum transaction version we support. */ uint32_t tx_version; + OpenChannel__LocktimeCase locktime_case; + union { + uint32_t locktime_seconds; + uint32_t locktime_blocks; + }; }; #define OPEN_CHANNEL__INIT \ { PROTOBUF_C_MESSAGE_INIT (&open_channel__descriptor) \ - , 0, 0, NULL, NULL, 0, NULL, 0 } + , 0, NULL, NULL, 0, NULL, 0, OPEN_CHANNEL__LOCKTIME__NOT_SET, {} } /* diff --git a/lightning.proto b/lightning.proto index a2fb9f51c..6c823658a 100644 --- a/lightning.proto +++ b/lightning.proto @@ -73,7 +73,10 @@ message open_channel { // Seed which sets order we create outputs for all transactions. required uint64 seed = 1; // Relative locktime for outputs going to us. - required uint32 locktime_seconds = 2; + oneof locktime { + uint32 locktime_seconds = 2; + uint32 locktime_blocks = 3; + } // Hash seed for revoking commitment transactions. required sha256_hash revocation_hash = 4; // How to pay money to us from commit_tx. diff --git a/pkt.c b/pkt.c index 46666c839..16626a039 100644 --- a/pkt.c +++ b/pkt.c @@ -45,6 +45,7 @@ struct pkt *openchannel_pkt(const tal_t *ctx, o.final = pubkey_to_proto(ctx, to_me); o.commitment_fee = commitment_fee; o.anchor = anchor; + o.locktime_case = OPEN_CHANNEL__LOCKTIME_LOCKTIME_SECONDS; o.locktime_seconds = rel_locktime_seconds; o.tx_version = BITCOIN_TX_VERSION; diff --git a/protobuf_convert.c b/protobuf_convert.c index 1d86bfc9f..1cf0d1e2a 100644 --- a/protobuf_convert.c +++ b/protobuf_convert.c @@ -81,3 +81,18 @@ void proto_to_sha256(const Sha256Hash *pb, struct sha256 *hash) memcpy(hash->u.u8 + 16, &pb->c, 8); memcpy(hash->u.u8 + 24, &pb->d, 8); } + +bool proto_to_locktime(const OpenChannel *o, uint32_t *locktime) +{ + switch (o->locktime_case) { + case OPEN_CHANNEL__LOCKTIME_LOCKTIME_SECONDS: + *locktime = 500000000 + o->locktime_seconds; + break; + case OPEN_CHANNEL__LOCKTIME_LOCKTIME_BLOCKS: + *locktime = o->locktime_blocks; + break; + default: + return false; + } + return true; +} diff --git a/protobuf_convert.h b/protobuf_convert.h index be6999b38..f3f8db81e 100644 --- a/protobuf_convert.h +++ b/protobuf_convert.h @@ -18,4 +18,6 @@ bool proto_to_pubkey(const BitcoinPubkey *pb, struct pubkey *key); struct sha256; Sha256Hash *sha256_to_proto(const tal_t *ctx, const struct sha256 *hash); void proto_to_sha256(const Sha256Hash *pb, struct sha256 *hash); + +bool proto_to_locktime(const OpenChannel *o, uint32_t *locktime); #endif /* LIGHTNING_PROTOBUF_CONVERT_H */ diff --git a/test-cli/create-commit-spend-tx.c b/test-cli/create-commit-spend-tx.c index 197e74d0c..f77bc1d69 100644 --- a/test-cli/create-commit-spend-tx.c +++ b/test-cli/create-commit-spend-tx.c @@ -39,6 +39,7 @@ int main(int argc, char *argv[]) struct sha256 rhash; size_t p2sh_out; u64 fee = 10000; + u32 locktime_seconds; err_set_progname(argv[0]); @@ -61,6 +62,8 @@ int main(int argc, char *argv[]) o1 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; o2 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open; + if (!proto_to_locktime(o2, &locktime_seconds)) + errx(1, "Invalid locktime in o2"); /* We need our private key to spend commit output. */ privkey = key_from_base58(argv[4], strlen(argv[4]), &testnet, &pubkey1); @@ -86,7 +89,7 @@ int main(int argc, char *argv[]) /* Create redeem script */ redeemscript = bitcoin_redeem_revocable(ctx, &pubkey1, - o2->locktime_seconds, + locktime_seconds, &pubkey2, &rhash); /* Now, create transaction to spend it. */ diff --git a/test-cli/create-steal-tx.c b/test-cli/create-steal-tx.c index 8f3d9cd56..b0e81d777 100644 --- a/test-cli/create-steal-tx.c +++ b/test-cli/create-steal-tx.c @@ -36,6 +36,7 @@ int main(int argc, char *argv[]) char *tx_hex; EC_KEY *privkey; bool testnet; + u32 locktime_seconds; err_set_progname(argv[0]); @@ -73,6 +74,8 @@ int main(int argc, char *argv[]) o1 = pkt_from_file(argv[4], PKT__PKT_OPEN)->open; o2 = pkt_from_file(argv[5], PKT__PKT_OPEN)->open; + if (!proto_to_locktime(o2, &locktime_seconds)) + errx(1, "Invalid locktime in o2"); if (!pubkey_from_hexstr(argv[6], &outpubkey)) errx(1, "Invalid bitcoin pubkey '%s'", argv[6]); @@ -89,7 +92,7 @@ int main(int argc, char *argv[]) /* Now, which commit output? Match redeem script. */ sha256(&revoke_hash, &revoke_preimage, sizeof(revoke_preimage)); redeemscript = bitcoin_redeem_revocable(ctx, &pubkey2, - o2->locktime_seconds, + locktime_seconds, &pubkey1, &revoke_hash); p2sh = scriptpubkey_p2sh(ctx, redeemscript);