github.com/onflow/flow-go@v0.33.17/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  
     9  	"github.com/onflow/flow-go/consensus/hotstuff"
    10  	"github.com/onflow/flow-go/consensus/hotstuff/signature"
    11  	"github.com/onflow/flow-go/engine/common/rpc/convert"
    12  	"github.com/onflow/flow-go/model/flow"
    13  	"github.com/onflow/flow-go/module"
    14  
    15  	"github.com/onflow/flow/protobuf/go/flow/access"
    16  	"github.com/onflow/flow/protobuf/go/flow/entities"
    17  )
    18  
    19  type Handler struct {
    20  	api                  API
    21  	chain                flow.Chain
    22  	signerIndicesDecoder hotstuff.BlockSignerDecoder
    23  	finalizedHeaderCache module.FinalizedHeaderCache
    24  	me                   module.Local
    25  }
    26  
    27  // HandlerOption is used to hand over optional constructor parameters
    28  type HandlerOption func(*Handler)
    29  
    30  var _ access.AccessAPIServer = (*Handler)(nil)
    31  
    32  func NewHandler(api API, chain flow.Chain, finalizedHeader module.FinalizedHeaderCache, me module.Local, options ...HandlerOption) *Handler {
    33  	h := &Handler{
    34  		api:                  api,
    35  		chain:                chain,
    36  		finalizedHeaderCache: finalizedHeader,
    37  		me:                   me,
    38  		signerIndicesDecoder: &signature.NoopBlockSignerDecoder{},
    39  	}
    40  	for _, opt := range options {
    41  		opt(h)
    42  	}
    43  	return h
    44  }
    45  
    46  // Ping the Access API server for a response.
    47  func (h *Handler) Ping(ctx context.Context, _ *access.PingRequest) (*access.PingResponse, error) {
    48  	err := h.api.Ping(ctx)
    49  	if err != nil {
    50  		return nil, err
    51  	}
    52  
    53  	return &access.PingResponse{}, nil
    54  }
    55  
    56  // GetNodeVersionInfo gets node version information such as semver, commit, sporkID, protocolVersion, etc
    57  func (h *Handler) GetNodeVersionInfo(
    58  	ctx context.Context,
    59  	_ *access.GetNodeVersionInfoRequest,
    60  ) (*access.GetNodeVersionInfoResponse, error) {
    61  	nodeVersionInfo, err := h.api.GetNodeVersionInfo(ctx)
    62  	if err != nil {
    63  		return nil, err
    64  	}
    65  
    66  	return &access.GetNodeVersionInfoResponse{
    67  		Info: &entities.NodeVersionInfo{
    68  			Semver:               nodeVersionInfo.Semver,
    69  			Commit:               nodeVersionInfo.Commit,
    70  			SporkId:              nodeVersionInfo.SporkId[:],
    71  			ProtocolVersion:      nodeVersionInfo.ProtocolVersion,
    72  			SporkRootBlockHeight: nodeVersionInfo.SporkRootBlockHeight,
    73  			NodeRootBlockHeight:  nodeVersionInfo.NodeRootBlockHeight,
    74  		},
    75  	}, nil
    76  }
    77  
    78  func (h *Handler) GetNetworkParameters(
    79  	ctx context.Context,
    80  	_ *access.GetNetworkParametersRequest,
    81  ) (*access.GetNetworkParametersResponse, error) {
    82  	params := h.api.GetNetworkParameters(ctx)
    83  
    84  	return &access.GetNetworkParametersResponse{
    85  		ChainId: string(params.ChainID),
    86  	}, nil
    87  }
    88  
    89  // GetLatestBlockHeader gets the latest sealed block header.
    90  func (h *Handler) GetLatestBlockHeader(
    91  	ctx context.Context,
    92  	req *access.GetLatestBlockHeaderRequest,
    93  ) (*access.BlockHeaderResponse, error) {
    94  	header, status, err := h.api.GetLatestBlockHeader(ctx, req.GetIsSealed())
    95  	if err != nil {
    96  		return nil, err
    97  	}
    98  	return h.blockHeaderResponse(header, status)
    99  }
   100  
   101  // GetBlockHeaderByHeight gets a block header by height.
   102  func (h *Handler) GetBlockHeaderByHeight(
   103  	ctx context.Context,
   104  	req *access.GetBlockHeaderByHeightRequest,
   105  ) (*access.BlockHeaderResponse, error) {
   106  	header, status, err := h.api.GetBlockHeaderByHeight(ctx, req.GetHeight())
   107  	if err != nil {
   108  		return nil, err
   109  	}
   110  	return h.blockHeaderResponse(header, status)
   111  }
   112  
   113  // GetBlockHeaderByID gets a block header by ID.
   114  func (h *Handler) GetBlockHeaderByID(
   115  	ctx context.Context,
   116  	req *access.GetBlockHeaderByIDRequest,
   117  ) (*access.BlockHeaderResponse, error) {
   118  	id, err := convert.BlockID(req.GetId())
   119  	if err != nil {
   120  		return nil, status.Errorf(codes.InvalidArgument, "invalid block id: %v", err)
   121  	}
   122  	header, status, err := h.api.GetBlockHeaderByID(ctx, id)
   123  	if err != nil {
   124  		return nil, err
   125  	}
   126  	return h.blockHeaderResponse(header, status)
   127  }
   128  
   129  // GetLatestBlock gets the latest sealed block.
   130  func (h *Handler) GetLatestBlock(
   131  	ctx context.Context,
   132  	req *access.GetLatestBlockRequest,
   133  ) (*access.BlockResponse, error) {
   134  	block, status, err := h.api.GetLatestBlock(ctx, req.GetIsSealed())
   135  	if err != nil {
   136  		return nil, err
   137  	}
   138  	return h.blockResponse(block, req.GetFullBlockResponse(), status)
   139  }
   140  
   141  // GetBlockByHeight gets a block by height.
   142  func (h *Handler) GetBlockByHeight(
   143  	ctx context.Context,
   144  	req *access.GetBlockByHeightRequest,
   145  ) (*access.BlockResponse, error) {
   146  	block, status, err := h.api.GetBlockByHeight(ctx, req.GetHeight())
   147  	if err != nil {
   148  		return nil, err
   149  	}
   150  	return h.blockResponse(block, req.GetFullBlockResponse(), status)
   151  }
   152  
   153  // GetBlockByID gets a block by ID.
   154  func (h *Handler) GetBlockByID(
   155  	ctx context.Context,
   156  	req *access.GetBlockByIDRequest,
   157  ) (*access.BlockResponse, error) {
   158  	id, err := convert.BlockID(req.GetId())
   159  	if err != nil {
   160  		return nil, status.Errorf(codes.InvalidArgument, "invalid block id: %v", err)
   161  	}
   162  	block, status, err := h.api.GetBlockByID(ctx, id)
   163  	if err != nil {
   164  		return nil, err
   165  	}
   166  	return h.blockResponse(block, req.GetFullBlockResponse(), status)
   167  }
   168  
   169  // GetCollectionByID gets a collection by ID.
   170  func (h *Handler) GetCollectionByID(
   171  	ctx context.Context,
   172  	req *access.GetCollectionByIDRequest,
   173  ) (*access.CollectionResponse, error) {
   174  	metadata := h.buildMetadataResponse()
   175  
   176  	id, err := convert.CollectionID(req.GetId())
   177  	if err != nil {
   178  		return nil, status.Errorf(codes.InvalidArgument, "invalid collection id: %v", err)
   179  	}
   180  
   181  	col, err := h.api.GetCollectionByID(ctx, id)
   182  	if err != nil {
   183  		return nil, err
   184  	}
   185  
   186  	colMsg, err := convert.LightCollectionToMessage(col)
   187  	if err != nil {
   188  		return nil, status.Error(codes.Internal, err.Error())
   189  	}
   190  
   191  	return &access.CollectionResponse{
   192  		Collection: colMsg,
   193  		Metadata:   metadata,
   194  	}, nil
   195  }
   196  
   197  // SendTransaction submits a transaction to the network.
   198  func (h *Handler) SendTransaction(
   199  	ctx context.Context,
   200  	req *access.SendTransactionRequest,
   201  ) (*access.SendTransactionResponse, error) {
   202  	metadata := h.buildMetadataResponse()
   203  
   204  	txMsg := req.GetTransaction()
   205  
   206  	tx, err := convert.MessageToTransaction(txMsg, h.chain)
   207  	if err != nil {
   208  		return nil, status.Error(codes.InvalidArgument, err.Error())
   209  	}
   210  
   211  	err = h.api.SendTransaction(ctx, &tx)
   212  	if err != nil {
   213  		return nil, err
   214  	}
   215  
   216  	txID := tx.ID()
   217  
   218  	return &access.SendTransactionResponse{
   219  		Id:       txID[:],
   220  		Metadata: metadata,
   221  	}, nil
   222  }
   223  
   224  // GetTransaction gets a transaction by ID.
   225  func (h *Handler) GetTransaction(
   226  	ctx context.Context,
   227  	req *access.GetTransactionRequest,
   228  ) (*access.TransactionResponse, error) {
   229  	metadata := h.buildMetadataResponse()
   230  
   231  	id, err := convert.TransactionID(req.GetId())
   232  	if err != nil {
   233  		return nil, status.Errorf(codes.InvalidArgument, "invalid transaction id: %v", err)
   234  	}
   235  
   236  	tx, err := h.api.GetTransaction(ctx, id)
   237  	if err != nil {
   238  		return nil, err
   239  	}
   240  
   241  	return &access.TransactionResponse{
   242  		Transaction: convert.TransactionToMessage(*tx),
   243  		Metadata:    metadata,
   244  	}, nil
   245  }
   246  
   247  // GetTransactionResult gets a transaction by ID.
   248  func (h *Handler) GetTransactionResult(
   249  	ctx context.Context,
   250  	req *access.GetTransactionRequest,
   251  ) (*access.TransactionResultResponse, error) {
   252  	metadata := h.buildMetadataResponse()
   253  
   254  	transactionID, err := convert.TransactionID(req.GetId())
   255  	if err != nil {
   256  		return nil, status.Errorf(codes.InvalidArgument, "invalid transaction id: %v", err)
   257  	}
   258  
   259  	blockId := flow.ZeroID
   260  	requestBlockId := req.GetBlockId()
   261  	if requestBlockId != nil {
   262  		blockId, err = convert.BlockID(requestBlockId)
   263  		if err != nil {
   264  			return nil, status.Errorf(codes.InvalidArgument, "invalid block id: %v", err)
   265  		}
   266  	}
   267  
   268  	collectionId := flow.ZeroID
   269  	requestCollectionId := req.GetCollectionId()
   270  	if requestCollectionId != nil {
   271  		collectionId, err = convert.CollectionID(requestCollectionId)
   272  		if err != nil {
   273  			return nil, status.Errorf(codes.InvalidArgument, "invalid collection id: %v", err)
   274  		}
   275  	}
   276  
   277  	eventEncodingVersion := req.GetEventEncodingVersion()
   278  	result, err := h.api.GetTransactionResult(ctx, transactionID, blockId, collectionId, eventEncodingVersion)
   279  	if err != nil {
   280  		return nil, err
   281  	}
   282  
   283  	message := TransactionResultToMessage(result)
   284  	message.Metadata = metadata
   285  
   286  	return message, nil
   287  }
   288  
   289  func (h *Handler) GetTransactionResultsByBlockID(
   290  	ctx context.Context,
   291  	req *access.GetTransactionsByBlockIDRequest,
   292  ) (*access.TransactionResultsResponse, error) {
   293  	metadata := h.buildMetadataResponse()
   294  
   295  	id, err := convert.BlockID(req.GetBlockId())
   296  	if err != nil {
   297  		return nil, status.Errorf(codes.InvalidArgument, "invalid block id: %v", err)
   298  	}
   299  
   300  	eventEncodingVersion := req.GetEventEncodingVersion()
   301  
   302  	results, err := h.api.GetTransactionResultsByBlockID(ctx, id, eventEncodingVersion)
   303  	if err != nil {
   304  		return nil, err
   305  	}
   306  
   307  	message := TransactionResultsToMessage(results)
   308  	message.Metadata = metadata
   309  
   310  	return message, nil
   311  }
   312  
   313  func (h *Handler) GetSystemTransaction(
   314  	ctx context.Context,
   315  	req *access.GetSystemTransactionRequest,
   316  ) (*access.TransactionResponse, error) {
   317  	metadata := h.buildMetadataResponse()
   318  
   319  	id, err := convert.BlockID(req.GetBlockId())
   320  	if err != nil {
   321  		return nil, status.Errorf(codes.InvalidArgument, "invalid block id: %v", err)
   322  	}
   323  
   324  	tx, err := h.api.GetSystemTransaction(ctx, id)
   325  	if err != nil {
   326  		return nil, err
   327  	}
   328  
   329  	return &access.TransactionResponse{
   330  		Transaction: convert.TransactionToMessage(*tx),
   331  		Metadata:    metadata,
   332  	}, nil
   333  }
   334  
   335  func (h *Handler) GetSystemTransactionResult(
   336  	ctx context.Context,
   337  	req *access.GetSystemTransactionResultRequest,
   338  ) (*access.TransactionResultResponse, error) {
   339  	metadata := h.buildMetadataResponse()
   340  
   341  	id, err := convert.BlockID(req.GetBlockId())
   342  	if err != nil {
   343  		return nil, status.Errorf(codes.InvalidArgument, "invalid block id: %v", err)
   344  	}
   345  
   346  	result, err := h.api.GetSystemTransactionResult(ctx, id, req.GetEventEncodingVersion())
   347  	if err != nil {
   348  		return nil, err
   349  	}
   350  
   351  	message := TransactionResultToMessage(result)
   352  	message.Metadata = metadata
   353  
   354  	return message, nil
   355  }
   356  
   357  func (h *Handler) GetTransactionsByBlockID(
   358  	ctx context.Context,
   359  	req *access.GetTransactionsByBlockIDRequest,
   360  ) (*access.TransactionsResponse, error) {
   361  	metadata := h.buildMetadataResponse()
   362  
   363  	id, err := convert.BlockID(req.GetBlockId())
   364  	if err != nil {
   365  		return nil, status.Errorf(codes.InvalidArgument, "invalid block id: %v", err)
   366  	}
   367  
   368  	transactions, err := h.api.GetTransactionsByBlockID(ctx, id)
   369  	if err != nil {
   370  		return nil, err
   371  	}
   372  
   373  	return &access.TransactionsResponse{
   374  		Transactions: convert.TransactionsToMessages(transactions),
   375  		Metadata:     metadata,
   376  	}, nil
   377  }
   378  
   379  // GetTransactionResultByIndex gets a transaction at a specific index for in a block that is executed,
   380  // pending or finalized transactions return errors
   381  func (h *Handler) GetTransactionResultByIndex(
   382  	ctx context.Context,
   383  	req *access.GetTransactionByIndexRequest,
   384  ) (*access.TransactionResultResponse, error) {
   385  	metadata := h.buildMetadataResponse()
   386  
   387  	blockID, err := convert.BlockID(req.GetBlockId())
   388  	if err != nil {
   389  		return nil, status.Errorf(codes.InvalidArgument, "invalid block id: %v", err)
   390  	}
   391  
   392  	eventEncodingVersion := req.GetEventEncodingVersion()
   393  
   394  	result, err := h.api.GetTransactionResultByIndex(ctx, blockID, req.GetIndex(), eventEncodingVersion)
   395  	if err != nil {
   396  		return nil, err
   397  	}
   398  
   399  	message := TransactionResultToMessage(result)
   400  	message.Metadata = metadata
   401  
   402  	return message, nil
   403  }
   404  
   405  // GetAccount returns an account by address at the latest sealed block.
   406  func (h *Handler) GetAccount(
   407  	ctx context.Context,
   408  	req *access.GetAccountRequest,
   409  ) (*access.GetAccountResponse, error) {
   410  	metadata := h.buildMetadataResponse()
   411  
   412  	address, err := convert.Address(req.GetAddress(), h.chain)
   413  	if err != nil {
   414  		return nil, status.Errorf(codes.InvalidArgument, "invalid address: %v", err)
   415  	}
   416  
   417  	account, err := h.api.GetAccount(ctx, address)
   418  	if err != nil {
   419  		return nil, err
   420  	}
   421  
   422  	accountMsg, err := convert.AccountToMessage(account)
   423  	if err != nil {
   424  		return nil, status.Error(codes.Internal, err.Error())
   425  	}
   426  
   427  	return &access.GetAccountResponse{
   428  		Account:  accountMsg,
   429  		Metadata: metadata,
   430  	}, nil
   431  }
   432  
   433  // GetAccountAtLatestBlock returns an account by address at the latest sealed block.
   434  func (h *Handler) GetAccountAtLatestBlock(
   435  	ctx context.Context,
   436  	req *access.GetAccountAtLatestBlockRequest,
   437  ) (*access.AccountResponse, error) {
   438  	metadata := h.buildMetadataResponse()
   439  
   440  	address, err := convert.Address(req.GetAddress(), h.chain)
   441  	if err != nil {
   442  		return nil, status.Errorf(codes.InvalidArgument, "invalid address: %v", err)
   443  	}
   444  
   445  	account, err := h.api.GetAccountAtLatestBlock(ctx, address)
   446  	if err != nil {
   447  		return nil, err
   448  	}
   449  
   450  	accountMsg, err := convert.AccountToMessage(account)
   451  	if err != nil {
   452  		return nil, status.Error(codes.Internal, err.Error())
   453  	}
   454  
   455  	return &access.AccountResponse{
   456  		Account:  accountMsg,
   457  		Metadata: metadata,
   458  	}, nil
   459  }
   460  
   461  func (h *Handler) GetAccountAtBlockHeight(
   462  	ctx context.Context,
   463  	req *access.GetAccountAtBlockHeightRequest,
   464  ) (*access.AccountResponse, error) {
   465  	metadata := h.buildMetadataResponse()
   466  
   467  	address, err := convert.Address(req.GetAddress(), h.chain)
   468  	if err != nil {
   469  		return nil, status.Errorf(codes.InvalidArgument, "invalid address: %v", err)
   470  	}
   471  
   472  	account, err := h.api.GetAccountAtBlockHeight(ctx, address, req.GetBlockHeight())
   473  	if err != nil {
   474  		return nil, err
   475  	}
   476  
   477  	accountMsg, err := convert.AccountToMessage(account)
   478  	if err != nil {
   479  		return nil, status.Error(codes.Internal, err.Error())
   480  	}
   481  
   482  	return &access.AccountResponse{
   483  		Account:  accountMsg,
   484  		Metadata: metadata,
   485  	}, nil
   486  }
   487  
   488  // ExecuteScriptAtLatestBlock executes a script at a the latest block.
   489  func (h *Handler) ExecuteScriptAtLatestBlock(
   490  	ctx context.Context,
   491  	req *access.ExecuteScriptAtLatestBlockRequest,
   492  ) (*access.ExecuteScriptResponse, error) {
   493  	metadata := h.buildMetadataResponse()
   494  
   495  	script := req.GetScript()
   496  	arguments := req.GetArguments()
   497  
   498  	value, err := h.api.ExecuteScriptAtLatestBlock(ctx, script, arguments)
   499  	if err != nil {
   500  		return nil, err
   501  	}
   502  
   503  	return &access.ExecuteScriptResponse{
   504  		Value:    value,
   505  		Metadata: metadata,
   506  	}, nil
   507  }
   508  
   509  // ExecuteScriptAtBlockHeight executes a script at a specific block height.
   510  func (h *Handler) ExecuteScriptAtBlockHeight(
   511  	ctx context.Context,
   512  	req *access.ExecuteScriptAtBlockHeightRequest,
   513  ) (*access.ExecuteScriptResponse, error) {
   514  	metadata := h.buildMetadataResponse()
   515  
   516  	script := req.GetScript()
   517  	arguments := req.GetArguments()
   518  	blockHeight := req.GetBlockHeight()
   519  
   520  	value, err := h.api.ExecuteScriptAtBlockHeight(ctx, blockHeight, script, arguments)
   521  	if err != nil {
   522  		return nil, err
   523  	}
   524  
   525  	return &access.ExecuteScriptResponse{
   526  		Value:    value,
   527  		Metadata: metadata,
   528  	}, nil
   529  }
   530  
   531  // ExecuteScriptAtBlockID executes a script at a specific block ID.
   532  func (h *Handler) ExecuteScriptAtBlockID(
   533  	ctx context.Context,
   534  	req *access.ExecuteScriptAtBlockIDRequest,
   535  ) (*access.ExecuteScriptResponse, error) {
   536  	metadata := h.buildMetadataResponse()
   537  
   538  	script := req.GetScript()
   539  	arguments := req.GetArguments()
   540  	blockID := convert.MessageToIdentifier(req.GetBlockId())
   541  
   542  	value, err := h.api.ExecuteScriptAtBlockID(ctx, blockID, script, arguments)
   543  	if err != nil {
   544  		return nil, err
   545  	}
   546  
   547  	return &access.ExecuteScriptResponse{
   548  		Value:    value,
   549  		Metadata: metadata,
   550  	}, nil
   551  }
   552  
   553  // GetEventsForHeightRange returns events matching a query.
   554  func (h *Handler) GetEventsForHeightRange(
   555  	ctx context.Context,
   556  	req *access.GetEventsForHeightRangeRequest,
   557  ) (*access.EventsResponse, error) {
   558  	metadata := h.buildMetadataResponse()
   559  
   560  	eventType, err := convert.EventType(req.GetType())
   561  	if err != nil {
   562  		return nil, err
   563  	}
   564  
   565  	startHeight := req.GetStartHeight()
   566  	endHeight := req.GetEndHeight()
   567  
   568  	eventEncodingVersion := req.GetEventEncodingVersion()
   569  
   570  	results, err := h.api.GetEventsForHeightRange(ctx, eventType, startHeight, endHeight, eventEncodingVersion)
   571  	if err != nil {
   572  		return nil, err
   573  	}
   574  
   575  	resultEvents, err := convert.BlockEventsToMessages(results)
   576  	if err != nil {
   577  		return nil, err
   578  	}
   579  	return &access.EventsResponse{
   580  		Results:  resultEvents,
   581  		Metadata: metadata,
   582  	}, nil
   583  }
   584  
   585  // GetEventsForBlockIDs returns events matching a set of block IDs.
   586  func (h *Handler) GetEventsForBlockIDs(
   587  	ctx context.Context,
   588  	req *access.GetEventsForBlockIDsRequest,
   589  ) (*access.EventsResponse, error) {
   590  	metadata := h.buildMetadataResponse()
   591  
   592  	eventType, err := convert.EventType(req.GetType())
   593  	if err != nil {
   594  		return nil, err
   595  	}
   596  
   597  	blockIDs, err := convert.BlockIDs(req.GetBlockIds())
   598  	if err != nil {
   599  		return nil, err
   600  	}
   601  
   602  	eventEncodingVersion := req.GetEventEncodingVersion()
   603  
   604  	results, err := h.api.GetEventsForBlockIDs(ctx, eventType, blockIDs, eventEncodingVersion)
   605  	if err != nil {
   606  		return nil, err
   607  	}
   608  
   609  	resultEvents, err := convert.BlockEventsToMessages(results)
   610  	if err != nil {
   611  		return nil, err
   612  	}
   613  
   614  	return &access.EventsResponse{
   615  		Results:  resultEvents,
   616  		Metadata: metadata,
   617  	}, nil
   618  }
   619  
   620  // GetLatestProtocolStateSnapshot returns the latest serializable Snapshot
   621  func (h *Handler) GetLatestProtocolStateSnapshot(ctx context.Context, req *access.GetLatestProtocolStateSnapshotRequest) (*access.ProtocolStateSnapshotResponse, error) {
   622  	metadata := h.buildMetadataResponse()
   623  
   624  	snapshot, err := h.api.GetLatestProtocolStateSnapshot(ctx)
   625  	if err != nil {
   626  		return nil, err
   627  	}
   628  
   629  	return &access.ProtocolStateSnapshotResponse{
   630  		SerializedSnapshot: snapshot,
   631  		Metadata:           metadata,
   632  	}, nil
   633  }
   634  
   635  // GetProtocolStateSnapshotByBlockID returns serializable Snapshot by blockID
   636  func (h *Handler) GetProtocolStateSnapshotByBlockID(ctx context.Context, req *access.GetProtocolStateSnapshotByBlockIDRequest) (*access.ProtocolStateSnapshotResponse, error) {
   637  	metadata := h.buildMetadataResponse()
   638  
   639  	blockID := convert.MessageToIdentifier(req.GetBlockId())
   640  
   641  	snapshot, err := h.api.GetProtocolStateSnapshotByBlockID(ctx, blockID)
   642  	if err != nil {
   643  		return nil, err
   644  	}
   645  
   646  	return &access.ProtocolStateSnapshotResponse{
   647  		SerializedSnapshot: snapshot,
   648  		Metadata:           metadata,
   649  	}, nil
   650  }
   651  
   652  // GetProtocolStateSnapshotByHeight returns serializable Snapshot by block height
   653  func (h *Handler) GetProtocolStateSnapshotByHeight(ctx context.Context, req *access.GetProtocolStateSnapshotByHeightRequest) (*access.ProtocolStateSnapshotResponse, error) {
   654  	metadata := h.buildMetadataResponse()
   655  
   656  	snapshot, err := h.api.GetProtocolStateSnapshotByHeight(ctx, req.GetBlockHeight())
   657  	if err != nil {
   658  		return nil, err
   659  	}
   660  
   661  	return &access.ProtocolStateSnapshotResponse{
   662  		SerializedSnapshot: snapshot,
   663  		Metadata:           metadata,
   664  	}, nil
   665  }
   666  
   667  // GetExecutionResultForBlockID returns the latest received execution result for the given block ID.
   668  // AN might receive multiple receipts with conflicting results for unsealed blocks.
   669  // 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.
   670  func (h *Handler) GetExecutionResultForBlockID(ctx context.Context, req *access.GetExecutionResultForBlockIDRequest) (*access.ExecutionResultForBlockIDResponse, error) {
   671  	metadata := h.buildMetadataResponse()
   672  
   673  	blockID := convert.MessageToIdentifier(req.GetBlockId())
   674  
   675  	result, err := h.api.GetExecutionResultForBlockID(ctx, blockID)
   676  	if err != nil {
   677  		return nil, err
   678  	}
   679  
   680  	return executionResultToMessages(result, metadata)
   681  }
   682  
   683  // GetExecutionResultByID returns the execution result for the given ID.
   684  func (h *Handler) GetExecutionResultByID(ctx context.Context, req *access.GetExecutionResultByIDRequest) (*access.ExecutionResultByIDResponse, error) {
   685  	metadata := h.buildMetadataResponse()
   686  
   687  	blockID := convert.MessageToIdentifier(req.GetId())
   688  
   689  	result, err := h.api.GetExecutionResultByID(ctx, blockID)
   690  	if err != nil {
   691  		return nil, err
   692  	}
   693  
   694  	execResult, err := convert.ExecutionResultToMessage(result)
   695  	if err != nil {
   696  		return nil, err
   697  	}
   698  	return &access.ExecutionResultByIDResponse{
   699  		ExecutionResult: execResult,
   700  		Metadata:        metadata,
   701  	}, nil
   702  }
   703  
   704  func (h *Handler) blockResponse(block *flow.Block, fullResponse bool, status flow.BlockStatus) (*access.BlockResponse, error) {
   705  	metadata := h.buildMetadataResponse()
   706  
   707  	signerIDs, err := h.signerIndicesDecoder.DecodeSignerIDs(block.Header)
   708  	if err != nil {
   709  		return nil, err // the block was retrieved from local storage - so no errors are expected
   710  	}
   711  
   712  	var msg *entities.Block
   713  	if fullResponse {
   714  		msg, err = convert.BlockToMessage(block, signerIDs)
   715  		if err != nil {
   716  			return nil, err
   717  		}
   718  	} else {
   719  		msg = convert.BlockToMessageLight(block)
   720  	}
   721  
   722  	return &access.BlockResponse{
   723  		Block:       msg,
   724  		BlockStatus: entities.BlockStatus(status),
   725  		Metadata:    metadata,
   726  	}, nil
   727  }
   728  
   729  func (h *Handler) blockHeaderResponse(header *flow.Header, status flow.BlockStatus) (*access.BlockHeaderResponse, error) {
   730  	metadata := h.buildMetadataResponse()
   731  
   732  	signerIDs, err := h.signerIndicesDecoder.DecodeSignerIDs(header)
   733  	if err != nil {
   734  		return nil, err // the block was retrieved from local storage - so no errors are expected
   735  	}
   736  
   737  	msg, err := convert.BlockHeaderToMessage(header, signerIDs)
   738  	if err != nil {
   739  		return nil, err
   740  	}
   741  
   742  	return &access.BlockHeaderResponse{
   743  		Block:       msg,
   744  		BlockStatus: entities.BlockStatus(status),
   745  		Metadata:    metadata,
   746  	}, nil
   747  }
   748  
   749  // buildMetadataResponse builds and returns the metadata response object.
   750  func (h *Handler) buildMetadataResponse() *entities.Metadata {
   751  	lastFinalizedHeader := h.finalizedHeaderCache.Get()
   752  	blockId := lastFinalizedHeader.ID()
   753  	nodeId := h.me.NodeID()
   754  
   755  	return &entities.Metadata{
   756  		LatestFinalizedBlockId: blockId[:],
   757  		LatestFinalizedHeight:  lastFinalizedHeader.Height,
   758  		NodeId:                 nodeId[:],
   759  	}
   760  }
   761  
   762  func executionResultToMessages(er *flow.ExecutionResult, metadata *entities.Metadata) (*access.ExecutionResultForBlockIDResponse, error) {
   763  	execResult, err := convert.ExecutionResultToMessage(er)
   764  	if err != nil {
   765  		return nil, err
   766  	}
   767  	return &access.ExecutionResultForBlockIDResponse{
   768  		ExecutionResult: execResult,
   769  		Metadata:        metadata,
   770  	}, nil
   771  }
   772  
   773  // WithBlockSignerDecoder configures the Handler to decode signer indices
   774  // via the provided hotstuff.BlockSignerDecoder
   775  func WithBlockSignerDecoder(signerIndicesDecoder hotstuff.BlockSignerDecoder) func(*Handler) {
   776  	return func(handler *Handler) {
   777  		handler.signerIndicesDecoder = signerIndicesDecoder
   778  	}
   779  }