Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add gateway connector capability config #14238

Closed
wants to merge 3 commits into from

Conversation

DavidOrchard
Copy link
Contributor

@DavidOrchard DavidOrchard commented Aug 26, 2024

CAPPL-19

  1. toml/types.go
    add
type ConnectorConfig struct {
type WorkflowConnectorConfig struct {

and add

WorkflowConnector WorkflowConnectorConfig `toml:", omitempty"`

to Capabilities.

  1. core/config/capabilities_config.go
    add
type ConnectorConfig interface {
type ConnectorGatewayConfig interface {
type WorkflowConnectorConfig interface {
  1. services/chainlink/config_capabilities.go
    add
type workflowConnectorConfig struct {
  1. delete core/services/gateway/connector/config.go
  2. core/services/gateway/connector/connector.go
    import config
    update ConnectorConfig to config.ConnectorConfig
    update function var from config to configLocal
    Now has a type error on configLocal.donId, see comment.

@DavidOrchard DavidOrchard added poc Proof of concept DO_NOT_MERGE labels Aug 26, 2024
@DavidOrchard DavidOrchard requested a review from a team as a code owner August 26, 2024 22:46
@DavidOrchard DavidOrchard requested review from krehermann and removed request for a team August 26, 2024 22:46
@cl-sonarqube-production
Copy link

"github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common"
)

type WorkflowConnectorConfig struct {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed in DMs, this need to be a part of node's TOML config.

@DavidOrchard DavidOrchard force-pushed the feature/CAPPL-19-connector-service branch 2 times, most recently from 2167011 to 29f6e46 Compare August 29, 2024 00:57
url *url.URL
wsClient network.WebSocketClient
}

func NewGatewayConnector(config *ConnectorConfig, signer Signer, handler GatewayConnectorHandler, clock clockwork.Clock, lggr logger.Logger) (GatewayConnector, error) {
if config == nil || signer == nil || handler == nil || clock == nil || lggr == nil {
func NewGatewayConnector(configLocal *config.ConnectorConfig, signer Signer, handler GatewayConnectorHandler, clock clockwork.Clock, lggr logger.Logger) (GatewayConnector, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DavidOrchard Your problem is that you're passing in a pointer to an interface and then expecting to use the interface itself.

Interfaces are a bit strange in Golang: they represent a container type over a concrete type and for that reason are typically always passed around by value. The container itself could contain a pointer type though.

You should be able to fix this if you replace -> *config.ConnectorConfig with config.ConnectorConfig

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the original (connector's)ConnectorConfig is a struct. If I want to preserve using a struct, does that mean I should use toml.ConnectorConfig instead of config.ConnectorConfig? Is that appropriate? cc @justinkaseman

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From @cedric-cordenier via slack For config we usually pass around interfaces t is a bit odd as a pattern so your instincts are right, but it's correct in this context

// configLocal.DonId undefined
// (type *"github.com/smartcontractkit/chainlink/v2/core/config".ConnectorConfig
// is pointer to interface, not interface)compilerMissingFieldOrMethod
if len(configLocal.DonId) == 0 || len(configLocal.DonId) > network.HandshakeDonIdLen {
Copy link
Contributor

@cedric-cordenier cedric-cordenier Aug 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additionally, interfaces define a collection of methods a type must have; so the only way to access the underlying type is to call the methods. In other words, you have to call methods to access any attributes.

configLocal.DonId -> configLocal.DonId()

return nil, errors.New("invalid DON ID")
}
addressBytes, err := hex.DecodeString(config.NodeAddress)
addressBytes, err := hex.DecodeString(configLocal.NodeAddress)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

configLocal.NodeAddress -> configLocal.NodeAddress()

NodeAddress() string
DonId() string
Gateways() []ConnectorGatewayConfig
// copied from wsclient.go as can't import
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not?

Copy link
Contributor

@justinkaseman justinkaseman Aug 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a circular dependency in services/gateway/network. @DavidOrchard I think you could make this cleaner by getting rid of that circular dependency in services/gateway/config and then keeping the types in there.

@DavidOrchard DavidOrchard force-pushed the feature/CAPPL-19-connector-service branch from 29f6e46 to c639695 Compare August 29, 2024 22:27
@DavidOrchard DavidOrchard marked this pull request as draft August 29, 2024 22:31
// "github.com/smartcontractkit/chainlink/v2/core/config".WorkflowConnectorConfig value in return statement:
// *workflowConnectorConfig does not implement "github.com/smartcontractkit/chainlink/v2/core/config".WorkflowConnectorConfig (wrong type for method GatewayConnectorConfig)
// have GatewayConnectorConfig() "github.com/smartcontractkit/chainlink/v2/core/config/toml".GatewayConnectorConfig
// want GatewayConnectorConfig() "github.com/smartcontractkit/chainlink/v2/core/config".GatewayConnectorConfigcompilerInvalidIfaceAssign
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your problem here is that Go isn't very smart when it comes to determining whether an interface is satisfied, particularly when there's nesting involved.

toml.GatewayConnectorConfig might on its own satisfy this portion

GatewayConnectorConfig GatewayConnectorConfig json:"gatewayConnectorConfig"``

of the WorkflowConnectorInterface, but your method signature for the implementation needs to match, so line 70

func (c *workflowConnectorConfig) GatewayConnectorConfig() toml.GatewayConnectorConfig

needs to become

func (c *workflowConnectorConfig) GatewayConnectorConfig() GatewayConnectorConfig

}
}

type ConnectorGatewayConfig struct {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: you have both ConnectorGatewayConfig AND GatewayConnectorConfig which is a bit confusing here. Can we be more specific about what each config is for?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that it's confusing. Note that the gateway/connector used to contain

type ConnectorConfig struct {
	NodeAddress               string
	DonId                     string
	Gateways                  []ConnectorGatewayConfig
	WsClientConfig            network.WebSocketClientConfig
	AuthMinChallengeLen       int
	AuthTimestampToleranceSec uint32
}

type ConnectorGatewayConfig struct {
	Id  string
	URL string
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And there's also a GatewayConfig outthere.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can rename this one into something more meaningful, maybe "GatewayNodeAddress" or "GatewayNodeIdentifier" (neither is perfect, though).

// invalid operation: cannot indirect
// c.c.GatewayConnectorConfig (variable of type "github.com/smartcontractkit/chainlink/v2/core/config/toml".ConnectorConfig)
// compilerInvalidIndirection
return c.c.GatewayConnectorConfig
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The toml struct won't be its own satisfy GatewayConnectorConfig since it doesn't have any of the interface methods on it. You'll need to define a wrapper like this and do the mapping of method on the interface to the attribute on the underlying toml fragment yourself.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ty. Having read your comment, now the error seems perfectly clear.

@DavidOrchard DavidOrchard force-pushed the feature/CAPPL-19-connector-service branch from c639695 to e9cf6a8 Compare August 30, 2024 17:21
@DavidOrchard DavidOrchard force-pushed the feature/CAPPL-19-connector-service branch from e9cf6a8 to 44de5da Compare August 30, 2024 19:32
@@ -33,18 +34,21 @@ Id = "another_one"
URL = "wss://example.com:8090/node_endpoint"
`

func parseTOMLConfig(t *testing.T, tomlConfig string) *connector.ConnectorConfig {
var cfg connector.ConnectorConfig
func parseTOMLConfig(t *testing.T, tomlConfig string) *config.ConnectorConfig {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func parseTOMLConfig(t *testing.T, tomlConfig string) *config.ConnectorConfig {
func parseTOMLConfig(t *testing.T, tomlConfig string) *config.GatewayConnectorConfig {

func parseTOMLConfig(t *testing.T, tomlConfig string) *connector.ConnectorConfig {
var cfg connector.ConnectorConfig
func parseTOMLConfig(t *testing.T, tomlConfig string) *config.ConnectorConfig {
var cfg config.ConnectorConfig
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var cfg config.ConnectorConfig
var cfg config.GatewayConnectorConfig

url *url.URL
wsClient network.WebSocketClient
}

func NewGatewayConnector(config *ConnectorConfig, signer Signer, handler GatewayConnectorHandler, clock clockwork.Clock, lggr logger.Logger) (GatewayConnector, error) {
if config == nil || signer == nil || handler == nil || clock == nil || lggr == nil {
func NewGatewayConnector(configLocal config.GatewayConnectorConfig, signer Signer, handler GatewayConnectorHandler, clock clockwork.Clock, lggr logger.Logger) (GatewayConnector, error) {
Copy link
Contributor

@justinkaseman justinkaseman Aug 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

config *ConnectorConfig was a struct, now configLocal config.GatewayConnectorConfig is an interface, which is why you had to change things in this file. It's also causing some breaks in some other files.

@@ -152,6 +153,13 @@ func TestIntegration_Gateway_NoFullNodes_BasicConnectionAndMessage(t *testing.T)

// Launch Connector
client := &client{privateKey: nodeKeys.PrivateKey}
// cannot use parseConnectorConfig(t, nodeConfigTemplate, nodeKeys.Address, nodeUrl)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Breaking from comment on NewGatewayConnector

@@ -83,6 +83,7 @@ func NewFunctionsConnectorHandler(pluginConfig *config.PluginConfig, signerKey *
allowedHeartbeatInitiators[strings.ToLower(initiator)] = struct{}{}
}
return &functionsConnectorHandler{
// pluginConfig.GatewayConnectorConfig.NodeAddress undefined (type *invalid type has no field or method NodeAddress)
Copy link
Contributor

@justinkaseman justinkaseman Aug 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

core/services/ocr2/plugins/functions/config/config.go needs to be updated too

@@ -80,6 +80,7 @@ func TestFunctionsConnectorHandler(t *testing.T) {
subscriptions.On("Start", mock.Anything).Return(nil)
subscriptions.On("Close", mock.Anything).Return(nil)
config := &config.PluginConfig{
// undefined: gwconnector.ConnectorConfigcompilerUndeclaredImportedName
Copy link
Contributor

@justinkaseman justinkaseman Aug 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's looking for ConnectorGatewayConfig struct

// undefined: gwconnector.ConnectorConfigcompilerUndeclaredImportedName
GatewayConnectorConfig: &gwconnector.ConnectorConfig{
config := config.PluginConfig{
// invalid composite literal type "github.com/smartcontractkit/chainlink/v2/core/config".GatewayConnectorConfigcompilerInvalidLit
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to pass in a concrete implementation of the interface

@@ -46,7 +47,7 @@ type GatewayConnectorHandler interface {
type gatewayConnector struct {
services.StateMachine

config *ConnectorConfig
config config.GatewayConnectorConfig
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't need to be changed; keep using the struct (obviously you need the struct)

}

// TODO: verify this copy by reference is ok, or does array need to be copied by value
if f.Gateways != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's fine to just copy by reference here, but when returning the array (i.e. in the interface implementation) you probably do want to copy it

@DavidOrchard
Copy link
Contributor Author

Closed as replaced by newer PR.

@DavidOrchard DavidOrchard deleted the feature/CAPPL-19-connector-service branch September 5, 2024 22:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
DO_NOT_MERGE poc Proof of concept
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants