Browse Source

daemon: add state.c.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 9 years ago
parent
commit
abc002ff15
  1. 6
      daemon/Makefile
  2. 270
      daemon/packets.c
  3. 275
      daemon/peer.c
  4. 13
      daemon/peer.h

6
daemon/Makefile

@ -21,9 +21,13 @@ DAEMON_SRC := \
daemon/lightningd.c \
daemon/netaddr.c \
daemon/peer.c \
daemon/packets.c \
daemon/secrets.c \
daemon/timeout.c \
daemon/watch.c
daemon/watch.c \
names.c \
state.c
DAEMON_OBJS := $(DAEMON_SRC:.c=.o)
DAEMON_CLI_SRC := daemon/lightning-cli.c

270
daemon/packets.c

@ -0,0 +1,270 @@
#include "lightningd.h"
#include "log.h"
#include "names.h"
#include "peer.h"
#include "protobuf_convert.h"
#include "secrets.h"
#include "state.h"
#include <ccan/crypto/sha256/sha256.h>
#include <ccan/mem/mem.h>
#define FIXME_STUB(peer) do { log_broken((peer)->dstate->base_log, "%s:%u: Implement %s!", __FILE__, __LINE__, __func__); abort(); } while(0)
/* Wrap (and own!) member inside Pkt */
static Pkt *make_pkt(const tal_t *ctx, Pkt__PktCase type, const void *msg)
{
Pkt *pkt = tal(ctx, Pkt);
pkt__init(pkt);
pkt->pkt_case = type;
/* This is a union, so doesn't matter which we assign. */
pkt->error = (Error *)tal_steal(ctx, msg);
/* This makes sure all packets are valid. */
#ifndef NDEBUG
{
size_t len;
u8 *packed;
Pkt *cpy;
len = pkt__get_packed_size(pkt);
packed = tal_arr(pkt, u8, len);
pkt__pack(pkt, packed);
cpy = pkt__unpack(NULL, len, memcheck(packed, len));
assert(cpy);
pkt__free_unpacked(cpy, NULL);
tal_free(packed);
}
#endif
return pkt;
}
Pkt *pkt_open(const tal_t *ctx, const struct peer *peer,
OpenChannel__AnchorOffer anchor)
{
struct sha256 revocation_hash;
OpenChannel *o = tal(ctx, OpenChannel);
open_channel__init(o);
peer_get_revocation_hash(peer, 0, &revocation_hash);
o->revocation_hash = sha256_to_proto(ctx, &revocation_hash);
o->commit_key = pubkey_to_proto(o, &peer->us.commitkey);
o->final_key = pubkey_to_proto(o, &peer->us.finalkey);
o->delay = tal(o, Locktime);
locktime__init(o->delay);
o->delay->locktime_case = LOCKTIME__LOCKTIME_SECONDS;
o->delay->seconds = rel_locktime_to_seconds(&peer->us.locktime);
o->commitment_fee = peer->us.commit_fee;
if (anchor == OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR)
assert(peer->us.offer_anchor == CMD_OPEN_WITH_ANCHOR);
else {
assert(anchor == OPEN_CHANNEL__ANCHOR_OFFER__WONT_CREATE_ANCHOR);
assert(peer->us.offer_anchor == CMD_OPEN_WITHOUT_ANCHOR);
}
o->anch = anchor;
o->min_depth = peer->us.mindepth;
return make_pkt(ctx, PKT__PKT_OPEN, o);
}
Pkt *pkt_anchor(const tal_t *ctx, const struct peer *peer)
{
FIXME_STUB(peer);
}
Pkt *pkt_open_commit_sig(const tal_t *ctx, const struct peer *peer)
{
FIXME_STUB(peer);
}
Pkt *pkt_open_complete(const tal_t *ctx, const struct peer *peer)
{
FIXME_STUB(peer);
}
Pkt *pkt_htlc_update(const tal_t *ctx, const struct peer *peer,
const struct htlc_progress *htlc_prog)
{
FIXME_STUB(peer);
}
Pkt *pkt_htlc_fulfill(const tal_t *ctx, const struct peer *peer,
const struct htlc_progress *htlc_prog)
{
FIXME_STUB(peer);
}
Pkt *pkt_htlc_timedout(const tal_t *ctx, const struct peer *peer,
const struct htlc_progress *htlc_prog)
{
FIXME_STUB(peer);
}
Pkt *pkt_htlc_routefail(const tal_t *ctx, const struct peer *peer,
const struct htlc_progress *htlc_prog)
{
FIXME_STUB(peer);
}
Pkt *pkt_update_accept(const tal_t *ctx, const struct peer *peer)
{
FIXME_STUB(peer);
}
Pkt *pkt_update_signature(const tal_t *ctx, const struct peer *peer)
{
FIXME_STUB(peer);
}
Pkt *pkt_update_complete(const tal_t *ctx, const struct peer *peer)
{
FIXME_STUB(peer);
}
Pkt *pkt_err(const tal_t *ctx, const char *msg, ...)
{
abort();
}
Pkt *pkt_close(const tal_t *ctx, const struct peer *peer)
{
FIXME_STUB(peer);
}
Pkt *pkt_close_complete(const tal_t *ctx, const struct peer *peer)
{
FIXME_STUB(peer);
}
Pkt *pkt_close_ack(const tal_t *ctx, const struct peer *peer)
{
FIXME_STUB(peer);
}
Pkt *pkt_err_unexpected(const tal_t *ctx, const Pkt *pkt)
{
return pkt_err(ctx, "Unexpected packet %s", state_name(pkt->pkt_case));
}
/* Process various packets: return an error packet on failure. */
Pkt *accept_pkt_open(const tal_t *ctx,
struct peer *peer, const Pkt *pkt)
{
struct rel_locktime locktime;
OpenChannel *o = pkt->open;
if (!proto_to_rel_locktime(o->delay, &locktime))
return pkt_err(ctx, "Invalid delay");
/* FIXME: handle blocks in locktime */
if (o->delay->locktime_case != LOCKTIME__LOCKTIME_SECONDS)
return pkt_err(ctx, "Delay in blocks not accepted");
if (o->delay->seconds > peer->dstate->config.rel_locktime_max)
return pkt_err(ctx, "Delay too great");
if (o->min_depth > peer->dstate->config.anchor_confirms_max)
return pkt_err(ctx, "min_depth too great");
if (o->commitment_fee < peer->dstate->config.commitment_fee_min)
return pkt_err(ctx, "Commitment fee too low");
if (o->anch == OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR)
peer->them.offer_anchor = CMD_OPEN_WITH_ANCHOR;
else if (o->anch == OPEN_CHANNEL__ANCHOR_OFFER__WONT_CREATE_ANCHOR)
peer->them.offer_anchor = CMD_OPEN_WITHOUT_ANCHOR;
else
return pkt_err(ctx, "Unknown offer anchor value");
if (peer->them.offer_anchor == peer->us.offer_anchor)
return pkt_err(ctx, "Only one side can offer anchor");
if (!proto_to_rel_locktime(o->delay, &peer->them.locktime))
return pkt_err(ctx, "Malformed locktime");
peer->them.mindepth = o->min_depth;
peer->them.commit_fee = o->commitment_fee;
if (!proto_to_pubkey(peer->dstate->secpctx,
o->commit_key, &peer->them.commitkey))
return pkt_err(ctx, "Bad commitkey");
if (!proto_to_pubkey(peer->dstate->secpctx,
o->final_key, &peer->them.finalkey))
return pkt_err(ctx, "Bad finalkey");
proto_to_sha256(o->revocation_hash, &peer->their_rhash);
return NULL;
}
Pkt *accept_pkt_anchor(const tal_t *ctx,
struct peer *peer,
const Pkt *pkt)
{
FIXME_STUB(peer);
}
Pkt *accept_pkt_open_commit_sig(const tal_t *ctx,
struct peer *peer, const Pkt *pkt)
{
FIXME_STUB(peer);
}
Pkt *accept_pkt_htlc_update(const tal_t *ctx,
struct peer *peer, const Pkt *pkt,
Pkt **decline)
{
FIXME_STUB(peer);
}
Pkt *accept_pkt_htlc_routefail(const tal_t *ctx,
struct peer *peer, const Pkt *pkt)
{
FIXME_STUB(peer);
}
Pkt *accept_pkt_htlc_timedout(const tal_t *ctx,
struct peer *peer, const Pkt *pkt)
{
FIXME_STUB(peer);
}
Pkt *accept_pkt_htlc_fulfill(const tal_t *ctx,
struct peer *peer, const Pkt *pkt)
{
FIXME_STUB(peer);
}
Pkt *accept_pkt_update_accept(const tal_t *ctx,
struct peer *peer, const Pkt *pkt)
{
FIXME_STUB(peer);
}
Pkt *accept_pkt_update_complete(const tal_t *ctx,
struct peer *peer, const Pkt *pkt)
{
FIXME_STUB(peer);
}
Pkt *accept_pkt_update_signature(const tal_t *ctx,
struct peer *peer,
const Pkt *pkt)
{
FIXME_STUB(peer);
}
Pkt *accept_pkt_close(const tal_t *ctx, struct peer *peer, const Pkt *pkt)
{
FIXME_STUB(peer);
}
Pkt *accept_pkt_close_complete(const tal_t *ctx,
struct peer *peer, const Pkt *pkt)
{
FIXME_STUB(peer);
}
Pkt *accept_pkt_simultaneous_close(const tal_t *ctx,
struct peer *peer,
const Pkt *pkt)
{
FIXME_STUB(peer);
}
Pkt *accept_pkt_close_ack(const tal_t *ctx, struct peer *peer, const Pkt *pkt)
{
FIXME_STUB(peer);
}

275
daemon/peer.c

@ -4,6 +4,7 @@
#include "lightningd.h"
#include "log.h"
#include "peer.h"
#include "state.h"
#include <ccan/io/io.h>
#include <ccan/list/list.h>
#include <ccan/noerr/noerr.h>
@ -15,6 +16,8 @@
#include <sys/socket.h>
#include <sys/types.h>
#define FIXME_STUB(peer) do { log_broken((peer)->dstate->base_log, "%s:%u: Implement %s!", __FILE__, __LINE__, __func__); abort(); } while(0)
struct json_connecting {
/* This owns us, so we're freed after command_fail or command_success */
struct command *cmd;
@ -69,6 +72,8 @@ static struct peer *new_peer(struct lightningd_state *dstate,
/* FIXME: Stop listening if too many peers? */
list_add(&dstate->peers, &peer->list);
peer->state = STATE_INIT;
peer->cond = PEER_CMD_OK;
peer->dstate = dstate;
peer->addr.type = addr_type;
peer->addr.protocol = addr_protocol;
@ -77,7 +82,10 @@ static struct peer *new_peer(struct lightningd_state *dstate,
list_head_init(&peer->watches);
peer->us.offer_anchor = offer_anchor;
peer->us.locktime = dstate->config.rel_locktime;
if (!seconds_to_rel_locktime(dstate->config.rel_locktime,
&peer->us.locktime))
fatal("Invalid locktime configuration %u",
dstate->config.rel_locktime);
peer->us.mindepth = dstate->config.anchor_confirms;
/* FIXME: Make this dynamic. */
peer->us.commit_fee = dstate->config.commitment_fee;
@ -261,6 +269,271 @@ const struct json_command connect_command = {
"Returns an empty result on success"
};
struct anchor_watch {
struct peer *peer;
enum state_input depthok;
enum state_input timeout;
enum state_input unspent;
enum state_input theyspent;
enum state_input otherspent;
};
void peer_watch_anchor(struct peer *peer,
enum state_input depthok,
enum state_input timeout,
enum state_input unspent,
enum state_input theyspent,
enum state_input otherspent)
{
FIXME_STUB(peer);
}
void peer_unwatch_anchor_depth(struct peer *peer,
enum state_input depthok,
enum state_input timeout)
{
FIXME_STUB(peer);
}
void peer_watch_delayed(struct peer *peer,
const struct bitcoin_tx *tx,
enum state_input canspend)
{
FIXME_STUB(peer);
}
void peer_watch_tx(struct peer *peer,
const struct bitcoin_tx *tx,
enum state_input done)
{
FIXME_STUB(peer);
}
void peer_watch_close(struct peer *peer,
enum state_input done, enum state_input timedout)
{
FIXME_STUB(peer);
}
void peer_unwatch_close_timeout(struct peer *peer, enum state_input timedout)
{
FIXME_STUB(peer);
}
bool peer_watch_our_htlc_outputs(struct peer *peer,
const struct bitcoin_tx *tx,
enum state_input tous_timeout,
enum state_input tothem_spent,
enum state_input tothem_timeout)
{
FIXME_STUB(peer);
}
bool peer_watch_their_htlc_outputs(struct peer *peer,
const struct bitcoin_event *tx,
enum state_input tous_timeout,
enum state_input tothem_spent,
enum state_input tothem_timeout)
{
FIXME_STUB(peer);
}
void peer_unwatch_htlc_output(struct peer *peer,
const struct htlc *htlc,
enum state_input all_done)
{
FIXME_STUB(peer);
}
void peer_unwatch_all_htlc_outputs(struct peer *peer)
{
FIXME_STUB(peer);
}
void peer_watch_htlc_spend(struct peer *peer,
const struct bitcoin_tx *tx,
const struct htlc *htlc,
enum state_input done)
{
FIXME_STUB(peer);
}
void peer_unwatch_htlc_spend(struct peer *peer,
const struct htlc *htlc,
enum state_input all_done)
{
FIXME_STUB(peer);
}
void peer_unexpected_pkt(struct peer *peer, const Pkt *pkt)
{
FIXME_STUB(peer);
}
/* Someone declined our HTLC: details in pkt (we will also get CMD_FAIL) */
void peer_htlc_declined(struct peer *peer, const Pkt *pkt)
{
FIXME_STUB(peer);
}
/* Called when their update overrides our update cmd. */
void peer_htlc_ours_deferred(struct peer *peer)
{
FIXME_STUB(peer);
}
/* Successfully added/fulfilled/timedout/routefail an HTLC. */
void peer_htlc_done(struct peer *peer)
{
FIXME_STUB(peer);
}
/* Someone aborted an existing HTLC. */
void peer_htlc_aborted(struct peer *peer)
{
FIXME_STUB(peer);
}
/* An on-chain transaction revealed an R value. */
const struct htlc *peer_tx_revealed_r_value(struct peer *peer,
const struct bitcoin_event *btc)
{
FIXME_STUB(peer);
}
bool committed_to_htlcs(const struct peer *peer)
{
FIXME_STUB(peer);
}
/* Create a bitcoin close tx. */
const struct bitcoin_tx *bitcoin_close(const tal_t *ctx,
const struct peer *peer)
{
#if 0
struct bitcoin_tx *close_tx;
u8 *redeemscript;
close_tx = create_close_tx(ctx, peer->us.openpkt, peer->them.openpkt,
peer->anchorpkt,
peer->cstate.a.pay_msat / 1000,
peer->cstate.b.pay_msat / 1000);
/* This is what the anchor pays to. */
redeemscript = bitcoin_redeem_2of2(close_tx, &peer->us.commitkey,
&peer->them.commitkey);
/* Combined signatures must validate correctly. */
if (!check_2of2_sig(close_tx, 0, redeemscript, tal_count(redeemscript),
&peer->us.finalkey, &peer->them.finalkey,
&peer->us.closesig, &peer->them.closesig))
fatal("bitcoin_close signature failed");
/* Create p2sh input for close_tx */
close_tx->input[0].script = scriptsig_p2sh_2of2(close_tx,
&peer->us.closesig,
&peer->them.closesig,
&peer->us.finalkey,
&peer->them.finalkey);
close_tx->input[0].script_length = tal_count(close_tx->input[0].script);
return close_tx;
#endif
FIXME_STUB(peer);
}
/* Create a bitcoin spend tx (to spend our commit's outputs) */
const struct bitcoin_tx *bitcoin_spend_ours(const tal_t *ctx,
const struct peer *peer)
{
#if 0
u8 *redeemscript;
redeemscript = bitcoin_redeem_secret_or_delay(ctx,
&peer->us.commitkey,
&peer->them.locktime,
&peer->them.commitkey,
&peer->revocation_hash);
/* Now, create transaction to spend it. */
tx = bitcoin_tx(ctx, 1, 1);
bitcoin_txid(commit, &tx->input[0].txid);
p2sh_out = find_p2sh_out(commit, redeemscript);
tx->input[0].index = p2sh_out;
tx->input[0].input_amount = commit->output[p2sh_out].amount;
tx->fee = fee;
tx->input[0].sequence_number = bitcoin_nsequence(locktime);
if (commit->output[p2sh_out].amount <= fee)
errx(1, "Amount of %llu won't exceed fee",
(unsigned long long)commit->output[p2sh_out].amount);
tx->output[0].amount = commit->output[p2sh_out].amount - fee;
tx->output[0].script = scriptpubkey_p2sh(tx,
bitcoin_redeem_single(tx, &outpubkey));
tx->output[0].script_length = tal_count(tx->output[0].script);
/* Now get signature, to set up input script. */
if (!sign_tx_input(tx, 0, redeemscript, tal_count(redeemscript),
&privkey, &pubkey1, &sig.sig))
errx(1, "Could not sign tx");
sig.stype = SIGHASH_ALL;
tx->input[0].script = scriptsig_p2sh_secret(tx, NULL, 0, &sig,
redeemscript,
tal_count(redeemscript));
tx->input[0].script_length = tal_count(tx->input[0].script);
#endif
FIXME_STUB(peer);
}
/* Create a bitcoin spend tx (to spend their commit's outputs) */
const struct bitcoin_tx *bitcoin_spend_theirs(const tal_t *ctx,
const struct peer *peer,
const struct bitcoin_event *btc)
{
FIXME_STUB(peer);
}
/* Create a bitcoin steal tx (to steal all their commit's outputs) */
const struct bitcoin_tx *bitcoin_steal(const tal_t *ctx,
const struct peer *peer,
struct bitcoin_event *btc)
{
FIXME_STUB(peer);
}
/* Create our commit tx */
const struct bitcoin_tx *bitcoin_commit(const tal_t *ctx, struct peer *peer)
{
FIXME_STUB(peer);
}
/* Create a HTLC refund collection */
const struct bitcoin_tx *bitcoin_htlc_timeout(const tal_t *ctx,
const struct peer *peer,
const struct htlc *htlc)
{
FIXME_STUB(peer);
}
/* Create a HTLC collection */
const struct bitcoin_tx *bitcoin_htlc_spend(const tal_t *ctx,
const struct peer *peer,
const struct htlc *htlc)
{
FIXME_STUB(peer);
}
/* Start creation of the bitcoin anchor tx. */
void bitcoin_create_anchor(struct peer *peer, enum state_input done)
{
FIXME_STUB(peer);
}
/* We didn't end up broadcasting the anchor: release the utxos.
* If done != INPUT_NONE, remove existing create_anchor too. */
void bitcoin_release_anchor(struct peer *peer, enum state_input done)
{
FIXME_STUB(peer);
}
/* Get the bitcoin anchor tx. */
const struct bitcoin_tx *bitcoin_anchor(const tal_t *ctx, struct peer *peer)
{
FIXME_STUB(peer);
}
/* FIXME: Somehow we should show running DNS lookups! */
/* FIXME: Show status of peers! */
static void json_getpeers(struct command *cmd,

13
daemon/peer.h

@ -1,10 +1,12 @@
#ifndef LIGHTNING_DAEMON_PEER_H
#define LIGHTNING_DAEMON_PEER_H
#include "config.h"
#include "bitcoin/locktime.h"
#include "bitcoin/pubkey.h"
#include "lightning.pb-c.h"
#include "netaddr.h"
#include "state_types.h"
#include <ccan/crypto/sha256/sha256.h>
#include <ccan/list/list.h>
struct peer_visible_state {
@ -13,7 +15,7 @@ struct peer_visible_state {
/* Key for commitment tx inputs, then key for commitment tx outputs */
struct pubkey commitkey, finalkey;
/* How long to they want the other's outputs locked (seconds) */
unsigned int locktime;
struct rel_locktime locktime;
/* Minimum depth of anchor before channel usable. */
unsigned int mindepth;
/* Commitment fee they're offering (satoshi). */
@ -24,6 +26,12 @@ struct peer {
/* dstate->peers list */
struct list_node list;
/* State in state machine. */
enum state state;
/* Condition of communications */
enum state_peercond cond;
/* Global state. */
struct lightningd_state *dstate;
@ -50,6 +58,9 @@ struct peer {
/* Stuff we have in common. */
struct peer_visible_state us, them;
/* Their last revocation hash. */
struct sha256 their_rhash;
};
void setup_listeners(struct lightningd_state *dstate, unsigned int portnum);

Loading…
Cancel
Save