Skip to content
This repository has been archived by the owner on Aug 2, 2021. It is now read-only.

swarm/pss: Message handler refactor #965

Closed
wants to merge 16 commits into from
Closed

Conversation

nolash
Copy link
Contributor

@nolash nolash commented Oct 18, 2018

This is the first in a series of PR providing the following enhancements to PSS:

Send fully addressed messages to neighbourhoods

The possibility of sending a message with full PssAddress to a neighbourhood of nodes, by interactive with the Kademlia. The primary use case is chunk syncing, where the chunk will have full address but nodes that have responsibility for storing the chunk should still regard themselves as recipients of it.

Mitigate external influence of resource expenditure

If receiving raw messages, currently all raw messages will be passed on to handling code, effectively passing the responsibility of limiting resource expenditure to the handlers. This can be risky, in case of implementations that do not protect against request flooding. Whether to handle raw messages or not should therefore be explicitly set on the handler.

This also pertains to symmetric decryptions, were all registered symmetric keys (for decryption) share the same LRU cache which is tried sequentially on the decrypt. Instead, there should be symkey decrypt caches per topic.

Symkey filter in message type

To reduce resource expenditure in symmetric decryption, an extra field in the message type will be introduced where up to 32 bytes of symmetric key hint can be added. The hint is a hash of the symmetric key, indexed on both sides. The symkey cache must be refactored to be able to take advantage of this hint. A zero-value in this field would indicate public key crypto.

This also clears the way for upgrading whisper support to v6, as one of the changes in whisper v6 is omission of the symkey nonce in the whisper envelope; with this field it's still possible to identify incoming symmetrically encrypted messages, to avoid a forced attempt of asymmetric decryption on every reception.

Part 1

protocols, handshakes, pss/client and notify have all been edited to pass tests with the new Handler struct, but need to be revisited for implementation details. This will follow in a later PR

  • - Change Handler from func to struct with necessary params
  • - Set raw message allowance per handler
  • - Add possible recipient logic to use kademlia depth
  • - Handler capabilities tests
  • - Prox destinations tests
  • - Make sender handle message if topic has prox handler and is possible recipient

The PR also replaces the -v[v] verbosity flags for tests with --loglevel flag that sets the loglevel explicitly, and default level to 2 (log.Warn).

@zelig
Copy link
Member

zelig commented Oct 19, 2018

