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
31 changes: 27 additions & 4 deletions p2p/validation/msg_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package validation

import (
"context"

"github.com/bloxapp/ssv-spec/qbft"
"github.com/bloxapp/ssv-spec/ssv"
"github.com/bloxapp/ssv-spec/types"
Expand All @@ -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

if err != nil {
return pubsub.ValidationReject
}
if validateSSVMessage(runner, ssvMsg) != nil {

// Validate SignedSSVMessage
if validateSignedSSVMessage(runner, signedSSVMsg) != nil {
return pubsub.ValidationReject
}

// Get SSVMessage
ssvMsg, err := signedSSVMsg.GetSSVMessageFromData()
if err != nil {
return pubsub.ValidationReject
}

Expand All @@ -40,15 +49,29 @@ func MsgValidation(runner ssv.Runner) MsgValidatorFunc {
}
}

func DecodePubsubMsg(msg *pubsub.Message) (*types.SSVMessage, error) {
func DecodePubsubMsg(msg *pubsub.Message) (*types.SignedSSVMessage, error) {
byts := msg.GetData()
ret := &types.SSVMessage{}
ret := &types.SignedSSVMessage{}
if err := ret.Decode(byts); err != nil {
return nil, err
}
return ret, nil
}

func validateSignedSSVMessage(runner ssv.Runner, msg *types.SignedSSVMessage) error {

if err := msg.Validate(); err != nil {
return err
}

ssvMessage, err := msg.GetSSVMessageFromData()
if err != nil {
return err
}

return validateSSVMessage(runner, ssvMessage)
}

func validateSSVMessage(runner ssv.Runner, msg *types.SSVMessage) error {
if !runner.GetBaseRunner().Share.ValidatorPubKey.MessageIDBelongs(msg.GetID()) {
return errors.New("msg ID doesn't match validator ID")
Expand Down
2 changes: 1 addition & 1 deletion types/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

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

//go:generate rm -f ./beacon_types_encoding.go
//go:generate go run github.com/ferranbt/fastssz/sszgen --path beacon_types.go --include $GOPATH/pkg/mod/github.com/attestantio/[email protected]/spec/phase0 --exclude-objs BeaconNetwork,BeaconRole
Expand Down
61 changes: 61 additions & 0 deletions types/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"bytes"
"encoding/binary"
"encoding/hex"

"github.com/pkg/errors"
)

// ValidatorPK is an eth2 validator public key
Expand Down Expand Up @@ -125,3 +127,62 @@ func (msg *SSVMessage) Encode() ([]byte, error) {
func (msg *SSVMessage) Decode(data []byte) error {
return msg.UnmarshalSSZ(data)
}

// 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"` // 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
}

// GetOperatorID returns the sender operator ID
func (msg *SignedSSVMessage) GetOperatorID() OperatorID {
return msg.OperatorID
}

// GetSignature returns the signature of the OperatorID over Data
func (msg *SignedSSVMessage) GetSignature() []byte {
return msg.Signature
}

// GetData returns message Data as byte slice
func (msg *SignedSSVMessage) GetData() []byte {
return msg.Data
}

// GetSSVMessageFromData returns message SSVMessage decoded from data
func (msg *SignedSSVMessage) GetSSVMessageFromData() (*SSVMessage, error) {
ssvMessage := &SSVMessage{}
err := ssvMessage.Decode(msg.Data)
if err != nil {
return nil, errors.Wrap(err, "could not decode SSVMessage from data in SignedSSVMessage")
}
return ssvMessage, nil
}

// Encode returns a msg encoded bytes or error
func (msg *SignedSSVMessage) Encode() ([]byte, error) {
return msg.MarshalSSZ()
}

// Decode returns error if decoding failed
func (msg *SignedSSVMessage) Decode(data []byte) error {
return msg.UnmarshalSSZ(data)
}

// Validate checks the following rules:
// - OperatorID should not be 0
// - Signature length should not be 0
// - Data length should not be 0
func (msg *SignedSSVMessage) Validate() error {
if msg.OperatorID == 0 {
return errors.New("OperatorID in SignedSSVMessage is 0")
}
if len(msg.Signature) == 0 {
return errors.New("Signature has length 0 in SignedSSVMessage")
}
if len(msg.Data) == 0 {
return errors.New("Data has length 0 in SignedSSVMessage")
}
return nil
}
152 changes: 151 additions & 1 deletion types/messages_encoding.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions types/spectest/all_tests.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"github.com/bloxapp/ssv-spec/types/spectest/tests/partialsigmessage"
"github.com/bloxapp/ssv-spec/types/spectest/tests/share"
"github.com/bloxapp/ssv-spec/types/spectest/tests/ssvmsg"

"github.com/bloxapp/ssv-spec/types/spectest/tests/signedssvmsg"
"github.com/bloxapp/ssv-spec/types/spectest/tests/ssz"
)

Expand Down Expand Up @@ -97,6 +99,13 @@ var AllTests = []SpecTest{

beacon.DepositData(),

signedssvmsg.Encoding(),
signedssvmsg.Valid(),
signedssvmsg.NoData(),
signedssvmsg.EmptySignature(),
signedssvmsg.ZeroSigner(),
signedssvmsg.WrongData(),

share.HasPartialQuorumButNoQuorum(),
share.HasQuorum(),
share.HasQuorum3f1(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"Name": "encoding",
"Data": "AQAAAAAAAAAQAAAAEAEAAJ4RbcE7rt9XkrU0Gz+CmiUMg88fH/b8hB/oHOpFocKDdcWx5Q5xbAjiCHmq8rZtUHzrskOqPoZLsR9UY3LRAlJF9ban+DOnDnmloFi67e82d6EAfk6AYZ1ZNSZinWVYkRvP03J5gk3yRddHhPOWVDc4rwdxGYrTOLNZTTwyMcEiBqrPMrJ2SDwVpmw9RXGdEDNLrpVsuBRsCQKjr+7X1PBijkvmDfZO78uzyELIr/WUXWjgeBt1JK+4EVS2fn6DHY+t4E+kjKOrwsTw/+I6h7onqZa4kN7MM/10Cftu/NRTFhLiSwAxGgu6PcrDfDfmpaqFZgr1kdGrrGp8gDgB4CcBAAAAAAAAAAAAAwGOgAZlUagbMYJYcJ7a990fY81oag5NuLKbu3rP5lYIZ3r1pSfZRI7keDVIXgK1C8AAAAAARAAAAGwAAAC4Hs0i5KpVrepqk99cOgnRwFklXk1z+iLSuhz7kDMpGlKR3Fcf+DnJb/Hl+PSPwFcARY04jz4nVo8NdgTUduo7GOUm+WixamknKtLuJv5boz/EBTmKKiYlItZjiR4ztSABAAAAAAAAAAIAAAAAAAAADAAAAAAAAAAUAAAApHmwI9nyjrnM3TW7lg+1wmVTDf8Xiufkqbd/AX91nKWiEl5ya94M2SozMAlUlMjAB4Kif6iQfowarePazbjgYUaGxn4fYoMEYF14YeDtmAPGriFrSq5VqP+0nu0ZPL6nRiYR0sWSvfUhTxJP56Ummrc9RO/J5s4avjL4GWrlJt4BAAAAAAAAAA=="
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"Name": "empty signature",
"Messages": [
{
"OperatorID": 1,
"Signature": "",
"Data": "AQIDBA=="
}
],
"ExpectedError": "Signature has length 0 in SignedSSVMessage",
"RSAPublicKey": null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"Name": "no data",
"Messages": [
{
"OperatorID": 1,
"Signature": "AQIDBA==",
"Data": ""
}
],
"ExpectedError": "Data has length 0 in SignedSSVMessage",
"RSAPublicKey": null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"Name": "valid",
"Messages": [
{
"OperatorID": 1,
"Signature": "asg313UXGPJPH1X4S5kFA0mP0EViK+/fiAudKPNWxmgSLAOOZa+zwhUCkd1lI6Mzxta8GsUwxxRekEclK7ipkjqeND6S9M5+EyyKOIXPkv3jaSHSJgy3czrM95vmr+ZEvlFeNVc1ueCVSc4tYn1WPE2Jgv5x2yGiI65gxOptXXUULfwxeTt+N+9nhKwYkHkosHYLEcSzVJ8+VSBLtQUQhZPAIhQBAQU5QO2xlHQaGz3AYoWXf1dMI3fmDJzxxT+We2pwW8mZ5uFiZnKxJKbo0Qjw6Pp8ZGBHAf9+3O3AxHjpwgJq7enmMTPVcgf8igiB4lqPSS2EbpNUBkAo6CyXqg==",
"Data": "AQAAAAAAAAAAAAMBjoAGZVGoGzGCWHCe2vfdH2PNaGoOTbiym7t6z+ZWCGd69aUn2USO5Hg1SF4CtQvAAAAAAEQAAABsAAAAuB7NIuSqVa3qapPfXDoJ0cBZJV5Nc/oi0roc+5AzKRpSkdxXH/g5yW/x5fj0j8BXAEWNOI8+J1aPDXYE1HbqOxjlJvlosWppJyrS7ib+W6M/xAU5iiomJSLWY4keM7UgAQAAAAAAAAACAAAAAAAAAAwAAAAAAAAAFAAAAKR5sCPZ8o65zN01u5YPtcJlUw3/F4rn5Km3fwF/dZylohJecmveDNkqMzAJVJTIwAeCon+okH6MGq3j2s244GFGhsZ+H2KDBGBdeGHg7ZgDxq4ha0quVaj/tJ7tGTy+p0YmEdLFkr31IU8ST+elJpq3PUTvyebOGr4y+Blq5SbeAQAAAAAAAAA="
}
],
"ExpectedError": "",
"RSAPublicKey": "LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBdU1WaU9YbWZ6aTA5MnZ6aUZrVUkKRHNRdEhLemlRZXh2cDhCa0lBd3R4cXpadFJXT2IzVFp3NG8zbDB3Z2RiQ0wvQzBLUWlMOUFCOGViTUQzUi9UdApFRXJtcEhHdTlDOTY5OTdyNlhtbjk2a3RabjN2RjdXUzN4elFHTytkR2Z0S0hLMG5YdldLVXAvcUJ6KzFFNnBYCkVTeVNHR01lZ2w5L3BSQkdXSEZVZUVXODRDV0ttaWlXVU1aYXBlTE1BalJwK20zTi96Unc3dHVpMmZrVnNFV0UKNGwxck01VlZ1R0JOUFc2dDR3cUJpbDdHY3pHNmpyQ3Z2TDJEZzF6eDM3cUVWZHBkMVBQdjc1VzdQUlVuTzV5NApkVTVwSEZPUENwbmZvRkJENjgwOTZHYW5EU2NTaDRpd3VkeGgyTGg0MmREVzI2eUNQYTQ3OUZXd0NFMk9JVEk1Cjl3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"Name": "wrong data",
"Messages": [
{
"OperatorID": 1,
"Signature": "AQIDBA==",
"Data": "AQIDBA=="
}
],
"ExpectedError": "could not decode SSVMessage from data in SignedSSVMessage: incorrect size",
"RSAPublicKey": null
}
Loading
Loading