|
|
@ -11,6 +11,7 @@ |
|
|
|
#include <ccan/structeq/structeq.h> |
|
|
|
#include <ccan/tal/str/str.h> |
|
|
|
#include <inttypes.h> |
|
|
|
#include "wire/gen_peer_wire.h" |
|
|
|
|
|
|
|
/* 365.25 * 24 * 60 / 10 */ |
|
|
|
#define BLOCKS_PER_YEAR 52596 |
|
|
@ -635,3 +636,207 @@ u8 *write_ip(const tal_t *ctx, const char *srcip, int port) |
|
|
|
return address; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void handle_channel_announcement( |
|
|
|
struct routing_state *rstate, |
|
|
|
const u8 *announce, size_t len) |
|
|
|
{ |
|
|
|
u8 *serialized; |
|
|
|
bool forward = false; |
|
|
|
secp256k1_ecdsa_signature node_signature_1; |
|
|
|
secp256k1_ecdsa_signature node_signature_2; |
|
|
|
struct channel_id channel_id; |
|
|
|
secp256k1_ecdsa_signature bitcoin_signature_1; |
|
|
|
secp256k1_ecdsa_signature bitcoin_signature_2; |
|
|
|
struct pubkey node_id_1; |
|
|
|
struct pubkey node_id_2; |
|
|
|
struct pubkey bitcoin_key_1; |
|
|
|
struct pubkey bitcoin_key_2; |
|
|
|
const tal_t *tmpctx = tal_tmpctx(rstate); |
|
|
|
u8 *features; |
|
|
|
|
|
|
|
serialized = tal_dup_arr(tmpctx, u8, announce, len, 0); |
|
|
|
if (!fromwire_channel_announcement(tmpctx, serialized, NULL, |
|
|
|
&node_signature_1, &node_signature_2, |
|
|
|
&bitcoin_signature_1, |
|
|
|
&bitcoin_signature_2, |
|
|
|
&channel_id, |
|
|
|
&node_id_1, &node_id_2, |
|
|
|
&bitcoin_key_1, &bitcoin_key_2, |
|
|
|
&features)) { |
|
|
|
tal_free(tmpctx); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// FIXME: Check features!
|
|
|
|
//FIXME(cdecker) Check signatures, when the spec is settled
|
|
|
|
//FIXME(cdecker) Check chain topology for the anchor TX
|
|
|
|
|
|
|
|
log_debug(rstate->base_log, |
|
|
|
"Received channel_announcement for channel %d:%d:%d", |
|
|
|
channel_id.blocknum, |
|
|
|
channel_id.txnum, |
|
|
|
channel_id.outnum |
|
|
|
); |
|
|
|
|
|
|
|
forward |= add_channel_direction(rstate, &node_id_1, |
|
|
|
&node_id_2, 0, &channel_id, |
|
|
|
serialized); |
|
|
|
forward |= add_channel_direction(rstate, &node_id_2, |
|
|
|
&node_id_1, 1, &channel_id, |
|
|
|
serialized); |
|
|
|
if (!forward){ |
|
|
|
log_debug(rstate->base_log, "Not forwarding channel_announcement"); |
|
|
|
tal_free(tmpctx); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
u8 *tag = tal_arr(tmpctx, u8, 0); |
|
|
|
towire_channel_id(&tag, &channel_id); |
|
|
|
queue_broadcast(rstate->broadcasts, WIRE_CHANNEL_ANNOUNCEMENT, |
|
|
|
tag, serialized); |
|
|
|
|
|
|
|
tal_free(tmpctx); |
|
|
|
} |
|
|
|
|
|
|
|
void handle_channel_update(struct routing_state *rstate, const u8 *update, size_t len) |
|
|
|
{ |
|
|
|
u8 *serialized; |
|
|
|
struct node_connection *c; |
|
|
|
secp256k1_ecdsa_signature signature; |
|
|
|
struct channel_id channel_id; |
|
|
|
u32 timestamp; |
|
|
|
u16 flags; |
|
|
|
u16 expiry; |
|
|
|
u32 htlc_minimum_msat; |
|
|
|
u32 fee_base_msat; |
|
|
|
u32 fee_proportional_millionths; |
|
|
|
const tal_t *tmpctx = tal_tmpctx(rstate); |
|
|
|
|
|
|
|
serialized = tal_dup_arr(tmpctx, u8, update, len, 0); |
|
|
|
if (!fromwire_channel_update(serialized, NULL, &signature, &channel_id, |
|
|
|
×tamp, &flags, &expiry, |
|
|
|
&htlc_minimum_msat, &fee_base_msat, |
|
|
|
&fee_proportional_millionths)) { |
|
|
|
tal_free(tmpctx); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
log_debug(rstate->base_log, "Received channel_update for channel %d:%d:%d(%d)", |
|
|
|
channel_id.blocknum, |
|
|
|
channel_id.txnum, |
|
|
|
channel_id.outnum, |
|
|
|
flags & 0x01 |
|
|
|
); |
|
|
|
|
|
|
|
c = get_connection_by_cid(rstate, &channel_id, flags & 0x1); |
|
|
|
|
|
|
|
if (!c) { |
|
|
|
log_debug(rstate->base_log, "Ignoring update for unknown channel %d:%d:%d", |
|
|
|
channel_id.blocknum, |
|
|
|
channel_id.txnum, |
|
|
|
channel_id.outnum |
|
|
|
); |
|
|
|
tal_free(tmpctx); |
|
|
|
return; |
|
|
|
} else if (c->last_timestamp >= timestamp) { |
|
|
|
log_debug(rstate->base_log, "Ignoring outdated update."); |
|
|
|
tal_free(tmpctx); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
//FIXME(cdecker) Check signatures
|
|
|
|
c->last_timestamp = timestamp; |
|
|
|
c->delay = expiry; |
|
|
|
c->htlc_minimum_msat = htlc_minimum_msat; |
|
|
|
c->base_fee = fee_base_msat; |
|
|
|
c->proportional_fee = fee_proportional_millionths; |
|
|
|
c->active = true; |
|
|
|
log_debug(rstate->base_log, "Channel %d:%d:%d(%d) was updated.", |
|
|
|
channel_id.blocknum, |
|
|
|
channel_id.txnum, |
|
|
|
channel_id.outnum, |
|
|
|
flags |
|
|
|
); |
|
|
|
|
|
|
|
u8 *tag = tal_arr(tmpctx, u8, 0); |
|
|
|
towire_channel_id(&tag, &channel_id); |
|
|
|
queue_broadcast(rstate->broadcasts, |
|
|
|
WIRE_CHANNEL_UPDATE, |
|
|
|
tag, |
|
|
|
serialized); |
|
|
|
|
|
|
|
tal_free(c->channel_update); |
|
|
|
c->channel_update = tal_steal(c, serialized); |
|
|
|
tal_free(tmpctx); |
|
|
|
} |
|
|
|
|
|
|
|
void handle_node_announcement( |
|
|
|
struct routing_state *rstate, const u8 *node_ann, size_t len) |
|
|
|
{ |
|
|
|
u8 *serialized; |
|
|
|
struct sha256_double hash; |
|
|
|
struct node *node; |
|
|
|
secp256k1_ecdsa_signature signature; |
|
|
|
u32 timestamp; |
|
|
|
struct pubkey node_id; |
|
|
|
u8 rgb_color[3]; |
|
|
|
u8 alias[32]; |
|
|
|
u8 *features, *addresses; |
|
|
|
const tal_t *tmpctx = tal_tmpctx(rstate); |
|
|
|
|
|
|
|
serialized = tal_dup_arr(tmpctx, u8, node_ann, len, 0); |
|
|
|
if (!fromwire_node_announcement(tmpctx, serialized, NULL, |
|
|
|
&signature, ×tamp, |
|
|
|
&node_id, rgb_color, alias, &features, |
|
|
|
&addresses)) { |
|
|
|
tal_free(tmpctx); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// FIXME: Check features!
|
|
|
|
log_debug_struct(rstate->base_log, |
|
|
|
"Received node_announcement for node %s", |
|
|
|
struct pubkey, &node_id); |
|
|
|
|
|
|
|
sha256_double(&hash, serialized + 66, tal_count(serialized) - 66); |
|
|
|
if (!check_signed_hash(&hash, &signature, &node_id)) { |
|
|
|
log_debug(rstate->base_log, |
|
|
|
"Ignoring node announcement, signature verification failed."); |
|
|
|
tal_free(tmpctx); |
|
|
|
return; |
|
|
|
} |
|
|
|
node = get_node(rstate, &node_id); |
|
|
|
|
|
|
|
if (!node) { |
|
|
|
log_debug(rstate->base_log, |
|
|
|
"Node not found, was the node_announcement preceeded by at least channel_announcement?"); |
|
|
|
tal_free(tmpctx); |
|
|
|
return; |
|
|
|
} else if (node->last_timestamp >= timestamp) { |
|
|
|
log_debug(rstate->base_log, |
|
|
|
"Ignoring node announcement, it's outdated."); |
|
|
|
tal_free(tmpctx); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
node->last_timestamp = timestamp; |
|
|
|
node->hostname = tal_free(node->hostname); |
|
|
|
if (!read_ip(node, addresses, &node->hostname, &node->port)) { |
|
|
|
/* FIXME: SHOULD fail connection here. */ |
|
|
|
tal_free(serialized); |
|
|
|
return; |
|
|
|
} |
|
|
|
memcpy(node->rgb_color, rgb_color, 3); |
|
|
|
|
|
|
|
u8 *tag = tal_arr(tmpctx, u8, 0); |
|
|
|
towire_pubkey(&tag, &node_id); |
|
|
|
queue_broadcast(rstate->broadcasts, |
|
|
|
WIRE_NODE_ANNOUNCEMENT, |
|
|
|
tag, |
|
|
|
serialized); |
|
|
|
tal_free(node->node_announcement); |
|
|
|
node->node_announcement = tal_steal(node, serialized); |
|
|
|
tal_free(tmpctx); |
|
|
|
} |
|
|
|