daemon: code to open channel and watch anchor.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2016-01-22 06:45:05 +10:30
parent ecbe671688
commit 3c9fd4fbe6
2 changed files with 136 additions and 5 deletions

View File

@ -1,4 +1,5 @@
#include "bitcoin/script.h"
#include "bitcoin/tx.h"
#include "find_p2sh_out.h"
#include "lightningd.h"
#include "log.h"
@ -9,9 +10,29 @@
#include "state.h"
#include <ccan/crypto/sha256/sha256.h>
#include <ccan/mem/mem.h>
#include <ccan/str/hex/hex.h>
#define FIXME_STUB(peer) do { log_broken((peer)->dstate->base_log, "%s:%u: Implement %s!", __FILE__, __LINE__, __func__); abort(); } while(0)
static char *hex_of(const tal_t *ctx, const void *p, size_t n)
{
char *hex = tal_arr(ctx, char, hex_str_size(n));
hex_encode(p, n, hex, hex_str_size(n));
return hex;
}
static void dump_tx(const char *str, const struct bitcoin_tx *tx)
{
u8 *linear = linearize_tx(NULL, tx);
printf("%s:%s\n", str, hex_of(linear, linear, tal_count(linear)));
tal_free(linear);
}
static void dump_key(const char *str, const struct pubkey *key)
{
printf("%s:%s\n", str, hex_of(NULL, key->der, pubkey_derlen(key)));
}
/* Wrap (and own!) member inside Pkt */
static Pkt *make_pkt(const tal_t *ctx, Pkt__PktCase type, const void *msg)
{
@ -86,12 +107,26 @@ Pkt *pkt_anchor(const tal_t *ctx, const struct peer *peer)
Pkt *pkt_open_commit_sig(const tal_t *ctx, const struct peer *peer)
{
FIXME_STUB(peer);
struct signature sig;
OpenCommitSig *s = tal(ctx, OpenCommitSig);
open_commit_sig__init(s);
dump_tx("Creating sig for:", peer->them.commit);
dump_key("Using key:", &peer->us.commitkey);
peer_sign_theircommit(peer, &sig);
s->sig = signature_to_proto(s, &sig);
return make_pkt(ctx, PKT__PKT_OPEN_COMMIT_SIG, s);
}
Pkt *pkt_open_complete(const tal_t *ctx, const struct peer *peer)
{
FIXME_STUB(peer);
OpenComplete *o = tal(ctx, OpenComplete);
open_complete__init(o);
return make_pkt(ctx, PKT__PKT_OPEN_COMPLETE, o);
}
Pkt *pkt_htlc_update(const tal_t *ctx, const struct peer *peer,
@ -252,7 +287,25 @@ Pkt *accept_pkt_anchor(const tal_t *ctx,
Pkt *accept_pkt_open_commit_sig(const tal_t *ctx,
struct peer *peer, const Pkt *pkt)
{
FIXME_STUB(peer);
const OpenCommitSig *s = pkt->open_commit_sig;
peer->cur_commit_theirsig.stype = SIGHASH_ALL;
if (!proto_to_signature(s->sig, &peer->cur_commit_theirsig.sig))
return pkt_err(ctx, "Malformed signature");
dump_tx("Checking sig for:", peer->us.commit);
dump_key("Using key:", &peer->them.commitkey);
/* Their sig should sign our commit tx. */
if (!check_tx_sig(peer->dstate->secpctx,
peer->us.commit, 0,
peer->anchor.redeemscript,
tal_count(peer->anchor.redeemscript),
&peer->them.commitkey,
&peer->cur_commit_theirsig))
return pkt_err(ctx, "Bad signature");
return NULL;
}
Pkt *accept_pkt_htlc_update(const tal_t *ctx,

View File

@ -17,6 +17,7 @@
#include <ccan/io/io.h>
#include <ccan/list/list.h>
#include <ccan/noerr/noerr.h>
#include <ccan/structeq/structeq.h>
#include <ccan/tal/str/str.h>
#include <ccan/tal/tal.h>
#include <errno.h>
@ -439,7 +440,6 @@ const struct json_command connect_command = {
};
struct anchor_watch {
struct peer *peer;
enum state_input depthok;
enum state_input timeout;
enum state_input unspent;
@ -447,6 +447,71 @@ struct anchor_watch {
enum state_input otherspent;
};
static void anchor_depthchange(struct peer *peer, int depth,
struct anchor_watch *w)
{
/* Still waiting for it to reach depth? */
if (w->depthok != INPUT_NONE) {
/* Beware sign! */
if (depth >= (int)peer->us.mindepth) {
enum state_input in = w->depthok;
w->depthok = INPUT_NONE;
update_state(peer, in, NULL);
}
} else {
if (depth < 0 && w->unspent != INPUT_NONE) {
enum state_input in = w->unspent;
w->unspent = INPUT_NONE;
update_state(peer, in, NULL);
}
}
}
/* We don't compare scriptSigs: we don't know them anyway! */
static bool txmatch(const struct bitcoin_tx *txa, const struct bitcoin_tx *txb)
{
size_t i;
if (txa->version != txb->version
|| txa->input_count != txb->input_count
|| txa->output_count != txb->output_count
|| txa->lock_time != txb->lock_time)
return false;
for (i = 0; i < txa->input_count; i++) {
if (!structeq(&txa->input[i].txid, &txb->input[i].txid)
|| txa->input[i].index != txb->input[i].index
|| txa->input[i].sequence_number != txb->input[i].sequence_number)
return false;
}
for (i = 0; i < txa->output_count; i++) {
if (txa->output[i].amount != txb->output[i].amount
|| txa->output[i].script_length != txb->output[i].script_length
|| memcmp(txa->output[i].script, txb->output[i].script,
txa->output[i].script_length != 0))
return false;
}
return true;
}
/* We assume the tx is valid! Don't do a blockchain.info and feed this
* invalid transactions! */
static void anchor_spent(struct peer *peer,
const struct bitcoin_tx *tx,
struct anchor_watch *w)
{
union input idata;
/* FIXME: change type in idata? */
idata.btc = (struct bitcoin_event *)tx;
if (txmatch(tx, peer->them.commit))
update_state(peer, w->theyspent, &idata);
else
update_state(peer, w->otherspent, &idata);
}
void peer_watch_anchor(struct peer *peer,
enum state_input depthok,
enum state_input timeout,
@ -454,7 +519,20 @@ void peer_watch_anchor(struct peer *peer,
enum state_input theyspent,
enum state_input otherspent)
{
FIXME_STUB(peer);
struct anchor_watch *w = tal(peer, struct anchor_watch);
w->depthok = depthok;
w->timeout = timeout;
w->unspent = unspent;
w->theyspent = theyspent;
w->otherspent = otherspent;
add_anchor_watch(peer, &peer->anchor.txid, peer->anchor.index,
anchor_depthchange,
anchor_spent,
w);
/* FIXME: add timeout */
}
void peer_unwatch_anchor_depth(struct peer *peer,