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 #374

Merged
merged 19 commits into from
Mar 28, 2024
Merged

SignedSSVMessage #374

merged 19 commits into from
Mar 28, 2024

Conversation

MatheusFranco99
Copy link
Contributor

@MatheusFranco99 MatheusFranco99 commented Mar 27, 2024

Overview

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

Changes

  • New SignedSSVMesage structure in types
  • Flat encoding for SignedSSVMesage
  • 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

Note: this is a non-fork version of #345

@MatheusFranco99
Copy link
Contributor Author

@y0sher I changed the encoding to match with the implementation one

Comment on lines 17 to 20
type MessageValidator interface {
ValidateSignedSSVMessage(signedSSVMessage *types.SignedSSVMessage) error
ValidateSignature(signedSSVMessage *types.SignedSSVMessage) error
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Add comments:

  1. Open a github issue that we need to add spec for MsgValidation and reference for ValidateSignedSSVMessage. Comment with the link to the issue.
  2. For ValidateSignature comment that it is an RSA sig with PKCSv1.5 padding. You can link to the RFC... I think the link I gave is good, you can double-check 😛

Comment on lines 140 to 144
type SignedSSVMessage struct {
OperatorID OperatorID
Signature []byte `ssz-max:"512"` // Created by the operator's private key. Max size allow keys up to 512*8 = 4096 bits
Data []byte `ssz-max:"6291893"` // Max size extracted from SSVMessage
}
Copy link
Contributor

@GalRogozinski GalRogozinski Mar 27, 2024

Choose a reason for hiding this comment

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

signature is the first field in impl
let's do it exactly the same...

Also remove the ssz notations

Comment on lines 125 to 274
// Field (0) 'OperatorID'
s.OperatorID = OperatorID(ssz.UnmarshallUint64(buf[0:8]))

// Offset (1) 'Signature'
if o1 = ssz.ReadOffset(buf[8:12]); o1 > size {
return ssz.ErrOffset
}

if o1 < 16 {
return ssz.ErrInvalidVariableOffset
}

// Offset (2) 'Data'
if o2 = ssz.ReadOffset(buf[12:16]); o2 > size || o1 > o2 {
return ssz.ErrOffset
}

// Field (1) 'Signature'
{
buf = tail[o1:o2]
if len(buf) > 512 {
return ssz.ErrBytesLength
}
if cap(s.Signature) == 0 {
s.Signature = make([]byte, 0, len(buf))
}
s.Signature = append(s.Signature, buf...)
}

// Field (2) 'Data'
{
buf = tail[o2:]
if len(buf) > 6291893 {
return ssz.ErrBytesLength
}
if cap(s.Data) == 0 {
s.Data = make([]byte, 0, len(buf))
}
s.Data = append(s.Data, buf...)
}
return err
}

// SizeSSZ returns the ssz encoded size in bytes for the SignedSSVMessage object
func (s *SignedSSVMessage) SizeSSZ() (size int) {
size = 16

// Field (1) 'Signature'
size += len(s.Signature)

// Field (2) 'Data'
size += len(s.Data)

return
}

// HashTreeRoot ssz hashes the SignedSSVMessage object
func (s *SignedSSVMessage) HashTreeRoot() ([32]byte, error) {
return ssz.HashWithDefaultHasher(s)
}

// HashTreeRootWith ssz hashes the SignedSSVMessage object with a hasher
func (s *SignedSSVMessage) HashTreeRootWith(hh ssz.HashWalker) (err error) {
indx := hh.Index()

// Field (0) 'OperatorID'
hh.PutUint64(uint64(s.OperatorID))

// Field (1) 'Signature'
{
elemIndx := hh.Index()
byteLen := uint64(len(s.Signature))
if byteLen > 512 {
err = ssz.ErrIncorrectListSize
return
}
hh.PutBytes(s.Signature)
hh.MerkleizeWithMixin(elemIndx, byteLen, (512+31)/32)
}

// Field (2) 'Data'
{
elemIndx := hh.Index()
byteLen := uint64(len(s.Data))
if byteLen > 6291893 {
err = ssz.ErrIncorrectListSize
return
}
hh.PutBytes(s.Data)
hh.MerkleizeWithMixin(elemIndx, byteLen, (6291893+31)/32)
}

hh.Merkleize(indx)
return
}

// GetTree ssz hashes the SignedSSVMessage object
func (s *SignedSSVMessage) GetTree() (*ssz.Node, error) {
return ssz.ProofTree(s)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

won't this be regenrated automatically?
we either need to make an exception for the type or move it to a file that won't cause automatic generation

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is not automatically generated because the encoding of the messages.go file is not included in the generate file. Adding a remark anyway.

)

// Valid tests a valid SignedSSVMessageTest
func Valid() *SignedSSVMessageTest {
Copy link
Contributor

@GalRogozinski GalRogozinski Mar 28, 2024

Choose a reason for hiding this comment

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

Now that you added MessageValidator maybe sig tests should be in MessageValidatorTest... (edit)

The issue is since our MessageValidator isn't aligned with implementation not sure how this will work out for the SSV team.

wdyt @y0sher and @moshe-blox

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree a lot has to be done regarding Message Validation. Plus, tests for it and SignedSSVMessage are related. But I think we could do it in a later PR, since (if I'm not mistaken) it's not a top priority and we're overheaded with other tasks.

Copy link
Contributor

Choose a reason for hiding this comment

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

@GalRogozinski @MatheusFranco99
I think this test should just use message validator as a blackbox, this means this test should check that all the behavior we expect to happen or not happen based on the msg validator response should be tested under SignedSSVMsg tests, all the stuff regarding message validation (signatures and other validations) should happen on its own place.
For this test, what message validator did doesn't matter , it should just test what it expects to see if message validator returned valid/invalid. could use a mock imo.

// To-Do: better spec the intended Message Validation behavior. Issue #375: https://github.com/bloxapp/ssv-spec/issues/375
type MessageValidator interface {
ValidateSignedSSVMessage(runner ssv.Runner, signedSSVMessage *types.SignedSSVMessage) error
ValidateSignature(runner ssv.Runner, signedSSVMessage *types.SignedSSVMessage) error // Verifies the message's RSA signature with PKCSv1.5 encoding. Ref: https://datatracker.ietf.org/doc/html/rfc8017#section-8.2.2
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
ValidateSignature(runner ssv.Runner, signedSSVMessage *types.SignedSSVMessage) error // Verifies the message's RSA signature with PKCSv1.5 encoding. Ref: https://datatracker.ietf.org/doc/html/rfc8017#section-8.2.2
VerifySignature(runner ssv.Runner, signedSSVMessage *types.SignedSSVMessage) error // Verifies the message's RSA signature with PKCSv1.5 encoding. Ref: https://datatracker.ietf.org/doc/html/rfc8017#section-8.2.2

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't object

I just want to admit that I use the words as synonyms and never understood the difference

type MessageValidator interface {
ValidateSignedSSVMessage(runner ssv.Runner, signedSSVMessage *types.SignedSSVMessage) error
ValidateSignature(runner ssv.Runner, signedSSVMessage *types.SignedSSVMessage) error
ValidateSignature(runner ssv.Runner, signedSSVMessage *types.SignedSSVMessage) error // Verifies the message's RSA signature with PKCSv1.5 encoding. Ref: https://datatracker.ietf.org/doc/html/rfc8017#section-8.2.2
Copy link
Contributor

Choose a reason for hiding this comment

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

nit, can you put the comment above the function please?

@GalRogozinski GalRogozinski merged commit 7a3b1de into main Mar 28, 2024
2 checks passed
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