Skip to content

Commit

Permalink
Read only payload attestation message with verifier
Browse files Browse the repository at this point in the history
  • Loading branch information
terencechain committed Jul 20, 2024
1 parent 09e1443 commit 2b8e44f
Show file tree
Hide file tree
Showing 8 changed files with 247 additions and 0 deletions.
1 change: 1 addition & 0 deletions beacon-chain/core/helpers/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ go_test(
"validators_test.go",
"weak_subjectivity_test.go",
],
data = glob(["testdata/**"]),
embed = [":go_default_library"],
shard_count = 2,
tags = ["CI_race_detection"],
Expand Down
23 changes: 23 additions & 0 deletions consensus-types/payload-attestation/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
load("@prysm//tools/go:def.bzl", "go_library")

go_library(
name = "go_default_library",
srcs = [
"error.go",
"log.go",
"mock.go",
"readonly.go",
"requirement.go",
"verifier.go",
],
importpath = "github.com/prysmaticlabs/prysm/v5/consensus-types/payload-attestation",
visibility = ["//visibility:public"],
deps = [
"//beacon-chain/startup:go_default_library",
"//consensus-types/primitives:go_default_library",
"//encoding/bytesutil:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
],
)
11 changes: 11 additions & 0 deletions consensus-types/payload-attestation/error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package payloadattestation

import "github.com/pkg/errors"

var (
errNilPayloadMessage = errors.New("received nil payload message")
errNilPayloadData = errors.New("received nil payload data")
errMissingPayloadSignature = errors.New("received nil payload signature")
ErrMismatchCurrentSlot = errors.New("does not match current slot")
ErrUnknownPayloadStatus = errors.New("unknown payload status")
)
18 changes: 18 additions & 0 deletions consensus-types/payload-attestation/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package payloadattestation

import (
"fmt"

"github.com/sirupsen/logrus"
)

// logFields returns log fields for a ReadOnlyPayloadAtt instance.
func logFields(payload ReadOnlyPayloadAtt) logrus.Fields {
return logrus.Fields{
"slot": payload.Slot(),
"validatorIndex": payload.ValidatorIndex(),
"signature": fmt.Sprintf("%#x", payload.Signature()),
"beaconBlockRoot": fmt.Sprintf("%#x", payload.BeaconBlockRoot()),
"payloadStatus": payload.PayloadStatus(),
}
}
47 changes: 47 additions & 0 deletions consensus-types/payload-attestation/mock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package payloadattestation

type MockVerifier struct {
ErrCurrentSlot error
ErrAlreadySeenMessage error
ErrInvalidStatus error
ErrValidatorNotInPayload error
ErrBlockRootNotSeen error
ErrInvalidBlockRoot error
ErrInvalidMessageSignature error
ErrUnsatisfiedRequirement error
cbVerifiedMessage func() (VerifiedReadOnly, error)
}

func (m *MockVerifier) CheckCurrentSlot() error {
return m.ErrCurrentSlot
}

func (m *MockVerifier) CheckPayloadMessageAlreadySeen() error {
return m.ErrAlreadySeenMessage
}

func (m *MockVerifier) CheckKnownPayloadStatus() error {
return m.ErrInvalidStatus
}

func (m *MockVerifier) CheckValidatorInPayload() error {
return m.ErrValidatorNotInPayload
}

func (m *MockVerifier) CheckBlockRootSeen() error {
return m.ErrBlockRootNotSeen
}

func (m *MockVerifier) CheckBlockRootValid() error {
return m.ErrInvalidBlockRoot
}

func (m *MockVerifier) CheckSignatureValid() error {
return m.ErrInvalidMessageSignature
}

func (m *MockVerifier) SatisfyRequirement(requirement Requirement) {}

func (m *MockVerifier) VerifiedPayloadAttestationMessage() (VerifiedReadOnly, error) {
return m.cbVerifiedMessage()
}
64 changes: 64 additions & 0 deletions consensus-types/payload-attestation/readonly.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package payloadattestation

import (
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
)

// ReadOnlyPayloadAtt represents a read-only payload attestation message.
type ReadOnlyPayloadAtt struct {
message *ethpb.PayloadAttestationMessage
}

// validatePayload checks if the given payload attestation message is valid.
func validatePayload(message *ethpb.PayloadAttestationMessage) error {
if message == nil {
return errNilPayloadMessage
}
if message.Data == nil {
return errNilPayloadData
}
if len(message.Signature) == 0 {
return errMissingPayloadSignature
}
return nil
}