swarm/network/kademlia.go Outdated Show resolved Hide resolved
swarm/network/kademlia.go Outdated Show resolved Hide resolved
swarm/network/kademlia.go Show resolved Hide resolved
swarm/pss/api.go Outdated
},
}
if raw {
hndlr.caps |= handlerCapRaw
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wdym?

swarm/pss/pss.go Outdated Show resolved Hide resolved
swarm/pss/types.go Outdated Show resolved Hide resolved
swarm/pss/api.go Outdated Show resolved Hide resolved
// - no prox handler on message and partial address matches
// - prox handler on message and we are in prox regardless of partial address match
// store this result so we don't calculate again on every handler
var isProx bool
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now I think you execute a raw handler for a message if there is another handler that allows prox even if that handler does not allow prox.

I think this logic should be different now, instead of isSelf calls we should just have a call to func getHandlersFor(topic, type) *handler when the type enum is

  • raw if the message is raw
  • sym if the message has a symkey hint
  • asym if there is no hint.

the handlers would be in a map indexed by topic+type serialised.
this would return a list of handlers where the handler would have an address matcher
to be called with address and sym key hint.

func (*handler) match(address, symhint) (payload []byte, handlers []*handlerFunc, forward bool)
this would

  • lookup decryption key from hint and open for sym
  • it would match on address
  • or partial address if allowed
  • or proximity if allowed
  • or it would decrypt with asym if there was no hint

and return the decrypted payload and the handlers that matched and a bool to indicate if the message needs to be forwarded (only false if full destination address matches)

Copy link
Contributor Author

@nolash nolash Oct 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now I think you execute a raw handler for a message if there is another handler that allows prox even if that handler does not allow prox.

It's not clear to mean what you mean here, but the condition in pss.go:380 stops handling of raw message if no raw handlers are registered for the topic.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure but it still tries it even though we could know better by then....

swarm/pss/pss.go Show resolved Hide resolved
swarm/pss/types.go Show resolved Hide resolved
@zelig
Copy link
Member

zelig commented Oct 21, 2018

@zelig zelig force-pushed the pss-handler-refactor-depth branch from f42eca7 to 9edcb1c Compare October 24, 2018 18:11
@nolash nolash force-pushed the pss-handler-refactor-depth branch from 10def86 to 11f1528 Compare November 9, 2018 10:30
Copy link
Member

@zelig zelig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

swarm/network/kademlia.go Outdated Show resolved Hide resolved
swarm/pss/protocol_test.go Outdated Show resolved Hide resolved
swarm/pss/pss.go Outdated Show resolved Hide resolved
swarm/pss/pss.go Outdated Show resolved Hide resolved
swarm/pss/pss_test.go Show resolved Hide resolved
// remote address distances from localAddr to try and the expected outcomes if we use prox handler
remoteDistances := []int{
255,
kad.MinBinSize + 1,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is very confusing and most likely wrong. How is kad.MinBinSize relate to proximity order (you call distance)?

This works only becuse you set peerCount := kad.MinBinSize + 2 , kad.MinProxBinSize happens to be 2 and you fill the table with peers in PO bins staring from 0.
This is way too arcane for a test.

Copy link
Contributor Author

@nolash nolash Nov 10, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to make sure that I have one peer in each bin, two more peers than NNs. The NNs in this test will be in two separate bins.

Are you arguing that the test will break if kad.MinBinSize would change? I'm not sure how?

I do agree however that the naming in this test makes it confusing. How about I copy the kad.MinBinSize to a local var, and only use local var names thereafter?

swarm/pss/types.go Outdated Show resolved Hide resolved
swarm/pss/types.go Show resolved Hide resolved
@zelig
Copy link
Member

zelig commented Nov 10, 2018

Also, the algo for forwarding needs fixing as per our convo (see my code)
https://github.com/ethersphere/go-ethereum/blob/11f152819632d3c7a09de5f468e2f506280dd75d/swarm/pss/pss.go#L875

@nolash
Copy link
Contributor Author

nolash commented Nov 20, 2018

@zelig I think this was wrong before. Can you evaluate too please?

https://github.com/ethersphere/go-ethereum/pull/965/files#diff-2d1fd9a8750299d8ae63031e6b30be89R347

@nolash nolash force-pushed the pss-handler-refactor-depth branch from a46ac96 to b13b05c Compare November 20, 2018 12:18
Copy link
Member

@zelig zelig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor things, otherwise LGTM

@@ -430,6 +433,12 @@ func (k *Kademlia) eachAddr(base []byte, o int, f func(*BzzAddr, int, bool) bool
// the nearest neighbour set with cardinality >= MinProxBinSize
// if there is altogether less than MinProxBinSize peers it returns 0
// caller must hold the lock
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this last comment please

@@ -129,7 +129,9 @@ func testProtocol(t *testing.T) {
case <-lmsgC:
log.Debug("lnode ok")
case cerr := <-lctx.Done():
t.Fatalf("test message timed out: %v", cerr)
_ = cerr
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reinstate t.Fatal line

swarm/pss/pss.go Outdated
return false
}

minProx := p.Kademlia.NeighbourhoodDepth()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would call this depth

swarm/pss/pss.go Outdated
}

minProx := p.Kademlia.NeighbourhoodDepth()
depth, _ := p.Kademlia.Pof(p.Kademlia.BaseAddr(), msg.To, 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would call it po or msgpo

if err != nil {
return err
}
if p.isSelfPossibleRecipient(pssMsg, true) && p.topicHandlerCaps[topic].prox {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

worth a comment that this is loopback

@nolash nolash force-pushed the pss-handler-refactor-depth branch from 45e6069 to 8b7918b Compare November 21, 2018 08:51
swarm/pss/pss.go Outdated

if minProx <= depth {
if po <= depth {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but now the other way round :)

Copy link
Contributor Author

@nolash nolash Nov 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol sorry. thanks for catching it

@zelig
Copy link
Member

zelig commented Nov 23, 2018

@nolash
Copy link
Contributor Author

nolash commented Nov 23, 2018

Submitted upstream ethereum/go-ethereum#18169

@nolash nolash closed this Nov 23, 2018
@zelig zelig mentioned this pull request Nov 29, 2018
20 tasks
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants