Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@

env_vars = { CL_EVM_CMD = "" }
capabilities = ["ocr3", "custom-compute", "web-api-trigger", "cron", "http-action", "http-trigger", "consensus", "don-time"]
registry_based_launch_allowlist = ["cron-trigger@1.0.0"]

# See ./examples/workflow-don-overrides.toml to learn how to override capability configs

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

env_vars = { CL_EVM_CMD = "" }
capabilities = ["ocr3", "custom-compute", "web-api-target", "web-api-trigger", "vault", "cron", "http-action", "http-trigger", "consensus", "don-time", "write-evm-1337", "write-evm-3360022319", "read-contract-1337", "read-contract-3360022319"]
registry_based_launch_allowlist = ["cron-trigger@1.0.0"]

# See ./examples/workflow-don-overrides.toml to learn how to override capability configs

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@

env_vars = { CL_EVM_CMD = "" }
capabilities = ["ocr3", "custom-compute", "web-api-trigger", "cron", "http-action", "http-trigger", "consensus", "don-time", "write-evm-1337", "read-contract-1337", "evm-1337"]
registry_based_launch_allowlist = ["cron-trigger@1.0.0"]

# See ./examples/workflow-don-overrides.toml to learn how to override capability configs

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@

env_vars = { CL_EVM_CMD = "" }
capabilities = ["ocr3", "custom-compute", "web-api-target", "web-api-trigger", "vault", "cron", "http-action", "http-trigger", "consensus", "don-time", "write-evm-1337", "write-evm-2337", "read-contract-1337", "read-contract-2337", "evm-1337", "evm-2337"]
registry_based_launch_allowlist = ["cron-trigger@1.0.0"]

# See ./examples/workflow-don-overrides.toml to learn how to override capability configs

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@

env_vars = { CL_EVM_CMD = "" }
capabilities = ["ocr3", "custom-compute", "web-api-target", "web-api-trigger", "vault", "cron", "http-action", "http-trigger", "consensus", "don-time", "write-evm-1337", "write-evm-2337", "evm-1337", "evm-2337", "read-contract-1337", "read-contract-2337"]
registry_based_launch_allowlist = ["cron-trigger@1.0.0"]

[nodesets.db]
image = "postgres:12.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@

env_vars = { CL_EVM_CMD = "" }
capabilities = ["ocr3", "custom-compute", "web-api-target", "web-api-trigger", "vault", "cron", "http-action", "http-trigger", "consensus", "don-time", "write-evm-1337", "read-contract-1337", "evm-1337", "write-evm-2337", "read-contract-2337", "evm-2337"]
registry_based_launch_allowlist = ["cron-trigger@1.0.0"]

# See ./examples/workflow-don-overrides.toml to learn how to override capability configs

Expand Down Expand Up @@ -100,6 +101,7 @@
env_vars = { CL_EVM_CMD = "" }
# add "vault", "http-action", "http-trigger", when gateway can support more than 1 DON per service
capabilities = ["ocr3", "custom-compute", "web-api-target", "web-api-trigger", "cron", "consensus", "don-time", "write-evm-1337", "read-contract-1337", "evm-1337", "write-evm-2337", "read-contract-2337", "evm-2337"]
registry_based_launch_allowlist = ["cron-trigger@1.0.0"]

# See ./examples/workflow-don-overrides.toml to learn how to override capability configs

Expand Down Expand Up @@ -127,6 +129,7 @@
env_vars = { CL_EVM_CMD = "" }
# add "vault", "http-action", "http-trigger", when gateway can support more than 1 DON per service
capabilities = ["ocr3", "custom-compute", "web-api-target", "web-api-trigger", "cron", "consensus", "don-time", "write-evm-1337", "read-contract-1337", "evm-1337", "write-evm-2337", "read-contract-2337", "evm-2337"]
registry_based_launch_allowlist = ["cron-trigger@1.0.0"]

# See ./examples/workflow-don-overrides.toml to learn how to override capability configs

Expand Down Expand Up @@ -154,6 +157,7 @@
env_vars = { CL_EVM_CMD = "" }
# add "vault", "http-action", "http-trigger", when gateway can support more than 1 DON per service
capabilities = ["ocr3", "custom-compute", "web-api-target", "web-api-trigger", "cron", "consensus", "don-time", "write-evm-1337", "read-contract-1337", "evm-1337", "write-evm-2337", "read-contract-2337", "evm-2337"]
registry_based_launch_allowlist = ["cron-trigger@1.0.0"]

# See ./examples/workflow-don-overrides.toml to learn how to override capability configs

Expand Down Expand Up @@ -181,6 +185,7 @@
env_vars = { CL_EVM_CMD = "" }
# add "vault", "http-action", "http-trigger", when gateway can support more than 1 DON per service
capabilities = ["ocr3", "custom-compute", "web-api-target", "web-api-trigger", "cron", "consensus", "don-time", "write-evm-1337", "read-contract-1337", "evm-1337", "write-evm-2337", "read-contract-2337", "evm-2337"]
registry_based_launch_allowlist = ["cron-trigger@1.0.0"]

# See ./examples/workflow-don-overrides.toml to learn how to override capability configs

Expand Down Expand Up @@ -208,6 +213,7 @@
env_vars = { CL_EVM_CMD = "" }
# add "vault", "http-action", "http-trigger", when gateway can support more than 1 DON per service
capabilities = ["ocr3", "custom-compute", "web-api-target", "web-api-trigger", "cron", "consensus", "don-time", "write-evm-1337", "read-contract-1337", "evm-1337", "write-evm-2337", "read-contract-2337", "evm-2337"]
registry_based_launch_allowlist = ["cron-trigger@1.0.0"]

# See ./examples/workflow-don-overrides.toml to learn how to override capability configs

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

env_vars = { CL_EVM_CMD = "" }
capabilities = ["ocr3", "custom-compute", "web-api-target", "web-api-trigger", "vault", "cron", "http-action", "http-trigger", "consensus", "don-time", "write-evm-1337", "read-contract-1337", "evm-1337", "write-evm-2337", "read-contract-2337", "evm-2337"]
registry_based_launch_allowlist = ["cron-trigger@1.0.0"]

# See ./examples/workflow-don-overrides.toml to learn how to override capability configs

Expand Down Expand Up @@ -101,6 +102,7 @@
env_vars = { CL_EVM_CMD = "" }
# add "vault", "http-action", "http-trigger", when gateway can support more than 1 DON per service
capabilities = ["ocr3", "custom-compute", "web-api-target", "web-api-trigger", "cron", "consensus", "don-time", "write-evm-1337", "read-contract-1337", "evm-1337", "write-evm-2337", "read-contract-2337", "evm-2337"]
registry_based_launch_allowlist = ["cron-trigger@1.0.0"]

# See ./examples/workflow-don-overrides.toml to learn how to override capability configs

