Skip to content

Commit

Permalink
some big code refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
parkgunou committed Jan 21, 2025
1 parent 96433ee commit d9bf70d
Show file tree
Hide file tree
Showing 4 changed files with 216 additions and 98 deletions.
108 changes: 78 additions & 30 deletions op-signer/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ type SignerApp struct {

rpc *oprpc.Server

proxy *oprpc.Server
proxyService *service.SignerProxyService
wsProxy *oprpc.Server
wsProxyService *service.ProxyWSService

stopped atomic.Bool
}
Expand All @@ -63,23 +63,20 @@ func InitFromConfig(ctx context.Context, log log.Logger, cfg *Config, version st
}

func (s *SignerApp) init(cfg *Config) error {
var proxyClients *service.ProxyWSClients
if cfg.ProxyConfig.EnableProxy {
proxyClients = &service.ProxyWSClients{}
}
if err := s.initPprof(cfg); err != nil {
return fmt.Errorf("pprof error: %w", err)
}
if err := s.initMetrics(cfg); err != nil {
return fmt.Errorf("metrics error: %w", err)
}
if err := s.initRPC(cfg, proxyClients); err != nil {
return fmt.Errorf("metrics error: %w", err)
}
if cfg.ProxyConfig.EnableProxy {
if err := s.initProxy(cfg, proxyClients); err != nil {
if err := s.initProxy(cfg); err != nil {
return fmt.Errorf("proxy error: %w", err)
}
} else {
if err := s.initRPC(cfg); err != nil {
return fmt.Errorf("metrics error: %w", err)
}
}
return nil
}
Expand Down Expand Up @@ -123,7 +120,7 @@ func (s *SignerApp) initMetrics(cfg *Config) error {
return nil
}

func (s *SignerApp) initRPC(cfg *Config, proxyClients *service.ProxyWSClients) error {
func (s *SignerApp) initRPC(cfg *Config) error {
caCert, err := os.ReadFile(cfg.TLSConfig.TLSCaCert)
if err != nil {
return fmt.Errorf("failed to read tls ca cert: %s", string(caCert))
Expand Down Expand Up @@ -164,26 +161,74 @@ func (s *SignerApp) initRPC(cfg *Config, proxyClients *service.ProxyWSClients) e
if err != nil {
return fmt.Errorf("failed to read service config: %w", err)
}
s.signer = service.NewSignerService(s.log, serviceCfg, proxyClients)
s.signer = service.NewSignerService(s.log, serviceCfg)
s.signer.RegisterAPIs(s.rpc)

if err := s.rpc.Start(); err != nil {
return fmt.Errorf("error starting RPC server: %w", err)
}
s.log.Info("Started op-signer RPC server", "addr", s.rpc.Endpoint())

proxyTLSConfig := &tls.Config{
GetClientCertificate: cm.GetClientCertificate,
RootCAs: caCertPool, // will be default
if len(serviceCfg.Proxy) > 0 {
proxyTLSConfig := &tls.Config{
GetClientCertificate: cm.GetClientCertificate,
}
s.ConnectProxy(serviceCfg, proxyTLSConfig)
}
s.ConnectProxy(serviceCfg, proxyTLSConfig)

return nil
}

func (s *SignerApp) initProxy(cfg *Config, proxyClients *service.ProxyWSClients) error {
// CA cert of op-signer
caCert, err := os.ReadFile(cfg.ProxyConfig.SignerCA)
func (s *SignerApp) initProxy(cfg *Config) error {
sc := &service.SignerClients{}

// init ws server for op-signer
// client (op-signer) CA must be trusted
wsCaCert, err := os.ReadFile(cfg.ProxyConfig.SignerCA)
if err != nil {
return fmt.Errorf("failed to read tls ca cert: %s", string(wsCaCert))
}
wsCaCertPool := x509.NewCertPool()
wsCaCertPool.AppendCertsFromPEM(wsCaCert)

wsCm, err := certman.New(s.log, cfg.TLSConfig.TLSCert, cfg.TLSConfig.TLSKey)
if err != nil {
return fmt.Errorf("failed to read tls cert or key: %w", err)
}
if err := wsCm.Watch(); err != nil {
return fmt.Errorf("failed to start certman watcher: %w", err)
}

wsTlsConfig := &tls.Config{
GetCertificate: wsCm.GetCertificate,
ClientCAs: wsCaCertPool,
ClientAuth: tls.VerifyClientCertIfGiven, // necessary for k8s healthz probes, but we check the cert in service/auth.go
}
wsServerTlsConfig := &oprpc.ServerTLSConfig{
Config: wsTlsConfig,
}

wsProxyConfig := cfg.ProxyConfig
s.wsProxy = oprpc.NewServer(
wsProxyConfig.ListenAddr,
wsProxyConfig.ListenPort,
s.version,
oprpc.WithWebsocketEnabled(),
oprpc.WithLogger(s.log),
oprpc.WithTLSConfig(wsServerTlsConfig),
oprpc.WithMiddleware(service.NewAuthMiddleware()),
oprpc.WithHTTPRecorder(opmetrics.NewPromHTTPRecorder(s.registry, "wsproxy")),
)
s.wsProxyService = service.NewProxyWSService(s.log, sc)
s.wsProxyService.RegisterAPIs(s.wsProxy)

if err := s.wsProxy.Start(); err != nil {
return fmt.Errorf("error starting proxy RPC(WS) server: %w", err)
}
s.log.Info("Started op-signer proxy RPC(WS) server", "addr", s.wsProxy.Endpoint())

// init RPC proxy server
caCert, err := os.ReadFile(cfg.TLSConfig.TLSCaCert)
if err != nil {
return fmt.Errorf("failed to read tls ca cert: %s", string(caCert))
}
Expand All @@ -208,27 +253,30 @@ func (s *SignerApp) initProxy(cfg *Config, proxyClients *service.ProxyWSClients)
CLIConfig: &cfg.TLSConfig,
}

proxyConfig := cfg.ProxyConfig
s.proxy = oprpc.NewServer(
proxyConfig.ListenAddr,
proxyConfig.ListenPort,
rpcCfg := cfg.RPCConfig
s.rpc = oprpc.NewServer(
rpcCfg.ListenAddr,
rpcCfg.ListenPort,
s.version,
oprpc.WithWebsocketEnabled(),
oprpc.WithLogger(s.log),
oprpc.WithTLSConfig(serverTlsConfig),
oprpc.WithMiddleware(service.NewAuthMiddleware()),
oprpc.WithHTTPRecorder(opmetrics.NewPromHTTPRecorder(s.registry, "signerproxy")),
)
s.proxyService = service.NewSignerProxyService(s.log, proxyClients)
s.proxyService.RegisterAPIs(s.proxy)

if err := s.proxy.Start(); err != nil {
return fmt.Errorf("error starting proxy RPC(WS) server: %w", err)
serviceCfg, err := service.ReadConfig(cfg.ServiceConfigPath)
if err != nil {
return fmt.Errorf("failed to read service config: %w", err)
}
s.log.Info("Started op-signer proxy RPC(WS) server", "addr", s.proxy.Endpoint())
s.signer = service.NewProxySignerService(s.log, serviceCfg, sc)
s.signer.RegisterAPIs(s.rpc)

return nil
if err := s.rpc.Start(); err != nil {
return fmt.Errorf("error starting RPC server: %w", err)
}
s.log.Info("Started op-signer RPC server", "addr", s.rpc.Endpoint())

return nil
}

func (s *SignerApp) ConnectProxy(cfg service.SignerServiceConfig, tlsConfig *tls.Config) {
Expand Down
84 changes: 72 additions & 12 deletions op-signer/service/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,101 @@ package service
import (
"context"
"errors"
"net/url"

"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc"

oprpc "github.com/ethereum-optimism/optimism/op-service/rpc"
"github.com/ethereum-optimism/optimism/op-service/signer"
)

type SignerProxyService struct {
opsignerproxy *OpsignerproxyService
type ProxyWSService struct {
wsProxy *WSService
}

type OpsignerproxyService struct {
type WSService struct {
logger log.Logger

pc *ProxyWSClients
sc *SignerClients
}

func NewSignerProxyService(logger log.Logger, proxyClients *ProxyWSClients) *SignerProxyService {
opsignerproxyService := OpsignerproxyService{logger, proxyClients}
return &SignerProxyService{&opsignerproxyService}
func NewProxyWSService(logger log.Logger, sc *SignerClients) *ProxyWSService {
proxyWSService := WSService{logger, sc}
return &ProxyWSService{&proxyWSService}
}

func (s *SignerProxyService) RegisterAPIs(server *oprpc.Server) {
func (s *ProxyWSService) RegisterAPIs(server *oprpc.Server) {
server.AddAPI(rpc.API{
Namespace: "opsignerproxy",
Service: s.opsignerproxy,
Service: s.wsProxy,
})
}

func (s *OpsignerproxyService) ServeSigner(ctx context.Context) (bool, error) {
func (s *WSService) ServeSigner(ctx context.Context) (bool, error) {
wsClient, ok := rpc.ClientFromContext(ctx)
if !ok {
s.logger.Warn("ws client not provided on opsignerproxy_ServeSigner")
return false, errors.New("ws client not provided on opsignerproxy_ServeSigner")
}
s.pc.wsClients = append(s.pc.wsClients, wsClient)
s.sc.wsClients = append(s.sc.wsClients, wsClient)
return true, nil
}

func NewProxySignerService(logger log.Logger, config SignerServiceConfig, sc *SignerClients) *SignerService {
ethService := EthProxyService{logger, config, sc}
opsignerproxy := OpsignerProxyService{logger, config, sc}
return &SignerService{&ethService, &opsignerproxy}
}

type EthProxyService struct {
logger log.Logger
config SignerServiceConfig
sc *SignerClients
}

func (s *EthProxyService) SignTransaction(ctx context.Context, args signer.TransactionArgs) (hexutil.Bytes, error) {
clientName := ""
u, err := url.Parse(rpc.PeerInfoFromContext(ctx).HTTP.Host)
if err == nil {
clientName = u.Hostname()
} else {
s.logger.Warn("failed to parse ws peer hostname", "err", err)
}

if _, err := s.config.GetAuthConfigForClient(clientName, nil); err != nil {
return nil, rpc.HTTPError{StatusCode: 403, Status: "Forbidden", Body: []byte(err.Error())}
}

var result hexutil.Bytes
if err := s.sc.Call(ctx, &result, "eth_signTransaction", args); err != nil {
return nil, rpc.HTTPError{StatusCode: 500, Status: "Proxy Error", Body: []byte(err.Error())}
}
return result, nil
}

type OpsignerProxyService struct {
logger log.Logger
config SignerServiceConfig
sc *SignerClients
}

func (s *OpsignerProxyService) SignBlockPayload(ctx context.Context, args signer.BlockPayloadArgs) (hexutil.Bytes, error) {
clientName := ""
u, err := url.Parse(rpc.PeerInfoFromContext(ctx).HTTP.Host)
if err == nil {
clientName = u.Hostname()
} else {
s.logger.Warn("failed to parse ws peer hostname", "err", err)
}

if _, err := s.config.GetAuthConfigForClient(clientName, args.SenderAddress); err != nil {
return nil, rpc.HTTPError{StatusCode: 403, Status: "Forbidden", Body: []byte(err.Error())}
}

var result hexutil.Bytes
if err := s.sc.Call(ctx, &result, "eth_signTransaction", args); err != nil {
return nil, rpc.HTTPError{StatusCode: 500, Status: "Proxy Error", Body: []byte(err.Error())}
}
return result, nil
}
Loading

0 comments on commit d9bf70d

Please sign in to comment.