mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-03-01 17:47:30 +01:00
daemon: newhtlc command.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
645958920e
commit
6bdaa5d1ca
8 changed files with 341 additions and 16 deletions
|
@ -238,6 +238,7 @@ static const struct json_command *cmdlist[] = {
|
||||||
&getlog_command,
|
&getlog_command,
|
||||||
&connect_command,
|
&connect_command,
|
||||||
&getpeers_command,
|
&getpeers_command,
|
||||||
|
&newhtlc_command,
|
||||||
/* Developer/debugging options. */
|
/* Developer/debugging options. */
|
||||||
&echo_command,
|
&echo_command,
|
||||||
&rhash_command,
|
&rhash_command,
|
||||||
|
|
|
@ -58,5 +58,5 @@ void setup_jsonrpc(struct lightningd_state *dstate, const char *rpc_filename);
|
||||||
/* Commands (from other files) */
|
/* Commands (from other files) */
|
||||||
extern const struct json_command connect_command;
|
extern const struct json_command connect_command;
|
||||||
extern const struct json_command getpeers_command;
|
extern const struct json_command getpeers_command;
|
||||||
|
extern const struct json_command newhtlc_command;
|
||||||
#endif /* LIGHTNING_DAEMON_JSONRPC_H */
|
#endif /* LIGHTNING_DAEMON_JSONRPC_H */
|
||||||
|
|
208
daemon/packets.c
208
daemon/packets.c
|
@ -11,6 +11,8 @@
|
||||||
#include <ccan/crypto/sha256/sha256.h>
|
#include <ccan/crypto/sha256/sha256.h>
|
||||||
#include <ccan/mem/mem.h>
|
#include <ccan/mem/mem.h>
|
||||||
#include <ccan/str/hex/hex.h>
|
#include <ccan/str/hex/hex.h>
|
||||||
|
#include <ccan/structeq/structeq.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
#define FIXME_STUB(peer) do { log_broken((peer)->dstate->base_log, "%s:%u: Implement %s!", __FILE__, __LINE__, __func__); abort(); } while(0)
|
#define FIXME_STUB(peer) do { log_broken((peer)->dstate->base_log, "%s:%u: Implement %s!", __FILE__, __LINE__, __func__); abort(); } while(0)
|
||||||
|
|
||||||
|
@ -99,7 +101,7 @@ Pkt *pkt_anchor(const tal_t *ctx, const struct peer *peer)
|
||||||
a->amount = peer->anchor.satoshis;
|
a->amount = peer->anchor.satoshis;
|
||||||
|
|
||||||
/* Sign their commit sig */
|
/* Sign their commit sig */
|
||||||
peer_sign_theircommit(peer, &sig);
|
peer_sign_theircommit(peer, peer->them.commit, &sig);
|
||||||
a->commit_sig = signature_to_proto(a, &sig);
|
a->commit_sig = signature_to_proto(a, &sig);
|
||||||
|
|
||||||
return make_pkt(ctx, PKT__PKT_OPEN_ANCHOR, a);
|
return make_pkt(ctx, PKT__PKT_OPEN_ANCHOR, a);
|
||||||
|
@ -115,7 +117,7 @@ Pkt *pkt_open_commit_sig(const tal_t *ctx, const struct peer *peer)
|
||||||
dump_tx("Creating sig for:", peer->them.commit);
|
dump_tx("Creating sig for:", peer->them.commit);
|
||||||
dump_key("Using key:", &peer->us.commitkey);
|
dump_key("Using key:", &peer->us.commitkey);
|
||||||
|
|
||||||
peer_sign_theircommit(peer, &sig);
|
peer_sign_theircommit(peer, peer->them.commit, &sig);
|
||||||
s->sig = signature_to_proto(s, &sig);
|
s->sig = signature_to_proto(s, &sig);
|
||||||
|
|
||||||
return make_pkt(ctx, PKT__PKT_OPEN_COMMIT_SIG, s);
|
return make_pkt(ctx, PKT__PKT_OPEN_COMMIT_SIG, s);
|
||||||
|
@ -132,7 +134,16 @@ Pkt *pkt_open_complete(const tal_t *ctx, const struct peer *peer)
|
||||||
Pkt *pkt_htlc_update(const tal_t *ctx, const struct peer *peer,
|
Pkt *pkt_htlc_update(const tal_t *ctx, const struct peer *peer,
|
||||||
const struct htlc_progress *htlc_prog)
|
const struct htlc_progress *htlc_prog)
|
||||||
{
|
{
|
||||||
FIXME_STUB(peer);
|
UpdateAddHtlc *u = tal(ctx, UpdateAddHtlc);
|
||||||
|
|
||||||
|
update_add_htlc__init(u);
|
||||||
|
|
||||||
|
u->revocation_hash = sha256_to_proto(u, &htlc_prog->our_revocation_hash);
|
||||||
|
u->amount_msat = htlc_prog->msatoshis;
|
||||||
|
u->r_hash = sha256_to_proto(u, &htlc_prog->rhash);
|
||||||
|
u->expiry = abs_locktime_to_proto(u, &htlc_prog->expiry);
|
||||||
|
|
||||||
|
return make_pkt(ctx, PKT__PKT_UPDATE_ADD_HTLC, u);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pkt *pkt_htlc_fulfill(const tal_t *ctx, const struct peer *peer,
|
Pkt *pkt_htlc_fulfill(const tal_t *ctx, const struct peer *peer,
|
||||||
|
@ -155,17 +166,50 @@ Pkt *pkt_htlc_routefail(const tal_t *ctx, const struct peer *peer,
|
||||||
|
|
||||||
Pkt *pkt_update_accept(const tal_t *ctx, const struct peer *peer)
|
Pkt *pkt_update_accept(const tal_t *ctx, const struct peer *peer)
|
||||||
{
|
{
|
||||||
FIXME_STUB(peer);
|
UpdateAccept *u = tal(ctx, UpdateAccept);
|
||||||
|
const struct htlc_progress *cur = peer->current_htlc;
|
||||||
|
struct signature sig;
|
||||||
|
|
||||||
|
update_accept__init(u);
|
||||||
|
|
||||||
|
dump_tx("Signing tx", cur->their_commit);
|
||||||
|
peer_sign_theircommit(peer, cur->their_commit, &sig);
|
||||||
|
u->sig = signature_to_proto(u, &sig);
|
||||||
|
u->revocation_hash
|
||||||
|
= sha256_to_proto(u, &cur->our_revocation_hash);
|
||||||
|
|
||||||
|
return make_pkt(ctx, PKT__PKT_UPDATE_ACCEPT, u);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pkt *pkt_update_signature(const tal_t *ctx, const struct peer *peer)
|
Pkt *pkt_update_signature(const tal_t *ctx, const struct peer *peer)
|
||||||
{
|
{
|
||||||
FIXME_STUB(peer);
|
UpdateSignature *u = tal(ctx, UpdateSignature);
|
||||||
|
const struct htlc_progress *cur = peer->current_htlc;
|
||||||
|
struct signature sig;
|
||||||
|
struct sha256 preimage;
|
||||||
|
|
||||||
|
update_signature__init(u);
|
||||||
|
|
||||||
|
peer_sign_theircommit(peer, cur->their_commit, &sig);
|
||||||
|
u->sig = signature_to_proto(u, &sig);
|
||||||
|
assert(peer->num_htlcs > 0);
|
||||||
|
peer_get_revocation_preimage(peer, peer->num_htlcs-1, &preimage);
|
||||||
|
u->revocation_preimage = sha256_to_proto(u, &preimage);
|
||||||
|
|
||||||
|
return make_pkt(ctx, PKT__PKT_UPDATE_SIGNATURE, u);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pkt *pkt_update_complete(const tal_t *ctx, const struct peer *peer)
|
Pkt *pkt_update_complete(const tal_t *ctx, const struct peer *peer)
|
||||||
{
|
{
|
||||||
FIXME_STUB(peer);
|
UpdateComplete *u = tal(ctx, UpdateComplete);
|
||||||
|
struct sha256 preimage;
|
||||||
|
|
||||||
|
update_complete__init(u);
|
||||||
|
|
||||||
|
peer_get_revocation_preimage(peer, peer->num_htlcs-1, &preimage);
|
||||||
|
u->revocation_preimage = sha256_to_proto(u, &preimage);
|
||||||
|
|
||||||
|
return make_pkt(ctx, PKT__PKT_UPDATE_COMPLETE, u);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pkt *pkt_err(const tal_t *ctx, const char *msg, ...)
|
Pkt *pkt_err(const tal_t *ctx, const char *msg, ...)
|
||||||
|
@ -317,8 +361,49 @@ Pkt *accept_pkt_htlc_update(const tal_t *ctx,
|
||||||
struct peer *peer, const Pkt *pkt,
|
struct peer *peer, const Pkt *pkt,
|
||||||
Pkt **decline)
|
Pkt **decline)
|
||||||
{
|
{
|
||||||
FIXME_STUB(peer);
|
const UpdateAddHtlc *u = pkt->update_add_htlc;
|
||||||
}
|
struct htlc_progress *cur = tal(peer, struct htlc_progress);
|
||||||
|
Pkt *err;
|
||||||
|
|
||||||
|
cur->msatoshis = u->amount_msat;
|
||||||
|
proto_to_sha256(u->r_hash, &cur->rhash);
|
||||||
|
proto_to_sha256(u->revocation_hash, &cur->their_revocation_hash);
|
||||||
|
if (!proto_to_abs_locktime(u->expiry, &cur->expiry)) {
|
||||||
|
err = pkt_err(ctx, "Invalid HTLC expiry");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
cur->cstate = copy_funding(cur, peer->cstate);
|
||||||
|
if (!funding_delta(peer->them.offer_anchor == CMD_OPEN_WITH_ANCHOR,
|
||||||
|
peer->anchor.satoshis,
|
||||||
|
0, cur->msatoshis,
|
||||||
|
&cur->cstate->b, &cur->cstate->a)) {
|
||||||
|
err = pkt_err(ctx, "Cannot afford %"PRIu64" milli-satoshis",
|
||||||
|
cur->msatoshis);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
/* Add the htlc to their side of channel. */
|
||||||
|
funding_add_htlc(&cur->cstate->b, cur->msatoshis,
|
||||||
|
&cur->expiry, &cur->rhash);
|
||||||
|
|
||||||
|
peer_get_revocation_hash(peer, peer->num_htlcs+1,
|
||||||
|
&cur->our_revocation_hash);
|
||||||
|
|
||||||
|
/* Now we create the commit tx pair. */
|
||||||
|
make_commit_txs(cur, peer, &cur->our_revocation_hash,
|
||||||
|
&cur->their_revocation_hash,
|
||||||
|
cur->cstate,
|
||||||
|
&cur->our_commit, &cur->their_commit);
|
||||||
|
|
||||||
|
/* FIXME: Fees must be sufficient. */
|
||||||
|
*decline = NULL;
|
||||||
|
assert(!peer->current_htlc);
|
||||||
|
peer->current_htlc = cur;
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
tal_free(cur);
|
||||||
|
return err;
|
||||||
|
};
|
||||||
|
|
||||||
Pkt *accept_pkt_htlc_routefail(const tal_t *ctx,
|
Pkt *accept_pkt_htlc_routefail(const tal_t *ctx,
|
||||||
struct peer *peer, const Pkt *pkt)
|
struct peer *peer, const Pkt *pkt)
|
||||||
|
@ -338,23 +423,124 @@ Pkt *accept_pkt_htlc_fulfill(const tal_t *ctx,
|
||||||
FIXME_STUB(peer);
|
FIXME_STUB(peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u64 total_funds(const struct channel_oneside *c)
|
||||||
|
{
|
||||||
|
u64 total = (u64)c->pay_msat + c->fee_msat;
|
||||||
|
size_t i, n = tal_count(c->htlcs);
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
total += c->htlcs[i].msatoshis;
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_to_new_htlcs(struct peer *peer)
|
||||||
|
{
|
||||||
|
struct htlc_progress *cur = peer->current_htlc;
|
||||||
|
|
||||||
|
/* FIXME: Add to shachain too. */
|
||||||
|
|
||||||
|
/* HTLCs can't change total balance in channel! */
|
||||||
|
if (total_funds(&peer->cstate->a) + total_funds(&peer->cstate->b)
|
||||||
|
!= total_funds(&cur->cstate->a) + total_funds(&cur->cstate->b))
|
||||||
|
fatal("Illegal funding transition from %u/%u (total %"PRIu64")"
|
||||||
|
" to %u/%u (total %"PRIu64")",
|
||||||
|
peer->cstate->a.pay_msat, peer->cstate->a.fee_msat,
|
||||||
|
total_funds(&peer->cstate->a),
|
||||||
|
peer->cstate->b.pay_msat, peer->cstate->b.fee_msat,
|
||||||
|
total_funds(&peer->cstate->b));
|
||||||
|
|
||||||
|
/* Now, we consider this channel_state current one. */
|
||||||
|
tal_free(peer->cstate);
|
||||||
|
peer->cstate = tal_steal(peer, cur->cstate);
|
||||||
|
|
||||||
|
tal_free(peer->us.commit);
|
||||||
|
peer->us.commit = tal_steal(peer, cur->our_commit);
|
||||||
|
/* FIXME: Save their old commit details, to steal funds. */
|
||||||
|
tal_free(peer->them.commit);
|
||||||
|
peer->them.commit = tal_steal(peer, cur->their_commit);
|
||||||
|
peer->us.revocation_hash = cur->our_revocation_hash;
|
||||||
|
peer->them.revocation_hash = cur->their_revocation_hash;
|
||||||
|
|
||||||
|
peer->num_htlcs++;
|
||||||
|
}
|
||||||
|
|
||||||
Pkt *accept_pkt_update_accept(const tal_t *ctx,
|
Pkt *accept_pkt_update_accept(const tal_t *ctx,
|
||||||
struct peer *peer, const Pkt *pkt)
|
struct peer *peer, const Pkt *pkt)
|
||||||
{
|
{
|
||||||
FIXME_STUB(peer);
|
const UpdateAccept *a = pkt->update_accept;
|
||||||
|
struct htlc_progress *cur = peer->current_htlc;
|
||||||
|
|
||||||
|
proto_to_sha256(a->revocation_hash, &cur->their_revocation_hash);
|
||||||
|
|
||||||
|
cur->their_sig.stype = SIGHASH_ALL;
|
||||||
|
if (!proto_to_signature(a->sig, &cur->their_sig.sig))
|
||||||
|
return pkt_err(ctx, "Malformed signature");
|
||||||
|
|
||||||
|
/* Now we can make commit tx pair. */
|
||||||
|
make_commit_txs(cur, peer, &cur->our_revocation_hash,
|
||||||
|
&cur->their_revocation_hash,
|
||||||
|
cur->cstate,
|
||||||
|
&cur->our_commit, &cur->their_commit);
|
||||||
|
|
||||||
|
/* Their sig should sign our new commit tx. */
|
||||||
|
if (!check_tx_sig(peer->dstate->secpctx,
|
||||||
|
cur->our_commit, 0,
|
||||||
|
peer->anchor.redeemscript,
|
||||||
|
tal_count(peer->anchor.redeemscript),
|
||||||
|
&peer->them.commitkey,
|
||||||
|
&cur->their_sig))
|
||||||
|
return pkt_err(ctx, "Bad signature");
|
||||||
|
|
||||||
|
/* Our next step will be to send the revocation preimage, so
|
||||||
|
* update to new HTLC now so we never use the old one. */
|
||||||
|
update_to_new_htlcs(peer);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool check_preimage(const Sha256Hash *preimage, const struct sha256 *hash)
|
||||||
|
{
|
||||||
|
struct sha256 h;
|
||||||
|
|
||||||
|
proto_to_sha256(preimage, &h);
|
||||||
|
sha256(&h, &h, sizeof(h));
|
||||||
|
return structeq(&h, hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pkt *accept_pkt_update_complete(const tal_t *ctx,
|
Pkt *accept_pkt_update_complete(const tal_t *ctx,
|
||||||
struct peer *peer, const Pkt *pkt)
|
struct peer *peer, const Pkt *pkt)
|
||||||
{
|
{
|
||||||
FIXME_STUB(peer);
|
/* FIXME: Check preimage against old tx! */
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pkt *accept_pkt_update_signature(const tal_t *ctx,
|
Pkt *accept_pkt_update_signature(const tal_t *ctx,
|
||||||
struct peer *peer,
|
struct peer *peer,
|
||||||
const Pkt *pkt)
|
const Pkt *pkt)
|
||||||
{
|
{
|
||||||
FIXME_STUB(peer);
|
const UpdateSignature *s = pkt->update_signature;
|
||||||
|
struct htlc_progress *cur = peer->current_htlc;
|
||||||
|
|
||||||
|
cur->their_sig.stype = SIGHASH_ALL;
|
||||||
|
if (!proto_to_signature(s->sig, &cur->their_sig.sig))
|
||||||
|
return pkt_err(ctx, "Malformed signature");
|
||||||
|
|
||||||
|
/* Their sig should sign our new commit tx. */
|
||||||
|
if (!check_tx_sig(peer->dstate->secpctx,
|
||||||
|
cur->our_commit, 0,
|
||||||
|
peer->anchor.redeemscript,
|
||||||
|
tal_count(peer->anchor.redeemscript),
|
||||||
|
&peer->them.commitkey,
|
||||||
|
&cur->their_sig))
|
||||||
|
return pkt_err(ctx, "Bad signature");
|
||||||
|
|
||||||
|
/* Check their revocation preimage. */
|
||||||
|
if (!check_preimage(s->revocation_preimage, &peer->them.revocation_hash))
|
||||||
|
return pkt_err(ctx, "Bad revocation preimage");
|
||||||
|
|
||||||
|
/* Our next step will be to send the revocation preimage, so
|
||||||
|
* update to new HTLC now so we never use the old one. */
|
||||||
|
update_to_new_htlcs(peer);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pkt *accept_pkt_close(const tal_t *ctx, struct peer *peer, const Pkt *pkt)
|
Pkt *accept_pkt_close(const tal_t *ctx, struct peer *peer, const Pkt *pkt)
|
||||||
|
|
112
daemon/peer.c
112
daemon/peer.c
|
@ -17,10 +17,12 @@
|
||||||
#include <ccan/io/io.h>
|
#include <ccan/io/io.h>
|
||||||
#include <ccan/list/list.h>
|
#include <ccan/list/list.h>
|
||||||
#include <ccan/noerr/noerr.h>
|
#include <ccan/noerr/noerr.h>
|
||||||
|
#include <ccan/str/hex/hex.h>
|
||||||
#include <ccan/structeq/structeq.h>
|
#include <ccan/structeq/structeq.h>
|
||||||
#include <ccan/tal/str/str.h>
|
#include <ccan/tal/str/str.h>
|
||||||
#include <ccan/tal/tal.h>
|
#include <ccan/tal/tal.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <inttypes.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
@ -35,6 +37,17 @@ struct json_connecting {
|
||||||
u64 satoshis;
|
u64 satoshis;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct peer *find_peer(struct lightningd_state *dstate,
|
||||||
|
const struct pubkey *id)
|
||||||
|
{
|
||||||
|
struct peer *peer;
|
||||||
|
list_for_each(&dstate->peers, peer, list) {
|
||||||
|
if (peer->state != STATE_INIT && pubkey_eq(&peer->id, id))
|
||||||
|
return peer;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void queue_output_pkt(struct peer *peer, Pkt *pkt)
|
static void queue_output_pkt(struct peer *peer, Pkt *pkt)
|
||||||
{
|
{
|
||||||
peer->outpkt[peer->num_outpkt++] = pkt;
|
peer->outpkt[peer->num_outpkt++] = pkt;
|
||||||
|
@ -236,6 +249,8 @@ static struct peer *new_peer(struct lightningd_state *dstate,
|
||||||
list_head_init(&peer->watches);
|
list_head_init(&peer->watches);
|
||||||
peer->num_outpkt = 0;
|
peer->num_outpkt = 0;
|
||||||
peer->cmd = INPUT_NONE;
|
peer->cmd = INPUT_NONE;
|
||||||
|
peer->current_htlc = NULL;
|
||||||
|
peer->num_htlcs = 0;
|
||||||
|
|
||||||
/* If we free peer, conn should be closed, but can't be freed
|
/* If we free peer, conn should be closed, but can't be freed
|
||||||
* immediately so don't make peer a parent. */
|
* immediately so don't make peer a parent. */
|
||||||
|
@ -622,7 +637,7 @@ void peer_htlc_ours_deferred(struct peer *peer)
|
||||||
/* Successfully added/fulfilled/timedout/routefail an HTLC. */
|
/* Successfully added/fulfilled/timedout/routefail an HTLC. */
|
||||||
void peer_htlc_done(struct peer *peer)
|
void peer_htlc_done(struct peer *peer)
|
||||||
{
|
{
|
||||||
FIXME_STUB(peer);
|
peer->current_htlc = tal_free(peer->current_htlc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Someone aborted an existing HTLC. */
|
/* Someone aborted an existing HTLC. */
|
||||||
|
@ -898,3 +913,98 @@ const struct json_command getpeers_command = {
|
||||||
"List the current peers",
|
"List the current peers",
|
||||||
"Returns a 'peers' array"
|
"Returns a 'peers' array"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void json_newhtlc(struct command *cmd,
|
||||||
|
const char *buffer, const jsmntok_t *params)
|
||||||
|
{
|
||||||
|
struct peer *peer;
|
||||||
|
jsmntok_t *idtok, *msatoshistok, *expirytok, *rhashtok;
|
||||||
|
struct pubkey id;
|
||||||
|
unsigned int expiry;
|
||||||
|
struct htlc_progress *cur;
|
||||||
|
|
||||||
|
json_get_params(buffer, params,
|
||||||
|
"id", &idtok,
|
||||||
|
"msatoshis", &msatoshistok,
|
||||||
|
"expiry", &expirytok,
|
||||||
|
"rhash", &rhashtok,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (!idtok || !msatoshistok || !expirytok || !rhashtok) {
|
||||||
|
command_fail(cmd, "Need id, msatoshis, expiry and rhash");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pubkey_from_hexstr(cmd->dstate->secpctx,
|
||||||
|
buffer + idtok->start,
|
||||||
|
idtok->end - idtok->start, &id)) {
|
||||||
|
command_fail(cmd, "Not a valid id");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
peer = find_peer(cmd->dstate, &id);
|
||||||
|
if (!peer) {
|
||||||
|
command_fail(cmd, "Could not find peer with that id");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attach to cmd until it's complete. */
|
||||||
|
cur = tal(cmd, struct htlc_progress);
|
||||||
|
if (!json_tok_u64(buffer, msatoshistok, &cur->msatoshis)) {
|
||||||
|
command_fail(cmd, "'%.*s' is not a valid number",
|
||||||
|
(int)(msatoshistok->end - msatoshistok->start),
|
||||||
|
buffer + msatoshistok->start);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!json_tok_number(buffer, expirytok, &expiry)) {
|
||||||
|
command_fail(cmd, "'%.*s' is not a valid number",
|
||||||
|
(int)(expirytok->end - expirytok->start),
|
||||||
|
buffer + expirytok->start);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!seconds_to_abs_locktime(expiry, &cur->expiry)) {
|
||||||
|
command_fail(cmd, "'%.*s' is not a valid number",
|
||||||
|
(int)(expirytok->end - expirytok->start),
|
||||||
|
buffer + expirytok->start);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!hex_decode(buffer + rhashtok->start,
|
||||||
|
rhashtok->end - rhashtok->start,
|
||||||
|
&cur->rhash, sizeof(cur->rhash))) {
|
||||||
|
command_fail(cmd, "'%.*s' is not a valid sha256 hash",
|
||||||
|
(int)(rhashtok->end - rhashtok->start),
|
||||||
|
buffer + rhashtok->start);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
peer_get_revocation_hash(peer, peer->num_htlcs+1,
|
||||||
|
&cur->our_revocation_hash);
|
||||||
|
|
||||||
|
/* Can we even offer this much? */
|
||||||
|
cur->cstate = copy_funding(cur, peer->cstate);
|
||||||
|
if (!funding_delta(peer->us.offer_anchor == CMD_OPEN_WITH_ANCHOR,
|
||||||
|
peer->anchor.satoshis,
|
||||||
|
0, cur->msatoshis,
|
||||||
|
&cur->cstate->a, &cur->cstate->b)) {
|
||||||
|
command_fail(cmd, "Cannot afford %"PRIu64" milli-satoshis",
|
||||||
|
cur->msatoshis);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Add the htlc to our side of channel. */
|
||||||
|
funding_add_htlc(&cur->cstate->a, cur->msatoshis,
|
||||||
|
&cur->expiry, &cur->rhash);
|
||||||
|
|
||||||
|
peer->current_htlc = tal_steal(peer, cur);
|
||||||
|
peer->jsoncmd = cmd;
|
||||||
|
|
||||||
|
/* FIXME: do we need this? */
|
||||||
|
peer->cmddata.htlc_prog = peer->current_htlc;
|
||||||
|
peer->cmd = CMD_SEND_HTLC_UPDATE;
|
||||||
|
try_command(peer);
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct json_command newhtlc_command = {
|
||||||
|
"newhtlc",
|
||||||
|
json_newhtlc,
|
||||||
|
"Offer {id} an HTLC worth {msatoshis} in {expiry} (in seconds since Jan 1 1970) with {rhash}",
|
||||||
|
"Returns an empty result on success"
|
||||||
|
};
|
||||||
|
|
|
@ -29,6 +29,17 @@ struct peer_visible_state {
|
||||||
struct bitcoin_tx *commit;
|
struct bitcoin_tx *commit;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct htlc_progress {
|
||||||
|
/* Channel funding state, after we've completed htlc. */
|
||||||
|
struct channel_state *cstate;
|
||||||
|
struct abs_locktime expiry;
|
||||||
|
u64 msatoshis;
|
||||||
|
struct sha256 rhash;
|
||||||
|
struct sha256 our_revocation_hash, their_revocation_hash;
|
||||||
|
struct bitcoin_tx *our_commit, *their_commit;
|
||||||
|
struct bitcoin_signature their_sig;
|
||||||
|
};
|
||||||
|
|
||||||
struct peer {
|
struct peer {
|
||||||
/* dstate->peers list */
|
/* dstate->peers list */
|
||||||
struct list_node list;
|
struct list_node list;
|
||||||
|
@ -79,6 +90,11 @@ struct peer {
|
||||||
/* Their signature for our current commit sig. */
|
/* Their signature for our current commit sig. */
|
||||||
struct bitcoin_signature cur_commit_theirsig;
|
struct bitcoin_signature cur_commit_theirsig;
|
||||||
|
|
||||||
|
/* Current HTLC, if any. */
|
||||||
|
struct htlc_progress *current_htlc;
|
||||||
|
/* Number of HTLC updates (== number of previous commit txs) */
|
||||||
|
u64 num_htlcs;
|
||||||
|
|
||||||
/* Current ongoing packetflow */
|
/* Current ongoing packetflow */
|
||||||
struct io_data *io_data;
|
struct io_data *io_data;
|
||||||
|
|
||||||
|
|
|
@ -41,11 +41,13 @@ struct peer_secrets {
|
||||||
struct sha256 revocation_seed;
|
struct sha256 revocation_seed;
|
||||||
};
|
};
|
||||||
|
|
||||||
void peer_sign_theircommit(const struct peer *peer, struct signature *sig)
|
void peer_sign_theircommit(const struct peer *peer,
|
||||||
|
struct bitcoin_tx *commit,
|
||||||
|
struct signature *sig)
|
||||||
{
|
{
|
||||||
/* Commit tx only has one input: that of the anchor. */
|
/* Commit tx only has one input: that of the anchor. */
|
||||||
sign_tx_input(peer->dstate->secpctx,
|
sign_tx_input(peer->dstate->secpctx,
|
||||||
peer->them.commit, 0,
|
commit, 0,
|
||||||
peer->anchor.redeemscript,
|
peer->anchor.redeemscript,
|
||||||
tal_count(peer->anchor.redeemscript),
|
tal_count(peer->anchor.redeemscript),
|
||||||
&peer->secrets->commit,
|
&peer->secrets->commit,
|
||||||
|
|
|
@ -12,7 +12,9 @@ struct sha256;
|
||||||
void privkey_sign(struct peer *peer, const void *src, size_t len,
|
void privkey_sign(struct peer *peer, const void *src, size_t len,
|
||||||
struct signature *sig);
|
struct signature *sig);
|
||||||
|
|
||||||
void peer_sign_theircommit(const struct peer *peer, struct signature *sig);
|
void peer_sign_theircommit(const struct peer *peer,
|
||||||
|
struct bitcoin_tx *commit,
|
||||||
|
struct signature *sig);
|
||||||
|
|
||||||
void peer_secrets_init(struct peer *peer);
|
void peer_secrets_init(struct peer *peer);
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,9 @@ while ! $LCLI2 getlog | grep 'listener on port'; do
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
ID1=`$LCLI1 getlog | sed -n 's/.*"ID: \([0-9a-f]*\)".*/\1/p'`
|
||||||
|
ID2=`$LCLI2 getlog | sed -n 's/.*"ID: \([0-9a-f]*\)".*/\1/p'`
|
||||||
|
|
||||||
PORT2=`$LCLI2 getlog | sed -n 's/.*on port \([0-9]*\).*/\1/p'`
|
PORT2=`$LCLI2 getlog | sed -n 's/.*on port \([0-9]*\).*/\1/p'`
|
||||||
|
|
||||||
$LCLI1 connect localhost $PORT2 999999
|
$LCLI1 connect localhost $PORT2 999999
|
||||||
|
@ -71,6 +74,11 @@ sleep 2
|
||||||
$LCLI1 getpeers | grep STATE_NORMAL_HIGHPRIO
|
$LCLI1 getpeers | grep STATE_NORMAL_HIGHPRIO
|
||||||
$LCLI2 getpeers | grep STATE_NORMAL_LOWPRIO
|
$LCLI2 getpeers | grep STATE_NORMAL_LOWPRIO
|
||||||
|
|
||||||
|
EXPIRY=$(( $(date +%s) + 1000))
|
||||||
|
SECRET=1de08917a61cb2b62ed5937d38577f6a7bfe59c176781c6d8128018e8b5ccdfd
|
||||||
|
RHASH=`$LCLI1 dev-rhash $SECRET | sed 's/.*"\([0-9a-f]*\)".*/\1/'`
|
||||||
|
$LCLI1 newhtlc $ID2 1000000 $EXPIRY $RHASH
|
||||||
|
|
||||||
$LCLI1 stop
|
$LCLI1 stop
|
||||||
$LCLI2 stop
|
$LCLI2 stop
|
||||||
scripts/shutdown.sh
|
scripts/shutdown.sh
|
||||||
|
|
Loading…
Add table
Reference in a new issue