Expand Down
9 changes: 6 additions & 3 deletions core/services/chainlink/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -666,9 +666,12 @@ func NewApplication(ctx context.Context, opts ApplicationOpts) (Application, err
)
delegates[job.StandardCapabilities] = stdcapDelegate
if creServices.SetDelegatesDeps != nil {
err = creServices.SetDelegatesDeps(stdcapDelegate)
if err != nil {
return nil, fmt.Errorf("failed to set CRE delegates dependencies: %w", err)
depSvc, depErr := creServices.SetDelegatesDeps(stdcapDelegate)
if depErr != nil {
return nil, fmt.Errorf("failed to set CRE delegates dependencies: %w", depErr)
}
if depSvc != nil {
srvcs = append(srvcs, depSvc)
}
}

Expand Down
11 changes: 4 additions & 7 deletions core/services/cre/cre.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ type Services struct {
OCRConfigService capregconfig.OCRConfigService

// callback to wire Delegates into CRE services (e.g. Launcher) when ready
SetDelegatesDeps func(*standardcapabilities.Delegate) error
SetDelegatesDeps func(*standardcapabilities.Delegate) (commonsrv.Service, error)
}

func (s *Services) close() error {
Expand Down Expand Up @@ -409,19 +409,16 @@ func (s *Services) newRegistrySyncer(
// callback to wire LocalCapabilityManager into the launcher if local capabilities are configured.
localCfg := cfg.Capabilities().Local()
if localCfg != nil && len(localCfg.RegistryBasedLaunchAllowlist()) > 0 {
// will be called when the Delegate is ready
s.SetDelegatesDeps = func(stdcapDelegate *standardcapabilities.Delegate) error {
// abstraction for the Delegate
s.SetDelegatesDeps = func(stdcapDelegate *standardcapabilities.Delegate) (commonsrv.Service, error) {
newServicesFn := func(ctx context.Context, capID string, command string, configJSON string) ([]job.ServiceCtx, error) {
return stdcapDelegate.NewServices(ctx, command, configJSON, 0, capID, uuid.New(), job.OracleFactoryConfig{})
}
localCapMgr, lcmErr := localcapmgr.NewLocalCapabilityManager(lggr, localCfg, newServicesFn)
if lcmErr != nil {
return fmt.Errorf("could not create local capability manager: %w", lcmErr)
return nil, fmt.Errorf("could not create local capability manager: %w", lcmErr)
}
wfLauncher.SetLocalCapabilityManager(localCapMgr)
srvcs = append(srvcs, localCapMgr) // srvcs is still valid when the callback is called
return nil
return localCapMgr, nil
}
}

Expand Down
4 changes: 4 additions & 0 deletions core/services/gateway/connectionmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,10 @@ func (m *donConnectionManager) getHandler(method string) (handlers.Handler, erro
}
}
serviceName := strings.Split(method, ".")[0]
// Special case for legacy methods - default to "workflows" service.
if !strings.Contains(method, ".") {
serviceName = "workflows"
}
handler, ok := m.handlers[serviceName]
if !ok {
return nil, fmt.Errorf("no handler for service %q (method %q)", serviceName, method)
Expand Down
14 changes: 7 additions & 7 deletions core/services/gateway/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,17 @@ func setupFromNewConfig(

donNameToConfig := make(map[string]config.ShardedDONConfig)
for _, don := range cfg.ShardedDONs {
for si, shard := range don.Shards {
for ni, node := range shard.Nodes {
don.Shards[si].Nodes[ni].Address = strings.ToLower(node.Address)
}
}
donNameToConfig[don.DonName] = don
}

assignedDONs := make(map[string]struct{})
// For each service, create a MultiHandler with its handlers and attached DONs
// Each DON can belong to multiple services. Each service can have multiple handlers.
// In practice, each handler is associated with a single service (either 'workflows' or 'vault').
for _, svc := range cfg.Services {
var shardedDONs []config.ShardedDONConfig
var shardsConnMgrs [][]handlers.DON
Expand All @@ -131,12 +137,6 @@ func setupFromNewConfig(
if !ok {
return nil, fmt.Errorf("service %q references unknown DON: %s", svc.ServiceName, donName)
}
if _, assigned := assignedDONs[donName]; assigned {
// NOTE: this check can be relaxed in the future once we clean up all "service.method" strings
// and split them correctly in Multihandler
return nil, fmt.Errorf("DON %q is assigned to multiple services", donName)
}
assignedDONs[donName] = struct{}{}
shardedDONs = append(shardedDONs, donCfg)

var shardConnMgrs []handlers.DON
Expand Down
121 changes: 121 additions & 0 deletions core/services/gateway/gateway_internal_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package gateway

import (
"encoding/json"
"testing"

"github.com/jonboulle/clockwork"
"github.com/stretchr/testify/require"

"github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/chainlink-common/pkg/settings/limits"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/config"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers"
handlermocks "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/mocks"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/monitoring"
gw_net "github.com/smartcontractkit/chainlink/v2/core/services/gateway/network"
)

type capturingHandlerFactory struct {
t *testing.T
handlers map[HandlerType]handlers.Handler
calls map[HandlerType][]config.ShardedDONConfig
}

func (f *capturingHandlerFactory) NewHandler(handlerType HandlerType, _ json.RawMessage, shardedDONs []config.ShardedDONConfig, _ [][]handlers.DON) (handlers.Handler, error) {
f.calls[handlerType] = shardedDONs
h, ok := f.handlers[handlerType]
require.True(f.t, ok, "missing test handler for type %q", handlerType)
return h, nil
}

func TestSetupFromNewConfig_SharedDONAndLegacyMethodRouting(t *testing.T) {
t.Parallel()

lggr := logger.Test(t)
gMetrics, err := monitoring.NewGatewayMetrics()
require.NoError(t, err)

cfg := &config.GatewayConfig{
NodeServerConfig: gw_net.WebSocketServerConfig{
HTTPServerConfig: gw_net.HTTPServerConfig{Path: "/node"},
},
ShardedDONs: []config.ShardedDONConfig{
{
DonName: "shared-don",
F: 0,
Shards: []config.Shard{
{
Nodes: []config.NodeConfig{
{
Name: "node-1",
Address: "0x68902D681C28119F9B2531473A417088BF008E59",
},
},
},
},
},
},
Services: []config.ServiceConfig{
{
ServiceName: "workflows",
DONs: []string{"shared-don"},
Handlers: []config.Handler{
{Name: "workflows-handler"},
},
},
{
ServiceName: "vault",
DONs: []string{"shared-don"},
Handlers: []config.Handler{
{Name: "vault-handler"},
},
},
},
}

connMgr, err := NewConnectionManager(cfg, clockwork.NewFakeClock(), gMetrics, lggr, limits.Factory{Logger: lggr})
require.NoError(t, err)

workflowsHandler := handlermocks.NewHandler(t)
workflowsHandler.On("Methods").Return([]string{"workflows.execute"})
vaultHandler := handlermocks.NewHandler(t)
vaultHandler.On("Methods").Return([]string{"vault.store"})

factory := &capturingHandlerFactory{
t: t,
handlers: map[HandlerType]handlers.Handler{
"workflows-handler": workflowsHandler,
"vault-handler": vaultHandler,
},
calls: make(map[HandlerType][]config.ShardedDONConfig),
}

serviceToHandler, err := setupFromNewConfig(cfg, factory, connMgr, lggr)
require.NoError(t, err)
require.Len(t, serviceToHandler, 2, "shared DON should be attachable to multiple services")
require.NotNil(t, serviceToHandler["workflows"])
require.NotNil(t, serviceToHandler["vault"])

require.Equal(t,
"0x68902d681c28119f9b2531473a417088bf008e59",
factory.calls["workflows-handler"][0].Shards[0].Nodes[0].Address,
"setupFromNewConfig should normalize node addresses before passing DON configs to handlers",
)
require.Equal(t,
"0x68902d681c28119f9b2531473a417088bf008e59",
factory.calls["vault-handler"][0].Shards[0].Nodes[0].Address,
"setupFromNewConfig should normalize node addresses before passing DON configs to handlers",
)

donConnMgr := connMgr.DONConnectionManager(config.ShardDONID("shared-don", 0))
require.NotNil(t, donConnMgr)

legacyHandler, err := donConnMgr.getHandler("legacyMethodWithoutServicePrefix")
require.NoError(t, err)
require.Same(t, serviceToHandler["workflows"], legacyHandler, "legacy methods should route to workflows service")

vaultMethodHandler, err := donConnMgr.getHandler("vault.store")
require.NoError(t, err)
require.Same(t, serviceToHandler["vault"], vaultMethodHandler, "service-prefixed methods should route by prefix")
}
6 changes: 1 addition & 5 deletions deployment/cre/jobs/ring.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,7 @@ func verifyRingJobSpecInputs(inputs job_types.JobSpecInput) error {
return errors.New("chainSelectorEVM is required")
}

if strings.TrimSpace(ringInput.ShardConfigAddr) == "" {
return errors.New("shardConfigAddr is required")
}

if !common.IsHexAddress(ringInput.ShardConfigAddr) {
if ringInput.ShardConfigAddr != "" && !common.IsHexAddress(ringInput.ShardConfigAddr) {
return errors.New("shardConfigAddr is invalid: not a valid hex address")
}

Expand Down
6 changes: 6 additions & 0 deletions system-tests/lib/cre/don/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,12 @@ func addWorkerNodeConfig(
WorkflowRegistry: existingWorkflowRegistry,
}

if len(donMetadata.RegistryBasedLaunchAllowlist) > 0 {
existingConfig.Capabilities.Local = coretoml.LocalCapabilities{
RegistryBasedLaunchAllowlist: donMetadata.RegistryBasedLaunchAllowlist,
}
}

for _, evmChain := range commonInputs.evmChains {
appendEVMChain(&existingConfig.EVM, evmChain)
}
Expand Down
Loading
Loading