Skip to content
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

SignedSSVMessage #345

Merged
merged 13 commits into from
Mar 21, 2024
Merged

SignedSSVMessage #345

merged 13 commits into from
Mar 21, 2024

Conversation

MatheusFranco99
Copy link
Contributor

@MatheusFranco99 MatheusFranco99 commented Jan 10, 2024

Overview

Introduce SignedSSVMessage, which encapsulates SSVMessage along with a signature and a sender identifier fields.

Changes

  • New SignedSSVMesage structure in types
  • DecodePubsubMsg now returns a SignedSSVMesage
  • MsgValidation adapted to receive a SignedSSVMesage instead of a SSVMessage.

Note: though SSVMessage is no longer the transmitted message in the network, the Runner still processes the type SSVMessage in the ProcessMessage function.

Tests

  • Encoding
  • Valid SignedSSVMessage
  • Invalid SignedSSVMessage with no data
  • Invalid SignedSSVMessage with empty signature
  • Invalid SignedSSVMessage with zero signer
  • Invalid SignedSSVMessage with wrong data

@MatheusFranco99 MatheusFranco99 self-assigned this Jan 10, 2024
@@ -15,11 +16,19 @@ type MsgValidatorFunc = func(ctx context.Context, p peer.ID, msg *pubsub.Message

func MsgValidation(runner ssv.Runner) MsgValidatorFunc {
return func(ctx context.Context, p peer.ID, msg *pubsub.Message) pubsub.ValidationResult {
ssvMsg, err := DecodePubsubMsg(msg)
signedSSVMsg, err := DecodePubsubMsg(msg)
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe this is a complaint to myself.. but we should have deleted MsgValidation since it is definitely not what the code does at the moment

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, let's remove it in another PR

@GalRogozinski GalRogozinski self-requested a review January 10, 2024 20:29
Copy link
Contributor

@GalRogozinski GalRogozinski left a comment

Choose a reason for hiding this comment

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

Looks great!

@@ -7,7 +7,7 @@ package types
//go:generate go run github.com/ferranbt/fastssz/sszgen --path share.go --include ./operator.go,./messages.go,./signer.go,./domain_type.go

//go:generate rm -f ./messages_encoding.go
//go:generate go run github.com/ferranbt/fastssz/sszgen --path messages.go --exclude-objs ValidatorPK,MessageID,MsgType
//go:generate go run github.com/ferranbt/fastssz/sszgen --path messages.go --include ./operator.go --exclude-objs ValidatorPK,MessageID,MsgType
Copy link
Contributor

Choose a reason for hiding this comment

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

not sure why this changed?

Copy link
Contributor

Choose a reason for hiding this comment

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

Because of OperatorID addition

// SSVMessage is the main message passed within the SSV network. It encapsulates the SSVMessage structure and a signature
type SignedSSVMessage struct {
OperatorID OperatorID
Signature []byte `ssz-max:"512"` // Current signature max size allow keys up to 512*8 = 4096 bits
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe it is just nice to comment that this is created by the operator's private key

Copy link
Contributor

@GalRogozinski GalRogozinski left a comment

Choose a reason for hiding this comment

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

I think maybe we need to add at least one test where we validate a real signature
to show that use RSA with correct padding

@MatheusFranco99
Copy link
Contributor Author

@GalRogozinski
The current tests only check msg.Validate() which doesn't check the signature. This is because we don't specify here how this signature should be created or validated.
I didn't add such a restriction on the type of signature because the message validation module (in p2p/validation) will be removed from spec in a future PR (right?) and the validator or runner don't have access to this signature.
What do you think?

@GalRogozinski
Copy link
Contributor

@MatheusFranco99

The spec should achieve 2 objectives in my eyes:

  1. Make sure that the node implementation doesn't accidentally change the protocol w.o detection
  2. Allow anyone to implement a node, ideally w.o looking at any other source.

Currently the spec doesn't exactly reach those objectives and in the spec rewrite I am hoping to change this.
In the meanwhile I wish to do things correctly for new additions :-)

Imagine someone changes the RSA parameters (for better security) and then creates an incompatibility.
This should be caught by the spec

@MatheusFranco99
Copy link
Contributor Author

@GalRogozinski
Sure, I'll be adding a check in message validation to verify the RSA signature and tests for it.

Copy link
Contributor

@GalRogozinski GalRogozinski left a comment

Choose a reason for hiding this comment

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

LGTM

@MatheusFranco99 MatheusFranco99 changed the title SignedMsgType SignedSSVMessage Mar 15, 2024
Comment on lines +38 to +46
if err == nil {
var pk *rsa.PublicKey
pk, err = types.PemToPublicKey(test.RSAPublicKey)
if err != nil {
panic(err.Error())
}

messageHash := sha256.Sum256(msg.Data)
err = rsa.VerifyPKCS1v15(pk, crypto.SHA256, messageHash[:], msg.Signature)
Copy link
Contributor

Choose a reason for hiding this comment

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

for a future PR, something we are working in ssv-node is encapsulating all operator pubkey/private key operation to make them less dependent on specific functions. so if for example we'll want to change our RSA implementation it will be easy.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's great. I will try to encapsulate it here too.

Copy link
Contributor

@y0sher y0sher left a comment

Choose a reason for hiding this comment

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

FYI this is probably a fork. we are creating signed messages in the node a bit differently right now.
https://github.com/bloxapp/ssv/blob/main/network/commons/common.go#L43

it might be good idea to consider using the same approach in the node unless this fork has some significant advantages.

@MatheusFranco99
Copy link
Contributor Author

@y0sher
Yes, I'm aware of that. The point of this PR is not only to define a type for this buffer approach that we're using on the node, but it also is a pre-requisite for the next "reduce signatures" PR. This signed message type will now be used in the runner module.

Copy link
Contributor

@GalRogozinski GalRogozinski left a comment

Choose a reason for hiding this comment

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

@y0sher @MatheusFranco99

This is a fork because the implementation puts signature first and the PR puts operator first, right?

If so we should change this to not be a fork because I don't think there is a real advantage here...

@y0sher
Copy link
Contributor

y0sher commented Mar 19, 2024

@y0sher @MatheusFranco99

This is a fork because the implementation puts signature first and the PR puts operator first, right?

If so we should change this to not be a fork because I don't think there is a real advantage here...

Its a fork because the implementation uses its own way of encoding the sig and operators. even if you create the struct in the PR in the same order it doesn't mean the final encoded data will be the same unless you enforce the struct to be encoded in the same way.
In your PR the encoding is SSZ, where in the impl it is just raw data bytes on a buffer.

@GalRogozinski
Copy link
Contributor

@moshe-blox @y0sher

There are 2 things we can do here:

  1. Delete the ssz encoding and use the same encoding as impl
  2. Make this part of the upcoming fork

The only reason I would use SSZ is just for the sake of consistency, since we use SSZ everywhere. Besides this I don't see an advantage. But this is good enough for me to opt for 2.
If you guys don't want to change to SSZ then we can go for 1.

Copy link
Contributor

@GalRogozinski GalRogozinski left a comment

Choose a reason for hiding this comment

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

Currently we fork so changed order is fine

@GalRogozinski GalRogozinski changed the base branch from main to Atlanta March 21, 2024 11:42
@GalRogozinski GalRogozinski merged commit df58d97 into Atlanta Mar 21, 2024
2 checks passed
@GalRogozinski GalRogozinski mentioned this pull request Mar 28, 2024
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants