github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/access/handler.go (about) 1 package access 2 3 import ( 4 "context" 5 6 "google.golang.org/grpc/codes" 7 "google.golang.org/grpc/status" 8 "google.golang.org/protobuf/types/known/timestamppb" 9 10 "github.com/onflow/flow-go/consensus/hotstuff" 11 "github.com/onflow/flow-go/consensus/hotstuff/signature" 12 "github.com/onflow/flow-go/engine/access/subscription" 13 "github.com/onflow/flow-go/engine/common/rpc" 14 "github.com/onflow/flow-go/engine/common/rpc/convert" 15 "github.com/onflow/flow-go/model/flow" 16 "github.com/onflow/flow-go/module" 17 "github.com/onflow/flow-go/module/counters" 18 19 "github.com/onflow/flow/protobuf/go/flow/access" 20 "github.com/onflow/flow/protobuf/go/flow/entities" 21 ) 22 23 type Handler struct { 24 subscription.StreamingData 25 api API 26 chain flow.Chain 27 signerIndicesDecoder hotstuff.BlockSignerDecoder 28 finalizedHeaderCache module.FinalizedHeaderCache 29 me module.Local 30 } 31 32 // HandlerOption is used to hand over optional constructor parameters 33 type HandlerOption func(*Handler) 34 35 var _ access.AccessAPIServer = (*Handler)(nil) 36 37 // sendSubscribeBlocksResponseFunc is a callback function used to send 38 // SubscribeBlocksResponse to the client stream. 39 type sendSubscribeBlocksResponseFunc func(*access.SubscribeBlocksResponse) error 40 41 // sendSubscribeBlockHeadersResponseFunc is a callback function used to send 42 // SubscribeBlockHeadersResponse to the client stream. 43 type sendSubscribeBlockHeadersResponseFunc func(*access.SubscribeBlockHeadersResponse) error 44 45 // sendSubscribeBlockDigestsResponseFunc is a callback function used to send 46 // SubscribeBlockDigestsResponse to the client stream. 47 type sendSubscribeBlockDigestsResponseFunc func(*access.SubscribeBlockDigestsResponse) error 48 49 func NewHandler( 50 api API, 51 chain flow.Chain, 52 finalizedHeader module.FinalizedHeaderCache, 53 me module.Local, 54 maxStreams uint32, 55 options ...HandlerOption, 56 ) *Handler { 57 h := &Handler{ 58 StreamingData: subscription.NewStreamingData(maxStreams), 59 api: api, 60 chain: chain, 61 finalizedHeaderCache: finalizedHeader, 62 me: me, 63 signerIndicesDecoder: &signature.NoopBlockSignerDecoder{}, 64 } 65 for _, opt := range options { 66 opt(h) 67 } 68 return h 69 } 70 71 // Ping the Access API server for a response. 72 func (h *Handler) Ping(ctx context.Context, _ *access.PingRequest) (*access.PingResponse, error) { 73 err := h.api.Ping(ctx) 74 if err != nil { 75 return nil, err 76 } 77 78 return &access.PingResponse{}, nil 79 } 80 81 // GetNodeVersionInfo gets node version information such as semver, commit, sporkID, protocolVersion, etc 82 func (h *Handler) GetNodeVersionInfo( 83 ctx context.Context, 84 _ *access.GetNodeVersionInfoRequest, 85 ) (*access.GetNodeVersionInfoResponse, error) { 86 nodeVersionInfo, err := h.api.GetNodeVersionInfo(ctx) 87 if err != nil { 88 return nil, err 89 } 90 91 return &access.GetNodeVersionInfoResponse{ 92 Info: &entities.NodeVersionInfo{ 93 Semver: nodeVersionInfo.Semver, 94 Commit: nodeVersionInfo.Commit, 95 SporkId: nodeVersionInfo.SporkId[:], 96 ProtocolVersion: nodeVersionInfo.ProtocolVersion, 97 SporkRootBlockHeight: nodeVersionInfo.SporkRootBlockHeight, 98 NodeRootBlockHeight: nodeVersionInfo.NodeRootBlockHeight, 99 }, 100 }, nil 101 } 102 103 func (h *Handler) GetNetworkParameters( 104 ctx context.Context, 105 _ *access.GetNetworkParametersRequest, 106 ) (*access.GetNetworkParametersResponse, error) { 107 params := h.api.GetNetworkParameters(ctx) 108 109 return &access.GetNetworkParametersResponse{ 110 ChainId: string(params.ChainID), 111 }, nil 112 } 113 114 // GetLatestBlockHeader gets the latest sealed block header. 115 func (h *Handler) GetLatestBlockHeader( 116 ctx context.Context, 117 req *access.GetLatestBlockHeaderRequest, 118 ) (*access.BlockHeaderResponse, error) { 119 header, status, err := h.api.GetLatestBlockHeader(ctx, req.GetIsSealed()) 120 if err != nil { 121 return nil, err 122 } 123 return h.blockHeaderResponse(header, status) 124 } 125 126 // GetBlockHeaderByHeight gets a block header by height. 127 func (h *Handler) GetBlockHeaderByHeight( 128 ctx context.Context, 129 req *access.GetBlockHeaderByHeightRequest, 130 ) (*access.BlockHeaderResponse, error) { 131 header, status, err := h.api.GetBlockHeaderByHeight(ctx, req.GetHeight()) 132 if err != nil { 133 return nil, err 134 } 135 return h.blockHeaderResponse(header, status) 136 } 137 138 // GetBlockHeaderByID gets a block header by ID. 139 func (h *Handler) GetBlockHeaderByID( 140 ctx context.Context, 141 req *access.GetBlockHeaderByIDRequest, 142 ) (*access.BlockHeaderResponse, error) { 143 id, err := convert.BlockID(req.GetId()) 144 if err != nil { 145 return nil, status.Errorf(codes.InvalidArgument, "invalid block id: %v", err) 146 } 147 header, status, err := h.api.GetBlockHeaderByID(ctx, id) 148 if err != nil { 149 return nil, err 150 } 151 return h.blockHeaderResponse(header, status) 152 } 153 154 // GetLatestBlock gets the latest sealed block. 155 func (h *Handler) GetLatestBlock( 156 ctx context.Context, 157 req *access.GetLatestBlockRequest, 158 ) (*access.BlockResponse, error) { 159 block, status, err := h.api.GetLatestBlock(ctx, req.GetIsSealed()) 160 if err != nil { 161 return nil, err 162 } 163 return h.blockResponse(block, req.GetFullBlockResponse(), status) 164 } 165 166 // GetBlockByHeight gets a block by height. 167 func (h *Handler) GetBlockByHeight( 168 ctx context.Context, 169 req *access.GetBlockByHeightRequest, 170 ) (*access.BlockResponse, error) { 171 block, status, err := h.api.GetBlockByHeight(ctx, req.GetHeight()) 172 if err != nil { 173 return nil, err 174 } 175 return h.blockResponse(block, req.GetFullBlockResponse(), status) 176 } 177 178 // GetBlockByID gets a block by ID. 179 func (h *Handler) GetBlockByID( 180 ctx context.Context, 181 req *access.GetBlockByIDRequest, 182 ) (*access.BlockResponse, error) { 183 id, err := convert.BlockID(req.GetId()) 184 if err != nil { 185 return nil, status.Errorf(codes.InvalidArgument, "invalid block id: %v", err) 186 } 187 block, status, err := h.api.GetBlockByID(ctx, id) 188 if err != nil { 189 return nil, err 190 } 191 return h.blockResponse(block, req.GetFullBlockResponse(), status) 192 } 193 194 // GetCollectionByID gets a collection by ID. 195 func (h *Handler) GetCollectionByID( 196 ctx context.Context, 197 req *access.GetCollectionByIDRequest, 198 ) (*access.CollectionResponse, error) { 199 metadata := h.buildMetadataResponse() 200 201 id, err := convert.CollectionID(req.GetId()) 202 if err != nil { 203 return nil, status.Errorf(codes.InvalidArgument, "invalid collection id: %v", err) 204 } 205 206 col, err := h.api.GetCollectionByID(ctx, id) 207 if err != nil { 208 return nil, err 209 } 210 211 colMsg, err := convert.LightCollectionToMessage(col) 212 if err != nil { 213 return nil, status.Error(codes.Internal, err.Error()) 214 } 215 216 return &access.CollectionResponse{ 217 Collection: colMsg, 218 Metadata: metadata, 219 }, nil 220 } 221 222 // SendTransaction submits a transaction to the network. 223 func (h *Handler) SendTransaction( 224 ctx context.Context, 225 req *access.SendTransactionRequest, 226 ) (*access.SendTransactionResponse, error) { 227 metadata := h.buildMetadataResponse() 228 229 txMsg := req.GetTransaction() 230 231 tx, err := convert.MessageToTransaction(txMsg, h.chain) 232 if err != nil { 233 return nil, status.Error(codes.InvalidArgument, err.Error()) 234 } 235 236 err = h.api.SendTransaction(ctx, &tx) 237 if err != nil { 238 return nil, err 239 } 240 241 txID := tx.ID() 242 243 return &access.SendTransactionResponse{ 244 Id: txID[:], 245 Metadata: metadata, 246 }, nil 247 } 248 249 // GetTransaction gets a transaction by ID. 250 func (h *Handler) GetTransaction( 251 ctx context.Context, 252 req *access.GetTransactionRequest, 253 ) (*access.TransactionResponse, error) { 254 metadata := h.buildMetadataResponse() 255 256 id, err := convert.TransactionID(req.GetId()) 257 if err != nil { 258 return nil, status.Errorf(codes.InvalidArgument, "invalid transaction id: %v", err) 259 } 260 261 tx, err := h.api.GetTransaction(ctx, id) 262 if err != nil { 263 return nil, err 264 } 265 266 return &access.TransactionResponse{ 267 Transaction: convert.TransactionToMessage(*tx), 268 Metadata: metadata, 269 }, nil 270 } 271 272 // GetTransactionResult gets a transaction by ID. 273 func (h *Handler) GetTransactionResult( 274 ctx context.Context, 275 req *access.GetTransactionRequest, 276 ) (*access.TransactionResultResponse, error) { 277 metadata := h.buildMetadataResponse() 278 279 transactionID, err := convert.TransactionID(req.GetId()) 280 if err != nil { 281 return nil, status.Errorf(codes.InvalidArgument, "invalid transaction id: %v", err) 282 } 283 284 blockId := flow.ZeroID 285 requestBlockId := req.GetBlockId() 286 if requestBlockId != nil { 287 blockId, err = convert.BlockID(requestBlockId) 288 if err != nil { 289 return nil, status.Errorf(codes.InvalidArgument, "invalid block id: %v", err) 290 } 291 } 292 293 collectionId := flow.ZeroID 294 requestCollectionId := req.GetCollectionId() 295 if requestCollectionId != nil { 296 collectionId, err = convert.CollectionID(requestCollectionId) 297 if err != nil { 298 return nil, status.Errorf(codes.InvalidArgument, "invalid collection id: %v", err) 299 } 300 } 301 302 eventEncodingVersion := req.GetEventEncodingVersion() 303 result, err := h.api.GetTransactionResult(ctx, transactionID, blockId, collectionId, eventEncodingVersion) 304 if err != nil { 305 return nil, err 306 } 307 308 message := TransactionResultToMessage(result) 309 message.Metadata = metadata 310 311 return message, nil 312 } 313 314 func (h *Handler) GetTransactionResultsByBlockID( 315 ctx context.Context, 316 req *access.GetTransactionsByBlockIDRequest, 317 ) (*access.TransactionResultsResponse, error) { 318 metadata := h.buildMetadataResponse() 319 320 id, err := convert.BlockID(req.GetBlockId()) 321 if err != nil { 322 return nil, status.Errorf(codes.InvalidArgument, "invalid block id: %v", err) 323 } 324 325 eventEncodingVersion := req.GetEventEncodingVersion() 326 327 results, err := h.api.GetTransactionResultsByBlockID(ctx, id, eventEncodingVersion) 328 if err != nil { 329 return nil, err 330 } 331 332 message := TransactionResultsToMessage(results) 333 message.Metadata = metadata 334 335 return message, nil 336 } 337 338 func (h *Handler) GetSystemTransaction( 339 ctx context.Context, 340 req *access.GetSystemTransactionRequest, 341 ) (*access.TransactionResponse, error) { 342 metadata := h.buildMetadataResponse() 343 344 id, err := convert.BlockID(req.GetBlockId()) 345 if err != nil { 346 return nil, status.Errorf(codes.InvalidArgument, "invalid block id: %v", err) 347 } 348 349 tx, err := h.api.GetSystemTransaction(ctx, id) 350 if err != nil { 351 return nil, err 352 } 353 354 return &access.TransactionResponse{ 355 Transaction: convert.TransactionToMessage(*tx), 356 Metadata: metadata, 357 }, nil 358 } 359 360 func (h *Handler) GetSystemTransactionResult( 361 ctx context.Context, 362 req *access.GetSystemTransactionResultRequest, 363 ) (*access.TransactionResultResponse, error) { 364 metadata := h.buildMetadataResponse() 365 366 id, err := convert.BlockID(req.GetBlockId()) 367 if err != nil { 368 return nil, status.Errorf(codes.InvalidArgument, "invalid block id: %v", err) 369 } 370 371 result, err := h.api.GetSystemTransactionResult(ctx, id, req.GetEventEncodingVersion()) 372 if err != nil { 373 return nil, err 374 } 375 376 message := TransactionResultToMessage(result) 377 message.Metadata = metadata 378 379 return message, nil 380 } 381 382 func (h *Handler) GetTransactionsByBlockID( 383 ctx context.Context, 384 req *access.GetTransactionsByBlockIDRequest, 385 ) (*access.TransactionsResponse, error) { 386 metadata := h.buildMetadataResponse() 387 388 id, err := convert.BlockID(req.GetBlockId()) 389 if err != nil { 390 return nil, status.Errorf(codes.InvalidArgument, "invalid block id: %v", err) 391 } 392 393 transactions, err := h.api.GetTransactionsByBlockID(ctx, id) 394 if err != nil { 395 return nil, err 396 } 397 398 return &access.TransactionsResponse{ 399 Transactions: convert.TransactionsToMessages(transactions), 400 Metadata: metadata, 401 }, nil 402 } 403 404 // GetTransactionResultByIndex gets a transaction at a specific index for in a block that is executed, 405 // pending or finalized transactions return errors 406 func (h *Handler) GetTransactionResultByIndex( 407 ctx context.Context, 408 req *access.GetTransactionByIndexRequest, 409 ) (*access.TransactionResultResponse, error) { 410 metadata := h.buildMetadataResponse() 411 412 blockID, err := convert.BlockID(req.GetBlockId()) 413 if err != nil { 414 return nil, status.Errorf(codes.InvalidArgument, "invalid block id: %v", err) 415 } 416 417 eventEncodingVersion := req.GetEventEncodingVersion() 418 419 result, err := h.api.GetTransactionResultByIndex(ctx, blockID, req.GetIndex(), eventEncodingVersion) 420 if err != nil { 421 return nil, err 422 } 423 424 message := TransactionResultToMessage(result) 425 message.Metadata = metadata 426 427 return message, nil 428 } 429 430 // GetAccount returns an account by address at the latest sealed block. 431 func (h *Handler) GetAccount( 432 ctx context.Context, 433 req *access.GetAccountRequest, 434 ) (*access.GetAccountResponse, error) { 435 metadata := h.buildMetadataResponse() 436 437 address, err := convert.Address(req.GetAddress(), h.chain) 438 if err != nil { 439 return nil, status.Errorf(codes.InvalidArgument, "invalid address: %v", err) 440 } 441 442 account, err := h.api.GetAccount(ctx, address) 443 if err != nil { 444 return nil, err 445 } 446 447 accountMsg, err := convert.AccountToMessage(account) 448 if err != nil { 449 return nil, status.Error(codes.Internal, err.Error()) 450 } 451 452 return &access.GetAccountResponse{ 453 Account: accountMsg, 454 Metadata: metadata, 455 }, nil 456 } 457 458 // GetAccountAtLatestBlock returns an account by address at the latest sealed block. 459 func (h *Handler) GetAccountAtLatestBlock( 460 ctx context.Context, 461 req *access.GetAccountAtLatestBlockRequest, 462 ) (*access.AccountResponse, error) { 463 metadata := h.buildMetadataResponse() 464 465 address, err := convert.Address(req.GetAddress(), h.chain) 466 if err != nil { 467 return nil, status.Errorf(codes.InvalidArgument, "invalid address: %v", err) 468 } 469 470 account, err := h.api.GetAccountAtLatestBlock(ctx, address) 471 if err != nil { 472 return nil, err 473 } 474 475 accountMsg, err := convert.AccountToMessage(account) 476 if err != nil { 477 return nil, status.Error(codes.Internal, err.Error()) 478 } 479 480 return &access.AccountResponse{ 481 Account: accountMsg, 482 Metadata: metadata, 483 }, nil 484 } 485 486 func (h *Handler) GetAccountAtBlockHeight( 487 ctx context.Context, 488 req *access.GetAccountAtBlockHeightRequest, 489 ) (*access.AccountResponse, error) { 490 metadata := h.buildMetadataResponse() 491 492 address, err := convert.Address(req.GetAddress(), h.chain) 493 if err != nil { 494 return nil, status.Errorf(codes.InvalidArgument, "invalid address: %v", err) 495 } 496 497 account, err := h.api.GetAccountAtBlockHeight(ctx, address, req.GetBlockHeight()) 498 if err != nil { 499 return nil, err 500 } 501 502 accountMsg, err := convert.AccountToMessage(account) 503 if err != nil { 504 return nil, status.Error(codes.Internal, err.Error()) 505 } 506 507 return &access.AccountResponse{ 508 Account: accountMsg, 509 Metadata: metadata, 510 }, nil 511 } 512 513 // ExecuteScriptAtLatestBlock executes a script at a the latest block. 514 func (h *Handler) ExecuteScriptAtLatestBlock( 515 ctx context.Context, 516 req *access.ExecuteScriptAtLatestBlockRequest, 517 ) (*access.ExecuteScriptResponse, error) { 518 metadata := h.buildMetadataResponse() 519 520 script := req.GetScript() 521 arguments := req.GetArguments() 522 523 value, err := h.api.ExecuteScriptAtLatestBlock(ctx, script, arguments) 524 if err != nil { 525 return nil, err 526 } 527 528 return &access.ExecuteScriptResponse{ 529 Value: value, 530 Metadata: metadata, 531 }, nil 532 } 533 534 // ExecuteScriptAtBlockHeight executes a script at a specific block height. 535 func (h *Handler) ExecuteScriptAtBlockHeight( 536 ctx context.Context, 537 req *access.ExecuteScriptAtBlockHeightRequest, 538 ) (*access.ExecuteScriptResponse, error) { 539 metadata := h.buildMetadataResponse() 540 541 script := req.GetScript() 542 arguments := req.GetArguments() 543 blockHeight := req.GetBlockHeight() 544 545 value, err := h.api.ExecuteScriptAtBlockHeight(ctx, blockHeight, script, arguments) 546 if err != nil { 547 return nil, err 548 } 549 550 return &access.ExecuteScriptResponse{ 551 Value: value, 552 Metadata: metadata, 553 }, nil 554 } 555 556 // ExecuteScriptAtBlockID executes a script at a specific block ID. 557 func (h *Handler) ExecuteScriptAtBlockID( 558 ctx context.Context, 559 req *access.ExecuteScriptAtBlockIDRequest, 560 ) (*access.ExecuteScriptResponse, error) { 561 metadata := h.buildMetadataResponse() 562 563 script := req.GetScript() 564 arguments := req.GetArguments() 565 blockID := convert.MessageToIdentifier(req.GetBlockId()) 566 567 value, err := h.api.ExecuteScriptAtBlockID(ctx, blockID, script, arguments) 568 if err != nil { 569 return nil, err 570 } 571 572 return &access.ExecuteScriptResponse{ 573 Value: value, 574 Metadata: metadata, 575 }, nil 576 } 577 578 // GetEventsForHeightRange returns events matching a query. 579 func (h *Handler) GetEventsForHeightRange( 580 ctx context.Context, 581 req *access.GetEventsForHeightRangeRequest, 582 ) (*access.EventsResponse, error) { 583 metadata := h.buildMetadataResponse() 584 585 eventType, err := convert.EventType(req.GetType()) 586 if err != nil { 587 return nil, err 588 } 589 590 startHeight := req.GetStartHeight() 591 endHeight := req.GetEndHeight() 592 593 eventEncodingVersion := req.GetEventEncodingVersion() 594 595 results, err := h.api.GetEventsForHeightRange(ctx, eventType, startHeight, endHeight, eventEncodingVersion) 596 if err != nil { 597 return nil, err 598 } 599 600 resultEvents, err := convert.BlockEventsToMessages(results) 601 if err != nil { 602 return nil, err 603 } 604 return &access.EventsResponse{ 605 Results: resultEvents, 606 Metadata: metadata, 607 }, nil 608 } 609 610 // GetEventsForBlockIDs returns events matching a set of block IDs. 611 func (h *Handler) GetEventsForBlockIDs( 612 ctx context.Context, 613 req *access.GetEventsForBlockIDsRequest, 614 ) (*access.EventsResponse, error) { 615 metadata := h.buildMetadataResponse() 616 617 eventType, err := convert.EventType(req.GetType()) 618 if err != nil { 619 return nil, err 620 } 621 622 blockIDs, err := convert.BlockIDs(req.GetBlockIds()) 623 if err != nil { 624 return nil, err 625 } 626 627 eventEncodingVersion := req.GetEventEncodingVersion() 628 629 results, err := h.api.GetEventsForBlockIDs(ctx, eventType, blockIDs, eventEncodingVersion) 630 if err != nil { 631 return nil, err 632 } 633 634 resultEvents, err := convert.BlockEventsToMessages(results) 635 if err != nil { 636 return nil, err 637 } 638 639 return &access.EventsResponse{ 640 Results: resultEvents, 641 Metadata: metadata, 642 }, nil 643 } 644 645 // GetLatestProtocolStateSnapshot returns the latest serializable Snapshot 646 func (h *Handler) GetLatestProtocolStateSnapshot(ctx context.Context, req *access.GetLatestProtocolStateSnapshotRequest) (*access.ProtocolStateSnapshotResponse, error) { 647 metadata := h.buildMetadataResponse() 648 649 snapshot, err := h.api.GetLatestProtocolStateSnapshot(ctx) 650 if err != nil { 651 return nil, err 652 } 653 654 return &access.ProtocolStateSnapshotResponse{ 655 SerializedSnapshot: snapshot, 656 Metadata: metadata, 657 }, nil 658 } 659 660 // GetProtocolStateSnapshotByBlockID returns serializable Snapshot by blockID 661 func (h *Handler) GetProtocolStateSnapshotByBlockID(ctx context.Context, req *access.GetProtocolStateSnapshotByBlockIDRequest) (*access.ProtocolStateSnapshotResponse, error) { 662 metadata := h.buildMetadataResponse() 663 664 blockID := convert.MessageToIdentifier(req.GetBlockId()) 665 666 snapshot, err := h.api.GetProtocolStateSnapshotByBlockID(ctx, blockID) 667 if err != nil { 668 return nil, err 669 } 670 671 return &access.ProtocolStateSnapshotResponse{ 672 SerializedSnapshot: snapshot, 673 Metadata: metadata, 674 }, nil 675 } 676 677 // GetProtocolStateSnapshotByHeight returns serializable Snapshot by block height 678 func (h *Handler) GetProtocolStateSnapshotByHeight(ctx context.Context, req *access.GetProtocolStateSnapshotByHeightRequest) (*access.ProtocolStateSnapshotResponse, error) { 679 metadata := h.buildMetadataResponse() 680 681 snapshot, err := h.api.GetProtocolStateSnapshotByHeight(ctx, req.GetBlockHeight()) 682 if err != nil { 683 return nil, err 684 } 685 686 return &access.ProtocolStateSnapshotResponse{ 687 SerializedSnapshot: snapshot, 688 Metadata: metadata, 689 }, nil 690 } 691 692 // GetExecutionResultForBlockID returns the latest received execution result for the given block ID. 693 // AN might receive multiple receipts with conflicting results for unsealed blocks. 694 // If this case happens, since AN is not able to determine which result is the correct one until the block is sealed, it has to pick one result to respond to this query. For now, we return the result from the latest received receipt. 695 func (h *Handler) GetExecutionResultForBlockID(ctx context.Context, req *access.GetExecutionResultForBlockIDRequest) (*access.ExecutionResultForBlockIDResponse, error) { 696 metadata := h.buildMetadataResponse() 697 698 blockID := convert.MessageToIdentifier(req.GetBlockId()) 699 700 result, err := h.api.GetExecutionResultForBlockID(ctx, blockID) 701 if err != nil { 702 return nil, err 703 } 704 705 return executionResultToMessages(result, metadata) 706 } 707 708 // GetExecutionResultByID returns the execution result for the given ID. 709 func (h *Handler) GetExecutionResultByID(ctx context.Context, req *access.GetExecutionResultByIDRequest) (*access.ExecutionResultByIDResponse, error) { 710 metadata := h.buildMetadataResponse() 711 712 resultID := convert.MessageToIdentifier(req.GetId()) 713 714 result, err := h.api.GetExecutionResultByID(ctx, resultID) 715 if err != nil { 716 return nil, err 717 } 718 719 execResult, err := convert.ExecutionResultToMessage(result) 720 if err != nil { 721 return nil, err 722 } 723 return &access.ExecutionResultByIDResponse{ 724 ExecutionResult: execResult, 725 Metadata: metadata, 726 }, nil 727 } 728 729 // SubscribeBlocksFromStartBlockID handles subscription requests for blocks started from block id. 730 // It takes a SubscribeBlocksFromStartBlockIDRequest and an AccessAPI_SubscribeBlocksFromStartBlockIDServer stream as input. 731 // The handler manages the subscription to block updates and sends the subscribed block information 732 // to the client via the provided stream. 733 // 734 // Expected errors during normal operation: 735 // - codes.InvalidArgument - if invalid startBlockID provided or unknown block status provided. 736 // - codes.ResourceExhausted - if the maximum number of streams is reached. 737 // - codes.Internal - if stream encountered an error, if stream got unexpected response or could not convert block to message or could not send response. 738 func (h *Handler) SubscribeBlocksFromStartBlockID(request *access.SubscribeBlocksFromStartBlockIDRequest, stream access.AccessAPI_SubscribeBlocksFromStartBlockIDServer) error { 739 // check if the maximum number of streams is reached 740 if h.StreamCount.Load() >= h.MaxStreams { 741 return status.Errorf(codes.ResourceExhausted, "maximum number of streams reached") 742 } 743 h.StreamCount.Add(1) 744 defer h.StreamCount.Add(-1) 745 746 startBlockID, blockStatus, err := h.getSubscriptionDataFromStartBlockID(request.GetStartBlockId(), request.GetBlockStatus()) 747 if err != nil { 748 return err 749 } 750 751 sub := h.api.SubscribeBlocksFromStartBlockID(stream.Context(), startBlockID, blockStatus) 752 return subscription.HandleSubscription(sub, h.handleBlocksResponse(stream.Send, request.GetFullBlockResponse(), blockStatus)) 753 } 754 755 // SubscribeBlocksFromStartHeight handles subscription requests for blocks started from block height. 756 // It takes a SubscribeBlocksFromStartHeightRequest and an AccessAPI_SubscribeBlocksFromStartHeightServer stream as input. 757 // The handler manages the subscription to block updates and sends the subscribed block information 758 // to the client via the provided stream. 759 // 760 // Expected errors during normal operation: 761 // - codes.InvalidArgument - if unknown block status provided. 762 // - codes.ResourceExhausted - if the maximum number of streams is reached. 763 // - codes.Internal - if stream encountered an error, if stream got unexpected response or could not convert block to message or could not send response. 764 func (h *Handler) SubscribeBlocksFromStartHeight(request *access.SubscribeBlocksFromStartHeightRequest, stream access.AccessAPI_SubscribeBlocksFromStartHeightServer) error { 765 // check if the maximum number of streams is reached 766 if h.StreamCount.Load() >= h.MaxStreams { 767 return status.Errorf(codes.ResourceExhausted, "maximum number of streams reached") 768 } 769 h.StreamCount.Add(1) 770 defer h.StreamCount.Add(-1) 771 772 blockStatus := convert.MessageToBlockStatus(request.GetBlockStatus()) 773 err := checkBlockStatus(blockStatus) 774 if err != nil { 775 return err 776 } 777 778 sub := h.api.SubscribeBlocksFromStartHeight(stream.Context(), request.GetStartBlockHeight(), blockStatus) 779 return subscription.HandleSubscription(sub, h.handleBlocksResponse(stream.Send, request.GetFullBlockResponse(), blockStatus)) 780 } 781 782 // SubscribeBlocksFromLatest handles subscription requests for blocks started from latest sealed block. 783 // It takes a SubscribeBlocksFromLatestRequest and an AccessAPI_SubscribeBlocksFromLatestServer stream as input. 784 // The handler manages the subscription to block updates and sends the subscribed block information 785 // to the client via the provided stream. 786 // 787 // Expected errors during normal operation: 788 // - codes.InvalidArgument - if unknown block status provided. 789 // - codes.ResourceExhausted - if the maximum number of streams is reached. 790 // - codes.Internal - if stream encountered an error, if stream got unexpected response or could not convert block to message or could not send response. 791 func (h *Handler) SubscribeBlocksFromLatest(request *access.SubscribeBlocksFromLatestRequest, stream access.AccessAPI_SubscribeBlocksFromLatestServer) error { 792 // check if the maximum number of streams is reached 793 if h.StreamCount.Load() >= h.MaxStreams { 794 return status.Errorf(codes.ResourceExhausted, "maximum number of streams reached") 795 } 796 h.StreamCount.Add(1) 797 defer h.StreamCount.Add(-1) 798 799 blockStatus := convert.MessageToBlockStatus(request.GetBlockStatus()) 800 err := checkBlockStatus(blockStatus) 801 if err != nil { 802 return err 803 } 804 805 sub := h.api.SubscribeBlocksFromLatest(stream.Context(), blockStatus) 806 return subscription.HandleSubscription(sub, h.handleBlocksResponse(stream.Send, request.GetFullBlockResponse(), blockStatus)) 807 } 808 809 // handleBlocksResponse handles the subscription to block updates and sends 810 // the subscribed block information to the client via the provided stream. 811 // 812 // Parameters: 813 // - send: The function responsible for sending the block response to the client. 814 // - fullBlockResponse: A boolean indicating whether to include full block responses. 815 // - blockStatus: The current block status. 816 // 817 // Returns a function that can be used as a callback for block updates. 818 // 819 // This function is designed to be used as a callback for block updates in a subscription. 820 // It takes a block, processes it, and sends the corresponding response to the client using the provided send function. 821 // 822 // Expected errors during normal operation: 823 // - codes.Internal: If cannot convert a block to a message or the stream could not send a response. 824 func (h *Handler) handleBlocksResponse(send sendSubscribeBlocksResponseFunc, fullBlockResponse bool, blockStatus flow.BlockStatus) func(*flow.Block) error { 825 return func(block *flow.Block) error { 826 msgBlockResponse, err := h.blockResponse(block, fullBlockResponse, blockStatus) 827 if err != nil { 828 return rpc.ConvertError(err, "could not convert block to message", codes.Internal) 829 } 830 831 err = send(&access.SubscribeBlocksResponse{ 832 Block: msgBlockResponse.Block, 833 }) 834 if err != nil { 835 return rpc.ConvertError(err, "could not send response", codes.Internal) 836 } 837 838 return nil 839 } 840 } 841 842 // SubscribeBlockHeadersFromStartBlockID handles subscription requests for block headers started from block id. 843 // It takes a SubscribeBlockHeadersFromStartBlockIDRequest and an AccessAPI_SubscribeBlockHeadersFromStartBlockIDServer stream as input. 844 // The handler manages the subscription to block updates and sends the subscribed block header information 845 // to the client via the provided stream. 846 // 847 // Expected errors during normal operation: 848 // - codes.InvalidArgument - if invalid startBlockID provided or unknown block status provided. 849 // - codes.ResourceExhausted - if the maximum number of streams is reached. 850 // - codes.Internal - if stream encountered an error, if stream got unexpected response or could not convert block header to message or could not send response. 851 func (h *Handler) SubscribeBlockHeadersFromStartBlockID(request *access.SubscribeBlockHeadersFromStartBlockIDRequest, stream access.AccessAPI_SubscribeBlockHeadersFromStartBlockIDServer) error { 852 // check if the maximum number of streams is reached 853 if h.StreamCount.Load() >= h.MaxStreams { 854 return status.Errorf(codes.ResourceExhausted, "maximum number of streams reached") 855 } 856 h.StreamCount.Add(1) 857 defer h.StreamCount.Add(-1) 858 859 startBlockID, blockStatus, err := h.getSubscriptionDataFromStartBlockID(request.GetStartBlockId(), request.GetBlockStatus()) 860 if err != nil { 861 return err 862 } 863 864 sub := h.api.SubscribeBlockHeadersFromStartBlockID(stream.Context(), startBlockID, blockStatus) 865 return subscription.HandleSubscription(sub, h.handleBlockHeadersResponse(stream.Send)) 866 } 867 868 // SubscribeBlockHeadersFromStartHeight handles subscription requests for block headers started from block height. 869 // It takes a SubscribeBlockHeadersFromStartHeightRequest and an AccessAPI_SubscribeBlockHeadersFromStartHeightServer stream as input. 870 // The handler manages the subscription to block updates and sends the subscribed block header information 871 // to the client via the provided stream. 872 // 873 // Expected errors during normal operation: 874 // - codes.InvalidArgument - if unknown block status provided. 875 // - codes.ResourceExhausted - if the maximum number of streams is reached. 876 // - codes.Internal - if stream encountered an error, if stream got unexpected response or could not convert block header to message or could not send response. 877 func (h *Handler) SubscribeBlockHeadersFromStartHeight(request *access.SubscribeBlockHeadersFromStartHeightRequest, stream access.AccessAPI_SubscribeBlockHeadersFromStartHeightServer) error { 878 // check if the maximum number of streams is reached 879 if h.StreamCount.Load() >= h.MaxStreams { 880 return status.Errorf(codes.ResourceExhausted, "maximum number of streams reached") 881 } 882 h.StreamCount.Add(1) 883 defer h.StreamCount.Add(-1) 884 885 blockStatus := convert.MessageToBlockStatus(request.GetBlockStatus()) 886 err := checkBlockStatus(blockStatus) 887 if err != nil { 888 return err 889 } 890 891 sub := h.api.SubscribeBlockHeadersFromStartHeight(stream.Context(), request.GetStartBlockHeight(), blockStatus) 892 return subscription.HandleSubscription(sub, h.handleBlockHeadersResponse(stream.Send)) 893 } 894 895 // SubscribeBlockHeadersFromLatest handles subscription requests for block headers started from latest sealed block. 896 // It takes a SubscribeBlockHeadersFromLatestRequest and an AccessAPI_SubscribeBlockHeadersFromLatestServer stream as input. 897 // The handler manages the subscription to block updates and sends the subscribed block header information 898 // to the client via the provided stream. 899 // 900 // Expected errors during normal operation: 901 // - codes.InvalidArgument - if unknown block status provided. 902 // - codes.ResourceExhausted - if the maximum number of streams is reached. 903 // - codes.Internal - if stream encountered an error, if stream got unexpected response or could not convert block header to message or could not send response. 904 func (h *Handler) SubscribeBlockHeadersFromLatest(request *access.SubscribeBlockHeadersFromLatestRequest, stream access.AccessAPI_SubscribeBlockHeadersFromLatestServer) error { 905 // check if the maximum number of streams is reached 906 if h.StreamCount.Load() >= h.MaxStreams { 907 return status.Errorf(codes.ResourceExhausted, "maximum number of streams reached") 908 } 909 h.StreamCount.Add(1) 910 defer h.StreamCount.Add(-1) 911 912 blockStatus := convert.MessageToBlockStatus(request.GetBlockStatus()) 913 err := checkBlockStatus(blockStatus) 914 if err != nil { 915 return err 916 } 917 918 sub := h.api.SubscribeBlockHeadersFromLatest(stream.Context(), blockStatus) 919 return subscription.HandleSubscription(sub, h.handleBlockHeadersResponse(stream.Send)) 920 } 921 922 // handleBlockHeadersResponse handles the subscription to block updates and sends 923 // the subscribed block header information to the client via the provided stream. 924 // 925 // Parameters: 926 // - send: The function responsible for sending the block header response to the client. 927 // 928 // Returns a function that can be used as a callback for block header updates. 929 // 930 // This function is designed to be used as a callback for block header updates in a subscription. 931 // It takes a block header, processes it, and sends the corresponding response to the client using the provided send function. 932 // 933 // Expected errors during normal operation: 934 // - codes.Internal: If could not decode the signer indices from the given block header, could not convert a block header to a message or the stream could not send a response. 935 func (h *Handler) handleBlockHeadersResponse(send sendSubscribeBlockHeadersResponseFunc) func(*flow.Header) error { 936 return func(header *flow.Header) error { 937 signerIDs, err := h.signerIndicesDecoder.DecodeSignerIDs(header) 938 if err != nil { 939 return rpc.ConvertError(err, "could not decode the signer indices from the given block header", codes.Internal) // the block was retrieved from local storage - so no errors are expected 940 } 941 942 msgHeader, err := convert.BlockHeaderToMessage(header, signerIDs) 943 if err != nil { 944 return rpc.ConvertError(err, "could not convert block header to message", codes.Internal) 945 } 946 947 err = send(&access.SubscribeBlockHeadersResponse{ 948 Header: msgHeader, 949 }) 950 if err != nil { 951 return rpc.ConvertError(err, "could not send response", codes.Internal) 952 } 953 954 return nil 955 } 956 } 957 958 // SubscribeBlockDigestsFromStartBlockID streams finalized or sealed lightweight block starting at the requested block id. 959 // It takes a SubscribeBlockDigestsFromStartBlockIDRequest and an AccessAPI_SubscribeBlockDigestsFromStartBlockIDServer stream as input. 960 // 961 // Expected errors during normal operation: 962 // - codes.InvalidArgument - if invalid startBlockID provided or unknown block status provided, 963 // - codes.ResourceExhausted - if the maximum number of streams is reached. 964 // - codes.Internal - if stream encountered an error, if stream got unexpected response or could not convert block to message or could not send response. 965 func (h *Handler) SubscribeBlockDigestsFromStartBlockID(request *access.SubscribeBlockDigestsFromStartBlockIDRequest, stream access.AccessAPI_SubscribeBlockDigestsFromStartBlockIDServer) error { 966 // check if the maximum number of streams is reached 967 if h.StreamCount.Load() >= h.MaxStreams { 968 return status.Errorf(codes.ResourceExhausted, "maximum number of streams reached") 969 } 970 h.StreamCount.Add(1) 971 defer h.StreamCount.Add(-1) 972 973 startBlockID, blockStatus, err := h.getSubscriptionDataFromStartBlockID(request.GetStartBlockId(), request.GetBlockStatus()) 974 if err != nil { 975 return err 976 } 977 978 sub := h.api.SubscribeBlockDigestsFromStartBlockID(stream.Context(), startBlockID, blockStatus) 979 return subscription.HandleSubscription(sub, h.handleBlockDigestsResponse(stream.Send)) 980 } 981 982 // SubscribeBlockDigestsFromStartHeight handles subscription requests for lightweight blocks started from block height. 983 // It takes a SubscribeBlockDigestsFromStartHeightRequest and an AccessAPI_SubscribeBlockDigestsFromStartHeightServer stream as input. 984 // The handler manages the subscription to block updates and sends the subscribed block information 985 // to the client via the provided stream. 986 // 987 // Expected errors during normal operation: 988 // - codes.InvalidArgument - if unknown block status provided. 989 // - codes.ResourceExhausted - if the maximum number of streams is reached. 990 // - codes.Internal - if stream encountered an error, if stream got unexpected response or could not convert block to message or could not send response. 991 func (h *Handler) SubscribeBlockDigestsFromStartHeight(request *access.SubscribeBlockDigestsFromStartHeightRequest, stream access.AccessAPI_SubscribeBlockDigestsFromStartHeightServer) error { 992 // check if the maximum number of streams is reached 993 if h.StreamCount.Load() >= h.MaxStreams { 994 return status.Errorf(codes.ResourceExhausted, "maximum number of streams reached") 995 } 996 h.StreamCount.Add(1) 997 defer h.StreamCount.Add(-1) 998 999 blockStatus := convert.MessageToBlockStatus(request.GetBlockStatus()) 1000 err := checkBlockStatus(blockStatus) 1001 if err != nil { 1002 return err 1003 } 1004 1005 sub := h.api.SubscribeBlockDigestsFromStartHeight(stream.Context(), request.GetStartBlockHeight(), blockStatus) 1006 return subscription.HandleSubscription(sub, h.handleBlockDigestsResponse(stream.Send)) 1007 } 1008 1009 // SubscribeBlockDigestsFromLatest handles subscription requests for lightweight block started from latest sealed block. 1010 // It takes a SubscribeBlockDigestsFromLatestRequest and an AccessAPI_SubscribeBlockDigestsFromLatestServer stream as input. 1011 // The handler manages the subscription to block updates and sends the subscribed block header information 1012 // to the client via the provided stream. 1013 // 1014 // Expected errors during normal operation: 1015 // - codes.InvalidArgument - if unknown block status provided. 1016 // - codes.ResourceExhausted - if the maximum number of streams is reached. 1017 // - codes.Internal - if stream encountered an error, if stream got unexpected response or could not convert block to message or could not send response. 1018 func (h *Handler) SubscribeBlockDigestsFromLatest(request *access.SubscribeBlockDigestsFromLatestRequest, stream access.AccessAPI_SubscribeBlockDigestsFromLatestServer) error { 1019 // check if the maximum number of streams is reached 1020 if h.StreamCount.Load() >= h.MaxStreams { 1021 return status.Errorf(codes.ResourceExhausted, "maximum number of streams reached") 1022 } 1023 h.StreamCount.Add(1) 1024 defer h.StreamCount.Add(-1) 1025 1026 blockStatus := convert.MessageToBlockStatus(request.GetBlockStatus()) 1027 err := checkBlockStatus(blockStatus) 1028 if err != nil { 1029 return err 1030 } 1031 1032 sub := h.api.SubscribeBlockDigestsFromLatest(stream.Context(), blockStatus) 1033 return subscription.HandleSubscription(sub, h.handleBlockDigestsResponse(stream.Send)) 1034 } 1035 1036 // handleBlockDigestsResponse handles the subscription to block updates and sends 1037 // the subscribed block digest information to the client via the provided stream. 1038 // 1039 // Parameters: 1040 // - send: The function responsible for sending the block digest response to the client. 1041 // 1042 // Returns a function that can be used as a callback for block digest updates. 1043 // 1044 // This function is designed to be used as a callback for block digest updates in a subscription. 1045 // It takes a block digest, processes it, and sends the corresponding response to the client using the provided send function. 1046 // 1047 // Expected errors during normal operation: 1048 // - codes.Internal: if the stream cannot send a response. 1049 func (h *Handler) handleBlockDigestsResponse(send sendSubscribeBlockDigestsResponseFunc) func(*flow.BlockDigest) error { 1050 return func(blockDigest *flow.BlockDigest) error { 1051 err := send(&access.SubscribeBlockDigestsResponse{ 1052 BlockId: convert.IdentifierToMessage(blockDigest.ID()), 1053 BlockHeight: blockDigest.Height, 1054 BlockTimestamp: timestamppb.New(blockDigest.Timestamp), 1055 }) 1056 if err != nil { 1057 return rpc.ConvertError(err, "could not send response", codes.Internal) 1058 } 1059 1060 return nil 1061 } 1062 } 1063 1064 // getSubscriptionDataFromStartBlockID processes subscription start data from start block id. 1065 // It takes a union representing the start block id and a BlockStatus from the entities package. 1066 // Performs validation of input data and returns it in expected format for further processing. 1067 // 1068 // Returns: 1069 // - flow.Identifier: The start block id for searching. 1070 // - flow.BlockStatus: Block status. 1071 // - error: An error indicating the result of the operation, if any. 1072 // 1073 // Expected errors during normal operation: 1074 // - codes.InvalidArgument: If blockStatus is flow.BlockStatusUnknown, or startBlockID could not convert to flow.Identifier. 1075 func (h *Handler) getSubscriptionDataFromStartBlockID(msgBlockId []byte, msgBlockStatus entities.BlockStatus) (flow.Identifier, flow.BlockStatus, error) { 1076 startBlockID, err := convert.BlockID(msgBlockId) 1077 if err != nil { 1078 return flow.ZeroID, flow.BlockStatusUnknown, err 1079 } 1080 1081 blockStatus := convert.MessageToBlockStatus(msgBlockStatus) 1082 err = checkBlockStatus(blockStatus) 1083 if err != nil { 1084 return flow.ZeroID, flow.BlockStatusUnknown, err 1085 } 1086 1087 return startBlockID, blockStatus, nil 1088 } 1089 1090 // SendAndSubscribeTransactionStatuses streams transaction statuses starting from the reference block saved in the 1091 // transaction itself until the block containing the transaction becomes sealed or expired. When the transaction 1092 // status becomes TransactionStatusSealed or TransactionStatusExpired, the subscription will automatically shut down. 1093 func (h *Handler) SendAndSubscribeTransactionStatuses( 1094 request *access.SendAndSubscribeTransactionStatusesRequest, 1095 stream access.AccessAPI_SendAndSubscribeTransactionStatusesServer, 1096 ) error { 1097 ctx := stream.Context() 1098 1099 // check if the maximum number of streams is reached 1100 if h.StreamCount.Load() >= h.MaxStreams { 1101 return status.Errorf(codes.ResourceExhausted, "maximum number of streams reached") 1102 } 1103 h.StreamCount.Add(1) 1104 defer h.StreamCount.Add(-1) 1105 1106 tx, err := convert.MessageToTransaction(request.GetTransaction(), h.chain) 1107 if err != nil { 1108 return status.Error(codes.InvalidArgument, err.Error()) 1109 } 1110 1111 err = h.api.SendTransaction(ctx, &tx) 1112 if err != nil { 1113 return err 1114 } 1115 1116 sub := h.api.SubscribeTransactionStatuses(ctx, &tx, request.GetEventEncodingVersion()) 1117 1118 messageIndex := counters.NewMonotonousCounter(0) 1119 return subscription.HandleSubscription(sub, func(txResults []*TransactionResult) error { 1120 for i := range txResults { 1121 value := messageIndex.Increment() 1122 1123 err = stream.Send(&access.SendAndSubscribeTransactionStatusesResponse{ 1124 TransactionResults: TransactionResultToMessage(txResults[i]), 1125 MessageIndex: value, 1126 }) 1127 if err != nil { 1128 return rpc.ConvertError(err, "could not send response", codes.Internal) 1129 } 1130 } 1131 1132 return nil 1133 }) 1134 } 1135 1136 func (h *Handler) blockResponse(block *flow.Block, fullResponse bool, status flow.BlockStatus) (*access.BlockResponse, error) { 1137 metadata := h.buildMetadataResponse() 1138 1139 signerIDs, err := h.signerIndicesDecoder.DecodeSignerIDs(block.Header) 1140 if err != nil { 1141 return nil, err // the block was retrieved from local storage - so no errors are expected 1142 } 1143 1144 var msg *entities.Block 1145 if fullResponse { 1146 msg, err = convert.BlockToMessage(block, signerIDs) 1147 if err != nil { 1148 return nil, rpc.ConvertError(err, "could not convert block to message", codes.Internal) 1149 } 1150 } else { 1151 msg = convert.BlockToMessageLight(block) 1152 } 1153 1154 return &access.BlockResponse{ 1155 Block: msg, 1156 BlockStatus: entities.BlockStatus(status), 1157 Metadata: metadata, 1158 }, nil 1159 } 1160 1161 func (h *Handler) blockHeaderResponse(header *flow.Header, status flow.BlockStatus) (*access.BlockHeaderResponse, error) { 1162 metadata := h.buildMetadataResponse() 1163 1164 signerIDs, err := h.signerIndicesDecoder.DecodeSignerIDs(header) 1165 if err != nil { 1166 return nil, err // the block was retrieved from local storage - so no errors are expected 1167 } 1168 1169 msg, err := convert.BlockHeaderToMessage(header, signerIDs) 1170 if err != nil { 1171 return nil, rpc.ConvertError(err, "could not convert block header to message", codes.Internal) 1172 } 1173 1174 return &access.BlockHeaderResponse{ 1175 Block: msg, 1176 BlockStatus: entities.BlockStatus(status), 1177 Metadata: metadata, 1178 }, nil 1179 } 1180 1181 // buildMetadataResponse builds and returns the metadata response object. 1182 func (h *Handler) buildMetadataResponse() *entities.Metadata { 1183 lastFinalizedHeader := h.finalizedHeaderCache.Get() 1184 blockId := lastFinalizedHeader.ID() 1185 nodeId := h.me.NodeID() 1186 1187 return &entities.Metadata{ 1188 LatestFinalizedBlockId: blockId[:], 1189 LatestFinalizedHeight: lastFinalizedHeader.Height, 1190 NodeId: nodeId[:], 1191 } 1192 } 1193 1194 func executionResultToMessages(er *flow.ExecutionResult, metadata *entities.Metadata) (*access.ExecutionResultForBlockIDResponse, error) { 1195 execResult, err := convert.ExecutionResultToMessage(er) 1196 if err != nil { 1197 return nil, err 1198 } 1199 return &access.ExecutionResultForBlockIDResponse{ 1200 ExecutionResult: execResult, 1201 Metadata: metadata, 1202 }, nil 1203 } 1204 1205 // WithBlockSignerDecoder configures the Handler to decode signer indices 1206 // via the provided hotstuff.BlockSignerDecoder 1207 func WithBlockSignerDecoder(signerIndicesDecoder hotstuff.BlockSignerDecoder) func(*Handler) { 1208 return func(handler *Handler) { 1209 handler.signerIndicesDecoder = signerIndicesDecoder 1210 } 1211 } 1212 1213 // checkBlockStatus checks the validity of the provided block status. 1214 // 1215 // Expected errors during normal operation: 1216 // - codes.InvalidArgument - if blockStatus is flow.BlockStatusUnknown 1217 func checkBlockStatus(blockStatus flow.BlockStatus) error { 1218 if blockStatus != flow.BlockStatusFinalized && blockStatus != flow.BlockStatusSealed { 1219 return status.Errorf(codes.InvalidArgument, "block status is unknown. Possible variants: BLOCK_FINALIZED, BLOCK_SEALED") 1220 } 1221 return nil 1222 }