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 }