From 716165c1f02b6138e94792a531aadc58bc682899 Mon Sep 17 00:00:00 2001 From: shana Date: Sat, 21 Oct 2023 13:22:09 +1100 Subject: [PATCH] ssz encode request to publish block --- .golangci.yaml | 1 + beaconclient/prod_beacon_instance.go | 32 +++++++++--------- beaconclient/util.go | 50 +++++++++++++++++++++------- common/types.go | 2 +- common/types_spec.go | 50 +++++++++++++++++++++++----- datastore/redis_test.go | 32 +++++++++--------- services/api/utils.go | 2 +- 7 files changed, 115 insertions(+), 54 deletions(-) diff --git a/.golangci.yaml b/.golangci.yaml index 7abd2052..3b8561d8 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -70,6 +70,7 @@ linters-settings: gomoddirectives: replace-allow-list: + - github.com/attestantio/go-builder-client - github.com/attestantio/go-eth2-client maintidx: diff --git a/beaconclient/prod_beacon_instance.go b/beaconclient/prod_beacon_instance.go index 98a2df9a..4215f602 100644 --- a/beaconclient/prod_beacon_instance.go +++ b/beaconclient/prod_beacon_instance.go @@ -151,7 +151,7 @@ type ValidatorResponseValidatorData struct { func (c *ProdBeaconInstance) GetStateValidators(stateID string) (*GetStateValidatorsResponse, error) { uri := fmt.Sprintf("%s/eth/v1/beacon/states/%s/validators?status=active,pending", c.beaconURI, stateID) vd := new(GetStateValidatorsResponse) - _, err := fetchBeacon(http.MethodGet, uri, nil, vd, nil, http.Header{}) + _, err := fetchBeacon(http.MethodGet, uri, nil, vd, nil, http.Header{}, false) return vd, err } @@ -172,7 +172,7 @@ func (c *ProdBeaconInstance) SyncStatus() (*SyncStatusPayloadData, error) { uri := c.beaconURI + "/eth/v1/node/syncing" timeout := 5 * time.Second resp := new(SyncStatusPayload) - _, err := fetchBeacon(http.MethodGet, uri, nil, resp, &timeout, http.Header{}) + _, err := fetchBeacon(http.MethodGet, uri, nil, resp, &timeout, http.Header{}, false) if err != nil { return nil, err } @@ -202,7 +202,7 @@ type ProposerDutiesResponseData struct { func (c *ProdBeaconInstance) GetProposerDuties(epoch uint64) (*ProposerDutiesResponse, error) { uri := fmt.Sprintf("%s/eth/v1/validator/duties/proposer/%d", c.beaconURI, epoch) resp := new(ProposerDutiesResponse) - _, err := fetchBeacon(http.MethodGet, uri, nil, resp, nil, http.Header{}) + _, err := fetchBeacon(http.MethodGet, uri, nil, resp, nil, http.Header{}, false) return resp, err } @@ -225,7 +225,7 @@ type GetHeaderResponseMessage struct { func (c *ProdBeaconInstance) GetHeader() (*GetHeaderResponse, error) { uri := fmt.Sprintf("%s/eth/v1/beacon/headers/head", c.beaconURI) resp := new(GetHeaderResponse) - _, err := fetchBeacon(http.MethodGet, uri, nil, resp, nil, http.Header{}) + _, err := fetchBeacon(http.MethodGet, uri, nil, resp, nil, http.Header{}, false) return resp, err } @@ -233,7 +233,7 @@ func (c *ProdBeaconInstance) GetHeader() (*GetHeaderResponse, error) { func (c *ProdBeaconInstance) GetHeaderForSlot(slot uint64) (*GetHeaderResponse, error) { uri := fmt.Sprintf("%s/eth/v1/beacon/headers/%d", c.beaconURI, slot) resp := new(GetHeaderResponse) - _, err := fetchBeacon(http.MethodGet, uri, nil, resp, nil, http.Header{}) + _, err := fetchBeacon(http.MethodGet, uri, nil, resp, nil, http.Header{}, false) return resp, err } @@ -253,7 +253,7 @@ type GetBlockResponse struct { func (c *ProdBeaconInstance) GetBlock(blockID string) (block *GetBlockResponse, err error) { uri := fmt.Sprintf("%s/eth/v2/beacon/blocks/%s", c.beaconURI, blockID) resp := new(GetBlockResponse) - _, err = fetchBeacon(http.MethodGet, uri, nil, resp, nil, http.Header{}) + _, err = fetchBeacon(http.MethodGet, uri, nil, resp, nil, http.Header{}, false) return resp, err } @@ -261,7 +261,7 @@ func (c *ProdBeaconInstance) GetBlock(blockID string) (block *GetBlockResponse, func (c *ProdBeaconInstance) GetBlockForSlot(slot uint64) (*GetBlockResponse, error) { uri := fmt.Sprintf("%s/eth/v2/beacon/blocks/%d", c.beaconURI, slot) resp := new(GetBlockResponse) - _, err := fetchBeacon(http.MethodGet, uri, nil, resp, nil, http.Header{}) + _, err := fetchBeacon(http.MethodGet, uri, nil, resp, nil, http.Header{}, false) return resp, err } @@ -271,14 +271,16 @@ func (c *ProdBeaconInstance) GetURI() string { func (c *ProdBeaconInstance) PublishBlock(block *common.VersionedSignedBlockRequest, broadcastMode BroadcastMode) (code int, err error) { var uri string + headers := http.Header{} + headers.Add("Eth-Consensus-Version", block.Version.String()) // optional in v1, required in v2 + if c.ffUseV2PublishBlockEndpoint { uri = fmt.Sprintf("%s/eth/v2/beacon/blocks?broadcast_validation=%s", c.beaconURI, broadcastMode.String()) + return fetchBeacon(http.MethodPost, uri, block, nil, nil, headers, true) } else { uri = fmt.Sprintf("%s/eth/v1/beacon/blocks", c.beaconURI) + return fetchBeacon(http.MethodPost, uri, block, nil, nil, headers, false) } - headers := http.Header{} - headers.Add("Eth-Consensus-Version", block.Version.String()) // optional in v1, required in v2 - return fetchBeacon(http.MethodPost, uri, block, nil, nil, headers) } type GetGenesisResponse struct { @@ -295,7 +297,7 @@ type GetGenesisResponseData struct { func (c *ProdBeaconInstance) GetGenesis() (*GetGenesisResponse, error) { uri := fmt.Sprintf("%s/eth/v1/beacon/genesis", c.beaconURI) resp := new(GetGenesisResponse) - _, err := fetchBeacon(http.MethodGet, uri, nil, resp, nil, http.Header{}) + _, err := fetchBeacon(http.MethodGet, uri, nil, resp, nil, http.Header{}, false) return resp, err } @@ -312,7 +314,7 @@ type GetSpecResponse struct { func (c *ProdBeaconInstance) GetSpec() (spec *GetSpecResponse, err error) { uri := fmt.Sprintf("%s/eth/v1/config/spec", c.beaconURI) resp := new(GetSpecResponse) - _, err = fetchBeacon(http.MethodGet, uri, nil, resp, nil, http.Header{}) + _, err = fetchBeacon(http.MethodGet, uri, nil, resp, nil, http.Header{}, false) return resp, err } @@ -328,7 +330,7 @@ type GetForkScheduleResponse struct { func (c *ProdBeaconInstance) GetForkSchedule() (spec *GetForkScheduleResponse, err error) { uri := fmt.Sprintf("%s/eth/v1/config/fork_schedule", c.beaconURI) resp := new(GetForkScheduleResponse) - _, err = fetchBeacon(http.MethodGet, uri, nil, resp, nil, http.Header{}) + _, err = fetchBeacon(http.MethodGet, uri, nil, resp, nil, http.Header{}, false) return resp, err } @@ -342,7 +344,7 @@ type GetRandaoResponse struct { func (c *ProdBeaconInstance) GetRandao(slot uint64) (randaoResp *GetRandaoResponse, err error) { uri := fmt.Sprintf("%s/eth/v1/beacon/states/%d/randao", c.beaconURI, slot) resp := new(GetRandaoResponse) - _, err = fetchBeacon(http.MethodGet, uri, nil, resp, nil, http.Header{}) + _, err = fetchBeacon(http.MethodGet, uri, nil, resp, nil, http.Header{}, false) return resp, err } @@ -356,6 +358,6 @@ type GetWithdrawalsResponse struct { func (c *ProdBeaconInstance) GetWithdrawals(slot uint64) (withdrawalsResp *GetWithdrawalsResponse, err error) { uri := fmt.Sprintf("%s/eth/v1/beacon/states/%d/withdrawals", c.beaconURI, slot) resp := new(GetWithdrawalsResponse) - _, err = fetchBeacon(http.MethodGet, uri, nil, resp, nil, http.Header{}) + _, err = fetchBeacon(http.MethodGet, uri, nil, resp, nil, http.Header{}, false) return resp, err } diff --git a/beaconclient/util.go b/beaconclient/util.go index 7301dd21..c04ac63d 100644 --- a/beaconclient/util.go +++ b/beaconclient/util.go @@ -12,7 +12,8 @@ import ( ) var ( - ErrHTTPErrorResponse = errors.New("got an HTTP error response") + ErrHTTPErrorResponse = errors.New("got an HTTP error response") + ErrInvalidRequestPayload = errors.New("invalid request payload") StateIDHead = "head" StateIDGenesis = "genesis" @@ -30,28 +31,53 @@ func parseBroadcastModeString(s string) (BroadcastMode, bool) { return b, ok } -func fetchBeacon(method, url string, payload, dst any, timeout *time.Duration, headers http.Header) (code int, err error) { +func makeJSONRequest(method, url string, payload any) (*http.Request, error) { + payloadBytes, err := json.Marshal(payload) + if err != nil { + return nil, fmt.Errorf("could not marshal request: %w", err) + } + req, err := http.NewRequest(method, url, bytes.NewReader(payloadBytes)) + if err != nil { + return nil, fmt.Errorf("invalid request for %s: %w", url, err) + } + // Set content-type + req.Header.Add("Content-Type", "application/json") + return req, nil +} + +func makeSSZRequest(method, url string, payload any) (*http.Request, error) { + if payloadBytes, ok := payload.([]byte); ok { + req, err := http.NewRequest(method, url, bytes.NewReader(payloadBytes)) + if err != nil { + return nil, fmt.Errorf("invalid request for %s: %w", url, err) + } + // Set content-type + req.Header.Add("Content-Type", "application/octet-stream") + return req, nil + } + return nil, fmt.Errorf("invalid payload type for SSZ request: %w", ErrInvalidRequestPayload) +} + +func fetchBeacon(method, url string, payload, dst any, timeout *time.Duration, headers http.Header, ssz bool) (code int, err error) { var req *http.Request if payload == nil { req, err = http.NewRequest(method, url, nil) } else { - payloadBytes, err2 := json.Marshal(payload) - if err2 != nil { - return 0, fmt.Errorf("could not marshal request: %w", err2) - } - req, err = http.NewRequest(method, url, bytes.NewReader(payloadBytes)) - - // Set content-type - req.Header.Add("Content-Type", "application/json") - for k, v := range headers { - req.Header.Add(k, v[0]) + if ssz { + req, err = makeSSZRequest(method, url, payload) + } else { + req, err = makeJSONRequest(method, url, payload) } } if err != nil { return 0, fmt.Errorf("invalid request for %s: %w", url, err) } + + for k, v := range headers { + req.Header.Add(k, v[0]) + } req.Header.Set("accept", "application/json") client := http.DefaultClient diff --git a/common/types.go b/common/types.go index a9b62f05..75d4e458 100644 --- a/common/types.go +++ b/common/types.go @@ -131,7 +131,7 @@ func NewEthNetworkDetails(networkName string) (ret *EthNetworkDetails, err error DomainBeaconProposerBellatrix: domainBeaconProposerBellatrix, DomainBeaconProposerCapella: domainBeaconProposerCapella, DomainBeaconProposerDeneb: domainBeaconProposerDeneb, - DomainBlobSidecarDeneb: domainBlobSidecarDeneb , + DomainBlobSidecarDeneb: domainBlobSidecarDeneb, }, nil } diff --git a/common/types_spec.go b/common/types_spec.go index 5418347a..41b5b280 100644 --- a/common/types_spec.go +++ b/common/types_spec.go @@ -9,8 +9,8 @@ import ( builderApiDeneb "github.com/attestantio/go-builder-client/api/deneb" builderSpec "github.com/attestantio/go-builder-client/spec" eth2Api "github.com/attestantio/go-eth2-client/api" - eth2builderApiV1Capella "github.com/attestantio/go-eth2-client/api/v1/capella" - eth2builderApiV1Deneb "github.com/attestantio/go-eth2-client/api/v1/deneb" + eth2ApiV1Capella "github.com/attestantio/go-eth2-client/api/v1/capella" + eth2ApiV1Deneb "github.com/attestantio/go-eth2-client/api/v1/deneb" "github.com/attestantio/go-eth2-client/spec" "github.com/attestantio/go-eth2-client/spec/capella" "github.com/attestantio/go-eth2-client/spec/deneb" @@ -189,7 +189,7 @@ func SignedBlindedBeaconBlockToBeaconBlock(signedBlindedBeaconBlock *VersionedSi if len(denebBlindedBlobs) != len(blockPayload.Deneb.BlobsBundle.Blobs) { return nil, errors.New("number of blinded blobs does not match blobs bundle length") } - + denebBlindedBlock := signedBlindedBeaconBlock.Deneb.SignedBlindedBlock blockRoot, err := denebBlindedBlock.Message.HashTreeRoot() if err != nil { @@ -203,7 +203,7 @@ func SignedBlindedBeaconBlockToBeaconBlock(signedBlindedBeaconBlock *VersionedSi return &signedBeaconBlock, nil } -func CapellaUnblindSignedBlock(blindedBlock *eth2builderApiV1Capella.SignedBlindedBeaconBlock, executionPayload *capella.ExecutionPayload) *capella.SignedBeaconBlock { +func CapellaUnblindSignedBlock(blindedBlock *eth2ApiV1Capella.SignedBlindedBeaconBlock, executionPayload *capella.ExecutionPayload) *capella.SignedBeaconBlock { return &capella.SignedBeaconBlock{ Signature: blindedBlock.Signature, Message: &capella.BeaconBlock{ @@ -228,7 +228,7 @@ func CapellaUnblindSignedBlock(blindedBlock *eth2builderApiV1Capella.SignedBlind } } -func DenebUnblindSignedBlock(blindedBlock *eth2builderApiV1Deneb.SignedBlindedBeaconBlock, blindedBlobs []*eth2builderApiV1Deneb.SignedBlindedBlobSidecar, blockPayload *builderApiDeneb.ExecutionPayloadAndBlobsBundle, blockRoot phase0.Root) *eth2builderApiV1Deneb.SignedBlockContents { +func DenebUnblindSignedBlock(blindedBlock *eth2ApiV1Deneb.SignedBlindedBeaconBlock, blindedBlobs []*eth2ApiV1Deneb.SignedBlindedBlobSidecar, blockPayload *builderApiDeneb.ExecutionPayloadAndBlobsBundle, blockRoot phase0.Root) *eth2ApiV1Deneb.SignedBlockContents { denebBlobSidecars := make([]*deneb.SignedBlobSidecar, len(blockPayload.BlobsBundle.Blobs)) for i := range denebBlobSidecars { @@ -246,7 +246,7 @@ func DenebUnblindSignedBlock(blindedBlock *eth2builderApiV1Deneb.SignedBlindedBe Signature: blindedBlobs[i].Signature, } } - return ð2builderApiV1Deneb.SignedBlockContents{ + return ð2ApiV1Deneb.SignedBlockContents{ SignedBlock: &deneb.SignedBeaconBlock{ Message: &deneb.BeaconBlock{ Slot: blindedBlock.Message.Slot, @@ -372,6 +372,38 @@ type VersionedSignedBlockRequest struct { eth2Api.VersionedBlockRequest } +func (r *VersionedSignedBlockRequest) MarshalSSZ() ([]byte, error) { + switch r.Version { + case spec.DataVersionCapella: + return r.Capella.MarshalSSZ() + case spec.DataVersionDeneb: + return r.Deneb.MarshalSSZ() + case spec.DataVersionUnknown, spec.DataVersionPhase0, spec.DataVersionAltair, spec.DataVersionBellatrix: + fallthrough + default: + return nil, errors.Wrap(ErrInvalidVersion, fmt.Sprintf("%d is not supported", r.Version)) + } +} + +func (r *VersionedSignedBlockRequest) UnmarshalSSZ(input []byte) error { + var err error + + denebRequest := new(eth2ApiV1Deneb.SignedBlockContents) + if err = denebRequest.UnmarshalSSZ(input); err == nil { + r.Version = spec.DataVersionDeneb + r.Deneb = denebRequest + return nil + } + + capellaRequest := new(capella.SignedBeaconBlock) + if err = capellaRequest.UnmarshalSSZ(input); err == nil { + r.Version = spec.DataVersionCapella + r.Capella = capellaRequest + return nil + } + return errors.Wrap(err, "failed to unmarshal SubmitBlockRequest SSZ") +} + func (r *VersionedSignedBlockRequest) MarshalJSON() ([]byte, error) { switch r.Version { case spec.DataVersionCapella: @@ -388,7 +420,7 @@ func (r *VersionedSignedBlockRequest) MarshalJSON() ([]byte, error) { func (r *VersionedSignedBlockRequest) UnmarshalJSON(input []byte) error { var err error - denebContents := new(eth2builderApiV1Deneb.SignedBlockContents) + denebContents := new(eth2ApiV1Deneb.SignedBlockContents) if err = json.Unmarshal(input, denebContents); err == nil { r.Version = spec.DataVersionDeneb r.Deneb = denebContents @@ -424,14 +456,14 @@ func (r *VersionedSignedBlindedBlockRequest) MarshalJSON() ([]byte, error) { func (r *VersionedSignedBlindedBlockRequest) UnmarshalJSON(input []byte) error { var err error - denebContents := new(eth2builderApiV1Deneb.SignedBlindedBlockContents) + denebContents := new(eth2ApiV1Deneb.SignedBlindedBlockContents) if err = json.Unmarshal(input, denebContents); err == nil { r.Version = spec.DataVersionDeneb r.Deneb = denebContents return nil } - capellaBlock := new(eth2builderApiV1Capella.SignedBlindedBeaconBlock) + capellaBlock := new(eth2ApiV1Capella.SignedBlindedBeaconBlock) if err = json.Unmarshal(input, capellaBlock); err == nil { r.Version = spec.DataVersionCapella r.Capella = capellaBlock diff --git a/datastore/redis_test.go b/datastore/redis_test.go index d27e4230..2cc8a78b 100644 --- a/datastore/redis_test.go +++ b/datastore/redis_test.go @@ -129,13 +129,13 @@ func TestBuilderBids(t *testing.T) { ProposerPubkey: proposerPubkey, Version: version, } - + trace := &common.BidTraceV2{ BidTrace: builderApiV1.BidTrace{ Value: uint256.NewInt(123), }, } - + // Notation: // - ba1: builder A, bid 1 // - ba1c: builder A, bid 1, cancellation enabled @@ -144,10 +144,10 @@ func TestBuilderBids(t *testing.T) { // bApubkey := "0xfa1ed37c3553d0ce1e9349b2c5063cf6e394d231c8d3e0df75e9462257c081543086109ffddaacc0aa76f33dc9661c83" bBpubkey := "0x2e02be2c9f9eccf9856478fdb7876598fed2da09f45c233969ba647a250231150ecf38bce5771adb6171c86b79a92f16" - + // Setup redis instance cache := setupTestRedis(t) - + // Helper to ensure writing to redis worked as expected ensureBestBidValueEquals := func(expectedValue int64, builderPubkey string) { bestBid, err := cache.GetBestBid(slot, parentHash, proposerPubkey) @@ -155,28 +155,28 @@ func TestBuilderBids(t *testing.T) { value, err := bestBid.Value() require.NoError(t, err) require.Equal(t, big.NewInt(expectedValue), value.ToBig()) - + topBidValue, err := cache.GetTopBidValue(context.Background(), cache.client.Pipeline(), slot, parentHash, proposerPubkey) require.NoError(t, err) require.Equal(t, big.NewInt(expectedValue), topBidValue) - + if builderPubkey != "" { latestBidValue, err := cache.GetBuilderLatestValue(slot, parentHash, proposerPubkey, builderPubkey) require.NoError(t, err) require.Equal(t, big.NewInt(expectedValue), latestBidValue) } } - + ensureBidFloor := func(expectedValue int64) { floorValue, err := cache.GetFloorBidValue(context.Background(), cache.client.Pipeline(), slot, parentHash, proposerPubkey) require.NoError(t, err) require.Equal(t, big.NewInt(expectedValue), floorValue) } - + // deleting a bid that doesn't exist should not error err := cache.DelBuilderBid(context.Background(), cache.client.Pipeline(), slot, parentHash, proposerPubkey, bApubkey) require.NoError(t, err) - + // submit ba1=10 payload, getPayloadResp, getHeaderResp := common.CreateTestBlockSubmission(t, bApubkey, uint256.NewInt(10), &opts) resp, err := cache.SaveBidAndUpdateTopBid(context.Background(), cache.NewPipeline(), trace, payload, getPayloadResp, getHeaderResp, time.Now(), false, nil) @@ -187,15 +187,15 @@ func TestBuilderBids(t *testing.T) { require.Equal(t, big.NewInt(10), resp.TopBidValue) ensureBestBidValueEquals(10, bApubkey) ensureBidFloor(10) - + // deleting ba1 err = cache.DelBuilderBid(context.Background(), cache.client.Pipeline(), slot, parentHash, proposerPubkey, bApubkey) require.NoError(t, err) - + // best bid and floor should still exist, because it was the floor bid ensureBestBidValueEquals(10, "") ensureBidFloor(10) - + // submit ba2=5 (should not update, because floor is 10) payload, getPayloadResp, getHeaderResp = common.CreateTestBlockSubmission(t, bApubkey, uint256.NewInt(5), &opts) resp, err = cache.SaveBidAndUpdateTopBid(context.Background(), cache.NewPipeline(), trace, payload, getPayloadResp, getHeaderResp, time.Now(), false, nil) @@ -206,7 +206,7 @@ func TestBuilderBids(t *testing.T) { require.Equal(t, big.NewInt(10), resp.TopBidValue) ensureBestBidValueEquals(10, "") ensureBidFloor(10) - + // submit ba3c=5 (should not update, because floor is 10) payload, getPayloadResp, getHeaderResp = common.CreateTestBlockSubmission(t, bApubkey, uint256.NewInt(5), &opts) resp, err = cache.SaveBidAndUpdateTopBid(context.Background(), cache.NewPipeline(), trace, payload, getPayloadResp, getHeaderResp, time.Now(), true, nil) @@ -218,7 +218,7 @@ func TestBuilderBids(t *testing.T) { require.Equal(t, big.NewInt(10), resp.PrevTopBidValue) ensureBestBidValueEquals(10, "") ensureBidFloor(10) - + // submit bb1=20 payload, getPayloadResp, getHeaderResp = common.CreateTestBlockSubmission(t, bBpubkey, uint256.NewInt(20), &opts) resp, err = cache.SaveBidAndUpdateTopBid(context.Background(), cache.NewPipeline(), trace, payload, getPayloadResp, getHeaderResp, time.Now(), false, nil) @@ -229,7 +229,7 @@ func TestBuilderBids(t *testing.T) { require.Equal(t, big.NewInt(20), resp.TopBidValue) ensureBestBidValueEquals(20, bBpubkey) ensureBidFloor(20) - + // submit bb2c=22 payload, getPayloadResp, getHeaderResp = common.CreateTestBlockSubmission(t, bBpubkey, uint256.NewInt(22), &opts) resp, err = cache.SaveBidAndUpdateTopBid(context.Background(), cache.NewPipeline(), trace, payload, getPayloadResp, getHeaderResp, time.Now(), true, nil) @@ -240,7 +240,7 @@ func TestBuilderBids(t *testing.T) { require.Equal(t, big.NewInt(22), resp.TopBidValue) ensureBestBidValueEquals(22, bBpubkey) ensureBidFloor(20) - + // submit bb3c=12 (should update top bid, using floor at 20) payload, getPayloadResp, getHeaderResp = common.CreateTestBlockSubmission(t, bBpubkey, uint256.NewInt(12), &opts) resp, err = cache.SaveBidAndUpdateTopBid(context.Background(), cache.NewPipeline(), trace, payload, getPayloadResp, getHeaderResp, time.Now(), true, nil) diff --git a/services/api/utils.go b/services/api/utils.go index 39402738..658b6d6b 100644 --- a/services/api/utils.go +++ b/services/api/utils.go @@ -180,4 +180,4 @@ func verifyBlobSidecarSignature(sidecar *eth2builderApiV1Deneb.SignedBlindedBlob } return bls.VerifySignatureBytes(msg[:], sidecar.Signature[:], pubKey[:]) -} \ No newline at end of file +}