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

swarm/pss: Allow transmission of raw messages #376

Merged
merged 9 commits into from
Apr 11, 2018
Merged

Conversation

nolash
Copy link
Contributor

@nolash nolash commented Apr 6, 2018

This PR enables sending and receiving of raw messages, bypassing the builtin pss encryption mechanisms.

The intended usage is for applications that prefer to handle encryption themselves.

It also makes it possible to use the pss node as a multiplexing node, in essence handling several clients with different public keys, something that is not currently possible in a pss node since the public key is unique for this node.

It also introduces a protected topic value 0x0 which, if set, denotes an unencrypted message, and is passed to the raw message handler before decryption is attempted.


The PR also introduces outbox capacity handling code, which errs on failed attempt of message enqueueing.

@nolash nolash self-assigned this Apr 6, 2018
@nolash nolash requested review from gbalint, zelig and nonsense and removed request for gbalint April 6, 2018 07:39
}

func (self *Pss) executeHandlers(topic Topic, payload []byte, from *PssAddress, asymmetric bool, keyid string) {
handlers := self.getHandlers(topic)
Copy link
Member

Choose a reason for hiding this comment

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

why is this peer created can you remind me?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we need the peer passed to the PssProtocol handler.

swarm/pss/pss.go Outdated
@@ -365,17 +371,25 @@ func (self *Pss) process(pssmsg *PssMsg) bool {
self.outbox <- pssmsg
}()
}
handlers := self.getHandlers(psstopic)
if psstopic == rawTopic {
Copy link
Member

Choose a reason for hiding this comment

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

so lets talk about this. I dont understand why for no encryption there would be a specific topic rather than a bool field on the message or nothing (just the first assumption)

Copy link
Contributor Author

@nolash nolash Apr 6, 2018

Choose a reason for hiding this comment

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

nothing sounds better. Let's try that. nothing is not possible, because whisper topics are 4 byte fixed arrays. If we detach from whisper (to allow for more bytes in topic) we can do this.

Bool on message, well, yeah;

  1. That's one more byte pr msg.
  2. If we later want to use empty topic instead and would want to revert, that will change the pss message structure itself, which means version change in protocol and incompatible nodes, I guess.

Disallowing certain hashes is not so elegant either, I know.

I don't have a strong opinion here, but I would like to avoid changing the message structure in the future.

@@ -1172,13 +1254,13 @@ func benchmarkSymkeyBruteforceSameaddr(b *testing.B) {
}

// setup simulated network and connect nodes in circle
func setupNetwork(numnodes int) (clients []*rpc.Client, err error) {
func setupNetwork(numnodes int, allowRaw bool) (clients []*rpc.Client, err error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

please document setupNetwork explaining about allowRaw... something along the lines of

setupNetwork is creating a simulated network with `numnodes` number of nodes. `allowRaw` is ...

swarm/pss/pss.go Outdated
@@ -71,6 +72,7 @@ type PssParams struct {
CacheTTL time.Duration
privateKey *ecdsa.PrivateKey
SymKeyCacheCapacity int
AllowRaw bool
Copy link
Contributor

Choose a reason for hiding this comment

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

We should start to document the params in structs like this one. Please add a comment next to AllowRaw explaining its purpose and usage.

swarm/pss/pss.go Outdated
@@ -365,17 +371,25 @@ func (self *Pss) process(pssmsg *PssMsg) bool {
self.outbox <- pssmsg
}()
}
handlers := self.getHandlers(psstopic)
if psstopic == rawTopic {
Copy link
Contributor

Choose a reason for hiding this comment

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

I am not sure I understand this - how is it possible to end up in this if-condition? If we are using rawTopic for psstopic wouldn't we always end up in the err != nil block above?

This if-condition looks redundant to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If the message is encrypted but has topic 0x0 it will hit this check.

Copy link
Contributor

@nonsense nonsense Apr 10, 2018

Choose a reason for hiding this comment

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

Then I don't understand the raw concept... from the description of this PR - It also introduces a protected topic value 0x0 which, if set, denotes an unencrypted message, and is passed through to the raw message handler in case of failed decryption.

@nolash maybe we do an interactive review, on a call, so that we don't have another 100 comments on this PR - I just want to understand the background a bit better :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're right. I'll move the topic check up. We don't need to waste cycles trying to decrypt the message if it has topic 0x0

swarm/pss/pss.go Outdated
@@ -365,17 +371,25 @@ func (self *Pss) process(pssmsg *PssMsg) bool {
self.outbox <- pssmsg
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it is quite error-prone to create a go-routine for adding messages to the outbox channel. We should have some other mechanism to signal to the user if the outbox size is reached, and we should do something about it, not create unlimited number of go-routines that are blocked in memory.

I would just remove this goroutine altogether as a start.

Copy link
Contributor Author

@nolash nolash Apr 10, 2018

Choose a reason for hiding this comment

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

I originally was using arrays and counters which was quite a bit slower according to benchmarks, but which had error on capacity issues. @zelig suggested use channels instead. See #354

So you suggest to introduce a counter?

Copy link
Contributor

@nonsense nonsense Apr 10, 2018

Choose a reason for hiding this comment

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

using channels for the outbox is good, but when you have a buffered channel you should address what happens when the limit of the buffer is reached, and address this pressure. AFAIK you cannot have an unlimited buffer, as this basically means unlimited memory and this doesn't exist.

what you are doing now (goroutine which blocks once you reach the size of the outbox), means that you essentially have an unlimited number of goroutines that might block and you have a memory problem. we should not have that, but rather return an error and block if the outbox size is reached.

here is a summary of the questions we should answer when we have a buffered channel - https://www.ardanlabs.com/blog/2017/10/the-behavior-of-channels.html

@nonsense
Copy link
Contributor

@nolash you don't have to maintain a counter to keep track whether the buffered channel is full or not. you can do the same with a select statement and a default - see https://stackoverflow.com/questions/25657207/golang-how-to-know-a-buffered-channel-is-full

swarm/pss/pss.go Outdated
}()
if !self.enqueue(pssmsg) {
log.Error("outbox full!")
return false
Copy link
Member

Choose a reason for hiding this comment

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

why not return error?

swarm/pss/pss.go Outdated
return true
default:
}
return true
Copy link
Member

Choose a reason for hiding this comment

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

return false
or better errOutboxFull

swarm/pss/pss.go Outdated
@@ -745,11 +798,14 @@ func (self *Pss) forward(msg *PssMsg) {
if sent == 0 {
log.Debug("unable to forward to any peers")
time.Sleep(time.Millisecond)
self.outbox <- msg
if !self.enqueue(msg) {
return errors.New("outbox full!")
Copy link
Member

Choose a reason for hiding this comment

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

3rd way of calling enqueue

Copy link
Contributor Author

Choose a reason for hiding this comment

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

huh?

@zelig
Copy link
Member

zelig commented Apr 11, 2018

still dont understand rawTopic

@nolash
Copy link
Contributor Author

nolash commented Apr 11, 2018

@zelig did you read my comment on your comment on rawTopic before?

Copy link
Contributor

@nonsense nonsense left a comment

Choose a reason for hiding this comment

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

lgtm

@nolash nolash merged commit 5b7c6da into swarm-network-rewrite Apr 11, 2018
@nolash nolash deleted the pss-raw branch April 11, 2018 16:20
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.

4 participants