Skip to content

Commit 4e78ec8

Browse files
Create ssz type: SubmitBlockRequestV2Optimistic (#518)
* create ssz type: SubmitBlockRequestV2Optimistic * unmarshall -> unmarshal * lint fixes * go mod tidy
1 parent 36ed373 commit 4e78ec8

File tree

3 files changed

+389
-3
lines changed

3 files changed

+389
-3
lines changed

common/types.go

Lines changed: 270 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)