From aaf56f9c39bc2f11888205f0fb4ac7046aaf7e68 Mon Sep 17 00:00:00 2001 From: "Aratz M. Lasa" Date: Wed, 11 Jan 2023 17:01:23 +0100 Subject: [PATCH 1/2] extract errors into error types --- pkg/api/api.go | 47 ++++++++++++++++++++++++--------- pkg/relay/relay.go | 51 +++++++++++++++--------------------- pkg/structs/errors.go | 17 +++++++++++- pkg/validators/validators.go | 7 +++-- 4 files changed, 74 insertions(+), 48 deletions(-) diff --git a/pkg/api/api.go b/pkg/api/api.go index 42af7ce0..b8d155c2 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -15,7 +15,6 @@ import ( "github.com/lthibault/log" "github.com/prometheus/client_golang/prometheus" - "github.com/blocknative/dreamboat/pkg/relay" "github.com/blocknative/dreamboat/pkg/structs" ) @@ -524,18 +523,40 @@ type jsonError struct { } func unwrapError(err error, defaultMsg string) error { - if errors.Is(err, relay.ErrNoPayloadFound) { - return relay.ErrNoPayloadFound - } else if errors.Is(err, relay.ErrNoBuilderBid) { - return relay.ErrNoBuilderBid - } else if errors.Is(err, relay.ErrBadHeader) { - return relay.ErrBadHeader - } else if errors.Is(err, relay.ErrMissingRequest) { - return relay.ErrMissingRequest - } else if errors.Is(err, relay.ErrMissingSecretKey) { - return relay.ErrMissingSecretKey - } else if errors.Is(err, relay.ErrOldSlot) { - return relay.ErrOldSlot + if errors.Is(err, structs.ErrUnknownValue) { + return structs.ErrUnknownValue + } else if errors.Is(err, structs.ErrPayloadAlreadyDelivered) { + return structs.ErrPayloadAlreadyDelivered + } else if errors.Is(err, structs.ErrNoPayloadFound) { + return structs.ErrNoPayloadFound + } else if errors.Is(err, structs.ErrMissingRequest) { + return structs.ErrMissingRequest + } else if errors.Is(err, structs.ErrMissingSecretKey) { + return structs.ErrMissingSecretKey + } else if errors.Is(err, structs.ErrNoBuilderBid) { + return structs.ErrNoBuilderBid + } else if errors.Is(err, structs.ErrOldSlot) { + return structs.ErrOldSlot + } else if errors.Is(err, structs.ErrBadHeader) { + return structs.ErrBadHeader + } else if errors.Is(err, structs.ErrInvalidSignature) { + return structs.ErrInvalidSignature + } else if errors.Is(err, structs.ErrStore) { + return structs.ErrStore + } else if errors.Is(err, structs.ErrMarshal) { + return structs.ErrMarshal + } else if errors.Is(err, structs.ErrInternal) { + return structs.ErrInternal + } else if errors.Is(err, structs.ErrUnknownValidator) { + return structs.ErrUnknownValidator + } else if errors.Is(err, structs.ErrVerification) { + return structs.ErrVerification + } else if errors.Is(err, structs.ErrInvalidTimestamp) { + return structs.ErrInvalidTimestamp + } else if errors.Is(err, structs.ErrInvalidSlot) { + return structs.ErrInvalidSlot + } else if errors.Is(err, structs.ErrEmptyBlock) { + return structs.ErrEmptyBlock } return errors.New(defaultMsg) diff --git a/pkg/relay/relay.go b/pkg/relay/relay.go index 10839ccd..b2b59236 100644 --- a/pkg/relay/relay.go +++ b/pkg/relay/relay.go @@ -24,15 +24,6 @@ type Verifier interface { Enqueue(ctx context.Context, sig [96]byte, pubkey [48]byte, msg [32]byte) (err error) } -var ( - ErrNoPayloadFound = errors.New("no payload found") - ErrMissingRequest = errors.New("req is nil") - ErrMissingSecretKey = errors.New("secret key is nil") - ErrNoBuilderBid = errors.New("no builder bid") - ErrOldSlot = errors.New("requested slot is old") - ErrBadHeader = errors.New("invalid block header from datastore") -) - type Datastore interface { CheckSlotDelivered(context.Context, uint64) (bool, error) PutDelivered(context.Context, structs.Slot, structs.DeliveredTrace, time.Duration) error @@ -138,10 +129,10 @@ func (rs *Relay) GetHeader(ctx context.Context, m *structs.MetricGroup, request if !ok { if slot < rs.beaconState.Beacon().HeadSlot()-1 { rs.m.MissHeaderCount.WithLabelValues("oldSlot").Add(1) - return nil, ErrOldSlot + return nil, structs.ErrOldSlot } rs.m.MissHeaderCount.WithLabelValues("noSubmission").Add(1) - return nil, ErrNoBuilderBid + return nil, structs.ErrNoBuilderBid } m.AppendSince(tGet, "getHeader", "get") @@ -154,9 +145,9 @@ func (rs *Relay) GetHeader(ctx context.Context, m *structs.MetricGroup, request header := maxProfitBlock.Header if header.Header == nil || (header.Header.ParentHash != parentHash) { - logger.Debug(ErrBadHeader.Error()) + logger.Debug(structs.ErrBadHeader.Error()) rs.m.MissHeaderCount.WithLabelValues("badHeader").Add(1) - return nil, ErrNoBuilderBid + return nil, structs.ErrNoBuilderBid } bid := types.BuilderBid{ @@ -169,7 +160,7 @@ func (rs *Relay) GetHeader(ctx context.Context, m *structs.MetricGroup, request signature, err := types.SignMessage(&bid, rs.config.BuilderSigningDomain, rs.config.SecretKey) m.AppendSince(tSignature, "getHeader", "signature") if err != nil { - return nil, fmt.Errorf("internal server error") + return nil, structs.ErrInternal } logger.With(log.F{ @@ -192,12 +183,12 @@ func (rs *Relay) GetPayload(ctx context.Context, m *structs.MetricGroup, payload defer m.AppendSince(tStart, "getPayload", "all") if len(payloadRequest.Signature) != 96 { - return nil, fmt.Errorf("invalid signature") + return nil, structs.ErrInvalidSignature } proposerPubkey, err := rs.beaconState.Beacon().KnownValidatorByIndex(payloadRequest.Message.ProposerIndex) if err != nil && errors.Is(err, structs.ErrUnknownValue) { - return nil, fmt.Errorf("unknown validator for index %d", payloadRequest.Message.ProposerIndex) + return nil, fmt.Errorf("%w for index %d", structs.ErrUnknownValidator, payloadRequest.Message.ProposerIndex) } else if err != nil { return nil, err } @@ -218,11 +209,11 @@ func (rs *Relay) GetPayload(ctx context.Context, m *structs.MetricGroup, payload msg, err := types.ComputeSigningRoot(payloadRequest.Message, rs.config.ProposerSigningDomain) if err != nil { - return nil, fmt.Errorf("signature invalid") // err + return nil, structs.ErrInvalidSignature // err } ok, err := verify.VerifySignatureBytes(msg, payloadRequest.Signature[:], pk[:]) if err != nil || !ok { - return nil, fmt.Errorf("signature invalid") + return nil, structs.ErrInvalidSignature } m.AppendSince(tVerify, "getPayload", "verify") @@ -235,7 +226,7 @@ func (rs *Relay) GetPayload(ctx context.Context, m *structs.MetricGroup, payload payload, fromCache, err := rs.d.GetPayload(ctx, key) if err != nil || payload == nil { - return nil, ErrNoPayloadFound + return nil, structs.ErrNoPayloadFound } m.AppendSince(tGet, "getPayload", "get") @@ -299,11 +290,11 @@ func (rs *Relay) GetPayload(ctx context.Context, m *structs.MetricGroup, payload // SubmitBlockRequestToSignedBuilderBid converts a builders block submission to a bid compatible with mev-boost func SubmitBlockRequestToSignedBuilderBid(req *types.BuilderSubmitBlockRequest, sk *bls.SecretKey, pubkey *types.PublicKey, domain types.Domain) (*types.SignedBuilderBid, error) { // TODO(l): remove FB type if req == nil { - return nil, ErrMissingRequest + return nil, structs.ErrMissingRequest } if sk == nil { - return nil, ErrMissingSecretKey + return nil, structs.ErrMissingSecretKey } header, err := types.PayloadToPayloadHeader(req.ExecutionPayload) @@ -344,7 +335,7 @@ func (rs *Relay) SubmitBlock(ctx context.Context, m *structs.MetricGroup, submit _, err := rs.verifyBlock(submitBlockRequest, rs.beaconState.Beacon()) if err != nil { - return fmt.Errorf("verify block: %w", err) + return fmt.Errorf("%w: %s", structs.ErrVerification, err.Error()) // TODO: multiple err wrapping in Go 1.20 } tCheckDelivered := time.Now() @@ -361,14 +352,14 @@ func (rs *Relay) SubmitBlock(ctx context.Context, m *structs.MetricGroup, submit tVerify := time.Now() msg, err := types.ComputeSigningRoot(submitBlockRequest.Message, rs.config.BuilderSigningDomain) if err != nil { - return fmt.Errorf("signature invalid") + return structs.ErrInvalidSignature } err = rs.ver.Enqueue(ctx, submitBlockRequest.Signature, submitBlockRequest.Message.BuilderPubkey, msg) m.AppendSince(tVerify, "submitBlock", "verify") if err != nil { - return fmt.Errorf("verify block: %w", err) + return fmt.Errorf("%w: %s", structs.ErrVerification, err.Error()) // TODO: multiple err wrapping in Go 1.20 } complete, err := rs.prepareContents(submitBlockRequest) @@ -378,12 +369,12 @@ func (rs *Relay) SubmitBlock(ctx context.Context, m *structs.MetricGroup, submit b, err := json.Marshal(complete.Header) if err != nil { - return fmt.Errorf("fail to marshal block as header: %w", err) + return fmt.Errorf("%w block as header: %s", structs.ErrMarshal, err.Error()) // TODO: multiple err wrapping in Go 1.20 } tPutPayload := time.Now() if err := rs.d.PutPayload(ctx, SubmissionToKey(submitBlockRequest), &complete.Payload, rs.config.TTL); err != nil { - return fmt.Errorf("fail to store block as payload: %w", err) + return fmt.Errorf("%w block as payload: %s", structs.ErrStore, err.Error()) // TODO: multiple err wrapping in Go 1.20 } m.AppendSince(tPutPayload, "submitBlock", "putPayload") @@ -398,7 +389,7 @@ func (rs *Relay) SubmitBlock(ctx context.Context, m *structs.MetricGroup, submit HeaderAndTrace: complete.Header, }, rs.config.TTL) if err != nil { - return fmt.Errorf("fail to store block as header: %w", err) + return fmt.Errorf("%w block as header: %s", structs.ErrStore, err.Error()) // TODO: multiple err wrapping in Go 1.20 } m.AppendSince(tPutHeader, "submitBlock", "putHeader") @@ -457,16 +448,16 @@ func (rs *Relay) prepareContents(submitBlockRequest *types.BuilderSubmitBlockReq func (rs *Relay) verifyBlock(submitBlockRequest *types.BuilderSubmitBlockRequest, beaconState *structs.BeaconState) (bool, error) { // TODO(l): remove FB type if submitBlockRequest == nil || submitBlockRequest.Message == nil { - return false, fmt.Errorf("block empty") + return false, structs.ErrEmptyBlock } expectedTimestamp := beaconState.GenesisTime + (submitBlockRequest.Message.Slot * 12) if submitBlockRequest.ExecutionPayload.Timestamp != expectedTimestamp { - return false, fmt.Errorf("builder submission with wrong timestamp. got %d, expected %d", submitBlockRequest.ExecutionPayload.Timestamp, expectedTimestamp) + return false, fmt.Errorf("%w: got %d, expected %d", structs.ErrInvalidTimestamp, submitBlockRequest.ExecutionPayload.Timestamp, expectedTimestamp) } if structs.Slot(submitBlockRequest.Message.Slot) < beaconState.CurrentSlot { - return false, fmt.Errorf("builder submission with wrong slot. got %d, expected %d", submitBlockRequest.Message.Slot, beaconState.CurrentSlot) + return false, fmt.Errorf("%w: got %d, expected %d", structs.ErrInvalidSlot, submitBlockRequest.Message.Slot, beaconState.CurrentSlot) } return true, nil diff --git a/pkg/structs/errors.go b/pkg/structs/errors.go index bb44b4b4..ddf660ac 100644 --- a/pkg/structs/errors.go +++ b/pkg/structs/errors.go @@ -4,5 +4,20 @@ import "errors" var ( ErrUnknownValue = errors.New("value is unknown") - ErrPayloadAlreadyDelivered = errors.New("the slot payload was already delivered") + ErrPayloadAlreadyDelivered = errors.New("slot payload already delivered") + ErrNoPayloadFound = errors.New("no payload found") + ErrMissingRequest = errors.New("req is nil") + ErrMissingSecretKey = errors.New("secret key is nil") + ErrNoBuilderBid = errors.New("no builder bid") + ErrOldSlot = errors.New("requested slot is old") + ErrBadHeader = errors.New("invalid block header from datastore") + ErrInvalidSignature = errors.New("invalid signature") + ErrStore = errors.New("failed to store") + ErrMarshal = errors.New("failed to marshal") + ErrInternal = errors.New("internal server error") + ErrUnknownValidator = errors.New("unknown validator") + ErrVerification = errors.New("failed to verify") + ErrInvalidTimestamp = errors.New("invalid timestamp") + ErrInvalidSlot = errors.New("invalid slot") + ErrEmptyBlock = errors.New("block is empty") ) diff --git a/pkg/validators/validators.go b/pkg/validators/validators.go index 991fa9a9..25135b22 100644 --- a/pkg/validators/validators.go +++ b/pkg/validators/validators.go @@ -3,7 +3,6 @@ package validators import ( "context" - "errors" "fmt" "time" @@ -107,7 +106,7 @@ SendPayloads: msg, err := types.ComputeSigningRoot(payload[i].Message, rs.builderSigningDomain) if err != nil { - response.Close(i, errors.New("invalid signature")) + response.Close(i, structs.ErrInvalidSignature) break SendPayloads } @@ -161,13 +160,13 @@ SendPayloads: func verifyOther(beacon *structs.BeaconState, tsReg RegistrationManager, i int, sp types.SignedValidatorRegistration) (svresp verify.Resp, ok bool) { if verifyTimestamp(sp.Message.Timestamp) { - return verify.Resp{Commit: false, ID: i, Err: fmt.Errorf("request too far in future for %s", sp.Message.Pubkey.String())}, false + return verify.Resp{Commit: false, ID: i, Err: fmt.Errorf("%w: too far in future for %s", structs.ErrInvalidTimestamp, sp.Message.Pubkey.String())}, false } pk := structs.PubKey{PublicKey: sp.Message.Pubkey} known, _ := beacon.IsKnownValidator(pk.PubkeyHex()) if !known { - return verify.Resp{Commit: false, ID: i, Err: fmt.Errorf("%s not a known validator", sp.Message.Pubkey.String())}, false + return verify.Resp{Commit: false, ID: i, Err: fmt.Errorf("%w: %s not a known validator", structs.ErrUnknownValidator, sp.Message.Pubkey.String())}, false } previousValidatorTimestamp, ok := tsReg.Get(pk.String()) // Do not error on this From f8564629e4e00238055fef414294a2130eb47c14 Mon Sep 17 00:00:00 2001 From: "Aratz M. Lasa" Date: Mon, 16 Jan 2023 14:56:14 +0100 Subject: [PATCH 2/2] move errors from structs to their own packages --- pkg/api/api.go | 78 ++++++++++++++++++++---------------- pkg/relay/relay.go | 66 +++++++++++++++++++----------- pkg/structs/errors.go | 23 ----------- pkg/structs/structs.go | 5 ++- pkg/validators/validators.go | 13 ++++-- 5 files changed, 100 insertions(+), 85 deletions(-) delete mode 100644 pkg/structs/errors.go diff --git a/pkg/api/api.go b/pkg/api/api.go index b8d155c2..9f44128b 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -15,7 +15,9 @@ import ( "github.com/lthibault/log" "github.com/prometheus/client_golang/prometheus" + "github.com/blocknative/dreamboat/pkg/relay" "github.com/blocknative/dreamboat/pkg/structs" + "github.com/blocknative/dreamboat/pkg/validators" ) // Router paths @@ -251,7 +253,7 @@ func (a *API) submitBlock(w http.ResponseWriter, r *http.Request) (int, error) { m := structs.NewMetricGroup(4) if err := a.r.SubmitBlock(r.Context(), m, &req); err != nil { m.ObserveWithError(a.m.RelayTiming, unwrapError(err, "submit block unknown")) - if errors.Is(err, structs.ErrPayloadAlreadyDelivered) { + if errors.Is(err, relay.ErrPayloadAlreadyDelivered) { a.m.ApiReqCounter.WithLabelValues("submitBlock", "400", "payload already delivered").Inc() } else { a.m.ApiReqCounter.WithLabelValues("submitBlock", "400", "block submission").Inc() @@ -523,40 +525,46 @@ type jsonError struct { } func unwrapError(err error, defaultMsg string) error { - if errors.Is(err, structs.ErrUnknownValue) { - return structs.ErrUnknownValue - } else if errors.Is(err, structs.ErrPayloadAlreadyDelivered) { - return structs.ErrPayloadAlreadyDelivered - } else if errors.Is(err, structs.ErrNoPayloadFound) { - return structs.ErrNoPayloadFound - } else if errors.Is(err, structs.ErrMissingRequest) { - return structs.ErrMissingRequest - } else if errors.Is(err, structs.ErrMissingSecretKey) { - return structs.ErrMissingSecretKey - } else if errors.Is(err, structs.ErrNoBuilderBid) { - return structs.ErrNoBuilderBid - } else if errors.Is(err, structs.ErrOldSlot) { - return structs.ErrOldSlot - } else if errors.Is(err, structs.ErrBadHeader) { - return structs.ErrBadHeader - } else if errors.Is(err, structs.ErrInvalidSignature) { - return structs.ErrInvalidSignature - } else if errors.Is(err, structs.ErrStore) { - return structs.ErrStore - } else if errors.Is(err, structs.ErrMarshal) { - return structs.ErrMarshal - } else if errors.Is(err, structs.ErrInternal) { - return structs.ErrInternal - } else if errors.Is(err, structs.ErrUnknownValidator) { - return structs.ErrUnknownValidator - } else if errors.Is(err, structs.ErrVerification) { - return structs.ErrVerification - } else if errors.Is(err, structs.ErrInvalidTimestamp) { - return structs.ErrInvalidTimestamp - } else if errors.Is(err, structs.ErrInvalidSlot) { - return structs.ErrInvalidSlot - } else if errors.Is(err, structs.ErrEmptyBlock) { - return structs.ErrEmptyBlock + if errors.Is(err, relay.ErrUnknownValue) { + return relay.ErrUnknownValue + } else if errors.Is(err, relay.ErrPayloadAlreadyDelivered) { + return relay.ErrPayloadAlreadyDelivered + } else if errors.Is(err, relay.ErrNoPayloadFound) { + return relay.ErrNoPayloadFound + } else if errors.Is(err, relay.ErrMissingRequest) { + return relay.ErrMissingRequest + } else if errors.Is(err, relay.ErrMissingSecretKey) { + return relay.ErrMissingSecretKey + } else if errors.Is(err, relay.ErrNoBuilderBid) { + return relay.ErrNoBuilderBid + } else if errors.Is(err, relay.ErrOldSlot) { + return relay.ErrOldSlot + } else if errors.Is(err, relay.ErrBadHeader) { + return relay.ErrBadHeader + } else if errors.Is(err, relay.ErrInvalidSignature) { + return relay.ErrInvalidSignature + } else if errors.Is(err, relay.ErrStore) { + return relay.ErrStore + } else if errors.Is(err, relay.ErrMarshal) { + return relay.ErrMarshal + } else if errors.Is(err, relay.ErrInternal) { + return relay.ErrInternal + } else if errors.Is(err, relay.ErrUnknownValidator) { + return relay.ErrUnknownValidator + } else if errors.Is(err, relay.ErrVerification) { + return relay.ErrVerification + } else if errors.Is(err, relay.ErrInvalidTimestamp) { + return relay.ErrInvalidTimestamp + } else if errors.Is(err, relay.ErrInvalidSlot) { + return relay.ErrInvalidSlot + } else if errors.Is(err, relay.ErrEmptyBlock) { + return relay.ErrEmptyBlock + } else if errors.Is(err, validators.ErrInvalidSignature) { + return validators.ErrInvalidSignature + } else if errors.Is(err, validators.ErrUnknownValidator) { + return validators.ErrUnknownValidator + } else if errors.Is(err, validators.ErrInvalidTimestamp) { + return validators.ErrInvalidTimestamp } return errors.New(defaultMsg) diff --git a/pkg/relay/relay.go b/pkg/relay/relay.go index b2b59236..08def66f 100644 --- a/pkg/relay/relay.go +++ b/pkg/relay/relay.go @@ -16,6 +16,26 @@ import ( "github.com/blocknative/dreamboat/pkg/verify" ) +var ( + ErrUnknownValue = errors.New("value is unknown") + ErrPayloadAlreadyDelivered = errors.New("slot payload already delivered") + ErrNoPayloadFound = errors.New("no payload found") + ErrMissingRequest = errors.New("req is nil") + ErrMissingSecretKey = errors.New("secret key is nil") + ErrNoBuilderBid = errors.New("no builder bid") + ErrOldSlot = errors.New("requested slot is old") + ErrBadHeader = errors.New("invalid block header from datastore") + ErrInvalidSignature = errors.New("invalid signature") + ErrStore = errors.New("failed to store") + ErrMarshal = errors.New("failed to marshal") + ErrInternal = errors.New("internal server error") + ErrUnknownValidator = errors.New("unknown validator") + ErrVerification = errors.New("failed to verify") + ErrInvalidTimestamp = errors.New("invalid timestamp") + ErrInvalidSlot = errors.New("invalid slot") + ErrEmptyBlock = errors.New("block is empty") +) + type State interface { Beacon() *structs.BeaconState } @@ -129,10 +149,10 @@ func (rs *Relay) GetHeader(ctx context.Context, m *structs.MetricGroup, request if !ok { if slot < rs.beaconState.Beacon().HeadSlot()-1 { rs.m.MissHeaderCount.WithLabelValues("oldSlot").Add(1) - return nil, structs.ErrOldSlot + return nil, ErrOldSlot } rs.m.MissHeaderCount.WithLabelValues("noSubmission").Add(1) - return nil, structs.ErrNoBuilderBid + return nil, ErrNoBuilderBid } m.AppendSince(tGet, "getHeader", "get") @@ -145,9 +165,9 @@ func (rs *Relay) GetHeader(ctx context.Context, m *structs.MetricGroup, request header := maxProfitBlock.Header if header.Header == nil || (header.Header.ParentHash != parentHash) { - logger.Debug(structs.ErrBadHeader.Error()) + logger.Debug(ErrBadHeader.Error()) rs.m.MissHeaderCount.WithLabelValues("badHeader").Add(1) - return nil, structs.ErrNoBuilderBid + return nil, ErrNoBuilderBid } bid := types.BuilderBid{ @@ -160,7 +180,7 @@ func (rs *Relay) GetHeader(ctx context.Context, m *structs.MetricGroup, request signature, err := types.SignMessage(&bid, rs.config.BuilderSigningDomain, rs.config.SecretKey) m.AppendSince(tSignature, "getHeader", "signature") if err != nil { - return nil, structs.ErrInternal + return nil, ErrInternal } logger.With(log.F{ @@ -183,12 +203,12 @@ func (rs *Relay) GetPayload(ctx context.Context, m *structs.MetricGroup, payload defer m.AppendSince(tStart, "getPayload", "all") if len(payloadRequest.Signature) != 96 { - return nil, structs.ErrInvalidSignature + return nil, ErrInvalidSignature } proposerPubkey, err := rs.beaconState.Beacon().KnownValidatorByIndex(payloadRequest.Message.ProposerIndex) - if err != nil && errors.Is(err, structs.ErrUnknownValue) { - return nil, fmt.Errorf("%w for index %d", structs.ErrUnknownValidator, payloadRequest.Message.ProposerIndex) + if err != nil && errors.Is(err, ErrUnknownValue) { + return nil, fmt.Errorf("%w for index %d", ErrUnknownValidator, payloadRequest.Message.ProposerIndex) } else if err != nil { return nil, err } @@ -209,11 +229,11 @@ func (rs *Relay) GetPayload(ctx context.Context, m *structs.MetricGroup, payload msg, err := types.ComputeSigningRoot(payloadRequest.Message, rs.config.ProposerSigningDomain) if err != nil { - return nil, structs.ErrInvalidSignature // err + return nil, ErrInvalidSignature // err } ok, err := verify.VerifySignatureBytes(msg, payloadRequest.Signature[:], pk[:]) if err != nil || !ok { - return nil, structs.ErrInvalidSignature + return nil, ErrInvalidSignature } m.AppendSince(tVerify, "getPayload", "verify") @@ -226,7 +246,7 @@ func (rs *Relay) GetPayload(ctx context.Context, m *structs.MetricGroup, payload payload, fromCache, err := rs.d.GetPayload(ctx, key) if err != nil || payload == nil { - return nil, structs.ErrNoPayloadFound + return nil, ErrNoPayloadFound } m.AppendSince(tGet, "getPayload", "get") @@ -290,11 +310,11 @@ func (rs *Relay) GetPayload(ctx context.Context, m *structs.MetricGroup, payload // SubmitBlockRequestToSignedBuilderBid converts a builders block submission to a bid compatible with mev-boost func SubmitBlockRequestToSignedBuilderBid(req *types.BuilderSubmitBlockRequest, sk *bls.SecretKey, pubkey *types.PublicKey, domain types.Domain) (*types.SignedBuilderBid, error) { // TODO(l): remove FB type if req == nil { - return nil, structs.ErrMissingRequest + return nil, ErrMissingRequest } if sk == nil { - return nil, structs.ErrMissingSecretKey + return nil, ErrMissingSecretKey } header, err := types.PayloadToPayloadHeader(req.ExecutionPayload) @@ -335,7 +355,7 @@ func (rs *Relay) SubmitBlock(ctx context.Context, m *structs.MetricGroup, submit _, err := rs.verifyBlock(submitBlockRequest, rs.beaconState.Beacon()) if err != nil { - return fmt.Errorf("%w: %s", structs.ErrVerification, err.Error()) // TODO: multiple err wrapping in Go 1.20 + return fmt.Errorf("%w: %s", ErrVerification, err.Error()) // TODO: multiple err wrapping in Go 1.20 } tCheckDelivered := time.Now() @@ -343,7 +363,7 @@ func (rs *Relay) SubmitBlock(ctx context.Context, m *structs.MetricGroup, submit ok, err := rs.d.CheckSlotDelivered(ctx, uint64(slot)) m.AppendSince(tCheckDelivered, "submitBlock", "checkDelivered") if ok { - return structs.ErrPayloadAlreadyDelivered + return ErrPayloadAlreadyDelivered } if err != nil { return err @@ -352,14 +372,14 @@ func (rs *Relay) SubmitBlock(ctx context.Context, m *structs.MetricGroup, submit tVerify := time.Now() msg, err := types.ComputeSigningRoot(submitBlockRequest.Message, rs.config.BuilderSigningDomain) if err != nil { - return structs.ErrInvalidSignature + return ErrInvalidSignature } err = rs.ver.Enqueue(ctx, submitBlockRequest.Signature, submitBlockRequest.Message.BuilderPubkey, msg) m.AppendSince(tVerify, "submitBlock", "verify") if err != nil { - return fmt.Errorf("%w: %s", structs.ErrVerification, err.Error()) // TODO: multiple err wrapping in Go 1.20 + return fmt.Errorf("%w: %s", ErrVerification, err.Error()) // TODO: multiple err wrapping in Go 1.20 } complete, err := rs.prepareContents(submitBlockRequest) @@ -369,12 +389,12 @@ func (rs *Relay) SubmitBlock(ctx context.Context, m *structs.MetricGroup, submit b, err := json.Marshal(complete.Header) if err != nil { - return fmt.Errorf("%w block as header: %s", structs.ErrMarshal, err.Error()) // TODO: multiple err wrapping in Go 1.20 + return fmt.Errorf("%w block as header: %s", ErrMarshal, err.Error()) // TODO: multiple err wrapping in Go 1.20 } tPutPayload := time.Now() if err := rs.d.PutPayload(ctx, SubmissionToKey(submitBlockRequest), &complete.Payload, rs.config.TTL); err != nil { - return fmt.Errorf("%w block as payload: %s", structs.ErrStore, err.Error()) // TODO: multiple err wrapping in Go 1.20 + return fmt.Errorf("%w block as payload: %s", ErrStore, err.Error()) // TODO: multiple err wrapping in Go 1.20 } m.AppendSince(tPutPayload, "submitBlock", "putPayload") @@ -389,7 +409,7 @@ func (rs *Relay) SubmitBlock(ctx context.Context, m *structs.MetricGroup, submit HeaderAndTrace: complete.Header, }, rs.config.TTL) if err != nil { - return fmt.Errorf("%w block as header: %s", structs.ErrStore, err.Error()) // TODO: multiple err wrapping in Go 1.20 + return fmt.Errorf("%w block as header: %s", ErrStore, err.Error()) // TODO: multiple err wrapping in Go 1.20 } m.AppendSince(tPutHeader, "submitBlock", "putHeader") @@ -448,16 +468,16 @@ func (rs *Relay) prepareContents(submitBlockRequest *types.BuilderSubmitBlockReq func (rs *Relay) verifyBlock(submitBlockRequest *types.BuilderSubmitBlockRequest, beaconState *structs.BeaconState) (bool, error) { // TODO(l): remove FB type if submitBlockRequest == nil || submitBlockRequest.Message == nil { - return false, structs.ErrEmptyBlock + return false, ErrEmptyBlock } expectedTimestamp := beaconState.GenesisTime + (submitBlockRequest.Message.Slot * 12) if submitBlockRequest.ExecutionPayload.Timestamp != expectedTimestamp { - return false, fmt.Errorf("%w: got %d, expected %d", structs.ErrInvalidTimestamp, submitBlockRequest.ExecutionPayload.Timestamp, expectedTimestamp) + return false, fmt.Errorf("%w: got %d, expected %d", ErrInvalidTimestamp, submitBlockRequest.ExecutionPayload.Timestamp, expectedTimestamp) } if structs.Slot(submitBlockRequest.Message.Slot) < beaconState.CurrentSlot { - return false, fmt.Errorf("%w: got %d, expected %d", structs.ErrInvalidSlot, submitBlockRequest.Message.Slot, beaconState.CurrentSlot) + return false, fmt.Errorf("%w: got %d, expected %d", ErrInvalidSlot, submitBlockRequest.Message.Slot, beaconState.CurrentSlot) } return true, nil diff --git a/pkg/structs/errors.go b/pkg/structs/errors.go deleted file mode 100644 index ddf660ac..00000000 --- a/pkg/structs/errors.go +++ /dev/null @@ -1,23 +0,0 @@ -package structs - -import "errors" - -var ( - ErrUnknownValue = errors.New("value is unknown") - ErrPayloadAlreadyDelivered = errors.New("slot payload already delivered") - ErrNoPayloadFound = errors.New("no payload found") - ErrMissingRequest = errors.New("req is nil") - ErrMissingSecretKey = errors.New("secret key is nil") - ErrNoBuilderBid = errors.New("no builder bid") - ErrOldSlot = errors.New("requested slot is old") - ErrBadHeader = errors.New("invalid block header from datastore") - ErrInvalidSignature = errors.New("invalid signature") - ErrStore = errors.New("failed to store") - ErrMarshal = errors.New("failed to marshal") - ErrInternal = errors.New("internal server error") - ErrUnknownValidator = errors.New("unknown validator") - ErrVerification = errors.New("failed to verify") - ErrInvalidTimestamp = errors.New("invalid timestamp") - ErrInvalidSlot = errors.New("invalid slot") - ErrEmptyBlock = errors.New("block is empty") -) diff --git a/pkg/structs/structs.go b/pkg/structs/structs.go index 3bb97eab..e7d4927b 100644 --- a/pkg/structs/structs.go +++ b/pkg/structs/structs.go @@ -2,12 +2,15 @@ package structs import ( "encoding/json" + "errors" "fmt" "github.com/flashbots/go-boost-utils/types" ds "github.com/ipfs/go-datastore" ) +var ErrUnknownValue = errors.New("value is unknown") + type Slot uint64 func (s Slot) Loggable() map[string]any { @@ -255,4 +258,4 @@ func SignedBlindedBeaconBlockToBeaconBlock(signedBlindedBeaconBlock *types.Signe }, }, } -} \ No newline at end of file +} diff --git a/pkg/validators/validators.go b/pkg/validators/validators.go index 25135b22..825a34db 100644 --- a/pkg/validators/validators.go +++ b/pkg/validators/validators.go @@ -3,6 +3,7 @@ package validators import ( "context" + "errors" "fmt" "time" @@ -13,6 +14,12 @@ import ( "github.com/lthibault/log" ) +var ( + ErrInvalidSignature = errors.New("invalid signature") + ErrUnknownValidator = errors.New("unknown validator") + ErrInvalidTimestamp = errors.New("invalid timestamp") +) + type State interface { Beacon() *structs.BeaconState } @@ -106,7 +113,7 @@ SendPayloads: msg, err := types.ComputeSigningRoot(payload[i].Message, rs.builderSigningDomain) if err != nil { - response.Close(i, structs.ErrInvalidSignature) + response.Close(i, ErrInvalidSignature) break SendPayloads } @@ -160,13 +167,13 @@ SendPayloads: func verifyOther(beacon *structs.BeaconState, tsReg RegistrationManager, i int, sp types.SignedValidatorRegistration) (svresp verify.Resp, ok bool) { if verifyTimestamp(sp.Message.Timestamp) { - return verify.Resp{Commit: false, ID: i, Err: fmt.Errorf("%w: too far in future for %s", structs.ErrInvalidTimestamp, sp.Message.Pubkey.String())}, false + return verify.Resp{Commit: false, ID: i, Err: fmt.Errorf("%w: too far in future for %s", ErrInvalidTimestamp, sp.Message.Pubkey.String())}, false } pk := structs.PubKey{PublicKey: sp.Message.Pubkey} known, _ := beacon.IsKnownValidator(pk.PubkeyHex()) if !known { - return verify.Resp{Commit: false, ID: i, Err: fmt.Errorf("%w: %s not a known validator", structs.ErrUnknownValidator, sp.Message.Pubkey.String())}, false + return verify.Resp{Commit: false, ID: i, Err: fmt.Errorf("%w: %s not a known validator", ErrUnknownValidator, sp.Message.Pubkey.String())}, false } previousValidatorTimestamp, ok := tsReg.Get(pk.String()) // Do not error on this