@@ -7,15 +7,18 @@ import (
77 "os"
88 "strconv"
99 "strings"
10+ "time"
1011
1112 builderApiV1 "github.com/attestantio/go-builder-client/api/v1"
1213 "github.com/attestantio/go-eth2-client/spec/bellatrix"
1314 "github.com/attestantio/go-eth2-client/spec/capella"
1415 "github.com/attestantio/go-eth2-client/spec/deneb"
1516 "github.com/attestantio/go-eth2-client/spec/electra"
1617 "github.com/attestantio/go-eth2-client/spec/phase0"
18+ "github.com/buger/jsonparser"
1719 ssz "github.com/ferranbt/fastssz"
1820 boostSsz "github.com/flashbots/go-boost-utils/ssz"
21+ "github.com/flashbots/go-boost-utils/utils"
1922)
2023
2124var (
@@ -218,6 +221,8 @@ func (e *EthNetworkDetails) String() string {
218221 e .DomainBeaconProposerElectra )
219222}
220223
224+ // PubkeyHex represents a hex-encoded public key.
225+ // It is lowercased on creation and is not validated/parsed.
221226type PubkeyHex string
222227
223228func NewPubkeyHex (pk string ) PubkeyHex {
@@ -228,6 +233,10 @@ func (p PubkeyHex) String() string {
228233 return string (p )
229234}
230235
236+ func (p PubkeyHex ) ToPubkey () (ret phase0.BLSPubKey , err error ) {
237+ return utils .HexToPubkey (string (p ))
238+ }
239+
231240type BuilderGetValidatorsResponseEntry struct {
232241 Slot uint64 `json:"slot,string"`
233242 ValidatorIndex uint64 `json:"validator_index,string"`
@@ -728,3 +737,68 @@ func (s *SubmitBlockRequestV2Optimistic) SizeSSZ() (size int) {
728737
729738 return
730739}
740+
741+ // SimpleValidatorRegistration is a helper type for fast JSON decoding
742+ type SimpleValidatorRegistration struct {
743+ FeeRecipient bellatrix.ExecutionAddress
744+ GasLimit uint64
745+ Timestamp time.Time
746+
747+ // These two are intentionally left unparsed due to heavy parsing maths
748+ Pubkey PubkeyHex
749+ Signature string
750+ }
751+
752+ func (r * SimpleValidatorRegistration ) UnmarshalJSON (value []byte ) error {
753+ _feeRecipient , err := jsonparser .GetUnsafeString (value , "message" , "fee_recipient" )
754+ if err != nil {
755+ return fmt .Errorf ("registration message error (fee_recipient): %w" , err )
756+ }
757+
758+ // this one is fast, it's hex decode, no fancy crypto maths
759+ feeRecipient , err := utils .HexToAddress (_feeRecipient )
760+ if err != nil {
761+ return fmt .Errorf ("registration message error (fee_recipient): %w" , err )
762+ }
763+
764+ _gasLimit , err := jsonparser .GetUnsafeString (value , "message" , "gas_limit" )
765+ if err != nil {
766+ return fmt .Errorf ("registration message error (gasLimit): %w" , err )
767+ }
768+
769+ gasLimit , err := strconv .ParseUint (_gasLimit , 10 , 64 )
770+ if err != nil {
771+ return fmt .Errorf ("invalid gasLimit: %w" , err )
772+ }
773+
774+ _timestamp , err := jsonparser .GetUnsafeString (value , "message" , "timestamp" )
775+ if err != nil {
776+ return fmt .Errorf ("registration message error (timestamp): %w" , err )
777+ }
778+
779+ timestamp , err := strconv .ParseInt (_timestamp , 10 , 64 )
780+ if err != nil {
781+ return fmt .Errorf ("invalid timestamp: %w" , err )
782+ }
783+ if timestamp < 0 {
784+ return ErrTimestampNegative
785+ }
786+
787+ pubkey , err := jsonparser .GetUnsafeString (value , "message" , "pubkey" )
788+ if err != nil {
789+ return fmt .Errorf ("registration message error (pubkey): %w" , err )
790+ }
791+
792+ signature , err := jsonparser .GetUnsafeString (value , "signature" )
793+ if err != nil {
794+ return fmt .Errorf ("registration message error (signature): %w" , err )
795+ }
796+
797+ r .FeeRecipient = feeRecipient
798+ r .GasLimit = gasLimit
799+ r .Timestamp = time .Unix (timestamp , 0 )
800+ r .Pubkey = NewPubkeyHex (pubkey )
801+ r .Signature = signature
802+
803+ return nil
804+ }
0 commit comments