Skip to content

Commit

Permalink
EVM GRPC provider (#11208)
Browse files Browse the repository at this point in the history
* Initial draft

* Add median provider checks

* Move provider-server to relay

* Bump chainlink-relay version

* Add tests

* Add comment explaining why the code lives inside the newServicesGenericPlugin method

* Fix formatting

* Fix lint
  • Loading branch information
george-dorin authored Nov 13, 2023
1 parent 94625ef commit 0ba7e9a
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 3 deletions.
23 changes: 20 additions & 3 deletions core/services/ocr2/delegate.go
Original file line number Diff line number Diff line change
Expand Up @@ -590,9 +590,26 @@ func (d *Delegate) newServicesGenericPlugin(
}

errorLog := &errorLog{jobID: jb.ID, recordError: d.jobORM.RecordError}
var providerClientConn grpc.ClientConnInterface
providerConn, ok := provider.(connProvider)
if !ok {
return nil, errors.New("provider not supported: the provider is not a LOOPP provider")
if ok {
providerClientConn = providerConn.ClientConn()
} else {
//We chose to deal with the difference between a LOOP provider and an embedded provider here rather than
//in NewServerAdapter because this has a smaller blast radius, as the scope of this workaround is to
//enable the medianpoc for EVM and not touch the other providers.
//TODO: remove this workaround when the EVM relayer is running inside of an LOOPP
d.lggr.Info("provider is not a LOOPP provider, switching to provider server")

ps, err2 := relay.NewProviderServer(provider, types.OCR2PluginType(cconf.ProviderType), d.lggr)
if err2 != nil {
return nil, fmt.Errorf("cannot start EVM provider server: %s", err)
}
providerClientConn, err2 = ps.GetConn()
if err2 != nil {
return nil, fmt.Errorf("cannot connect to EVM provider server: %s", err)
}
srvs = append(srvs, ps)
}

pluginConfig := types.ReportingPluginServiceConfig{
Expand All @@ -606,7 +623,7 @@ func (d *Delegate) newServicesGenericPlugin(
pr := generic.NewPipelineRunnerAdapter(pluginLggr, jb, d.pipelineRunner)
ta := generic.NewTelemetryAdapter(d.monitoringEndpointGen)

plugin := reportingplugins.NewLOOPPService(pluginLggr, grpcOpts, cmdFn, pluginConfig, providerConn.ClientConn(), pr, ta, errorLog)
plugin := reportingplugins.NewLOOPPService(pluginLggr, grpcOpts, cmdFn, pluginConfig, providerClientConn, pr, ta, errorLog)
oracleArgs.ReportingPluginFactory = plugin
srvs = append(srvs, plugin)

Expand Down
68 changes: 68 additions & 0 deletions core/services/relay/grpc_provider_server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package relay

import (
"context"
"net"

"go.uber.org/multierr"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"

"github.com/smartcontractkit/chainlink-relay/pkg/loop"
"github.com/smartcontractkit/chainlink-relay/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
)

type ProviderServer struct {
s *grpc.Server
lis net.Listener
lggr logger.Logger
conns []*grpc.ClientConn
}

func (p *ProviderServer) Start(ctx context.Context) error {
p.serve()
return nil
}

func (p *ProviderServer) Close() error {
var err error
for _, c := range p.conns {
err = multierr.Combine(err, c.Close())
}
p.s.Stop()
return err
}

func (p *ProviderServer) GetConn() (*grpc.ClientConn, error) {
cc, err := grpc.Dial(p.lis.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
p.conns = append(p.conns, cc)
return cc, err
}

// NewProviderServer creates a GRPC server that will wrap a provider, this is a workaround to test the Node API PoC until the EVM relayer is loopifyed
func NewProviderServer(p types.PluginProvider, pType types.OCR2PluginType, lggr logger.Logger) (*ProviderServer, error) {
lis, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
return nil, err
}
ps := ProviderServer{
s: grpc.NewServer(),
lis: lis,
lggr: lggr.Named("EVM.ProviderServer"),
}
err = loop.RegisterStandAloneProvider(ps.s, p, pType)
if err != nil {
return nil, err
}

return &ps, nil
}

func (p *ProviderServer) serve() {
go func() {
if err := p.s.Serve(p.lis); err != nil {
p.lggr.Errorf("Failed to serve EVM provider server: %v", err)
}
}()
}
27 changes: 27 additions & 0 deletions core/services/relay/grpc_provider_server_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package relay

import (
"context"
"testing"

"github.com/stretchr/testify/require"

"github.com/smartcontractkit/chainlink-relay/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/logger"
)

func TestProviderServer(t *testing.T) {
r := &mockRelayer{}
sa := NewServerAdapter(r, mockRelayerExt{})
mp, _ := sa.NewPluginProvider(context.Background(), types.RelayArgs{ProviderType: string(types.Median)}, types.PluginArgs{})

lggr := logger.TestLogger(t)
_, err := NewProviderServer(mp, "unsupported-type", lggr)
require.Error(t, err)

ps, err := NewProviderServer(staticMedianProvider{}, types.Median, lggr)
require.NoError(t, err)

_, err = ps.GetConn()
require.NoError(t, err)
}
26 changes: 26 additions & 0 deletions core/services/relay/relay_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"context"
"testing"

"github.com/smartcontractkit/libocr/offchainreporting2/reportingplugin/median"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
"github.com/stretchr/testify/assert"

"github.com/smartcontractkit/chainlink-relay/pkg/loop"
Expand Down Expand Up @@ -61,6 +63,30 @@ type staticMedianProvider struct {
types.MedianProvider
}

func (s staticMedianProvider) OffchainConfigDigester() ocrtypes.OffchainConfigDigester {
return nil
}

func (s staticMedianProvider) ContractConfigTracker() ocrtypes.ContractConfigTracker {
return nil
}

func (s staticMedianProvider) ContractTransmitter() ocrtypes.ContractTransmitter {
return nil
}

func (s staticMedianProvider) ReportCodec() median.ReportCodec {
return nil
}

func (s staticMedianProvider) MedianContract() median.MedianContract {
return nil
}

func (s staticMedianProvider) OnchainConfigCodec() median.OnchainConfigCodec {
return nil
}

type staticFunctionsProvider struct {
types.FunctionsProvider
}
Expand Down

0 comments on commit 0ba7e9a

Please sign in to comment.