diff --git a/beacon-chain/rpc/apimiddleware/custom_handlers_test.go b/beacon-chain/rpc/apimiddleware/custom_handlers_test.go index 141cb438b8e8..f01aabb5c1c6 100644 --- a/beacon-chain/rpc/apimiddleware/custom_handlers_test.go +++ b/beacon-chain/rpc/apimiddleware/custom_handlers_test.go @@ -22,6 +22,7 @@ import ( type testSSZResponseJson struct { Version string `json:"version"` ExecutionOptimistic bool `json:"execution_optimistic"` + Finalized bool `json:"finalized"` Data string `json:"data"` } @@ -37,6 +38,10 @@ func (t testSSZResponseJson) SSZData() string { return t.Data } +func (t testSSZResponseJson) SSZFinalized() bool { + return t.Finalized +} + func TestSSZRequested(t *testing.T) { t.Run("ssz_requested", func(t *testing.T) { request := httptest.NewRequest("GET", "http://foo.example", nil) diff --git a/beacon-chain/rpc/apimiddleware/custom_hooks.go b/beacon-chain/rpc/apimiddleware/custom_hooks.go index c1da4417a4d3..10255105ed2a 100644 --- a/beacon-chain/rpc/apimiddleware/custom_hooks.go +++ b/beacon-chain/rpc/apimiddleware/custom_hooks.go @@ -454,36 +454,42 @@ type phase0BlockResponseJson struct { Version string `json:"version" enum:"true"` Data *SignedBeaconBlockContainerJson `json:"data"` ExecutionOptimistic bool `json:"execution_optimistic"` + Finalized bool `json:"finalized"` } type altairBlockResponseJson struct { Version string `json:"version" enum:"true"` Data *SignedBeaconBlockAltairContainerJson `json:"data"` ExecutionOptimistic bool `json:"execution_optimistic"` + Finalized bool `json:"finalized"` } type bellatrixBlockResponseJson struct { Version string `json:"version" enum:"true"` Data *SignedBeaconBlockBellatrixContainerJson `json:"data"` ExecutionOptimistic bool `json:"execution_optimistic"` + Finalized bool `json:"finalized"` } type capellaBlockResponseJson struct { Version string `json:"version"` Data *SignedBeaconBlockCapellaContainerJson `json:"data"` ExecutionOptimistic bool `json:"execution_optimistic"` + Finalized bool `json:"finalized"` } type bellatrixBlindedBlockResponseJson struct { Version string `json:"version" enum:"true"` Data *SignedBlindedBeaconBlockBellatrixContainerJson `json:"data"` ExecutionOptimistic bool `json:"execution_optimistic"` + Finalized bool `json:"finalized"` } type capellaBlindedBlockResponseJson struct { Version string `json:"version" enum:"true"` Data *SignedBlindedBeaconBlockCapellaContainerJson `json:"data"` ExecutionOptimistic bool `json:"execution_optimistic"` + Finalized bool `json:"finalized"` } func serializeV2Block(response interface{}) (apimiddleware.RunDefault, []byte, apimiddleware.ErrorJson) { @@ -502,6 +508,7 @@ func serializeV2Block(response interface{}) (apimiddleware.RunDefault, []byte, a Signature: respContainer.Data.Signature, }, ExecutionOptimistic: respContainer.ExecutionOptimistic, + Finalized: respContainer.Finalized, } case strings.EqualFold(respContainer.Version, strings.ToLower(ethpbv2.Version_ALTAIR.String())): actualRespContainer = &altairBlockResponseJson{ @@ -511,6 +518,7 @@ func serializeV2Block(response interface{}) (apimiddleware.RunDefault, []byte, a Signature: respContainer.Data.Signature, }, ExecutionOptimistic: respContainer.ExecutionOptimistic, + Finalized: respContainer.Finalized, } case strings.EqualFold(respContainer.Version, strings.ToLower(ethpbv2.Version_BELLATRIX.String())): actualRespContainer = &bellatrixBlockResponseJson{ @@ -520,6 +528,7 @@ func serializeV2Block(response interface{}) (apimiddleware.RunDefault, []byte, a Signature: respContainer.Data.Signature, }, ExecutionOptimistic: respContainer.ExecutionOptimistic, + Finalized: respContainer.Finalized, } case strings.EqualFold(respContainer.Version, strings.ToLower(ethpbv2.Version_CAPELLA.String())): actualRespContainer = &capellaBlockResponseJson{ @@ -529,6 +538,7 @@ func serializeV2Block(response interface{}) (apimiddleware.RunDefault, []byte, a Signature: respContainer.Data.Signature, }, ExecutionOptimistic: respContainer.ExecutionOptimistic, + Finalized: respContainer.Finalized, } default: return false, nil, apimiddleware.InternalServerError(fmt.Errorf("unsupported block version '%s'", respContainer.Version)) @@ -557,6 +567,7 @@ func serializeBlindedBlock(response interface{}) (apimiddleware.RunDefault, []by Signature: respContainer.Data.Signature, }, ExecutionOptimistic: respContainer.ExecutionOptimistic, + Finalized: respContainer.Finalized, } case strings.EqualFold(respContainer.Version, strings.ToLower(ethpbv2.Version_ALTAIR.String())): actualRespContainer = &altairBlockResponseJson{ @@ -566,6 +577,7 @@ func serializeBlindedBlock(response interface{}) (apimiddleware.RunDefault, []by Signature: respContainer.Data.Signature, }, ExecutionOptimistic: respContainer.ExecutionOptimistic, + Finalized: respContainer.Finalized, } case strings.EqualFold(respContainer.Version, strings.ToLower(ethpbv2.Version_BELLATRIX.String())): actualRespContainer = &bellatrixBlindedBlockResponseJson{ @@ -575,6 +587,7 @@ func serializeBlindedBlock(response interface{}) (apimiddleware.RunDefault, []by Signature: respContainer.Data.Signature, }, ExecutionOptimistic: respContainer.ExecutionOptimistic, + Finalized: respContainer.Finalized, } case strings.EqualFold(respContainer.Version, strings.ToLower(ethpbv2.Version_CAPELLA.String())): actualRespContainer = &capellaBlindedBlockResponseJson{ @@ -584,6 +597,7 @@ func serializeBlindedBlock(response interface{}) (apimiddleware.RunDefault, []by Signature: respContainer.Data.Signature, }, ExecutionOptimistic: respContainer.ExecutionOptimistic, + Finalized: respContainer.Finalized, } default: return false, nil, apimiddleware.InternalServerError(fmt.Errorf("unsupported block version '%s'", respContainer.Version)) diff --git a/beacon-chain/rpc/apimiddleware/structs.go b/beacon-chain/rpc/apimiddleware/structs.go index 2c5d51f3a91e..dc21b572e11c 100644 --- a/beacon-chain/rpc/apimiddleware/structs.go +++ b/beacon-chain/rpc/apimiddleware/structs.go @@ -112,12 +112,14 @@ type BlockV2ResponseJson struct { Version string `json:"version" enum:"true"` Data *SignedBeaconBlockContainerV2Json `json:"data"` ExecutionOptimistic bool `json:"execution_optimistic"` + Finalized bool `json:"finalized"` } type BlindedBlockResponseJson struct { Version string `json:"version" enum:"true"` Data *SignedBlindedBeaconBlockContainerJson `json:"data"` ExecutionOptimistic bool `json:"execution_optimistic"` + Finalized bool `json:"finalized"` } type BlockRootResponseJson struct { @@ -1038,6 +1040,7 @@ type SszResponse interface { SSZVersion() string SSZOptimistic() bool SSZData() string + SSZFinalized() bool } type SszResponseJson struct { @@ -1056,9 +1059,14 @@ func (*SszResponseJson) SSZOptimistic() bool { return false } +func (*SszResponseJson) SSZFinalized() bool { + return true +} + type VersionedSSZResponseJson struct { Version string `json:"version" enum:"true"` ExecutionOptimistic bool `json:"execution_optimistic"` + Finalized bool `json:"finalized"` Data string `json:"data"` } @@ -1074,6 +1082,10 @@ func (ssz *VersionedSSZResponseJson) SSZOptimistic() bool { return ssz.ExecutionOptimistic } +func (ssz *VersionedSSZResponseJson) SSZFinalized() bool { + return ssz.Finalized +} + // --------------- // Events. // --------------- diff --git a/beacon-chain/rpc/eth/beacon/blinded_blocks.go b/beacon-chain/rpc/eth/beacon/blinded_blocks.go index a5f31448f633..537360a84b79 100644 --- a/beacon-chain/rpc/eth/beacon/blinded_blocks.go +++ b/beacon-chain/rpc/eth/beacon/blinded_blocks.go @@ -30,9 +30,14 @@ func (bs *Server) GetBlindedBlock(ctx context.Context, req *ethpbv1.BlockRequest if err != nil { return nil, err } + blkRoot, err := blk.Block().HashTreeRoot() + if err != nil { + return nil, errors.Wrapf(err, "could not get block root") + } result, err := getBlindedBlockPhase0(blk) if result != nil { + result.Finalized = bs.FinalizationFetcher.IsFinalized(ctx, blkRoot) return result, nil } // ErrUnsupportedGetter means that we have another block type @@ -41,6 +46,7 @@ func (bs *Server) GetBlindedBlock(ctx context.Context, req *ethpbv1.BlockRequest } result, err = getBlindedBlockAltair(blk) if result != nil { + result.Finalized = bs.FinalizationFetcher.IsFinalized(ctx, blkRoot) return result, nil } // ErrUnsupportedGetter means that we have another block type @@ -49,6 +55,7 @@ func (bs *Server) GetBlindedBlock(ctx context.Context, req *ethpbv1.BlockRequest } result, err = bs.getBlindedBlockBellatrix(ctx, blk) if result != nil { + result.Finalized = bs.FinalizationFetcher.IsFinalized(ctx, blkRoot) return result, nil } // ErrUnsupportedGetter means that we have another block type @@ -57,6 +64,7 @@ func (bs *Server) GetBlindedBlock(ctx context.Context, req *ethpbv1.BlockRequest } result, err = bs.getBlindedBlockCapella(ctx, blk) if result != nil { + result.Finalized = bs.FinalizationFetcher.IsFinalized(ctx, blkRoot) return result, nil } // ErrUnsupportedGetter means that we have another block type @@ -77,9 +85,14 @@ func (bs *Server) GetBlindedBlockSSZ(ctx context.Context, req *ethpbv1.BlockRequ if err != nil { return nil, err } + blkRoot, err := blk.Block().HashTreeRoot() + if err != nil { + return nil, errors.Wrapf(err, "could not get block root") + } result, err := getSSZBlockPhase0(blk) if result != nil { + result.Finalized = bs.FinalizationFetcher.IsFinalized(ctx, blkRoot) return result, nil } // ErrUnsupportedGetter means that we have another block type @@ -88,6 +101,7 @@ func (bs *Server) GetBlindedBlockSSZ(ctx context.Context, req *ethpbv1.BlockRequ } result, err = getSSZBlockAltair(blk) if result != nil { + result.Finalized = bs.FinalizationFetcher.IsFinalized(ctx, blkRoot) return result, nil } // ErrUnsupportedGetter means that we have another block type @@ -96,6 +110,7 @@ func (bs *Server) GetBlindedBlockSSZ(ctx context.Context, req *ethpbv1.BlockRequ } result, err = bs.getBlindedSSZBlockBellatrix(ctx, blk) if result != nil { + result.Finalized = bs.FinalizationFetcher.IsFinalized(ctx, blkRoot) return result, nil } // ErrUnsupportedGetter means that we have another block type @@ -104,6 +119,7 @@ func (bs *Server) GetBlindedBlockSSZ(ctx context.Context, req *ethpbv1.BlockRequ } result, err = bs.getBlindedSSZBlockCapella(ctx, blk) if result != nil { + result.Finalized = bs.FinalizationFetcher.IsFinalized(ctx, blkRoot) return result, nil } // ErrUnsupportedGetter means that we have another block type diff --git a/beacon-chain/rpc/eth/beacon/blinded_blocks_test.go b/beacon-chain/rpc/eth/beacon/blinded_blocks_test.go index 71738cda9af2..6399dce7bf30 100644 --- a/beacon-chain/rpc/eth/beacon/blinded_blocks_test.go +++ b/beacon-chain/rpc/eth/beacon/blinded_blocks_test.go @@ -36,41 +36,27 @@ func TestServer_GetBlindedBlock(t *testing.T) { genBlk, blkContainers := fillDBTestBlocks(ctx, t, beaconDB) canonicalRoots := make(map[[32]byte]bool) - for _, bContr := range blkContainers { canonicalRoots[bytesutil.ToBytes32(bContr.BlockRoot)] = true } headBlock := blkContainers[len(blkContainers)-1] nextSlot := headBlock.GetPhase0Block().Block.Slot + 1 - - b2 := util.NewBeaconBlock() - b2.Block.Slot = 30 - b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32) - util.SaveBlock(t, ctx, beaconDB, b2) - b3 := util.NewBeaconBlock() - b3.Block.Slot = 30 - b3.Block.ParentRoot = bytesutil.PadTo([]byte{4}, 32) - util.SaveBlock(t, ctx, beaconDB, b3) - b4 := util.NewBeaconBlock() - b4.Block.Slot = nextSlot - b4.Block.ParentRoot = bytesutil.PadTo([]byte{8}, 32) - util.SaveBlock(t, ctx, beaconDB, b4) - wsb, err := blocks.NewSignedBeaconBlock(headBlock.Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block) require.NoError(t, err) - mockChainService := &mock.ChainService{ DB: beaconDB, Block: wsb, Root: headBlock.BlockRoot, FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, CanonicalRoots: canonicalRoots, + FinalizedRoots: map[[32]byte]bool{}, } bs := &Server{ BeaconDB: beaconDB, ChainInfoFetcher: mockChainService, HeadFetcher: mockChainService, OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, } root, err := genBlk.Block.HashTreeRoot() @@ -168,26 +154,11 @@ func TestServer_GetBlindedBlock(t *testing.T) { genBlk, blkContainers := fillDBTestBlocksAltair(ctx, t, beaconDB) canonicalRoots := make(map[[32]byte]bool) - for _, bContr := range blkContainers { canonicalRoots[bytesutil.ToBytes32(bContr.BlockRoot)] = true } headBlock := blkContainers[len(blkContainers)-1] nextSlot := headBlock.GetAltairBlock().Block.Slot + 1 - - b2 := util.NewBeaconBlockAltair() - b2.Block.Slot = 30 - b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32) - util.SaveBlock(t, ctx, beaconDB, b2) - b3 := util.NewBeaconBlockAltair() - b3.Block.Slot = 30 - b3.Block.ParentRoot = bytesutil.PadTo([]byte{4}, 32) - util.SaveBlock(t, ctx, beaconDB, b3) - b4 := util.NewBeaconBlockAltair() - b4.Block.Slot = nextSlot - b4.Block.ParentRoot = bytesutil.PadTo([]byte{8}, 32) - util.SaveBlock(t, ctx, beaconDB, b4) - chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetAltairBlock()) require.NoError(t, err) mockChainService := &mock.ChainService{ @@ -196,12 +167,14 @@ func TestServer_GetBlindedBlock(t *testing.T) { Root: headBlock.BlockRoot, FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, CanonicalRoots: canonicalRoots, + FinalizedRoots: map[[32]byte]bool{}, } bs := &Server{ BeaconDB: beaconDB, ChainInfoFetcher: mockChainService, HeadFetcher: mockChainService, OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, } root, err := genBlk.Block.HashTreeRoot() @@ -299,26 +272,11 @@ func TestServer_GetBlindedBlock(t *testing.T) { genBlk, blkContainers := fillDBTestBlocksBellatrixBlinded(ctx, t, beaconDB) canonicalRoots := make(map[[32]byte]bool) - for _, bContr := range blkContainers { canonicalRoots[bytesutil.ToBytes32(bContr.BlockRoot)] = true } headBlock := blkContainers[len(blkContainers)-1] nextSlot := headBlock.GetBlindedBellatrixBlock().Block.Slot + 1 - - b2 := util.NewBlindedBeaconBlockBellatrix() - b2.Block.Slot = 30 - b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32) - util.SaveBlock(t, ctx, beaconDB, b2) - b3 := util.NewBlindedBeaconBlockBellatrix() - b3.Block.Slot = 30 - b3.Block.ParentRoot = bytesutil.PadTo([]byte{4}, 32) - util.SaveBlock(t, ctx, beaconDB, b3) - b4 := util.NewBlindedBeaconBlockBellatrix() - b4.Block.Slot = nextSlot - b4.Block.ParentRoot = bytesutil.PadTo([]byte{8}, 32) - util.SaveBlock(t, ctx, beaconDB, b4) - chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetBlindedBellatrixBlock()) require.NoError(t, err) mockChainService := &mock.ChainService{ @@ -327,6 +285,7 @@ func TestServer_GetBlindedBlock(t *testing.T) { Root: headBlock.BlockRoot, FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, CanonicalRoots: canonicalRoots, + FinalizedRoots: map[[32]byte]bool{}, } bs := &Server{ BeaconDB: beaconDB, @@ -336,6 +295,7 @@ func TestServer_GetBlindedBlock(t *testing.T) { ExecutionPayloadReconstructor: &executionTest.EngineClient{ ExecutionPayloadByBlockHash: map[[32]byte]*enginev1.ExecutionPayload{}, }, + FinalizationFetcher: mockChainService, } root, err := genBlk.Block.HashTreeRoot() @@ -433,26 +393,11 @@ func TestServer_GetBlindedBlock(t *testing.T) { genBlk, blkContainers := fillDBTestBlocksCapellaBlinded(ctx, t, beaconDB) canonicalRoots := make(map[[32]byte]bool) - for _, bContr := range blkContainers { canonicalRoots[bytesutil.ToBytes32(bContr.BlockRoot)] = true } headBlock := blkContainers[len(blkContainers)-1] nextSlot := headBlock.GetBlindedCapellaBlock().Block.Slot + 1 - - b2 := util.NewBlindedBeaconBlockCapella() - b2.Block.Slot = 30 - b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32) - util.SaveBlock(t, ctx, beaconDB, b2) - b3 := util.NewBlindedBeaconBlockCapella() - b3.Block.Slot = 30 - b3.Block.ParentRoot = bytesutil.PadTo([]byte{4}, 32) - util.SaveBlock(t, ctx, beaconDB, b3) - b4 := util.NewBlindedBeaconBlockCapella() - b4.Block.Slot = nextSlot - b4.Block.ParentRoot = bytesutil.PadTo([]byte{8}, 32) - util.SaveBlock(t, ctx, beaconDB, b4) - chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetBlindedCapellaBlock()) require.NoError(t, err) mockChainService := &mock.ChainService{ @@ -461,6 +406,7 @@ func TestServer_GetBlindedBlock(t *testing.T) { Root: headBlock.BlockRoot, FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, CanonicalRoots: canonicalRoots, + FinalizedRoots: map[[32]byte]bool{}, } bs := &Server{ BeaconDB: beaconDB, @@ -470,6 +416,7 @@ func TestServer_GetBlindedBlock(t *testing.T) { ExecutionPayloadReconstructor: &executionTest.EngineClient{ ExecutionPayloadByBlockHash: map[[32]byte]*enginev1.ExecutionPayload{}, }, + FinalizationFetcher: mockChainService, } root, err := genBlk.Block.HashTreeRoot() @@ -567,16 +514,6 @@ func TestServer_GetBlindedBlock(t *testing.T) { _, blkContainers := fillDBTestBlocksBellatrix(ctx, t, beaconDB) headBlock := blkContainers[len(blkContainers)-1] - - b2 := util.NewBeaconBlockBellatrix() - b2.Block.Slot = 30 - b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32) - util.SaveBlock(t, ctx, beaconDB, b2) - b3 := util.NewBeaconBlockBellatrix() - b3.Block.Slot = 30 - b3.Block.ParentRoot = bytesutil.PadTo([]byte{4}, 32) - util.SaveBlock(t, ctx, beaconDB, b3) - chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetBellatrixBlock()) require.NoError(t, err) mockChainService := &mock.ChainService{ @@ -585,12 +522,14 @@ func TestServer_GetBlindedBlock(t *testing.T) { Root: headBlock.BlockRoot, FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, Optimistic: true, + FinalizedRoots: map[[32]byte]bool{}, } bs := &Server{ BeaconDB: beaconDB, ChainInfoFetcher: mockChainService, HeadFetcher: mockChainService, OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, } blk, err := bs.GetBlindedBlock(ctx, ðpbv1.BlockRequest{ @@ -599,6 +538,49 @@ func TestServer_GetBlindedBlock(t *testing.T) { require.NoError(t, err) assert.Equal(t, true, blk.ExecutionOptimistic) }) + + t.Run("finalized", func(t *testing.T) { + beaconDB := dbTest.SetupDB(t) + ctx := context.Background() + + _, blkContainers := fillDBTestBlocks(ctx, t, beaconDB) + headBlock := blkContainers[len(blkContainers)-1] + chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetPhase0Block()) + require.NoError(t, err) + mockChainService := &mock.ChainService{ + DB: beaconDB, + Block: chainBlk, + Root: headBlock.BlockRoot, + FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, + Optimistic: true, + FinalizedRoots: map[[32]byte]bool{ + bytesutil.ToBytes32(blkContainers[32].BlockRoot): true, + bytesutil.ToBytes32(blkContainers[64].BlockRoot): false, + }, + } + bs := &Server{ + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainService, + HeadFetcher: mockChainService, + OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, + } + + t.Run("true", func(t *testing.T) { + blk, err := bs.GetBlindedBlock(ctx, ðpbv1.BlockRequest{ + BlockId: []byte("32"), + }) + require.NoError(t, err) + assert.Equal(t, true, blk.Finalized) + }) + t.Run("false", func(t *testing.T) { + blk, err := bs.GetBlindedBlock(ctx, ðpbv1.BlockRequest{ + BlockId: []byte("64"), + }) + require.NoError(t, err) + assert.Equal(t, false, blk.Finalized) + }) + }) } func TestServer_GetBlindedBlockSSZ(t *testing.T) { @@ -608,23 +590,19 @@ func TestServer_GetBlindedBlockSSZ(t *testing.T) { _, blkContainers := fillDBTestBlocks(ctx, t, beaconDB) headBlock := blkContainers[len(blkContainers)-1] - - b2 := util.NewBeaconBlock() - b2.Block.Slot = 30 - b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32) - util.SaveBlock(t, ctx, beaconDB, b2) - wsb, err := blocks.NewSignedBeaconBlock(headBlock.Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block) require.NoError(t, err) - + mockChainService := &mock.ChainService{ + DB: beaconDB, + Block: wsb, + Root: headBlock.BlockRoot, + FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, + FinalizedRoots: map[[32]byte]bool{}, + } bs := &Server{ - BeaconDB: beaconDB, - ChainInfoFetcher: &mock.ChainService{ - DB: beaconDB, - Block: wsb, - Root: headBlock.BlockRoot, - FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, - }, + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainService, + FinalizationFetcher: mockChainService, } blks, err := beaconDB.BlocksBySlot(ctx, 30) @@ -646,22 +624,19 @@ func TestServer_GetBlindedBlockSSZ(t *testing.T) { _, blkContainers := fillDBTestBlocksAltair(ctx, t, beaconDB) headBlock := blkContainers[len(blkContainers)-1] - - b2 := util.NewBeaconBlockAltair() - b2.Block.Slot = 30 - b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32) - util.SaveBlock(t, ctx, beaconDB, b2) - chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetAltairBlock()) require.NoError(t, err) + mockChainService := &mock.ChainService{ + DB: beaconDB, + Block: chainBlk, + Root: headBlock.BlockRoot, + FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, + FinalizedRoots: map[[32]byte]bool{}, + } bs := &Server{ - BeaconDB: beaconDB, - ChainInfoFetcher: &mock.ChainService{ - DB: beaconDB, - Block: chainBlk, - Root: headBlock.BlockRoot, - FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, - }, + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainService, + FinalizationFetcher: mockChainService, } blks, err := beaconDB.BlocksBySlot(ctx, 30) @@ -683,23 +658,20 @@ func TestServer_GetBlindedBlockSSZ(t *testing.T) { _, blkContainers := fillDBTestBlocksBellatrixBlinded(ctx, t, beaconDB) headBlock := blkContainers[len(blkContainers)-1] - - b2 := util.NewBlindedBeaconBlockBellatrix() - b2.Block.Slot = 30 - b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32) - util.SaveBlock(t, ctx, beaconDB, b2) - chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetBlindedBellatrixBlock()) require.NoError(t, err) + mockChainService := &mock.ChainService{ + DB: beaconDB, + Block: chainBlk, + Root: headBlock.BlockRoot, + FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, + FinalizedRoots: map[[32]byte]bool{}, + } bs := &Server{ - BeaconDB: beaconDB, - ChainInfoFetcher: &mock.ChainService{ - DB: beaconDB, - Block: chainBlk, - Root: headBlock.BlockRoot, - FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, - }, - OptimisticModeFetcher: &mock.ChainService{}, + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainService, + OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, } blks, err := beaconDB.BlocksBySlot(ctx, 30) @@ -721,23 +693,20 @@ func TestServer_GetBlindedBlockSSZ(t *testing.T) { _, blkContainers := fillDBTestBlocksCapellaBlinded(ctx, t, beaconDB) headBlock := blkContainers[len(blkContainers)-1] - - b2 := util.NewBlindedBeaconBlockCapella() - b2.Block.Slot = 30 - b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32) - util.SaveBlock(t, ctx, beaconDB, b2) - chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetBlindedCapellaBlock()) require.NoError(t, err) + mockChainService := &mock.ChainService{ + DB: beaconDB, + Block: chainBlk, + Root: headBlock.BlockRoot, + FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, + FinalizedRoots: map[[32]byte]bool{}, + } bs := &Server{ - BeaconDB: beaconDB, - ChainInfoFetcher: &mock.ChainService{ - DB: beaconDB, - Block: chainBlk, - Root: headBlock.BlockRoot, - FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, - }, - OptimisticModeFetcher: &mock.ChainService{}, + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainService, + OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, } blks, err := beaconDB.BlocksBySlot(ctx, 30) @@ -752,6 +721,80 @@ func TestServer_GetBlindedBlockSSZ(t *testing.T) { assert.DeepEqual(t, sszBlock, resp.Data) assert.Equal(t, ethpbv2.Version_CAPELLA, resp.Version) }) + + t.Run("execution optimistic", func(t *testing.T) { + beaconDB := dbTest.SetupDB(t) + ctx := context.Background() + + _, blkContainers := fillDBTestBlocksBellatrix(ctx, t, beaconDB) + headBlock := blkContainers[len(blkContainers)-1] + chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetBellatrixBlock()) + require.NoError(t, err) + mockChainService := &mock.ChainService{ + DB: beaconDB, + Block: chainBlk, + Root: headBlock.BlockRoot, + FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, + Optimistic: true, + FinalizedRoots: map[[32]byte]bool{}, + } + bs := &Server{ + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainService, + HeadFetcher: mockChainService, + OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, + } + + blk, err := bs.GetBlindedBlockSSZ(ctx, ðpbv1.BlockRequest{ + BlockId: []byte("head"), + }) + require.NoError(t, err) + assert.Equal(t, true, blk.ExecutionOptimistic) + }) + + t.Run("finalized", func(t *testing.T) { + beaconDB := dbTest.SetupDB(t) + ctx := context.Background() + + _, blkContainers := fillDBTestBlocks(ctx, t, beaconDB) + headBlock := blkContainers[len(blkContainers)-1] + chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetPhase0Block()) + require.NoError(t, err) + mockChainService := &mock.ChainService{ + DB: beaconDB, + Block: chainBlk, + Root: headBlock.BlockRoot, + FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, + Optimistic: true, + FinalizedRoots: map[[32]byte]bool{ + bytesutil.ToBytes32(blkContainers[32].BlockRoot): true, + bytesutil.ToBytes32(blkContainers[64].BlockRoot): false, + }, + } + bs := &Server{ + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainService, + HeadFetcher: mockChainService, + OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, + } + + t.Run("true", func(t *testing.T) { + blk, err := bs.GetBlindedBlockSSZ(ctx, ðpbv1.BlockRequest{ + BlockId: []byte("32"), + }) + require.NoError(t, err) + assert.Equal(t, true, blk.Finalized) + }) + t.Run("false", func(t *testing.T) { + blk, err := bs.GetBlindedBlockSSZ(ctx, ðpbv1.BlockRequest{ + BlockId: []byte("64"), + }) + require.NoError(t, err) + assert.Equal(t, false, blk.Finalized) + }) + }) } func TestServer_SubmitBlindedBlockSSZ_OK(t *testing.T) { diff --git a/beacon-chain/rpc/eth/beacon/blocks.go b/beacon-chain/rpc/eth/beacon/blocks.go index 631242f6aac9..8455fe477f4d 100644 --- a/beacon-chain/rpc/eth/beacon/blocks.go +++ b/beacon-chain/rpc/eth/beacon/blocks.go @@ -342,9 +342,14 @@ func (bs *Server) GetBlockV2(ctx context.Context, req *ethpbv2.BlockRequestV2) ( if err != nil { return nil, err } + blkRoot, err := blk.Block().HashTreeRoot() + if err != nil { + return nil, errors.Wrapf(err, "could not get block root") + } result, err := getBlockPhase0(blk) if result != nil { + result.Finalized = bs.FinalizationFetcher.IsFinalized(ctx, blkRoot) return result, nil } // ErrUnsupportedGetter means that we have another block type @@ -353,6 +358,7 @@ func (bs *Server) GetBlockV2(ctx context.Context, req *ethpbv2.BlockRequestV2) ( } result, err = getBlockAltair(blk) if result != nil { + result.Finalized = bs.FinalizationFetcher.IsFinalized(ctx, blkRoot) return result, nil } // ErrUnsupportedGetter means that we have another block type @@ -361,6 +367,7 @@ func (bs *Server) GetBlockV2(ctx context.Context, req *ethpbv2.BlockRequestV2) ( } result, err = bs.getBlockBellatrix(ctx, blk) if result != nil { + result.Finalized = bs.FinalizationFetcher.IsFinalized(ctx, blkRoot) return result, nil } // ErrUnsupportedGetter means that we have another block type @@ -369,6 +376,7 @@ func (bs *Server) GetBlockV2(ctx context.Context, req *ethpbv2.BlockRequestV2) ( } result, err = bs.getBlockCapella(ctx, blk) if result != nil { + result.Finalized = bs.FinalizationFetcher.IsFinalized(ctx, blkRoot) return result, nil } // ErrUnsupportedGetter means that we have another block type @@ -388,9 +396,14 @@ func (bs *Server) GetBlockSSZV2(ctx context.Context, req *ethpbv2.BlockRequestV2 if err != nil { return nil, err } + blkRoot, err := blk.Block().HashTreeRoot() + if err != nil { + return nil, errors.Wrapf(err, "could not get block root") + } result, err := getSSZBlockPhase0(blk) if result != nil { + result.Finalized = bs.FinalizationFetcher.IsFinalized(ctx, blkRoot) return result, nil } // ErrUnsupportedGetter means that we have another block type @@ -399,6 +412,7 @@ func (bs *Server) GetBlockSSZV2(ctx context.Context, req *ethpbv2.BlockRequestV2 } result, err = getSSZBlockAltair(blk) if result != nil { + result.Finalized = bs.FinalizationFetcher.IsFinalized(ctx, blkRoot) return result, nil } // ErrUnsupportedGetter means that we have another block type @@ -407,6 +421,7 @@ func (bs *Server) GetBlockSSZV2(ctx context.Context, req *ethpbv2.BlockRequestV2 } result, err = bs.getSSZBlockBellatrix(ctx, blk) if result != nil { + result.Finalized = bs.FinalizationFetcher.IsFinalized(ctx, blkRoot) return result, nil } // ErrUnsupportedGetter means that we have another block type @@ -415,6 +430,7 @@ func (bs *Server) GetBlockSSZV2(ctx context.Context, req *ethpbv2.BlockRequestV2 } result, err = bs.getSSZBlockCapella(ctx, blk) if result != nil { + result.Finalized = bs.FinalizationFetcher.IsFinalized(ctx, blkRoot) return result, nil } // ErrUnsupportedGetter means that we have another block type diff --git a/beacon-chain/rpc/eth/beacon/blocks_test.go b/beacon-chain/rpc/eth/beacon/blocks_test.go index 26263b7609eb..ba59d33bde36 100644 --- a/beacon-chain/rpc/eth/beacon/blocks_test.go +++ b/beacon-chain/rpc/eth/beacon/blocks_test.go @@ -1095,26 +1095,12 @@ func TestServer_GetBlockV2(t *testing.T) { genBlk, blkContainers := fillDBTestBlocks(ctx, t, beaconDB) canonicalRoots := make(map[[32]byte]bool) - for _, bContr := range blkContainers { canonicalRoots[bytesutil.ToBytes32(bContr.BlockRoot)] = true } headBlock := blkContainers[len(blkContainers)-1] nextSlot := headBlock.GetPhase0Block().Block.Slot + 1 - b2 := util.NewBeaconBlock() - b2.Block.Slot = 30 - b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32) - util.SaveBlock(t, ctx, beaconDB, b2) - b3 := util.NewBeaconBlock() - b3.Block.Slot = 30 - b3.Block.ParentRoot = bytesutil.PadTo([]byte{4}, 32) - util.SaveBlock(t, ctx, beaconDB, b3) - b4 := util.NewBeaconBlock() - b4.Block.Slot = nextSlot - b4.Block.ParentRoot = bytesutil.PadTo([]byte{8}, 32) - util.SaveBlock(t, ctx, beaconDB, b4) - wsb, err := blocks.NewSignedBeaconBlock(headBlock.Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block) require.NoError(t, err) @@ -1124,12 +1110,14 @@ func TestServer_GetBlockV2(t *testing.T) { Root: headBlock.BlockRoot, FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, CanonicalRoots: canonicalRoots, + FinalizedRoots: map[[32]byte]bool{}, } bs := &Server{ BeaconDB: beaconDB, ChainInfoFetcher: mockChainService, HeadFetcher: mockChainService, OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, } root, err := genBlk.Block.HashTreeRoot() @@ -1227,26 +1215,12 @@ func TestServer_GetBlockV2(t *testing.T) { genBlk, blkContainers := fillDBTestBlocksAltair(ctx, t, beaconDB) canonicalRoots := make(map[[32]byte]bool) - for _, bContr := range blkContainers { canonicalRoots[bytesutil.ToBytes32(bContr.BlockRoot)] = true } headBlock := blkContainers[len(blkContainers)-1] nextSlot := headBlock.GetAltairBlock().Block.Slot + 1 - b2 := util.NewBeaconBlockAltair() - b2.Block.Slot = 30 - b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32) - util.SaveBlock(t, ctx, beaconDB, b2) - b3 := util.NewBeaconBlockAltair() - b3.Block.Slot = 30 - b3.Block.ParentRoot = bytesutil.PadTo([]byte{4}, 32) - util.SaveBlock(t, ctx, beaconDB, b3) - b4 := util.NewBeaconBlockAltair() - b4.Block.Slot = nextSlot - b4.Block.ParentRoot = bytesutil.PadTo([]byte{8}, 32) - util.SaveBlock(t, ctx, beaconDB, b4) - chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetAltairBlock()) require.NoError(t, err) mockChainService := &mock.ChainService{ @@ -1255,12 +1229,14 @@ func TestServer_GetBlockV2(t *testing.T) { Root: headBlock.BlockRoot, FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, CanonicalRoots: canonicalRoots, + FinalizedRoots: map[[32]byte]bool{}, } bs := &Server{ BeaconDB: beaconDB, ChainInfoFetcher: mockChainService, HeadFetcher: mockChainService, OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, } root, err := genBlk.Block.HashTreeRoot() @@ -1358,26 +1334,12 @@ func TestServer_GetBlockV2(t *testing.T) { genBlk, blkContainers := fillDBTestBlocksBellatrix(ctx, t, beaconDB) canonicalRoots := make(map[[32]byte]bool) - for _, bContr := range blkContainers { canonicalRoots[bytesutil.ToBytes32(bContr.BlockRoot)] = true } headBlock := blkContainers[len(blkContainers)-1] nextSlot := headBlock.GetBellatrixBlock().Block.Slot + 1 - b2 := util.NewBeaconBlockBellatrix() - b2.Block.Slot = 30 - b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32) - util.SaveBlock(t, ctx, beaconDB, b2) - b3 := util.NewBeaconBlockBellatrix() - b3.Block.Slot = 30 - b3.Block.ParentRoot = bytesutil.PadTo([]byte{4}, 32) - util.SaveBlock(t, ctx, beaconDB, b3) - b4 := util.NewBeaconBlockBellatrix() - b4.Block.Slot = nextSlot - b4.Block.ParentRoot = bytesutil.PadTo([]byte{8}, 32) - util.SaveBlock(t, ctx, beaconDB, b4) - chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetBellatrixBlock()) require.NoError(t, err) mockChainService := &mock.ChainService{ @@ -1386,6 +1348,7 @@ func TestServer_GetBlockV2(t *testing.T) { Root: headBlock.BlockRoot, FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, CanonicalRoots: canonicalRoots, + FinalizedRoots: map[[32]byte]bool{}, } bs := &Server{ BeaconDB: beaconDB, @@ -1395,6 +1358,7 @@ func TestServer_GetBlockV2(t *testing.T) { ExecutionPayloadReconstructor: &executionTest.EngineClient{ ExecutionPayloadByBlockHash: map[[32]byte]*enginev1.ExecutionPayload{}, }, + FinalizationFetcher: mockChainService, } root, err := genBlk.Block.HashTreeRoot() @@ -1499,19 +1463,6 @@ func TestServer_GetBlockV2(t *testing.T) { headBlock := blkContainers[len(blkContainers)-1] nextSlot := headBlock.GetCapellaBlock().Block.Slot + 1 - b2 := util.NewBeaconBlockCapella() - b2.Block.Slot = 30 - b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32) - util.SaveBlock(t, ctx, beaconDB, b2) - b3 := util.NewBeaconBlockCapella() - b3.Block.Slot = 30 - b3.Block.ParentRoot = bytesutil.PadTo([]byte{4}, 32) - util.SaveBlock(t, ctx, beaconDB, b3) - b4 := util.NewBeaconBlockCapella() - b4.Block.Slot = nextSlot - b4.Block.ParentRoot = bytesutil.PadTo([]byte{8}, 32) - util.SaveBlock(t, ctx, beaconDB, b4) - chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetCapellaBlock()) require.NoError(t, err) mockChainService := &mock.ChainService{ @@ -1520,6 +1471,7 @@ func TestServer_GetBlockV2(t *testing.T) { Root: headBlock.BlockRoot, FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, CanonicalRoots: canonicalRoots, + FinalizedRoots: map[[32]byte]bool{}, } bs := &Server{ BeaconDB: beaconDB, @@ -1529,6 +1481,7 @@ func TestServer_GetBlockV2(t *testing.T) { ExecutionPayloadReconstructor: &executionTest.EngineClient{ ExecutionPayloadByBlockHash: map[[32]byte]*enginev1.ExecutionPayload{}, }, + FinalizationFetcher: mockChainService, } root, err := genBlk.Block.HashTreeRoot() @@ -1627,15 +1580,6 @@ func TestServer_GetBlockV2(t *testing.T) { _, blkContainers := fillDBTestBlocksBellatrix(ctx, t, beaconDB) headBlock := blkContainers[len(blkContainers)-1] - b2 := util.NewBeaconBlockBellatrix() - b2.Block.Slot = 30 - b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32) - util.SaveBlock(t, ctx, beaconDB, b2) - b3 := util.NewBeaconBlockBellatrix() - b3.Block.Slot = 30 - b3.Block.ParentRoot = bytesutil.PadTo([]byte{4}, 32) - util.SaveBlock(t, ctx, beaconDB, b3) - chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetBellatrixBlock()) require.NoError(t, err) mockChainService := &mock.ChainService{ @@ -1644,12 +1588,14 @@ func TestServer_GetBlockV2(t *testing.T) { Root: headBlock.BlockRoot, FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, Optimistic: true, + FinalizedRoots: map[[32]byte]bool{}, } bs := &Server{ BeaconDB: beaconDB, ChainInfoFetcher: mockChainService, HeadFetcher: mockChainService, OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, } blk, err := bs.GetBlockV2(ctx, ðpbv2.BlockRequestV2{ @@ -1658,6 +1604,50 @@ func TestServer_GetBlockV2(t *testing.T) { require.NoError(t, err) assert.Equal(t, true, blk.ExecutionOptimistic) }) + + t.Run("finalized", func(t *testing.T) { + beaconDB := dbTest.SetupDB(t) + ctx := context.Background() + + _, blkContainers := fillDBTestBlocks(ctx, t, beaconDB) + headBlock := blkContainers[len(blkContainers)-1] + + chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetPhase0Block()) + require.NoError(t, err) + mockChainService := &mock.ChainService{ + DB: beaconDB, + Block: chainBlk, + Root: headBlock.BlockRoot, + FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, + Optimistic: true, + FinalizedRoots: map[[32]byte]bool{ + bytesutil.ToBytes32(blkContainers[32].BlockRoot): true, + bytesutil.ToBytes32(blkContainers[64].BlockRoot): false, + }, + } + bs := &Server{ + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainService, + HeadFetcher: mockChainService, + OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, + } + + t.Run("true", func(t *testing.T) { + blk, err := bs.GetBlockV2(ctx, ðpbv2.BlockRequestV2{ + BlockId: []byte("32"), + }) + require.NoError(t, err) + assert.Equal(t, true, blk.Finalized) + }) + t.Run("false", func(t *testing.T) { + blk, err := bs.GetBlockV2(ctx, ðpbv2.BlockRequestV2{ + BlockId: []byte("64"), + }) + require.NoError(t, err) + assert.Equal(t, false, blk.Finalized) + }) + }) } func TestServer_GetBlockSSZ(t *testing.T) { @@ -1704,23 +1694,19 @@ func TestServer_GetBlockSSZV2(t *testing.T) { _, blkContainers := fillDBTestBlocks(ctx, t, beaconDB) headBlock := blkContainers[len(blkContainers)-1] - - b2 := util.NewBeaconBlock() - b2.Block.Slot = 30 - b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32) - util.SaveBlock(t, ctx, beaconDB, b2) - wsb, err := blocks.NewSignedBeaconBlock(headBlock.Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block) require.NoError(t, err) - + mockChainService := &mock.ChainService{ + DB: beaconDB, + Block: wsb, + Root: headBlock.BlockRoot, + FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, + FinalizedRoots: map[[32]byte]bool{}, + } bs := &Server{ - BeaconDB: beaconDB, - ChainInfoFetcher: &mock.ChainService{ - DB: beaconDB, - Block: wsb, - Root: headBlock.BlockRoot, - FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, - }, + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainService, + FinalizationFetcher: mockChainService, } blks, err := beaconDB.BlocksBySlot(ctx, 30) @@ -1742,22 +1728,19 @@ func TestServer_GetBlockSSZV2(t *testing.T) { _, blkContainers := fillDBTestBlocksAltair(ctx, t, beaconDB) headBlock := blkContainers[len(blkContainers)-1] - - b2 := util.NewBeaconBlockAltair() - b2.Block.Slot = 30 - b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32) - util.SaveBlock(t, ctx, beaconDB, b2) - chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetAltairBlock()) require.NoError(t, err) + mockChainService := &mock.ChainService{ + DB: beaconDB, + Block: chainBlk, + Root: headBlock.BlockRoot, + FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, + FinalizedRoots: map[[32]byte]bool{}, + } bs := &Server{ - BeaconDB: beaconDB, - ChainInfoFetcher: &mock.ChainService{ - DB: beaconDB, - Block: chainBlk, - Root: headBlock.BlockRoot, - FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, - }, + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainService, + FinalizationFetcher: mockChainService, } blks, err := beaconDB.BlocksBySlot(ctx, 30) @@ -1779,23 +1762,20 @@ func TestServer_GetBlockSSZV2(t *testing.T) { _, blkContainers := fillDBTestBlocksBellatrix(ctx, t, beaconDB) headBlock := blkContainers[len(blkContainers)-1] - - b2 := util.NewBeaconBlockBellatrix() - b2.Block.Slot = 30 - b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32) - util.SaveBlock(t, ctx, beaconDB, b2) - chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetBellatrixBlock()) require.NoError(t, err) + mockChainService := &mock.ChainService{ + DB: beaconDB, + Block: chainBlk, + Root: headBlock.BlockRoot, + FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, + FinalizedRoots: map[[32]byte]bool{}, + } bs := &Server{ - BeaconDB: beaconDB, - ChainInfoFetcher: &mock.ChainService{ - DB: beaconDB, - Block: chainBlk, - Root: headBlock.BlockRoot, - FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, - }, - OptimisticModeFetcher: &mock.ChainService{}, + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainService, + OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, } blks, err := beaconDB.BlocksBySlot(ctx, 30) @@ -1817,23 +1797,20 @@ func TestServer_GetBlockSSZV2(t *testing.T) { _, blkContainers := fillDBTestBlocksCapella(ctx, t, beaconDB) headBlock := blkContainers[len(blkContainers)-1] - - b2 := util.NewBeaconBlockCapella() - b2.Block.Slot = 30 - b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32) - util.SaveBlock(t, ctx, beaconDB, b2) - chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetCapellaBlock()) require.NoError(t, err) + mockChainService := &mock.ChainService{ + DB: beaconDB, + Block: chainBlk, + Root: headBlock.BlockRoot, + FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, + FinalizedRoots: map[[32]byte]bool{}, + } bs := &Server{ - BeaconDB: beaconDB, - ChainInfoFetcher: &mock.ChainService{ - DB: beaconDB, - Block: chainBlk, - Root: headBlock.BlockRoot, - FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, - }, - OptimisticModeFetcher: &mock.ChainService{}, + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainService, + OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, } blks, err := beaconDB.BlocksBySlot(ctx, 30) @@ -1848,6 +1825,82 @@ func TestServer_GetBlockSSZV2(t *testing.T) { assert.DeepEqual(t, sszBlock, resp.Data) assert.Equal(t, ethpbv2.Version_CAPELLA, resp.Version) }) + + t.Run("execution optimistic", func(t *testing.T) { + beaconDB := dbTest.SetupDB(t) + ctx := context.Background() + + _, blkContainers := fillDBTestBlocksBellatrix(ctx, t, beaconDB) + headBlock := blkContainers[len(blkContainers)-1] + + chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetBellatrixBlock()) + require.NoError(t, err) + mockChainService := &mock.ChainService{ + DB: beaconDB, + Block: chainBlk, + Root: headBlock.BlockRoot, + FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, + Optimistic: true, + FinalizedRoots: map[[32]byte]bool{}, + } + bs := &Server{ + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainService, + HeadFetcher: mockChainService, + OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, + } + + blk, err := bs.GetBlockSSZV2(ctx, ðpbv2.BlockRequestV2{ + BlockId: []byte("head"), + }) + require.NoError(t, err) + assert.Equal(t, true, blk.ExecutionOptimistic) + }) + + t.Run("finalized", func(t *testing.T) { + beaconDB := dbTest.SetupDB(t) + ctx := context.Background() + + _, blkContainers := fillDBTestBlocks(ctx, t, beaconDB) + headBlock := blkContainers[len(blkContainers)-1] + + chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetPhase0Block()) + require.NoError(t, err) + mockChainService := &mock.ChainService{ + DB: beaconDB, + Block: chainBlk, + Root: headBlock.BlockRoot, + FinalizedCheckPoint: ðpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot}, + Optimistic: true, + FinalizedRoots: map[[32]byte]bool{ + bytesutil.ToBytes32(blkContainers[32].BlockRoot): true, + bytesutil.ToBytes32(blkContainers[64].BlockRoot): false, + }, + } + bs := &Server{ + BeaconDB: beaconDB, + ChainInfoFetcher: mockChainService, + HeadFetcher: mockChainService, + OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, + } + + t.Run("true", func(t *testing.T) { + blk, err := bs.GetBlockV2(ctx, ðpbv2.BlockRequestV2{ + BlockId: []byte("32"), + }) + require.NoError(t, err) + assert.Equal(t, true, blk.Finalized) + }) + t.Run("false", func(t *testing.T) { + blk, err := bs.GetBlockV2(ctx, ðpbv2.BlockRequestV2{ + BlockId: []byte("64"), + }) + require.NoError(t, err) + assert.Equal(t, false, blk.Finalized) + }) + }) } func TestServer_GetBlockRoot(t *testing.T) {