mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-19 05:44:12 +01:00
gossipd: store and index most recent and last non-rate-limited gossip
This grows the routing state in order to index both okay-to-broadcast and rate-limited gossip. The gossip_store also logs the rate-limited gossip if useful. This allows the broadcast of the last non-rate-limited gossip.
This commit is contained in:
parent
08a2b3b86c
commit
87a66c1802
@ -368,6 +368,7 @@ static struct node *new_node(struct routing_state *rstate,
|
||||
n->id = *id;
|
||||
memset(n->chans.arr, 0, sizeof(n->chans.arr));
|
||||
broadcastable_init(&n->bcast);
|
||||
broadcastable_init(&n->rgraph);
|
||||
n->tokens = TOKEN_MAX;
|
||||
node_map_add(rstate->nodes, n);
|
||||
tal_add_destructor2(n, destroy_node, rstate);
|
||||
@ -521,6 +522,7 @@ static void init_half_chan(struct routing_state *rstate,
|
||||
struct half_chan *c = &chan->half[channel_idx];
|
||||
|
||||
broadcastable_init(&c->bcast);
|
||||
broadcastable_init(&c->rgraph);
|
||||
c->tokens = TOKEN_MAX;
|
||||
}
|
||||
|
||||
@ -1340,7 +1342,7 @@ bool routing_add_channel_update(struct routing_state *rstate,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (timestamp <= hc->bcast.timestamp) {
|
||||
if (timestamp <= hc->rgraph.timestamp) {
|
||||
SUPERVERBOSE("Ignoring outdated update.");
|
||||
/* Ignoring != failing */
|
||||
return true;
|
||||
@ -1377,15 +1379,34 @@ bool routing_add_channel_update(struct routing_state *rstate,
|
||||
} else {
|
||||
spam = false;
|
||||
}
|
||||
|
||||
chan->half[direction].bcast.timestamp = timestamp;
|
||||
|
||||
/* Safe even if was never added, but if it's a private channel it
|
||||
* would be a WIRE_GOSSIP_STORE_PRIVATE_UPDATE. */
|
||||
gossip_store_delete(rstate->gs, &hc->bcast,
|
||||
is_chan_public(chan)
|
||||
? WIRE_CHANNEL_UPDATE
|
||||
: WIRE_GOSSIP_STORE_PRIVATE_UPDATE);
|
||||
/* Routing graph always uses the latest message. */
|
||||
hc->rgraph.timestamp = timestamp;
|
||||
if (spam) {
|
||||
/* Remove the prior spam update if it exists. */
|
||||
if (hc->rgraph.index != hc->bcast.index) {
|
||||
gossip_store_delete(rstate->gs, &hc->rgraph,
|
||||
is_chan_public(chan)
|
||||
? WIRE_CHANNEL_UPDATE
|
||||
: WIRE_GOSSIP_STORE_PRIVATE_UPDATE);
|
||||
}
|
||||
} else {
|
||||
/* Safe to broadcast */
|
||||
hc->bcast.timestamp = timestamp;
|
||||
/* Remove prior spam update if one exists. */
|
||||
if (hc->rgraph.index != hc->bcast.index) {
|
||||
/* Safe even if was never added, but if it's a
|
||||
* private channel it would be a
|
||||
* WIRE_GOSSIP_STORE_PRIVATE_UPDATE. */
|
||||
gossip_store_delete(rstate->gs, &hc->rgraph,
|
||||
is_chan_public(chan)
|
||||
? WIRE_CHANNEL_UPDATE
|
||||
: WIRE_GOSSIP_STORE_PRIVATE_UPDATE);
|
||||
}
|
||||
gossip_store_delete(rstate->gs, &hc->bcast,
|
||||
is_chan_public(chan)
|
||||
? WIRE_CHANNEL_UPDATE
|
||||
: WIRE_GOSSIP_STORE_PRIVATE_UPDATE);
|
||||
}
|
||||
|
||||
/* BOLT #7:
|
||||
* - MUST consider the `timestamp` of the `channel_announcement` to be
|
||||
@ -1407,23 +1428,31 @@ bool routing_add_channel_update(struct routing_state *rstate,
|
||||
hc->bcast.index
|
||||
= gossip_store_add_private_update(rstate->gs,
|
||||
update);
|
||||
} else
|
||||
/* No need to separately track spam for private
|
||||
* channels. */
|
||||
hc->rgraph.index = hc->bcast.index;
|
||||
} else {
|
||||
hc->bcast.index = index;
|
||||
hc->rgraph.index = index;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* If we're loading from store, this means we don't re-add to store. */
|
||||
if (index)
|
||||
hc->bcast.index = index;
|
||||
else {
|
||||
hc->bcast.index
|
||||
= gossip_store_add(rstate->gs, update,
|
||||
hc->bcast.timestamp,
|
||||
if (index) {
|
||||
if (!spam)
|
||||
hc->bcast.index = index;
|
||||
hc->rgraph.index = index;
|
||||
} else {
|
||||
hc->rgraph.index
|
||||
= gossip_store_add(rstate->gs, update, timestamp,
|
||||
local_direction(rstate, chan, NULL),
|
||||
spam, NULL);
|
||||
if (hc->bcast.timestamp > rstate->last_timestamp
|
||||
&& hc->bcast.timestamp < time_now().ts.tv_sec)
|
||||
rstate->last_timestamp = hc->bcast.timestamp;
|
||||
if (!spam)
|
||||
hc->bcast.index = hc->rgraph.index;
|
||||
|
||||
peer_supplied_good_gossip(peer, 1);
|
||||
}
|
||||
@ -1653,7 +1682,7 @@ bool routing_add_node_announcement(struct routing_state *rstate,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (node->bcast.timestamp >= timestamp) {
|
||||
if (node->rgraph.timestamp >= timestamp) {
|
||||
SUPERVERBOSE("Ignoring node announcement, it's outdated.");
|
||||
/* OK unless we're loading from store */
|
||||
return index == 0;
|
||||
@ -1691,26 +1720,41 @@ bool routing_add_node_announcement(struct routing_state *rstate,
|
||||
spam = false;
|
||||
}
|
||||
|
||||
/* Harmless if it was never added */
|
||||
gossip_store_delete(rstate->gs,
|
||||
&node->bcast,
|
||||
WIRE_NODE_ANNOUNCEMENT);
|
||||
/* Routing graph always references the latest message. */
|
||||
node->rgraph.timestamp = timestamp;
|
||||
if (!spam) {
|
||||
node->bcast.timestamp = timestamp;
|
||||
/* remove prior spam update if one exists */
|
||||
if (node->rgraph.index != node->bcast.index) {
|
||||
/* Harmless if it was never added */
|
||||
gossip_store_delete(rstate->gs, &node->rgraph,
|
||||
WIRE_NODE_ANNOUNCEMENT);
|
||||
}
|
||||
gossip_store_delete(rstate->gs, &node->bcast,
|
||||
WIRE_NODE_ANNOUNCEMENT);
|
||||
/* Remove prior spam update. */
|
||||
} else if (node->rgraph.index != node->bcast.index) {
|
||||
gossip_store_delete(rstate->gs, &node->rgraph,
|
||||
WIRE_NODE_ANNOUNCEMENT);
|
||||
}
|
||||
|
||||
node->bcast.timestamp = timestamp;
|
||||
if (node->bcast.timestamp > rstate->last_timestamp
|
||||
&& node->bcast.timestamp < time_now().ts.tv_sec)
|
||||
rstate->last_timestamp = node->bcast.timestamp;
|
||||
|
||||
if (index)
|
||||
node->bcast.index = index;
|
||||
else {
|
||||
node->bcast.index
|
||||
= gossip_store_add(rstate->gs, msg,
|
||||
node->bcast.timestamp,
|
||||
/* Don't add to the store if it was loaded from the store. */
|
||||
if (index) {
|
||||
node->rgraph.index = index;
|
||||
if (!spam)
|
||||
node->bcast.index = index;
|
||||
} else {
|
||||
node->rgraph.index
|
||||
= gossip_store_add(rstate->gs, msg, timestamp,
|
||||
node_id_eq(&node_id,
|
||||
&rstate->local_id),
|
||||
spam,
|
||||
NULL);
|
||||
spam, NULL);
|
||||
if (node->bcast.timestamp > rstate->last_timestamp
|
||||
&& node->bcast.timestamp < time_now().ts.tv_sec)
|
||||
rstate->last_timestamp = node->bcast.timestamp;
|
||||
if (!spam)
|
||||
node->bcast.index = node->rgraph.index;
|
||||
|
||||
peer_supplied_good_gossip(peer, 1);
|
||||
}
|
||||
|
||||
|
@ -20,9 +20,13 @@ struct peer;
|
||||
struct routing_state;
|
||||
|
||||
struct half_chan {
|
||||
/* Timestamp and index into store file */
|
||||
/* Timestamp and index into store file - safe to broadcast */
|
||||
struct broadcastable bcast;
|
||||
|
||||
/* Most recent gossip for the routing graph - may be rate-limited and
|
||||
* non-broadcastable. If there is no spam, rgraph == bcast. */
|
||||
struct broadcastable rgraph;
|
||||
|
||||
/* Token bucket */
|
||||
u8 tokens;
|
||||
};
|
||||
@ -105,6 +109,10 @@ struct node {
|
||||
/* Timestamp and index into store file */
|
||||
struct broadcastable bcast;
|
||||
|
||||
/* Possibly spam flagged. Nonbroadcastable, but used for routing graph.
|
||||
* If there is no current spam, rgraph == bcast. */
|
||||
struct broadcastable rgraph;
|
||||
|
||||
/* Token bucket */
|
||||
u8 tokens;
|
||||
|
||||
|
@ -1863,7 +1863,8 @@ def test_gossip_ratelimit(node_factory, bitcoind):
|
||||
'0102c479b7684b9db496b844f6925f4ffd8a27c5840a020d1b537623c1545dcd8e195776381bbf51213e541a853a4a49a0faf84316e7ccca5e7074901a96bbabe04e06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f00006700000100015d77400201010006000000000000000000000014000003eb000000003b023380',
|
||||
# timestamp=1568096259, fee_proportional_millionths=1004
|
||||
'01024b866012d995d3d7aec7b7218a283de2d03492dbfa21e71dd546ec2e36c3d4200453420aa02f476f99c73fe1e223ea192f5fa544b70a8319f2a216f1513d503d06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f00006700000100015d77400301010006000000000000000000000014000003ec000000003b023380',
|
||||
# update 5 marks you as a nasty spammer, but we listen to you anyway now! fee_proportional_millionths=1005
|
||||
# update 5 marks you as a nasty spammer, but the routing graph is
|
||||
# updated with this even though the gossip is not broadcast.
|
||||
'01025b5b5a0daed874ab02bd3356d38190ff46bbaf5f10db5067da70f3ca203480ca78059e6621c6143f3da4e454d0adda6d01a9980ed48e71ccd0c613af73570a7106226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f00006700000100015d77400401010006000000000000000000000014000003ed000000003b023380'
|
||||
],
|
||||
timeout=TIMEOUT
|
||||
@ -1887,6 +1888,7 @@ def test_gossip_ratelimit(node_factory, bitcoind):
|
||||
check=True,
|
||||
timeout=TIMEOUT,
|
||||
stdout=subprocess.PIPE).stdout.decode('utf8')
|
||||
assert("fee_proportional_millionths=1004" in decoded)
|
||||
# Used in routing graph, but not passed to gossip peers.
|
||||
assert("fee_proportional_millionths=1005" not in decoded)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user