github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/engine/access/rpc/engine_builder.go (about) 1 package rpc 2 3 import ( 4 "fmt" 5 6 grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" 7 8 "github.com/onflow/flow-go/access" 9 legacyaccess "github.com/onflow/flow-go/access/legacy" 10 "github.com/onflow/flow-go/consensus/hotstuff" 11 "github.com/onflow/flow-go/module" 12 13 accessproto "github.com/onflow/flow/protobuf/go/flow/access" 14 legacyaccessproto "github.com/onflow/flow/protobuf/go/flow/legacy/access" 15 ) 16 17 type RPCEngineBuilder struct { 18 *Engine 19 me module.Local 20 finalizedHeaderCache module.FinalizedHeaderCache 21 22 // optional parameters, only one can be set during build phase 23 signerIndicesDecoder hotstuff.BlockSignerDecoder 24 rpcHandler accessproto.AccessAPIServer // Use the parent interface instead of implementation, so that we can assign it to proxy. 25 } 26 27 // NewRPCEngineBuilder helps to build a new RPC engine. 28 func NewRPCEngineBuilder(engine *Engine, me module.Local, finalizedHeaderCache module.FinalizedHeaderCache) *RPCEngineBuilder { 29 // the default handler will use the engine.backend implementation 30 return &RPCEngineBuilder{ 31 Engine: engine, 32 me: me, 33 finalizedHeaderCache: finalizedHeaderCache, 34 } 35 } 36 37 func (builder *RPCEngineBuilder) RpcHandler() accessproto.AccessAPIServer { 38 return builder.rpcHandler 39 } 40 41 // WithBlockSignerDecoder specifies that signer indices in block headers should be translated 42 // to full node IDs with the given decoder. 43 // Caution: 44 // you can inject either a `BlockSignerDecoder` (via method `WithBlockSignerDecoder`) 45 // or an `AccessAPIServer` (via method `WithNewHandler`); but not both. If both are 46 // specified, the builder will error during the build step. 47 // 48 // Returns self-reference for chaining. 49 func (builder *RPCEngineBuilder) WithBlockSignerDecoder(signerIndicesDecoder hotstuff.BlockSignerDecoder) *RPCEngineBuilder { 50 builder.signerIndicesDecoder = signerIndicesDecoder 51 return builder 52 } 53 54 // WithRpcHandler specifies that the given `AccessAPIServer` should be used for serving API queries. 55 // Caution: 56 // you can inject either a `BlockSignerDecoder` (via method `WithBlockSignerDecoder`) 57 // or an `AccessAPIServer` (via method `WithRpcHandler`); but not both. If both are 58 // specified, the builder will error during the build step. 59 // 60 // Returns self-reference for chaining. 61 func (builder *RPCEngineBuilder) WithRpcHandler(handler accessproto.AccessAPIServer) *RPCEngineBuilder { 62 builder.rpcHandler = handler 63 return builder 64 } 65 66 // WithLegacy specifies that a legacy access API should be instantiated 67 // Returns self-reference for chaining. 68 func (builder *RPCEngineBuilder) WithLegacy() *RPCEngineBuilder { 69 // Register legacy gRPC handlers for backwards compatibility, to be removed at a later date 70 legacyaccessproto.RegisterAccessAPIServer( 71 builder.unsecureGrpcServer.Server, 72 legacyaccess.NewHandler(builder.backend, builder.chain), 73 ) 74 legacyaccessproto.RegisterAccessAPIServer( 75 builder.secureGrpcServer.Server, 76 legacyaccess.NewHandler(builder.backend, builder.chain), 77 ) 78 return builder 79 } 80 81 func (builder *RPCEngineBuilder) DefaultHandler(signerIndicesDecoder hotstuff.BlockSignerDecoder) *access.Handler { 82 if signerIndicesDecoder == nil { 83 return access.NewHandler(builder.Engine.backend, builder.Engine.chain, builder.finalizedHeaderCache, builder.me, builder.stateStreamConfig.MaxGlobalStreams) 84 } else { 85 return access.NewHandler(builder.Engine.backend, builder.Engine.chain, builder.finalizedHeaderCache, builder.me, builder.stateStreamConfig.MaxGlobalStreams, access.WithBlockSignerDecoder(signerIndicesDecoder)) 86 } 87 } 88 89 // WithMetrics specifies the metrics should be collected. 90 // Returns self-reference for chaining. 91 func (builder *RPCEngineBuilder) WithMetrics() *RPCEngineBuilder { 92 // Not interested in legacy metrics, so initialize here 93 grpc_prometheus.EnableHandlingTimeHistogram() 94 grpc_prometheus.Register(builder.unsecureGrpcServer.Server) 95 grpc_prometheus.Register(builder.secureGrpcServer.Server) 96 return builder 97 } 98 99 func (builder *RPCEngineBuilder) Build() (*Engine, error) { 100 if builder.signerIndicesDecoder != nil && builder.rpcHandler != nil { 101 return nil, fmt.Errorf("only BlockSignerDecoder (via method `WithBlockSignerDecoder`) or AccessAPIServer (via method `WithNewHandler`) can be specified but not both") 102 } 103 rpcHandler := builder.rpcHandler 104 if rpcHandler == nil { 105 rpcHandler = builder.DefaultHandler(builder.signerIndicesDecoder) 106 } 107 accessproto.RegisterAccessAPIServer(builder.unsecureGrpcServer.Server, rpcHandler) 108 accessproto.RegisterAccessAPIServer(builder.secureGrpcServer.Server, rpcHandler) 109 return builder.Engine, nil 110 }