remove need for consensus api

This commit is contained in:
Jordan Oroshiba 2023-09-12 10:31:53 -07:00
parent 7d62342e3a
commit 2ab39c48b5

View file

@ -11,6 +11,7 @@ import (
"github.com/ethereum/go-ethereum/beacon/engine" "github.com/ethereum/go-ethereum/beacon/engine"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/catalyst" "github.com/ethereum/go-ethereum/eth/catalyst"
@ -19,6 +20,8 @@ import (
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/miner" "github.com/ethereum/go-ethereum/miner"
"google.golang.org/protobuf/types/known/timestamppb" "google.golang.org/protobuf/types/known/timestamppb"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
) )
// executionServiceServer is the implementation of the ExecutionServiceServerV1Alpha1 interface. // executionServiceServer is the implementation of the ExecutionServiceServerV1Alpha1 interface.
@ -127,7 +130,7 @@ func (s *ExecutionServiceServerV1Alpha1) FinalizeBlock(ctx context.Context, req
} }
func (s *ExecutionServiceServerV1Alpha1) InitState(ctx context.Context, req *executionv1a1.InitStateRequest) (*executionv1a1.InitStateResponse, error) { func (s *ExecutionServiceServerV1Alpha1) InitState(ctx context.Context, req *executionv1a1.InitStateRequest) (*executionv1a1.InitStateResponse, error) {
currHead := s.eth.BlockChain().CurrentHeader() currHead := s.bc.CurrentHeader()
res := &executionv1a1.InitStateResponse{ res := &executionv1a1.InitStateResponse{
BlockHash: currHead.Hash().Bytes(), BlockHash: currHead.Hash().Bytes(),
} }
@ -141,21 +144,16 @@ type ExecutionServiceServerV1Alpha2 struct {
// All implementations must embed UnimplementedExecutionServiceServer // All implementations must embed UnimplementedExecutionServiceServer
// for forward compatibility // for forward compatibility
executionv1a2.UnimplementedExecutionServiceServer executionv1a2.UnimplementedExecutionServiceServer
consensus *catalyst.ConsensusAPI eth *eth.Ethereum
eth *eth.Ethereum bc *core.BlockChain
bc *core.BlockChain
} }
func NewExecutionServiceServerV1Alpha2(eth *eth.Ethereum) *ExecutionServiceServerV1Alpha2 { func NewExecutionServiceServerV1Alpha2(eth *eth.Ethereum) *ExecutionServiceServerV1Alpha2 {
consensus := catalyst.NewConsensusAPI(eth)
bc := eth.BlockChain() bc := eth.BlockChain()
return &ExecutionServiceServerV1Alpha2{ return &ExecutionServiceServerV1Alpha2{
eth: eth, eth: eth,
consensus: consensus,
bc: bc, bc: bc,
} }
} }
@ -166,7 +164,7 @@ func (s *ExecutionServiceServerV1Alpha2) GetBlock(ctx context.Context, req *exec
res, err := s.getBlockFromIdentifier(req.GetIdentifier()) res, err := s.getBlockFromIdentifier(req.GetIdentifier())
if err != nil { if err != nil {
return nil, fmt.Errorf("Block header cannot be converted to execution block") return nil, status.Error(codes.NotFound, "Block header cannot be converted to execution block")
} }
return res, nil return res, nil
@ -201,7 +199,7 @@ func (s *ExecutionServiceServerV1Alpha2) ExecuteBlock(ctx context.Context, req *
prevHeadHash := common.BytesToHash(req.PrevBlockHash) prevHeadHash := common.BytesToHash(req.PrevBlockHash)
softHash := s.bc.CurrentSafeBlock().Hash() softHash := s.bc.CurrentSafeBlock().Hash()
if prevHeadHash != softHash { if prevHeadHash != softHash {
return nil, fmt.Errorf("Block can only be created on top of soft block.") return nil, status.Error(codes.FailedPrecondition, "Block can only be created on top of soft block.")
} }
// The Engine API has been modified to use transactions from this mempool and abide by it's ordering. // The Engine API has been modified to use transactions from this mempool and abide by it's ordering.
@ -217,7 +215,7 @@ func (s *ExecutionServiceServerV1Alpha2) ExecuteBlock(ctx context.Context, req *
payload, err := s.eth.Miner().BuildPayload(payloadAttributes) payload, err := s.eth.Miner().BuildPayload(payloadAttributes)
if err != nil { if err != nil {
log.Error("failed to build payload", "err", err) log.Error("failed to build payload", "err", err)
return nil, err return nil, status.Error(codes.InvalidArgument, "could not build block with provided txs")
} }
// call blockchain.InsertChain to actually execute and write the blocks to state // call blockchain.InsertChain to actually execute and write the blocks to state
@ -230,10 +228,11 @@ func (s *ExecutionServiceServerV1Alpha2) ExecuteBlock(ctx context.Context, req *
} }
n, err := s.bc.InsertChain(blocks) n, err := s.bc.InsertChain(blocks)
if err != nil { if err != nil {
return nil, err return nil, status.Error(codes.Internal, "failed to insert block to chain")
} }
if n != 1 { if n != 1 {
return nil, fmt.Errorf("failed to insert block into blockchain (n=%d)", n) log.Error("block was inserted at height ", n, " instead of head")
return nil, status.Error(codes.Internal, "failed to insert block to chain")
} }
// remove txs from original mempool // remove txs from original mempool
@ -257,7 +256,7 @@ func (s *ExecutionServiceServerV1Alpha2) GetCommitmentState(ctx context.Context,
firmBlock, err := s.ethHeaderToExecutionBlock(s.bc.CurrentFinalBlock()) firmBlock, err := s.ethHeaderToExecutionBlock(s.bc.CurrentFinalBlock())
if err != nil { if err != nil {
return nil, fmt.Errorf("Failed finding CommitmentState") return nil, err
} }
res := &executionv1a2.CommitmentState{ res := &executionv1a2.CommitmentState{
@ -270,15 +269,47 @@ func (s *ExecutionServiceServerV1Alpha2) GetCommitmentState(ctx context.Context,
// UpdateCommitmentState replaces the whole CommitmentState with a new CommitmentState. // UpdateCommitmentState replaces the whole CommitmentState with a new CommitmentState.
func (s *ExecutionServiceServerV1Alpha2) UpdateCommitmentState(ctx context.Context, req *executionv1a2.UpdateCommitmentStateRequest) (*executionv1a2.CommitmentState, error) { func (s *ExecutionServiceServerV1Alpha2) UpdateCommitmentState(ctx context.Context, req *executionv1a2.UpdateCommitmentStateRequest) (*executionv1a2.CommitmentState, error) {
newForkChoice := &engine.ForkchoiceStateV1{ softEthHash := common.BytesToHash(req.CommitmentState.Soft.Hash)
HeadBlockHash: common.BytesToHash(req.CommitmentState.Soft.Hash), firmEthHash := common.BytesToHash(req.CommitmentState.Firm.Hash)
SafeBlockHash: common.BytesToHash(req.CommitmentState.Soft.Hash),
FinalizedBlockHash: common.BytesToHash(req.CommitmentState.Firm.Hash), // Validate that the firm and soft blocks exist before going further
softBlock := s.bc.GetBlockByHash(softEthHash)
if (softBlock == nil) {
return nil, status.Error(codes.InvalidArgument, "Soft block specified does not exist")
}
firmBlock := s.bc.GetBlockByHash(firmEthHash)
if (firmBlock == nil) {
return nil, status.Error(codes.InvalidArgument, "Firm block specified does not exist")
}
currentHead := s.bc.CurrentBlock().Hash()
// Update the head block to soft commitment
// This must be done before last validation step, we can only check if a block
// belongs to the canonical chain.
if currentHead != softEthHash {
if _, err := s.bc.SetCanonical(softBlock); err != nil {
return nil, status.Error(codes.Internal, "could not update head to safe hash")
}
} }
_, err := s.consensus.ForkchoiceUpdatedV1(*newForkChoice, nil) // Once head is updated validate that firm belongs to chain
if err != nil { if (rawdb.ReadCanonicalHash(s.eth.ChainDb(), firmBlock.NumberU64()) != firmEthHash) {
return nil, err // We don't want partial commitments, rolling back.
rollbackBlock := s.bc.GetBlockByHash(currentHead)
s.bc.SetCanonical(rollbackBlock)
return nil, status.Error(codes.InvalidArgument, "Firm block specified does not exist on canonical chain")
}
// Updating the safe and final after everything validated
currentSafe := s.bc.CurrentSafeBlock().Hash()
if currentSafe != softEthHash {
s.bc.SetSafe(softBlock.Header())
}
currentFirm := s.bc.CurrentFinalBlock().Hash()
if currentFirm != firmEthHash {
s.bc.SetFinalized(firmBlock.Header())
} }
return req.CommitmentState, nil return req.CommitmentState, nil
@ -286,6 +317,8 @@ func (s *ExecutionServiceServerV1Alpha2) UpdateCommitmentState(ctx context.Conte
func (s *ExecutionServiceServerV1Alpha2) getBlockFromIdentifier(identifier *executionv1a2.BlockIdentifier) (*executionv1a2.Block, error) { func (s *ExecutionServiceServerV1Alpha2) getBlockFromIdentifier(identifier *executionv1a2.BlockIdentifier) (*executionv1a2.Block, error) {
var header *types.Header var header *types.Header
// Grab the header based on the identifier provided
switch id_type := identifier.Identifier.(type) { switch id_type := identifier.Identifier.(type) {
case *executionv1a2.BlockIdentifier_BlockNumber: case *executionv1a2.BlockIdentifier_BlockNumber:
header = s.bc.GetHeaderByNumber(uint64(identifier.GetBlockNumber())) header = s.bc.GetHeaderByNumber(uint64(identifier.GetBlockNumber()))
@ -294,16 +327,16 @@ func (s *ExecutionServiceServerV1Alpha2) getBlockFromIdentifier(identifier *exec
header = s.bc.GetHeaderByHash(common.BytesToHash(identifier.GetBlockHash())) header = s.bc.GetHeaderByHash(common.BytesToHash(identifier.GetBlockHash()))
break break
default: default:
return nil, fmt.Errorf("Identifier has unexpected type %T", id_type) return nil, status.Errorf(codes.InvalidArgument, "identifier has unexpected type %T", id_type)
} }
if header == nil { if header == nil {
return nil, fmt.Errorf("Couldn't locate block with identifier %s", identifier.Identifier) return nil, status.Errorf(codes.NotFound, "Couldn't locate block with identifier %s", identifier.Identifier)
} }
res, err := s.ethHeaderToExecutionBlock(header) res, err := s.ethHeaderToExecutionBlock(header)
if err != nil { if err != nil {
return nil, fmt.Errorf("Block header cannot be converted to execution block") return nil, status.Errorf(codes.Internal, "internal error")
} }
return res, nil return res, nil