// NewReadOnly creates a new ReadOnlyPayloadAtt instance after validating the message.
func NewReadOnly(message *ethpb.PayloadAttestationMessage) (ReadOnlyPayloadAtt, error) {
if err := validatePayload(message); err != nil {
return ReadOnlyPayloadAtt{}, err
}
return ReadOnlyPayloadAtt{message}, nil
}

// ValidatorIndex returns the validator index from the payload attestation message.
func (r *ReadOnlyPayloadAtt) ValidatorIndex() primitives.ValidatorIndex {
return r.message.ValidatorIndex
}

// Signature returns the signature from the payload attestation message.
func (r *ReadOnlyPayloadAtt) Signature() [96]byte {
return bytesutil.ToBytes96(r.message.Signature)
}

// BeaconBlockRoot returns the beacon block root from the payload attestation message.
func (r *ReadOnlyPayloadAtt) BeaconBlockRoot() [32]byte {
return bytesutil.ToBytes32(r.message.Data.BeaconBlockRoot)
}

// Slot returns the slot from the payload attestation message.
func (r *ReadOnlyPayloadAtt) Slot() primitives.Slot {
return r.message.Data.Slot
}

// PayloadStatus returns the payload status from the payload attestation message.
func (r *ReadOnlyPayloadAtt) PayloadStatus() primitives.PTCStatus {
return r.message.Data.PayloadStatus
}

// VerifiedReadOnly represents a verified read-only payload attestation message.
type VerifiedReadOnly struct {
ReadOnlyPayloadAtt
}
31 changes: 31 additions & 0 deletions consensus-types/payload-attestation/requirement.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package payloadattestation

// Requirement represents a type of requirement for payload attestation.
type Requirement int

// RequirementList defines a list of requirements.
type RequirementList []Requirement

const (
RequireCurrentSlot Requirement = iota
RequireMessageNotSeen
RequireKnownPayloadStatus
RequireValidatorInPayload
RequireBlockRootSeen
RequireBlockRootValid
RequireSignatureValid
)

// GossipRequirements defines the list of requirements for gossip payload attestation messages.
var GossipRequirements = []Requirement{
RequireCurrentSlot,
RequireMessageNotSeen,
RequireKnownPayloadStatus,
RequireValidatorInPayload,
RequireBlockRootSeen,
RequireBlockRootValid,
RequireSignatureValid,
}

// GossipPayloadAttestationMessageRequirements is a requirement list for gossip payload attestation messages.
var GossipPayloadAttestationMessageRequirements = RequirementList(GossipRequirements)
52 changes: 52 additions & 0 deletions consensus-types/payload-attestation/verifier.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package payloadattestation

import (
"github.com/prysmaticlabs/prysm/v5/beacon-chain/startup"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
log "github.com/sirupsen/logrus"
)

// Verifier defines the methods required for verifying payload attestation messages.
type Verifier interface {
VerifyCurrentSlot() error
VerifyPayloadMessageAlreadySeen(error)
VerifyKnownPayloadStatus() error
VerifyValidatorInPayload() error
VerifyBlockRootSeen() error
VerifyBlockRootValid() error
VerifySignatureValid() error
MeetRequirement(Requirement)
GetVerifiedPayloadAttestationMessage() (VerifiedReadOnly, error)
}

// Resources contains the resources shared across verifiers.
type Resources struct {
clock *startup.Clock
}

// NewVerifierFunc is a factory function to create a new Verifier.
type NewVerifierFunc func(r ReadOnlyPayloadAtt, reqs []Requirement) Verifier

// PayloadVerifier is a read-only verifier for payload attestation messages.
type PayloadVerifier struct {
Resources
payloadAtt ReadOnlyPayloadAtt
}

// VerifyCurrentSlot verifies if the current slot matches the expected slot.
func (v *PayloadVerifier) VerifyCurrentSlot() error {
if v.clock.CurrentSlot() != v.clock.CurrentSlot() {
log.WithFields(fields(v.payloadAtt)).Errorf("does not match current slot %d", v.clock.CurrentSlot())
return ErrMismatchCurrentSlot
}
return nil
}

// VerifyKnownPayloadStatus verifies if the payload status is known.
func (v *PayloadVerifier) VerifyKnownPayloadStatus() error {
if v.payloadAtt.PayloadStatus() > primitives.PAYLOAD_INVALID_STATUS {
log.WithFields(fields(v.payloadAtt)).Error("unknown payload status")
return ErrUnknownPayloadStatus
}
return nil
}

0 comments on commit 2b8e44f

Please sign in to comment.