github.com/ava-labs/avalanchego@v1.11.11/vms/rpcchainvm/vm_server.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package rpcchainvm
     5  
     6  import (
     7  	"context"
     8  	"encoding/json"
     9  	"errors"
    10  	"fmt"
    11  	"os"
    12  	"time"
    13  
    14  	"github.com/prometheus/client_golang/prometheus"
    15  	"github.com/prometheus/client_golang/prometheus/collectors"
    16  	"google.golang.org/protobuf/types/known/emptypb"
    17  
    18  	"github.com/ava-labs/avalanchego/api/keystore/gkeystore"
    19  	"github.com/ava-labs/avalanchego/api/metrics"
    20  	"github.com/ava-labs/avalanchego/chains/atomic/gsharedmemory"
    21  	"github.com/ava-labs/avalanchego/database"
    22  	"github.com/ava-labs/avalanchego/database/corruptabledb"
    23  	"github.com/ava-labs/avalanchego/database/rpcdb"
    24  	"github.com/ava-labs/avalanchego/ids"
    25  	"github.com/ava-labs/avalanchego/ids/galiasreader"
    26  	"github.com/ava-labs/avalanchego/snow"
    27  	"github.com/ava-labs/avalanchego/snow/consensus/snowman"
    28  	"github.com/ava-labs/avalanchego/snow/engine/common"
    29  	"github.com/ava-labs/avalanchego/snow/engine/common/appsender"
    30  	"github.com/ava-labs/avalanchego/snow/engine/snowman/block"
    31  	"github.com/ava-labs/avalanchego/snow/validators/gvalidators"
    32  	"github.com/ava-labs/avalanchego/upgrade"
    33  	"github.com/ava-labs/avalanchego/utils"
    34  	"github.com/ava-labs/avalanchego/utils/crypto/bls"
    35  	"github.com/ava-labs/avalanchego/utils/logging"
    36  	"github.com/ava-labs/avalanchego/utils/wrappers"
    37  	"github.com/ava-labs/avalanchego/version"
    38  	"github.com/ava-labs/avalanchego/vms/platformvm/warp/gwarp"
    39  	"github.com/ava-labs/avalanchego/vms/rpcchainvm/ghttp"
    40  	"github.com/ava-labs/avalanchego/vms/rpcchainvm/grpcutils"
    41  	"github.com/ava-labs/avalanchego/vms/rpcchainvm/messenger"
    42  
    43  	aliasreaderpb "github.com/ava-labs/avalanchego/proto/pb/aliasreader"
    44  	appsenderpb "github.com/ava-labs/avalanchego/proto/pb/appsender"
    45  	httppb "github.com/ava-labs/avalanchego/proto/pb/http"
    46  	keystorepb "github.com/ava-labs/avalanchego/proto/pb/keystore"
    47  	messengerpb "github.com/ava-labs/avalanchego/proto/pb/messenger"
    48  	rpcdbpb "github.com/ava-labs/avalanchego/proto/pb/rpcdb"
    49  	sharedmemorypb "github.com/ava-labs/avalanchego/proto/pb/sharedmemory"
    50  	validatorstatepb "github.com/ava-labs/avalanchego/proto/pb/validatorstate"
    51  	vmpb "github.com/ava-labs/avalanchego/proto/pb/vm"
    52  	warppb "github.com/ava-labs/avalanchego/proto/pb/warp"
    53  	grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
    54  )
    55  
    56  var (
    57  	_ vmpb.VMServer = (*VMServer)(nil)
    58  
    59  	originalStderr = os.Stderr
    60  
    61  	errExpectedBlockWithVerifyContext = errors.New("expected block.WithVerifyContext")
    62  	errNilNetworkUpgradesPB           = errors.New("network upgrades protobuf is nil")
    63  )
    64  
    65  // VMServer is a VM that is managed over RPC.
    66  type VMServer struct {
    67  	vmpb.UnsafeVMServer
    68  
    69  	vm block.ChainVM
    70  	// If nil, the underlying VM doesn't implement the interface.
    71  	bVM block.BuildBlockWithContextChainVM
    72  	// If nil, the underlying VM doesn't implement the interface.
    73  	ssVM block.StateSyncableVM
    74  
    75  	allowShutdown *utils.Atomic[bool]
    76  
    77  	metrics prometheus.Gatherer
    78  	db      database.Database
    79  	log     logging.Logger
    80  
    81  	serverCloser grpcutils.ServerCloser
    82  	connCloser   wrappers.Closer
    83  
    84  	ctx    *snow.Context
    85  	closed chan struct{}
    86  }
    87  
    88  // NewServer returns a vm instance connected to a remote vm instance
    89  func NewServer(vm block.ChainVM, allowShutdown *utils.Atomic[bool]) *VMServer {
    90  	bVM, _ := vm.(block.BuildBlockWithContextChainVM)
    91  	ssVM, _ := vm.(block.StateSyncableVM)
    92  	return &VMServer{
    93  		vm:            vm,
    94  		bVM:           bVM,
    95  		ssVM:          ssVM,
    96  		allowShutdown: allowShutdown,
    97  	}
    98  }
    99  
   100  func (vm *VMServer) Initialize(ctx context.Context, req *vmpb.InitializeRequest) (*vmpb.InitializeResponse, error) {
   101  	subnetID, err := ids.ToID(req.SubnetId)
   102  	if err != nil {
   103  		return nil, err
   104  	}
   105  	chainID, err := ids.ToID(req.ChainId)
   106  	if err != nil {
   107  		return nil, err
   108  	}
   109  	nodeID, err := ids.ToNodeID(req.NodeId)
   110  	if err != nil {
   111  		return nil, err
   112  	}
   113  	publicKey, err := bls.PublicKeyFromCompressedBytes(req.PublicKey)
   114  	if err != nil {
   115  		return nil, err
   116  	}
   117  
   118  	networkUpgrades, err := convertNetworkUpgrades(req.NetworkUpgrades)
   119  	if err != nil {
   120  		return nil, err
   121  	}
   122  
   123  	xChainID, err := ids.ToID(req.XChainId)
   124  	if err != nil {
   125  		return nil, err
   126  	}
   127  	cChainID, err := ids.ToID(req.CChainId)
   128  	if err != nil {
   129  		return nil, err
   130  	}
   131  	avaxAssetID, err := ids.ToID(req.AvaxAssetId)
   132  	if err != nil {
   133  		return nil, err
   134  	}
   135  
   136  	pluginMetrics := metrics.NewPrefixGatherer()
   137  	vm.metrics = pluginMetrics
   138  
   139  	processMetrics, err := metrics.MakeAndRegister(
   140  		pluginMetrics,
   141  		"process",
   142  	)
   143  	if err != nil {
   144  		return nil, err
   145  	}
   146  
   147  	// Current state of process metrics
   148  	processCollector := collectors.NewProcessCollector(collectors.ProcessCollectorOpts{})
   149  	if err := processMetrics.Register(processCollector); err != nil {
   150  		return nil, err
   151  	}
   152  
   153  	// Go process metrics using debug.GCStats
   154  	goCollector := collectors.NewGoCollector()
   155  	if err := processMetrics.Register(goCollector); err != nil {
   156  		return nil, err
   157  	}
   158  
   159  	grpcMetrics, err := metrics.MakeAndRegister(
   160  		pluginMetrics,
   161  		"grpc",
   162  	)
   163  	if err != nil {
   164  		return nil, err
   165  	}
   166  
   167  	// gRPC client metrics
   168  	grpcClientMetrics := grpc_prometheus.NewClientMetrics()
   169  	if err := grpcMetrics.Register(grpcClientMetrics); err != nil {
   170  		return nil, err
   171  	}
   172  
   173  	vmMetrics := metrics.NewPrefixGatherer()
   174  	if err := pluginMetrics.Register("vm", vmMetrics); err != nil {
   175  		return nil, err
   176  	}
   177  
   178  	// Dial the database
   179  	dbClientConn, err := grpcutils.Dial(
   180  		req.DbServerAddr,
   181  		grpcutils.WithChainUnaryInterceptor(grpcClientMetrics.UnaryClientInterceptor()),
   182  		grpcutils.WithChainStreamInterceptor(grpcClientMetrics.StreamClientInterceptor()),
   183  	)
   184  	if err != nil {
   185  		return nil, err
   186  	}
   187  	vm.connCloser.Add(dbClientConn)
   188  	vm.db = corruptabledb.New(
   189  		rpcdb.NewClient(rpcdbpb.NewDatabaseClient(dbClientConn)),
   190  	)
   191  
   192  	// TODO: Allow the logger to be configured by the client
   193  	vm.log = logging.NewLogger(
   194  		fmt.Sprintf("<%s Chain>", chainID),
   195  		logging.NewWrappedCore(
   196  			logging.Info,
   197  			originalStderr,
   198  			logging.Colors.ConsoleEncoder(),
   199  		),
   200  	)
   201  
   202  	clientConn, err := grpcutils.Dial(
   203  		req.ServerAddr,
   204  		grpcutils.WithChainUnaryInterceptor(grpcClientMetrics.UnaryClientInterceptor()),
   205  		grpcutils.WithChainStreamInterceptor(grpcClientMetrics.StreamClientInterceptor()),
   206  	)
   207  	if err != nil {
   208  		// Ignore closing errors to return the original error
   209  		_ = vm.connCloser.Close()
   210  		return nil, err
   211  	}
   212  
   213  	vm.connCloser.Add(clientConn)
   214  
   215  	msgClient := messenger.NewClient(messengerpb.NewMessengerClient(clientConn))
   216  	keystoreClient := gkeystore.NewClient(keystorepb.NewKeystoreClient(clientConn))
   217  	sharedMemoryClient := gsharedmemory.NewClient(sharedmemorypb.NewSharedMemoryClient(clientConn))
   218  	bcLookupClient := galiasreader.NewClient(aliasreaderpb.NewAliasReaderClient(clientConn))
   219  	appSenderClient := appsender.NewClient(appsenderpb.NewAppSenderClient(clientConn))
   220  	validatorStateClient := gvalidators.NewClient(validatorstatepb.NewValidatorStateClient(clientConn))
   221  	warpSignerClient := gwarp.NewClient(warppb.NewSignerClient(clientConn))
   222  
   223  	toEngine := make(chan common.Message, 1)
   224  	vm.closed = make(chan struct{})
   225  	go func() {
   226  		for {
   227  			select {
   228  			case msg, ok := <-toEngine:
   229  				if !ok {
   230  					return
   231  				}
   232  				// Nothing to do with the error within the goroutine
   233  				_ = msgClient.Notify(msg)
   234  			case <-vm.closed:
   235  				return
   236  			}
   237  		}
   238  	}()
   239  
   240  	vm.ctx = &snow.Context{
   241  		NetworkID:       req.NetworkId,
   242  		SubnetID:        subnetID,
   243  		ChainID:         chainID,
   244  		NodeID:          nodeID,
   245  		PublicKey:       publicKey,
   246  		NetworkUpgrades: networkUpgrades,
   247  
   248  		XChainID:    xChainID,
   249  		CChainID:    cChainID,
   250  		AVAXAssetID: avaxAssetID,
   251  
   252  		Log:          vm.log,
   253  		Keystore:     keystoreClient,
   254  		SharedMemory: sharedMemoryClient,
   255  		BCLookup:     bcLookupClient,
   256  		Metrics:      vmMetrics,
   257  
   258  		// Signs warp messages
   259  		WarpSigner: warpSignerClient,
   260  
   261  		ValidatorState: validatorStateClient,
   262  		// TODO: support remaining snowman++ fields
   263  
   264  		ChainDataDir: req.ChainDataDir,
   265  	}
   266  
   267  	if err := vm.vm.Initialize(ctx, vm.ctx, vm.db, req.GenesisBytes, req.UpgradeBytes, req.ConfigBytes, toEngine, nil, appSenderClient); err != nil {
   268  		// Ignore errors closing resources to return the original error
   269  		_ = vm.connCloser.Close()
   270  		close(vm.closed)
   271  		return nil, err
   272  	}
   273  
   274  	lastAccepted, err := vm.vm.LastAccepted(ctx)
   275  	if err != nil {
   276  		// Ignore errors closing resources to return the original error
   277  		_ = vm.vm.Shutdown(ctx)
   278  		_ = vm.connCloser.Close()
   279  		close(vm.closed)
   280  		return nil, err
   281  	}
   282  
   283  	blk, err := vm.vm.GetBlock(ctx, lastAccepted)
   284  	if err != nil {
   285  		// Ignore errors closing resources to return the original error
   286  		_ = vm.vm.Shutdown(ctx)
   287  		_ = vm.connCloser.Close()
   288  		close(vm.closed)
   289  		return nil, err
   290  	}
   291  	parentID := blk.Parent()
   292  	return &vmpb.InitializeResponse{
   293  		LastAcceptedId:       lastAccepted[:],
   294  		LastAcceptedParentId: parentID[:],
   295  		Height:               blk.Height(),
   296  		Bytes:                blk.Bytes(),
   297  		Timestamp:            grpcutils.TimestampFromTime(blk.Timestamp()),
   298  	}, nil
   299  }
   300  
   301  func (vm *VMServer) SetState(ctx context.Context, stateReq *vmpb.SetStateRequest) (*vmpb.SetStateResponse, error) {
   302  	err := vm.vm.SetState(ctx, snow.State(stateReq.State))
   303  	if err != nil {
   304  		return nil, err
   305  	}
   306  
   307  	lastAccepted, err := vm.vm.LastAccepted(ctx)
   308  	if err != nil {
   309  		return nil, err
   310  	}
   311  
   312  	blk, err := vm.vm.GetBlock(ctx, lastAccepted)
   313  	if err != nil {
   314  		return nil, err
   315  	}
   316  
   317  	parentID := blk.Parent()
   318  	return &vmpb.SetStateResponse{
   319  		LastAcceptedId:       lastAccepted[:],
   320  		LastAcceptedParentId: parentID[:],
   321  		Height:               blk.Height(),
   322  		Bytes:                blk.Bytes(),
   323  		Timestamp:            grpcutils.TimestampFromTime(blk.Timestamp()),
   324  	}, nil
   325  }
   326  
   327  func (vm *VMServer) Shutdown(ctx context.Context, _ *emptypb.Empty) (*emptypb.Empty, error) {
   328  	vm.allowShutdown.Set(true)
   329  	if vm.closed == nil {
   330  		return &emptypb.Empty{}, nil
   331  	}
   332  	errs := wrappers.Errs{}
   333  	errs.Add(vm.vm.Shutdown(ctx))
   334  	close(vm.closed)
   335  	vm.serverCloser.Stop()
   336  	errs.Add(vm.connCloser.Close())
   337  	return &emptypb.Empty{}, errs.Err
   338  }
   339  
   340  func (vm *VMServer) CreateHandlers(ctx context.Context, _ *emptypb.Empty) (*vmpb.CreateHandlersResponse, error) {
   341  	handlers, err := vm.vm.CreateHandlers(ctx)
   342  	if err != nil {
   343  		return nil, err
   344  	}
   345  	resp := &vmpb.CreateHandlersResponse{}
   346  	for prefix, handler := range handlers {
   347  		serverListener, err := grpcutils.NewListener()
   348  		if err != nil {
   349  			return nil, err
   350  		}
   351  		server := grpcutils.NewServer()
   352  		vm.serverCloser.Add(server)
   353  		httppb.RegisterHTTPServer(server, ghttp.NewServer(handler))
   354  
   355  		// Start HTTP service
   356  		go grpcutils.Serve(serverListener, server)
   357  
   358  		resp.Handlers = append(resp.Handlers, &vmpb.Handler{
   359  			Prefix:     prefix,
   360  			ServerAddr: serverListener.Addr().String(),
   361  		})
   362  	}
   363  	return resp, nil
   364  }
   365  
   366  func (vm *VMServer) Connected(ctx context.Context, req *vmpb.ConnectedRequest) (*emptypb.Empty, error) {
   367  	nodeID, err := ids.ToNodeID(req.NodeId)
   368  	if err != nil {
   369  		return nil, err
   370  	}
   371  
   372  	peerVersion := &version.Application{
   373  		Name:  req.Name,
   374  		Major: int(req.Major),
   375  		Minor: int(req.Minor),
   376  		Patch: int(req.Patch),
   377  	}
   378  	return &emptypb.Empty{}, vm.vm.Connected(ctx, nodeID, peerVersion)
   379  }
   380  
   381  func (vm *VMServer) Disconnected(ctx context.Context, req *vmpb.DisconnectedRequest) (*emptypb.Empty, error) {
   382  	nodeID, err := ids.ToNodeID(req.NodeId)
   383  	if err != nil {
   384  		return nil, err
   385  	}
   386  	return &emptypb.Empty{}, vm.vm.Disconnected(ctx, nodeID)
   387  }
   388  
   389  // If the underlying VM doesn't actually implement this method, its [BuildBlock]
   390  // method will be called instead.
   391  func (vm *VMServer) BuildBlock(ctx context.Context, req *vmpb.BuildBlockRequest) (*vmpb.BuildBlockResponse, error) {
   392  	var (
   393  		blk snowman.Block
   394  		err error
   395  	)
   396  	if vm.bVM == nil || req.PChainHeight == nil {
   397  		blk, err = vm.vm.BuildBlock(ctx)
   398  	} else {
   399  		blk, err = vm.bVM.BuildBlockWithContext(ctx, &block.Context{
   400  			PChainHeight: *req.PChainHeight,
   401  		})
   402  	}
   403  	if err != nil {
   404  		return nil, err
   405  	}
   406  
   407  	blkWithCtx, verifyWithCtx := blk.(block.WithVerifyContext)
   408  	if verifyWithCtx {
   409  		verifyWithCtx, err = blkWithCtx.ShouldVerifyWithContext(ctx)
   410  		if err != nil {
   411  			return nil, err
   412  		}
   413  	}
   414  
   415  	var (
   416  		blkID    = blk.ID()
   417  		parentID = blk.Parent()
   418  	)
   419  	return &vmpb.BuildBlockResponse{
   420  		Id:                blkID[:],
   421  		ParentId:          parentID[:],
   422  		Bytes:             blk.Bytes(),
   423  		Height:            blk.Height(),
   424  		Timestamp:         grpcutils.TimestampFromTime(blk.Timestamp()),
   425  		VerifyWithContext: verifyWithCtx,
   426  	}, nil
   427  }
   428  
   429  func (vm *VMServer) ParseBlock(ctx context.Context, req *vmpb.ParseBlockRequest) (*vmpb.ParseBlockResponse, error) {
   430  	blk, err := vm.vm.ParseBlock(ctx, req.Bytes)
   431  	if err != nil {
   432  		return nil, err
   433  	}
   434  
   435  	blkWithCtx, verifyWithCtx := blk.(block.WithVerifyContext)
   436  	if verifyWithCtx {
   437  		verifyWithCtx, err = blkWithCtx.ShouldVerifyWithContext(ctx)
   438  		if err != nil {
   439  			return nil, err
   440  		}
   441  	}
   442  
   443  	var (
   444  		blkID    = blk.ID()
   445  		parentID = blk.Parent()
   446  	)
   447  	return &vmpb.ParseBlockResponse{
   448  		Id:                blkID[:],
   449  		ParentId:          parentID[:],
   450  		Height:            blk.Height(),
   451  		Timestamp:         grpcutils.TimestampFromTime(blk.Timestamp()),
   452  		VerifyWithContext: verifyWithCtx,
   453  	}, nil
   454  }
   455  
   456  func (vm *VMServer) GetBlock(ctx context.Context, req *vmpb.GetBlockRequest) (*vmpb.GetBlockResponse, error) {
   457  	id, err := ids.ToID(req.Id)
   458  	if err != nil {
   459  		return nil, err
   460  	}
   461  	blk, err := vm.vm.GetBlock(ctx, id)
   462  	if err != nil {
   463  		return &vmpb.GetBlockResponse{
   464  			Err: errorToErrEnum[err],
   465  		}, errorToRPCError(err)
   466  	}
   467  
   468  	blkWithCtx, verifyWithCtx := blk.(block.WithVerifyContext)
   469  	if verifyWithCtx {
   470  		verifyWithCtx, err = blkWithCtx.ShouldVerifyWithContext(ctx)
   471  		if err != nil {
   472  			return nil, err
   473  		}
   474  	}
   475  
   476  	parentID := blk.Parent()
   477  	return &vmpb.GetBlockResponse{
   478  		ParentId:          parentID[:],
   479  		Bytes:             blk.Bytes(),
   480  		Height:            blk.Height(),
   481  		Timestamp:         grpcutils.TimestampFromTime(blk.Timestamp()),
   482  		VerifyWithContext: verifyWithCtx,
   483  	}, nil
   484  }
   485  
   486  func (vm *VMServer) SetPreference(ctx context.Context, req *vmpb.SetPreferenceRequest) (*emptypb.Empty, error) {
   487  	id, err := ids.ToID(req.Id)
   488  	if err != nil {
   489  		return nil, err
   490  	}
   491  	return &emptypb.Empty{}, vm.vm.SetPreference(ctx, id)
   492  }
   493  
   494  func (vm *VMServer) Health(ctx context.Context, _ *emptypb.Empty) (*vmpb.HealthResponse, error) {
   495  	vmHealth, err := vm.vm.HealthCheck(ctx)
   496  	if err != nil {
   497  		return &vmpb.HealthResponse{}, err
   498  	}
   499  	dbHealth, err := vm.db.HealthCheck(ctx)
   500  	if err != nil {
   501  		return &vmpb.HealthResponse{}, err
   502  	}
   503  	report := map[string]interface{}{
   504  		"database": dbHealth,
   505  		"health":   vmHealth,
   506  	}
   507  
   508  	details, err := json.Marshal(report)
   509  	return &vmpb.HealthResponse{
   510  		Details: details,
   511  	}, err
   512  }
   513  
   514  func (vm *VMServer) Version(ctx context.Context, _ *emptypb.Empty) (*vmpb.VersionResponse, error) {
   515  	version, err := vm.vm.Version(ctx)
   516  	return &vmpb.VersionResponse{
   517  		Version: version,
   518  	}, err
   519  }
   520  
   521  func (vm *VMServer) AppRequest(ctx context.Context, req *vmpb.AppRequestMsg) (*emptypb.Empty, error) {
   522  	nodeID, err := ids.ToNodeID(req.NodeId)
   523  	if err != nil {
   524  		return nil, err
   525  	}
   526  	deadline, err := grpcutils.TimestampAsTime(req.Deadline)
   527  	if err != nil {
   528  		return nil, err
   529  	}
   530  	return &emptypb.Empty{}, vm.vm.AppRequest(ctx, nodeID, req.RequestId, deadline, req.Request)
   531  }
   532  
   533  func (vm *VMServer) AppRequestFailed(ctx context.Context, req *vmpb.AppRequestFailedMsg) (*emptypb.Empty, error) {
   534  	nodeID, err := ids.ToNodeID(req.NodeId)
   535  	if err != nil {
   536  		return nil, err
   537  	}
   538  
   539  	appErr := &common.AppError{
   540  		Code:    req.ErrorCode,
   541  		Message: req.ErrorMessage,
   542  	}
   543  	return &emptypb.Empty{}, vm.vm.AppRequestFailed(ctx, nodeID, req.RequestId, appErr)
   544  }
   545  
   546  func (vm *VMServer) AppResponse(ctx context.Context, req *vmpb.AppResponseMsg) (*emptypb.Empty, error) {
   547  	nodeID, err := ids.ToNodeID(req.NodeId)
   548  	if err != nil {
   549  		return nil, err
   550  	}
   551  	return &emptypb.Empty{}, vm.vm.AppResponse(ctx, nodeID, req.RequestId, req.Response)
   552  }
   553  
   554  func (vm *VMServer) AppGossip(ctx context.Context, req *vmpb.AppGossipMsg) (*emptypb.Empty, error) {
   555  	nodeID, err := ids.ToNodeID(req.NodeId)
   556  	if err != nil {
   557  		return nil, err
   558  	}
   559  	return &emptypb.Empty{}, vm.vm.AppGossip(ctx, nodeID, req.Msg)
   560  }
   561  
   562  func (vm *VMServer) Gather(context.Context, *emptypb.Empty) (*vmpb.GatherResponse, error) {
   563  	metrics, err := vm.metrics.Gather()
   564  	return &vmpb.GatherResponse{MetricFamilies: metrics}, err
   565  }
   566  
   567  func (vm *VMServer) GetAncestors(ctx context.Context, req *vmpb.GetAncestorsRequest) (*vmpb.GetAncestorsResponse, error) {
   568  	blkID, err := ids.ToID(req.BlkId)
   569  	if err != nil {
   570  		return nil, err
   571  	}
   572  	maxBlksNum := int(req.MaxBlocksNum)
   573  	maxBlksSize := int(req.MaxBlocksSize)
   574  	maxBlocksRetrivalTime := time.Duration(req.MaxBlocksRetrivalTime)
   575  
   576  	blocks, err := block.GetAncestors(
   577  		ctx,
   578  		vm.log,
   579  		vm.vm,
   580  		blkID,
   581  		maxBlksNum,
   582  		maxBlksSize,
   583  		maxBlocksRetrivalTime,
   584  	)
   585  	return &vmpb.GetAncestorsResponse{
   586  		BlksBytes: blocks,
   587  	}, err
   588  }
   589  
   590  func (vm *VMServer) BatchedParseBlock(
   591  	ctx context.Context,
   592  	req *vmpb.BatchedParseBlockRequest,
   593  ) (*vmpb.BatchedParseBlockResponse, error) {
   594  	blocks := make([]*vmpb.ParseBlockResponse, len(req.Request))
   595  	for i, blockBytes := range req.Request {
   596  		block, err := vm.ParseBlock(ctx, &vmpb.ParseBlockRequest{
   597  			Bytes: blockBytes,
   598  		})
   599  		if err != nil {
   600  			return nil, err
   601  		}
   602  		blocks[i] = block
   603  	}
   604  	return &vmpb.BatchedParseBlockResponse{
   605  		Response: blocks,
   606  	}, nil
   607  }
   608  
   609  func (vm *VMServer) GetBlockIDAtHeight(
   610  	ctx context.Context,
   611  	req *vmpb.GetBlockIDAtHeightRequest,
   612  ) (*vmpb.GetBlockIDAtHeightResponse, error) {
   613  	blkID, err := vm.vm.GetBlockIDAtHeight(ctx, req.Height)
   614  	return &vmpb.GetBlockIDAtHeightResponse{
   615  		BlkId: blkID[:],
   616  		Err:   errorToErrEnum[err],
   617  	}, errorToRPCError(err)
   618  }
   619  
   620  func (vm *VMServer) StateSyncEnabled(ctx context.Context, _ *emptypb.Empty) (*vmpb.StateSyncEnabledResponse, error) {
   621  	var (
   622  		enabled bool
   623  		err     error
   624  	)
   625  	if vm.ssVM != nil {
   626  		enabled, err = vm.ssVM.StateSyncEnabled(ctx)
   627  	}
   628  
   629  	return &vmpb.StateSyncEnabledResponse{
   630  		Enabled: enabled,
   631  		Err:     errorToErrEnum[err],
   632  	}, errorToRPCError(err)
   633  }
   634  
   635  func (vm *VMServer) GetOngoingSyncStateSummary(
   636  	ctx context.Context,
   637  	_ *emptypb.Empty,
   638  ) (*vmpb.GetOngoingSyncStateSummaryResponse, error) {
   639  	var (
   640  		summary block.StateSummary
   641  		err     error
   642  	)
   643  	if vm.ssVM != nil {
   644  		summary, err = vm.ssVM.GetOngoingSyncStateSummary(ctx)
   645  	} else {
   646  		err = block.ErrStateSyncableVMNotImplemented
   647  	}
   648  
   649  	if err != nil {
   650  		return &vmpb.GetOngoingSyncStateSummaryResponse{
   651  			Err: errorToErrEnum[err],
   652  		}, errorToRPCError(err)
   653  	}
   654  
   655  	summaryID := summary.ID()
   656  	return &vmpb.GetOngoingSyncStateSummaryResponse{
   657  		Id:     summaryID[:],
   658  		Height: summary.Height(),
   659  		Bytes:  summary.Bytes(),
   660  	}, nil
   661  }
   662  
   663  func (vm *VMServer) GetLastStateSummary(ctx context.Context, _ *emptypb.Empty) (*vmpb.GetLastStateSummaryResponse, error) {
   664  	var (
   665  		summary block.StateSummary
   666  		err     error
   667  	)
   668  	if vm.ssVM != nil {
   669  		summary, err = vm.ssVM.GetLastStateSummary(ctx)
   670  	} else {
   671  		err = block.ErrStateSyncableVMNotImplemented
   672  	}
   673  
   674  	if err != nil {
   675  		return &vmpb.GetLastStateSummaryResponse{
   676  			Err: errorToErrEnum[err],
   677  		}, errorToRPCError(err)
   678  	}
   679  
   680  	summaryID := summary.ID()
   681  	return &vmpb.GetLastStateSummaryResponse{
   682  		Id:     summaryID[:],
   683  		Height: summary.Height(),
   684  		Bytes:  summary.Bytes(),
   685  	}, nil
   686  }
   687  
   688  func (vm *VMServer) ParseStateSummary(
   689  	ctx context.Context,
   690  	req *vmpb.ParseStateSummaryRequest,
   691  ) (*vmpb.ParseStateSummaryResponse, error) {
   692  	var (
   693  		summary block.StateSummary
   694  		err     error
   695  	)
   696  	if vm.ssVM != nil {
   697  		summary, err = vm.ssVM.ParseStateSummary(ctx, req.Bytes)
   698  	} else {
   699  		err = block.ErrStateSyncableVMNotImplemented
   700  	}
   701  
   702  	if err != nil {
   703  		return &vmpb.ParseStateSummaryResponse{
   704  			Err: errorToErrEnum[err],
   705  		}, errorToRPCError(err)
   706  	}
   707  
   708  	summaryID := summary.ID()
   709  	return &vmpb.ParseStateSummaryResponse{
   710  		Id:     summaryID[:],
   711  		Height: summary.Height(),
   712  	}, nil
   713  }
   714  
   715  func (vm *VMServer) GetStateSummary(
   716  	ctx context.Context,
   717  	req *vmpb.GetStateSummaryRequest,
   718  ) (*vmpb.GetStateSummaryResponse, error) {
   719  	var (
   720  		summary block.StateSummary
   721  		err     error
   722  	)
   723  	if vm.ssVM != nil {
   724  		summary, err = vm.ssVM.GetStateSummary(ctx, req.Height)
   725  	} else {
   726  		err = block.ErrStateSyncableVMNotImplemented
   727  	}
   728  
   729  	if err != nil {
   730  		return &vmpb.GetStateSummaryResponse{
   731  			Err: errorToErrEnum[err],
   732  		}, errorToRPCError(err)
   733  	}
   734  
   735  	summaryID := summary.ID()
   736  	return &vmpb.GetStateSummaryResponse{
   737  		Id:    summaryID[:],
   738  		Bytes: summary.Bytes(),
   739  	}, nil
   740  }
   741  
   742  func (vm *VMServer) BlockVerify(ctx context.Context, req *vmpb.BlockVerifyRequest) (*vmpb.BlockVerifyResponse, error) {
   743  	blk, err := vm.vm.ParseBlock(ctx, req.Bytes)
   744  	if err != nil {
   745  		return nil, err
   746  	}
   747  
   748  	if req.PChainHeight == nil {
   749  		err = blk.Verify(ctx)
   750  	} else {
   751  		blkWithCtx, ok := blk.(block.WithVerifyContext)
   752  		if !ok {
   753  			return nil, fmt.Errorf("%w but got %T", errExpectedBlockWithVerifyContext, blk)
   754  		}
   755  		blockCtx := &block.Context{
   756  			PChainHeight: *req.PChainHeight,
   757  		}
   758  		err = blkWithCtx.VerifyWithContext(ctx, blockCtx)
   759  	}
   760  	if err != nil {
   761  		return nil, err
   762  	}
   763  
   764  	return &vmpb.BlockVerifyResponse{
   765  		Timestamp: grpcutils.TimestampFromTime(blk.Timestamp()),
   766  	}, nil
   767  }
   768  
   769  func (vm *VMServer) BlockAccept(ctx context.Context, req *vmpb.BlockAcceptRequest) (*emptypb.Empty, error) {
   770  	id, err := ids.ToID(req.Id)
   771  	if err != nil {
   772  		return nil, err
   773  	}
   774  	blk, err := vm.vm.GetBlock(ctx, id)
   775  	if err != nil {
   776  		return nil, err
   777  	}
   778  	if err := blk.Accept(ctx); err != nil {
   779  		return nil, err
   780  	}
   781  	return &emptypb.Empty{}, nil
   782  }
   783  
   784  func (vm *VMServer) BlockReject(ctx context.Context, req *vmpb.BlockRejectRequest) (*emptypb.Empty, error) {
   785  	id, err := ids.ToID(req.Id)
   786  	if err != nil {
   787  		return nil, err
   788  	}
   789  	blk, err := vm.vm.GetBlock(ctx, id)
   790  	if err != nil {
   791  		return nil, err
   792  	}
   793  	if err := blk.Reject(ctx); err != nil {
   794  		return nil, err
   795  	}
   796  	return &emptypb.Empty{}, nil
   797  }
   798  
   799  func (vm *VMServer) StateSummaryAccept(
   800  	ctx context.Context,
   801  	req *vmpb.StateSummaryAcceptRequest,
   802  ) (*vmpb.StateSummaryAcceptResponse, error) {
   803  	var (
   804  		mode = block.StateSyncSkipped
   805  		err  error
   806  	)
   807  	if vm.ssVM != nil {
   808  		var summary block.StateSummary
   809  		summary, err = vm.ssVM.ParseStateSummary(ctx, req.Bytes)
   810  		if err == nil {
   811  			mode, err = summary.Accept(ctx)
   812  		}
   813  	} else {
   814  		err = block.ErrStateSyncableVMNotImplemented
   815  	}
   816  
   817  	return &vmpb.StateSummaryAcceptResponse{
   818  		Mode: vmpb.StateSummaryAcceptResponse_Mode(mode),
   819  		Err:  errorToErrEnum[err],
   820  	}, errorToRPCError(err)
   821  }
   822  
   823  func convertNetworkUpgrades(pbUpgrades *vmpb.NetworkUpgrades) (upgrade.Config, error) {
   824  	if pbUpgrades == nil {
   825  		return upgrade.Config{}, errNilNetworkUpgradesPB
   826  	}
   827  
   828  	ap1, err := grpcutils.TimestampAsTime(pbUpgrades.ApricotPhase_1Time)
   829  	if err != nil {
   830  		return upgrade.Config{}, err
   831  	}
   832  	ap2, err := grpcutils.TimestampAsTime(pbUpgrades.ApricotPhase_2Time)
   833  	if err != nil {
   834  		return upgrade.Config{}, err
   835  	}
   836  	ap3, err := grpcutils.TimestampAsTime(pbUpgrades.ApricotPhase_3Time)
   837  	if err != nil {
   838  		return upgrade.Config{}, err
   839  	}
   840  	ap4, err := grpcutils.TimestampAsTime(pbUpgrades.ApricotPhase_4Time)
   841  	if err != nil {
   842  		return upgrade.Config{}, err
   843  	}
   844  	ap5, err := grpcutils.TimestampAsTime(pbUpgrades.ApricotPhase_5Time)
   845  	if err != nil {
   846  		return upgrade.Config{}, err
   847  	}
   848  	apPre6, err := grpcutils.TimestampAsTime(pbUpgrades.ApricotPhasePre_6Time)
   849  	if err != nil {
   850  		return upgrade.Config{}, err
   851  	}
   852  	ap6, err := grpcutils.TimestampAsTime(pbUpgrades.ApricotPhase_6Time)
   853  	if err != nil {
   854  		return upgrade.Config{}, err
   855  	}
   856  	apPost6, err := grpcutils.TimestampAsTime(pbUpgrades.ApricotPhasePost_6Time)
   857  	if err != nil {
   858  		return upgrade.Config{}, err
   859  	}
   860  	banff, err := grpcutils.TimestampAsTime(pbUpgrades.BanffTime)
   861  	if err != nil {
   862  		return upgrade.Config{}, err
   863  	}
   864  	cortina, err := grpcutils.TimestampAsTime(pbUpgrades.CortinaTime)
   865  	if err != nil {
   866  		return upgrade.Config{}, err
   867  	}
   868  	durango, err := grpcutils.TimestampAsTime(pbUpgrades.DurangoTime)
   869  	if err != nil {
   870  		return upgrade.Config{}, err
   871  	}
   872  	etna, err := grpcutils.TimestampAsTime(pbUpgrades.EtnaTime)
   873  	if err != nil {
   874  		return upgrade.Config{}, err
   875  	}
   876  
   877  	cortinaXChainStopVertexID, err := ids.ToID(pbUpgrades.CortinaXChainStopVertexId)
   878  	if err != nil {
   879  		return upgrade.Config{}, err
   880  	}
   881  
   882  	return upgrade.Config{
   883  		ApricotPhase1Time:            ap1,
   884  		ApricotPhase2Time:            ap2,
   885  		ApricotPhase3Time:            ap3,
   886  		ApricotPhase4Time:            ap4,
   887  		ApricotPhase4MinPChainHeight: pbUpgrades.ApricotPhase_4MinPChainHeight,
   888  		ApricotPhase5Time:            ap5,
   889  		ApricotPhasePre6Time:         apPre6,
   890  		ApricotPhase6Time:            ap6,
   891  		ApricotPhasePost6Time:        apPost6,
   892  		BanffTime:                    banff,
   893  		CortinaTime:                  cortina,
   894  		CortinaXChainStopVertexID:    cortinaXChainStopVertexID,
   895  		DurangoTime:                  durango,
   896  		EtnaTime:                     etna,
   897  	}, nil
   898  }