diff --git a/.changeset/four-eggs-invite.md b/.changeset/four-eggs-invite.md new file mode 100644 index 00000000000..46dac304a10 --- /dev/null +++ b/.changeset/four-eggs-invite.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +configuration updates diff --git a/core/config/capabilities_config.go b/core/config/capabilities_config.go index 8c10896d093..b7e5a3b86a7 100644 --- a/core/config/capabilities_config.go +++ b/core/config/capabilities_config.go @@ -11,8 +11,24 @@ type CapabilitiesExternalRegistry interface { RelayID() types.RelayID } +type GatewayConnector interface { + ChainIDForNodeKey() string + NodeAddress() string + DonID() string + Gateways() []ConnectorGateway + WSHandshakeTimeoutMillis() uint32 + AuthMinChallengeLen() int + AuthTimestampToleranceSec() uint32 +} + +type ConnectorGateway interface { + ID() string + URL() string +} + type Capabilities interface { Peering() P2P Dispatcher() Dispatcher ExternalRegistry() CapabilitiesExternalRegistry + GatewayConnector() GatewayConnector } diff --git a/core/config/docs/core.toml b/core/config/docs/core.toml index e8524c29186..2f7ff847e4b 100644 --- a/core/config/docs/core.toml +++ b/core/config/docs/core.toml @@ -509,6 +509,26 @@ DeltaReconcile = '1m' # Default # but the host and port must be fully specified and cannot be empty. You can specify `0.0.0.0` (IPv4) or `::` (IPv6) to listen on all interfaces, but that is not recommended. ListenAddresses = ['1.2.3.4:9999', '[a52d:0:a88:1274::abcd]:1337'] # Example +[Capabilities.GatewayConnector] +# ChainIDForNodeKey is the ChainID of the network associated with a private key to be used for authentication with Gateway nodes +ChainIDForNodeKey = '11155111' # Example +# NodeAddress is the address of the desired private key to be used for authentication with Gateway nodes +NodeAddress = '0x68902d681c28119f9b2531473a417088bf008e59' # Example +# DonID is the Id of the Don +DonID = 'example_don' # Example +# WSHandshakeTimeoutMillis is Websocket handshake timeout +WSHandshakeTimeoutMillis = 1000 # Example +# AuthMinChallengeLen is the minimum number of bytes in authentication challenge payload +AuthMinChallengeLen = 10 # Example +# AuthTimestampToleranceSec is Authentication timestamp tolerance +AuthTimestampToleranceSec = 10 # Example + +[[Capabilities.GatewayConnector.Gateways]] +# ID of the Gateway +ID = 'example_gateway' # Example +# URL of the Gateway +URL = 'wss://localhost:8081/node' # Example + [Keeper] # **ADVANCED** # DefaultTransactionQueueDepth controls the queue size for `DropOldestStrategy` in Keeper. Set to 0 to use `SendEvery` strategy instead. diff --git a/core/config/toml/types.go b/core/config/toml/types.go index 47c8cb46b70..f89ecab9c08 100644 --- a/core/config/toml/types.go +++ b/core/config/toml/types.go @@ -5,6 +5,7 @@ import ( "fmt" "net" "net/url" + "reflect" "regexp" "strings" @@ -25,6 +26,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/store/dialects" "github.com/smartcontractkit/chainlink/v2/core/store/models" "github.com/smartcontractkit/chainlink/v2/core/utils" + configutils "github.com/smartcontractkit/chainlink/v2/core/utils/config" ) @@ -1478,16 +1480,63 @@ func (drl *DispatcherRateLimit) setFrom(f *DispatcherRateLimit) { } } +type GatewayConnector struct { + ChainIDForNodeKey *string + NodeAddress *string + DonID *string + Gateways []ConnectorGateway + WSHandshakeTimeoutMillis *uint32 + AuthMinChallengeLen *int + AuthTimestampToleranceSec *uint32 +} + +func (r *GatewayConnector) setFrom(f *GatewayConnector) { + if f.ChainIDForNodeKey != nil { + r.ChainIDForNodeKey = f.ChainIDForNodeKey + } + + if f.NodeAddress != nil { + r.NodeAddress = f.NodeAddress + } + + if f.DonID != nil { + r.DonID = f.DonID + } + + if f.Gateways != nil { + r.Gateways = f.Gateways + } + + if !reflect.ValueOf(f.WSHandshakeTimeoutMillis).IsZero() { + r.WSHandshakeTimeoutMillis = f.WSHandshakeTimeoutMillis + } + + if f.AuthMinChallengeLen != nil { + r.AuthMinChallengeLen = f.AuthMinChallengeLen + } + + if f.AuthTimestampToleranceSec != nil { + r.AuthTimestampToleranceSec = f.AuthTimestampToleranceSec + } +} + +type ConnectorGateway struct { + ID *string + URL *string +} + type Capabilities struct { Peering P2P `toml:",omitempty"` Dispatcher Dispatcher `toml:",omitempty"` ExternalRegistry ExternalRegistry `toml:",omitempty"` + GatewayConnector GatewayConnector `toml:",omitempty"` } func (c *Capabilities) setFrom(f *Capabilities) { c.Peering.setFrom(&f.Peering) c.ExternalRegistry.setFrom(&f.ExternalRegistry) c.Dispatcher.setFrom(&f.Dispatcher) + c.GatewayConnector.setFrom(&f.GatewayConnector) } type ThresholdKeyShareSecrets struct { diff --git a/core/services/chainlink/config_capabilities.go b/core/services/chainlink/config_capabilities.go index 734a5ae2701..032eec58bea 100644 --- a/core/services/chainlink/config_capabilities.go +++ b/core/services/chainlink/config_capabilities.go @@ -1,10 +1,9 @@ package chainlink import ( + "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/config/toml" - - "github.com/smartcontractkit/chainlink-common/pkg/types" ) var _ config.Capabilities = (*capabilitiesConfig)(nil) @@ -63,6 +62,12 @@ func (r *dispatcherRateLimit) PerSenderBurst() int { return *r.r.PerSenderBurst } +func (c *capabilitiesConfig) GatewayConnector() config.GatewayConnector { + return &gatewayConnector{ + c: c.c.GatewayConnector, + } +} + type capabilitiesExternalRegistry struct { c toml.ExternalRegistry } @@ -82,3 +87,50 @@ func (c *capabilitiesExternalRegistry) ChainID() string { func (c *capabilitiesExternalRegistry) Address() string { return *c.c.Address } + +type gatewayConnector struct { + c toml.GatewayConnector +} + +func (c *gatewayConnector) ChainIDForNodeKey() string { + return *c.c.ChainIDForNodeKey +} +func (c *gatewayConnector) NodeAddress() string { + return *c.c.NodeAddress +} + +func (c *gatewayConnector) DonID() string { + return *c.c.DonID +} + +func (c *gatewayConnector) Gateways() []config.ConnectorGateway { + t := make([]config.ConnectorGateway, len(c.c.Gateways)) + for index, element := range c.c.Gateways { + t[index] = &connectorGateway{element} + } + return t +} + +func (c *gatewayConnector) WSHandshakeTimeoutMillis() uint32 { + return *c.c.WSHandshakeTimeoutMillis +} + +func (c *gatewayConnector) AuthMinChallengeLen() int { + return *c.c.AuthMinChallengeLen +} + +func (c *gatewayConnector) AuthTimestampToleranceSec() uint32 { + return *c.c.AuthTimestampToleranceSec +} + +type connectorGateway struct { + c toml.ConnectorGateway +} + +func (c *connectorGateway) ID() string { + return *c.c.ID +} + +func (c *connectorGateway) URL() string { + return *c.c.URL +} diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index 7b915833085..cba3c9ea054 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -462,6 +462,17 @@ func TestConfig_Marshal(t *testing.T) { PerSenderBurst: ptr(50), }, }, + GatewayConnector: toml.GatewayConnector{ + ChainIDForNodeKey: ptr("11155111"), + NodeAddress: ptr("0x68902d681c28119f9b2531473a417088bf008e59"), + DonID: ptr("example_don"), + WSHandshakeTimeoutMillis: ptr[uint32](100), + AuthMinChallengeLen: ptr[int](10), + AuthTimestampToleranceSec: ptr[uint32](10), + Gateways: []toml.ConnectorGateway{ + {ID: ptr("example_gateway"), URL: ptr("wss://localhost:8081/node")}, + }, + }, } full.Keeper = toml.Keeper{ DefaultTransactionQueueDepth: ptr[uint32](17), diff --git a/core/services/chainlink/testdata/config-empty-effective.toml b/core/services/chainlink/testdata/config-empty-effective.toml index 6050401634a..aff50754280 100644 --- a/core/services/chainlink/testdata/config-empty-effective.toml +++ b/core/services/chainlink/testdata/config-empty-effective.toml @@ -267,3 +267,15 @@ PerSenderBurst = 50 Address = '' NetworkID = 'evm' ChainID = '1' + +[Capabilities.GatewayConnector] +ChainIDForNodeKey = '' +NodeAddress = '' +DonID = '' +WSHandshakeTimeoutMillis = 0 +AuthMinChallengeLen = 0 +AuthTimestampToleranceSec = 0 + +[[Capabilities.GatewayConnector.Gateways]] +ID = '' +URL = '' diff --git a/core/services/chainlink/testdata/config-full.toml b/core/services/chainlink/testdata/config-full.toml index 80d2ca7fbbd..2202c601925 100644 --- a/core/services/chainlink/testdata/config-full.toml +++ b/core/services/chainlink/testdata/config-full.toml @@ -278,6 +278,18 @@ Address = '' NetworkID = 'evm' ChainID = '1' +[Capabilities.GatewayConnector] +ChainIDForNodeKey = '11155111' +NodeAddress = '0x68902d681c28119f9b2531473a417088bf008e59' +DonID = 'example_don' +WSHandshakeTimeoutMillis = 100 +AuthMinChallengeLen = 10 +AuthTimestampToleranceSec = 10 + +[[Capabilities.GatewayConnector.Gateways]] +ID = 'example_gateway' +URL = 'wss://localhost:8081/node' + [[EVM]] ChainID = '1' Enabled = false diff --git a/core/services/chainlink/testdata/config-multi-chain-effective.toml b/core/services/chainlink/testdata/config-multi-chain-effective.toml index 6a1cda457e5..91d00841def 100644 --- a/core/services/chainlink/testdata/config-multi-chain-effective.toml +++ b/core/services/chainlink/testdata/config-multi-chain-effective.toml @@ -268,6 +268,18 @@ Address = '' NetworkID = 'evm' ChainID = '1' +[Capabilities.GatewayConnector] +ChainIDForNodeKey = '' +NodeAddress = '' +DonID = '' +WSHandshakeTimeoutMillis = 0 +AuthMinChallengeLen = 0 +AuthTimestampToleranceSec = 0 + +[[Capabilities.GatewayConnector.Gateways]] +ID = '' +URL = '' + [[EVM]] ChainID = '1' AutoCreateKey = true diff --git a/core/web/resolver/testdata/config-empty-effective.toml b/core/web/resolver/testdata/config-empty-effective.toml index 6050401634a..aff50754280 100644 --- a/core/web/resolver/testdata/config-empty-effective.toml +++ b/core/web/resolver/testdata/config-empty-effective.toml @@ -267,3 +267,15 @@ PerSenderBurst = 50 Address = '' NetworkID = 'evm' ChainID = '1' + +[Capabilities.GatewayConnector] +ChainIDForNodeKey = '' +NodeAddress = '' +DonID = '' +WSHandshakeTimeoutMillis = 0 +AuthMinChallengeLen = 0 +AuthTimestampToleranceSec = 0 + +[[Capabilities.GatewayConnector.Gateways]] +ID = '' +URL = '' diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml index c10f68dd242..f50e3c76adf 100644 --- a/core/web/resolver/testdata/config-full.toml +++ b/core/web/resolver/testdata/config-full.toml @@ -278,6 +278,18 @@ Address = '' NetworkID = 'evm' ChainID = '1' +[Capabilities.GatewayConnector] +ChainIDForNodeKey = '11155111' +NodeAddress = '0x68902d681c28119f9b2531473a417088bf008e59' +DonID = 'example_don' +WSHandshakeTimeoutMillis = 100 +AuthMinChallengeLen = 10 +AuthTimestampToleranceSec = 10 + +[[Capabilities.GatewayConnector.Gateways]] +ID = 'example_gateway' +URL = 'wss://localhost:8081/node' + [[EVM]] ChainID = '1' Enabled = false diff --git a/core/web/resolver/testdata/config-multi-chain-effective.toml b/core/web/resolver/testdata/config-multi-chain-effective.toml index d7513ada267..5e68ba21d1e 100644 --- a/core/web/resolver/testdata/config-multi-chain-effective.toml +++ b/core/web/resolver/testdata/config-multi-chain-effective.toml @@ -268,6 +268,18 @@ Address = '' NetworkID = 'evm' ChainID = '1' +[Capabilities.GatewayConnector] +ChainIDForNodeKey = '' +NodeAddress = '' +DonID = '' +WSHandshakeTimeoutMillis = 0 +AuthMinChallengeLen = 0 +AuthTimestampToleranceSec = 0 + +[[Capabilities.GatewayConnector.Gateways]] +ID = '' +URL = '' + [[EVM]] ChainID = '1' AutoCreateKey = true diff --git a/docs/CONFIG.md b/docs/CONFIG.md index 66ce21a21ea..e3d5058a3b4 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -1393,6 +1393,74 @@ ListenAddresses = ['1.2.3.4:9999', '[a52d:0:a88:1274::abcd]:1337'] # Example ListenAddresses is the addresses the peer will listen to on the network in `host:port` form as accepted by `net.Listen()`, but the host and port must be fully specified and cannot be empty. You can specify `0.0.0.0` (IPv4) or `::` (IPv6) to listen on all interfaces, but that is not recommended. +## Capabilities.GatewayConnector +```toml +[Capabilities.GatewayConnector] +ChainIDForNodeKey = '11155111' # Example +NodeAddress = '0x68902d681c28119f9b2531473a417088bf008e59' # Example +DonID = 'example_don' # Example +WSHandshakeTimeoutMillis = 1000 # Example +AuthMinChallengeLen = 10 # Example +AuthTimestampToleranceSec = 10 # Example +``` + + +### ChainIDForNodeKey +```toml +ChainIDForNodeKey = '11155111' # Example +``` +ChainIDForNodeKey is the ChainID of the network associated with a private key to be used for authentication with Gateway nodes + +### NodeAddress +```toml +NodeAddress = '0x68902d681c28119f9b2531473a417088bf008e59' # Example +``` +NodeAddress is the address of the desired private key to be used for authentication with Gateway nodes + +### DonID +```toml +DonID = 'example_don' # Example +``` +DonID is the Id of the Don + +### WSHandshakeTimeoutMillis +```toml +WSHandshakeTimeoutMillis = 1000 # Example +``` +WSHandshakeTimeoutMillis is Websocket handshake timeout + +### AuthMinChallengeLen +```toml +AuthMinChallengeLen = 10 # Example +``` +AuthMinChallengeLen is the minimum number of bytes in authentication challenge payload + +### AuthTimestampToleranceSec +```toml +AuthTimestampToleranceSec = 10 # Example +``` +AuthTimestampToleranceSec is Authentication timestamp tolerance + +## Capabilities.GatewayConnector.Gateways +```toml +[[Capabilities.GatewayConnector.Gateways]] +ID = 'example_gateway' # Example +URL = 'wss://localhost:8081/node' # Example +``` + + +### ID +```toml +ID = 'example_gateway' # Example +``` +ID of the Gateway + +### URL +```toml +URL = 'wss://localhost:8081/node' # Example +``` +URL of the Gateway + ## Keeper ```toml [Keeper] diff --git a/testdata/scripts/node/db/help.txtar b/testdata/scripts/node/db/help.txtar index 4f2fe3e0767..ccdf3431786 100644 --- a/testdata/scripts/node/db/help.txtar +++ b/testdata/scripts/node/db/help.txtar @@ -20,4 +20,4 @@ COMMANDS: OPTIONS: --help, -h show help - \ No newline at end of file + diff --git a/testdata/scripts/node/validate/default.txtar b/testdata/scripts/node/validate/default.txtar index cca4f4ef5e0..1177b0d97e3 100644 --- a/testdata/scripts/node/validate/default.txtar +++ b/testdata/scripts/node/validate/default.txtar @@ -280,6 +280,18 @@ Address = '' NetworkID = 'evm' ChainID = '1' +[Capabilities.GatewayConnector] +ChainIDForNodeKey = '' +NodeAddress = '' +DonID = '' +WSHandshakeTimeoutMillis = 0 +AuthMinChallengeLen = 0 +AuthTimestampToleranceSec = 0 + +[[Capabilities.GatewayConnector.Gateways]] +ID = '' +URL = '' + Invalid configuration: invalid secrets: 2 errors: - Database.URL: empty: must be provided and non-empty - Password.Keystore: empty: must be provided and non-empty diff --git a/testdata/scripts/node/validate/defaults-override.txtar b/testdata/scripts/node/validate/defaults-override.txtar index d419443711d..47555b4bdde 100644 --- a/testdata/scripts/node/validate/defaults-override.txtar +++ b/testdata/scripts/node/validate/defaults-override.txtar @@ -341,6 +341,18 @@ Address = '' NetworkID = 'evm' ChainID = '1' +[Capabilities.GatewayConnector] +ChainIDForNodeKey = '' +NodeAddress = '' +DonID = '' +WSHandshakeTimeoutMillis = 0 +AuthMinChallengeLen = 0 +AuthTimestampToleranceSec = 0 + +[[Capabilities.GatewayConnector.Gateways]] +ID = '' +URL = '' + [[EVM]] ChainID = '1' AutoCreateKey = true diff --git a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar index c1801789207..43a7b5a1dfa 100644 --- a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar @@ -324,6 +324,18 @@ Address = '' NetworkID = 'evm' ChainID = '1' +[Capabilities.GatewayConnector] +ChainIDForNodeKey = '' +NodeAddress = '' +DonID = '' +WSHandshakeTimeoutMillis = 0 +AuthMinChallengeLen = 0 +AuthTimestampToleranceSec = 0 + +[[Capabilities.GatewayConnector.Gateways]] +ID = '' +URL = '' + [[EVM]] ChainID = '1' AutoCreateKey = true diff --git a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar index 72832f37834..f108e303564 100644 --- a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar @@ -324,6 +324,18 @@ Address = '' NetworkID = 'evm' ChainID = '1' +[Capabilities.GatewayConnector] +ChainIDForNodeKey = '' +NodeAddress = '' +DonID = '' +WSHandshakeTimeoutMillis = 0 +AuthMinChallengeLen = 0 +AuthTimestampToleranceSec = 0 + +[[Capabilities.GatewayConnector.Gateways]] +ID = '' +URL = '' + [[EVM]] ChainID = '1' AutoCreateKey = true diff --git a/testdata/scripts/node/validate/disk-based-logging.txtar b/testdata/scripts/node/validate/disk-based-logging.txtar index 7921d124c40..f84ce5da407 100644 --- a/testdata/scripts/node/validate/disk-based-logging.txtar +++ b/testdata/scripts/node/validate/disk-based-logging.txtar @@ -324,6 +324,18 @@ Address = '' NetworkID = 'evm' ChainID = '1' +[Capabilities.GatewayConnector] +ChainIDForNodeKey = '' +NodeAddress = '' +DonID = '' +WSHandshakeTimeoutMillis = 0 +AuthMinChallengeLen = 0 +AuthTimestampToleranceSec = 0 + +[[Capabilities.GatewayConnector.Gateways]] +ID = '' +URL = '' + [[EVM]] ChainID = '1' AutoCreateKey = true diff --git a/testdata/scripts/node/validate/invalid-ocr-p2p.txtar b/testdata/scripts/node/validate/invalid-ocr-p2p.txtar index 3fe384e4877..a434f75048a 100644 --- a/testdata/scripts/node/validate/invalid-ocr-p2p.txtar +++ b/testdata/scripts/node/validate/invalid-ocr-p2p.txtar @@ -309,6 +309,18 @@ Address = '' NetworkID = 'evm' ChainID = '1' +[Capabilities.GatewayConnector] +ChainIDForNodeKey = '' +NodeAddress = '' +DonID = '' +WSHandshakeTimeoutMillis = 0 +AuthMinChallengeLen = 0 +AuthTimestampToleranceSec = 0 + +[[Capabilities.GatewayConnector.Gateways]] +ID = '' +URL = '' + Invalid configuration: invalid configuration: P2P.V2.Enabled: invalid value (false): P2P required for OCR or OCR2. Please enable P2P or disable OCR/OCR2. -- err.txt -- diff --git a/testdata/scripts/node/validate/invalid.txtar b/testdata/scripts/node/validate/invalid.txtar index 66ca83e03e3..016a02e088c 100644 --- a/testdata/scripts/node/validate/invalid.txtar +++ b/testdata/scripts/node/validate/invalid.txtar @@ -314,6 +314,18 @@ Address = '' NetworkID = 'evm' ChainID = '1' +[Capabilities.GatewayConnector] +ChainIDForNodeKey = '' +NodeAddress = '' +DonID = '' +WSHandshakeTimeoutMillis = 0 +AuthMinChallengeLen = 0 +AuthTimestampToleranceSec = 0 + +[[Capabilities.GatewayConnector.Gateways]] +ID = '' +URL = '' + [[EVM]] ChainID = '1' AutoCreateKey = true diff --git a/testdata/scripts/node/validate/valid.txtar b/testdata/scripts/node/validate/valid.txtar index 166db265d5a..c4d188bff06 100644 --- a/testdata/scripts/node/validate/valid.txtar +++ b/testdata/scripts/node/validate/valid.txtar @@ -321,6 +321,18 @@ Address = '' NetworkID = 'evm' ChainID = '1' +[Capabilities.GatewayConnector] +ChainIDForNodeKey = '' +NodeAddress = '' +DonID = '' +WSHandshakeTimeoutMillis = 0 +AuthMinChallengeLen = 0 +AuthTimestampToleranceSec = 0 + +[[Capabilities.GatewayConnector.Gateways]] +ID = '' +URL = '' + [[EVM]] ChainID = '1' AutoCreateKey = true diff --git a/testdata/scripts/node/validate/warnings.txtar b/testdata/scripts/node/validate/warnings.txtar index ed727815b30..f900bc96263 100644 --- a/testdata/scripts/node/validate/warnings.txtar +++ b/testdata/scripts/node/validate/warnings.txtar @@ -303,6 +303,18 @@ Address = '' NetworkID = 'evm' ChainID = '1' +[Capabilities.GatewayConnector] +ChainIDForNodeKey = '' +NodeAddress = '' +DonID = '' +WSHandshakeTimeoutMillis = 0 +AuthMinChallengeLen = 0 +AuthTimestampToleranceSec = 0 + +[[Capabilities.GatewayConnector.Gateways]] +ID = '' +URL = '' + # Configuration warning: Tracing.TLSCertPath: invalid value (something): must be empty when Tracing.Mode is 'unencrypted' Valid configuration.