Bellatrix publish block - API Middleware fixes (#10348)

* Bellatrix publish block - API Middleware fixes

* update field name

* correct docs
This commit is contained in:
Radosław Kapka
2022-03-14 14:36:46 +01:00
committed by GitHub
parent 1e845bc276
commit 75bb25d515
2 changed files with 86 additions and 7 deletions

View File

@@ -181,9 +181,14 @@ type altairPublishBlockRequestJson struct {
Signature string `json:"signature" hex:"true"`
}
type bellatrixPublishBlockRequestJson struct {
BellatrixBlock *beaconBlockBellatrixJson `json:"bellatrix_block"`
Signature string `json:"signature" hex:"true"`
}
// setInitialPublishBlockPostRequest is triggered before we deserialize the request JSON into a struct.
// We don't know which version of the block got posted, but we can determine it from the slot.
// We know that both Phase 0 and Altair blocks have a Message field with a Slot field,
// We know that blocks of all versions have a Message field with a Slot field,
// so we deserialize the request into a struct s, which has the right fields, to obtain the slot.
// Once we know the slot, we can determine what the PostRequest field of the endpoint should be, and we set it appropriately.
func setInitialPublishBlockPostRequest(endpoint *apimiddleware.Endpoint,
@@ -207,17 +212,20 @@ func setInitialPublishBlockPostRequest(endpoint *apimiddleware.Endpoint,
if err != nil {
return false, apimiddleware.InternalServerErrorWithMessage(err, "slot is not an unsigned integer")
}
if slots.ToEpoch(types.Slot(slot)) < params.BeaconConfig().AltairForkEpoch {
currentEpoch := slots.ToEpoch(types.Slot(slot))
if currentEpoch < params.BeaconConfig().AltairForkEpoch {
endpoint.PostRequest = &signedBeaconBlockContainerJson{}
} else {
} else if currentEpoch < params.BeaconConfig().BellatrixForkEpoch {
endpoint.PostRequest = &signedBeaconBlockAltairContainerJson{}
} else {
endpoint.PostRequest = &signedBeaconBlockBellatrixContainerJson{}
}
req.Body = ioutil.NopCloser(bytes.NewBuffer(buf))
return true, nil
}
// In preparePublishedBlock we transform the PostRequest.
// gRPC expects either a phase0_block or an altair_block field in the JSON object, but we have a message field at this point.
// gRPC expects an XXX_block field in the JSON object, but we have a message field at this point.
// We do a simple conversion depending on the type of endpoint.PostRequest
// (which was filled out previously in setInitialPublishBlockPostRequest).
func preparePublishedBlock(endpoint *apimiddleware.Endpoint, _ http.ResponseWriter, _ *http.Request) apimiddleware.ErrorJson {
@@ -239,6 +247,15 @@ func preparePublishedBlock(endpoint *apimiddleware.Endpoint, _ http.ResponseWrit
endpoint.PostRequest = actualPostReq
return nil
}
if block, ok := endpoint.PostRequest.(*signedBeaconBlockBellatrixContainerJson); ok {
// Prepare post request that can be properly decoded on gRPC side.
actualPostReq := &bellatrixPublishBlockRequestJson{
BellatrixBlock: block.Message,
Signature: block.Signature,
}
endpoint.PostRequest = actualPostReq
return nil
}
return apimiddleware.InternalServerError(errors.New("unsupported block type"))
}

View File

@@ -363,6 +363,11 @@ func TestWrapSignedContributionAndProofsArray(t *testing.T) {
}
func TestSetInitialPublishBlockPostRequest(t *testing.T) {
params.SetupTestConfigCleanup(t)
cfg := params.BeaconConfig()
cfg.BellatrixForkEpoch = params.BeaconConfig().AltairForkEpoch + 1
params.OverrideBeaconConfig(cfg)
endpoint := &apimiddleware.Endpoint{}
s := struct {
Message struct {
@@ -397,6 +402,21 @@ func TestSetInitialPublishBlockPostRequest(t *testing.T) {
assert.Equal(t, apimiddleware.RunDefault(true), runDefault)
assert.Equal(t, reflect.TypeOf(signedBeaconBlockAltairContainerJson{}).Name(), reflect.Indirect(reflect.ValueOf(endpoint.PostRequest)).Type().Name())
})
t.Run("Bellatrix", func(t *testing.T) {
slot, err := slots.EpochStart(params.BeaconConfig().BellatrixForkEpoch)
require.NoError(t, err)
s.Message = struct{ Slot string }{Slot: strconv.FormatUint(uint64(slot), 10)}
j, err := json.Marshal(s)
require.NoError(t, err)
var body bytes.Buffer
_, err = body.Write(j)
require.NoError(t, err)
request := httptest.NewRequest("POST", "http://foo.example", &body)
runDefault, errJson := setInitialPublishBlockPostRequest(endpoint, nil, request)
require.Equal(t, true, errJson == nil)
assert.Equal(t, apimiddleware.RunDefault(true), runDefault)
assert.Equal(t, reflect.TypeOf(signedBeaconBlockBellatrixContainerJson{}).Name(), reflect.Indirect(reflect.ValueOf(endpoint.PostRequest)).Type().Name())
})
}
func TestPreparePublishedBlock(t *testing.T) {
@@ -428,6 +448,20 @@ func TestPreparePublishedBlock(t *testing.T) {
assert.Equal(t, true, ok)
})
t.Run("Bellatrix", func(t *testing.T) {
endpoint := &apimiddleware.Endpoint{
PostRequest: &signedBeaconBlockBellatrixContainerJson{
Message: &beaconBlockBellatrixJson{
Body: &beaconBlockBodyBellatrixJson{},
},
},
}
errJson := preparePublishedBlock(endpoint, nil, nil)
require.Equal(t, true, errJson == nil)
_, ok := endpoint.PostRequest.(*bellatrixPublishBlockRequestJson)
assert.Equal(t, true, ok)
})
t.Run("unsupported block type", func(t *testing.T) {
errJson := preparePublishedBlock(&apimiddleware.Endpoint{}, nil, nil)
assert.Equal(t, true, strings.Contains(errJson.Msg(), "unsupported block type"))
@@ -471,8 +505,7 @@ func TestSerializeV2Block(t *testing.T) {
StateRoot: "root",
Body: &beaconBlockBodyJson{},
},
AltairBlock: nil,
Signature: "sig",
Signature: "sig",
},
}
runDefault, j, errJson := serializeV2Block(response)
@@ -495,7 +528,6 @@ func TestSerializeV2Block(t *testing.T) {
response := &blockV2ResponseJson{
Version: ethpbv2.Version_ALTAIR.String(),
Data: &signedBeaconBlockContainerV2Json{
Phase0Block: nil,
AltairBlock: &beaconBlockAltairJson{
Slot: "1",
ProposerIndex: "1",
@@ -522,6 +554,36 @@ func TestSerializeV2Block(t *testing.T) {
require.NotNil(t, beaconBlock.Body)
})
t.Run("Bellatrix", func(t *testing.T) {
response := &blockV2ResponseJson{
Version: ethpbv2.Version_BELLATRIX.String(),
Data: &signedBeaconBlockContainerV2Json{
BellatrixBlock: &beaconBlockBellatrixJson{
Slot: "1",
ProposerIndex: "1",
ParentRoot: "root",
StateRoot: "root",
Body: &beaconBlockBodyBellatrixJson{},
},
Signature: "sig",
},
}
runDefault, j, errJson := serializeV2Block(response)
require.Equal(t, nil, errJson)
require.Equal(t, apimiddleware.RunDefault(false), runDefault)
require.NotNil(t, j)
resp := &bellatrixBlockResponseJson{}
require.NoError(t, json.Unmarshal(j, resp))
require.NotNil(t, resp.Data)
require.NotNil(t, resp.Data.Message)
beaconBlock := resp.Data.Message
assert.Equal(t, "1", beaconBlock.Slot)
assert.Equal(t, "1", beaconBlock.ProposerIndex)
assert.Equal(t, "root", beaconBlock.ParentRoot)
assert.Equal(t, "root", beaconBlock.StateRoot)
require.NotNil(t, beaconBlock.Body)
})
t.Run("incorrect response type", func(t *testing.T) {
response := &types.Empty{}
runDefault, j, errJson := serializeV2Block(response)