From c679b9d436fa1e5e00690dba443c0c9f31b321b9 Mon Sep 17 00:00:00 2001 From: kdeme Date: Thu, 13 Feb 2020 17:48:55 +0100 Subject: [PATCH] Fix priority check of topic-interest versus bloom filter --- eth/p2p/rlpx_protocols/waku_protocol.nim | 28 ++++++----- tests/p2p/test_waku_connect.nim | 64 ++++++++++++++++++------ 2 files changed, 64 insertions(+), 28 deletions(-) diff --git a/eth/p2p/rlpx_protocols/waku_protocol.nim b/eth/p2p/rlpx_protocols/waku_protocol.nim index 52ef124..4902723 100644 --- a/eth/p2p/rlpx_protocols/waku_protocol.nim +++ b/eth/p2p/rlpx_protocols/waku_protocol.nim @@ -201,16 +201,16 @@ proc allowed*(msg: Message, config: WakuConfig): bool = warn "Message PoW too low", pow = msg.pow, minPow = config.powRequirement return false - if not bloomFilterMatch(config.bloom, msg.bloom): - dropped_bloom_filter_mismatch_envelopes.inc() - warn "Message does not match node bloom filter" - return false - if config.topics.isSome(): if msg.env.topic notin config.topics.get(): dropped_topic_mismatch_envelopes.inc() warn "Message topic does not match Waku topic list" return false + else: + if not bloomFilterMatch(config.bloom, msg.bloom): + dropped_bloom_filter_mismatch_envelopes.inc() + warn "Message does not match node bloom filter" + return false return true @@ -365,8 +365,9 @@ p2pProtocol Waku(version = wakuVersion, return # TODO: We currently do not allow changing topic-interest. - # If we want the check here should be removed, however this would be no - # consistent (with Status packet) way of changing back to no topic-interest. + # We could allow this by also resetting topic-interest on a bloom filter + # exchange. But we don't for now and will instead introduce another packet + # type in the Waku Specification. if peer.state.topics.isSome(): peer.state.topics = some(topics) @@ -429,14 +430,14 @@ proc processQueue(peer: Peer) = powReq = wakuPeer.powRequirement continue - if not bloomFilterMatch(wakuPeer.bloom, message.bloom): - trace "Message does not match peer bloom filter" - continue - if wakuPeer.topics.isSome(): if message.env.topic notin wakuPeer.topics.get(): trace "Message does not match topics list" continue + else: + if not bloomFilterMatch(wakuPeer.bloom, message.bloom): + trace "Message does not match peer bloom filter" + continue trace "Adding envelope" envelopes.add(message.env) @@ -611,11 +612,14 @@ proc setBloomFilter*(node: EthereumNode, bloom: Bloom) {.async.} = # Exceptions from sendMsg will not be raised await allFutures(futures) -proc setTopics*(node: EthereumNode, topics: seq[Topic]): +proc setTopicInterest*(node: EthereumNode, topics: seq[Topic]): Future[bool] {.async.} = if topics.len > topicInterestMax: return false + if node.protocolState(Waku).config.topics.isNone(): + return false + node.protocolState(Waku).config.topics = some(topics) var futures: seq[Future[void]] = @[] for peer in node.peers(Waku): diff --git a/tests/p2p/test_waku_connect.nim b/tests/p2p/test_waku_connect.nim index e3171e1..62b792d 100644 --- a/tests/p2p/test_waku_connect.nim +++ b/tests/p2p/test_waku_connect.nim @@ -19,11 +19,12 @@ const # TODO: Just repeat all the test_shh_connect tests here that are applicable or # have some commonly shared test code for both protocols. suite "Waku connections": - asyncTest "Test Waku connections": - var n1 = setupTestNode(Waku) - var n2 = setupTestNode(Waku) - var n3 = setupTestNode(Waku) - var n4 = setupTestNode(Waku) + asyncTest "Waku connections": + var + n1 = setupTestNode(Waku) + n2 = setupTestNode(Waku) + n3 = setupTestNode(Waku) + n4 = setupTestNode(Waku) var topics: seq[Topic] n1.protocolState(Waku).config.topics = some(topics) @@ -34,27 +35,30 @@ suite "Waku connections": n1.startListening() n3.startListening() - let p1 = await n2.rlpxConnect(newNode(initENode(n1.keys.pubKey, n1.address))) - let p2 = await n2.rlpxConnect(newNode(initENode(n3.keys.pubKey, n3.address))) - let p3 = await n4.rlpxConnect(newNode(initENode(n3.keys.pubKey, n3.address))) + let + p1 = await n2.rlpxConnect(newNode(initENode(n1.keys.pubKey, n1.address))) + p2 = await n2.rlpxConnect(newNode(initENode(n3.keys.pubKey, n3.address))) + p3 = await n4.rlpxConnect(newNode(initENode(n3.keys.pubKey, n3.address))) check: p1.isNil p2.isNil == false p3.isNil == false - asyncTest "Test Waku topic-interest": - var wakuTopicNode = setupTestNode(Waku) - var wakuNode = setupTestNode(Waku) + asyncTest "Waku topic-interest": + var + wakuTopicNode = setupTestNode(Waku) + wakuNode = setupTestNode(Waku) - let topic1 = [byte 0xDA, 0xDA, 0xDA, 0xAA] - let topic2 = [byte 0xD0, 0xD0, 0xD0, 0x00] - let wrongTopic = [byte 0x4B, 0x1D, 0x4B, 0x1D] + let + topic1 = [byte 0xDA, 0xDA, 0xDA, 0xAA] + topic2 = [byte 0xD0, 0xD0, 0xD0, 0x00] + wrongTopic = [byte 0x4B, 0x1D, 0x4B, 0x1D] wakuTopicNode.protocolState(Waku).config.topics = some(@[topic1, topic2]) wakuNode.startListening() - await wakuTopicNode.peerPool.connectToNode(newNode(initENode(wakuNode.keys.pubKey, - wakuNode.address))) + await wakuTopicNode.peerPool.connectToNode(newNode( + initENode(wakuNode.keys.pubKey, wakuNode.address))) let payload = repeat(byte 0, 10) check: @@ -66,6 +70,34 @@ suite "Waku connections": check: wakuTopicNode.protocolState(Waku).queue.items.len == 2 + asyncTest "Waku topic-interest versus bloom filter": + var + wakuTopicNode = setupTestNode(Waku) + wakuNode = setupTestNode(Waku) + + let + topic1 = [byte 0xDA, 0xDA, 0xDA, 0xAA] + topic2 = [byte 0xD0, 0xD0, 0xD0, 0x00] + bloomTopic = [byte 0x4B, 0x1D, 0x4B, 0x1D] + + # It was checked that the topics don't trigger false positives on the bloom. + wakuTopicNode.protocolState(Waku).config.topics = some(@[topic1, topic2]) + wakuTopicNode.protocolState(Waku).config.bloom = toBloom([bloomTopic]) + + wakuNode.startListening() + await wakuTopicNode.peerPool.connectToNode(newNode( + initENode(wakuNode.keys.pubKey, wakuNode.address))) + + let payload = repeat(byte 0, 10) + check: + wakuNode.postMessage(ttl = safeTTL, topic = topic1, payload = payload) + wakuNode.postMessage(ttl = safeTTL, topic = topic2, payload = payload) + wakuNode.postMessage(ttl = safeTTL, topic = bloomTopic, payload = payload) + wakuNode.protocolState(Waku).queue.items.len == 3 + await sleepAsync(waitInterval) + check: + wakuTopicNode.protocolState(Waku).queue.items.len == 2 + asyncTest "Light node posting": var ln = setupTestNode(Waku) ln.setLightNode(true)