mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 15:37:56 -05:00
fix getStateRandao not returning historic RANDAO mix values (#15653)
* fix getStateRandao not returning historic RANDAO mix values * update: the lower bound statement * Update changelog/muzry_fix_state_randao.md * Update changelog/muzry_fix_state_randao.md --------- Co-authored-by: Radosław Kapka <radoslaw.kapka@gmail.com>
This commit is contained in:
@@ -109,10 +109,10 @@ func (s *Server) GetRandao(w http.ResponseWriter, r *http.Request) {
|
||||
// future epochs and epochs too far back are not supported.
|
||||
randaoEpochLowerBound := uint64(0)
|
||||
// Lower bound should not underflow.
|
||||
if uint64(stEpoch) > uint64(st.RandaoMixesLength()) {
|
||||
randaoEpochLowerBound = uint64(stEpoch) - uint64(st.RandaoMixesLength())
|
||||
if uint64(stEpoch) >= uint64(st.RandaoMixesLength()) {
|
||||
randaoEpochLowerBound = uint64(stEpoch) - uint64(st.RandaoMixesLength()) + 1
|
||||
}
|
||||
if epoch > stEpoch || uint64(epoch) < randaoEpochLowerBound+1 {
|
||||
if epoch > stEpoch || (uint64(epoch) < randaoEpochLowerBound) {
|
||||
httputil.HandleError(w, "Epoch is out of range for the randao mixes of the state", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -192,8 +192,14 @@ func TestGetRandao(t *testing.T) {
|
||||
assert.Equal(t, hexutil.Encode(mixOld[:]), resp.Data.Randao)
|
||||
})
|
||||
t.Run("head state below `EpochsPerHistoricalVector`", func(t *testing.T) {
|
||||
s.Stater = &testutil.MockStater{
|
||||
BeaconState: headSt,
|
||||
s := &Server{
|
||||
Stater: &testutil.MockStater{
|
||||
BeaconState: headSt,
|
||||
},
|
||||
HeadFetcher: chainService,
|
||||
OptimisticModeFetcher: chainService,
|
||||
FinalizationFetcher: chainService,
|
||||
BeaconDB: db,
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(http.MethodGet, "http://example.com//eth/v1/beacon/states/{state_id}/randao", nil)
|
||||
@@ -303,6 +309,74 @@ func TestGetRandao(t *testing.T) {
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
assert.DeepEqual(t, true, resp.Finalized)
|
||||
})
|
||||
t.Run("early epoch scenario - epoch 0 from state at epoch (EpochsPerHistoricalVector - 1)", func(t *testing.T) {
|
||||
// Create a state at early epoch
|
||||
earlyEpochState, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
earlyEpoch := params.BeaconConfig().EpochsPerHistoricalVector - 1
|
||||
require.NoError(t, earlyEpochState.SetSlot(params.BeaconConfig().SlotsPerEpoch*primitives.Slot(earlyEpoch)))
|
||||
|
||||
// Set up RANDAO mix for epoch 0
|
||||
// In real networks, this would be the ETH1 block hash used for genesis
|
||||
epoch0Randao := bytesutil.ToBytes32([]byte("epoch0"))
|
||||
require.NoError(t, earlyEpochState.UpdateRandaoMixesAtIndex(0, epoch0Randao))
|
||||
|
||||
earlyServer := &Server{
|
||||
Stater: &testutil.MockStater{
|
||||
BeaconState: earlyEpochState,
|
||||
},
|
||||
HeadFetcher: &chainMock.ChainService{},
|
||||
OptimisticModeFetcher: &chainMock.ChainService{},
|
||||
FinalizationFetcher: &chainMock.ChainService{},
|
||||
}
|
||||
|
||||
// Query epoch 0 from state at epoch (EpochsPerHistoricalVector - 1) - should succeed
|
||||
request := httptest.NewRequest(http.MethodGet, "http://example.com//eth/v1/beacon/states/{state_id}/randao?epoch=0", nil)
|
||||
request.SetPathValue("state_id", "head")
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
|
||||
earlyServer.GetRandao(writer, request)
|
||||
require.Equal(t, http.StatusOK, writer.Code, "Early epoch queries should succeed when within bounds")
|
||||
|
||||
resp := &structs.GetRandaoResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
assert.Equal(t, hexutil.Encode(epoch0Randao[:]), resp.Data.Randao)
|
||||
})
|
||||
t.Run("early epoch scenario - epoch 0 from state at epoch EpochsPerHistoricalVector", func(t *testing.T) {
|
||||
// Create a state at early epoch
|
||||
earlyEpochState, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
earlyEpoch := params.BeaconConfig().EpochsPerHistoricalVector
|
||||
require.NoError(t, earlyEpochState.SetSlot(params.BeaconConfig().SlotsPerEpoch*primitives.Slot(earlyEpoch)))
|
||||
|
||||
// Set up RANDAO mix for epoch 0
|
||||
// In real networks, this would be the ETH1 block hash used for genesis
|
||||
epoch0Randao := bytesutil.ToBytes32([]byte("epoch0"))
|
||||
require.NoError(t, earlyEpochState.UpdateRandaoMixesAtIndex(0, epoch0Randao))
|
||||
|
||||
earlyServer := &Server{
|
||||
Stater: &testutil.MockStater{
|
||||
BeaconState: earlyEpochState,
|
||||
},
|
||||
HeadFetcher: &chainMock.ChainService{},
|
||||
OptimisticModeFetcher: &chainMock.ChainService{},
|
||||
FinalizationFetcher: &chainMock.ChainService{},
|
||||
}
|
||||
|
||||
// Query epoch 0 from state at epoch EpochsPerHistoricalVector - should fail
|
||||
request := httptest.NewRequest(http.MethodGet, "http://example.com//eth/v1/beacon/states/{state_id}/randao?epoch=0", nil)
|
||||
request.SetPathValue("state_id", "head")
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
|
||||
earlyServer.GetRandao(writer, request)
|
||||
require.Equal(t, http.StatusBadRequest, writer.Code)
|
||||
e := &httputil.DefaultJsonError{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e))
|
||||
assert.Equal(t, http.StatusBadRequest, e.Code)
|
||||
require.StringContains(t, "Epoch is out of range for the randao mixes of the state", e.Message)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_currentCommitteeIndicesFromState(t *testing.T) {
|
||||
|
||||
3
changelog/muzry_fix_state_randao.md
Normal file
3
changelog/muzry_fix_state_randao.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Fixed
|
||||
|
||||
- Fix getStateRandao not returning historic RANDAO mix values
|
||||
Reference in New Issue
Block a user