-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use libp2p gossipsub upstream validator framework #4318
Conversation
This solution is not going to work as is. Adding a pubsub validator to reject all re-propagation will block all messages from being received. The problem with using the pubsub validator framework for validation is that when you need to inspect the message contents, you would need to deserialize the message more than once for any given valid message. With the assumption that the majority of the messages will be valid, this could be an expensive task. As is, we all repropagate messages once, thanks to content addressable message IDs. The problem is that we want to stop propagation of messages that are invalid. My thinking now is that we consider these two approaches:
I've reached out to @raulk on telegram to see if there is any expert feedback from their team. |
There's another option: introduce a preprocessing step, to then continue with the preprocessed message in validation and the subscription.
|
These options would certainly solve our problem. I imagine this pipeline:
|
Yes, I agree that we could add a baggage map where validators could store deserialised payloads or other computed/derived information, for downstream validators to reuse. We could also propagate this baggage to the final consumer. |
Oh hey! we already have a place for the validators to put things for the consumer, you can set Message.ValidatorData in the validator, and it is accessible by the receiver. |
Yep, it turns out this is already implemented and I had missed it :-) |
Awesome. Thanks @whyrusleeping @raulk @protolambda. We'll refactor our validation pipeline and use that field to pass around the message data. Thanks!!! |
OK this is ready for review again. I was experiencing some weird behavior that appears to run a validator on broadcast as well as the subscriber. libp2p/go-libp2p-pubsub#250 If anyone knows how to disable the validator on publish, I'd appreciate that info. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few nitpicks, I'm following this PR, good work so far 👍
func noopValidator(_ context.Context, _ proto.Message, _ p2p.Broadcaster, _ bool) (bool, error) { | ||
return true, nil | ||
// noopValidator is a no-op that only decodes the message, but does not check its contents. | ||
func (r *Service) noopValidator(ctx context.Context, _ peer.ID, msg *pubsub.Message) bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe call it preProcessValidator to make clear what it really is?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I think pubsub has a way to chain validators in sync, so you do not have to repeatedly call decodePubsubMessage, and put this as the preprocess validator instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually only used in test. From what I recall, all validators were run asynchronously. Chaining would be nice with your suggestion though.
From godocs:
RegisterTopicValidator registers a validator for topic. By default validators are asynchronous, which means they will run in a separate goroutine. The number of active goroutines is controlled by global and per topic validator throttles; if it exceeds the throttle threshold, messages will be dropped.
I'll leave this for now unless we can chain these.
return false | ||
} | ||
topic := msg.TopicIDs[0] | ||
topic = strings.TrimSuffix(topic, r.p2p.Encoding().ProtocolSuffix()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe the msg checks and topic extraction can be refactored into a helper function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice refactor, ninja'd this problem before I submitted the review. Great
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Terence beat you to it lol
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me otherwise
Co-Authored-By: terence tsao <terence@prysmaticlabs.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For all our failed message validations, is there anyway to capture this in our metrics ?
} | ||
seenAttesterSlashings.Set(cacheKey, true /*value*/, 1 /*cost*/) | ||
|
||
if fromSelf { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does libp2p not process messages from self ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's right, it won't send messages from itself to the subscription. It does, however, run validation on all messages published or subscribed. I've added a bit of a hack to immediately return true in validation if the pubsub message comes from ourselves. This bypasses the validation effectively as suggested here libp2p/go-libp2p-pubsub#250 (comment)
…ailure counter
…o pubsub-validator
* add reject all pubsub validator to stop automatic propagation of messages * gaz * Merge branch 'master' of github.com:prysmaticlabs/prysm into pubsub-validator * refactor p2p validator pipeline * add sanity check * Merge branch 'pubsub-validator' of github.com:prysmaticlabs/prysm into pubsub-validator * fixed up test * rem * gaz * Merge refs/heads/master into pubsub-validator * fix from self test * ensure validator data is set * resolve todo * Merge refs/heads/master into pubsub-validator * gaz * Merge refs/heads/master into pubsub-validator * Merge branch 'pubsub-validator' of github.com:prysmaticlabs/prysm into pubsub-validator * Merge refs/heads/master into pubsub-validator * remove all of the 'from self' logic. filed libp2p/go-libp2p-pubsub#250 * Merge branch 'pubsub-validator' of github.com:prysmaticlabs/prysm into pubsub-validator * gaz * update comment * Merge refs/heads/master into pubsub-validator * rename "VaidatorData" * Merge branch 'pubsub-validator' of github.com:prysmaticlabs/prysm into pubsub-validator * refactor * one more bit of refactoring * Update beacon-chain/sync/validate_beacon_attestation.go Co-Authored-By: terence tsao <terence@prysmaticlabs.com> * skip validation on self messages, add @nisdas feedback to increment failure counter * Merge branch 'pubsub-validator' of github.com:prysmaticlabs/prysm into pubsub-validator * remove flakey
* add reject all pubsub validator to stop automatic propagation of messages * gaz * Merge branch 'master' of github.com:prysmaticlabs/prysm into pubsub-validator * refactor p2p validator pipeline * add sanity check * Merge branch 'pubsub-validator' of github.com:prysmaticlabs/prysm into pubsub-validator * fixed up test * rem * gaz * Merge refs/heads/master into pubsub-validator * fix from self test * ensure validator data is set * resolve todo * Merge refs/heads/master into pubsub-validator * gaz * Merge refs/heads/master into pubsub-validator * Merge branch 'pubsub-validator' of github.com:prysmaticlabs/prysm into pubsub-validator * Merge refs/heads/master into pubsub-validator * remove all of the 'from self' logic. filed libp2p/go-libp2p-pubsub#250 * Merge branch 'pubsub-validator' of github.com:prysmaticlabs/prysm into pubsub-validator * gaz * update comment * Merge refs/heads/master into pubsub-validator * rename "VaidatorData" * Merge branch 'pubsub-validator' of github.com:prysmaticlabs/prysm into pubsub-validator * refactor * one more bit of refactoring * Update beacon-chain/sync/validate_beacon_attestation.go Co-Authored-By: terence tsao <terence@prysmaticlabs.com> * skip validation on self messages, add @nisdas feedback to increment failure counter * Merge branch 'pubsub-validator' of github.com:prysmaticlabs/prysm into pubsub-validator * remove flakey
Resolves #4317
Thanks to @protolambda for pointing this out.
This is now a refactoring to use the gossipsub validator framework.