From 0daf7fc8e54684362fca0fd8aed693f58a6cb257 Mon Sep 17 00:00:00 2001 From: DeividasK Date: Tue, 29 Jul 2025 19:54:20 +0300 Subject: [PATCH 1/3] Re-enable Vault smoke test --- core/services/ocr2/delegate.go | 2 +- core/services/ocr2/plugins/vault/config.go | 7 +- .../cre/environment-gateway-vault-don.toml | 35 ++++- system-tests/tests/smoke/cre/vault_test.go | 130 ++++++++++++++++-- 4 files changed, 159 insertions(+), 15 deletions(-) diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go index 51e627644b9..1e793d54676 100644 --- a/core/services/ocr2/delegate.go +++ b/core/services/ocr2/delegate.go @@ -642,7 +642,7 @@ func (d *Delegate) newServicesVaultPlugin( lggr, store, clockwork.NewRealClock(), - cfg.RequestExpiryDuration, + cfg.RequestExpiryDuration.Duration(), ) srvs = append(srvs, service) diff --git a/core/services/ocr2/plugins/vault/config.go b/core/services/ocr2/plugins/vault/config.go index a38fdc3638a..418675ad855 100644 --- a/core/services/ocr2/plugins/vault/config.go +++ b/core/services/ocr2/plugins/vault/config.go @@ -2,15 +2,16 @@ package vault import ( "errors" - "time" + + commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" ) type Config struct { - RequestExpiryDuration time.Duration `json:"requestExpiryDuration"` + RequestExpiryDuration commonconfig.Duration `json:"requestExpiryDuration"` } func (c *Config) Validate() error { - if c.RequestExpiryDuration <= 0 { + if c.RequestExpiryDuration.Duration() <= 0 { return errors.New("request expiry duration cannot be 0") } return nil diff --git a/system-tests/tests/smoke/cre/environment-gateway-vault-don.toml b/system-tests/tests/smoke/cre/environment-gateway-vault-don.toml index dbd66c72968..be089c5c34d 100644 --- a/system-tests/tests/smoke/cre/environment-gateway-vault-don.toml +++ b/system-tests/tests/smoke/cre/environment-gateway-vault-don.toml @@ -4,11 +4,42 @@ chain_id = "1337" port = "8550" +[[nodesets]] + name = "bootstrap_set" + nodes = 1 + http_port_range_start = 10100 + + [nodesets.db] + image = "postgres:12.0" + port = 13002 + + [[nodesets.node_specs]] + + [nodesets.node_specs.node] + docker_ctx = "../../../../" + docker_file = "./core/chainlink.Dockerfile" + + user_config_overrides = """ + [Feature] + LogPoller = true + + [OCR2] + Enabled = true + + [P2P.V2] + Enabled = true + ListenAddresses = ['0.0.0.0:5004'] + """ + + # A port opened for the bootstrap job + custom_ports = ["5004:5004"] + + [[nodesets]] name = "gateway_set" nodes = 1 override_mode = "each" - http_port_range_start = 10100 + http_port_range_start = 10200 [nodesets.db] image = "postgres:12.0" @@ -27,7 +58,7 @@ name = "vault_set" nodes = 1 override_mode = "each" - http_port_range_start = 10200 + http_port_range_start = 10300 [nodesets.db] image = "postgres:12.0" diff --git a/system-tests/tests/smoke/cre/vault_test.go b/system-tests/tests/smoke/cre/vault_test.go index 73b25efe42d..ab4b5625343 100644 --- a/system-tests/tests/smoke/cre/vault_test.go +++ b/system-tests/tests/smoke/cre/vault_test.go @@ -6,20 +6,31 @@ import ( "encoding/json" "fmt" "io" + "maps" "net/http" "net/url" "os" + "strings" "testing" "time" "github.com/stretchr/testify/require" + chain_selectors "github.com/smartcontractkit/chain-selectors" + jsonrpc "github.com/smartcontractkit/chainlink-common/pkg/jsonrpc2" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-deployments-framework/datastore" + cldf_chain "github.com/smartcontractkit/chainlink-deployments-framework/chain" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink-testing-framework/framework" "github.com/smartcontractkit/chainlink-testing-framework/framework/clclient" "github.com/smartcontractkit/chainlink-testing-framework/framework/components/blockchain" "github.com/smartcontractkit/chainlink-testing-framework/framework/components/simple_node_set" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + "github.com/smartcontractkit/chainlink/deployment/environment/devenv" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" "github.com/smartcontractkit/chainlink/v2/core/services/gateway" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/vault" @@ -38,18 +49,112 @@ const GatewayPortForNodes = "18080" const GatewayPortForUsers = "5002" const NodeRequestPath = "/node" +// This key is taken from https://smartcontractkit.github.io/chainlink-testing-framework/framework/components/blockchains/evm.html#test-private-keys +// It couldn't find a way to read keys from the blockchain node output. +const DefaultAnvilPrivateKey = "59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d" + func TestVault_E2E(t *testing.T) { - t.Skip("Skipping vault because it is flaky") + lggr, err := logger.New() + require.NoError(t, err) + configErr := setDefaultConfig("environment-gateway-vault-don.toml") require.NoError(t, configErr, "failed to set default CTF config") c, err := framework.Load[Config](t) require.NoError(t, err) + bootstrapNodeSetConfig := c.NodeSets[0] + gatewayNodeSetConfig := c.NodeSets[1] + vaultNodeSetConfig := c.NodeSets[2] + + // BLOCKCHAIN SETUP - start bc, err := blockchain.NewBlockchainNetwork(c.Blockchain) require.NoError(t, err) - gatewayNodeSet, err := simple_node_set.NewSharedDBNodeSet(c.NodeSets[0], bc) + // Create seth client for deployments + sethClient, err := seth.NewClientBuilder(). + WithRpcUrl(bc.Nodes[0].ExternalWSUrl). + WithPrivateKeys([]string{DefaultAnvilPrivateKey}). + // do not check if there's a pending nonce nor check node's health + WithProtections(false, false, seth.MustMakeDuration(time.Second)). + Build() + require.NoError(t, err) + + chainsConfigs := make([]devenv.ChainConfig, 0) + chainsConfigs = append(chainsConfigs, devenv.ChainConfig{ + ChainID: c.Blockchain.ChainID, + ChainName: sethClient.Cfg.Network.Name, + ChainType: strings.ToUpper(bc.Family), + WSRPCs: []devenv.CribRPCs{{ + External: bc.Nodes[0].ExternalWSUrl, + Internal: bc.Nodes[0].InternalWSUrl, + }}, + HTTPRPCs: []devenv.CribRPCs{{ + External: bc.Nodes[0].ExternalHTTPUrl, + Internal: bc.Nodes[0].InternalHTTPUrl, + }}, + DeployerKey: sethClient.NewTXOpts(seth.WithNonce(nil)), // set nonce to nil, so that it will be fetched from the RPC node + }) + blockChains, err := devenv.NewChains(lggr, chainsConfigs) + require.NoError(t, err) + + // Create CLDF environment + cldEnv := &cldf.Environment{ + Logger: lggr, + ExistingAddresses: cldf.NewMemoryAddressBook(), + DataStore: datastore.NewMemoryDataStore().Seal(), + GetContext: func() context.Context { return t.Context() }, + BlockChains: cldf_chain.NewBlockChains(maps.Collect(blockChains.All())), + } + + registrySel := cldEnv.BlockChains.ListChainSelectors(cldf_chain.WithFamily(chain_selectors.FamilyEVM))[0] + + resp, err := changeset.DeployOCR3V2(*cldEnv, &changeset.DeployRequestV2{ + ChainSel: registrySel, + }) + require.NoError(t, err) + + addrs, err := resp.DataStore.Addresses().Fetch() + require.NoError(t, err) + require.Len(t, addrs, 1) + ocr3Addr := addrs[0].Address + + // BLOCKCHAIN SETUP - end + + bootstrapNodeSet, err := simple_node_set.NewSharedDBNodeSet(bootstrapNodeSetConfig, bc) + require.NoError(t, err) + + bootstrapNodeSetClients, err := clclient.New(bootstrapNodeSet.CLNodes) + require.NoError(t, err) + + // Add bootstrap job spec to the bootstrap node + bootstrapJobSpec := fmt.Sprintf(` + type = "bootstrap" + schemaVersion = 1 + name = "Bootstrap" + forwardingAllowed = false + contractID = "%s" + relay = "evm" + + [relayConfig] + chainID = "%s" + providerType = "ocr3-capability" + `, ocr3Addr, c.Blockchain.ChainID) + var bootstrapP2PKeyID string + + for _, client := range bootstrapNodeSetClients { + job, resp, err := client.CreateJobRaw(bootstrapJobSpec) + require.NoError(t, err, "Bootstrap job creation request must not error") + require.Empty(t, job.Errors, "Bootstrap job creation response must not return any errors") + require.NotEmpty(t, job.Data.ID, "Bootstrap job creation response must return a job ID: %v.", job) + require.Equal(t, http.StatusOK, resp.StatusCode, "Bootstrap job creation request must return 200 OK") + + keys, err := client.MustReadP2PKeys() + require.NoError(t, err) + bootstrapP2PKeyID = keys.Data[0].Attributes.PeerID + } + + gatewayNodeSet, err := simple_node_set.NewSharedDBNodeSet(gatewayNodeSetConfig, bc) require.NoError(t, err) gatewayNodeSetClients, err := clclient.New(gatewayNodeSet.CLNodes) @@ -65,7 +170,6 @@ func TestVault_E2E(t *testing.T) { // Id, which must match the AuthGatewayId in the gateway job spec // URL, which is the WS URL of the gateway node (outputted after the node is configured) - vaultNodeSetConfig := c.NodeSets[1] vaultNodeSet, err := simple_node_set.NewSharedDBNodeSet(vaultNodeSetConfig, bc) require.NoError(t, err) @@ -87,6 +191,9 @@ func TestVault_E2E(t *testing.T) { require.NoError(t, err2) internalGatewayURL := fmt.Sprintf("ws://%s:%s%s", parsedURL.Hostname(), GatewayPortForNodes, NodeRequestPath) node.Node.UserConfigOverrides += fmt.Sprintf(` + [Feature] + LogPoller = true + [Capabilities.GatewayConnector] DonID = "%s" ChainIDForNodeKey = "%s" @@ -184,6 +291,11 @@ func TestVault_E2E(t *testing.T) { } fmt.Println("✅ Gateway jobs created successfully.") + // Create bootstrap P2P locator in format: {peerID}@{host}:{port} + parsedBootstrapURL, err := url.Parse(bootstrapNodeSet.CLNodes[0].Node.InternalP2PUrl) + require.NoError(t, err) + bootstrapP2PLocator := fmt.Sprintf("%s@%s", bootstrapP2PKeyID, parsedBootstrapURL.Host) + // Add the vault job to each node in the second nodeset for _, client := range vaultNodeSetClients { // Get the actual OCR key bundle ID and transmitter address for this node @@ -210,20 +322,20 @@ func TestVault_E2E(t *testing.T) { name = "vault_node" forwardingAllowed = false maxTaskDuration = "30s" - contractID = "0x0000000000000000000000000000000000000000" + contractID = "%s" ocrKeyBundleID = "%s" transmitterID = "%s" relay = "evm" - p2pv2Bootstrappers = [] - allowNoBootstrappers = true + p2pv2Bootstrappers = ["%s"] [relayConfig] chainID = "%s" - `, nodeOCRKeyID, nodeTransmitterAddresses[0], c.Blockchain.ChainID) + + [pluginConfig] + requestExpiryDuration = "60s" + `, ocr3Addr, nodeOCRKeyID, nodeTransmitterAddresses[0], bootstrapP2PLocator, c.Blockchain.ChainID) job, resp, err := client.CreateJobRaw(vaultJobSpec) - fmt.Println(job) - fmt.Println(resp) require.NoError(t, err, "Vault job creation request must not error") require.Equal(t, http.StatusOK, resp.StatusCode, "Vault job creation response must return 200 OK: %v", resp) require.NotEmpty(t, job.Data.ID, "Vault job creation response must return a job ID: %v.", job) From 1cbb6f09ca755dba0247114b427d127835e3d1f8 Mon Sep 17 00:00:00 2001 From: DeividasK Date: Wed, 30 Jul 2025 09:15:23 +0300 Subject: [PATCH 2/3] go mod tidy --- .changeset/eighty-turkeys-smash.md | 5 +++++ system-tests/tests/go.mod | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/eighty-turkeys-smash.md diff --git a/.changeset/eighty-turkeys-smash.md b/.changeset/eighty-turkeys-smash.md new file mode 100644 index 00000000000..e088796aec2 --- /dev/null +++ b/.changeset/eighty-turkeys-smash.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal Re-enable Vault smoke test diff --git a/system-tests/tests/go.mod b/system-tests/tests/go.mod index e4c8078b261..6ce90d131e6 100644 --- a/system-tests/tests/go.mod +++ b/system-tests/tests/go.mod @@ -23,6 +23,7 @@ require ( github.com/prometheus/common v0.65.0 github.com/rs/zerolog v1.33.0 github.com/shopspring/decimal v1.4.0 + github.com/smartcontractkit/chain-selectors v1.0.62 github.com/smartcontractkit/chainlink-common v0.8.1-0.20250724173916-a78e01aa7d37 github.com/smartcontractkit/chainlink-common/pkg/values v0.0.0-20250718143957-41236f9ef8b4 github.com/smartcontractkit/chainlink-data-streams v0.1.2 @@ -457,7 +458,6 @@ require ( github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chain-selectors v1.0.62 // indirect github.com/smartcontractkit/chainlink-aptos v0.0.0-20250626122206-319db248496a // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20250716191209-5639135b7716 // indirect From fac013d2dfce1f120c4fee33b15f2beec56a849e Mon Sep 17 00:00:00 2001 From: DeividasK Date: Wed, 30 Jul 2025 09:27:12 +0300 Subject: [PATCH 3/3] Lint fixes --- system-tests/tests/smoke/cre/vault_test.go | 37 ++++++++++------------ 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/system-tests/tests/smoke/cre/vault_test.go b/system-tests/tests/smoke/cre/vault_test.go index ab4b5625343..6dda94da9d8 100644 --- a/system-tests/tests/smoke/cre/vault_test.go +++ b/system-tests/tests/smoke/cre/vault_test.go @@ -109,12 +109,12 @@ func TestVault_E2E(t *testing.T) { registrySel := cldEnv.BlockChains.ListChainSelectors(cldf_chain.WithFamily(chain_selectors.FamilyEVM))[0] - resp, err := changeset.DeployOCR3V2(*cldEnv, &changeset.DeployRequestV2{ + ocrDeploymentOutput, err := changeset.DeployOCR3V2(*cldEnv, &changeset.DeployRequestV2{ ChainSel: registrySel, }) require.NoError(t, err) - addrs, err := resp.DataStore.Addresses().Fetch() + addrs, err := ocrDeploymentOutput.DataStore.Addresses().Fetch() require.NoError(t, err) require.Len(t, addrs, 1) ocr3Addr := addrs[0].Address @@ -126,8 +126,8 @@ func TestVault_E2E(t *testing.T) { bootstrapNodeSetClients, err := clclient.New(bootstrapNodeSet.CLNodes) require.NoError(t, err) + bootstrapNodeClient := bootstrapNodeSetClients[0] - // Add bootstrap job spec to the bootstrap node bootstrapJobSpec := fmt.Sprintf(` type = "bootstrap" schemaVersion = 1 @@ -140,19 +140,19 @@ func TestVault_E2E(t *testing.T) { chainID = "%s" providerType = "ocr3-capability" `, ocr3Addr, c.Blockchain.ChainID) - var bootstrapP2PKeyID string - - for _, client := range bootstrapNodeSetClients { - job, resp, err := client.CreateJobRaw(bootstrapJobSpec) - require.NoError(t, err, "Bootstrap job creation request must not error") - require.Empty(t, job.Errors, "Bootstrap job creation response must not return any errors") - require.NotEmpty(t, job.Data.ID, "Bootstrap job creation response must return a job ID: %v.", job) - require.Equal(t, http.StatusOK, resp.StatusCode, "Bootstrap job creation request must return 200 OK") - - keys, err := client.MustReadP2PKeys() - require.NoError(t, err) - bootstrapP2PKeyID = keys.Data[0].Attributes.PeerID - } + + job, resp, err := bootstrapNodeClient.CreateJobRaw(bootstrapJobSpec) + require.NoError(t, err, "Bootstrap job creation request must not error") + require.Empty(t, job.Errors, "Bootstrap job creation response must not return any errors") + require.NotEmpty(t, job.Data.ID, "Bootstrap job creation response must return a job ID: %v.", job) + require.Equal(t, http.StatusOK, resp.StatusCode, "Bootstrap job creation request must return 200 OK") + + keys, err := bootstrapNodeClient.MustReadP2PKeys() + require.NoError(t, err) + + parsedBootstrapURL, err := url.Parse(bootstrapNodeSet.CLNodes[0].Node.InternalP2PUrl) + require.NoError(t, err) + bootstrapP2PLocator := fmt.Sprintf("%s@%s", keys.Data[0].Attributes.PeerID, parsedBootstrapURL.Host) gatewayNodeSet, err := simple_node_set.NewSharedDBNodeSet(gatewayNodeSetConfig, bc) require.NoError(t, err) @@ -291,11 +291,6 @@ func TestVault_E2E(t *testing.T) { } fmt.Println("✅ Gateway jobs created successfully.") - // Create bootstrap P2P locator in format: {peerID}@{host}:{port} - parsedBootstrapURL, err := url.Parse(bootstrapNodeSet.CLNodes[0].Node.InternalP2PUrl) - require.NoError(t, err) - bootstrapP2PLocator := fmt.Sprintf("%s@%s", bootstrapP2PKeyID, parsedBootstrapURL.Host) - // Add the vault job to each node in the second nodeset for _, client := range vaultNodeSetClients { // Get the actual OCR key bundle ID and transmitter address for this node