github.com/koko1123/flow-go-1@v0.29.6/engine/access/apiproxy/access_api_proxy.go (about)

     1  package apiproxy
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"sync"
     7  	"time"
     8  
     9  	"google.golang.org/grpc/connectivity"
    10  
    11  	"google.golang.org/grpc"
    12  	"google.golang.org/grpc/codes"
    13  	"google.golang.org/grpc/credentials"
    14  	"google.golang.org/grpc/status"
    15  
    16  	"github.com/onflow/flow/protobuf/go/flow/access"
    17  	"github.com/rs/zerolog"
    18  
    19  	"github.com/koko1123/flow-go-1/engine/access/rpc/backend"
    20  	"github.com/koko1123/flow-go-1/engine/protocol"
    21  	"github.com/koko1123/flow-go-1/model/flow"
    22  	"github.com/koko1123/flow-go-1/module/metrics"
    23  	"github.com/koko1123/flow-go-1/utils/grpcutils"
    24  )
    25  
    26  // FlowAccessAPIRouter is a structure that represents the routing proxy algorithm.
    27  // It splits requests between a local and a remote API service.
    28  type FlowAccessAPIRouter struct {
    29  	Logger   zerolog.Logger
    30  	Metrics  *metrics.ObserverCollector
    31  	Upstream *FlowAccessAPIForwarder
    32  	Observer *protocol.Handler
    33  }
    34  
    35  func (h *FlowAccessAPIRouter) log(handler, rpc string, err error) {
    36  	code := status.Code(err)
    37  	h.Metrics.RecordRPC(handler, rpc, code)
    38  
    39  	logger := h.Logger.With().
    40  		Str("handler", handler).
    41  		Str("grpc_method", rpc).
    42  		Str("grpc_code", code.String()).
    43  		Logger()
    44  
    45  	if err != nil {
    46  		logger.Error().Err(err).Msg("request failed")
    47  		return
    48  	}
    49  
    50  	logger.Info().Msg("request succeeded")
    51  }
    52  
    53  // reconnectingClient returns an active client, or
    54  // creates one, if the last one is not ready anymore.
    55  func (h *FlowAccessAPIForwarder) reconnectingClient(i int) error {
    56  	timeout := h.timeout
    57  
    58  	if h.connections[i] == nil || h.connections[i].GetState() != connectivity.Ready {
    59  		identity := h.ids[i]
    60  		var connection *grpc.ClientConn
    61  		var err error
    62  		if identity.NetworkPubKey == nil {
    63  			connection, err = grpc.Dial(
    64  				identity.Address,
    65  				grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(grpcutils.DefaultMaxMsgSize)),
    66  				grpc.WithInsecure(), //nolint:staticcheck
    67  				backend.WithClientUnaryInterceptor(timeout))
    68  			if err != nil {
    69  				return err
    70  			}
    71  		} else {
    72  			tlsConfig, err := grpcutils.DefaultClientTLSConfig(identity.NetworkPubKey)
    73  			if err != nil {
    74  				return fmt.Errorf("failed to get default TLS client config using public flow networking key %s %w", identity.NetworkPubKey.String(), err)
    75  			}
    76  
    77  			connection, err = grpc.Dial(
    78  				identity.Address,
    79  				grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(grpcutils.DefaultMaxMsgSize)),
    80  				grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)),
    81  				backend.WithClientUnaryInterceptor(timeout))
    82  			if err != nil {
    83  				return fmt.Errorf("cannot connect to %s %w", identity.Address, err)
    84  			}
    85  		}
    86  		connection.Connect()
    87  		time.Sleep(1 * time.Second)
    88  		state := connection.GetState()
    89  		if state != connectivity.Ready && state != connectivity.Connecting {
    90  			return fmt.Errorf("%v", state)
    91  		}
    92  		h.connections[i] = connection
    93  		h.upstream[i] = access.NewAccessAPIClient(connection)
    94  	}
    95  
    96  	return nil
    97  }
    98  
    99  // faultTolerantClient implements an upstream connection that reconnects on errors
   100  // a reasonable amount of time.
   101  func (h *FlowAccessAPIForwarder) faultTolerantClient() (access.AccessAPIClient, error) {
   102  	if h.upstream == nil || len(h.upstream) == 0 {
   103  		return nil, status.Errorf(codes.Unimplemented, "method not implemented")
   104  	}
   105  
   106  	// Reasoning: A retry count of three gives an acceptable 5% failure ratio from a 37% failure ratio.
   107  	// A bigger number is problematic due to the DNS resolve and connection times,
   108  	// plus the need to log and debug each individual connection failure.
   109  	//
   110  	// This reasoning eliminates the need of making this parameter configurable.
   111  	// The logic works rolling over a single connection as well making clean code.
   112  	const retryMax = 3
   113  
   114  	h.lock.Lock()
   115  	defer h.lock.Unlock()
   116  
   117  	var err error
   118  	for i := 0; i < retryMax; i++ {
   119  		h.roundRobin++
   120  		h.roundRobin = h.roundRobin % len(h.upstream)
   121  		err = h.reconnectingClient(h.roundRobin)
   122  		if err != nil {
   123  			continue
   124  		}
   125  		state := h.connections[h.roundRobin].GetState()
   126  		if state != connectivity.Ready && state != connectivity.Connecting {
   127  			continue
   128  		}
   129  		return h.upstream[h.roundRobin], nil
   130  	}
   131  
   132  	return nil, status.Errorf(codes.Unavailable, err.Error())
   133  }
   134  
   135  // Ping pings the service. It is special in the sense that it responds successful,
   136  // only if all underlying services are ready.
   137  func (h *FlowAccessAPIRouter) Ping(context context.Context, req *access.PingRequest) (*access.PingResponse, error) {
   138  	h.log("observer", "Ping", nil)
   139  	return &access.PingResponse{}, nil
   140  }
   141  
   142  func (h *FlowAccessAPIRouter) GetLatestBlockHeader(context context.Context, req *access.GetLatestBlockHeaderRequest) (*access.BlockHeaderResponse, error) {
   143  	res, err := h.Observer.GetLatestBlockHeader(context, req)
   144  	h.log("observer", "GetLatestBlockHeader", err)
   145  	return res, err
   146  }
   147  
   148  func (h *FlowAccessAPIRouter) GetBlockHeaderByID(context context.Context, req *access.GetBlockHeaderByIDRequest) (*access.BlockHeaderResponse, error) {
   149  	res, err := h.Observer.GetBlockHeaderByID(context, req)
   150  	h.log("observer", "GetBlockHeaderByID", err)
   151  	return res, err
   152  }
   153  
   154  func (h *FlowAccessAPIRouter) GetBlockHeaderByHeight(context context.Context, req *access.GetBlockHeaderByHeightRequest) (*access.BlockHeaderResponse, error) {
   155  	res, err := h.Observer.GetBlockHeaderByHeight(context, req)
   156  	h.log("observer", "GetBlockHeaderByHeight", err)
   157  	return res, err
   158  }
   159  
   160  func (h *FlowAccessAPIRouter) GetLatestBlock(context context.Context, req *access.GetLatestBlockRequest) (*access.BlockResponse, error) {
   161  	res, err := h.Observer.GetLatestBlock(context, req)
   162  	h.log("observer", "GetLatestBlock", err)
   163  	return res, err
   164  }
   165  
   166  func (h *FlowAccessAPIRouter) GetBlockByID(context context.Context, req *access.GetBlockByIDRequest) (*access.BlockResponse, error) {
   167  	res, err := h.Observer.GetBlockByID(context, req)
   168  	h.log("observer", "GetBlockByID", err)
   169  	return res, err
   170  }
   171  
   172  func (h *FlowAccessAPIRouter) GetBlockByHeight(context context.Context, req *access.GetBlockByHeightRequest) (*access.BlockResponse, error) {
   173  	res, err := h.Observer.GetBlockByHeight(context, req)
   174  	h.log("observer", "GetBlockByHeight", err)
   175  	return res, err
   176  }
   177  
   178  func (h *FlowAccessAPIRouter) GetCollectionByID(context context.Context, req *access.GetCollectionByIDRequest) (*access.CollectionResponse, error) {
   179  	res, err := h.Upstream.GetCollectionByID(context, req)
   180  	h.log("upstream", "GetCollectionByID", err)
   181  	return res, err
   182  }
   183  
   184  func (h *FlowAccessAPIRouter) SendTransaction(context context.Context, req *access.SendTransactionRequest) (*access.SendTransactionResponse, error) {
   185  	res, err := h.Upstream.SendTransaction(context, req)
   186  	h.log("upstream", "SendTransaction", err)
   187  	return res, err
   188  }
   189  
   190  func (h *FlowAccessAPIRouter) GetTransaction(context context.Context, req *access.GetTransactionRequest) (*access.TransactionResponse, error) {
   191  	res, err := h.Upstream.GetTransaction(context, req)
   192  	h.log("upstream", "GetTransaction", err)
   193  	return res, err
   194  }
   195  
   196  func (h *FlowAccessAPIRouter) GetTransactionResult(context context.Context, req *access.GetTransactionRequest) (*access.TransactionResultResponse, error) {
   197  	res, err := h.Upstream.GetTransactionResult(context, req)
   198  	h.log("upstream", "GetTransactionResult", err)
   199  	return res, err
   200  }
   201  
   202  func (h *FlowAccessAPIRouter) GetTransactionResultsByBlockID(context context.Context, req *access.GetTransactionsByBlockIDRequest) (*access.TransactionResultsResponse, error) {
   203  	res, err := h.Upstream.GetTransactionResultsByBlockID(context, req)
   204  	h.log("upstream", "GetTransactionResultsByBlockID", err)
   205  	return res, err
   206  }
   207  
   208  func (h *FlowAccessAPIRouter) GetTransactionsByBlockID(context context.Context, req *access.GetTransactionsByBlockIDRequest) (*access.TransactionsResponse, error) {
   209  	res, err := h.Upstream.GetTransactionsByBlockID(context, req)
   210  	h.log("upstream", "GetTransactionsByBlockID", err)
   211  	return res, err
   212  }
   213  
   214  func (h *FlowAccessAPIRouter) GetTransactionResultByIndex(context context.Context, req *access.GetTransactionByIndexRequest) (*access.TransactionResultResponse, error) {
   215  	res, err := h.Upstream.GetTransactionResultByIndex(context, req)
   216  	h.log("upstream", "GetTransactionResultByIndex", err)
   217  	return res, err
   218  }
   219  
   220  func (h *FlowAccessAPIRouter) GetAccount(context context.Context, req *access.GetAccountRequest) (*access.GetAccountResponse, error) {
   221  	res, err := h.Upstream.GetAccount(context, req)
   222  	h.log("upstream", "GetAccount", err)
   223  	return res, err
   224  }
   225  
   226  func (h *FlowAccessAPIRouter) GetAccountAtLatestBlock(context context.Context, req *access.GetAccountAtLatestBlockRequest) (*access.AccountResponse, error) {
   227  	res, err := h.Upstream.GetAccountAtLatestBlock(context, req)
   228  	h.log("upstream", "GetAccountAtLatestBlock", err)
   229  	return res, err
   230  }
   231  
   232  func (h *FlowAccessAPIRouter) GetAccountAtBlockHeight(context context.Context, req *access.GetAccountAtBlockHeightRequest) (*access.AccountResponse, error) {
   233  	res, err := h.Upstream.GetAccountAtBlockHeight(context, req)
   234  	h.log("upstream", "GetAccountAtBlockHeight", err)
   235  	return res, err
   236  }
   237  
   238  func (h *FlowAccessAPIRouter) ExecuteScriptAtLatestBlock(context context.Context, req *access.ExecuteScriptAtLatestBlockRequest) (*access.ExecuteScriptResponse, error) {
   239  	res, err := h.Upstream.ExecuteScriptAtLatestBlock(context, req)
   240  	h.log("upstream", "ExecuteScriptAtLatestBlock", err)
   241  	return res, err
   242  }
   243  
   244  func (h *FlowAccessAPIRouter) ExecuteScriptAtBlockID(context context.Context, req *access.ExecuteScriptAtBlockIDRequest) (*access.ExecuteScriptResponse, error) {
   245  	res, err := h.Upstream.ExecuteScriptAtBlockID(context, req)
   246  	h.log("upstream", "ExecuteScriptAtBlockID", err)
   247  	return res, err
   248  }
   249  
   250  func (h *FlowAccessAPIRouter) ExecuteScriptAtBlockHeight(context context.Context, req *access.ExecuteScriptAtBlockHeightRequest) (*access.ExecuteScriptResponse, error) {
   251  	res, err := h.Upstream.ExecuteScriptAtBlockHeight(context, req)
   252  	h.log("upstream", "ExecuteScriptAtBlockHeight", err)
   253  	return res, err
   254  }
   255  
   256  func (h *FlowAccessAPIRouter) GetEventsForHeightRange(context context.Context, req *access.GetEventsForHeightRangeRequest) (*access.EventsResponse, error) {
   257  	res, err := h.Upstream.GetEventsForHeightRange(context, req)
   258  	h.log("upstream", "GetEventsForHeightRange", err)
   259  	return res, err
   260  }
   261  
   262  func (h *FlowAccessAPIRouter) GetEventsForBlockIDs(context context.Context, req *access.GetEventsForBlockIDsRequest) (*access.EventsResponse, error) {
   263  	res, err := h.Upstream.GetEventsForBlockIDs(context, req)
   264  	h.log("upstream", "GetEventsForBlockIDs", err)
   265  	return res, err
   266  }
   267  
   268  func (h *FlowAccessAPIRouter) GetNetworkParameters(context context.Context, req *access.GetNetworkParametersRequest) (*access.GetNetworkParametersResponse, error) {
   269  	res, err := h.Observer.GetNetworkParameters(context, req)
   270  	h.log("observer", "GetNetworkParameters", err)
   271  	return res, err
   272  }
   273  
   274  func (h *FlowAccessAPIRouter) GetLatestProtocolStateSnapshot(context context.Context, req *access.GetLatestProtocolStateSnapshotRequest) (*access.ProtocolStateSnapshotResponse, error) {
   275  	res, err := h.Observer.GetLatestProtocolStateSnapshot(context, req)
   276  	h.log("observer", "GetLatestProtocolStateSnapshot", err)
   277  	return res, err
   278  }
   279  
   280  func (h *FlowAccessAPIRouter) GetExecutionResultForBlockID(context context.Context, req *access.GetExecutionResultForBlockIDRequest) (*access.ExecutionResultForBlockIDResponse, error) {
   281  	res, err := h.Upstream.GetExecutionResultForBlockID(context, req)
   282  	h.log("upstream", "GetExecutionResultForBlockID", err)
   283  	return res, err
   284  }
   285  
   286  // FlowAccessAPIForwarder forwards all requests to a set of upstream access nodes or observers
   287  type FlowAccessAPIForwarder struct {
   288  	lock        sync.Mutex
   289  	roundRobin  int
   290  	ids         flow.IdentityList
   291  	upstream    []access.AccessAPIClient
   292  	connections []*grpc.ClientConn
   293  	timeout     time.Duration
   294  }
   295  
   296  func NewFlowAccessAPIForwarder(identities flow.IdentityList, timeout time.Duration) (*FlowAccessAPIForwarder, error) {
   297  	forwarder := &FlowAccessAPIForwarder{}
   298  	err := forwarder.setFlowAccessAPI(identities, timeout)
   299  	return forwarder, err
   300  }
   301  
   302  // setFlowAccessAPI sets a backend access API that forwards some requests to an upstream node.
   303  // It is used by Observer services, Blockchain Data Service, etc.
   304  // Make sure that this is just for observation and not a staked participant in the flow network.
   305  // This means that observers see a copy of the data but there is no interaction to ensure integrity from the root block.
   306  func (ret *FlowAccessAPIForwarder) setFlowAccessAPI(accessNodeAddressAndPort flow.IdentityList, timeout time.Duration) error {
   307  	ret.timeout = timeout
   308  	ret.ids = accessNodeAddressAndPort
   309  	ret.upstream = make([]access.AccessAPIClient, accessNodeAddressAndPort.Count())
   310  	ret.connections = make([]*grpc.ClientConn, accessNodeAddressAndPort.Count())
   311  	for i, identity := range accessNodeAddressAndPort {
   312  		// Store the faultTolerantClient setup parameters such as address, public, key and timeout, so that
   313  		// we can refresh the API on connection loss
   314  		ret.ids[i] = identity
   315  
   316  		// We fail on any single error on startup, so that
   317  		// we identify bootstrapping errors early
   318  		err := ret.reconnectingClient(i)
   319  		if err != nil {
   320  			return err
   321  		}
   322  	}
   323  
   324  	ret.roundRobin = 0
   325  	return nil
   326  }
   327  
   328  // Ping pings the service. It is special in the sense that it responds successful,
   329  // only if all underlying services are ready.
   330  func (h *FlowAccessAPIForwarder) Ping(context context.Context, req *access.PingRequest) (*access.PingResponse, error) {
   331  	// This is a passthrough request
   332  	upstream, err := h.faultTolerantClient()
   333  	if err != nil {
   334  		return nil, err
   335  	}
   336  	return upstream.Ping(context, req)
   337  }
   338  
   339  func (h *FlowAccessAPIForwarder) GetLatestBlockHeader(context context.Context, req *access.GetLatestBlockHeaderRequest) (*access.BlockHeaderResponse, error) {
   340  	// This is a passthrough request
   341  	upstream, err := h.faultTolerantClient()
   342  	if err != nil {
   343  		return nil, err
   344  	}
   345  	return upstream.GetLatestBlockHeader(context, req)
   346  }
   347  
   348  func (h *FlowAccessAPIForwarder) GetBlockHeaderByID(context context.Context, req *access.GetBlockHeaderByIDRequest) (*access.BlockHeaderResponse, error) {
   349  	// This is a passthrough request
   350  	upstream, err := h.faultTolerantClient()
   351  	if err != nil {
   352  		return nil, err
   353  	}
   354  	return upstream.GetBlockHeaderByID(context, req)
   355  }
   356  
   357  func (h *FlowAccessAPIForwarder) GetBlockHeaderByHeight(context context.Context, req *access.GetBlockHeaderByHeightRequest) (*access.BlockHeaderResponse, error) {
   358  	// This is a passthrough request
   359  	upstream, err := h.faultTolerantClient()
   360  	if err != nil {
   361  		return nil, err
   362  	}
   363  	return upstream.GetBlockHeaderByHeight(context, req)
   364  }
   365  
   366  func (h *FlowAccessAPIForwarder) GetLatestBlock(context context.Context, req *access.GetLatestBlockRequest) (*access.BlockResponse, error) {
   367  	// This is a passthrough request
   368  	upstream, err := h.faultTolerantClient()
   369  	if err != nil {
   370  		return nil, err
   371  	}
   372  	return upstream.GetLatestBlock(context, req)
   373  }
   374  
   375  func (h *FlowAccessAPIForwarder) GetBlockByID(context context.Context, req *access.GetBlockByIDRequest) (*access.BlockResponse, error) {
   376  	// This is a passthrough request
   377  	upstream, err := h.faultTolerantClient()
   378  	if err != nil {
   379  		return nil, err
   380  	}
   381  	return upstream.GetBlockByID(context, req)
   382  }
   383  
   384  func (h *FlowAccessAPIForwarder) GetBlockByHeight(context context.Context, req *access.GetBlockByHeightRequest) (*access.BlockResponse, error) {
   385  	// This is a passthrough request
   386  	upstream, err := h.faultTolerantClient()
   387  	if err != nil {
   388  		return nil, err
   389  	}
   390  	return upstream.GetBlockByHeight(context, req)
   391  }
   392  
   393  func (h *FlowAccessAPIForwarder) GetCollectionByID(context context.Context, req *access.GetCollectionByIDRequest) (*access.CollectionResponse, error) {
   394  	// This is a passthrough request
   395  	upstream, err := h.faultTolerantClient()
   396  	if err != nil {
   397  		return nil, err
   398  	}
   399  	return upstream.GetCollectionByID(context, req)
   400  }
   401  
   402  func (h *FlowAccessAPIForwarder) SendTransaction(context context.Context, req *access.SendTransactionRequest) (*access.SendTransactionResponse, error) {
   403  	// This is a passthrough request
   404  	upstream, err := h.faultTolerantClient()
   405  	if err != nil {
   406  		return nil, err
   407  	}
   408  	return upstream.SendTransaction(context, req)
   409  }
   410  
   411  func (h *FlowAccessAPIForwarder) GetTransaction(context context.Context, req *access.GetTransactionRequest) (*access.TransactionResponse, error) {
   412  	// This is a passthrough request
   413  	upstream, err := h.faultTolerantClient()
   414  	if err != nil {
   415  		return nil, err
   416  	}
   417  	return upstream.GetTransaction(context, req)
   418  }
   419  
   420  func (h *FlowAccessAPIForwarder) GetTransactionResult(context context.Context, req *access.GetTransactionRequest) (*access.TransactionResultResponse, error) {
   421  	// This is a passthrough request
   422  	upstream, err := h.faultTolerantClient()
   423  	if err != nil {
   424  		return nil, err
   425  	}
   426  	return upstream.GetTransactionResult(context, req)
   427  }
   428  
   429  func (h *FlowAccessAPIForwarder) GetTransactionResultByIndex(context context.Context, req *access.GetTransactionByIndexRequest) (*access.TransactionResultResponse, error) {
   430  	// This is a passthrough request
   431  	upstream, err := h.faultTolerantClient()
   432  	if err != nil {
   433  		return nil, err
   434  	}
   435  	return upstream.GetTransactionResultByIndex(context, req)
   436  }
   437  
   438  func (h *FlowAccessAPIForwarder) GetTransactionResultsByBlockID(context context.Context, req *access.GetTransactionsByBlockIDRequest) (*access.TransactionResultsResponse, error) {
   439  	// This is a passthrough request
   440  	upstream, err := h.faultTolerantClient()
   441  	if err != nil {
   442  		return nil, err
   443  	}
   444  	return upstream.GetTransactionResultsByBlockID(context, req)
   445  }
   446  
   447  func (h *FlowAccessAPIForwarder) GetTransactionsByBlockID(context context.Context, req *access.GetTransactionsByBlockIDRequest) (*access.TransactionsResponse, error) {
   448  	upstream, err := h.faultTolerantClient()
   449  	if err != nil {
   450  		return nil, err
   451  	}
   452  	return upstream.GetTransactionsByBlockID(context, req)
   453  }
   454  
   455  func (h *FlowAccessAPIForwarder) GetAccount(context context.Context, req *access.GetAccountRequest) (*access.GetAccountResponse, error) {
   456  	// This is a passthrough request
   457  	upstream, err := h.faultTolerantClient()
   458  	if err != nil {
   459  		return nil, err
   460  	}
   461  	return upstream.GetAccount(context, req)
   462  }
   463  
   464  func (h *FlowAccessAPIForwarder) GetAccountAtLatestBlock(context context.Context, req *access.GetAccountAtLatestBlockRequest) (*access.AccountResponse, error) {
   465  	// This is a passthrough request
   466  	upstream, err := h.faultTolerantClient()
   467  	if err != nil {
   468  		return nil, err
   469  	}
   470  	return upstream.GetAccountAtLatestBlock(context, req)
   471  }
   472  
   473  func (h *FlowAccessAPIForwarder) GetAccountAtBlockHeight(context context.Context, req *access.GetAccountAtBlockHeightRequest) (*access.AccountResponse, error) {
   474  	// This is a passthrough request
   475  	upstream, err := h.faultTolerantClient()
   476  	if err != nil {
   477  		return nil, err
   478  	}
   479  	return upstream.GetAccountAtBlockHeight(context, req)
   480  }
   481  
   482  func (h *FlowAccessAPIForwarder) ExecuteScriptAtLatestBlock(context context.Context, req *access.ExecuteScriptAtLatestBlockRequest) (*access.ExecuteScriptResponse, error) {
   483  	// This is a passthrough request
   484  	upstream, err := h.faultTolerantClient()
   485  	if err != nil {
   486  		return nil, err
   487  	}
   488  	return upstream.ExecuteScriptAtLatestBlock(context, req)
   489  }
   490  
   491  func (h *FlowAccessAPIForwarder) ExecuteScriptAtBlockID(context context.Context, req *access.ExecuteScriptAtBlockIDRequest) (*access.ExecuteScriptResponse, error) {
   492  	// This is a passthrough request
   493  	upstream, err := h.faultTolerantClient()
   494  	if err != nil {
   495  		return nil, err
   496  	}
   497  	return upstream.ExecuteScriptAtBlockID(context, req)
   498  }
   499  
   500  func (h *FlowAccessAPIForwarder) ExecuteScriptAtBlockHeight(context context.Context, req *access.ExecuteScriptAtBlockHeightRequest) (*access.ExecuteScriptResponse, error) {
   501  	// This is a passthrough request
   502  	upstream, err := h.faultTolerantClient()
   503  	if err != nil {
   504  		return nil, err
   505  	}
   506  	return upstream.ExecuteScriptAtBlockHeight(context, req)
   507  }
   508  
   509  func (h *FlowAccessAPIForwarder) GetEventsForHeightRange(context context.Context, req *access.GetEventsForHeightRangeRequest) (*access.EventsResponse, error) {
   510  	// This is a passthrough request
   511  	upstream, err := h.faultTolerantClient()
   512  	if err != nil {
   513  		return nil, err
   514  	}
   515  	return upstream.GetEventsForHeightRange(context, req)
   516  }
   517  
   518  func (h *FlowAccessAPIForwarder) GetEventsForBlockIDs(context context.Context, req *access.GetEventsForBlockIDsRequest) (*access.EventsResponse, error) {
   519  	// This is a passthrough request
   520  	upstream, err := h.faultTolerantClient()
   521  	if err != nil {
   522  		return nil, err
   523  	}
   524  	return upstream.GetEventsForBlockIDs(context, req)
   525  }
   526  
   527  func (h *FlowAccessAPIForwarder) GetNetworkParameters(context context.Context, req *access.GetNetworkParametersRequest) (*access.GetNetworkParametersResponse, error) {
   528  	// This is a passthrough request
   529  	upstream, err := h.faultTolerantClient()
   530  	if err != nil {
   531  		return nil, err
   532  	}
   533  	return upstream.GetNetworkParameters(context, req)
   534  }
   535  
   536  func (h *FlowAccessAPIForwarder) GetLatestProtocolStateSnapshot(context context.Context, req *access.GetLatestProtocolStateSnapshotRequest) (*access.ProtocolStateSnapshotResponse, error) {
   537  	// This is a passthrough request
   538  	upstream, err := h.faultTolerantClient()
   539  	if err != nil {
   540  		return nil, err
   541  	}
   542  	return upstream.GetLatestProtocolStateSnapshot(context, req)
   543  }
   544  
   545  func (h *FlowAccessAPIForwarder) GetExecutionResultForBlockID(context context.Context, req *access.GetExecutionResultForBlockIDRequest) (*access.ExecutionResultForBlockIDResponse, error) {
   546  	// This is a passthrough request
   547  	upstream, err := h.faultTolerantClient()
   548  	if err != nil {
   549  		return nil, err
   550  	}
   551  	return upstream.GetExecutionResultForBlockID(context, req)
   552  }