mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-20 07:34:24 +01:00
testing: make sure we don't see gossip in bad order.
This is something which generally shouldn't happen, but we didn't notice it previously. We ignore this warning in the case where a channel was deleted: this happens because one side can send an update while the other notices that the channel is closed. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
committed by
Christian Decker
parent
177a1fc88e
commit
8ee60e2d8e
@@ -201,6 +201,13 @@ static void init_half_chan(struct routing_state *rstate,
|
|||||||
c->last_timestamp = time_now().ts.tv_sec - rstate->prune_timeout/2;
|
c->last_timestamp = time_now().ts.tv_sec - rstate->prune_timeout/2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bad_gossip_order(const u8 *msg, const char *details)
|
||||||
|
{
|
||||||
|
status_trace("Bad gossip order: %s before announcement %s",
|
||||||
|
wire_type_name(fromwire_peektype(msg)),
|
||||||
|
details);
|
||||||
|
}
|
||||||
|
|
||||||
struct chan *new_chan(struct routing_state *rstate,
|
struct chan *new_chan(struct routing_state *rstate,
|
||||||
const struct short_channel_id *scid,
|
const struct short_channel_id *scid,
|
||||||
const struct pubkey *id1,
|
const struct pubkey *id1,
|
||||||
@@ -1015,9 +1022,12 @@ u8 *handle_channel_update(struct routing_state *rstate, const u8 *update)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!chan) {
|
if (!chan) {
|
||||||
SUPERVERBOSE("Ignoring update for unknown channel %s",
|
bad_gossip_order(serialized,
|
||||||
type_to_string(tmpctx, struct short_channel_id,
|
tal_fmt(tmpctx, "%s(%u)",
|
||||||
&short_channel_id));
|
type_to_string(tmpctx,
|
||||||
|
struct short_channel_id,
|
||||||
|
&short_channel_id),
|
||||||
|
flags));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1245,11 +1255,9 @@ u8 *handle_node_announcement(struct routing_state *rstate, const u8 *node_ann)
|
|||||||
pna = pending_node_map_get(rstate->pending_node_map,
|
pna = pending_node_map_get(rstate->pending_node_map,
|
||||||
&node_id.pubkey);
|
&node_id.pubkey);
|
||||||
if (!pna) {
|
if (!pna) {
|
||||||
SUPERVERBOSE("Node not found, was the node_announcement "
|
bad_gossip_order(serialized,
|
||||||
"for node %s preceded by at least "
|
type_to_string(tmpctx, struct pubkey,
|
||||||
"channel_announcement?",
|
&node_id));
|
||||||
type_to_string(tmpctx, struct pubkey,
|
|
||||||
&node_id));
|
|
||||||
} else if (pna->timestamp < timestamp) {
|
} else if (pna->timestamp < timestamp) {
|
||||||
SUPERVERBOSE(
|
SUPERVERBOSE(
|
||||||
"Deferring node_announcement for node %s",
|
"Deferring node_announcement for node %s",
|
||||||
@@ -1519,6 +1527,9 @@ void handle_local_add_channel(struct routing_state *rstate, const u8 *msg)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_trace("local_add_channel %s",
|
||||||
|
type_to_string(tmpctx, struct short_channel_id, &scid));
|
||||||
|
|
||||||
/* Create new (unannounced) channel */
|
/* Create new (unannounced) channel */
|
||||||
new_chan(rstate, &scid, &rstate->local_id, &remote_node_id);
|
new_chan(rstate, &scid, &rstate->local_id, &remote_node_id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,6 +83,9 @@ bool fromwire_gossip_store_node_announcement(const tal_t *ctx UNNEEDED, const vo
|
|||||||
/* Generated stub for fromwire_node_announcement */
|
/* Generated stub for fromwire_node_announcement */
|
||||||
bool fromwire_node_announcement(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED, u8 **features UNNEEDED, u32 *timestamp UNNEEDED, struct pubkey *node_id UNNEEDED, u8 rgb_color[3] UNNEEDED, u8 alias[32] UNNEEDED, u8 **addresses UNNEEDED)
|
bool fromwire_node_announcement(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED, u8 **features UNNEEDED, u32 *timestamp UNNEEDED, struct pubkey *node_id UNNEEDED, u8 rgb_color[3] UNNEEDED, u8 alias[32] UNNEEDED, u8 **addresses UNNEEDED)
|
||||||
{ fprintf(stderr, "fromwire_node_announcement called!\n"); abort(); }
|
{ fprintf(stderr, "fromwire_node_announcement called!\n"); abort(); }
|
||||||
|
/* Generated stub for fromwire_peektype */
|
||||||
|
int fromwire_peektype(const u8 *cursor UNNEEDED)
|
||||||
|
{ fprintf(stderr, "fromwire_peektype called!\n"); abort(); }
|
||||||
/* Generated stub for fromwire_u8 */
|
/* Generated stub for fromwire_u8 */
|
||||||
u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
|
u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
|
||||||
{ fprintf(stderr, "fromwire_u8 called!\n"); abort(); }
|
{ fprintf(stderr, "fromwire_u8 called!\n"); abort(); }
|
||||||
@@ -123,6 +126,9 @@ u8 *towire_gossip_store_local_add_channel(const tal_t *ctx UNNEEDED, const u8 *l
|
|||||||
/* Generated stub for towire_gossip_store_node_announcement */
|
/* Generated stub for towire_gossip_store_node_announcement */
|
||||||
u8 *towire_gossip_store_node_announcement(const tal_t *ctx UNNEEDED, const u8 *announcement UNNEEDED)
|
u8 *towire_gossip_store_node_announcement(const tal_t *ctx UNNEEDED, const u8 *announcement UNNEEDED)
|
||||||
{ fprintf(stderr, "towire_gossip_store_node_announcement called!\n"); abort(); }
|
{ fprintf(stderr, "towire_gossip_store_node_announcement called!\n"); abort(); }
|
||||||
|
/* Generated stub for wire_type_name */
|
||||||
|
const char *wire_type_name(int e UNNEEDED)
|
||||||
|
{ fprintf(stderr, "wire_type_name called!\n"); abort(); }
|
||||||
/* AUTOGENERATED MOCKS END */
|
/* AUTOGENERATED MOCKS END */
|
||||||
|
|
||||||
/* Updates existing route if required. */
|
/* Updates existing route if required. */
|
||||||
|
|||||||
@@ -47,6 +47,9 @@ bool fromwire_gossip_store_node_announcement(const tal_t *ctx UNNEEDED, const vo
|
|||||||
/* Generated stub for fromwire_node_announcement */
|
/* Generated stub for fromwire_node_announcement */
|
||||||
bool fromwire_node_announcement(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED, u8 **features UNNEEDED, u32 *timestamp UNNEEDED, struct pubkey *node_id UNNEEDED, u8 rgb_color[3] UNNEEDED, u8 alias[32] UNNEEDED, u8 **addresses UNNEEDED)
|
bool fromwire_node_announcement(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED, u8 **features UNNEEDED, u32 *timestamp UNNEEDED, struct pubkey *node_id UNNEEDED, u8 rgb_color[3] UNNEEDED, u8 alias[32] UNNEEDED, u8 **addresses UNNEEDED)
|
||||||
{ fprintf(stderr, "fromwire_node_announcement called!\n"); abort(); }
|
{ fprintf(stderr, "fromwire_node_announcement called!\n"); abort(); }
|
||||||
|
/* Generated stub for fromwire_peektype */
|
||||||
|
int fromwire_peektype(const u8 *cursor UNNEEDED)
|
||||||
|
{ fprintf(stderr, "fromwire_peektype called!\n"); abort(); }
|
||||||
/* Generated stub for fromwire_u8 */
|
/* Generated stub for fromwire_u8 */
|
||||||
u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
|
u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
|
||||||
{ fprintf(stderr, "fromwire_u8 called!\n"); abort(); }
|
{ fprintf(stderr, "fromwire_u8 called!\n"); abort(); }
|
||||||
@@ -87,6 +90,9 @@ u8 *towire_gossip_store_local_add_channel(const tal_t *ctx UNNEEDED, const u8 *l
|
|||||||
/* Generated stub for towire_gossip_store_node_announcement */
|
/* Generated stub for towire_gossip_store_node_announcement */
|
||||||
u8 *towire_gossip_store_node_announcement(const tal_t *ctx UNNEEDED, const u8 *announcement UNNEEDED)
|
u8 *towire_gossip_store_node_announcement(const tal_t *ctx UNNEEDED, const u8 *announcement UNNEEDED)
|
||||||
{ fprintf(stderr, "towire_gossip_store_node_announcement called!\n"); abort(); }
|
{ fprintf(stderr, "towire_gossip_store_node_announcement called!\n"); abort(); }
|
||||||
|
/* Generated stub for wire_type_name */
|
||||||
|
const char *wire_type_name(int e UNNEEDED)
|
||||||
|
{ fprintf(stderr, "wire_type_name called!\n"); abort(); }
|
||||||
/* AUTOGENERATED MOCKS END */
|
/* AUTOGENERATED MOCKS END */
|
||||||
|
|
||||||
const void *trc;
|
const void *trc;
|
||||||
|
|||||||
@@ -45,6 +45,9 @@ bool fromwire_gossip_store_node_announcement(const tal_t *ctx UNNEEDED, const vo
|
|||||||
/* Generated stub for fromwire_node_announcement */
|
/* Generated stub for fromwire_node_announcement */
|
||||||
bool fromwire_node_announcement(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED, u8 **features UNNEEDED, u32 *timestamp UNNEEDED, struct pubkey *node_id UNNEEDED, u8 rgb_color[3] UNNEEDED, u8 alias[32] UNNEEDED, u8 **addresses UNNEEDED)
|
bool fromwire_node_announcement(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED, u8 **features UNNEEDED, u32 *timestamp UNNEEDED, struct pubkey *node_id UNNEEDED, u8 rgb_color[3] UNNEEDED, u8 alias[32] UNNEEDED, u8 **addresses UNNEEDED)
|
||||||
{ fprintf(stderr, "fromwire_node_announcement called!\n"); abort(); }
|
{ fprintf(stderr, "fromwire_node_announcement called!\n"); abort(); }
|
||||||
|
/* Generated stub for fromwire_peektype */
|
||||||
|
int fromwire_peektype(const u8 *cursor UNNEEDED)
|
||||||
|
{ fprintf(stderr, "fromwire_peektype called!\n"); abort(); }
|
||||||
/* Generated stub for fromwire_u8 */
|
/* Generated stub for fromwire_u8 */
|
||||||
u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
|
u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
|
||||||
{ fprintf(stderr, "fromwire_u8 called!\n"); abort(); }
|
{ fprintf(stderr, "fromwire_u8 called!\n"); abort(); }
|
||||||
@@ -85,6 +88,9 @@ u8 *towire_gossip_store_local_add_channel(const tal_t *ctx UNNEEDED, const u8 *l
|
|||||||
/* Generated stub for towire_gossip_store_node_announcement */
|
/* Generated stub for towire_gossip_store_node_announcement */
|
||||||
u8 *towire_gossip_store_node_announcement(const tal_t *ctx UNNEEDED, const u8 *announcement UNNEEDED)
|
u8 *towire_gossip_store_node_announcement(const tal_t *ctx UNNEEDED, const u8 *announcement UNNEEDED)
|
||||||
{ fprintf(stderr, "towire_gossip_store_node_announcement called!\n"); abort(); }
|
{ fprintf(stderr, "towire_gossip_store_node_announcement called!\n"); abort(); }
|
||||||
|
/* Generated stub for wire_type_name */
|
||||||
|
const char *wire_type_name(int e UNNEEDED)
|
||||||
|
{ fprintf(stderr, "wire_type_name called!\n"); abort(); }
|
||||||
/* AUTOGENERATED MOCKS END */
|
/* AUTOGENERATED MOCKS END */
|
||||||
|
|
||||||
/* Updates existing route if required. */
|
/* Updates existing route if required. */
|
||||||
|
|||||||
@@ -91,6 +91,10 @@ def node_factory(directory, test_name, bitcoind, executor):
|
|||||||
err_count += checkReconnect(node)
|
err_count += checkReconnect(node)
|
||||||
if err_count:
|
if err_count:
|
||||||
raise ValueError("{} nodes had unexpected reconnections".format(err_count))
|
raise ValueError("{} nodes had unexpected reconnections".format(err_count))
|
||||||
|
for node in nf.nodes:
|
||||||
|
err_count += checkBadGossipOrder(node)
|
||||||
|
if err_count:
|
||||||
|
raise ValueError("{} nodes had bad gossip order".format(err_count))
|
||||||
|
|
||||||
if not ok:
|
if not ok:
|
||||||
raise Exception("At least one lightning exited with unexpected non-zero return code")
|
raise Exception("At least one lightning exited with unexpected non-zero return code")
|
||||||
@@ -147,6 +151,12 @@ def checkReconnect(node):
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def checkBadGossipOrder(node):
|
||||||
|
if node.daemon.is_in_log('Bad gossip order') and not node.daemon.is_in_log('Deleting channel'):
|
||||||
|
return 1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def executor():
|
def executor():
|
||||||
ex = futures.ThreadPoolExecutor(max_workers=20)
|
ex = futures.ThreadPoolExecutor(max_workers=20)
|
||||||
|
|||||||
@@ -299,6 +299,13 @@ class BaseLightningDTests(unittest.TestCase):
|
|||||||
return 1
|
return 1
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
def checkBadGossipOrder(self, node):
|
||||||
|
# We can have a race where we notice a channel deleted and someone
|
||||||
|
# sends an update.
|
||||||
|
if node.daemon.is_in_log('Bad gossip order') and not node.daemon.is_in_log('Deleting channel'):
|
||||||
|
return 1
|
||||||
|
return 0
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
ok = self.node_factory.killall([not n.may_fail for n in self.node_factory.nodes])
|
ok = self.node_factory.killall([not n.may_fail for n in self.node_factory.nodes])
|
||||||
self.executor.shutdown(wait=False)
|
self.executor.shutdown(wait=False)
|
||||||
@@ -322,6 +329,11 @@ class BaseLightningDTests(unittest.TestCase):
|
|||||||
if err_count:
|
if err_count:
|
||||||
raise ValueError("{} nodes had unexpected reconnections".format(err_count))
|
raise ValueError("{} nodes had unexpected reconnections".format(err_count))
|
||||||
|
|
||||||
|
for node in self.node_factory.nodes:
|
||||||
|
err_count += self.checkBadGossipOrder(node)
|
||||||
|
if err_count:
|
||||||
|
raise ValueError("{} nodes had bad gossip order".format(err_count))
|
||||||
|
|
||||||
if not ok:
|
if not ok:
|
||||||
raise Exception("At least one lightning exited with unexpected non-zero return code")
|
raise Exception("At least one lightning exited with unexpected non-zero return code")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user