@@ -13,9 +13,10 @@ import (
1313 "github.com/attestantio/go-builder-client/spec"
1414 apiv1capella "github.com/attestantio/go-eth2-client/api/v1/capella"
1515 consensusspec "github.com/attestantio/go-eth2-client/spec"
16- "github.com/attestantio/go-eth2-client/spec/bellatrix"
16+ consensusbellatrix "github.com/attestantio/go-eth2-client/spec/bellatrix"
1717 consensuscapella "github.com/attestantio/go-eth2-client/spec/capella"
1818 "github.com/attestantio/go-eth2-client/spec/phase0"
19+ ssz "github.com/ferranbt/fastssz"
1920 boostTypes "github.com/flashbots/go-boost-utils/types"
2021)
2122
@@ -692,7 +693,7 @@ func BoostBidToBidTrace(bidTrace *boostTypes.BidTrace) *apiv1.BidTrace {
692693 BuilderPubkey : phase0 .BLSPubKey (bidTrace .BuilderPubkey ),
693694 Slot : bidTrace .Slot ,
694695 ProposerPubkey : phase0 .BLSPubKey (bidTrace .ProposerPubkey ),
695- ProposerFeeRecipient : bellatrix .ExecutionAddress (bidTrace .ProposerFeeRecipient ),
696+ ProposerFeeRecipient : consensusbellatrix .ExecutionAddress (bidTrace .ProposerFeeRecipient ),
696697 BlockHash : phase0 .Hash32 (bidTrace .BlockHash ),
697698 Value : U256StrToUint256 (bidTrace .Value ),
698699 ParentHash : phase0 .Hash32 (bidTrace .ParentHash ),
@@ -802,3 +803,270 @@ func (b *BuilderSubmitBlockRequest) Withdrawals() []*consensuscapella.Withdrawal
802803 }
803804 return nil
804805}
806+
807+ /*
808+ SubmitBlockRequestV2Optimistic is the v2 request from the builder to submit
809+ a block. The message must be SSZ encoded. The first three fields are at most
810+ 944 bytes, which fit into a single 1500 MTU ethernet packet. The
811+ `UnmarshalSSZHeaderOnly` function just parses the first three fields,
812+ which is sufficient data to set the bid of the builder. The `Transactions`
813+ and `Withdrawals` fields are required to construct the full SignedBeaconBlock
814+ and are parsed asynchronously.
815+
816+ Header only layout:
817+ [000-236) = Message (236 bytes)
818+ [236-240) = offset1 ( 4 bytes)
819+ [240-336) = Signature ( 96 bytes)
820+ [336-340) = offset2 ( 4 bytes)
821+ [340-344) = offset3 ( 4 bytes)
822+ [344-944) = EPH (600 bytes)
823+ */
824+ type SubmitBlockRequestV2Optimistic struct {
825+ Message * apiv1.BidTrace
826+ ExecutionPayloadHeader * consensuscapella.ExecutionPayloadHeader
827+ Signature phase0.BLSSignature `ssz-size:"96"`
828+ Transactions []consensusbellatrix.Transaction `ssz-max:"1048576,1073741824" ssz-size:"?,?"`
829+ Withdrawals []* consensuscapella.Withdrawal `ssz-max:"16"`
830+ }
831+
832+ // MarshalSSZ ssz marshals the SubmitBlockRequestV2Optimistic object
833+ func (s * SubmitBlockRequestV2Optimistic ) MarshalSSZ () ([]byte , error ) {
834+ return ssz .MarshalSSZ (s )
835+ }
836+
837+ // UnmarshalSSZ ssz unmarshals the SubmitBlockRequestV2Optimistic object
838+ func (s * SubmitBlockRequestV2Optimistic ) UnmarshalSSZ (buf []byte ) error {
839+ var err error
840+ size := uint64 (len (buf ))
841+ if size < 344 {
842+ return ssz .ErrSize
843+ }
844+
845+ tail := buf
846+ var o1 , o3 , o4 uint64
847+
848+ // Field (0) 'Message'
849+ if s .Message == nil {
850+ s .Message = new (apiv1.BidTrace )
851+ }
852+ if err = s .Message .UnmarshalSSZ (buf [0 :236 ]); err != nil {
853+ return err
854+ }
855+
856+ // Offset (1) 'ExecutionPayloadHeader'
857+ if o1 = ssz .ReadOffset (buf [236 :240 ]); o1 > size {
858+ return ssz .ErrOffset
859+ }
860+
861+ if o1 < 344 {
862+ return ssz .ErrInvalidVariableOffset
863+ }
864+
865+ // Field (2) 'Signature'
866+ copy (s .Signature [:], buf [240 :336 ])
867+
868+ // Offset (3) 'Transactions'
869+ if o3 = ssz .ReadOffset (buf [336 :340 ]); o3 > size || o1 > o3 {
870+ return ssz .ErrOffset
871+ }
872+
873+ // Offset (4) 'Withdrawals'
874+ if o4 = ssz .ReadOffset (buf [340 :344 ]); o4 > size || o3 > o4 {
875+ return ssz .ErrOffset
876+ }
877+
878+ // Field (1) 'ExecutionPayloadHeader'
879+ {
880+ buf = tail [o1 :o3 ]
881+ if s .ExecutionPayloadHeader == nil {
882+ s .ExecutionPayloadHeader = new (consensuscapella.ExecutionPayloadHeader )
883+ }
884+ if err = s .ExecutionPayloadHeader .UnmarshalSSZ (buf ); err != nil {
885+ return err
886+ }
887+ }
888+
889+ // Field (3) 'Transactions'
890+ {
891+ buf = tail [o3 :o4 ]
892+ num , err := ssz .DecodeDynamicLength (buf , 1073741824 )
893+ if err != nil {
894+ return err
895+ }
896+ s .Transactions = make ([]consensusbellatrix.Transaction , num )
897+ err = ssz .UnmarshalDynamic (buf , num , func (indx int , buf []byte ) (err error ) {
898+ if len (buf ) > 1073741824 {
899+ return ssz .ErrBytesLength
900+ }
901+ if cap (s .Transactions [indx ]) == 0 {
902+ s .Transactions [indx ] = consensusbellatrix .Transaction (make ([]byte , 0 , len (buf )))
903+ }
904+ s .Transactions [indx ] = append (s .Transactions [indx ], buf ... )
905+ return nil
906+ })
907+ if err != nil {
908+ return err
909+ }
910+ }
911+
912+ // Field (4) 'Withdrawals'
913+ {
914+ buf = tail [o4 :]
915+ num , err := ssz .DivideInt2 (len (buf ), 44 , 16 )
916+ if err != nil {
917+ return err
918+ }
919+ s .Withdrawals = make ([]* consensuscapella.Withdrawal , num )
920+ for ii := 0 ; ii < num ; ii ++ {
921+ if s .Withdrawals [ii ] == nil {
922+ s .Withdrawals [ii ] = new (consensuscapella.Withdrawal )
923+ }
924+ if err = s .Withdrawals [ii ].UnmarshalSSZ (buf [ii * 44 : (ii + 1 )* 44 ]); err != nil {
925+ return err
926+ }
927+ }
928+ }
929+ return err
930+ }
931+
932+ // UnmarshalSSZHeaderOnly ssz unmarshals the first 3 fields of the SubmitBlockRequestV2Optimistic object
933+ func (s * SubmitBlockRequestV2Optimistic ) UnmarshalSSZHeaderOnly (buf []byte ) error {
934+ var err error
935+ size := uint64 (len (buf ))
936+ if size < 344 {
937+ return ssz .ErrSize
938+ }
939+
940+ tail := buf
941+ var o1 , o3 uint64
942+
943+ // Field (0) 'Message'
944+ if s .Message == nil {
945+ s .Message = new (apiv1.BidTrace )
946+ }
947+ if err = s .Message .UnmarshalSSZ (buf [0 :236 ]); err != nil {
948+ return err
949+ }
950+
951+ // Offset (1) 'ExecutionPayloadHeader'
952+ if o1 = ssz .ReadOffset (buf [236 :240 ]); o1 > size {
953+ return ssz .ErrOffset
954+ }
955+
956+ if o1 < 344 {
957+ return ssz .ErrInvalidVariableOffset
958+ }
959+
960+ // Field (2) 'Signature'
961+ copy (s .Signature [:], buf [240 :336 ])
962+
963+ // Offset (3) 'Transactions'
964+ if o3 = ssz .ReadOffset (buf [336 :340 ]); o3 > size || o1 > o3 {
965+ return ssz .ErrOffset
966+ }
967+
968+ // Field (1) 'ExecutionPayloadHeader'
969+ {
970+ buf = tail [o1 :o3 ]
971+ if s .ExecutionPayloadHeader == nil {
972+ s .ExecutionPayloadHeader = new (consensuscapella.ExecutionPayloadHeader )
973+ }
974+ if err = s .ExecutionPayloadHeader .UnmarshalSSZ (buf ); err != nil {
975+ return err
976+ }
977+ }
978+ return err
979+ }
980+
981+ // MarshalSSZTo ssz marshals the SubmitBlockRequestV2Optimistic object to a target array
982+ func (s * SubmitBlockRequestV2Optimistic ) MarshalSSZTo (buf []byte ) (dst []byte , err error ) {
983+ dst = buf
984+ offset := int (344 )
985+
986+ // Field (0) 'Message'
987+ if s .Message == nil {
988+ s .Message = new (apiv1.BidTrace )
989+ }
990+ if dst , err = s .Message .MarshalSSZTo (dst ); err != nil {
991+ return
992+ }
993+
994+ // Offset (1) 'ExecutionPayloadHeader'
995+ dst = ssz .WriteOffset (dst , offset )
996+ if s .ExecutionPayloadHeader == nil {
997+ s .ExecutionPayloadHeader = new (consensuscapella.ExecutionPayloadHeader )
998+ }
999+ offset += s .ExecutionPayloadHeader .SizeSSZ ()
1000+
1001+ // Field (2) 'Signature'
1002+ dst = append (dst , s .Signature [:]... )
1003+
1004+ // Offset (3) 'Transactions'
1005+ dst = ssz .WriteOffset (dst , offset )
1006+ for ii := 0 ; ii < len (s .Transactions ); ii ++ {
1007+ offset += 4
1008+ offset += len (s .Transactions [ii ])
1009+ }
1010+
1011+ // Offset (4) 'Withdrawals'
1012+ dst = ssz .WriteOffset (dst , offset )
1013+
1014+ // Field (1) 'ExecutionPayloadHeader'
1015+ if dst , err = s .ExecutionPayloadHeader .MarshalSSZTo (dst ); err != nil {
1016+ return
1017+ }
1018+
1019+ // Field (3) 'Transactions'
1020+ if size := len (s .Transactions ); size > 1073741824 {
1021+ err = ssz .ErrListTooBigFn ("SubmitBlockRequestV2Optimistic.Transactions" , size , 1073741824 )
1022+ return
1023+ }
1024+ {
1025+ offset = 4 * len (s .Transactions )
1026+ for ii := 0 ; ii < len (s .Transactions ); ii ++ {
1027+ dst = ssz .WriteOffset (dst , offset )
1028+ offset += len (s .Transactions [ii ])
1029+ }
1030+ }
1031+ for ii := 0 ; ii < len (s .Transactions ); ii ++ {
1032+ if size := len (s .Transactions [ii ]); size > 1073741824 {
1033+ err = ssz .ErrBytesLengthFn ("SubmitBlockRequestV2Optimistic.Transactions[ii]" , size , 1073741824 )
1034+ return
1035+ }
1036+ dst = append (dst , s .Transactions [ii ]... )
1037+ }
1038+
1039+ // Field (4) 'Withdrawals'
1040+ if size := len (s .Withdrawals ); size > 16 {
1041+ err = ssz .ErrListTooBigFn ("SubmitBlockRequestV2Optimistic.Withdrawals" , size , 16 )
1042+ return
1043+ }
1044+ for ii := 0 ; ii < len (s .Withdrawals ); ii ++ {
1045+ if dst , err = s .Withdrawals [ii ].MarshalSSZTo (dst ); err != nil {
1046+ return
1047+ }
1048+ }
1049+ return dst , nil
1050+ }
1051+
1052+ // SizeSSZ returns the ssz encoded size in bytes for the SubmitBlockRequestV2Optimistic object
1053+ func (s * SubmitBlockRequestV2Optimistic ) SizeSSZ () (size int ) {
1054+ size = 344
1055+
1056+ // Field (1) 'ExecutionPayloadHeader'
1057+ if s .ExecutionPayloadHeader == nil {
1058+ s .ExecutionPayloadHeader = new (consensuscapella.ExecutionPayloadHeader )
1059+ }
1060+ size += s .ExecutionPayloadHeader .SizeSSZ ()
1061+
1062+ // Field (3) 'Transactions'
1063+ for ii := 0 ; ii < len (s .Transactions ); ii ++ {
1064+ size += 4
1065+ size += len (s .Transactions [ii ])
1066+ }
1067+
1068+ // Field (4) 'Withdrawals'
1069+ size += len (s .Withdrawals ) * 44
1070+
1071+ return
1072+ }
0 commit comments