diff --git a/cmd/geth/config.go b/cmd/geth/config.go index a45ab6602e..69005d6772 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -175,8 +175,9 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) { // Configure gRPC if requested. if ctx.IsSet(utils.GRPCEnabledFlag.Name) { - service := execution.NewExecutionServiceServer(eth) - utils.RegisterGRPCService(stack, service, &cfg.Node) + serviceV1a1 := execution.NewExecutionServiceServerV1Alpha1(eth) + serviceV1a2 := execution.NewExecutionServiceServerV1Alpha2(eth) + utils.RegisterGRPCExecutionService(stack, serviceV1a1, serviceV1a2, &cfg.Node) } // Add the Ethereum Stats daemon if requested. diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 1d7fedb72e..b313a4fe93 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -58,6 +58,7 @@ import ( "github.com/ethereum/go-ethereum/ethstats" "github.com/ethereum/go-ethereum/graphql" executionv1a1 "github.com/ethereum/go-ethereum/grpc/gen/astria/execution/v1alpha1" + executionv1a2 "github.com/ethereum/go-ethereum/grpc/gen/astria/execution/v1alpha2" "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/les" @@ -2063,10 +2064,10 @@ func RegisterGraphQLService(stack *node.Node, backend ethapi.Backend, filterSyst } } -// RegisterGRPCService adds the gRPC API to the node. +// RegisterGRPCExecutionService adds the gRPC API to the node. // It was done this way so that our grpc execution server can access the ethapi.Backend -func RegisterGRPCService(stack *node.Node, execServer executionv1a1.ExecutionServiceServer, cfg *node.Config) { - if err := node.NewGRPCServerHandler(stack, execServer, cfg); err != nil { +func RegisterGRPCExecutionService(stack *node.Node, execServerV1a1 executionv1a1.ExecutionServiceServer, execServerV1a2 executionv1a2.ExecutionServiceServer, cfg *node.Config) { + if err := node.NewGRPCServerHandler(stack, execServerV1a1, execServerV1a2, cfg); err != nil { Fatalf("Failed to register the gRPC service: %v", err) } } diff --git a/grpc/execution/server.go b/grpc/execution/server.go index ad561eaa70..c2e24a73b1 100644 --- a/grpc/execution/server.go +++ b/grpc/execution/server.go @@ -15,11 +15,16 @@ import ( "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth/catalyst" executionv1a1 "github.com/ethereum/go-ethereum/grpc/gen/astria/execution/v1alpha1" + executionv1a2 "github.com/ethereum/go-ethereum/grpc/gen/astria/execution/v1alpha2" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/miner" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/timestamppb" ) -// executionServiceServer is the implementation of the ExecutionServiceServer interface. -type ExecutionServiceServer struct { +// executionServiceServer is the implementation of the ExecutionServiceServerV1Alpha1 interface. +type ExecutionServiceServerV1Alpha1 struct { // NOTE - from the generated code: // All implementations must embed UnimplementedExecutionServiceServer // for forward compatibility @@ -31,19 +36,19 @@ type ExecutionServiceServer struct { bc *core.BlockChain } -func NewExecutionServiceServer(eth *eth.Ethereum) *ExecutionServiceServer { +func NewExecutionServiceServerV1Alpha1(eth *eth.Ethereum) *ExecutionServiceServerV1Alpha1 { consensus := catalyst.NewConsensusAPI(eth) bc := eth.BlockChain() - return &ExecutionServiceServer{ + return &ExecutionServiceServerV1Alpha1{ eth: eth, consensus: consensus, bc: bc, } } -func (s *ExecutionServiceServer) DoBlock(ctx context.Context, req *executionv1a1.DoBlockRequest) (*executionv1a1.DoBlockResponse, error) { +func (s *ExecutionServiceServerV1Alpha1) DoBlock(ctx context.Context, req *executionv1a1.DoBlockRequest) (*executionv1a1.DoBlockResponse, error) { log.Info("DoBlock called request", "request", req) prevHeadHash := common.BytesToHash(req.PrevBlockHash) @@ -113,7 +118,7 @@ func (s *ExecutionServiceServer) DoBlock(ctx context.Context, req *executionv1a1 return res, nil } -func (s *ExecutionServiceServer) FinalizeBlock(ctx context.Context, req *executionv1a1.FinalizeBlockRequest) (*executionv1a1.FinalizeBlockResponse, error) { +func (s *ExecutionServiceServerV1Alpha1) FinalizeBlock(ctx context.Context, req *executionv1a1.FinalizeBlockRequest) (*executionv1a1.FinalizeBlockResponse, error) { header := s.bc.GetHeaderByHash(common.BytesToHash(req.BlockHash)) if header == nil { return nil, fmt.Errorf("failed to get header for block hash 0x%x", req.BlockHash) @@ -123,11 +128,251 @@ func (s *ExecutionServiceServer) FinalizeBlock(ctx context.Context, req *executi return &executionv1a1.FinalizeBlockResponse{}, nil } -func (s *ExecutionServiceServer) InitState(ctx context.Context, req *executionv1a1.InitStateRequest) (*executionv1a1.InitStateResponse, error) { - currHead := s.eth.BlockChain().CurrentHeader() +func (s *ExecutionServiceServerV1Alpha1) InitState(ctx context.Context, req *executionv1a1.InitStateRequest) (*executionv1a1.InitStateResponse, error) { + currHead := s.bc.CurrentHeader() res := &executionv1a1.InitStateResponse{ BlockHash: currHead.Hash().Bytes(), } return res, nil } + +// ExecutionServiceServerV1Alpha2 is the implementation of the +// ExecutionServiceServer interface. +type ExecutionServiceServerV1Alpha2 struct { + // NOTE - from the generated code: All implementations must embed + // UnimplementedExecutionServiceServer for forward compatibility + executionv1a2.UnimplementedExecutionServiceServer + + eth *eth.Ethereum + bc *core.BlockChain +} + +func NewExecutionServiceServerV1Alpha2(eth *eth.Ethereum) *ExecutionServiceServerV1Alpha2 { + bc := eth.BlockChain() + + return &ExecutionServiceServerV1Alpha2{ + eth: eth, + bc: bc, + } +} + +// GetBlock will return a block given an identifier. +func (s *ExecutionServiceServerV1Alpha2) GetBlock(ctx context.Context, req *executionv1a2.GetBlockRequest) (*executionv1a2.Block, error) { + log.Info("GetBlock called", "request", req) + + res, err := s.getBlockFromIdentifier(req.GetIdentifier()) + if err != nil { + log.Error("failed finding block", err) + return nil, err + } + + log.Info("GetBlock completed", "request", req, "response", res) + return res, nil +} + +// BatchGetBlocks will return an array of Blocks given an array of block +// identifiers. +func (s *ExecutionServiceServerV1Alpha2) BatchGetBlocks(ctx context.Context, req *executionv1a2.BatchGetBlocksRequest) (*executionv1a2.BatchGetBlocksResponse, error) { + log.Info("BatchGetBlocks called", "request", req) + var blocks []*executionv1a2.Block + + ids := req.GetIdentifiers() + for _, id := range ids { + block, err := s.getBlockFromIdentifier(id) + if err != nil { + log.Error("failed finding block with id", id, "error", err) + return nil, err + } + + blocks = append(blocks, block) + } + + res := &executionv1a2.BatchGetBlocksResponse{ + Blocks: blocks, + } + + log.Info("BatchGetBlocks completed", "request", req, "response", res) + return res, nil +} + +// ExecuteBlock drives deterministic derivation of a rollup block from sequencer +// block data +func (s *ExecutionServiceServerV1Alpha2) ExecuteBlock(ctx context.Context, req *executionv1a2.ExecuteBlockRequest) (*executionv1a2.Block, error) { + log.Info("ExecuteBlock called", "request", req) + + // Validate block being created has valid previous hash + prevHeadHash := common.BytesToHash(req.PrevBlockHash) + softHash := s.bc.CurrentSafeBlock().Hash() + if prevHeadHash != softHash { + return nil, status.Error(codes.FailedPrecondition, "Block can only be created on top of soft block.") + } + + // This set of ordered TXs on the TxPool is has been configured to be used by + // the Miner when building a payload. + s.eth.TxPool().SetAstriaOrdered(req.Transactions) + + // Build a payload to add to the chain + payloadAttributes := &miner.BuildPayloadArgs{ + Parent: prevHeadHash, + Timestamp: uint64(req.GetTimestamp().GetSeconds()), + Random: common.Hash{}, + FeeRecipient: common.Address{}, + } + payload, err := s.eth.Miner().BuildPayload(payloadAttributes) + if err != nil { + log.Error("failed to build payload", "err", 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 + block, err := engine.ExecutableDataToBlock(*payload.Resolve().ExecutionPayload) + if err != nil { + log.Error("failed to convert executable data to block", err) + return nil, status.Error(codes.Internal, "failed to execute block") + } + blocks := types.Blocks{ + block, + } + n, err := s.bc.InsertChain(blocks) + if err != nil { + log.Error("failed to insert block to chain", err, "index", n) + return nil, status.Error(codes.Internal, "failed to insert block to chain") + } + + // remove txs from original mempool + for _, tx := range block.Transactions() { + s.eth.TxPool().RemoveTx(tx.Hash()) + } + + res := &executionv1a2.Block{ + Number: uint32(block.NumberU64()), + Hash: block.Hash().Bytes(), + Timestamp: ×tamppb.Timestamp{ + Seconds: int64(block.Time()), + }, + } + + log.Info("ExecuteBlock completed", "request", req, "response", res) + return res, nil +} + +// GetCommitmentState fetches the current CommitmentState of the chain. +func (s *ExecutionServiceServerV1Alpha2) GetCommitmentState(ctx context.Context, req *executionv1a2.GetCommitmentStateRequest) (*executionv1a2.CommitmentState, error) { + log.Info("GetCommitmentState called", "request", req) + + softBlock, err := ethHeaderToExecutionBlock(s.bc.CurrentSafeBlock()) + if err != nil { + log.Error("error finding safe block", err) + return nil, status.Error(codes.Internal, "could not locate soft block") + } + firmBlock, err := ethHeaderToExecutionBlock(s.bc.CurrentFinalBlock()) + if err != nil { + log.Error("error finding final block", err) + return nil, status.Error(codes.Internal, "could not locate firm block") + } + + res := &executionv1a2.CommitmentState{ + Soft: softBlock, + Firm: firmBlock, + } + + log.Info("GetCommitmentState completed", "request", req, "response", res) + return res, nil +} + +// UpdateCommitmentState replaces the whole CommitmentState with a new +// CommitmentState. +func (s *ExecutionServiceServerV1Alpha2) UpdateCommitmentState(ctx context.Context, req *executionv1a2.UpdateCommitmentStateRequest) (*executionv1a2.CommitmentState, error) { + log.Info("UpdateCommitmentState called", "request", req) + + softEthHash := common.BytesToHash(req.CommitmentState.Soft.Hash) + firmEthHash := 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 canonical chain to soft block. We must do this before last + // validation step since there is no way to check if firm block descends from + // anything but the canonical chain + if currentHead != softEthHash { + if _, err := s.bc.SetCanonical(softBlock); err != nil { + log.Error("failed updating canonical chain to soft block", err) + return nil, status.Error(codes.Internal, "Could not update head to safe hash") + } + } + + // Once head is updated validate that firm belongs to chain + if s.bc.GetCanonicalHash(firmBlock.NumberU64()) != firmEthHash { + log.Error("firm block not found in canonical chain defined by soft block, rolling back") + + // We don't want partial commitments, rolling back. + rollbackBlock := s.bc.GetBlockByHash(currentHead) + if _, err := s.bc.SetCanonical(rollbackBlock); err != nil { + panic("rollback to previous head after failed validation failed") + } + + return nil, status.Error(codes.InvalidArgument, "soft block in request is not a descendant of the current firmly committed block") + } + + // 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()) + } + + log.Info("UpdateCommitmentState completed", "request", req) + return req.CommitmentState, nil +} + +func (s *ExecutionServiceServerV1Alpha2) getBlockFromIdentifier(identifier *executionv1a2.BlockIdentifier) (*executionv1a2.Block, error) { + var header *types.Header + + // Grab the header based on the identifier provided + switch idType := identifier.Identifier.(type) { + case *executionv1a2.BlockIdentifier_BlockNumber: + header = s.bc.GetHeaderByNumber(uint64(identifier.GetBlockNumber())) + case *executionv1a2.BlockIdentifier_BlockHash: + header = s.bc.GetHeaderByHash(common.BytesToHash(identifier.GetBlockHash())) + default: + return nil, status.Errorf(codes.InvalidArgument, "identifier has unexpected type %T", idType) + } + + if header == nil { + return nil, status.Errorf(codes.NotFound, "Couldn't locate block with identifier %s", identifier.Identifier) + } + + res, err := ethHeaderToExecutionBlock(header) + if err != nil { + // This should never happen since we validate header exists above. + return nil, status.Error(codes.Internal, "internal error") + } + + return res, nil +} + +func ethHeaderToExecutionBlock(header *types.Header) (*executionv1a2.Block, error) { + if header == nil { + return nil, fmt.Errorf("cannot convert nil header to execution block") + } + + return &executionv1a2.Block{ + Number: uint32(header.Number.Int64()), + Hash: header.Hash().Bytes(), + ParentBlockHash: header.ParentHash.Bytes(), + }, nil +} diff --git a/grpc/gen/astria/execution/v1alpha2/execution.pb.go b/grpc/gen/astria/execution/v1alpha2/execution.pb.go index fefd8801e8..e62d75737f 100644 --- a/grpc/gen/astria/execution/v1alpha2/execution.pb.go +++ b/grpc/gen/astria/execution/v1alpha2/execution.pb.go @@ -21,7 +21,8 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -// The set of information which deterministic driver of execution must know about a given executed Block +// The set of information which deterministic driver of block production +// must know about a given rollup Block type Block struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -227,7 +228,8 @@ func (x *GetBlockRequest) GetIdentifier() *BlockIdentifier { return nil } -// Used in BatchGetBlocks, will find all or none based on the list of identifiers. +// Used in BatchGetBlocks, will find all or none based on the list of +// identifiers. type BatchGetBlocksRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -323,10 +325,12 @@ func (x *BatchGetBlocksResponse) GetBlocks() []*Block { return nil } -// CreateBlockRequest contains all the information needed to create a new executed block. +// ExecuteBlockRequest contains all the information needed to create a new rollup +// block. // -// This information comes from previous execution blocks, as well as from sequencer blocks. -type CreateBlockRequest struct { +// This information comes from previous rollup blocks, as well as from sequencer +// blocks. +type ExecuteBlockRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields @@ -339,8 +343,8 @@ type CreateBlockRequest struct { Timestamp *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"` } -func (x *CreateBlockRequest) Reset() { - *x = CreateBlockRequest{} +func (x *ExecuteBlockRequest) Reset() { + *x = ExecuteBlockRequest{} if protoimpl.UnsafeEnabled { mi := &file_astria_execution_v1alpha2_execution_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -348,13 +352,13 @@ func (x *CreateBlockRequest) Reset() { } } -func (x *CreateBlockRequest) String() string { +func (x *ExecuteBlockRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*CreateBlockRequest) ProtoMessage() {} +func (*ExecuteBlockRequest) ProtoMessage() {} -func (x *CreateBlockRequest) ProtoReflect() protoreflect.Message { +func (x *ExecuteBlockRequest) ProtoReflect() protoreflect.Message { mi := &file_astria_execution_v1alpha2_execution_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -366,50 +370,49 @@ func (x *CreateBlockRequest) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use CreateBlockRequest.ProtoReflect.Descriptor instead. -func (*CreateBlockRequest) Descriptor() ([]byte, []int) { +// Deprecated: Use ExecuteBlockRequest.ProtoReflect.Descriptor instead. +func (*ExecuteBlockRequest) Descriptor() ([]byte, []int) { return file_astria_execution_v1alpha2_execution_proto_rawDescGZIP(), []int{5} } -func (x *CreateBlockRequest) GetPrevBlockHash() []byte { +func (x *ExecuteBlockRequest) GetPrevBlockHash() []byte { if x != nil { return x.PrevBlockHash } return nil } -func (x *CreateBlockRequest) GetTransactions() [][]byte { +func (x *ExecuteBlockRequest) GetTransactions() [][]byte { if x != nil { return x.Transactions } return nil } -func (x *CreateBlockRequest) GetTimestamp() *timestamppb.Timestamp { +func (x *ExecuteBlockRequest) GetTimestamp() *timestamppb.Timestamp { if x != nil { return x.Timestamp } return nil } -// The CommitmentState holds the block at each stage of sequencer commitment level +// The CommitmentState holds the block at each stage of sequencer commitment +// level // // A Valid CommitmentState: -// - Block numbers are such that head >= soft >= firm. -// - Head block may either be the same as soft, or have a height 1 higher than soft. -// - No blocks ever decrease in block number, only head may stay the same and have other changes -// - The chain defined by head is the canonical chain which always contains soft and firm blocks. +// - Block numbers are such that soft >= firm. +// - No blocks ever decrease in block number. +// - The chain defined by soft is the head of the canonical chain the firm block +// must belong to. type CommitmentState struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // The head is the top of the executed chain - Head *Block `protobuf:"bytes,1,opt,name=head,proto3" json:"head,omitempty"` - // Soft commitment is the executed block matching sequencer block with full consensus. - Soft *Block `protobuf:"bytes,2,opt,name=soft,proto3" json:"soft,omitempty"` + // Soft commitment is the rollup block matching latest sequencer block. + Soft *Block `protobuf:"bytes,1,opt,name=soft,proto3" json:"soft,omitempty"` // Firm commitment is achieved when data has been seen in DA. - Firm *Block `protobuf:"bytes,3,opt,name=firm,proto3" json:"firm,omitempty"` + Firm *Block `protobuf:"bytes,2,opt,name=firm,proto3" json:"firm,omitempty"` } func (x *CommitmentState) Reset() { @@ -444,13 +447,6 @@ func (*CommitmentState) Descriptor() ([]byte, []int) { return file_astria_execution_v1alpha2_execution_proto_rawDescGZIP(), []int{6} } -func (x *CommitmentState) GetHead() *Block { - if x != nil { - return x.Head - } - return nil -} - func (x *CommitmentState) GetSoft() *Block { if x != nil { return x.Soft @@ -595,90 +591,87 @@ var file_astria_execution_v1alpha2_execution_proto_rawDesc = []byte{ 0x6f, 0x63, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x61, 0x73, 0x74, 0x72, 0x69, 0x61, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x06, 0x62, 0x6c, - 0x6f, 0x63, 0x6b, 0x73, 0x22, 0x9a, 0x01, 0x0a, 0x12, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x70, - 0x72, 0x65, 0x76, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x70, 0x72, 0x65, 0x76, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, - 0x61, 0x73, 0x68, 0x12, 0x22, 0x0a, 0x0c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0c, 0x74, 0x72, 0x61, 0x6e, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x22, 0xb3, 0x01, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x34, 0x0a, 0x04, 0x68, 0x65, 0x61, 0x64, 0x18, 0x01, 0x20, + 0x6f, 0x63, 0x6b, 0x73, 0x22, 0x9b, 0x01, 0x0a, 0x13, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0f, + 0x70, 0x72, 0x65, 0x76, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x70, 0x72, 0x65, 0x76, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x48, 0x61, 0x73, 0x68, 0x12, 0x22, 0x0a, 0x0c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0c, 0x74, 0x72, 0x61, 0x6e, + 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x22, 0x7d, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x34, 0x0a, 0x04, 0x73, 0x6f, 0x66, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x61, 0x73, 0x74, 0x72, 0x69, 0x61, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x04, 0x68, 0x65, 0x61, 0x64, 0x12, 0x34, 0x0a, 0x04, 0x73, - 0x6f, 0x66, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x61, 0x73, 0x74, 0x72, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x04, 0x73, 0x6f, 0x66, 0x74, 0x12, 0x34, 0x0a, 0x04, 0x66, + 0x69, 0x72, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x61, 0x73, 0x74, 0x72, 0x69, 0x61, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x04, 0x73, 0x6f, 0x66, - 0x74, 0x12, 0x34, 0x0a, 0x04, 0x66, 0x69, 0x72, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x20, 0x2e, 0x61, 0x73, 0x74, 0x72, 0x69, 0x61, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x52, 0x04, 0x66, 0x69, 0x72, 0x6d, 0x22, 0x1b, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x43, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x22, 0x75, 0x0a, 0x1c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x55, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, - 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, - 0x2e, 0x61, 0x73, 0x74, 0x72, 0x69, 0x61, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, - 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x32, 0xb9, 0x04, 0x0a, 0x10, - 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x58, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x2a, 0x2e, 0x61, - 0x73, 0x74, 0x72, 0x69, 0x61, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x61, 0x73, 0x74, 0x72, 0x69, + 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x04, 0x66, 0x69, 0x72, + 0x6d, 0x22, 0x1b, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, + 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x75, + 0x0a, 0x1c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, + 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x55, + 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x61, 0x73, 0x74, 0x72, 0x69, 0x61, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x32, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x75, 0x0a, 0x0e, 0x42, 0x61, - 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x30, 0x2e, 0x61, - 0x73, 0x74, 0x72, 0x69, 0x61, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, - 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, - 0x2e, 0x61, 0x73, 0x74, 0x72, 0x69, 0x61, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, - 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, - 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x5e, 0x0a, 0x0b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x12, 0x2d, 0x2e, 0x61, 0x73, 0x74, 0x72, 0x69, 0x61, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x20, 0x2e, 0x61, 0x73, 0x74, 0x72, 0x69, 0x61, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x12, 0x76, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, - 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x34, 0x2e, 0x61, 0x73, 0x74, 0x72, 0x69, 0x61, - 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, - 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, - 0x61, 0x73, 0x74, 0x72, 0x69, 0x61, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x7c, 0x0a, 0x15, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x12, 0x37, 0x2e, 0x61, 0x73, 0x74, 0x72, 0x69, 0x61, 0x2e, 0x65, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x61, 0x73, + 0x70, 0x68, 0x61, 0x32, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x32, 0xbb, 0x04, 0x0a, 0x10, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x58, 0x0a, 0x08, 0x47, 0x65, + 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x2a, 0x2e, 0x61, 0x73, 0x74, 0x72, 0x69, 0x61, 0x2e, + 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x61, 0x73, 0x74, 0x72, 0x69, 0x61, 0x2e, 0x65, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x75, 0x0a, 0x0e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x30, 0x2e, 0x61, 0x73, 0x74, 0x72, 0x69, 0x61, 0x2e, + 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x61, 0x73, 0x74, 0x72, 0x69, + 0x61, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x0c, 0x45, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x2e, 0x2e, 0x61, 0x73, 0x74, 0x72, 0x69, 0x61, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, - 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x42, 0x87, 0x02, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, - 0x61, 0x73, 0x74, 0x72, 0x69, 0x61, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x42, 0x0e, 0x45, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x50, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2f, 0x67, 0x6f, 0x2d, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2f, 0x67, 0x72, 0x70, - 0x63, 0x2f, 0x61, 0x73, 0x74, 0x72, 0x69, 0x61, 0x2f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x3b, 0x65, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0xa2, 0x02, 0x03, - 0x41, 0x45, 0x58, 0xaa, 0x02, 0x19, 0x41, 0x73, 0x74, 0x72, 0x69, 0x61, 0x2e, 0x45, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0xca, - 0x02, 0x19, 0x41, 0x73, 0x74, 0x72, 0x69, 0x61, 0x5c, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0xe2, 0x02, 0x25, 0x41, 0x73, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x61, 0x73, + 0x74, 0x72, 0x69, 0x61, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x76, 0x0a, + 0x12, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x12, 0x34, 0x2e, 0x61, 0x73, 0x74, 0x72, 0x69, 0x61, 0x2e, 0x65, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, + 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x61, 0x73, 0x74, 0x72, + 0x69, 0x61, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x7c, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x37, + 0x2e, 0x61, 0x73, 0x74, 0x72, 0x69, 0x61, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, + 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x61, 0x73, 0x74, 0x72, 0x69, 0x61, + 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x32, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x42, 0x87, 0x02, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x73, 0x74, 0x72, + 0x69, 0x61, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x32, 0x42, 0x0e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x50, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2f, 0x67, 0x6f, 0x2d, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x61, 0x73, + 0x74, 0x72, 0x69, 0x61, 0x2f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x3b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, + 0x6e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0xa2, 0x02, 0x03, 0x41, 0x45, 0x58, 0xaa, + 0x02, 0x19, 0x41, 0x73, 0x74, 0x72, 0x69, 0x61, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0xca, 0x02, 0x19, 0x41, 0x73, 0x74, 0x72, 0x69, 0x61, 0x5c, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5c, 0x56, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0xea, 0x02, 0x1b, 0x41, 0x73, 0x74, 0x72, 0x69, 0x61, 0x3a, 0x3a, 0x45, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0xe2, 0x02, 0x25, 0x41, 0x73, 0x74, 0x72, 0x69, 0x61, + 0x5c, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x32, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, + 0x02, 0x1b, 0x41, 0x73, 0x74, 0x72, 0x69, 0x61, 0x3a, 0x3a, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -700,7 +693,7 @@ var file_astria_execution_v1alpha2_execution_proto_goTypes = []interface{}{ (*GetBlockRequest)(nil), // 2: astria.execution.v1alpha2.GetBlockRequest (*BatchGetBlocksRequest)(nil), // 3: astria.execution.v1alpha2.BatchGetBlocksRequest (*BatchGetBlocksResponse)(nil), // 4: astria.execution.v1alpha2.BatchGetBlocksResponse - (*CreateBlockRequest)(nil), // 5: astria.execution.v1alpha2.CreateBlockRequest + (*ExecuteBlockRequest)(nil), // 5: astria.execution.v1alpha2.ExecuteBlockRequest (*CommitmentState)(nil), // 6: astria.execution.v1alpha2.CommitmentState (*GetCommitmentStateRequest)(nil), // 7: astria.execution.v1alpha2.GetCommitmentStateRequest (*UpdateCommitmentStateRequest)(nil), // 8: astria.execution.v1alpha2.UpdateCommitmentStateRequest @@ -711,26 +704,25 @@ var file_astria_execution_v1alpha2_execution_proto_depIdxs = []int32{ 1, // 1: astria.execution.v1alpha2.GetBlockRequest.identifier:type_name -> astria.execution.v1alpha2.BlockIdentifier 1, // 2: astria.execution.v1alpha2.BatchGetBlocksRequest.identifiers:type_name -> astria.execution.v1alpha2.BlockIdentifier 0, // 3: astria.execution.v1alpha2.BatchGetBlocksResponse.blocks:type_name -> astria.execution.v1alpha2.Block - 9, // 4: astria.execution.v1alpha2.CreateBlockRequest.timestamp:type_name -> google.protobuf.Timestamp - 0, // 5: astria.execution.v1alpha2.CommitmentState.head:type_name -> astria.execution.v1alpha2.Block - 0, // 6: astria.execution.v1alpha2.CommitmentState.soft:type_name -> astria.execution.v1alpha2.Block - 0, // 7: astria.execution.v1alpha2.CommitmentState.firm:type_name -> astria.execution.v1alpha2.Block - 6, // 8: astria.execution.v1alpha2.UpdateCommitmentStateRequest.commitment_state:type_name -> astria.execution.v1alpha2.CommitmentState - 2, // 9: astria.execution.v1alpha2.ExecutionService.GetBlock:input_type -> astria.execution.v1alpha2.GetBlockRequest - 3, // 10: astria.execution.v1alpha2.ExecutionService.BatchGetBlocks:input_type -> astria.execution.v1alpha2.BatchGetBlocksRequest - 5, // 11: astria.execution.v1alpha2.ExecutionService.CreateBlock:input_type -> astria.execution.v1alpha2.CreateBlockRequest - 7, // 12: astria.execution.v1alpha2.ExecutionService.GetCommitmentState:input_type -> astria.execution.v1alpha2.GetCommitmentStateRequest - 8, // 13: astria.execution.v1alpha2.ExecutionService.UpdateCommitmentState:input_type -> astria.execution.v1alpha2.UpdateCommitmentStateRequest - 0, // 14: astria.execution.v1alpha2.ExecutionService.GetBlock:output_type -> astria.execution.v1alpha2.Block - 4, // 15: astria.execution.v1alpha2.ExecutionService.BatchGetBlocks:output_type -> astria.execution.v1alpha2.BatchGetBlocksResponse - 0, // 16: astria.execution.v1alpha2.ExecutionService.CreateBlock:output_type -> astria.execution.v1alpha2.Block - 6, // 17: astria.execution.v1alpha2.ExecutionService.GetCommitmentState:output_type -> astria.execution.v1alpha2.CommitmentState - 6, // 18: astria.execution.v1alpha2.ExecutionService.UpdateCommitmentState:output_type -> astria.execution.v1alpha2.CommitmentState - 14, // [14:19] is the sub-list for method output_type - 9, // [9:14] is the sub-list for method input_type - 9, // [9:9] is the sub-list for extension type_name - 9, // [9:9] is the sub-list for extension extendee - 0, // [0:9] is the sub-list for field type_name + 9, // 4: astria.execution.v1alpha2.ExecuteBlockRequest.timestamp:type_name -> google.protobuf.Timestamp + 0, // 5: astria.execution.v1alpha2.CommitmentState.soft:type_name -> astria.execution.v1alpha2.Block + 0, // 6: astria.execution.v1alpha2.CommitmentState.firm:type_name -> astria.execution.v1alpha2.Block + 6, // 7: astria.execution.v1alpha2.UpdateCommitmentStateRequest.commitment_state:type_name -> astria.execution.v1alpha2.CommitmentState + 2, // 8: astria.execution.v1alpha2.ExecutionService.GetBlock:input_type -> astria.execution.v1alpha2.GetBlockRequest + 3, // 9: astria.execution.v1alpha2.ExecutionService.BatchGetBlocks:input_type -> astria.execution.v1alpha2.BatchGetBlocksRequest + 5, // 10: astria.execution.v1alpha2.ExecutionService.ExecuteBlock:input_type -> astria.execution.v1alpha2.ExecuteBlockRequest + 7, // 11: astria.execution.v1alpha2.ExecutionService.GetCommitmentState:input_type -> astria.execution.v1alpha2.GetCommitmentStateRequest + 8, // 12: astria.execution.v1alpha2.ExecutionService.UpdateCommitmentState:input_type -> astria.execution.v1alpha2.UpdateCommitmentStateRequest + 0, // 13: astria.execution.v1alpha2.ExecutionService.GetBlock:output_type -> astria.execution.v1alpha2.Block + 4, // 14: astria.execution.v1alpha2.ExecutionService.BatchGetBlocks:output_type -> astria.execution.v1alpha2.BatchGetBlocksResponse + 0, // 15: astria.execution.v1alpha2.ExecutionService.ExecuteBlock:output_type -> astria.execution.v1alpha2.Block + 6, // 16: astria.execution.v1alpha2.ExecutionService.GetCommitmentState:output_type -> astria.execution.v1alpha2.CommitmentState + 6, // 17: astria.execution.v1alpha2.ExecutionService.UpdateCommitmentState:output_type -> astria.execution.v1alpha2.CommitmentState + 13, // [13:18] is the sub-list for method output_type + 8, // [8:13] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name } func init() { file_astria_execution_v1alpha2_execution_proto_init() } @@ -800,7 +792,7 @@ func file_astria_execution_v1alpha2_execution_proto_init() { } } file_astria_execution_v1alpha2_execution_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateBlockRequest); i { + switch v := v.(*ExecuteBlockRequest); i { case 0: return &v.state case 1: diff --git a/grpc/gen/astria/execution/v1alpha2/execution_grpc.pb.go b/grpc/gen/astria/execution/v1alpha2/execution_grpc.pb.go index e8eb17887d..905f0779b0 100644 --- a/grpc/gen/astria/execution/v1alpha2/execution_grpc.pb.go +++ b/grpc/gen/astria/execution/v1alpha2/execution_grpc.pb.go @@ -21,7 +21,7 @@ const _ = grpc.SupportPackageIsVersion7 const ( ExecutionService_GetBlock_FullMethodName = "/astria.execution.v1alpha2.ExecutionService/GetBlock" ExecutionService_BatchGetBlocks_FullMethodName = "/astria.execution.v1alpha2.ExecutionService/BatchGetBlocks" - ExecutionService_CreateBlock_FullMethodName = "/astria.execution.v1alpha2.ExecutionService/CreateBlock" + ExecutionService_ExecuteBlock_FullMethodName = "/astria.execution.v1alpha2.ExecutionService/ExecuteBlock" ExecutionService_GetCommitmentState_FullMethodName = "/astria.execution.v1alpha2.ExecutionService/GetCommitmentState" ExecutionService_UpdateCommitmentState_FullMethodName = "/astria.execution.v1alpha2.ExecutionService/UpdateCommitmentState" ) @@ -32,13 +32,16 @@ const ( type ExecutionServiceClient interface { // GetBlock will return a block given an identifier. GetBlock(ctx context.Context, in *GetBlockRequest, opts ...grpc.CallOption) (*Block, error) - // BatchGetBlocks will return an array of Blocks given an array of block identifiers. + // BatchGetBlocks will return an array of Blocks given an array of block + // identifiers. BatchGetBlocks(ctx context.Context, in *BatchGetBlocksRequest, opts ...grpc.CallOption) (*BatchGetBlocksResponse, error) - // CreateBlock is used to drive deterministic creation of an executed block from a sequenced block. - CreateBlock(ctx context.Context, in *CreateBlockRequest, opts ...grpc.CallOption) (*Block, error) + // ExecuteBlock is called to deterministically derive a rollup block from + // filtered sequencer block information. + ExecuteBlock(ctx context.Context, in *ExecuteBlockRequest, opts ...grpc.CallOption) (*Block, error) // GetCommitmentState fetches the current CommitmentState of the chain. GetCommitmentState(ctx context.Context, in *GetCommitmentStateRequest, opts ...grpc.CallOption) (*CommitmentState, error) - // UpdateCommitmentState replaces the whole CommitmentState with a new CommitmentState. + // UpdateCommitmentState replaces the whole CommitmentState with a new + // CommitmentState. UpdateCommitmentState(ctx context.Context, in *UpdateCommitmentStateRequest, opts ...grpc.CallOption) (*CommitmentState, error) } @@ -68,9 +71,9 @@ func (c *executionServiceClient) BatchGetBlocks(ctx context.Context, in *BatchGe return out, nil } -func (c *executionServiceClient) CreateBlock(ctx context.Context, in *CreateBlockRequest, opts ...grpc.CallOption) (*Block, error) { +func (c *executionServiceClient) ExecuteBlock(ctx context.Context, in *ExecuteBlockRequest, opts ...grpc.CallOption) (*Block, error) { out := new(Block) - err := c.cc.Invoke(ctx, ExecutionService_CreateBlock_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, ExecutionService_ExecuteBlock_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -101,13 +104,16 @@ func (c *executionServiceClient) UpdateCommitmentState(ctx context.Context, in * type ExecutionServiceServer interface { // GetBlock will return a block given an identifier. GetBlock(context.Context, *GetBlockRequest) (*Block, error) - // BatchGetBlocks will return an array of Blocks given an array of block identifiers. + // BatchGetBlocks will return an array of Blocks given an array of block + // identifiers. BatchGetBlocks(context.Context, *BatchGetBlocksRequest) (*BatchGetBlocksResponse, error) - // CreateBlock is used to drive deterministic creation of an executed block from a sequenced block. - CreateBlock(context.Context, *CreateBlockRequest) (*Block, error) + // ExecuteBlock is called to deterministically derive a rollup block from + // filtered sequencer block information. + ExecuteBlock(context.Context, *ExecuteBlockRequest) (*Block, error) // GetCommitmentState fetches the current CommitmentState of the chain. GetCommitmentState(context.Context, *GetCommitmentStateRequest) (*CommitmentState, error) - // UpdateCommitmentState replaces the whole CommitmentState with a new CommitmentState. + // UpdateCommitmentState replaces the whole CommitmentState with a new + // CommitmentState. UpdateCommitmentState(context.Context, *UpdateCommitmentStateRequest) (*CommitmentState, error) mustEmbedUnimplementedExecutionServiceServer() } @@ -122,8 +128,8 @@ func (UnimplementedExecutionServiceServer) GetBlock(context.Context, *GetBlockRe func (UnimplementedExecutionServiceServer) BatchGetBlocks(context.Context, *BatchGetBlocksRequest) (*BatchGetBlocksResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method BatchGetBlocks not implemented") } -func (UnimplementedExecutionServiceServer) CreateBlock(context.Context, *CreateBlockRequest) (*Block, error) { - return nil, status.Errorf(codes.Unimplemented, "method CreateBlock not implemented") +func (UnimplementedExecutionServiceServer) ExecuteBlock(context.Context, *ExecuteBlockRequest) (*Block, error) { + return nil, status.Errorf(codes.Unimplemented, "method ExecuteBlock not implemented") } func (UnimplementedExecutionServiceServer) GetCommitmentState(context.Context, *GetCommitmentStateRequest) (*CommitmentState, error) { return nil, status.Errorf(codes.Unimplemented, "method GetCommitmentState not implemented") @@ -180,20 +186,20 @@ func _ExecutionService_BatchGetBlocks_Handler(srv interface{}, ctx context.Conte return interceptor(ctx, in, info, handler) } -func _ExecutionService_CreateBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(CreateBlockRequest) +func _ExecutionService_ExecuteBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ExecuteBlockRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(ExecutionServiceServer).CreateBlock(ctx, in) + return srv.(ExecutionServiceServer).ExecuteBlock(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ExecutionService_CreateBlock_FullMethodName, + FullMethod: ExecutionService_ExecuteBlock_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ExecutionServiceServer).CreateBlock(ctx, req.(*CreateBlockRequest)) + return srv.(ExecutionServiceServer).ExecuteBlock(ctx, req.(*ExecuteBlockRequest)) } return interceptor(ctx, in, info, handler) } @@ -250,8 +256,8 @@ var ExecutionService_ServiceDesc = grpc.ServiceDesc{ Handler: _ExecutionService_BatchGetBlocks_Handler, }, { - MethodName: "CreateBlock", - Handler: _ExecutionService_CreateBlock_Handler, + MethodName: "ExecuteBlock", + Handler: _ExecutionService_ExecuteBlock_Handler, }, { MethodName: "GetCommitmentState", diff --git a/miner/payload_building.go b/miner/payload_building.go index 08c772bacb..fd262dae58 100644 --- a/miner/payload_building.go +++ b/miner/payload_building.go @@ -164,12 +164,13 @@ func (w *worker) buildPayload(args *BuildPayloadArgs) (*Payload, error) { // Get the block to update with the payload block, fees, err := w.getSealingBlock(args.Parent, args.Timestamp, args.FeeRecipient, args.Random, args.Withdrawals, false) - if err == nil { - payload.update(block, fees) - log.Info("Stopping work on payload", "id", payload.id, "reason", "delivery") - return payload, nil - } else { + if err != nil { log.Info("Stopping work on payload", "id", payload.id, "reason", "failed to retrieve payload") - return payload, nil + return nil, err } + + // Add the updated block to the payload + payload.update(block, fees) + log.Info("Stopping work on payload", "id", payload.id, "reason", "delivery") + return payload, nil } diff --git a/node/grpcstack.go b/node/grpcstack.go index 5b7e8be4d4..a85ccf7a69 100644 --- a/node/grpcstack.go +++ b/node/grpcstack.go @@ -5,6 +5,7 @@ import ( "sync" executionv1a1 "github.com/ethereum/go-ethereum/grpc/gen/astria/execution/v1alpha1" + executionv1a2 "github.com/ethereum/go-ethereum/grpc/gen/astria/execution/v1alpha2" "github.com/ethereum/go-ethereum/log" "google.golang.org/grpc" ) @@ -14,26 +15,29 @@ import ( type GRPCServerHandler struct { mu sync.Mutex - endpoint string - server *grpc.Server - executionServiceServer *executionv1a1.ExecutionServiceServer + endpoint string + server *grpc.Server + executionServiceServerV1a1 *executionv1a1.ExecutionServiceServer + executionServiceServerV1a2 *executionv1a2.ExecutionServiceServer } // NewServer creates a new gRPC server. // It registers the execution service server. // It registers the gRPC server with the node so it can be stopped on shutdown. -func NewGRPCServerHandler(node *Node, execService executionv1a1.ExecutionServiceServer, cfg *Config) error { +func NewGRPCServerHandler(node *Node, execServiceV1a1 executionv1a1.ExecutionServiceServer, execServiceV1a2 executionv1a2.ExecutionServiceServer, cfg *Config) error { server := grpc.NewServer() log.Info("gRPC server enabled", "endpoint", cfg.GRPCEndpoint()) serverHandler := &GRPCServerHandler{ - endpoint: cfg.GRPCEndpoint(), - server: server, - executionServiceServer: &execService, + endpoint: cfg.GRPCEndpoint(), + server: server, + executionServiceServerV1a1: &execServiceV1a1, + executionServiceServerV1a2: &execServiceV1a2, } - executionv1a1.RegisterExecutionServiceServer(server, execService) + executionv1a1.RegisterExecutionServiceServer(server, execServiceV1a1) + executionv1a2.RegisterExecutionServiceServer(server, execServiceV1a2) node.RegisterGRPCServer(serverHandler) return nil