From 1e3efdfa0ffb0c8ba942df3eacd4bf03bea708ac Mon Sep 17 00:00:00 2001 From: Anindita Ghosh <88458927+AnieeG@users.noreply.github.com> Date: Tue, 17 Oct 2023 18:33:49 -0700 Subject: [PATCH] bump ctf (#214) --- .../workflows/integration-tests-publish.yml | 4 + integration-tests/Makefile | 2 +- integration-tests/actions/actions.go | 17 +- integration-tests/actions/actions_local.go | 1 - .../actions/automation_ocr_helpers.go | 23 +- .../actions/automation_ocr_helpers_local.go | 16 +- integration-tests/actions/keeper_helpers.go | 10 +- .../actions/ocr2_helpers_local.go | 21 +- .../actions/ocr_helpers_local.go | 30 +- .../actions/vrfv2_actions/vrfv2_steps.go | 17 +- .../vrfv2plus/vrfv2plus_config/config.go | 41 ++ .../actions/vrfv2plus/vrfv2plus_steps.go | 298 +++++++++---- integration-tests/benchmark/keeper_test.go | 21 +- .../ccip-tests/actions/ccip_helpers.go | 4 +- .../ccip-tests/testsetups/ccip.go | 3 +- .../chaos/automation_chaos_test.go | 342 ++++++++------- integration-tests/client/chainlink.go | 11 +- .../contracts/contract_deployer.go | 38 +- .../contracts/contract_loader.go | 52 +++ .../contracts/contract_vrf_models.go | 11 +- .../contracts/ethereum_contracts.go | 96 +++-- .../contracts/ethereum_contracts_local.go | 4 +- .../contracts/ethereum_keeper_contracts.go | 113 ++++- .../contracts/ethereum_ocr2vrf_contracts.go | 6 +- .../contracts/ethereum_vrf_contracts.go | 9 +- .../contracts/ethereum_vrfv2_contracts.go | 11 +- .../contracts/ethereum_vrfv2plus_contracts.go | 18 +- integration-tests/docker/cmd/test_env.go | 2 +- integration-tests/docker/test_env/cl_node.go | 34 +- .../docker/test_env/cl_node_cluster.go | 69 +++ integration-tests/docker/test_env/test_env.go | 270 ++++++------ .../docker/test_env/test_env_builder.go | 69 ++- .../docker/test_env/test_env_config.go | 19 +- integration-tests/go.mod | 70 ++- integration-tests/go.sum | 151 +++---- integration-tests/load/functions/README.md | 2 +- integration-tests/load/vrfv2/cmd/dashboard.go | 3 +- integration-tests/load/vrfv2/vrfv2_test.go | 5 +- integration-tests/load/vrfv2plus/README.md | 22 + .../load/vrfv2plus/cmd/dashboard.go | 99 +++++ integration-tests/load/vrfv2plus/config.go | 93 ++++ integration-tests/load/vrfv2plus/config.toml | 14 + integration-tests/load/vrfv2plus/gun.go | 56 +++ .../load/vrfv2plus/onchain_monitoring.go | 50 +++ .../load/vrfv2plus/vrfv2plus_test.go | 221 ++++++++++ .../migration/upgrade_version_test.go | 2 +- integration-tests/performance/cron_test.go | 5 +- .../performance/directrequest_test.go | 5 +- integration-tests/performance/flux_test.go | 5 +- integration-tests/performance/keeper_test.go | 5 +- integration-tests/performance/ocr_test.go | 5 +- integration-tests/performance/vrf_test.go | 5 +- .../reorg/automation_reorg_test.go | 272 ++++++------ integration-tests/scripts/buildTests | 4 +- integration-tests/scripts/entrypoint | 4 +- integration-tests/smoke/automation_test.go | 162 ++++--- .../smoke/automation_test.go_test_list.json | 2 +- integration-tests/smoke/cron_test.go | 25 +- integration-tests/smoke/flux_test.go | 20 +- integration-tests/smoke/forwarder_ocr_test.go | 14 +- .../smoke/forwarders_ocr2_test.go | 14 +- integration-tests/smoke/keeper_test.go | 9 +- integration-tests/smoke/ocr2_test.go | 14 +- integration-tests/smoke/ocr_test.go | 13 +- integration-tests/smoke/runlog_test.go | 20 +- integration-tests/smoke/vrf_test.go | 10 +- integration-tests/smoke/vrfv2_test.go | 15 +- integration-tests/smoke/vrfv2plus_test.go | 142 +++--- .../testsetups/keeper_benchmark.go | 408 +++++++++++------- integration-tests/testsetups/ocr.go | 35 +- 70 files changed, 2390 insertions(+), 1293 deletions(-) create mode 100644 integration-tests/actions/vrfv2plus/vrfv2plus_config/config.go create mode 100644 integration-tests/docker/test_env/cl_node_cluster.go create mode 100644 integration-tests/load/vrfv2plus/README.md create mode 100644 integration-tests/load/vrfv2plus/cmd/dashboard.go create mode 100644 integration-tests/load/vrfv2plus/config.go create mode 100644 integration-tests/load/vrfv2plus/config.toml create mode 100644 integration-tests/load/vrfv2plus/gun.go create mode 100644 integration-tests/load/vrfv2plus/onchain_monitoring.go create mode 100644 integration-tests/load/vrfv2plus/vrfv2plus_test.go diff --git a/.github/workflows/integration-tests-publish.yml b/.github/workflows/integration-tests-publish.yml index 755b37c2a1..77d2a1bc56 100644 --- a/.github/workflows/integration-tests-publish.yml +++ b/.github/workflows/integration-tests-publish.yml @@ -2,6 +2,10 @@ name: Integration Tests Publish # Publish the compiled integration tests on: push: + tags: + - "v*" + branches: + - ccip-develop workflow_dispatch: env: diff --git a/integration-tests/Makefile b/integration-tests/Makefile index 287bb93963..d12a1e789a 100644 --- a/integration-tests/Makefile +++ b/integration-tests/Makefile @@ -188,4 +188,4 @@ run_test_with_local_image: build_docker_image SELECTED_NETWORKS="SIMULATED,SIMULATED_1,SIMULATED_2" \ ARGS="$(args)" \ PRODUCT=$(product) \ - ./scripts/run_product_tests \ No newline at end of file + ./scripts/run_product_tests diff --git a/integration-tests/actions/actions.go b/integration-tests/actions/actions.go index e37c3738ff..dcdca91cc7 100644 --- a/integration-tests/actions/actions.go +++ b/integration-tests/actions/actions.go @@ -72,7 +72,10 @@ func FundChainlinkNodesAddress( if err != nil { return err } - gasEstimates, err := client.EstimateGas(ethereum.CallMsg{}) + toAddr := common.HexToAddress(toAddress[keyIndex]) + gasEstimates, err := client.EstimateGas(ethereum.CallMsg{ + To: &toAddr, + }) if err != nil { return err } @@ -96,7 +99,10 @@ func FundChainlinkNodesAddresses( return err } for _, addr := range toAddress { - gasEstimates, err := client.EstimateGas(ethereum.CallMsg{}) + toAddr := common.HexToAddress(addr) + gasEstimates, err := client.EstimateGas(ethereum.CallMsg{ + To: &toAddr, + }) if err != nil { return err } @@ -369,7 +375,7 @@ func ReturnFunds(chainlinkNodes []*client.ChainlinkK8sClient, blockchainClient b } err = blockchainClient.ReturnFunds(decryptedKey.PrivateKey) if err != nil { - return err + log.Error().Err(err).Str("Address", fundedKeys[0].Address).Msg("Error returning funds from Chainlink node") } } } @@ -379,7 +385,10 @@ func ReturnFunds(chainlinkNodes []*client.ChainlinkK8sClient, blockchainClient b // FundAddresses will fund a list of addresses with an amount of native currency func FundAddresses(blockchain blockchain.EVMClient, amount *big.Float, addresses ...string) error { for _, address := range addresses { - gasEstimates, err := blockchain.EstimateGas(ethereum.CallMsg{}) + toAddr := common.HexToAddress(address) + gasEstimates, err := blockchain.EstimateGas(ethereum.CallMsg{ + To: &toAddr, + }) if err != nil { return err } diff --git a/integration-tests/actions/actions_local.go b/integration-tests/actions/actions_local.go index d2e2fde321..b65bac43bb 100644 --- a/integration-tests/actions/actions_local.go +++ b/integration-tests/actions/actions_local.go @@ -3,7 +3,6 @@ package actions import ( "github.com/pkg/errors" - "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" ) diff --git a/integration-tests/actions/automation_ocr_helpers.go b/integration-tests/actions/automation_ocr_helpers.go index fb94d6109b..0c12319b82 100644 --- a/integration-tests/actions/automation_ocr_helpers.go +++ b/integration-tests/actions/automation_ocr_helpers.go @@ -11,19 +11,20 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/lib/pq" + "github.com/stretchr/testify/require" + "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" - "github.com/smartcontractkit/chainlink/v2/core/store/models" ocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" ocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" ocr2keepers20config "github.com/smartcontractkit/ocr2keepers/pkg/v2/config" ocr2keepers30config "github.com/smartcontractkit/ocr2keepers/pkg/v3/config" - "github.com/stretchr/testify/require" - "gopkg.in/guregu/null.v4" + + "github.com/smartcontractkit/chainlink/v2/core/services/job" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" + "github.com/smartcontractkit/chainlink/v2/core/store/models" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" @@ -37,7 +38,7 @@ func BuildAutoOCR2ConfigVars( registrar string, deltaStage time.Duration, ) (contracts.OCRv2Config, error) { - return BuildAutoOCR2ConfigVarsWithKeyIndex(t, chainlinkNodes, registryConfig, registrar, deltaStage, 0) + return BuildAutoOCR2ConfigVarsWithKeyIndex(t, chainlinkNodes, registryConfig, registrar, deltaStage, 0, common.Address{}) } func BuildAutoOCR2ConfigVarsWithKeyIndex( @@ -47,6 +48,7 @@ func BuildAutoOCR2ConfigVarsWithKeyIndex( registrar string, deltaStage time.Duration, keyIndex int, + registryOwnerAddress common.Address, ) (contracts.OCRv2Config, error) { l := logging.GetTestLogger(t) S, oracleIdentities, err := GetOracleIdentitiesWithKeyIndex(chainlinkNodes, keyIndex) @@ -147,7 +149,7 @@ func BuildAutoOCR2ConfigVarsWithKeyIndex( transmitters = append(transmitters, common.HexToAddress(string(transmitter))) } - onchainConfig, err := registryConfig.EncodeOnChainConfig(registrar) + onchainConfig, err := registryConfig.EncodeOnChainConfig(registrar, registryOwnerAddress) if err != nil { return contracts.OCRv2Config{}, err } @@ -201,7 +203,8 @@ func CreateOCRKeeperJobs( } _, err = bootstrapNode.MustCreateJob(bootstrapSpec) require.NoError(t, err, "Shouldn't fail creating bootstrap job on bootstrap node") - P2Pv2Bootstrapper := fmt.Sprintf("%s@%s:%d", bootstrapP2PId, bootstrapNode.Name(), 6690) + // TODO: Use service name returned by chainlink-env once that is available + P2Pv2Bootstrapper := fmt.Sprintf("%s@%s-node-1:%d", bootstrapP2PId, bootstrapNode.Name(), 6690) for nodeIndex := 1; nodeIndex < len(chainlinkNodes); nodeIndex++ { nodeTransmitterAddress, err := chainlinkNodes[nodeIndex].EthAddresses() @@ -258,8 +261,8 @@ func DeployAutoOCRRegistryAndRegistrar( return registry, registrar } -func DeployConsumers(t *testing.T, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, linkToken contracts.LinkToken, contractDeployer contracts.ContractDeployer, client blockchain.EVMClient, numberOfUpkeeps int, linkFundsForEachUpkeep *big.Int, upkeepGasLimit uint32, isLogTrigger bool) ([]contracts.KeeperConsumer, []*big.Int) { - upkeeps := DeployKeeperConsumers(t, contractDeployer, client, numberOfUpkeeps, isLogTrigger) +func DeployConsumers(t *testing.T, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, linkToken contracts.LinkToken, contractDeployer contracts.ContractDeployer, client blockchain.EVMClient, numberOfUpkeeps int, linkFundsForEachUpkeep *big.Int, upkeepGasLimit uint32, isLogTrigger bool, isMercury bool) ([]contracts.KeeperConsumer, []*big.Int) { + upkeeps := DeployKeeperConsumers(t, contractDeployer, client, numberOfUpkeeps, isLogTrigger, isMercury) var upkeepsAddresses []string for _, upkeep := range upkeeps { upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) diff --git a/integration-tests/actions/automation_ocr_helpers_local.go b/integration-tests/actions/automation_ocr_helpers_local.go index 86738b0247..ccc2eea99d 100644 --- a/integration-tests/actions/automation_ocr_helpers_local.go +++ b/integration-tests/actions/automation_ocr_helpers_local.go @@ -10,20 +10,20 @@ import ( "github.com/lib/pq" "github.com/pkg/errors" "github.com/rs/zerolog" - "gopkg.in/guregu/null.v4" - - "github.com/smartcontractkit/chainlink/integration-tests/client" - "github.com/smartcontractkit/chainlink/integration-tests/contracts" - "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" ocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" ocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" ocr2keepers20config "github.com/smartcontractkit/ocr2keepers/pkg/v2/config" ocr2keepers30config "github.com/smartcontractkit/ocr2keepers/pkg/v3/config" + "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" "github.com/smartcontractkit/chainlink/v2/core/store/models" + + "github.com/smartcontractkit/chainlink/integration-tests/client" + "github.com/smartcontractkit/chainlink/integration-tests/contracts" + "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" ) func BuildAutoOCR2ConfigVarsLocal( @@ -32,8 +32,9 @@ func BuildAutoOCR2ConfigVarsLocal( registryConfig contracts.KeeperRegistrySettings, registrar string, deltaStage time.Duration, + registryOwnerAddress common.Address, ) (contracts.OCRv2Config, error) { - return BuildAutoOCR2ConfigVarsWithKeyIndexLocal(l, chainlinkNodes, registryConfig, registrar, deltaStage, 0) + return BuildAutoOCR2ConfigVarsWithKeyIndexLocal(l, chainlinkNodes, registryConfig, registrar, deltaStage, 0, registryOwnerAddress) } func BuildAutoOCR2ConfigVarsWithKeyIndexLocal( @@ -43,6 +44,7 @@ func BuildAutoOCR2ConfigVarsWithKeyIndexLocal( registrar string, deltaStage time.Duration, keyIndex int, + registryOwnerAddress common.Address, ) (contracts.OCRv2Config, error) { S, oracleIdentities, err := GetOracleIdentitiesWithKeyIndexLocal(chainlinkNodes, keyIndex) if err != nil { @@ -146,7 +148,7 @@ func BuildAutoOCR2ConfigVarsWithKeyIndexLocal( transmitters = append(transmitters, common.HexToAddress(string(transmitter))) } - onchainConfig, err := registryConfig.EncodeOnChainConfig(registrar) + onchainConfig, err := registryConfig.EncodeOnChainConfig(registrar, registryOwnerAddress) if err != nil { return contracts.OCRv2Config{}, err } diff --git a/integration-tests/actions/keeper_helpers.go b/integration-tests/actions/keeper_helpers.go index f824e75019..645a5c7cb7 100644 --- a/integration-tests/actions/keeper_helpers.go +++ b/integration-tests/actions/keeper_helpers.go @@ -146,7 +146,7 @@ func DeployKeeperContracts( } registrar := DeployKeeperRegistrar(t, registryVersion, linkToken, registrarSettings, contractDeployer, client, registry) - upkeeps := DeployKeeperConsumers(t, contractDeployer, client, numberOfUpkeeps, false) + upkeeps := DeployKeeperConsumers(t, contractDeployer, client, numberOfUpkeeps, false, false) var upkeepsAddresses []string for _, upkeep := range upkeeps { upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) @@ -397,7 +397,7 @@ func RegisterUpkeepContractsWithCheckData(t *testing.T, linkToken contracts.Link return upkeepIds } -func DeployKeeperConsumers(t *testing.T, contractDeployer contracts.ContractDeployer, client blockchain.EVMClient, numberOfContracts int, isLogTrigger bool) []contracts.KeeperConsumer { +func DeployKeeperConsumers(t *testing.T, contractDeployer contracts.ContractDeployer, client blockchain.EVMClient, numberOfContracts int, isLogTrigger bool, isMercury bool) []contracts.KeeperConsumer { l := logging.GetTestLogger(t) keeperConsumerContracts := make([]contracts.KeeperConsumer, 0) @@ -406,7 +406,9 @@ func DeployKeeperConsumers(t *testing.T, contractDeployer contracts.ContractDepl var keeperConsumerInstance contracts.KeeperConsumer var err error - if isLogTrigger { + if isMercury { + keeperConsumerInstance, err = contractDeployer.DeployAutomationStreamsLookupUpkeepConsumer(big.NewInt(1000), big.NewInt(5), false, true, false) // 1000 block test range + } else if isLogTrigger { keeperConsumerInstance, err = contractDeployer.DeployAutomationLogTriggerConsumer(big.NewInt(1000)) // 1000 block test range } else { keeperConsumerInstance, err = contractDeployer.DeployKeeperConsumer(big.NewInt(5)) @@ -581,7 +583,7 @@ func RegisterNewUpkeeps( upkeepGasLimit uint32, numberOfNewUpkeeps int, ) ([]contracts.KeeperConsumer, []*big.Int) { - newlyDeployedUpkeeps := DeployKeeperConsumers(t, contractDeployer, client, numberOfNewUpkeeps, false) + newlyDeployedUpkeeps := DeployKeeperConsumers(t, contractDeployer, client, numberOfNewUpkeeps, false, false) var addressesOfNewUpkeeps []string for _, upkeep := range newlyDeployedUpkeeps { diff --git a/integration-tests/actions/ocr2_helpers_local.go b/integration-tests/actions/ocr2_helpers_local.go index 0b20e4cfee..b3fe6eb041 100644 --- a/integration-tests/actions/ocr2_helpers_local.go +++ b/integration-tests/actions/ocr2_helpers_local.go @@ -4,6 +4,7 @@ import ( "crypto/ed25519" "encoding/hex" "fmt" + "net/http" "strings" "time" @@ -11,7 +12,7 @@ import ( "github.com/google/uuid" "github.com/lib/pq" "github.com/rs/zerolog/log" - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" + "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/v2/core/services/job" @@ -29,9 +30,9 @@ func CreateOCRv2JobsLocal( ocrInstances []contracts.OffchainAggregatorV2, bootstrapNode *client.ChainlinkClient, workerChainlinkNodes []*client.ChainlinkClient, - mockserver *ctfClient.MockserverClient, - mockServerPath string, // Path on the mock server for the Chainlink nodes to query - mockServerValue int, // Value to get from the mock server when querying the path + mockAdapter *test_env.Killgrave, + mockAdapterPath string, // Path on the mock server for the Chainlink nodes to query + mockAdapterValue int, // Value to get from the mock server when querying the path chainId uint64, // EVM chain ID forwardingAllowed bool, ) error { @@ -42,12 +43,12 @@ func CreateOCRv2JobsLocal( } p2pV2Bootstrapper := fmt.Sprintf("%s@%s:%d", bootstrapP2PIds.Data[0].Attributes.PeerID, bootstrapNode.InternalIP(), 6690) // Set the value for the jobs to report on - err = mockserver.SetValuePath(mockServerPath, mockServerValue) + err = mockAdapter.SetAdapterBasedIntValuePath(mockAdapterPath, []string{http.MethodGet, http.MethodPost}, mockAdapterValue) if err != nil { return err } // Set the juelsPerFeeCoinSource config value - err = mockserver.SetValuePath(fmt.Sprintf("%s/juelsPerFeeCoinSource", mockServerPath), mockServerValue) + err = mockAdapter.SetAdapterBasedIntValuePath(fmt.Sprintf("%s/juelsPerFeeCoinSource", mockAdapterPath), []string{http.MethodGet, http.MethodPost}, mockAdapterValue) if err != nil { return err } @@ -62,7 +63,7 @@ func CreateOCRv2JobsLocal( RelayConfig: map[string]interface{}{ "chainID": chainId, }, - MonitoringEndpoint: null.StringFrom(fmt.Sprintf("%s/%s", mockserver.Config.ClusterURL, mockServerPath)), + MonitoringEndpoint: null.StringFrom(fmt.Sprintf("%s/%s", mockAdapter.InternalEndpoint, mockAdapterPath)), ContractConfigTrackerPollInterval: *models.NewInterval(15 * time.Second), }, } @@ -83,12 +84,12 @@ func CreateOCRv2JobsLocal( nodeOCRKeyId := nodeOCRKeys.Data[0].ID bta := &client.BridgeTypeAttributes{ - Name: fmt.Sprintf("%s-%s", mockServerPath, uuid.NewString()), - URL: fmt.Sprintf("%s/%s", mockserver.Config.ClusterURL, mockServerPath), + Name: fmt.Sprintf("%s-%s", mockAdapterPath, uuid.NewString()), + URL: fmt.Sprintf("%s/%s", mockAdapter.InternalEndpoint, mockAdapterPath), } juelsBridge := &client.BridgeTypeAttributes{ Name: fmt.Sprintf("juels-%s", uuid.NewString()), - URL: fmt.Sprintf("%s/%s/juelsPerFeeCoinSource", mockserver.Config.ClusterURL, mockServerPath), + URL: fmt.Sprintf("%s/%s/juelsPerFeeCoinSource", mockAdapter.InternalEndpoint, mockAdapterPath), } err = chainlinkNode.MustCreateBridge(bta) if err != nil { diff --git a/integration-tests/actions/ocr_helpers_local.go b/integration-tests/actions/ocr_helpers_local.go index ae2f3686da..8bb4e83479 100644 --- a/integration-tests/actions/ocr_helpers_local.go +++ b/integration-tests/actions/ocr_helpers_local.go @@ -3,6 +3,7 @@ package actions import ( "fmt" "math/big" + "net/http" "strings" "github.com/ethereum/go-ethereum" @@ -11,7 +12,7 @@ import ( "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" + "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" "golang.org/x/sync/errgroup" "github.com/smartcontractkit/chainlink/integration-tests/client" @@ -34,7 +35,10 @@ func FundChainlinkNodesLocal( if err != nil { return err } - gasEstimates, err := client.EstimateGas(ethereum.CallMsg{}) + toAddr := common.HexToAddress(toAddress) + gasEstimates, err := client.EstimateGas(ethereum.CallMsg{ + To: &toAddr, + }) if err != nil { return err } @@ -141,7 +145,7 @@ func CreateOCRJobsLocal( bootstrapNode *client.ChainlinkClient, workerNodes []*client.ChainlinkClient, mockValue int, - mockserver *ctfClient.MockserverClient, + mockAdapter *test_env.Killgrave, evmChainID string, ) error { for _, ocrInstance := range ocrInstances { @@ -184,9 +188,9 @@ func CreateOCRJobsLocal( } bta := &client.BridgeTypeAttributes{ Name: nodeContractPairID, - URL: fmt.Sprintf("%s/%s", mockserver.Config.ClusterURL, strings.TrimPrefix(nodeContractPairID, "/")), + URL: fmt.Sprintf("%s/%s", mockAdapter.InternalEndpoint, strings.TrimPrefix(nodeContractPairID, "/")), } - err = SetAdapterResponseLocal(mockValue, ocrInstance, node, mockserver) + err = SetAdapterResponseLocal(mockValue, ocrInstance, node, mockAdapter) if err != nil { return fmt.Errorf("setting adapter response for OCR node failed: %w", err) } @@ -234,16 +238,16 @@ func SetAdapterResponseLocal( response int, ocrInstance contracts.OffchainAggregator, chainlinkNode *client.ChainlinkClient, - mockserver *ctfClient.MockserverClient, + mockAdapter *test_env.Killgrave, ) error { nodeContractPairID, err := BuildNodeContractPairIDLocal(chainlinkNode, ocrInstance) if err != nil { return err } path := fmt.Sprintf("/%s", nodeContractPairID) - err = mockserver.SetValuePath(path, response) + err = mockAdapter.SetAdapterBasedIntValuePath(path, []string{http.MethodGet, http.MethodPost}, response) if err != nil { - return fmt.Errorf("setting mockserver value path failed: %w", err) + return fmt.Errorf("setting mock adapter value path failed: %w", err) } return nil } @@ -252,7 +256,7 @@ func SetAllAdapterResponsesToTheSameValueLocal( response int, ocrInstances []contracts.OffchainAggregator, chainlinkNodes []*client.ChainlinkClient, - mockserver *ctfClient.MockserverClient, + mockAdapter *test_env.Killgrave, ) error { eg := &errgroup.Group{} for _, o := range ocrInstances { @@ -260,7 +264,7 @@ func SetAllAdapterResponsesToTheSameValueLocal( for _, n := range chainlinkNodes { node := n eg.Go(func() error { - return SetAdapterResponseLocal(response, ocrInstance, node, mockserver) + return SetAdapterResponseLocal(response, ocrInstance, node, mockAdapter) }) } } @@ -358,7 +362,7 @@ func CreateOCRJobsWithForwarderLocal( bootstrapNode *client.ChainlinkClient, workerNodes []*client.ChainlinkClient, mockValue int, - mockserver *ctfClient.MockserverClient, + mockAdapter *test_env.Killgrave, evmChainID string, ) error { for _, ocrInstance := range ocrInstances { @@ -401,9 +405,9 @@ func CreateOCRJobsWithForwarderLocal( } bta := &client.BridgeTypeAttributes{ Name: nodeContractPairID, - URL: fmt.Sprintf("%s/%s", mockserver.Config.ClusterURL, strings.TrimPrefix(nodeContractPairID, "/")), + URL: fmt.Sprintf("%s/%s", mockAdapter.InternalEndpoint, strings.TrimPrefix(nodeContractPairID, "/")), } - err = SetAdapterResponseLocal(mockValue, ocrInstance, node, mockserver) + err = SetAdapterResponseLocal(mockValue, ocrInstance, node, mockAdapter) if err != nil { return err } diff --git a/integration-tests/actions/vrfv2_actions/vrfv2_steps.go b/integration-tests/actions/vrfv2_actions/vrfv2_steps.go index b59f8c761f..24ac217a33 100644 --- a/integration-tests/actions/vrfv2_actions/vrfv2_steps.go +++ b/integration-tests/actions/vrfv2_actions/vrfv2_steps.go @@ -3,13 +3,15 @@ package vrfv2_actions import ( "context" "fmt" - "github.com/smartcontractkit/chainlink/integration-tests/actions" - chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/utils" "math/big" "github.com/google/uuid" "github.com/pkg/errors" + "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/utils" + + "github.com/smartcontractkit/chainlink/integration-tests/actions" vrfConst "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions/vrfv2_constants" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" @@ -153,9 +155,10 @@ func SetupLocalLoadTestEnv(nodesFunding *big.Float, subFundingLINK *big.Int) (*t env, err := test_env.NewCLTestEnvBuilder(). WithGeth(). WithLogWatcher(). - WithMockServer(1). + WithMockAdapter(). WithCLNodes(1). WithFunding(nodesFunding). + WithLogWatcher(). Build() if err != nil { return nil, nil, [32]byte{}, err @@ -209,21 +212,21 @@ func SetupLocalLoadTestEnv(nodesFunding *big.Float, subFundingLINK *big.Int) (*t if err != nil { return nil, nil, [32]byte{}, err } - jobs, err := CreateVRFV2Jobs(env.GetAPIs(), vrfv2Contracts.Coordinator, env.EVMClient, vrfConst.MinimumConfirmations) + jobs, err := CreateVRFV2Jobs(env.ClCluster.NodeAPIs(), vrfv2Contracts.Coordinator, env.EVMClient, vrfConst.MinimumConfirmations) if err != nil { return nil, nil, [32]byte{}, err } // this part is here because VRFv2 can work with only a specific key // [[EVM.KeySpecific]] // Key = '...' - addr, err := env.CLNodes[0].API.PrimaryEthAddress() + addr, err := env.ClCluster.Nodes[0].API.PrimaryEthAddress() if err != nil { return nil, nil, [32]byte{}, err } - nodeConfig := node.NewConfig(env.CLNodes[0].NodeConfig, + nodeConfig := node.NewConfig(env.ClCluster.Nodes[0].NodeConfig, node.WithVRFv2EVMEstimator(addr), ) - err = env.CLNodes[0].Restart(nodeConfig) + err = env.ClCluster.Nodes[0].Restart(nodeConfig) if err != nil { return nil, nil, [32]byte{}, err } diff --git a/integration-tests/actions/vrfv2plus/vrfv2plus_config/config.go b/integration-tests/actions/vrfv2plus/vrfv2plus_config/config.go new file mode 100644 index 0000000000..0ff9b4afa7 --- /dev/null +++ b/integration-tests/actions/vrfv2plus/vrfv2plus_config/config.go @@ -0,0 +1,41 @@ +package vrfv2plus_config + +import "time" + +type VRFV2PlusConfig struct { + ChainlinkNodeFunding float64 `envconfig:"CHAINLINK_NODE_FUNDING" default:".1"` // Amount of native currency to fund each chainlink node with + IsNativePayment bool `envconfig:"IS_NATIVE_PAYMENT" default:"false"` // Whether to use native payment or LINK token + LinkNativeFeedResponse int64 `envconfig:"LINK_NATIVE_FEED_RESPONSE" default:"1000000000000000000"` // Response of the LINK/ETH feed + MinimumConfirmations uint16 `envconfig:"MINIMUM_CONFIRMATIONS" default:"3"` // Minimum number of confirmations for the VRF Coordinator + SubscriptionFundingAmountLink int64 `envconfig:"SUBSCRIPTION_FUNDING_AMOUNT_LINK" default:"10"` // Amount of LINK to fund the subscription with + SubscriptionFundingAmountNative int64 `envconfig:"SUBSCRIPTION_FUNDING_AMOUNT_NATIVE" default:"1"` // Amount of native currency to fund the subscription with + NumberOfWords uint32 `envconfig:"NUMBER_OF_WORDS" default:"3"` // Number of words to request + CallbackGasLimit uint32 `envconfig:"CALLBACK_GAS_LIMIT" default:"1000000"` // Gas limit for the callback + MaxGasLimitCoordinatorConfig uint32 `envconfig:"MAX_GAS_LIMIT_COORDINATOR_CONFIG" default:"2500000"` // Max gas limit for the VRF Coordinator config + FallbackWeiPerUnitLink int64 `envconfig:"FALLBACK_WEI_PER_UNIT_LINK" default:"60000000000000000"` // Fallback wei per unit LINK for the VRF Coordinator config + StalenessSeconds uint32 `envconfig:"STALENESS_SECONDS" default:"86400"` // Staleness in seconds for the VRF Coordinator config + GasAfterPaymentCalculation uint32 `envconfig:"GAS_AFTER_PAYMENT_CALCULATION" default:"33825"` // Gas after payment calculation for the VRF Coordinator config + FulfillmentFlatFeeLinkPPM uint32 `envconfig:"FULFILLMENT_FLAT_FEE_LINK_PPM" default:"500"` // Flat fee in ppm for LINK for the VRF Coordinator config + FulfillmentFlatFeeNativePPM uint32 `envconfig:"FULFILLMENT_FLAT_FEE_NATIVE_PPM" default:"500"` // Flat fee in ppm for native currency for the VRF Coordinator config + + RandomnessRequestCountPerRequest uint16 `envconfig:"RANDOMNESS_REQUEST_COUNT_PER_REQUEST" default:"1"` // How many randomness requests to send per request + + //Wrapper Config + WrapperGasOverhead uint32 `envconfig:"WRAPPER_GAS_OVERHEAD" default:"50000"` + CoordinatorGasOverhead uint32 `envconfig:"COORDINATOR_GAS_OVERHEAD" default:"52000"` + WrapperPremiumPercentage uint8 `envconfig:"WRAPPER_PREMIUM_PERCENTAGE" default:"25"` + WrapperMaxNumberOfWords uint8 `envconfig:"WRAPPER_MAX_NUMBER_OF_WORDS" default:"10"` + WrapperConsumerFundingAmountNativeToken float64 `envconfig:"WRAPPER_CONSUMER_FUNDING_AMOUNT_NATIVE_TOKEN" default:"1"` + WrapperConsumerFundingAmountLink int64 `envconfig:"WRAPPER_CONSUMER_FUNDING_AMOUNT_LINK" default:"10"` + + //LOAD/SOAK Test Config + TestDuration time.Duration `envconfig:"TEST_DURATION" default:"3m"` // How long to run the test for + RPS int64 `envconfig:"RPS" default:"1"` // How many requests per second to send + RateLimitUnitDuration time.Duration `envconfig:"RATE_LIMIT_UNIT_DURATION" default:"1m"` + //Using existing environment and contracts + UseExistingEnv bool `envconfig:"USE_EXISTING_ENV" default:"false"` // Whether to use an existing environment or create a new one + CoordinatorAddress string `envconfig:"COORDINATOR_ADDRESS" default:""` // Coordinator address + ConsumerAddress string `envconfig:"CONSUMER_ADDRESS" default:""` // Consumer address + SubID string `envconfig:"SUB_ID" default:""` // Subscription ID + KeyHash string `envconfig:"KEY_HASH" default:""` +} diff --git a/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go b/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go index aa6dba8e1b..17e321ea63 100644 --- a/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go +++ b/integration-tests/actions/vrfv2plus/vrfv2plus_steps.go @@ -6,18 +6,20 @@ import ( "math/big" "time" + "github.com/smartcontractkit/chainlink/v2/core/assets" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2plus_wrapper_load_test_consumer" + "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink/integration-tests/actions" - "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus/vrfv2plus_constants" + "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus/vrfv2plus_config" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" - "github.com/smartcontractkit/chainlink/v2/core/assets" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2_5" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_upgraded_version" chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/utils" @@ -232,6 +234,7 @@ func FundVRFCoordinatorV2_5Subscription(linkToken contracts.LinkToken, coordinat func SetupVRFV2_5Environment( env *test_env.CLClusterTestEnv, + vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig, linkToken contracts.LinkToken, mockNativeLINKFeed contracts.MockETHLINKFeed, consumerContractsAmount int, @@ -243,12 +246,15 @@ func SetupVRFV2_5Environment( } err = vrfv2_5Contracts.Coordinator.SetConfig( - vrfv2plus_constants.MinimumConfirmations, - vrfv2plus_constants.MaxGasLimitVRFCoordinatorConfig, - vrfv2plus_constants.StalenessSeconds, - vrfv2plus_constants.GasAfterPaymentCalculation, - vrfv2plus_constants.LinkNativeFeedResponse, - vrfv2plus_constants.VRFCoordinatorV2_5FeeConfig, + vrfv2PlusConfig.MinimumConfirmations, + vrfv2PlusConfig.MaxGasLimitCoordinatorConfig, + vrfv2PlusConfig.StalenessSeconds, + vrfv2PlusConfig.GasAfterPaymentCalculation, + big.NewInt(vrfv2PlusConfig.LinkNativeFeedResponse), + vrf_coordinator_v2_5.VRFCoordinatorV25FeeConfig{ + FulfillmentFlatFeeLinkPPM: vrfv2PlusConfig.FulfillmentFlatFeeLinkPPM, + FulfillmentFlatFeeNativePPM: vrfv2PlusConfig.FulfillmentFlatFeeNativePPM, + }, ) if err != nil { return nil, nil, nil, errors.Wrap(err, ErrSetVRFCoordinatorConfig) @@ -278,18 +284,18 @@ func SetupVRFV2_5Environment( if err != nil { return nil, nil, nil, errors.Wrap(err, ErrWaitTXsComplete) } - err = FundSubscription(env, linkToken, vrfv2_5Contracts.Coordinator, subID) + err = FundSubscription(env, vrfv2PlusConfig, linkToken, vrfv2_5Contracts.Coordinator, subID) if err != nil { return nil, nil, nil, err } - vrfKey, err := env.GetAPIs()[0].MustCreateVRFKey() + vrfKey, err := env.ClCluster.NodeAPIs()[0].MustCreateVRFKey() if err != nil { return nil, nil, nil, errors.Wrap(err, ErrCreatingVRFv2PlusKey) } pubKeyCompressed := vrfKey.Data.ID - nativeTokenPrimaryKeyAddress, err := env.GetAPIs()[0].PrimaryEthAddress() + nativeTokenPrimaryKeyAddress, err := env.ClCluster.NodeAPIs()[0].PrimaryEthAddress() if err != nil { return nil, nil, nil, errors.Wrap(err, ErrNodePrimaryKey) } @@ -305,12 +311,12 @@ func SetupVRFV2_5Environment( chainID := env.EVMClient.GetChainID() job, err := CreateVRFV2PlusJob( - env.GetAPIs()[0], + env.ClCluster.NodeAPIs()[0], vrfv2_5Contracts.Coordinator.Address(), nativeTokenPrimaryKeyAddress, pubKeyCompressed, chainID.String(), - vrfv2plus_constants.MinimumConfirmations, + vrfv2PlusConfig.MinimumConfirmations, ) if err != nil { return nil, nil, nil, errors.Wrap(err, ErrCreateVRFV2PlusJobs) @@ -319,14 +325,14 @@ func SetupVRFV2_5Environment( // this part is here because VRFv2 can work with only a specific key // [[EVM.KeySpecific]] // Key = '...' - addr, err := env.CLNodes[0].API.PrimaryEthAddress() + addr, err := env.ClCluster.Nodes[0].API.PrimaryEthAddress() if err != nil { return nil, nil, nil, errors.Wrap(err, ErrGetPrimaryKey) } - nodeConfig := node.NewConfig(env.CLNodes[0].NodeConfig, + nodeConfig := node.NewConfig(env.ClCluster.Nodes[0].NodeConfig, node.WithVRFv2EVMEstimator(addr), ) - err = env.CLNodes[0].Restart(nodeConfig) + err = env.ClCluster.Nodes[0].Restart(nodeConfig) if err != nil { return nil, nil, nil, errors.Wrap(err, ErrRestartCLNode) } @@ -349,6 +355,7 @@ func SetupVRFV2_5Environment( func SetupVRFV2PlusWrapperEnvironment( env *test_env.CLClusterTestEnv, + vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig, linkToken contracts.LinkToken, mockNativeLINKFeed contracts.MockETHLINKFeed, coordinator contracts.VRFCoordinatorV2_5, @@ -373,17 +380,16 @@ func SetupVRFV2PlusWrapperEnvironment( if err != nil { return nil, nil, errors.Wrap(err, ErrWaitTXsComplete) } - err = wrapperContracts.VRFV2PlusWrapper.SetConfig( - vrfv2plus_constants.WrapperGasOverhead, - vrfv2plus_constants.CoordinatorGasOverhead, - vrfv2plus_constants.WrapperPremiumPercentage, + vrfv2PlusConfig.WrapperGasOverhead, + vrfv2PlusConfig.CoordinatorGasOverhead, + vrfv2PlusConfig.WrapperPremiumPercentage, keyHash, - vrfv2plus_constants.WrapperMaxNumberOfWords, - vrfv2plus_constants.StalenessSeconds, - assets.GWei(50_000_000).ToInt(), - vrfv2plus_constants.VRFCoordinatorV2_5FeeConfig.FulfillmentFlatFeeLinkPPM, - vrfv2plus_constants.VRFCoordinatorV2_5FeeConfig.FulfillmentFlatFeeNativePPM, + vrfv2PlusConfig.WrapperMaxNumberOfWords, + vrfv2PlusConfig.StalenessSeconds, + big.NewInt(vrfv2PlusConfig.FallbackWeiPerUnitLink), + vrfv2PlusConfig.FulfillmentFlatFeeLinkPPM, + vrfv2PlusConfig.FulfillmentFlatFeeNativePPM, ) if err != nil { return nil, nil, err @@ -405,7 +411,7 @@ func SetupVRFV2PlusWrapperEnvironment( return nil, nil, errors.Wrap(err, ErrWaitTXsComplete) } - err = FundSubscription(env, linkToken, coordinator, wrapperSubID) + err = FundSubscription(env, vrfv2PlusConfig, linkToken, coordinator, wrapperSubID) if err != nil { return nil, nil, err } @@ -413,7 +419,7 @@ func SetupVRFV2PlusWrapperEnvironment( //fund consumer with Link err = linkToken.Transfer( wrapperContracts.LoadTestConsumers[0].Address(), - big.NewInt(0).Mul(big.NewInt(1e18), vrfv2plus_constants.WrapperConsumerFundingAmountLink), + big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(vrfv2PlusConfig.WrapperConsumerFundingAmountLink)), ) if err != nil { return nil, nil, err @@ -424,7 +430,7 @@ func SetupVRFV2PlusWrapperEnvironment( } //fund consumer with Eth - err = wrapperContracts.LoadTestConsumers[0].Fund(vrfv2plus_constants.WrapperConsumerFundingAmountNativeToken) + err = wrapperContracts.LoadTestConsumers[0].Fund(big.NewFloat(vrfv2PlusConfig.WrapperConsumerFundingAmountNativeToken)) if err != nil { return nil, nil, err } @@ -474,14 +480,20 @@ func GetCoordinatorTotalBalance(coordinator contracts.VRFCoordinatorV2_5) (linkT return } -func FundSubscription(env *test_env.CLClusterTestEnv, linkAddress contracts.LinkToken, coordinator contracts.VRFCoordinatorV2_5, subID *big.Int) error { +func FundSubscription( + env *test_env.CLClusterTestEnv, + vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig, + linkAddress contracts.LinkToken, + coordinator contracts.VRFCoordinatorV2_5, + subID *big.Int, +) error { //Native Billing - err := coordinator.FundSubscriptionWithNative(subID, big.NewInt(0).Mul(vrfv2plus_constants.VRFSubscriptionFundingAmountNativeToken, big.NewInt(1e18))) + err := coordinator.FundSubscriptionWithNative(subID, big.NewInt(0).Mul(big.NewInt(vrfv2PlusConfig.SubscriptionFundingAmountNative), big.NewInt(1e18))) if err != nil { return errors.Wrap(err, ErrFundSubWithNativeToken) } - err = FundVRFCoordinatorV2_5Subscription(linkAddress, coordinator, env.EVMClient, subID, vrfv2plus_constants.VRFSubscriptionFundingAmountLink) + err = FundVRFCoordinatorV2_5Subscription(linkAddress, coordinator, env.EVMClient, subID, big.NewInt(vrfv2PlusConfig.SubscriptionFundingAmountLink)) if err != nil { return errors.Wrap(err, ErrFundSubWithLinkToken) } @@ -499,22 +511,24 @@ func RequestRandomnessAndWaitForFulfillment( vrfv2PlusData *VRFV2PlusData, subID *big.Int, isNativeBilling bool, + vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig, l zerolog.Logger, ) (*vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled, error) { + logRandRequest(consumer.Address(), coordinator.Address(), subID, isNativeBilling, vrfv2PlusConfig, l) _, err := consumer.RequestRandomness( vrfv2PlusData.KeyHash, subID, - vrfv2plus_constants.MinimumConfirmations, - vrfv2plus_constants.CallbackGasLimit, + vrfv2PlusConfig.MinimumConfirmations, + vrfv2PlusConfig.CallbackGasLimit, isNativeBilling, - vrfv2plus_constants.NumberOfWords, - vrfv2plus_constants.RandomnessRequestCountPerRequest, + vrfv2PlusConfig.NumberOfWords, + vrfv2PlusConfig.RandomnessRequestCountPerRequest, ) if err != nil { return nil, errors.Wrap(err, ErrRequestRandomness) } - return WaitForRequestAndFulfillmentEvents(consumer.Address(), coordinator, vrfv2PlusData, subID, l) + return WaitForRequestAndFulfillmentEvents(consumer.Address(), coordinator, vrfv2PlusData, subID, isNativeBilling, l) } func RequestRandomnessAndWaitForFulfillmentUpgraded( @@ -523,16 +537,18 @@ func RequestRandomnessAndWaitForFulfillmentUpgraded( vrfv2PlusData *VRFV2PlusData, subID *big.Int, isNativeBilling bool, + vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig, l zerolog.Logger, ) (*vrf_v2plus_upgraded_version.VRFCoordinatorV2PlusUpgradedVersionRandomWordsFulfilled, error) { + logRandRequest(consumer.Address(), coordinator.Address(), subID, isNativeBilling, vrfv2PlusConfig, l) _, err := consumer.RequestRandomness( vrfv2PlusData.KeyHash, subID, - vrfv2plus_constants.MinimumConfirmations, - vrfv2plus_constants.CallbackGasLimit, + vrfv2PlusConfig.MinimumConfirmations, + vrfv2PlusConfig.CallbackGasLimit, isNativeBilling, - vrfv2plus_constants.NumberOfWords, - vrfv2plus_constants.RandomnessRequestCountPerRequest, + vrfv2PlusConfig.NumberOfWords, + vrfv2PlusConfig.RandomnessRequestCountPerRequest, ) if err != nil { return nil, errors.Wrap(err, ErrRequestRandomness) @@ -548,15 +564,7 @@ func RequestRandomnessAndWaitForFulfillmentUpgraded( return nil, errors.Wrap(err, ErrWaitRandomWordsRequestedEvent) } - l.Debug(). - Str("Request ID", randomWordsRequestedEvent.RequestId.String()). - Str("Subscription ID", randomWordsRequestedEvent.SubId.String()). - Str("Sender Address", randomWordsRequestedEvent.Sender.String()). - Interface("Keyhash", randomWordsRequestedEvent.KeyHash). - Uint32("Callback Gas Limit", randomWordsRequestedEvent.CallbackGasLimit). - Uint32("Number of Words", randomWordsRequestedEvent.NumWords). - Uint16("Minimum Request Confirmations", randomWordsRequestedEvent.MinimumRequestConfirmations). - Msg("RandomnessRequested Event") + LogRandomnessRequestedEventUpgraded(l, coordinator, randomWordsRequestedEvent) randomWordsFulfilledEvent, err := coordinator.WaitForRandomWordsFulfilledEvent( []*big.Int{subID}, @@ -566,14 +574,8 @@ func RequestRandomnessAndWaitForFulfillmentUpgraded( if err != nil { return nil, errors.Wrap(err, ErrWaitRandomWordsFulfilledEvent) } + LogRandomWordsFulfilledEventUpgraded(l, coordinator, randomWordsFulfilledEvent) - l.Debug(). - Str("Total Payment in Juels", randomWordsFulfilledEvent.Payment.String()). - Str("TX Hash", randomWordsFulfilledEvent.Raw.TxHash.String()). - Str("Subscription ID", randomWordsFulfilledEvent.SubID.String()). - Str("Request ID", randomWordsFulfilledEvent.RequestId.String()). - Bool("Success", randomWordsFulfilledEvent.Success). - Msg("RandomWordsFulfilled Event (TX metadata)") return randomWordsFulfilledEvent, err } @@ -583,24 +585,26 @@ func DirectFundingRequestRandomnessAndWaitForFulfillment( vrfv2PlusData *VRFV2PlusData, subID *big.Int, isNativeBilling bool, + vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig, l zerolog.Logger, ) (*vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled, error) { + logRandRequest(consumer.Address(), coordinator.Address(), subID, isNativeBilling, vrfv2PlusConfig, l) if isNativeBilling { _, err := consumer.RequestRandomnessNative( - vrfv2plus_constants.MinimumConfirmations, - vrfv2plus_constants.CallbackGasLimit, - vrfv2plus_constants.NumberOfWords, - vrfv2plus_constants.RandomnessRequestCountPerRequest, + vrfv2PlusConfig.MinimumConfirmations, + vrfv2PlusConfig.CallbackGasLimit, + vrfv2PlusConfig.NumberOfWords, + vrfv2PlusConfig.RandomnessRequestCountPerRequest, ) if err != nil { return nil, errors.Wrap(err, ErrRequestRandomnessDirectFundingNativePayment) } } else { _, err := consumer.RequestRandomness( - vrfv2plus_constants.MinimumConfirmations, - vrfv2plus_constants.CallbackGasLimit, - vrfv2plus_constants.NumberOfWords, - vrfv2plus_constants.RandomnessRequestCountPerRequest, + vrfv2PlusConfig.MinimumConfirmations, + vrfv2PlusConfig.CallbackGasLimit, + vrfv2PlusConfig.NumberOfWords, + vrfv2PlusConfig.RandomnessRequestCountPerRequest, ) if err != nil { return nil, errors.Wrap(err, ErrRequestRandomnessDirectFundingLinkPayment) @@ -610,7 +614,7 @@ func DirectFundingRequestRandomnessAndWaitForFulfillment( if err != nil { return nil, errors.Wrap(err, "error getting wrapper address") } - return WaitForRequestAndFulfillmentEvents(wrapperAddress.String(), coordinator, vrfv2PlusData, subID, l) + return WaitForRequestAndFulfillmentEvents(wrapperAddress.String(), coordinator, vrfv2PlusData, subID, isNativeBilling, l) } func WaitForRequestAndFulfillmentEvents( @@ -618,6 +622,7 @@ func WaitForRequestAndFulfillmentEvents( coordinator contracts.VRFCoordinatorV2_5, vrfv2PlusData *VRFV2PlusData, subID *big.Int, + isNativeBilling bool, l zerolog.Logger, ) (*vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled, error) { randomWordsRequestedEvent, err := coordinator.WaitForRandomWordsRequestedEvent( @@ -630,15 +635,7 @@ func WaitForRequestAndFulfillmentEvents( return nil, errors.Wrap(err, ErrWaitRandomWordsRequestedEvent) } - l.Debug(). - Str("Request ID", randomWordsRequestedEvent.RequestId.String()). - Str("Subscription ID", randomWordsRequestedEvent.SubId.String()). - Str("Sender Address", randomWordsRequestedEvent.Sender.String()). - Interface("Keyhash", randomWordsRequestedEvent.KeyHash). - Uint32("Callback Gas Limit", randomWordsRequestedEvent.CallbackGasLimit). - Uint32("Number of Words", randomWordsRequestedEvent.NumWords). - Uint16("Minimum Request Confirmations", randomWordsRequestedEvent.MinimumRequestConfirmations). - Msg("RandomnessRequested Event") + LogRandomnessRequestedEvent(l, coordinator, randomWordsRequestedEvent, isNativeBilling) randomWordsFulfilledEvent, err := coordinator.WaitForRandomWordsFulfilledEvent( []*big.Int{subID}, @@ -649,12 +646,163 @@ func WaitForRequestAndFulfillmentEvents( return nil, errors.Wrap(err, ErrWaitRandomWordsFulfilledEvent) } + LogRandomWordsFulfilledEvent(l, coordinator, randomWordsFulfilledEvent, isNativeBilling) + return randomWordsFulfilledEvent, err +} + +func LogSubDetails(l zerolog.Logger, subscription vrf_coordinator_v2_5.GetSubscription, subID *big.Int, coordinator contracts.VRFCoordinatorV2_5) { l.Debug(). + Str("Coordinator", coordinator.Address()). + Str("Link Balance", (*assets.Link)(subscription.Balance).Link()). + Str("Native Token Balance", assets.FormatWei(subscription.NativeBalance)). + Str("Subscription ID", subID.String()). + Str("Subscription Owner", subscription.Owner.String()). + Interface("Subscription Consumers", subscription.Consumers). + Msg("Subscription Data") +} + +func LogRandomnessRequestedEventUpgraded( + l zerolog.Logger, + coordinator contracts.VRFCoordinatorV2PlusUpgradedVersion, + randomWordsRequestedEvent *vrf_v2plus_upgraded_version.VRFCoordinatorV2PlusUpgradedVersionRandomWordsRequested, +) { + l.Debug(). + Str("Coordinator", coordinator.Address()). + Str("Request ID", randomWordsRequestedEvent.RequestId.String()). + Str("Subscription ID", randomWordsRequestedEvent.SubId.String()). + Str("Sender Address", randomWordsRequestedEvent.Sender.String()). + Interface("Keyhash", randomWordsRequestedEvent.KeyHash). + Uint32("Callback Gas Limit", randomWordsRequestedEvent.CallbackGasLimit). + Uint32("Number of Words", randomWordsRequestedEvent.NumWords). + Uint16("Minimum Request Confirmations", randomWordsRequestedEvent.MinimumRequestConfirmations). + Msg("RandomnessRequested Event") +} + +func LogRandomWordsFulfilledEventUpgraded( + l zerolog.Logger, + coordinator contracts.VRFCoordinatorV2PlusUpgradedVersion, + randomWordsFulfilledEvent *vrf_v2plus_upgraded_version.VRFCoordinatorV2PlusUpgradedVersionRandomWordsFulfilled, +) { + l.Debug(). + Str("Coordinator", coordinator.Address()). Str("Total Payment in Juels", randomWordsFulfilledEvent.Payment.String()). Str("TX Hash", randomWordsFulfilledEvent.Raw.TxHash.String()). + Str("Subscription ID", randomWordsFulfilledEvent.SubID.String()). + Str("Request ID", randomWordsFulfilledEvent.RequestId.String()). + Bool("Success", randomWordsFulfilledEvent.Success). + Msg("RandomWordsFulfilled Event (TX metadata)") +} + +func LogRandomnessRequestedEvent( + l zerolog.Logger, + coordinator contracts.VRFCoordinatorV2_5, + randomWordsRequestedEvent *vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsRequested, + isNativeBilling bool, +) { + l.Debug(). + Str("Coordinator", coordinator.Address()). + Bool("Native Billing", isNativeBilling). + Str("Request ID", randomWordsRequestedEvent.RequestId.String()). + Str("Subscription ID", randomWordsRequestedEvent.SubId.String()). + Str("Sender Address", randomWordsRequestedEvent.Sender.String()). + Interface("Keyhash", randomWordsRequestedEvent.KeyHash). + Uint32("Callback Gas Limit", randomWordsRequestedEvent.CallbackGasLimit). + Uint32("Number of Words", randomWordsRequestedEvent.NumWords). + Uint16("Minimum Request Confirmations", randomWordsRequestedEvent.MinimumRequestConfirmations). + Msg("RandomnessRequested Event") +} + +func LogRandomWordsFulfilledEvent( + l zerolog.Logger, + coordinator contracts.VRFCoordinatorV2_5, + randomWordsFulfilledEvent *vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled, + isNativeBilling bool, +) { + l.Debug(). + Bool("Native Billing", isNativeBilling). + Str("Coordinator", coordinator.Address()). + Str("Total Payment", randomWordsFulfilledEvent.Payment.String()). + Str("TX Hash", randomWordsFulfilledEvent.Raw.TxHash.String()). Str("Subscription ID", randomWordsFulfilledEvent.SubId.String()). Str("Request ID", randomWordsFulfilledEvent.RequestId.String()). Bool("Success", randomWordsFulfilledEvent.Success). Msg("RandomWordsFulfilled Event (TX metadata)") - return randomWordsFulfilledEvent, err +} + +func LogMigrationCompletedEvent(l zerolog.Logger, migrationCompletedEvent *vrf_coordinator_v2_5.VRFCoordinatorV25MigrationCompleted, vrfv2PlusContracts *VRFV2_5Contracts) { + l.Debug(). + Str("Subscription ID", migrationCompletedEvent.SubId.String()). + Str("Migrated From Coordinator", vrfv2PlusContracts.Coordinator.Address()). + Str("Migrated To Coordinator", migrationCompletedEvent.NewCoordinator.String()). + Msg("MigrationCompleted Event") +} + +func LogSubDetailsAfterMigration(l zerolog.Logger, newCoordinator contracts.VRFCoordinatorV2PlusUpgradedVersion, subID *big.Int, migratedSubscription vrf_v2plus_upgraded_version.GetSubscription) { + l.Debug(). + Str("New Coordinator", newCoordinator.Address()). + Str("Subscription ID", subID.String()). + Str("Juels Balance", migratedSubscription.Balance.String()). + Str("Native Token Balance", migratedSubscription.NativeBalance.String()). + Str("Subscription Owner", migratedSubscription.Owner.String()). + Interface("Subscription Consumers", migratedSubscription.Consumers). + Msg("Subscription Data After Migration to New Coordinator") +} + +func LogFulfillmentDetailsLinkBilling( + l zerolog.Logger, + wrapperConsumerJuelsBalanceBeforeRequest *big.Int, + wrapperConsumerJuelsBalanceAfterRequest *big.Int, + consumerStatus vrfv2plus_wrapper_load_test_consumer.GetRequestStatus, + randomWordsFulfilledEvent *vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled, +) { + l.Debug(). + Str("Consumer Balance Before Request (Link)", (*assets.Link)(wrapperConsumerJuelsBalanceBeforeRequest).Link()). + Str("Consumer Balance After Request (Link)", (*assets.Link)(wrapperConsumerJuelsBalanceAfterRequest).Link()). + Bool("Fulfilment Status", consumerStatus.Fulfilled). + Str("Paid by Consumer Contract (Link)", (*assets.Link)(consumerStatus.Paid).Link()). + Str("Paid by Coordinator Sub (Link)", (*assets.Link)(randomWordsFulfilledEvent.Payment).Link()). + Str("RequestTimestamp", consumerStatus.RequestTimestamp.String()). + Str("FulfilmentTimestamp", consumerStatus.FulfilmentTimestamp.String()). + Str("RequestBlockNumber", consumerStatus.RequestBlockNumber.String()). + Str("FulfilmentBlockNumber", consumerStatus.FulfilmentBlockNumber.String()). + Str("TX Hash", randomWordsFulfilledEvent.Raw.TxHash.String()). + Msg("Random Words Fulfilment Details For Link Billing") +} + +func LogFulfillmentDetailsNativeBilling( + l zerolog.Logger, + wrapperConsumerBalanceBeforeRequestWei *big.Int, + wrapperConsumerBalanceAfterRequestWei *big.Int, + consumerStatus vrfv2plus_wrapper_load_test_consumer.GetRequestStatus, + randomWordsFulfilledEvent *vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled, +) { + l.Debug(). + Str("Consumer Balance Before Request", assets.FormatWei(wrapperConsumerBalanceBeforeRequestWei)). + Str("Consumer Balance After Request", assets.FormatWei(wrapperConsumerBalanceAfterRequestWei)). + Bool("Fulfilment Status", consumerStatus.Fulfilled). + Str("Paid by Consumer Contract", assets.FormatWei(consumerStatus.Paid)). + Str("Paid by Coordinator Sub", assets.FormatWei(randomWordsFulfilledEvent.Payment)). + Str("RequestTimestamp", consumerStatus.RequestTimestamp.String()). + Str("FulfilmentTimestamp", consumerStatus.FulfilmentTimestamp.String()). + Str("RequestBlockNumber", consumerStatus.RequestBlockNumber.String()). + Str("FulfilmentBlockNumber", consumerStatus.FulfilmentBlockNumber.String()). + Str("TX Hash", randomWordsFulfilledEvent.Raw.TxHash.String()). + Msg("Random Words Request Fulfilment Details For Native Billing") +} + +func logRandRequest( + consumer string, + coordinator string, + subID *big.Int, + isNativeBilling bool, + vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig, + l zerolog.Logger) { + l.Debug(). + Str("Consumer", consumer). + Str("Coordinator", coordinator). + Str("subID", subID.String()). + Bool("IsNativePayment", isNativeBilling). + Uint16("MinimumConfirmations", vrfv2PlusConfig.MinimumConfirmations). + Uint16("RandomnessRequestCountPerRequest", vrfv2PlusConfig.RandomnessRequestCountPerRequest). + Msg("Requesting randomness") } diff --git a/integration-tests/benchmark/keeper_test.go b/integration-tests/benchmark/keeper_test.go index 59406e5158..7178ab854e 100644 --- a/integration-tests/benchmark/keeper_test.go +++ b/integration-tests/benchmark/keeper_test.go @@ -81,7 +81,7 @@ LimitDefault = 5_000_000` }, }, "stateful": true, - "capacity": "1Gi", + "capacity": "10Gi", } soakChainlinkResources = map[string]interface{}{ @@ -108,7 +108,7 @@ LimitDefault = 5_000_000` }, }, "stateful": true, - "capacity": "1Gi", + "capacity": "10Gi", } ) @@ -156,22 +156,22 @@ func TestAutomationBenchmark(t *testing.T) { chainClient, err := blockchain.NewEVMClient(benchmarkNetwork, testEnvironment, l) require.NoError(t, err, "Error connecting to blockchain") registryVersions := addRegistry(RegistryToTest) - keeperBenchmarkTest := testsetups.NewKeeperBenchmarkTest( + keeperBenchmarkTest := testsetups.NewKeeperBenchmarkTest(t, testsetups.KeeperBenchmarkTestInputs{ BlockchainClient: chainClient, RegistryVersions: registryVersions, KeeperRegistrySettings: &contracts.KeeperRegistrySettings{ PaymentPremiumPPB: uint32(0), BlockCountPerTurn: big.NewInt(100), - CheckGasLimit: uint32(45000000), //45M - StalenessSeconds: big.NewInt(90000), + CheckGasLimit: uint32(45_000_000), //45M + StalenessSeconds: big.NewInt(90_000), GasCeilingMultiplier: uint16(2), MaxPerformGas: uint32(MaxPerformGas), MinUpkeepSpend: big.NewInt(0), FallbackGasPrice: big.NewInt(2e11), FallbackLinkPrice: big.NewInt(2e18), - MaxCheckDataSize: uint32(5000), - MaxPerformDataSize: uint32(5000), + MaxCheckDataSize: uint32(5_000), + MaxPerformDataSize: uint32(5_000), }, Upkeeps: &testsetups.UpkeepConfig{ NumberOfUpkeeps: NumberOfUpkeeps, @@ -202,8 +202,8 @@ func TestAutomationBenchmark(t *testing.T) { l.Error().Err(err).Msg("Error when tearing down remote suite") } }) - keeperBenchmarkTest.Setup(t, testEnvironment) - keeperBenchmarkTest.Run(t) + keeperBenchmarkTest.Setup(testEnvironment) + keeperBenchmarkTest.Run() } func addRegistry(registryToTest string) []eth_contracts.KeeperRegistryVersion { @@ -316,7 +316,8 @@ func SetupAutomationBenchmarkEnv(t *testing.T) (*environment.Environment, blockc strings.ReplaceAll(strings.ToLower(testNetwork.Name), " ", "-"), strings.ReplaceAll(strings.ToLower(RegistryToTest), "_", "-"), ), - Test: t, + Test: t, + PreventPodEviction: true, }) // propagate TEST_INPUTS to remote runner if testEnvironment.WillUseRemoteRunner() { diff --git a/integration-tests/ccip-tests/actions/ccip_helpers.go b/integration-tests/ccip-tests/actions/ccip_helpers.go index 1503d898b8..7cfbebef6a 100644 --- a/integration-tests/ccip-tests/actions/ccip_helpers.go +++ b/integration-tests/ccip-tests/actions/ccip_helpers.go @@ -2231,7 +2231,7 @@ func (c *CCIPTestEnv) SetUpNodesAndKeys( //var err error if c.LocalCluster != nil { // for local cluster, fetch the values from the local cluster - for _, chainlinkNode := range c.LocalCluster.CLNodes { + for _, chainlinkNode := range c.LocalCluster.ClCluster.Nodes { chainlinkNodes = append(chainlinkNodes, chainlinkNode.API) c.nodeMutexes = append(c.nodeMutexes, &sync.Mutex{}) } @@ -2247,8 +2247,6 @@ func (c *CCIPTestEnv) SetUpNodesAndKeys( } for _, chainlinkNode := range chainlinkK8sNodes { - chainlinkNode.ChainlinkClient.SetLogger(logger) - chainlinkNode.ChainlinkClient.AddRetryAttempt(3) chainlinkNodes = append(chainlinkNodes, chainlinkNode.ChainlinkClient) c.nodeMutexes = append(c.nodeMutexes, &sync.Mutex{}) } diff --git a/integration-tests/ccip-tests/testsetups/ccip.go b/integration-tests/ccip-tests/testsetups/ccip.go index ae0da03602..77610c1726 100644 --- a/integration-tests/ccip-tests/testsetups/ccip.go +++ b/integration-tests/ccip-tests/testsetups/ccip.go @@ -1198,6 +1198,7 @@ func DeployLocalCluster( networks []blockchain.EVMNetwork, ) (*test_env.CLClusterTestEnv, func() error) { env, err := test_env.NewCLTestEnvBuilder(). + WithTestLogger(t). WithPrivateGethChains(networks). Build() require.NoError(t, err) @@ -1220,7 +1221,7 @@ func DeployLocalCluster( if err != nil { return err } - return env.StartClNodes(toml, noOfCLNodes, "") + return env.StartClCluster(toml, noOfCLNodes, "") } return env, deployCL } diff --git a/integration-tests/chaos/automation_chaos_test.go b/integration-tests/chaos/automation_chaos_test.go index c292c130c5..244f6c36ea 100644 --- a/integration-tests/chaos/automation_chaos_test.go +++ b/integration-tests/chaos/automation_chaos_test.go @@ -111,174 +111,190 @@ func TestAutomationChaos(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - testCases := map[string]struct { - networkChart environment.ConnectedChart - clChart environment.ConnectedChart - chaosFunc chaos.ManifestFunc - chaosProps *chaos.Props - }{ - // see ocr_chaos.test.go for comments - PodChaosFailMinorityNodes: { - ethereum.New(defaultEthereumSettings), - chainlink.New(0, defaultAutomationSettings), - chaos.NewFailPods, - &chaos.Props{ - LabelsSelector: &map[string]*string{ChaosGroupMinority: a.Str("1")}, - DurationStr: "1m", - }, - }, - PodChaosFailMajorityNodes: { - ethereum.New(defaultEthereumSettings), - chainlink.New(0, defaultAutomationSettings), - chaos.NewFailPods, - &chaos.Props{ - LabelsSelector: &map[string]*string{ChaosGroupMajority: a.Str("1")}, - DurationStr: "1m", - }, - }, - PodChaosFailMajorityDB: { - ethereum.New(defaultEthereumSettings), - chainlink.New(0, defaultAutomationSettings), - chaos.NewFailPods, - &chaos.Props{ - LabelsSelector: &map[string]*string{ChaosGroupMajority: a.Str("1")}, - DurationStr: "1m", - ContainerNames: &[]*string{a.Str("chainlink-db")}, - }, - }, - NetworkChaosFailMajorityNetwork: { - ethereum.New(defaultEthereumSettings), - chainlink.New(0, defaultAutomationSettings), - chaos.NewNetworkPartition, - &chaos.Props{ - FromLabels: &map[string]*string{ChaosGroupMajority: a.Str("1")}, - ToLabels: &map[string]*string{ChaosGroupMinority: a.Str("1")}, - DurationStr: "1m", - }, - }, - NetworkChaosFailBlockchainNode: { - ethereum.New(defaultEthereumSettings), - chainlink.New(0, defaultAutomationSettings), - chaos.NewNetworkPartition, - &chaos.Props{ - FromLabels: &map[string]*string{"app": a.Str("geth")}, - ToLabels: &map[string]*string{ChaosGroupMajorityPlus: a.Str("1")}, - DurationStr: "1m", - }, - }, + registryVersions := map[string]eth_contracts.KeeperRegistryVersion{ + "registry_2_0": eth_contracts.RegistryVersion_2_0, + "registry_2_1": eth_contracts.RegistryVersion_2_1, } - for n, tst := range testCases { - name := n - testCase := tst - t.Run(fmt.Sprintf("Automation_%s", name), func(t *testing.T) { + for name, registryVersion := range registryVersions { + t.Run(name, func(t *testing.T) { t.Parallel() - network := networks.SelectedNetwork // Need a new copy of the network for each test - - testEnvironment := environment. - New(&environment.Config{ - NamespacePrefix: fmt.Sprintf("chaos-automation-%s", name), - TTL: time.Hour * 1, - Test: t, - }). - AddHelm(testCase.networkChart). - AddHelm(testCase.clChart). - AddChart(blockscout.New(&blockscout.Props{ - Name: "geth-blockscout", - WsURL: network.URL, - HttpURL: network.HTTPURLs[0], - })) - err := testEnvironment.Run() - require.NoError(t, err, "Error setting up test environment") - if testEnvironment.WillUseRemoteRunner() { - return + + testCases := map[string]struct { + networkChart environment.ConnectedChart + clChart environment.ConnectedChart + chaosFunc chaos.ManifestFunc + chaosProps *chaos.Props + }{ + // see ocr_chaos.test.go for comments + PodChaosFailMinorityNodes: { + ethereum.New(defaultEthereumSettings), + chainlink.New(0, defaultAutomationSettings), + chaos.NewFailPods, + &chaos.Props{ + LabelsSelector: &map[string]*string{ChaosGroupMinority: a.Str("1")}, + DurationStr: "1m", + }, + }, + PodChaosFailMajorityNodes: { + ethereum.New(defaultEthereumSettings), + chainlink.New(0, defaultAutomationSettings), + chaos.NewFailPods, + &chaos.Props{ + LabelsSelector: &map[string]*string{ChaosGroupMajority: a.Str("1")}, + DurationStr: "1m", + }, + }, + PodChaosFailMajorityDB: { + ethereum.New(defaultEthereumSettings), + chainlink.New(0, defaultAutomationSettings), + chaos.NewFailPods, + &chaos.Props{ + LabelsSelector: &map[string]*string{ChaosGroupMajority: a.Str("1")}, + DurationStr: "1m", + ContainerNames: &[]*string{a.Str("chainlink-db")}, + }, + }, + NetworkChaosFailMajorityNetwork: { + ethereum.New(defaultEthereumSettings), + chainlink.New(0, defaultAutomationSettings), + chaos.NewNetworkPartition, + &chaos.Props{ + FromLabels: &map[string]*string{ChaosGroupMajority: a.Str("1")}, + ToLabels: &map[string]*string{ChaosGroupMinority: a.Str("1")}, + DurationStr: "1m", + }, + }, + NetworkChaosFailBlockchainNode: { + ethereum.New(defaultEthereumSettings), + chainlink.New(0, defaultAutomationSettings), + chaos.NewNetworkPartition, + &chaos.Props{ + FromLabels: &map[string]*string{"app": a.Str("geth")}, + ToLabels: &map[string]*string{ChaosGroupMajorityPlus: a.Str("1")}, + DurationStr: "1m", + }, + }, + } + + for n, tst := range testCases { + name := n + testCase := tst + t.Run(fmt.Sprintf("Automation_%s", name), func(t *testing.T) { + t.Parallel() + network := networks.SelectedNetwork // Need a new copy of the network for each test + + testEnvironment := environment. + New(&environment.Config{ + NamespacePrefix: fmt.Sprintf("chaos-automation-%s", name), + TTL: time.Hour * 1, + Test: t, + }). + AddHelm(testCase.networkChart). + AddHelm(testCase.clChart). + AddChart(blockscout.New(&blockscout.Props{ + Name: "geth-blockscout", + WsURL: network.URL, + HttpURL: network.HTTPURLs[0], + })) + err := testEnvironment.Run() + require.NoError(t, err, "Error setting up test environment") + if testEnvironment.WillUseRemoteRunner() { + return + } + + err = testEnvironment.Client.LabelChaosGroup(testEnvironment.Cfg.Namespace, "instance=node-", 1, 2, ChaosGroupMinority) + require.NoError(t, err) + err = testEnvironment.Client.LabelChaosGroup(testEnvironment.Cfg.Namespace, "instance=node-", 3, 5, ChaosGroupMajority) + require.NoError(t, err) + err = testEnvironment.Client.LabelChaosGroup(testEnvironment.Cfg.Namespace, "instance=node-", 2, 5, ChaosGroupMajorityPlus) + require.NoError(t, err) + + chainClient, err := blockchain.NewEVMClient(network, testEnvironment, l) + require.NoError(t, err, "Error connecting to blockchain") + contractDeployer, err := contracts.NewContractDeployer(chainClient, l) + require.NoError(t, err, "Error building contract deployer") + + chainlinkNodes, err := client.ConnectChainlinkNodes(testEnvironment) + require.NoError(t, err, "Error connecting to Chainlink nodes") + chainClient.ParallelTransactions(true) + + // Register cleanup for any test + t.Cleanup(func() { + if chainClient != nil { + chainClient.GasStats().PrintStats() + } + err := actions.TeardownSuite(t, testEnvironment, utils.ProjectRoot, chainlinkNodes, nil, zapcore.PanicLevel, chainClient) + require.NoError(t, err, "Error tearing down environment") + }) + + txCost, err := chainClient.EstimateCostForChainlinkOperations(1000) + require.NoError(t, err, "Error estimating cost for Chainlink Operations") + err = actions.FundChainlinkNodes(chainlinkNodes, chainClient, txCost) + require.NoError(t, err, "Error funding Chainlink nodes") + + linkToken, err := contractDeployer.DeployLinkTokenContract() + require.NoError(t, err, "Error deploying LINK token") + + registry, registrar := actions.DeployAutoOCRRegistryAndRegistrar( + t, + registryVersion, + defaultOCRRegistryConfig, + linkToken, + contractDeployer, + chainClient, + ) + + // Fund the registry with LINK + err = linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(numberOfUpkeeps)))) + require.NoError(t, err, "Funding keeper registry contract shouldn't fail") + + actions.CreateOCRKeeperJobs(t, chainlinkNodes, registry.Address(), network.ChainID, 0, registryVersion) + nodesWithoutBootstrap := chainlinkNodes[1:] + ocrConfig, err := actions.BuildAutoOCR2ConfigVars(t, nodesWithoutBootstrap, defaultOCRRegistryConfig, registrar.Address(), 30*time.Second) + require.NoError(t, err, "Error building OCR config vars") + err = registry.SetConfig(defaultOCRRegistryConfig, ocrConfig) + require.NoError(t, err, "Registry config should be be set successfully") + require.NoError(t, chainClient.WaitForEvents(), "Waiting for config to be set") + + consumers_conditional, upkeepIDs_conditional := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, numberOfUpkeeps, big.NewInt(defaultLinkFunds), defaultUpkeepGasLimit, false, false) + consumers_logtrigger, upkeepIDs_logtrigger := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, numberOfUpkeeps, big.NewInt(defaultLinkFunds), defaultUpkeepGasLimit, true, false) + + consumers := append(consumers_conditional, consumers_logtrigger...) + upkeepIDs := append(upkeepIDs_conditional, upkeepIDs_logtrigger...) + + l.Info().Msg("Waiting for all upkeeps to be performed") + + gom := gomega.NewGomegaWithT(t) + gom.Eventually(func(g gomega.Gomega) { + // Check if the upkeeps are performing multiple times by analyzing their counters and checking they are greater than 10 + for i := 0; i < len(upkeepIDs); i++ { + counter, err := consumers[i].Counter(context.Background()) + require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i) + expect := 5 + l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep ID", i).Msg("Number of upkeeps performed") + g.Expect(counter.Int64()).Should(gomega.BeNumerically(">=", int64(expect)), + "Expected consumer counter to be greater than %d, but got %d", expect, counter.Int64()) + } + }, "5m", "1s").Should(gomega.Succeed()) // ~1m for cluster setup, ~2m for performing each upkeep 5 times, ~2m buffer + + _, err = testEnvironment.Chaos.Run(testCase.chaosFunc(testEnvironment.Cfg.Namespace, testCase.chaosProps)) + require.NoError(t, err) + + gom.Eventually(func(g gomega.Gomega) { + // Check if the upkeeps are performing multiple times by analyzing their counters and checking they are greater than 10 + for i := 0; i < len(upkeepIDs); i++ { + counter, err := consumers[i].Counter(context.Background()) + require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i) + expect := 10 + l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep ID", i).Msg("Number of upkeeps performed") + g.Expect(counter.Int64()).Should(gomega.BeNumerically(">=", int64(expect)), + "Expected consumer counter to be greater than %d, but got %d", expect, counter.Int64()) + } + }, "3m", "1s").Should(gomega.Succeed()) // ~1m for cluster setup, ~2m for performing each upkeep 5 times, ~2m buffer + }) } - err = testEnvironment.Client.LabelChaosGroup(testEnvironment.Cfg.Namespace, "instance=node-", 1, 2, ChaosGroupMinority) - require.NoError(t, err) - err = testEnvironment.Client.LabelChaosGroup(testEnvironment.Cfg.Namespace, "instance=node-", 3, 5, ChaosGroupMajority) - require.NoError(t, err) - err = testEnvironment.Client.LabelChaosGroup(testEnvironment.Cfg.Namespace, "instance=node-", 2, 5, ChaosGroupMajorityPlus) - require.NoError(t, err) - - chainClient, err := blockchain.NewEVMClient(network, testEnvironment, l) - require.NoError(t, err, "Error connecting to blockchain") - contractDeployer, err := contracts.NewContractDeployer(chainClient, l) - require.NoError(t, err, "Error building contract deployer") - - chainlinkNodes, err := client.ConnectChainlinkNodes(testEnvironment) - require.NoError(t, err, "Error connecting to Chainlink nodes") - chainClient.ParallelTransactions(true) - - // Register cleanup for any test - t.Cleanup(func() { - if chainClient != nil { - chainClient.GasStats().PrintStats() - } - err := actions.TeardownSuite(t, testEnvironment, utils.ProjectRoot, chainlinkNodes, nil, zapcore.PanicLevel, chainClient) - require.NoError(t, err, "Error tearing down environment") - }) - - txCost, err := chainClient.EstimateCostForChainlinkOperations(1000) - require.NoError(t, err, "Error estimating cost for Chainlink Operations") - err = actions.FundChainlinkNodes(chainlinkNodes, chainClient, txCost) - require.NoError(t, err, "Error funding Chainlink nodes") - - linkToken, err := contractDeployer.DeployLinkTokenContract() - require.NoError(t, err, "Error deploying LINK token") - - registry, registrar := actions.DeployAutoOCRRegistryAndRegistrar( - t, - eth_contracts.RegistryVersion_2_0, - defaultOCRRegistryConfig, - linkToken, - contractDeployer, - chainClient, - ) - - // Fund the registry with LINK - err = linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(numberOfUpkeeps)))) - require.NoError(t, err, "Funding keeper registry contract shouldn't fail") - - actions.CreateOCRKeeperJobs(t, chainlinkNodes, registry.Address(), network.ChainID, 0, eth_contracts.RegistryVersion_2_0) - nodesWithoutBootstrap := chainlinkNodes[1:] - ocrConfig, err := actions.BuildAutoOCR2ConfigVars(t, nodesWithoutBootstrap, defaultOCRRegistryConfig, registrar.Address(), 30*time.Second) - require.NoError(t, err, "Error building OCR config vars") - err = registry.SetConfig(defaultOCRRegistryConfig, ocrConfig) - require.NoError(t, err, "Registry config should be be set successfully") - require.NoError(t, chainClient.WaitForEvents(), "Waiting for config to be set") - - consumers, upkeepIDs := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, numberOfUpkeeps, big.NewInt(defaultLinkFunds), defaultUpkeepGasLimit, false) - - l.Info().Msg("Waiting for all upkeeps to be performed") - - gom := gomega.NewGomegaWithT(t) - gom.Eventually(func(g gomega.Gomega) { - // Check if the upkeeps are performing multiple times by analyzing their counters and checking they are greater than 10 - for i := 0; i < len(upkeepIDs); i++ { - counter, err := consumers[i].Counter(context.Background()) - require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i) - expect := 5 - l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep ID", i).Msg("Number of upkeeps performed") - g.Expect(counter.Int64()).Should(gomega.BeNumerically(">=", int64(expect)), - "Expected consumer counter to be greater than %d, but got %d", expect, counter.Int64()) - } - }, "5m", "1s").Should(gomega.Succeed()) // ~1m for cluster setup, ~2m for performing each upkeep 5 times, ~2m buffer - - _, err = testEnvironment.Chaos.Run(testCase.chaosFunc(testEnvironment.Cfg.Namespace, testCase.chaosProps)) - require.NoError(t, err) - - gom.Eventually(func(g gomega.Gomega) { - // Check if the upkeeps are performing multiple times by analyzing their counters and checking they are greater than 10 - for i := 0; i < len(upkeepIDs); i++ { - counter, err := consumers[i].Counter(context.Background()) - require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i) - expect := 10 - l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep ID", i).Msg("Number of upkeeps performed") - g.Expect(counter.Int64()).Should(gomega.BeNumerically(">=", int64(expect)), - "Expected consumer counter to be greater than %d, but got %d", expect, counter.Int64()) - } - }, "3m", "1s").Should(gomega.Succeed()) // ~1m for cluster setup, ~2m for performing each upkeep 5 times, ~2m buffer }) } } diff --git a/integration-tests/client/chainlink.go b/integration-tests/client/chainlink.go index 51c7d5e13f..8a79cb3ec9 100644 --- a/integration-tests/client/chainlink.go +++ b/integration-tests/client/chainlink.go @@ -5,11 +5,12 @@ import ( "fmt" "math/big" "net/http" - "os" "strings" "sync" "time" + "os" + "github.com/ethereum/go-ethereum/common" "github.com/go-resty/resty/v2" "github.com/rs/zerolog" @@ -92,14 +93,6 @@ func (c *ChainlinkClient) URL() string { return c.Config.URL } -func (c *ChainlinkClient) SetLogger(l zerolog.Logger) { - c.l = l -} - -func (c *ChainlinkClient) AddRetryAttempt(retryCount int) { - c.APIClient.RetryCount = retryCount -} - // CreateJobRaw creates a Chainlink job based on the provided spec string func (c *ChainlinkClient) CreateJobRaw(spec string) (*Job, *http.Response, error) { job := &Job{} diff --git a/integration-tests/contracts/contract_deployer.go b/integration-tests/contracts/contract_deployer.go index e92b3870fa..5444464566 100644 --- a/integration-tests/contracts/contract_deployer.go +++ b/integration-tests/contracts/contract_deployer.go @@ -11,12 +11,8 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator" - "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" - ocrConfigHelper "github.com/smartcontractkit/libocr/offchainreporting/confighelper" - eth_contracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" + "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_load_test_client" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_v1_events_mock" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_consumer_benchmark" @@ -49,6 +45,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_gas_aggregator_wrapper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_factory" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/oracle_wrapper" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/streams_lookup_upkeep_wrapper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/test_api_consumer_wrapper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/upkeep_transcoder" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/fee_manager" @@ -56,6 +53,11 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier_proxy" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/werc20_mock" + "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator" + "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" + ocrConfigHelper "github.com/smartcontractkit/libocr/offchainreporting/confighelper" + + eth_contracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" ) // ContractDeployer is an interface for abstracting the contract deployment methods across network implementations @@ -81,6 +83,7 @@ type ContractDeployer interface { LoadKeeperRegistry(address common.Address, registryVersion eth_contracts.KeeperRegistryVersion) (KeeperRegistry, error) DeployKeeperConsumer(updateInterval *big.Int) (KeeperConsumer, error) DeployAutomationLogTriggerConsumer(testInterval *big.Int) (KeeperConsumer, error) + DeployAutomationStreamsLookupUpkeepConsumer(testRange *big.Int, interval *big.Int, useArbBlock bool, staging bool, verify bool) (KeeperConsumer, error) DeployKeeperConsumerPerformance( testBlockRange, averageCadence, @@ -154,6 +157,8 @@ func NewContractDeployer(bcClient blockchain.EVMClient, logger zerolog.Logger) ( return &BSCContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil case *blockchain.ScrollClient: return &ScrollContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil + case *blockchain.PolygonZkEvmClient: + return &PolygonZkEvmContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil } return nil, errors.New("unknown blockchain client implementation for contract deployer, register blockchain client in NewContractDeployer") } @@ -209,6 +214,10 @@ type ScrollContractDeployer struct { *EthereumContractDeployer } +type PolygonZkEvmContractDeployer struct { + *EthereumContractDeployer +} + // NewEthereumContractDeployer returns an instantiated instance of the ETH contract deployer func NewEthereumContractDeployer(ethClient blockchain.EVMClient, logger zerolog.Logger) *EthereumContractDeployer { return &EthereumContractDeployer{ @@ -1239,6 +1248,25 @@ func (e *EthereumContractDeployer) DeployAutomationLogTriggerConsumer(testInterv }, err } +func (e *EthereumContractDeployer) DeployAutomationStreamsLookupUpkeepConsumer(testRange *big.Int, interval *big.Int, useArbBlock bool, staging bool, verify bool) (KeeperConsumer, error) { + address, _, instance, err := e.client.DeployContract("StreamsLookupUpkeep", func( + auth *bind.TransactOpts, + backend bind.ContractBackend, + ) (common.Address, *types.Transaction, interface{}, error) { + return streams_lookup_upkeep_wrapper.DeployStreamsLookupUpkeep( + auth, backend, testRange, interval, useArbBlock, staging, verify, + ) + }) + if err != nil { + return nil, err + } + return &EthereumAutomationStreamsLookupUpkeepConsumer{ + client: e.client, + consumer: instance.(*streams_lookup_upkeep_wrapper.StreamsLookupUpkeep), + address: address, + }, err +} + func (e *EthereumContractDeployer) DeployUpkeepCounter(testRange *big.Int, interval *big.Int) (UpkeepCounter, error) { address, _, instance, err := e.client.DeployContract("UpkeepCounter", func( auth *bind.TransactOpts, diff --git a/integration-tests/contracts/contract_loader.go b/integration-tests/contracts/contract_loader.go index fc0272b107..4dda2d3f0c 100644 --- a/integration-tests/contracts/contract_loader.go +++ b/integration-tests/contracts/contract_loader.go @@ -2,6 +2,8 @@ package contracts import ( "errors" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2_5" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_load_test_with_metrics" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -39,6 +41,10 @@ type ContractLoader interface { LoadMercuryRewardManager(addr common.Address) (MercuryRewardManager, error) LoadWERC20Mock(addr common.Address) (WERC20Mock, error) + + // VRF + LoadVRFCoordinatorV2_5(addr string) (VRFCoordinatorV2_5, error) + LoadVRFv2PlusLoadTestConsumer(addr string) (VRFv2PlusLoadTestConsumer, error) } // NewContractLoader returns an instance of a contract Loader based on the client type @@ -56,6 +62,8 @@ func NewContractLoader(bcClient blockchain.EVMClient, logger zerolog.Logger) (Co return &PolygonContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil case *blockchain.OptimismClient: return &OptimismContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil + case *blockchain.PolygonZkEvmClient: + return &PolygonZkEvmContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil } return nil, errors.New("unknown blockchain client implementation for contract Loader, register blockchain client in NewContractLoader") } @@ -90,6 +98,14 @@ type PolygonContractLoader struct { type OptimismContractLoader struct { *EthereumContractLoader } +type PolygonZkEvmContractLoader struct { + *EthereumContractLoader +} + +// PolygonZKEVMContractLoader wraps for Polygon zkEVM +type PolygonZKEVMContractLoader struct { + *EthereumContractLoader +} // NewEthereumContractLoader returns an instantiated instance of the ETH contract Loader func NewEthereumContractLoader(ethClient blockchain.EVMClient, logger zerolog.Logger) *EthereumContractLoader { @@ -296,3 +312,39 @@ func (e *EthereumContractLoader) LoadWERC20Mock(addr common.Address) (WERC20Mock address: addr, }, err } + +func (e *EthereumContractLoader) LoadVRFCoordinatorV2_5(addr string) (VRFCoordinatorV2_5, error) { + address := common.HexToAddress(addr) + instance, err := e.client.LoadContract("VRFCoordinatorV2_5", address, func( + address common.Address, + backend bind.ContractBackend, + ) (interface{}, error) { + return vrf_coordinator_v2_5.NewVRFCoordinatorV25(address, backend) + }) + if err != nil { + return nil, err + } + return &EthereumVRFCoordinatorV2_5{ + address: &address, + client: e.client, + coordinator: instance.(*vrf_coordinator_v2_5.VRFCoordinatorV25), + }, err +} + +func (e *EthereumContractLoader) LoadVRFv2PlusLoadTestConsumer(addr string) (VRFv2PlusLoadTestConsumer, error) { + address := common.HexToAddress(addr) + instance, err := e.client.LoadContract("VRFV2PlusLoadTestWithMetrics", address, func( + address common.Address, + backend bind.ContractBackend, + ) (interface{}, error) { + return vrf_v2plus_load_test_with_metrics.NewVRFV2PlusLoadTestWithMetrics(address, backend) + }) + if err != nil { + return nil, err + } + return &EthereumVRFv2PlusLoadTestConsumer{ + client: e.client, + consumer: instance.(*vrf_v2plus_load_test_with_metrics.VRFV2PlusLoadTestWithMetrics), + address: &address, + }, err +} diff --git a/integration-tests/contracts/contract_vrf_models.go b/integration-tests/contracts/contract_vrf_models.go index 2b623469aa..ed46b08dbb 100644 --- a/integration-tests/contracts/contract_vrf_models.go +++ b/integration-tests/contracts/contract_vrf_models.go @@ -2,20 +2,18 @@ package contracts import ( "context" - "math/big" "time" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2_5" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_load_test_with_metrics" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_upgraded_version" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2plus_wrapper_load_test_consumer" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2_5" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_load_test_with_metrics" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_load_test_with_metrics" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_upgraded_version" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2plus_wrapper_load_test_consumer" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/dkg" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon" ) @@ -172,6 +170,7 @@ type VRFv2PlusLoadTestConsumer interface { GetLastRequestId(ctx context.Context) (*big.Int, error) GetLoadTestMetrics(ctx context.Context) (*VRFLoadTestMetrics, error) GetCoordinator(ctx context.Context) (common.Address, error) + ResetMetrics() error } type VRFv2PlusWrapperLoadTestConsumer interface { diff --git a/integration-tests/contracts/ethereum_contracts.go b/integration-tests/contracts/ethereum_contracts.go index fdeccfedad..5b3a93fe0c 100644 --- a/integration-tests/contracts/ethereum_contracts.go +++ b/integration-tests/contracts/ethereum_contracts.go @@ -5,27 +5,19 @@ import ( "encoding/hex" "fmt" "math/big" + "strings" "time" "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator" - "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" - ocrConfigHelper "github.com/smartcontractkit/libocr/offchainreporting/confighelper" - ocrTypes "github.com/smartcontractkit/libocr/offchainreporting/types" - "strings" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/pkg/errors" - - "github.com/smartcontractkit/chainlink/integration-tests/client" - eth_contracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" + "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_coordinator" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_load_test_client" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_router" @@ -52,6 +44,13 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier_proxy" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/werc20_mock" + "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator" + "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" + ocrConfigHelper "github.com/smartcontractkit/libocr/offchainreporting/confighelper" + ocrTypes "github.com/smartcontractkit/libocr/offchainreporting/types" + + "github.com/smartcontractkit/chainlink/integration-tests/client" + eth_contracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" ) // EthereumOracle oracle for "directrequest" job tests @@ -66,7 +65,9 @@ func (e *EthereumOracle) Address() string { } func (e *EthereumOracle) Fund(ethAmount *big.Float) error { - gasEstimates, err := e.client.EstimateGas(ethereum.CallMsg{}) + gasEstimates, err := e.client.EstimateGas(ethereum.CallMsg{ + To: e.address, + }) if err != nil { return err } @@ -106,7 +107,9 @@ func (e *EthereumAPIConsumer) RoundID(ctx context.Context) (*big.Int, error) { } func (e *EthereumAPIConsumer) Fund(ethAmount *big.Float) error { - gasEstimates, err := e.client.EstimateGas(ethereum.CallMsg{}) + gasEstimates, err := e.client.EstimateGas(ethereum.CallMsg{ + To: e.address, + }) if err != nil { return err } @@ -158,7 +161,9 @@ func (f *EthereumStaking) Address() string { // Fund sends specified currencies to the contract func (f *EthereumStaking) Fund(ethAmount *big.Float) error { - gasEstimates, err := f.client.EstimateGas(ethereum.CallMsg{}) + gasEstimates, err := f.client.EstimateGas(ethereum.CallMsg{ + To: f.address, + }) if err != nil { return err } @@ -902,7 +907,9 @@ func (f *EthereumFluxAggregator) Address() string { // Fund sends specified currencies to the contract func (f *EthereumFluxAggregator) Fund(ethAmount *big.Float) error { - gasEstimates, err := f.client.EstimateGas(ethereum.CallMsg{}) + gasEstimates, err := f.client.EstimateGas(ethereum.CallMsg{ + To: f.address, + }) if err != nil { return err } @@ -1193,7 +1200,9 @@ type EthereumLinkToken struct { // Fund the LINK Token contract with ETH to distribute the token func (l *EthereumLinkToken) Fund(ethAmount *big.Float) error { - gasEstimates, err := l.client.EstimateGas(ethereum.CallMsg{}) + gasEstimates, err := l.client.EstimateGas(ethereum.CallMsg{ + To: &l.address, + }) if err != nil { return err } @@ -1290,7 +1299,9 @@ type EthereumOffchainAggregator struct { // Fund sends specified currencies to the contract func (o *EthereumOffchainAggregator) Fund(ethAmount *big.Float) error { - gasEstimates, err := o.client.EstimateGas(ethereum.CallMsg{}) + gasEstimates, err := o.client.EstimateGas(ethereum.CallMsg{ + To: o.address, + }) if err != nil { return err } @@ -1960,7 +1971,9 @@ func (e *EthereumOffchainAggregatorV2) Address() string { } func (e *EthereumOffchainAggregatorV2) Fund(nativeAmount *big.Float) error { - gasEstimates, err := e.client.EstimateGas(ethereum.CallMsg{}) + gasEstimates, err := e.client.EstimateGas(ethereum.CallMsg{ + To: e.address, + }) if err != nil { return err } @@ -2238,10 +2251,7 @@ func (e *EthereumFunctionsLoadTestClient) ResetStats() error { if err != nil { return err } - if err := e.client.ProcessTransaction(tx); err != nil { - return err - } - return nil + return e.client.ProcessTransaction(tx) } func (e *EthereumFunctionsLoadTestClient) SendRequest(times uint32, source string, encryptedSecretsReferences []byte, args []string, subscriptionId uint64, jobId [32]byte) error { @@ -2433,66 +2443,66 @@ func (e *EthereumWERC20Mock) Address() common.Address { return e.address } -func (l *EthereumWERC20Mock) Approve(to string, amount *big.Int) error { - opts, err := l.client.TransactionOpts(l.client.GetDefaultWallet()) +func (e *EthereumWERC20Mock) Approve(to string, amount *big.Int) error { + opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) if err != nil { return err } - l.l.Info(). - Str("From", l.client.GetDefaultWallet().Address()). + e.l.Info(). + Str("From", e.client.GetDefaultWallet().Address()). Str("To", to). Str("Amount", amount.String()). Uint64("Nonce", opts.Nonce.Uint64()). Msg("Approving LINK Transfer") - tx, err := l.instance.Approve(opts, common.HexToAddress(to), amount) + tx, err := e.instance.Approve(opts, common.HexToAddress(to), amount) if err != nil { return err } - return l.client.ProcessTransaction(tx) + return e.client.ProcessTransaction(tx) } -func (l *EthereumWERC20Mock) BalanceOf(ctx context.Context, addr string) (*big.Int, error) { +func (e *EthereumWERC20Mock) BalanceOf(ctx context.Context, addr string) (*big.Int, error) { opts := &bind.CallOpts{ - From: common.HexToAddress(l.client.GetDefaultWallet().Address()), + From: common.HexToAddress(e.client.GetDefaultWallet().Address()), Context: ctx, } - balance, err := l.instance.BalanceOf(opts, common.HexToAddress(addr)) + balance, err := e.instance.BalanceOf(opts, common.HexToAddress(addr)) if err != nil { return nil, err } return balance, nil } -func (l *EthereumWERC20Mock) Transfer(to string, amount *big.Int) error { - opts, err := l.client.TransactionOpts(l.client.GetDefaultWallet()) +func (e *EthereumWERC20Mock) Transfer(to string, amount *big.Int) error { + opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) if err != nil { return err } - l.l.Info(). - Str("From", l.client.GetDefaultWallet().Address()). + e.l.Info(). + Str("From", e.client.GetDefaultWallet().Address()). Str("To", to). Str("Amount", amount.String()). Uint64("Nonce", opts.Nonce.Uint64()). Msg("EthereumWERC20Mock.Transfer()") - tx, err := l.instance.Transfer(opts, common.HexToAddress(to), amount) + tx, err := e.instance.Transfer(opts, common.HexToAddress(to), amount) if err != nil { return err } - return l.client.ProcessTransaction(tx) + return e.client.ProcessTransaction(tx) } -func (l *EthereumWERC20Mock) Mint(account common.Address, amount *big.Int) (*types.Transaction, error) { - opts, err := l.client.TransactionOpts(l.client.GetDefaultWallet()) +func (e *EthereumWERC20Mock) Mint(account common.Address, amount *big.Int) (*types.Transaction, error) { + opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) if err != nil { return nil, err } - l.l.Info(). + e.l.Info(). Str("account", account.Hex()). Str("amount", amount.String()). Msg("EthereumWERC20Mock.Mint()") - tx, err := l.instance.Mint(opts, account, amount) + tx, err := e.instance.Mint(opts, account, amount) if err != nil { return tx, err } - return tx, l.client.ProcessTransaction(tx) + return tx, e.client.ProcessTransaction(tx) } diff --git a/integration-tests/contracts/ethereum_contracts_local.go b/integration-tests/contracts/ethereum_contracts_local.go index aba6bc354e..316658a791 100644 --- a/integration-tests/contracts/ethereum_contracts_local.go +++ b/integration-tests/contracts/ethereum_contracts_local.go @@ -3,11 +3,13 @@ package contracts import ( "encoding/hex" "fmt" + "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/chainlink/integration-tests/client" ocrConfigHelper "github.com/smartcontractkit/libocr/offchainreporting/confighelper" ocrTypes "github.com/smartcontractkit/libocr/offchainreporting/types" + + "github.com/smartcontractkit/chainlink/integration-tests/client" ) // SetConfigLocal sets the payees and the offchain reporting protocol configuration diff --git a/integration-tests/contracts/ethereum_keeper_contracts.go b/integration-tests/contracts/ethereum_keeper_contracts.go index afb6550bd2..246fd0e914 100644 --- a/integration-tests/contracts/ethereum_keeper_contracts.go +++ b/integration-tests/contracts/ethereum_keeper_contracts.go @@ -11,14 +11,14 @@ import ( geth "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/rs/zerolog" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" goabi "github.com/umbracle/ethgo/abi" + "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + cltypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_consumer_benchmark" registrar21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registrar_wrapper2_1" @@ -32,6 +32,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper2_0" registry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper_2_1" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_upkeep_counter_wrapper" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/streams_lookup_upkeep_wrapper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/upkeep_transcoder" "github.com/smartcontractkit/chainlink/v2/core/utils" @@ -77,6 +78,8 @@ type KeeperRegistry interface { UnpauseUpkeep(id *big.Int) error UpdateCheckData(id *big.Int, newCheckData []byte) error SetUpkeepTriggerConfig(id *big.Int, triggerConfig []byte) error + SetUpkeepPrivilegeConfig(id *big.Int, privilegeConfig []byte) error + RegistryOwnerAddress() common.Address } type KeeperConsumer interface { @@ -219,7 +222,7 @@ func (v *EthereumKeeperRegistry) Fund(ethAmount *big.Float) error { return v.client.Fund(v.address.Hex(), ethAmount, gasEstimates) } -func (rcs *KeeperRegistrySettings) EncodeOnChainConfig(registrar string) ([]byte, error) { +func (rcs *KeeperRegistrySettings) EncodeOnChainConfig(registrar string, registryOwnerAddress common.Address) ([]byte, error) { if rcs.RegistryVersion == ethereum.RegistryVersion_2_1 { onchainConfigStruct := registry21.KeeperRegistryBase21OnchainConfig{ PaymentPremiumPPB: rcs.PaymentPremiumPPB, @@ -236,8 +239,9 @@ func (rcs *KeeperRegistrySettings) EncodeOnChainConfig(registrar string) ([]byte FallbackLinkPrice: rcs.FallbackLinkPrice, Transcoder: common.Address{}, Registrars: []common.Address{common.HexToAddress(registrar)}, - UpkeepPrivilegeManager: common.Address{}, + UpkeepPrivilegeManager: registryOwnerAddress, } + encodedOnchainConfig, err := utilsABI.Methods["_onChainConfig"].Inputs.Pack(&onchainConfigStruct) return encodedOnchainConfig, err @@ -262,6 +266,23 @@ func (rcs *KeeperRegistrySettings) EncodeOnChainConfig(registrar string) ([]byte } } +func (v *EthereumKeeperRegistry) RegistryOwnerAddress() common.Address { + callOpts := &bind.CallOpts{ + Pending: false, + } + + switch v.version { + case ethereum.RegistryVersion_2_1: + ownerAddress, _ := v.registry2_1.Owner(callOpts) + return ownerAddress + case ethereum.RegistryVersion_2_0: + ownerAddress, _ := v.registry2_0.Owner(callOpts) + return ownerAddress + } + + return common.HexToAddress(v.client.GetDefaultWallet().Address()) +} + func (v *EthereumKeeperRegistry) SetConfig(config KeeperRegistrySettings, ocrConfig OCRv2Config) error { txOpts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) if err != nil { @@ -925,6 +946,26 @@ func (v *EthereumKeeperRegistry) SetUpkeepTriggerConfig(id *big.Int, triggerConf } } +// SetUpkeepPrivilegeConfig sets the privilege config of an upkeep (only for version 2.1) +func (v *EthereumKeeperRegistry) SetUpkeepPrivilegeConfig(id *big.Int, privilegeConfig []byte) error { + + switch v.version { + case ethereum.RegistryVersion_2_1: + opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) + if err != nil { + return err + } + + tx, err := v.registry2_1.SetUpkeepPrivilegeConfig(opts, id, privilegeConfig) + if err != nil { + return err + } + return v.client.ProcessTransaction(tx) + default: + return fmt.Errorf("SetUpkeepPrivilegeConfig is not supported by keeper registry version %d", v.version) + } +} + // PauseUpkeep stops an upkeep from an upkeep func (v *EthereumKeeperRegistry) PauseUpkeep(id *big.Int) error { switch v.version { @@ -1356,13 +1397,13 @@ type KeeperConsumerBenchmarkRoundConfirmer struct { context context.Context cancel context.CancelFunc - firstBlockNum uint64 // Records the number of the first block that came in - lastBlockNum uint64 // Records the number of the last block that came in - blockRange int64 // How many blocks to watch upkeeps for - upkeepSLA int64 // SLA after which an upkeep is counted as 'missed' - metricsReporter *testreporters.KeeperBenchmarkTestReporter // Testreporter to track results - upkeepIndex int64 - firstEligibleuffer int64 + firstBlockNum uint64 // Records the number of the first block that came in + lastBlockNum uint64 // Records the number of the last block that came in + blockRange int64 // How many blocks to watch upkeeps for + upkeepSLA int64 // SLA after which an upkeep is counted as 'missed' + metricsReporter *testreporters.KeeperBenchmarkTestReporter // Testreporter to track results + upkeepIndex int64 + firstEligibleBuffer int64 // State variables, changes as we get blocks blocksSinceSubscription int64 // How many blocks have passed since subscribing @@ -1385,7 +1426,7 @@ func NewKeeperConsumerBenchmarkRoundConfirmer( upkeepSLA int64, metricsReporter *testreporters.KeeperBenchmarkTestReporter, upkeepIndex int64, - firstEligibleuffer int64, + firstEligibleBuffer int64, logger zerolog.Logger, ) *KeeperConsumerBenchmarkRoundConfirmer { ctx, cancelFunc := context.WithCancel(context.Background()) @@ -1407,7 +1448,7 @@ func NewKeeperConsumerBenchmarkRoundConfirmer( lastBlockNum: 0, upkeepIndex: upkeepIndex, firstBlockNum: 0, - firstEligibleuffer: firstEligibleuffer, + firstEligibleBuffer: firstEligibleBuffer, l: logger, } } @@ -1458,7 +1499,7 @@ func (o *KeeperConsumerBenchmarkRoundConfirmer) ReceiveHeader(receivedHeader blo o.blocksSinceEligible = 0 } - isEligible, err := o.instance.CheckEligible(context.Background(), big.NewInt(o.upkeepIndex), big.NewInt(o.blockRange), big.NewInt(o.firstEligibleuffer)) + isEligible, err := o.instance.CheckEligible(context.Background(), big.NewInt(o.upkeepIndex), big.NewInt(o.blockRange), big.NewInt(o.firstEligibleBuffer)) if err != nil { return err } @@ -1666,6 +1707,50 @@ func (v *EthereumKeeperConsumer) Counter(ctx context.Context) (*big.Int, error) return cnt, nil } +type EthereumAutomationStreamsLookupUpkeepConsumer struct { + client blockchain.EVMClient + consumer *streams_lookup_upkeep_wrapper.StreamsLookupUpkeep + address *common.Address +} + +func (v *EthereumAutomationStreamsLookupUpkeepConsumer) Address() string { + return v.address.Hex() +} + +func (v *EthereumAutomationStreamsLookupUpkeepConsumer) Start() error { + // For this consumer upkeep, we use this Start() function to set ParamKeys so as to run mercury v0.2 + txOpts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) + if err != nil { + return err + } + + tx, err := v.consumer.SetParamKeys(txOpts, "feedIdHex", "blockNumber") + if err != nil { + return err + } + return v.client.ProcessTransaction(tx) +} + +func (v *EthereumAutomationStreamsLookupUpkeepConsumer) Fund(ethAmount *big.Float) error { + gasEstimates, err := v.client.EstimateGas(geth.CallMsg{}) + if err != nil { + return err + } + return v.client.Fund(v.address.Hex(), ethAmount, gasEstimates) +} + +func (v *EthereumAutomationStreamsLookupUpkeepConsumer) Counter(ctx context.Context) (*big.Int, error) { + opts := &bind.CallOpts{ + From: common.HexToAddress(v.client.GetDefaultWallet().Address()), + Context: ctx, + } + cnt, err := v.consumer.Counter(opts) + if err != nil { + return nil, err + } + return cnt, nil +} + type EthereumAutomationLogCounterConsumer struct { client blockchain.EVMClient consumer *log_upkeep_counter_wrapper.LogUpkeepCounter diff --git a/integration-tests/contracts/ethereum_ocr2vrf_contracts.go b/integration-tests/contracts/ethereum_ocr2vrf_contracts.go index 11606de53e..e8149b2125 100644 --- a/integration-tests/contracts/ethereum_ocr2vrf_contracts.go +++ b/integration-tests/contracts/ethereum_ocr2vrf_contracts.go @@ -4,11 +4,15 @@ import ( "context" "encoding/hex" "fmt" + "math/big" + "time" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/pkg/errors" "github.com/rs/zerolog/log" + "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_blockhash_store" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_coordinator_interface" @@ -16,8 +20,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon_consumer" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_coordinator" - "math/big" - "time" ) // EthereumDKG represents DKG contract diff --git a/integration-tests/contracts/ethereum_vrf_contracts.go b/integration-tests/contracts/ethereum_vrf_contracts.go index f97ba86d97..427ac4ccbf 100644 --- a/integration-tests/contracts/ethereum_vrf_contracts.go +++ b/integration-tests/contracts/ethereum_vrf_contracts.go @@ -13,7 +13,6 @@ import ( "github.com/rs/zerolog/log" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_blockhash_store" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/blockhash_store" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_consumer_interface" @@ -175,7 +174,9 @@ func (v *EthereumVRFConsumer) Address() string { } func (v *EthereumVRFConsumer) Fund(ethAmount *big.Float) error { - gasEstimates, err := v.client.EstimateGas(ethereum.CallMsg{}) + gasEstimates, err := v.client.EstimateGas(ethereum.CallMsg{ + To: v.address, + }) if err != nil { return err } @@ -277,7 +278,9 @@ func (f *VRFConsumerRoundConfirmer) Wait() error { // Fund sends specified currencies to the contract func (v *EthereumVRF) Fund(ethAmount *big.Float) error { - gasEstimates, err := v.client.EstimateGas(ethereum.CallMsg{}) + gasEstimates, err := v.client.EstimateGas(ethereum.CallMsg{ + To: v.address, + }) if err != nil { return err } diff --git a/integration-tests/contracts/ethereum_vrfv2_contracts.go b/integration-tests/contracts/ethereum_vrfv2_contracts.go index 88dfe58eb2..1bcd460c39 100644 --- a/integration-tests/contracts/ethereum_vrfv2_contracts.go +++ b/integration-tests/contracts/ethereum_vrfv2_contracts.go @@ -3,17 +3,20 @@ package contracts import ( "context" "encoding/hex" + "math/big" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/rs/zerolog/log" + "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - eth_contracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_consumer_v2" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_load_test_with_metrics" - "math/big" + + eth_contracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" ) // EthereumVRFCoordinatorV2 represents VRFV2 coordinator contract @@ -286,7 +289,9 @@ func (v *EthereumVRFConsumerV2) GasAvailable() (*big.Int, error) { } func (v *EthereumVRFConsumerV2) Fund(ethAmount *big.Float) error { - gasEstimates, err := v.client.EstimateGas(ethereum.CallMsg{}) + gasEstimates, err := v.client.EstimateGas(ethereum.CallMsg{ + To: v.address, + }) if err != nil { return err } diff --git a/integration-tests/contracts/ethereum_vrfv2plus_contracts.go b/integration-tests/contracts/ethereum_vrfv2plus_contracts.go index 4ca5c0fec4..93baa6e745 100644 --- a/integration-tests/contracts/ethereum_vrfv2plus_contracts.go +++ b/integration-tests/contracts/ethereum_vrfv2plus_contracts.go @@ -10,7 +10,9 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2_5" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_load_test_with_metrics" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_upgraded_version" @@ -342,6 +344,18 @@ func (v *EthereumVRFv2PlusLoadTestConsumer) RequestRandomness(keyHash [32]byte, return tx, v.client.ProcessTransaction(tx) } +func (v *EthereumVRFv2PlusLoadTestConsumer) ResetMetrics() error { + opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) + if err != nil { + return err + } + tx, err := v.consumer.Reset(opts) + if err != nil { + return err + } + return v.client.ProcessTransaction(tx) +} + func (v *EthereumVRFv2PlusLoadTestConsumer) GetCoordinator(ctx context.Context) (common.Address, error) { return v.consumer.SVrfCoordinator(&bind.CallOpts{ From: common.HexToAddress(v.client.GetDefaultWallet().Address()), @@ -785,7 +799,9 @@ func (v *EthereumVRFV2PlusWrapper) GetSubID(ctx context.Context) (*big.Int, erro } func (v *EthereumVRFV2PlusWrapperLoadTestConsumer) Fund(ethAmount *big.Float) error { - gasEstimates, err := v.client.EstimateGas(ethereum.CallMsg{}) + gasEstimates, err := v.client.EstimateGas(ethereum.CallMsg{ + To: v.address, + }) if err != nil { return err } diff --git a/integration-tests/docker/cmd/test_env.go b/integration-tests/docker/cmd/test_env.go index 1acf594750..31b7de5dcd 100644 --- a/integration-tests/docker/cmd/test_env.go +++ b/integration-tests/docker/cmd/test_env.go @@ -36,7 +36,7 @@ func main() { _, err := test_env.NewCLTestEnvBuilder(). WithGeth(). - WithMockServer(1). + WithMockAdapter(). WithCLNodes(6). Build() if err != nil { diff --git a/integration-tests/docker/test_env/cl_node.go b/integration-tests/docker/test_env/cl_node.go index dbf9fdffaa..c9193d9095 100644 --- a/integration-tests/docker/test_env/cl_node.go +++ b/integration-tests/docker/test_env/cl_node.go @@ -16,7 +16,7 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" - "github.com/pelletier/go-toml" + "github.com/pelletier/go-toml/v2" "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/rs/zerolog/log" @@ -28,11 +28,10 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/logwatch" - ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2/types" - "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" - "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2/types" + "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/utils" @@ -46,15 +45,13 @@ var ( type ClNode struct { test_env.EnvComponent - API *client.ChainlinkClient - NodeConfig *chainlink.Config - NodeSecretsConfigTOML string - PostgresDb *test_env.PostgresDb - lw *logwatch.LogWatch - ContainerImage string - ContainerVersion string + API *client.ChainlinkClient `json:"-"` + NodeConfig *chainlink.Config `json:"-"` + NodeSecretsConfigTOML string `json:"-"` + PostgresDb *test_env.PostgresDb `json:"postgresDb"` t *testing.T l zerolog.Logger + lw *logwatch.LogWatch } type ClNodeOption = func(c *ClNode) @@ -108,11 +105,10 @@ func NewClNode(networks []string, nodeConfig *chainlink.Config, opts ...ClNodeOp return n } -func (n *ClNode) WithTestLogger(t *testing.T) *ClNode { +func (n *ClNode) SetTestLogger(t *testing.T) { n.l = logging.GetTestLogger(t) n.t = t n.PostgresDb.WithTestLogger(t) - return n } // Restart restarts only CL node, DB container is reused @@ -233,12 +229,16 @@ func (n *ClNode) Fund(evmClient blockchain.EVMClient, amount *big.Float) error { if err != nil { return err } - gasEstimates, err := evmClient.EstimateGas(ethereum.CallMsg{}) + toAddr := common.HexToAddress(toAddress) + gasEstimates, err := evmClient.EstimateGas(ethereum.CallMsg{ + To: &toAddr, + }) if err != nil { return err } return evmClient.Fund(toAddress, amount, gasEstimates) } + func (n *ClNode) StartContainer() error { err := n.PostgresDb.StartContainer() if err != nil { @@ -249,7 +249,7 @@ func (n *ClNode) StartContainer() error { nodeSecretsToml, err := templates.NodeSecretsTemplate{ PgDbName: n.PostgresDb.DbName, PgHost: n.PostgresDb.ContainerName, - PgPort: n.PostgresDb.Port, + PgPort: n.PostgresDb.InternalPort, PgPassword: n.PostgresDb.Password, CustomSecrets: n.NodeSecretsConfigTOML, }.String() @@ -272,7 +272,7 @@ func (n *ClNode) StartContainer() error { container, err := docker.StartContainerWithRetry(n.l, tc.GenericContainerRequest{ ContainerRequest: *cReq, Started: true, - Reuse: false, + Reuse: true, Logger: l, }) if err != nil { @@ -283,7 +283,7 @@ func (n *ClNode) StartContainer() error { return err } } - clEndpoint, err := container.Endpoint(context.Background(), "http") + clEndpoint, err := test_env.GetEndpoint(context.Background(), container, "http") if err != nil { return err } diff --git a/integration-tests/docker/test_env/cl_node_cluster.go b/integration-tests/docker/test_env/cl_node_cluster.go new file mode 100644 index 0000000000..5ae90bb982 --- /dev/null +++ b/integration-tests/docker/test_env/cl_node_cluster.go @@ -0,0 +1,69 @@ +package test_env + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + "golang.org/x/sync/errgroup" + + "github.com/smartcontractkit/chainlink/integration-tests/client" +) + +var ( + ErrGetNodeCSAKeys = "failed get CL node CSA keys" +) + +type ClCluster struct { + Nodes []*ClNode `json:"nodes"` +} + +// Start all nodes in the cluster./docker/tests/functional/api +func (c *ClCluster) Start() error { + eg := &errgroup.Group{} + nodes := c.Nodes + + for i := 0; i < len(nodes); i++ { + nodeIndex := i + eg.Go(func() error { + err := nodes[nodeIndex].StartContainer() + if err != nil { + return err + } + return nil + }) + } + + return eg.Wait() +} + +func (c *ClCluster) NodeAPIs() []*client.ChainlinkClient { + clients := make([]*client.ChainlinkClient, 0) + for _, c := range c.Nodes { + clients = append(clients, c.API) + } + return clients +} + +// Return all the on-chain wallet addresses for a set of Chainlink nodes +func (c *ClCluster) NodeAddresses() ([]common.Address, error) { + addresses := make([]common.Address, 0) + for _, n := range c.Nodes { + primaryAddress, err := n.ChainlinkNodeAddress() + if err != nil { + return nil, err + } + addresses = append(addresses, primaryAddress) + } + return addresses, nil +} + +func (c *ClCluster) NodeCSAKeys() ([]string, error) { + var keys []string + for _, n := range c.Nodes { + csaKeys, err := n.GetNodeCSAKeys() + if err != nil { + return nil, errors.Wrap(err, ErrGetNodeCSAKeys) + } + keys = append(keys, csaKeys.Data[0].ID) + } + return keys, nil +} diff --git a/integration-tests/docker/test_env/test_env.go b/integration-tests/docker/test_env/test_env.go index acf6d30021..9eb9ed9f39 100644 --- a/integration-tests/docker/test_env/test_env.go +++ b/integration-tests/docker/test_env/test_env.go @@ -12,7 +12,6 @@ import ( "time" "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/rs/zerolog/log" @@ -25,16 +24,14 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/logwatch" - "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/utils" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" ) var ( - ErrFundCLNode = "failed to fund CL node" - ErrGetNodeCSAKeys = "failed get CL node CSA keys" + ErrFundCLNode = "failed to fund CL node" ) type CLClusterTestEnv struct { @@ -43,10 +40,10 @@ type CLClusterTestEnv struct { LogWatch *logwatch.LogWatch /* components */ - CLNodes []*ClNode + ClCluster *ClCluster Geth *test_env.Geth // for tests using --dev networks PrivateChain []test_env.PrivateChain // for tests using non-dev networks - MockServer *test_env.MockServer + MockAdapter *test_env.Killgrave EVMClient blockchain.EVMClient ContractDeployer contracts.ContractDeployer ContractLoader contracts.ContractLoader @@ -62,20 +59,20 @@ func NewTestEnv() (*CLClusterTestEnv, error) { } n := []string{network.Name} return &CLClusterTestEnv{ - Geth: test_env.NewGeth(n), - MockServer: test_env.NewMockServer(n), - Network: network, - l: log.Logger, + Geth: test_env.NewGeth(n), + MockAdapter: test_env.NewKillgrave(n, ""), + Network: network, + l: log.Logger, }, nil } // WithTestEnvConfig sets the test environment cfg. -// Sets up the Geth and MockServer containers with the provided cfg. +// Sets up the Geth and MockAdapter containers with the provided cfg. func (te *CLClusterTestEnv) WithTestEnvConfig(cfg *TestEnvConfig) *CLClusterTestEnv { te.Cfg = cfg n := []string{te.Network.Name} - te.Geth = test_env.NewGeth(n, test_env.WithContainerName(cfg.Geth.ContainerName)) - te.MockServer = test_env.NewMockServer(n, test_env.WithContainerName(cfg.MockServer.ContainerName)) + te.Geth = test_env.NewGeth(n, test_env.WithContainerName(te.Cfg.Geth.ContainerName)) + te.MockAdapter = test_env.NewKillgrave(n, te.Cfg.MockAdapter.ImpostersPath, test_env.WithContainerName(te.Cfg.MockAdapter.ContainerName)) return te } @@ -83,7 +80,7 @@ func (te *CLClusterTestEnv) WithTestLogger(t *testing.T) *CLClusterTestEnv { te.t = t te.l = logging.GetTestLogger(t) te.Geth.WithTestLogger(t) - te.MockServer.WithTestLogger(t) + te.MockAdapter.WithTestLogger(t) return te } @@ -95,18 +92,17 @@ func (te *CLClusterTestEnv) WithPrivateChain(evmNetworks []blockchain.EVMNetwork var chains []test_env.PrivateChain for _, evmNetwork := range evmNetworks { n := evmNetwork + pgc := test_env.NewPrivateGethChain(&n, []string{te.Network.Name}) + if te.t != nil { + pgc.GetPrimaryNode().WithTestLogger(te.t) + } + chains = append(chains, pgc) var privateChain test_env.PrivateChain switch n.SimulationType { case "besu": privateChain = test_env.NewPrivateBesuChain(&n, []string{te.Network.Name}) - if te.t != nil { - privateChain.GetPrimaryNode().WithTestLogger(te.t) - } default: privateChain = test_env.NewPrivateGethChain(&n, []string{te.Network.Name}) - if te.t != nil { - privateChain.GetPrimaryNode().WithTestLogger(te.t) - } } chains = append(chains, privateChain) } @@ -136,77 +132,37 @@ func (te *CLClusterTestEnv) StartGeth() (blockchain.EVMNetwork, test_env.Interna return te.Geth.StartContainer() } -func (te *CLClusterTestEnv) StartMockServer() error { - return te.MockServer.StartContainer() +func (te *CLClusterTestEnv) StartMockAdapter() error { + return te.MockAdapter.StartContainer() } -func (te *CLClusterTestEnv) GetAPIs() []*client.ChainlinkClient { - clients := make([]*client.ChainlinkClient, 0) - for _, c := range te.CLNodes { - clients = append(clients, c.API) - } - return clients -} - -// StartClNodes start one bootstrap node and {count} OCR nodes -func (te *CLClusterTestEnv) StartClNodes(nodeConfig *chainlink.Config, count int, secretsConfig string) error { - eg := &errgroup.Group{} - nodes := make(chan *ClNode, count) - - // Start nodes - for i := 0; i < count; i++ { - nodeIndex := i - eg.Go(func() error { - var nodeContainerName, dbContainerName string - if te.Cfg != nil { - nodeContainerName = te.Cfg.Nodes[nodeIndex].NodeContainerName - dbContainerName = te.Cfg.Nodes[nodeIndex].DbContainerName - } - n := NewClNode([]string{te.Network.Name}, nodeConfig, +func (te *CLClusterTestEnv) StartClCluster(nodeConfig *chainlink.Config, count int, secretsConfig string) error { + if te.Cfg != nil && te.Cfg.ClCluster != nil { + te.ClCluster = te.Cfg.ClCluster + } else { + te.ClCluster = &ClCluster{} + for i := 0; i < count; i++ { + ocrNode := NewClNode([]string{te.Network.Name}, nodeConfig, WithSecrets(secretsConfig), - WithNodeContainerName(nodeContainerName), - WithDbContainerName(dbContainerName), ) - if te.t != nil { - n.WithTestLogger(te.t) - } - err := n.StartContainer() - if err != nil { - return err - } - nodes <- n - return nil - }) - } - - if err := eg.Wait(); err != nil { - return err - } - close(nodes) - - for node := range nodes { - te.CLNodes = append(te.CLNodes, node) + te.ClCluster.Nodes = append(te.ClCluster.Nodes, ocrNode) + } } - return nil -} - -// ChainlinkNodeAddresses will return all the on-chain wallet addresses for a set of Chainlink nodes -func (te *CLClusterTestEnv) ChainlinkNodeAddresses() ([]common.Address, error) { - addresses := make([]common.Address, 0) - for _, n := range te.CLNodes { - primaryAddress, err := n.ChainlinkNodeAddress() - if err != nil { - return nil, err + // Set test logger + if te.t != nil { + for _, n := range te.ClCluster.Nodes { + n.SetTestLogger(te.t) } - addresses = append(addresses, primaryAddress) } - return addresses, nil + + // Start/attach node containers + return te.ClCluster.Start() } // FundChainlinkNodes will fund all the provided Chainlink nodes with a set amount of native currency func (te *CLClusterTestEnv) FundChainlinkNodes(amount *big.Float) error { - for _, cl := range te.CLNodes { + for _, cl := range te.ClCluster.Nodes { if err := cl.Fund(te.EVMClient, amount); err != nil { return errors.Wrap(err, ErrFundCLNode) } @@ -214,101 +170,115 @@ func (te *CLClusterTestEnv) FundChainlinkNodes(amount *big.Float) error { return te.EVMClient.WaitForEvents() } -func (te *CLClusterTestEnv) GetNodeCSAKeys() ([]string, error) { - var keys []string - for _, n := range te.CLNodes { - csaKeys, err := n.GetNodeCSAKeys() - if err != nil { - return nil, errors.Wrap(err, ErrGetNodeCSAKeys) - } - keys = append(keys, csaKeys.Data[0].ID) - } - return keys, nil -} - func (te *CLClusterTestEnv) Terminate() error { // TESTCONTAINERS_RYUK_DISABLED=false by default so ryuk will remove all // the containers and the Network return nil } -// Cleanup cleans the environment up after it's done being used, mainly for returning funds when on live networks. -// Intended to be used as part of t.Cleanup() in tests. -func (te *CLClusterTestEnv) Cleanup(t *testing.T) error { - if te.EVMClient == nil { - return errors.New("blockchain client is nil, unable to return funds from chainlink nodes") +// Cleanup cleans the environment up after it's done being used, mainly for returning funds when on live networks and logs. +func (te *CLClusterTestEnv) Cleanup() error { + te.l.Info().Msg("Cleaning up test environment") + if te.t == nil { + return errors.New("cannot cleanup test environment without a testing.T") } - if te.CLNodes == nil { - return errors.New("chainlink nodes are nil, unable to return funds from chainlink nodes") + if te.ClCluster == nil || len(te.ClCluster.Nodes) == 0 { + return errors.New("chainlink nodes are nil, unable cleanup chainlink nodes") } // TODO: This is an imperfect and temporary solution, see TT-590 for a more sustainable solution // Collect logs if the test fails, or if we just want them - if t.Failed() || os.Getenv("TEST_LOG_COLLECT") == "true" { - folder := fmt.Sprintf("./logs/%s-%s", t.Name(), time.Now().Format("2006-01-02T15-04-05")) - if err := os.MkdirAll(folder, os.ModePerm); err != nil { + if te.t.Failed() || os.Getenv("TEST_LOG_COLLECT") == "true" { + if err := te.collectTestLogs(); err != nil { return err } + } - te.l.Info().Msg("Collecting test logs") - eg := &errgroup.Group{} - for _, n := range te.CLNodes { - node := n - eg.Go(func() error { - logFileName := filepath.Join(folder, fmt.Sprintf("node-%s.log", node.ContainerName)) - logFile, err := os.OpenFile(logFileName, os.O_CREATE|os.O_WRONLY, 0644) - if err != nil { - return err - } - defer logFile.Close() - logReader, err := node.Container.Logs(context.Background()) - if err != nil { - return err - } - _, err = io.Copy(logFile, logReader) - if err != nil { - return err - } - te.l.Info().Str("Node", node.ContainerName).Str("File", logFileName).Msg("Wrote Logs") - return nil - }) - } - - if err := eg.Wait(); err != nil { + if te.EVMClient == nil { + return errors.New("evm client is nil, unable to return funds from chainlink nodes during cleanup") + } else if te.EVMClient.NetworkSimulated() { + te.l.Info(). + Str("Network Name", te.EVMClient.GetNetworkName()). + Msg("Network is a simulated network. Skipping fund return.") + } else { + if err := te.returnFunds(); err != nil { return err } + } - te.l.Info().Str("Logs Location", folder).Msg("Wrote test logs") + // close EVMClient connections + if te.EVMClient != nil { + err := te.EVMClient.Close() + return err } - // Check if we need to return funds - if te.EVMClient.NetworkSimulated() { - te.l.Info().Str("Network Name", te.EVMClient.GetNetworkName()). - Msg("Network is a simulated network. Skipping fund return.") - } else { - te.l.Info().Msg("Attempting to return Chainlink node funds to default network wallets") - for _, chainlinkNode := range te.CLNodes { - fundedKeys, err := chainlinkNode.API.ExportEVMKeysForChain(te.EVMClient.GetChainID().String()) + return nil +} + +// collectTestLogs collects the logs from all the Chainlink nodes in the test environment and writes them to local files +func (te *CLClusterTestEnv) collectTestLogs() error { + te.l.Info().Msg("Collecting test logs") + folder := fmt.Sprintf("./logs/%s-%s", te.t.Name(), time.Now().Format("2006-01-02T15-04-05")) + if err := os.MkdirAll(folder, os.ModePerm); err != nil { + return err + } + + eg := &errgroup.Group{} + for _, n := range te.ClCluster.Nodes { + node := n + eg.Go(func() error { + logFileName := filepath.Join(folder, fmt.Sprintf("node-%s.log", node.ContainerName)) + logFile, err := os.OpenFile(logFileName, os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + return err + } + defer logFile.Close() + logReader, err := node.Container.Logs(context.Background()) + if err != nil { + return err + } + _, err = io.Copy(logFile, logReader) + if err != nil { + return err + } + te.l.Info().Str("Node", node.ContainerName).Str("File", logFileName).Msg("Wrote Logs") + return nil + }) + } + + if err := eg.Wait(); err != nil { + return err + } + + te.l.Info().Str("Logs Location", folder).Msg("Wrote test logs") + return nil +} + +func (te *CLClusterTestEnv) returnFunds() error { + te.l.Info().Msg("Attempting to return Chainlink node funds to default network wallets") + for _, chainlinkNode := range te.ClCluster.Nodes { + fundedKeys, err := chainlinkNode.API.ExportEVMKeysForChain(te.EVMClient.GetChainID().String()) + if err != nil { + return err + } + for _, key := range fundedKeys { + keyToDecrypt, err := json.Marshal(key) + if err != nil { + return err + } + // This can take up a good bit of RAM and time. When running on the remote-test-runner, this can lead to OOM + // issues. So we avoid running in parallel; slower, but safer. + decryptedKey, err := keystore.DecryptKey(keyToDecrypt, client.ChainlinkKeyPassword) if err != nil { return err } - for _, key := range fundedKeys { - keyToDecrypt, err := json.Marshal(key) - if err != nil { - return err - } - // This can take up a good bit of RAM and time. When running on the remote-test-runner, this can lead to OOM - // issues. So we avoid running in parallel; slower, but safer. - decryptedKey, err := keystore.DecryptKey(keyToDecrypt, client.ChainlinkKeyPassword) - if err != nil { - return err - } - if err = te.EVMClient.ReturnFunds(decryptedKey.PrivateKey); err != nil { - return err - } + if err = te.EVMClient.ReturnFunds(decryptedKey.PrivateKey); err != nil { + // If we fail to return funds from one, go on to try the others anyway + te.l.Error().Err(err).Str("Node", chainlinkNode.ContainerName).Msg("Error returning funds from node") } } } + te.l.Info().Msg("Returned funds from Chainlink nodes") return nil } diff --git a/integration-tests/docker/test_env/test_env_builder.go b/integration-tests/docker/test_env/test_env_builder.go index 83783fda38..cdae5a9d72 100644 --- a/integration-tests/docker/test_env/test_env_builder.go +++ b/integration-tests/docker/test_env/test_env_builder.go @@ -15,7 +15,6 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/logwatch" "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/integration-tests/contracts" @@ -23,21 +22,20 @@ import ( ) type CLTestEnvBuilder struct { - hasLogWatch bool - hasGeth bool - hasMockServer bool - hasForwarders bool - clNodeConfig *chainlink.Config - secretsConfig string - nonDevGethNetworks []blockchain.EVMNetwork - clNodesCount int - externalAdapterCount int - customNodeCsaKeys []string - defaultNodeCsaKeys []string - l zerolog.Logger - t *testing.T - te *CLClusterTestEnv - isNonEVM bool + hasLogWatch bool + hasGeth bool + hasKillgrave bool + hasForwarders bool + clNodeConfig *chainlink.Config + secretsConfig string + nonDevGethNetworks []blockchain.EVMNetwork + clNodesCount int + customNodeCsaKeys []string + defaultNodeCsaKeys []string + l zerolog.Logger + t *testing.T + te *CLClusterTestEnv + isNonEVM bool /* funding */ ETHFunds *big.Float @@ -45,8 +43,7 @@ type CLTestEnvBuilder struct { func NewCLTestEnvBuilder() *CLTestEnvBuilder { return &CLTestEnvBuilder{ - externalAdapterCount: 1, - l: log.Logger, + l: log.Logger, } } @@ -128,9 +125,8 @@ func (b *CLTestEnvBuilder) WithSecretsConfig(secrets string) *CLTestEnvBuilder { return b } -func (b *CLTestEnvBuilder) WithMockServer(externalAdapterCount int) *CLTestEnvBuilder { - b.hasMockServer = true - b.externalAdapterCount = externalAdapterCount +func (b *CLTestEnvBuilder) WithMockAdapter() *CLTestEnvBuilder { + b.hasKillgrave = true return b } @@ -150,8 +146,7 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { } b.l.Info(). Bool("hasGeth", b.hasGeth). - Bool("hasMockServer", b.hasMockServer). - Int("externalAdapterCount", b.externalAdapterCount). + Bool("hasKillgrave", b.hasKillgrave). Int("clNodesCount", b.clNodesCount). Strs("customNodeCsaKeys", b.customNodeCsaKeys). Strs("defaultNodeCsaKeys", b.defaultNodeCsaKeys). @@ -169,16 +164,19 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { } } - if b.hasMockServer { - err = b.te.StartMockServer() - if err != nil { - return nil, err - } - err = b.te.MockServer.SetExternalAdapterMocks(b.externalAdapterCount) + if b.hasKillgrave { + err = b.te.StartMockAdapter() if err != nil { return nil, err } } + + b.t.Cleanup(func() { + if err := b.te.Cleanup(); err != nil { + b.l.Error().Err(err).Msg("Error cleaning up test environment") + } + }) + if b.nonDevGethNetworks != nil { b.te.WithPrivateChain(b.nonDevGethNetworks) err := b.te.StartPrivateChain() @@ -198,11 +196,10 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { if nonDevNetworks == nil { return nil, errors.New("cannot create nodes with custom config without nonDevNetworks") } - if b.clNodesCount > 0 { - err = b.te.StartClNodes(b.clNodeConfig, b.clNodesCount, b.secretsConfig) - if err != nil { - return nil, err - } + + err = b.te.StartClCluster(b.clNodeConfig, b.clNodesCount, b.secretsConfig) + if err != nil { + return nil, err } return b.te, nil } @@ -264,12 +261,12 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { node.SetChainConfig(cfg, wsUrls, httpUrls, networkConfig, b.hasForwarders) } - err := b.te.StartClNodes(cfg, b.clNodesCount, b.secretsConfig) + err := b.te.StartClCluster(cfg, b.clNodesCount, b.secretsConfig) if err != nil { return nil, err } - nodeCsaKeys, err = b.te.GetNodeCSAKeys() + nodeCsaKeys, err = b.te.ClCluster.NodeCSAKeys() if err != nil { return nil, err } diff --git a/integration-tests/docker/test_env/test_env_config.go b/integration-tests/docker/test_env/test_env_config.go index da38575a86..1a0c8d5c86 100644 --- a/integration-tests/docker/test_env/test_env_config.go +++ b/integration-tests/docker/test_env/test_env_config.go @@ -7,26 +7,21 @@ import ( ) type TestEnvConfig struct { - Networks []string `json:"networks"` - Geth GethConfig `json:"geth"` - MockServer MockServerConfig `json:"mockserver"` - Nodes []ClNodeConfig `json:"nodes"` + Networks []string `json:"networks"` + Geth GethConfig `json:"geth"` + MockAdapter MockAdapterConfig `json:"mock_adapter"` + ClCluster *ClCluster `json:"clCluster"` } -type MockServerConfig struct { - ContainerName string `json:"container_name"` - EAMockUrls []string `json:"external_adapters_mock_urls"` +type MockAdapterConfig struct { + ContainerName string `json:"container_name"` + ImpostersPath string `json:"imposters_path"` } type GethConfig struct { ContainerName string `json:"container_name"` } -type ClNodeConfig struct { - NodeContainerName string `json:"container_name"` - DbContainerName string `json:"db_container_name"` -} - func NewTestEnvConfigFromFile(path string) (*TestEnvConfig, error) { c := &TestEnvConfig{} err := env.ParseJSONFile(path, c) diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 57ac78df2b..1c2907a100 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -15,17 +15,16 @@ require ( github.com/lib/pq v1.10.9 github.com/manifoldco/promptui v0.9.0 github.com/onsi/gomega v1.27.8 - github.com/pelletier/go-toml v1.9.5 github.com/pelletier/go-toml/v2 v2.1.0 github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.30.0 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chain-selectors v1.0.2 - github.com/smartcontractkit/chainlink-env v0.38.0 - github.com/smartcontractkit/chainlink-testing-framework v1.17.7-0.20231005234726-62948c0c7a5e + github.com/smartcontractkit/chainlink-env v0.38.3 + github.com/smartcontractkit/chainlink-testing-framework v1.17.12-0.20231017213944-4e1fc608fc27 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20230828183543-6d0939746966 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 - github.com/smartcontractkit/libocr v0.0.0-20230922131214-122accb19ea6 + github.com/smartcontractkit/libocr v0.0.0-20230925165524-ffa38fe11ef8 github.com/smartcontractkit/ocr2keepers v0.7.27 github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687 github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 @@ -37,9 +36,9 @@ require ( go.dedis.ch/kyber/v3 v3.1.0 go.uber.org/atomic v1.11.0 go.uber.org/multierr v1.11.0 - go.uber.org/zap v1.25.0 - golang.org/x/crypto v0.13.0 - golang.org/x/sync v0.3.0 + go.uber.org/zap v1.26.0 + golang.org/x/crypto v0.14.0 + golang.org/x/sync v0.4.0 gopkg.in/guregu/null.v4 v4.0.0 ) @@ -77,11 +76,10 @@ require ( github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/avast/retry-go/v4 v4.5.0 // indirect - github.com/aws/aws-sdk-go v1.44.276 // indirect + github.com/aws/aws-sdk-go v1.44.302 // indirect github.com/aws/constructs-go/constructs/v10 v10.1.255 // indirect github.com/aws/jsii-runtime-go v1.75.0 // indirect github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 // indirect - github.com/benbjohnson/clock v1.3.4 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect github.com/blendle/zapdriver v1.3.1 // indirect @@ -173,7 +171,7 @@ require ( github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-openapi/analysis v0.21.4 // indirect - github.com/go-openapi/errors v0.20.3 // indirect + github.com/go-openapi/errors v0.20.4 // indirect github.com/go-openapi/jsonpointer v0.20.0 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/loads v0.21.2 // indirect @@ -217,27 +215,27 @@ require ( github.com/grafana/dskit v0.0.0-20230201083518-528d8a7d52f2 // indirect github.com/grafana/loki v1.6.2-0.20230403212622-90888a0cc737 // indirect github.com/grafana/loki/pkg/push v0.0.0-20230127102416-571f88bc5765 // indirect - github.com/grafana/pyroscope-go v1.0.2 // indirect - github.com/grafana/pyroscope-go/godeltaprof v0.1.3 // indirect + github.com/grafana/pyroscope-go v1.0.4 // indirect + github.com/grafana/pyroscope-go/godeltaprof v0.1.4 // indirect github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd // indirect github.com/graph-gophers/dataloader v5.0.0+incompatible // indirect github.com/graph-gophers/graphql-go v1.3.0 // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect - github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0-rc.0 // indirect + github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.3 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/gtank/merlin v0.1.1 // indirect github.com/gtank/ristretto255 v0.1.2 // indirect - github.com/hashicorp/consul/api v1.21.0 // indirect + github.com/hashicorp/consul/api v1.22.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-msgpack v0.5.5 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-plugin v1.4.10 // indirect + github.com/hashicorp/go-plugin v1.5.2 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/go-sockaddr v1.0.2 // indirect github.com/hashicorp/golang-lru v0.6.0 // indirect @@ -276,7 +274,7 @@ require ( github.com/jpillora/backoff v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/julienschmidt/httprouter v1.3.0 // indirect - github.com/klauspost/compress v1.16.7 // indirect + github.com/klauspost/compress v1.17.0 // indirect github.com/klauspost/cpuid/v2 v2.2.4 // indirect github.com/koron/go-ssdp v0.0.2 // indirect github.com/kr/pretty v0.3.1 // indirect @@ -332,7 +330,7 @@ require ( github.com/mattn/go-isatty v0.0.19 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/miekg/dns v1.1.54 // indirect + github.com/miekg/dns v1.1.55 // indirect github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect github.com/minio/sha256-simd v1.0.0 // indirect @@ -376,18 +374,19 @@ require ( github.com/otiai10/copy v1.14.0 // indirect github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect + github.com/pelletier/go-toml v1.9.5 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/pressly/goose/v3 v3.15.0 // indirect github.com/prometheus/alertmanager v0.25.1 // indirect - github.com/prometheus/client_golang v1.16.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect + github.com/prometheus/client_golang v1.17.0 // indirect + github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.44.0 // indirect github.com/prometheus/common/sigv4 v0.1.0 // indirect github.com/prometheus/exporter-toolkit v0.10.0 // indirect - github.com/prometheus/procfs v0.11.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/prometheus/prometheus v0.46.0 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rivo/uniseg v0.4.4 // indirect @@ -400,7 +399,7 @@ require ( github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect github.com/sercand/kuberesolver v2.4.0+incompatible // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect - github.com/shirou/gopsutil/v3 v3.23.8 // indirect + github.com/shirou/gopsutil/v3 v3.23.9 // indirect github.com/shopspring/decimal v1.3.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect @@ -456,35 +455,35 @@ require ( go.etcd.io/etcd/api/v3 v3.5.9 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.9 // indirect go.etcd.io/etcd/client/v3 v3.5.9 // indirect - go.mongodb.org/mongo-driver v1.11.3 // indirect + go.mongodb.org/mongo-driver v1.12.0 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.42.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.45.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0 // indirect - go.opentelemetry.io/otel v1.16.0 // indirect - go.opentelemetry.io/otel/metric v1.16.0 // indirect - go.opentelemetry.io/otel/sdk v1.16.0 // indirect - go.opentelemetry.io/otel/trace v1.16.0 // indirect + go.opentelemetry.io/otel v1.19.0 // indirect + go.opentelemetry.io/otel/metric v1.19.0 // indirect + go.opentelemetry.io/otel/sdk v1.19.0 // indirect + go.opentelemetry.io/otel/trace v1.19.0 // indirect go.starlark.net v0.0.0-20220817180228-f738f5508c12 // indirect go.uber.org/goleak v1.2.1 // indirect go.uber.org/ratelimit v0.2.0 // indirect golang.org/x/arch v0.4.0 // indirect golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect - golang.org/x/mod v0.12.0 // indirect - golang.org/x/net v0.15.0 // indirect + golang.org/x/mod v0.13.0 // indirect + golang.org/x/net v0.17.0 // indirect golang.org/x/oauth2 v0.10.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/term v0.12.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/term v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.11.0 // indirect + golang.org/x/tools v0.14.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect gonum.org/v1/gonum v0.13.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20230717213848-3f92550aa753 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230717213848-3f92550aa753 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753 // indirect - google.golang.org/grpc v1.57.0 // indirect + google.golang.org/grpc v1.58.3 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/guregu/null.v2 v2.1.2 // indirect gopkg.in/inf.v0 v0.9.1 // indirect @@ -524,14 +523,13 @@ replace ( github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 // until merged upstream: https://github.com/hashicorp/go-plugin/pull/257 - github.com/hashicorp/go-plugin => github.com/smartcontractkit/go-plugin v0.0.0-20230605132010-0f4d515d1472 + github.com/hashicorp/go-plugin => github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 // until merged upstream: https://github.com/mwitkow/grpc-proxy/pull/69 github.com/mwitkow/grpc-proxy => github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f github.com/prometheus/prometheus => github.com/prometheus/prometheus v0.43.1-0.20230327151049-211ae4f1f0a2 - github.com/sercand/kuberesolver v2.4.0+incompatible => github.com/sercand/kuberesolver/v5 v5.1.0 + github.com/sercand/kuberesolver v2.4.0+incompatible => github.com/sercand/kuberesolver/v5 v5.1.1 github.com/smartcontractkit/chainlink/integration-tests => ../integration-tests - ) diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 0a3afa46bd..5f66873ee6 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -149,8 +149,8 @@ cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARy cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= -cloud.google.com/go/compute v1.20.1 h1:6aKEtlUiwEpJzM001l0yFkpXmUVXaN8W+fbkb2AZNbg= -cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute v1.21.0 h1:JNBsyXVoOoNJtTQcnEY5uYpZIbeCTYIeDe0Xh1bySMk= +cloud.google.com/go/compute v1.21.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= @@ -670,8 +670,8 @@ github.com/aws/aws-sdk-go v1.22.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= -github.com/aws/aws-sdk-go v1.44.276 h1:ywPlx9C5Yc482dUgAZ9bHpQ6onVvJvYE9FJWsNDCEy0= -github.com/aws/aws-sdk-go v1.44.276/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.302 h1:ST3ko6GrJKn3Xi+nAvxjG3uk/V1pW8KC52WLeIxqqNk= +github.com/aws/aws-sdk-go v1.44.302/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/constructs-go/constructs/v10 v10.1.255 h1:5hARfEmhBqHSTQf/C3QLA3sWOxO2Dfja0iA1W7ZcI7g= github.com/aws/constructs-go/constructs/v10 v10.1.255/go.mod h1:DCdBSjN04Ck2pajCacTD4RKFqSA7Utya8d62XreYctI= github.com/aws/jsii-runtime-go v1.75.0 h1:NhpUfyiL7/wsRuUekFsz8FFBCYLfPD/l61kKg9kL/a4= @@ -680,8 +680,6 @@ github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 h1:WWB576BN5zNSZc github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/benbjohnson/clock v1.3.4 h1:wj3BFPrTw8yYgA1OlMqvUk95nc8OMv3cvBSF5erT2W4= -github.com/benbjohnson/clock v1.3.4/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -939,14 +937,14 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go. github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI= -github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f h1:7T++XKzy4xg7PKy+bM+Sa9/oe1OC88yz2hXQUISoXfA= -github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q= +github.com/envoyproxy/go-control-plane v0.11.1 h1:wSUXTlLfiAQRWs2F+p+EKOY9rUyis1MyGqJ2DIk5HpM= +github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= -github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8= -github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= +github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= +github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/esote/minmaxheap v1.0.0 h1:rgA7StnXXpZG6qlM0S7pUmEv1KpWe32rYT4x8J8ntaA= github.com/esote/minmaxheap v1.0.0/go.mod h1:Ln8+i7fS1k3PLgZI2JAo0iA1as95QnIYiGCrqSJ5FZk= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= @@ -1069,8 +1067,8 @@ github.com/go-openapi/analysis v0.21.4/go.mod h1:4zQ35W4neeZTqh3ol0rv/O8JBbka9Qy github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= github.com/go-openapi/errors v0.19.9/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.20.3 h1:rz6kiC84sqNQoqrtulzaL/VERgkoCyB6WdEkc2ujzUc= -github.com/go-openapi/errors v0.20.3/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk= +github.com/go-openapi/errors v0.20.4 h1:unTcVm6PispJsMECE3zWgvG4xTiKda1LIR5rCRWLG6M= +github.com/go-openapi/errors v0.20.4/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= @@ -1363,10 +1361,10 @@ github.com/grafana/loki v1.6.2-0.20230403212622-90888a0cc737 h1:o45+fZAYRtTjx+9f github.com/grafana/loki v1.6.2-0.20230403212622-90888a0cc737/go.mod h1:kxNnWCr4EMobhndjy7a2Qpm7jkLPnJW2ariYvY77hLE= github.com/grafana/loki/pkg/push v0.0.0-20230127102416-571f88bc5765 h1:VXitROTlmZtLzvokNe8ZbUKpmwldM4Hy1zdNRO32jKU= github.com/grafana/loki/pkg/push v0.0.0-20230127102416-571f88bc5765/go.mod h1:DhJMrd2QInI/1CNtTN43BZuTmkccdizW1jZ+F6aHkhY= -github.com/grafana/pyroscope-go v1.0.2 h1:dEFgO9VbhYTwuwpCC5coTpuW0JjISEWDZtvRAW9v5Tw= -github.com/grafana/pyroscope-go v1.0.2/go.mod h1:bShDKsVZdzxq+Ol6no0JKigU9y5FTWUcFditMXaH09o= -github.com/grafana/pyroscope-go/godeltaprof v0.1.3 h1:eunWpv1B3Z7ZK9o4499EmQGlY+CsDmSZ4FbxjRx37uk= -github.com/grafana/pyroscope-go/godeltaprof v0.1.3/go.mod h1:1HSPtjU8vLG0jE9JrTdzjgFqdJ/VgN7fvxBNq3luJko= +github.com/grafana/pyroscope-go v1.0.4 h1:oyQX0BOkL+iARXzHuCdIF5TQ7/sRSel1YFViMHC7Bm0= +github.com/grafana/pyroscope-go v1.0.4/go.mod h1:0d7ftwSMBV/Awm7CCiYmHQEG8Y44Ma3YSjt+nWcWztY= +github.com/grafana/pyroscope-go/godeltaprof v0.1.4 h1:mDsJ3ngul7UfrHibGQpV66PbZ3q1T8glz/tK3bQKKEk= +github.com/grafana/pyroscope-go/godeltaprof v0.1.4/go.mod h1:1HSPtjU8vLG0jE9JrTdzjgFqdJ/VgN7fvxBNq3luJko= github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd h1:PpuIBO5P3e9hpqBD0O/HjhShYuM6XE0i/lbE6J94kww= github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd/go.mod h1:M5qHK+eWfAv8VR/265dIuEpL3fNfeC21tXXp9itM24A= github.com/graph-gophers/dataloader v5.0.0+incompatible h1:R+yjsbrNq1Mo3aPG+Z/EKYrXrXXUNJHOgbRt+U6jOug= @@ -1379,8 +1377,8 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmg github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0-rc.0 h1:mdLirNAJBxnGgyB6pjZLcs6ue/6eZGBui6gXspfq4ks= -github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0-rc.0/go.mod h1:kdXbOySqcQeTxiqglW7aahTmWZy3Pgi6SYL36yvKeyA= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 h1:f4tggROQKKcnh4eItay6z/HbHLqghBxS8g7pyMhmDio= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0/go.mod h1:hKAkSgNkL0FII46ZkJcpVEAai4KV+swlIWCKfekd1pA= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.3 h1:o95KDiV/b1xdkumY5YbLR0/n2+wBxUpgf3HgfKgTyLI= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.3/go.mod h1:hTxjzRcX49ogbTGVJ1sM5mz5s+SSgiGIyL3jjPxl32E= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= @@ -1400,11 +1398,11 @@ github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIv github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/api v1.21.0 h1:WMR2JiyuaQWRAMFaOGiYfY4Q4HRpyYRe/oYQofjyduM= -github.com/hashicorp/consul/api v1.21.0/go.mod h1:f8zVJwBcLdr1IQnfdfszjUM0xzp31Zl3bpws3pL9uFM= +github.com/hashicorp/consul/api v1.22.0 h1:ydEvDooB/A0c/xpsBd8GSt7P2/zYPBui4KrNip0xGjE= +github.com/hashicorp/consul/api v1.22.0/go.mod h1:zHpYgZ7TeYqS6zaszjwSt128OwESRpnhU9aGa6ue3Eg= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/consul/sdk v0.13.1 h1:EygWVWWMczTzXGpO93awkHFzfUka6hLYJ0qhETd+6lY= -github.com/hashicorp/consul/sdk v0.13.1/go.mod h1:SW/mM4LbKfqmMvcFu8v+eiQQ7oitXEFeiBe9StxERb0= +github.com/hashicorp/consul/sdk v0.14.0 h1:Hly+BMNMssVzoWddbBnBFi3W+Fzytvm0haSkihhj3GU= +github.com/hashicorp/consul/sdk v0.14.0/go.mod h1:gHYeuDa0+0qRAD6Wwr6yznMBvBwHKoxSBoW5l73+saE= github.com/hashicorp/cronexpr v1.1.1 h1:NJZDd87hGXjoZBdvyCF9mX4DCq5Wy7+A/w+A7q0wn6c= github.com/hashicorp/cronexpr v1.1.1/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -1674,8 +1672,8 @@ github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= -github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= +github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -1996,8 +1994,8 @@ github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKju github.com/miekg/dns v1.1.28/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/miekg/dns v1.1.54 h1:5jon9mWcb0sFJGpnI99tOMhCPyJ+RPVz5b63MQG0VWI= -github.com/miekg/dns v1.1.54/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= +github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo= +github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 h1:QRUSJEgZn2Snx0EmT/QLXibWjSUDjKWvXIT19NBVp94= github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= @@ -2244,15 +2242,15 @@ github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrb github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= @@ -2279,13 +2277,13 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= -github.com/prometheus/procfs v0.11.0 h1:5EAgkfkMl659uZPbe9AS2N68a7Cc1TJbPEuGzFuRbyk= -github.com/prometheus/procfs v0.11.0/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/prometheus/prometheus v0.43.1-0.20230327151049-211ae4f1f0a2 h1:i5hmbBzR+VeL5pPl1ZncsJ1bpg3SO66bwkE1msJBsMA= github.com/prometheus/prometheus v0.43.1-0.20230327151049-211ae4f1f0a2/go.mod h1:Mm42Acga98xgA+u5yTaC3ki3i0rJEJWFpbdHN7q2trk= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/pyroscope-io/client v0.6.0 h1:rcUFgcnfmuyVYDYT+4d0zfqc8YedOyruHSsUb9ImaBw= -github.com/pyroscope-io/client v0.6.0/go.mod h1:4h21iOU4pUOq0prKyDlvYRL+SCKsBc5wKiEtV+rJGqU= +github.com/pyroscope-io/client v0.7.1 h1:yFRhj3vbgjBxehvxQmedmUWJQ4CAfCHhn+itPsuWsHw= +github.com/pyroscope-io/client v0.7.1/go.mod h1:4h21iOU4pUOq0prKyDlvYRL+SCKsBc5wKiEtV+rJGqU= github.com/pyroscope-io/godeltaprof v0.1.2 h1:MdlEmYELd5w+lvIzmZvXGNMVzW2Qc9jDMuJaPOR75g4= github.com/pyroscope-io/godeltaprof v0.1.2/go.mod h1:psMITXp90+8pFenXkKIpNhrfmI9saQnPbba27VIaiQE= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= @@ -2343,15 +2341,15 @@ github.com/scylladb/go-reflectx v1.0.1 h1:b917wZM7189pZdlND9PbIJ6NQxfDPfBvUaQ7cj github.com/scylladb/go-reflectx v1.0.1/go.mod h1:rWnOfDIRWBGN0miMLIcoPt/Dhi2doCMZqwMCJ3KupFc= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/sercand/kuberesolver/v5 v5.1.0 h1:YLqreB1vUFbZHSidcqI5ChMp+RIRmop0brQOeUFWiRw= -github.com/sercand/kuberesolver/v5 v5.1.0/go.mod h1:Fs1KbKhVRnB2aDWN12NjKCB+RgYMWZJ294T3BtmVCpQ= +github.com/sercand/kuberesolver/v5 v5.1.1 h1:CYH+d67G0sGBj7q5wLK61yzqJJ8gLLC8aeprPTHb6yY= +github.com/sercand/kuberesolver/v5 v5.1.1/go.mod h1:Fs1KbKhVRnB2aDWN12NjKCB+RgYMWZJ294T3BtmVCpQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shirou/gopsutil/v3 v3.23.8 h1:xnATPiybo6GgdRoC4YoGnxXZFRc3dqQTGi73oLvvBrE= -github.com/shirou/gopsutil/v3 v3.23.8/go.mod h1:7hmCaBn+2ZwaZOr6jmPBZDfawwMGuo1id3C6aM8EDqQ= +github.com/shirou/gopsutil/v3 v3.23.9 h1:ZI5bWVeu2ep4/DIxB4U9okeYJ7zp/QLTO4auRb/ty/E= +github.com/shirou/gopsutil/v3 v3.23.9/go.mod h1:x/NWSb71eMcjFIO0vhyGW5nZ7oSIgVjrCnADckb85GA= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= @@ -2374,22 +2372,22 @@ github.com/smartcontractkit/chain-selectors v1.0.2 h1:IglJrBajHJ6uAFm1b2qwUcHZld github.com/smartcontractkit/chain-selectors v1.0.2/go.mod h1:WBhLlODF5b95vvx2tdKK55vGACg1+qZpuBhOGu1UXVo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47 h1:vdieOW3CZGdD2R5zvCSMS+0vksyExPN3/Fa1uVfld/A= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20230913032705-f924d753cc47/go.mod h1:xMwqRdj5vqYhCJXgKVqvyAwdcqM6ZAEhnwEQ4Khsop8= -github.com/smartcontractkit/chainlink-env v0.38.0 h1:3LaqV5wSRCVPK0haV5jC2zdZITV2Q0BPyUMUM3tyJ7o= -github.com/smartcontractkit/chainlink-env v0.38.0/go.mod h1:ICN9gOBY+NehK8mIxxM9CrWDohgkCQ1vgX9FazCbg8I= +github.com/smartcontractkit/chainlink-env v0.38.3 h1:ZtOnwkG622R0VCTxL5V09AnT/QXhlFwkGTjd0Lsfpfg= +github.com/smartcontractkit/chainlink-env v0.38.3/go.mod h1:7z4sw/hN8TxioQCLwFqQdhK3vaOV0a22Qe99z4bRUcg= github.com/smartcontractkit/chainlink-relay v0.1.7-0.20230926113942-a871b2976dc1 h1:Db333w+fSm2e18LMikcIQHIZqgxZruW9uCUGJLUC9mI= github.com/smartcontractkit/chainlink-relay v0.1.7-0.20230926113942-a871b2976dc1/go.mod h1:gWclxGW7rLkbjXn7FGizYlyKhp/boekto4MEYGyiMG4= github.com/smartcontractkit/chainlink-solana v1.0.3-0.20230831134610-680240b97aca h1:x7M0m512gtXw5Z4B1WJPZ52VgshoIv+IvHqQ8hsH4AE= github.com/smartcontractkit/chainlink-solana v1.0.3-0.20230831134610-680240b97aca/go.mod h1:RIUJXn7EVp24TL2p4FW79dYjyno23x5mjt1nKN+5WEk= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20230901115736-bbabe542a918 h1:ByVauKFXphRlSNG47lNuxZ9aicu+r8AoNp933VRPpCw= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20230901115736-bbabe542a918/go.mod h1:/yp/sqD8Iz5GU5fcercjrw0ivJF7HDcupYg+Gjr7EPg= -github.com/smartcontractkit/chainlink-testing-framework v1.17.7-0.20231005234726-62948c0c7a5e h1:czPS4TvkFWossV21fxn969iaqtpx27o61euIE/EH/YE= -github.com/smartcontractkit/chainlink-testing-framework v1.17.7-0.20231005234726-62948c0c7a5e/go.mod h1:rypNxetVFh6bwaoHn05bsd4vCtgdEsF+1Vdyy/AhAR8= -github.com/smartcontractkit/go-plugin v0.0.0-20230605132010-0f4d515d1472 h1:x3kNwgFlDmbE/n0gTSRMt9GBDfsfGrs4X9b9arPZtFI= -github.com/smartcontractkit/go-plugin v0.0.0-20230605132010-0f4d515d1472/go.mod h1:6/1TEzT0eQznvI/gV2CM29DLSkAK/e58mUWKVsPaph0= +github.com/smartcontractkit/chainlink-testing-framework v1.17.12-0.20231017213944-4e1fc608fc27 h1:t+3NTzN+XmoX2brXL6gMMl575FePJjoY8kSOuDdkMtU= +github.com/smartcontractkit/chainlink-testing-framework v1.17.12-0.20231017213944-4e1fc608fc27/go.mod h1:RWlmjwnjIGbQAnRfKwe02Ife82nNI3rZmdI0zgkfbyk= +github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88+ZznniNJZbZPWAvHQU8SwKAdHngdDZ+pvVgB5ss= +github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0= -github.com/smartcontractkit/libocr v0.0.0-20230922131214-122accb19ea6 h1:eSo9r53fARv2MnIO5pqYvQOXMBsTlAwhHyQ6BAVp6bY= -github.com/smartcontractkit/libocr v0.0.0-20230922131214-122accb19ea6/go.mod h1:2lyRkw/qLQgUWlrWWmq5nj0y90rWeO6Y+v+fCakRgb0= +github.com/smartcontractkit/libocr v0.0.0-20230925165524-ffa38fe11ef8 h1:R9NkVN+1fooUJFsN9zj9gDY1B+zv54zNO785RQZRVfE= +github.com/smartcontractkit/libocr v0.0.0-20230925165524-ffa38fe11ef8/go.mod h1:2lyRkw/qLQgUWlrWWmq5nj0y90rWeO6Y+v+fCakRgb0= github.com/smartcontractkit/ocr2keepers v0.7.27 h1:kwqMrzmEdq6gH4yqNuLQCbdlED0KaIjwZzu3FF+Gves= github.com/smartcontractkit/ocr2keepers v0.7.27/go.mod h1:1QGzJURnoWpysguPowOe2bshV0hNp1YX10HHlhDEsas= github.com/smartcontractkit/ocr2vrf v0.0.0-20230804151440-2f1eb1e20687 h1:NwC3SOc25noBTe1KUQjt45fyTIuInhoE2UfgcHAdihM= @@ -2559,8 +2557,10 @@ github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcY github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= +github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= +github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= @@ -2615,8 +2615,8 @@ go.etcd.io/etcd/client/v3 v3.5.9/go.mod h1:i/Eo5LrZ5IKqpbtpPDuaUnDOUv471oDg8cjQa go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= -go.mongodb.org/mongo-driver v1.11.3 h1:Ql6K6qYHEzB6xvu4+AU0BoRoqf9vFPcc4o7MUIdPW8Y= -go.mongodb.org/mongo-driver v1.11.3/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= +go.mongodb.org/mongo-driver v1.12.0 h1:aPx33jmn/rQuJXPQLZQ8NtfPQG8CaqgLThFtqRb0PiE= +go.mongodb.org/mongo-driver v1.12.0/go.mod h1:AZkxhPnFJUoH7kZlFkVKucV20K387miPfm7oimrSmK0= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= @@ -2627,18 +2627,18 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.42.0 h1:ZOLJc06r4CB42laIXg/7udr0pbZyuAihN10A/XuiQRY= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.42.0/go.mod h1:5z+/ZWJQKXa9YT34fQNx5K8Hd1EoIhvtUygUQPqEOgQ= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.45.0 h1:RsQi0qJ2imFfCvZabqzM9cNXBG8k6gXMv1A0cXRmH6A= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.45.0/go.mod h1:vsh3ySueQCiKPxFLvjWC4Z135gIa34TQ/NSqkDTZYUM= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0 h1:pginetY7+onl4qN1vl0xW/V/v6OBZ0vVdH+esuJgvmM= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0/go.mod h1:XiYsayHc36K3EByOO6nbAXnAWbrUxdjUROCEeeROOH8= -go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s= -go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4= -go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo= -go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4= -go.opentelemetry.io/otel/sdk v1.16.0 h1:Z1Ok1YsijYL0CSJpHt4cS3wDDh7p572grzNrBMiMWgE= -go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF9QD68aP6p4= -go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs= -go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0= +go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= +go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= +go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= +go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= +go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= +go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= +go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= +go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= @@ -2673,8 +2673,8 @@ go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= -go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.4.0 h1:A8WCeEWhLwPBKNbFi5Wv5UTCBx5zzubnXDlMOFAzFMc= golang.org/x/arch v0.4.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= @@ -2720,8 +2720,8 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20221012134737-56aed061732a/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -2782,8 +2782,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -2869,8 +2869,8 @@ golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -2919,8 +2919,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -3050,8 +3050,9 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -3062,8 +3063,8 @@ golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -3172,8 +3173,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/tools v0.11.0 h1:EMCa6U9S2LtZXLAMoWiR/R8dAQFRqbAitmbJ2UKhoi8= -golang.org/x/tools v0.11.0/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -3448,8 +3449,8 @@ google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsA google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= -google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= -google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= +google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/grpc/examples v0.0.0-20210424002626-9572fd6faeae/go.mod h1:Ly7ZA/ARzg8fnPU9TyZIxoz33sEUuWX7txiqs8lPTgE= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= diff --git a/integration-tests/load/functions/README.md b/integration-tests/load/functions/README.md index 65a87b897a..bcdbe92d52 100644 --- a/integration-tests/load/functions/README.md +++ b/integration-tests/load/functions/README.md @@ -18,7 +18,7 @@ All tests are split by network and in 3 groups: - Secrets decoding payload only - Realistic payload with args/http/secrets -Load test client is [here](../../../contracts/src/v0.8/functions/tests/v1_0_0/testhelpers/FunctionsLoadTestClient.sol) +Load test client is [here](../../../contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsLoadTestClient.sol) Load is controlled with 2 params: - RPS diff --git a/integration-tests/load/vrfv2/cmd/dashboard.go b/integration-tests/load/vrfv2/cmd/dashboard.go index f7e29bd7d7..3035da0422 100644 --- a/integration-tests/load/vrfv2/cmd/dashboard.go +++ b/integration-tests/load/vrfv2/cmd/dashboard.go @@ -8,10 +8,11 @@ import ( "github.com/K-Phoen/grabana/timeseries" "github.com/K-Phoen/grabana/timeseries/axis" "github.com/smartcontractkit/wasp" + "os" ) func main() { - lokiDS := "grafanacloud-logs" + lokiDS := os.Getenv("DATA_SOURCE_NAME") d, err := wasp.NewDashboard(nil, []dashboard.Option{ dashboard.Row("LoadContractMetrics", diff --git a/integration-tests/load/vrfv2/vrfv2_test.go b/integration-tests/load/vrfv2/vrfv2_test.go index 97a455dc71..a9fb80a72a 100644 --- a/integration-tests/load/vrfv2/vrfv2_test.go +++ b/integration-tests/load/vrfv2/vrfv2_test.go @@ -1,10 +1,11 @@ package loadvrfv2 import ( + "testing" + "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions" "github.com/smartcontractkit/wasp" "github.com/stretchr/testify/require" - "testing" ) func TestVRFV2Load(t *testing.T) { @@ -31,7 +32,7 @@ func TestVRFV2Load(t *testing.T) { T: t, LoadType: wasp.VU, GenName: "vu", - VU: NewJobVolumeVU(cfg.SoakVolume.Pace.Duration(), 1, env.GetAPIs(), env.EVMClient, vrfv2Contracts), + VU: NewJobVolumeVU(cfg.SoakVolume.Pace.Duration(), 1, env.ClCluster.NodeAPIs(), env.EVMClient, vrfv2Contracts), Labels: labels, LokiConfig: wasp.NewEnvLokiConfig(), } diff --git a/integration-tests/load/vrfv2plus/README.md b/integration-tests/load/vrfv2plus/README.md new file mode 100644 index 0000000000..1013a3f4c1 --- /dev/null +++ b/integration-tests/load/vrfv2plus/README.md @@ -0,0 +1,22 @@ +### VRFv2Plus Load tests + +## Usage +``` +export LOKI_TOKEN=... +export LOKI_URL=... + +go test -v -run TestVRFV2PlusLoad/vrfv2plus_soak_test +``` + +### Dashboards + +Deploying dashboard: +``` +export GRAFANA_URL=... +export GRAFANA_TOKEN=... +export DATA_SOURCE_NAME=grafanacloud-logs +export DASHBOARD_FOLDER=LoadTests +export DASHBOARD_NAME=${JobTypeName, for example WaspVRFv2Plus} + +go run dashboard.go +``` \ No newline at end of file diff --git a/integration-tests/load/vrfv2plus/cmd/dashboard.go b/integration-tests/load/vrfv2plus/cmd/dashboard.go new file mode 100644 index 0000000000..9a0ba682a1 --- /dev/null +++ b/integration-tests/load/vrfv2plus/cmd/dashboard.go @@ -0,0 +1,99 @@ +package main + +import ( + "github.com/K-Phoen/grabana/dashboard" + "github.com/K-Phoen/grabana/logs" + "github.com/K-Phoen/grabana/row" + "github.com/K-Phoen/grabana/target/prometheus" + "github.com/K-Phoen/grabana/timeseries" + "github.com/K-Phoen/grabana/timeseries/axis" + "github.com/smartcontractkit/wasp" + "os" +) + +func main() { + lokiDS := os.Getenv("DATA_SOURCE_NAME") + d, err := wasp.NewDashboard(nil, + []dashboard.Option{ + dashboard.Row("LoadContractMetrics", + row.WithTimeSeries( + "RequestCount + FulfilmentCount", + timeseries.Span(12), + timeseries.Height("300px"), + timeseries.DataSource(lokiDS), + timeseries.Axis( + axis.Unit("Requests"), + ), + timeseries.WithPrometheusTarget( + ` + last_over_time({type="vrfv2plus_contracts_load_summary", go_test_name=~"${go_test_name:pipe}", branch=~"${branch:pipe}", commit=~"${commit:pipe}", gen_name=~"${gen_name:pipe}"} + | json + | unwrap RequestCount [$__interval]) by (node_id, go_test_name, gen_name) + `, prometheus.Legend("{{go_test_name}} requests"), + ), + timeseries.WithPrometheusTarget( + ` + last_over_time({type="vrfv2plus_contracts_load_summary", go_test_name=~"${go_test_name:pipe}", branch=~"${branch:pipe}", commit=~"${commit:pipe}", gen_name=~"${gen_name:pipe}"} + | json + | unwrap FulfilmentCount [$__interval]) by (node_id, go_test_name, gen_name) + `, prometheus.Legend("{{go_test_name}} fulfillments"), + ), + ), + row.WithTimeSeries( + "Fulfillment time (blocks)", + timeseries.Span(12), + timeseries.Height("300px"), + timeseries.DataSource(lokiDS), + timeseries.Axis( + axis.Unit("Blocks"), + ), + timeseries.WithPrometheusTarget( + ` + last_over_time({type="vrfv2plus_contracts_load_summary", go_test_name=~"${go_test_name:pipe}", branch=~"${branch:pipe}", commit=~"${commit:pipe}", gen_name=~"${gen_name:pipe}"} + | json + | unwrap AverageFulfillmentInMillions [$__interval]) by (node_id, go_test_name, gen_name) / 1e6 + `, prometheus.Legend("{{go_test_name}} avg"), + ), + timeseries.WithPrometheusTarget( + ` + last_over_time({type="vrfv2plus_contracts_load_summary", go_test_name=~"${go_test_name:pipe}", branch=~"${branch:pipe}", commit=~"${commit:pipe}", gen_name=~"${gen_name:pipe}"} + | json + | unwrap SlowestFulfillment [$__interval]) by (node_id, go_test_name, gen_name) + `, prometheus.Legend("{{go_test_name}} slowest"), + ), + timeseries.WithPrometheusTarget( + ` + last_over_time({type="vrfv2plus_contracts_load_summary", go_test_name=~"${go_test_name:pipe}", branch=~"${branch:pipe}", commit=~"${commit:pipe}", gen_name=~"${gen_name:pipe}"} + | json + | unwrap FastestFulfillment [$__interval]) by (node_id, go_test_name, gen_name) + `, prometheus.Legend("{{go_test_name}} fastest"), + ), + ), + ), + dashboard.Row("CL nodes logs", + row.Collapse(), + row.WithLogs( + "CL nodes logs", + logs.DataSource(lokiDS), + logs.Span(12), + logs.Height("300px"), + logs.Transparent(), + logs.WithLokiTarget(` + {type="log_watch"} + `), + )), + }, + ) + if err != nil { + panic(err) + } + // set env vars + //export GRAFANA_URL=... + //export GRAFANA_TOKEN=... + //export DATA_SOURCE_NAME=Loki + //export DASHBOARD_FOLDER=LoadTests + //export DASHBOARD_NAME=Waspvrfv2plus + if _, err := d.Deploy(); err != nil { + panic(err) + } +} diff --git a/integration-tests/load/vrfv2plus/config.go b/integration-tests/load/vrfv2plus/config.go new file mode 100644 index 0000000000..3b76d64cc7 --- /dev/null +++ b/integration-tests/load/vrfv2plus/config.go @@ -0,0 +1,93 @@ +package loadvrfv2plus + +import ( + "encoding/base64" + "github.com/pelletier/go-toml/v2" + "github.com/pkg/errors" + "github.com/rs/zerolog/log" + "github.com/smartcontractkit/chainlink/v2/core/store/models" + "os" +) + +const ( + DefaultConfigFilename = "config.toml" + + ErrReadPerfConfig = "failed to read TOML config for performance tests" + ErrUnmarshalPerfConfig = "failed to unmarshal TOML config for performance tests" +) + +type PerformanceConfig struct { + Soak *Soak `toml:"Soak"` + Load *Load `toml:"Load"` + SoakVolume *SoakVolume `toml:"SoakVolume"` + LoadVolume *LoadVolume `toml:"LoadVolume"` + Common *Common `toml:"Common"` + ExistingEnvConfig *ExistingEnvConfig `toml:"ExistingEnvConfig"` +} + +type ExistingEnvConfig struct { + CoordinatorAddress string `toml:"coordinator_address"` + ConsumerAddress string `toml:"consumer_address"` + SubID string `toml:"sub_id"` + KeyHash string `toml:"key_hash"` +} + +type Common struct { + Funding + IsNativePayment bool `toml:"is_native_payment"` + MinimumConfirmations uint16 `toml:"minimum_confirmations"` +} + +type Funding struct { + NodeFunds float64 `toml:"node_funds"` + SubFundsLink int64 `toml:"sub_funds_link"` + SubFundsNative int64 `toml:"sub_funds_native"` +} + +type Soak struct { + RPS int64 `toml:"rps"` + Duration *models.Duration `toml:"duration"` +} + +type SoakVolume struct { + Products int64 `toml:"products"` + Pace *models.Duration `toml:"pace"` + Duration *models.Duration `toml:"duration"` +} + +type Load struct { + RPSFrom int64 `toml:"rps_from"` + RPSIncrease int64 `toml:"rps_increase"` + RPSSteps int `toml:"rps_steps"` + Duration *models.Duration `toml:"duration"` +} + +type LoadVolume struct { + ProductsFrom int64 `toml:"products_from"` + ProductsIncrease int64 `toml:"products_increase"` + ProductsSteps int `toml:"products_steps"` + Pace *models.Duration `toml:"pace"` + Duration *models.Duration `toml:"duration"` +} + +func ReadConfig() (*PerformanceConfig, error) { + var cfg *PerformanceConfig + rawConfig := os.Getenv("CONFIG") + var d []byte + var err error + if rawConfig == "" { + d, err = os.ReadFile(DefaultConfigFilename) + if err != nil { + return nil, errors.Wrap(err, ErrReadPerfConfig) + } + } else { + d, err = base64.StdEncoding.DecodeString(rawConfig) + } + err = toml.Unmarshal(d, &cfg) + if err != nil { + return nil, errors.Wrap(err, ErrUnmarshalPerfConfig) + } + + log.Debug().Interface("Config", cfg).Msg("Parsed config") + return cfg, nil +} diff --git a/integration-tests/load/vrfv2plus/config.toml b/integration-tests/load/vrfv2plus/config.toml new file mode 100644 index 0000000000..d77c22badb --- /dev/null +++ b/integration-tests/load/vrfv2plus/config.toml @@ -0,0 +1,14 @@ + +[Common] +node_funds = 0.1 +is_native_payment = false +minimum_confirmations = 3 +sub_funds_link = 10 +sub_funds_native = 1 + +[ExistingEnvConfig] +coordinator_address = "0x4931Ce2e341398c8eD8A5D0F6ADb920476D6DaBb" +consumer_address = "0x087F232165D9bA1A602f148025e5D0666953F64a" +sub_id = "52116875585187328970776211988181422347535732407068188096422095950800466618218" +key_hash = "0x4c422465ed6a06cfc84575a5437fef7b9dc6263133f648afbe6ae7b2c694d3b3" + diff --git a/integration-tests/load/vrfv2plus/gun.go b/integration-tests/load/vrfv2plus/gun.go new file mode 100644 index 0000000000..f1b15bb5fe --- /dev/null +++ b/integration-tests/load/vrfv2plus/gun.go @@ -0,0 +1,56 @@ +package loadvrfv2plus + +import ( + "github.com/rs/zerolog" + "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus" + "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus/vrfv2plus_config" + "github.com/smartcontractkit/wasp" + "math/big" +) + +/* SingleHashGun is a gun that constantly requests randomness for one feed */ + +type SingleHashGun struct { + contracts *vrfv2plus.VRFV2_5Contracts + keyHash [32]byte + subID *big.Int + vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig + logger zerolog.Logger +} + +func NewSingleHashGun( + contracts *vrfv2plus.VRFV2_5Contracts, + keyHash [32]byte, + subID *big.Int, + vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig, + logger zerolog.Logger, +) *SingleHashGun { + return &SingleHashGun{ + contracts: contracts, + keyHash: keyHash, + subID: subID, + vrfv2PlusConfig: vrfv2PlusConfig, + logger: logger, + } +} + +// Call implements example gun call, assertions on response bodies should be done here +func (m *SingleHashGun) Call(l *wasp.Generator) *wasp.CallResult { + //todo - should work with multiple consumers and consumers having different keyhashes and wallets + _, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( + m.contracts.LoadTestConsumers[0], + m.contracts.Coordinator, + &vrfv2plus.VRFV2PlusData{VRFV2PlusKeyData: vrfv2plus.VRFV2PlusKeyData{KeyHash: m.keyHash}}, + m.subID, + //todo - make this configurable + m.vrfv2PlusConfig.IsNativePayment, + m.vrfv2PlusConfig, + m.logger, + ) + + if err != nil { + return &wasp.CallResult{Error: err.Error(), Failed: true} + } + + return &wasp.CallResult{} +} diff --git a/integration-tests/load/vrfv2plus/onchain_monitoring.go b/integration-tests/load/vrfv2plus/onchain_monitoring.go new file mode 100644 index 0000000000..0ae27fe6be --- /dev/null +++ b/integration-tests/load/vrfv2plus/onchain_monitoring.go @@ -0,0 +1,50 @@ +package loadvrfv2plus + +import ( + "context" + "github.com/rs/zerolog/log" + "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus" + "github.com/smartcontractkit/wasp" + "testing" + "time" +) + +/* Monitors on-chain stats of LoadConsumer and pushes them to Loki every second */ + +const ( + LokiTypeLabel = "vrfv2plus_contracts_load_summary" + ErrMetrics = "failed to get VRFv2Plus load test metrics" + ErrLokiClient = "failed to create Loki client for monitoring" + ErrLokiPush = "failed to push monitoring metrics to Loki" +) + +func MonitorLoadStats(lc *wasp.LokiClient, vrfv2PlusContracts *vrfv2plus.VRFV2_5Contracts, labels map[string]string) { + go func() { + for { + time.Sleep(1 * time.Second) + SendLoadTestMetricsToLoki(vrfv2PlusContracts, lc, labels) + } + }() +} + +func UpdateLabels(labels map[string]string, t *testing.T) map[string]string { + updatedLabels := make(map[string]string) + for k, v := range labels { + updatedLabels[k] = v + } + updatedLabels["type"] = LokiTypeLabel + updatedLabels["go_test_name"] = t.Name() + updatedLabels["gen_name"] = "performance" + return updatedLabels +} + +func SendLoadTestMetricsToLoki(vrfv2PlusContracts *vrfv2plus.VRFV2_5Contracts, lc *wasp.LokiClient, updatedLabels map[string]string) { + //todo - should work with multiple consumers and consumers having different keyhashes and wallets + metrics, err := vrfv2PlusContracts.LoadTestConsumers[0].GetLoadTestMetrics(context.Background()) + if err != nil { + log.Error().Err(err).Msg(ErrMetrics) + } + if err := lc.HandleStruct(wasp.LabelsMapToModel(updatedLabels), time.Now(), metrics); err != nil { + log.Error().Err(err).Msg(ErrLokiPush) + } +} diff --git a/integration-tests/load/vrfv2plus/vrfv2plus_test.go b/integration-tests/load/vrfv2plus/vrfv2plus_test.go new file mode 100644 index 0000000000..5221a9860f --- /dev/null +++ b/integration-tests/load/vrfv2plus/vrfv2plus_test.go @@ -0,0 +1,221 @@ +package loadvrfv2plus + +import ( + "context" + "fmt" + "github.com/ethereum/go-ethereum/common" + "github.com/kelseyhightower/envconfig" + "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/smartcontractkit/wasp" + "github.com/stretchr/testify/require" + "math/big" + "sync" + "testing" + "time" + + "github.com/smartcontractkit/chainlink/integration-tests/actions" + "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus" + "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus/vrfv2plus_config" + "github.com/smartcontractkit/chainlink/integration-tests/contracts" + "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" +) + +func TestVRFV2PlusLoad(t *testing.T) { + cfg, err := ReadConfig() + require.NoError(t, err) + var vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig + err = envconfig.Process("VRFV2PLUS", &vrfv2PlusConfig) + require.NoError(t, err) + + l := logging.GetTestLogger(t) + //todo: temporary solution with envconfig and toml config until VRF-662 is implemented + vrfv2PlusConfig.ChainlinkNodeFunding = cfg.Common.NodeFunds + vrfv2PlusConfig.IsNativePayment = cfg.Common.IsNativePayment + vrfv2PlusConfig.MinimumConfirmations = cfg.Common.MinimumConfirmations + vrfv2PlusConfig.SubscriptionFundingAmountLink = cfg.Common.Funding.SubFundsLink + vrfv2PlusConfig.SubscriptionFundingAmountNative = cfg.Common.Funding.SubFundsNative + + var env *test_env.CLClusterTestEnv + var vrfv2PlusContracts *vrfv2plus.VRFV2_5Contracts + var subID *big.Int + var vrfv2PlusData *vrfv2plus.VRFV2PlusData + if vrfv2PlusConfig.UseExistingEnv { + //todo: temporary solution with envconfig and toml config until VRF-662 is implemented + vrfv2PlusConfig.CoordinatorAddress = cfg.ExistingEnvConfig.CoordinatorAddress + vrfv2PlusConfig.ConsumerAddress = cfg.ExistingEnvConfig.ConsumerAddress + vrfv2PlusConfig.SubID = cfg.ExistingEnvConfig.SubID + vrfv2PlusConfig.KeyHash = cfg.ExistingEnvConfig.KeyHash + + env, err = test_env.NewCLTestEnvBuilder(). + WithTestLogger(t). + Build() + + require.NoError(t, err, "error creating test env") + + coordinator, err := env.ContractLoader.LoadVRFCoordinatorV2_5(vrfv2PlusConfig.CoordinatorAddress) + require.NoError(t, err) + + consumer, err := env.ContractLoader.LoadVRFv2PlusLoadTestConsumer(vrfv2PlusConfig.ConsumerAddress) + require.NoError(t, err) + + vrfv2PlusContracts = &vrfv2plus.VRFV2_5Contracts{ + Coordinator: coordinator, + LoadTestConsumers: []contracts.VRFv2PlusLoadTestConsumer{consumer}, + BHS: nil, + } + var ok bool + subID, ok = new(big.Int).SetString(vrfv2PlusConfig.SubID, 10) + require.True(t, ok) + + vrfv2PlusData = &vrfv2plus.VRFV2PlusData{ + VRFV2PlusKeyData: vrfv2plus.VRFV2PlusKeyData{ + VRFKey: nil, + EncodedProvingKey: [2]*big.Int{}, + KeyHash: common.HexToHash(vrfv2PlusConfig.KeyHash), + }, + VRFJob: nil, + PrimaryEthAddress: "", + ChainID: nil, + } + } else { + env, err = test_env.NewCLTestEnvBuilder(). + WithTestLogger(t). + WithGeth(). + WithCLNodes(1). + WithFunding(big.NewFloat(vrfv2PlusConfig.ChainlinkNodeFunding)). + WithLogWatcher(). + Build() + + require.NoError(t, err, "error creating test env") + + env.ParallelTransactions(true) + + mockETHLinkFeed, err := actions.DeployMockETHLinkFeed(env.ContractDeployer, big.NewInt(vrfv2PlusConfig.LinkNativeFeedResponse)) + require.NoError(t, err, "error deploying mock ETH/LINK feed") + + linkToken, err := actions.DeployLINKToken(env.ContractDeployer) + require.NoError(t, err, "error deploying LINK contract") + + vrfv2PlusContracts, subID, vrfv2PlusData, err = vrfv2plus.SetupVRFV2_5Environment(env, vrfv2PlusConfig, linkToken, mockETHLinkFeed, 1) + require.NoError(t, err, "error setting up VRF v2_5 env") + } + + subscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), subID) + require.NoError(t, err, "error getting subscription information") + + vrfv2plus.LogSubDetails(l, subscription, subID, vrfv2PlusContracts.Coordinator) + + labels := map[string]string{ + "branch": "vrfv2Plus_healthcheck", + "commit": "vrfv2Plus_healthcheck", + } + + l.Info(). + Str("Test Duration", vrfv2PlusConfig.TestDuration.Truncate(time.Second).String()). + Int64("RPS", vrfv2PlusConfig.RPS). + Str("RateLimitUnitDuration", vrfv2PlusConfig.RateLimitUnitDuration.String()). + Uint16("RandomnessRequestCountPerRequest", vrfv2PlusConfig.RandomnessRequestCountPerRequest). + Bool("UseExistingEnv", vrfv2PlusConfig.UseExistingEnv). + Msg("Load Test Configs") + + lokiConfig := wasp.NewEnvLokiConfig() + lc, err := wasp.NewLokiClient(lokiConfig) + if err != nil { + l.Error().Err(err).Msg(ErrLokiClient) + return + } + + singleFeedConfig := &wasp.Config{ + T: t, + LoadType: wasp.RPS, + GenName: "gun", + RateLimitUnitDuration: vrfv2PlusConfig.RateLimitUnitDuration, + Gun: NewSingleHashGun( + vrfv2PlusContracts, + vrfv2PlusData.KeyHash, + subID, + vrfv2PlusConfig, + l, + ), + Labels: labels, + LokiConfig: lokiConfig, + CallTimeout: 2 * time.Minute, + } + consumer := vrfv2PlusContracts.LoadTestConsumers[0] + err = consumer.ResetMetrics() + require.NoError(t, err) + updatedLabels := UpdateLabels(labels, t) + MonitorLoadStats(lc, vrfv2PlusContracts, updatedLabels) + + // is our "job" stable at all, no memory leaks, no flaking performance under some RPS? + t.Run("vrfv2plus soak test", func(t *testing.T) { + + singleFeedConfig.Schedule = wasp.Plain( + vrfv2PlusConfig.RPS, + vrfv2PlusConfig.TestDuration, + ) + _, err = wasp.NewProfile(). + Add(wasp.NewGenerator(singleFeedConfig)). + Run(true) + require.NoError(t, err) + + var wg sync.WaitGroup + + wg.Add(1) + requestCount, fulfilmentCount, err := WaitForRequestCountEqualToFulfilmentCount(vrfv2PlusContracts.LoadTestConsumers[0], 30*time.Second, &wg) + l.Info(). + Interface("Request Count", requestCount). + Interface("Fulfilment Count", fulfilmentCount). + Msg("Final Request/Fulfilment Stats") + require.NoError(t, err) + wg.Wait() + //send final results + SendLoadTestMetricsToLoki(vrfv2PlusContracts, lc, updatedLabels) + }) + +} + +func WaitForRequestCountEqualToFulfilmentCount(consumer contracts.VRFv2PlusLoadTestConsumer, timeout time.Duration, wg *sync.WaitGroup) (*big.Int, *big.Int, error) { + metricsChannel := make(chan *contracts.VRFLoadTestMetrics) + metricsErrorChannel := make(chan error) + + testContext, testCancel := context.WithTimeout(context.Background(), timeout) + defer testCancel() + + ticker := time.NewTicker(time.Second * 1) + var metrics *contracts.VRFLoadTestMetrics + for { + select { + case <-testContext.Done(): + ticker.Stop() + wg.Done() + return metrics.RequestCount, metrics.FulfilmentCount, + fmt.Errorf("timeout waiting for rand request and fulfilments to be equal AFTER performance test was executed. Request Count: %d, Fulfilment Count: %d", + metrics.RequestCount.Uint64(), metrics.FulfilmentCount.Uint64()) + case <-ticker.C: + go getLoadTestMetrics(consumer, metricsChannel, metricsErrorChannel) + case metrics = <-metricsChannel: + if metrics.RequestCount.Cmp(metrics.FulfilmentCount) == 0 { + ticker.Stop() + wg.Done() + return metrics.RequestCount, metrics.FulfilmentCount, nil + } + case err := <-metricsErrorChannel: + ticker.Stop() + wg.Done() + return nil, nil, err + } + } +} + +func getLoadTestMetrics( + consumer contracts.VRFv2PlusLoadTestConsumer, + metricsChannel chan *contracts.VRFLoadTestMetrics, + metricsErrorChannel chan error, +) { + metrics, err := consumer.GetLoadTestMetrics(context.Background()) + if err != nil { + metricsErrorChannel <- err + } + metricsChannel <- metrics +} diff --git a/integration-tests/migration/upgrade_version_test.go b/integration-tests/migration/upgrade_version_test.go index d1d79de5ee..bf97f43d05 100644 --- a/integration-tests/migration/upgrade_version_test.go +++ b/integration-tests/migration/upgrade_version_test.go @@ -34,6 +34,6 @@ func TestVersionUpgrade(t *testing.T) { // MigrateOnStartup = true // // by default - err = env.CLNodes[0].Restart(env.CLNodes[0].NodeConfig) + err = env.ClCluster.Nodes[0].Restart(env.ClCluster.Nodes[0].NodeConfig) require.NoError(t, err) } diff --git a/integration-tests/performance/cron_test.go b/integration-tests/performance/cron_test.go index b5fc9c48b0..959cb0fa3e 100644 --- a/integration-tests/performance/cron_test.go +++ b/integration-tests/performance/cron_test.go @@ -126,8 +126,9 @@ HTTPWriteTimout = '300s'` }) testEnvironment = environment.New(&environment.Config{ - NamespacePrefix: fmt.Sprintf("performance-cron-%s", strings.ReplaceAll(strings.ToLower(network.Name), " ", "-")), - Test: t, + NamespacePrefix: fmt.Sprintf("performance-cron-%s", strings.ReplaceAll(strings.ToLower(network.Name), " ", "-")), + Test: t, + PreventPodEviction: true, }). AddHelm(mockservercfg.New(nil)). AddHelm(mockserver.New(nil)). diff --git a/integration-tests/performance/directrequest_test.go b/integration-tests/performance/directrequest_test.go index 1b3009043f..4ff2b85619 100644 --- a/integration-tests/performance/directrequest_test.go +++ b/integration-tests/performance/directrequest_test.go @@ -146,8 +146,9 @@ HTTPWriteTimout = '300s'` }) testEnvironment = environment.New(&environment.Config{ - NamespacePrefix: fmt.Sprintf("performance-cron-%s", strings.ReplaceAll(strings.ToLower(network.Name), " ", "-")), - Test: t, + NamespacePrefix: fmt.Sprintf("performance-cron-%s", strings.ReplaceAll(strings.ToLower(network.Name), " ", "-")), + Test: t, + PreventPodEviction: true, }). AddHelm(mockservercfg.New(nil)). AddHelm(mockserver.New(nil)). diff --git a/integration-tests/performance/flux_test.go b/integration-tests/performance/flux_test.go index 5ca5ae8096..3f9db27c10 100644 --- a/integration-tests/performance/flux_test.go +++ b/integration-tests/performance/flux_test.go @@ -193,8 +193,9 @@ Enabled = true` }) testEnvironment = environment.New(&environment.Config{ - NamespacePrefix: fmt.Sprintf("performance-flux-%s", strings.ReplaceAll(strings.ToLower(testNetwork.Name), " ", "-")), - Test: t, + NamespacePrefix: fmt.Sprintf("performance-flux-%s", strings.ReplaceAll(strings.ToLower(testNetwork.Name), " ", "-")), + Test: t, + PreventPodEviction: true, }). AddHelm(mockservercfg.New(nil)). AddHelm(mockserver.New(nil)). diff --git a/integration-tests/performance/keeper_test.go b/integration-tests/performance/keeper_test.go index e1ffecd28c..08ea95b434 100644 --- a/integration-tests/performance/keeper_test.go +++ b/integration-tests/performance/keeper_test.go @@ -160,8 +160,9 @@ PerformGasOverhead = 150_000` testEnvironment := environment.New( &environment.Config{ - NamespacePrefix: fmt.Sprintf("performance-keeper-%s-%s", testName, networkName), - Test: t, + NamespacePrefix: fmt.Sprintf("performance-keeper-%s-%s", testName, networkName), + Test: t, + PreventPodEviction: true, }, ). AddHelm(mockservercfg.New(nil)). diff --git a/integration-tests/performance/ocr_test.go b/integration-tests/performance/ocr_test.go index 3df0700c6e..b18d7f1f79 100644 --- a/integration-tests/performance/ocr_test.go +++ b/integration-tests/performance/ocr_test.go @@ -113,8 +113,9 @@ ListenPort = 6690` }) testEnvironment = environment.New(&environment.Config{ - NamespacePrefix: fmt.Sprintf("performance-ocr-%s", strings.ReplaceAll(strings.ToLower(testNetwork.Name), " ", "-")), - Test: t, + NamespacePrefix: fmt.Sprintf("performance-ocr-%s", strings.ReplaceAll(strings.ToLower(testNetwork.Name), " ", "-")), + Test: t, + PreventPodEviction: true, }). AddHelm(mockservercfg.New(nil)). AddHelm(mockserver.New(nil)). diff --git a/integration-tests/performance/vrf_test.go b/integration-tests/performance/vrf_test.go index 4f86c6585b..510e378eb8 100644 --- a/integration-tests/performance/vrf_test.go +++ b/integration-tests/performance/vrf_test.go @@ -151,8 +151,9 @@ HTTPWriteTimout = '300s'` }) testEnvironment = environment.New(&environment.Config{ - NamespacePrefix: fmt.Sprintf("smoke-vrf-%s", strings.ReplaceAll(strings.ToLower(testNetwork.Name), " ", "-")), - Test: t, + NamespacePrefix: fmt.Sprintf("smoke-vrf-%s", strings.ReplaceAll(strings.ToLower(testNetwork.Name), " ", "-")), + Test: t, + PreventPodEviction: true, }). AddHelm(evmConfig). AddHelm(cd) diff --git a/integration-tests/reorg/automation_reorg_test.go b/integration-tests/reorg/automation_reorg_test.go index 2f8db75f74..e94e5c2853 100644 --- a/integration-tests/reorg/automation_reorg_test.go +++ b/integration-tests/reorg/automation_reorg_test.go @@ -9,9 +9,6 @@ import ( "time" "github.com/onsi/gomega" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - "github.com/smartcontractkit/chainlink-env/environment" "github.com/smartcontractkit/chainlink-env/pkg/cdk8s/blockscout" "github.com/smartcontractkit/chainlink-env/pkg/helm/chainlink" @@ -20,6 +17,8 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink-testing-framework/utils" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" @@ -124,134 +123,147 @@ const ( * normal pace after the event. */ func TestAutomationReorg(t *testing.T) { + t.Parallel() l := logging.GetTestLogger(t) - network := networks.SelectedNetwork - defaultAutomationSettings["replicas"] = numberOfNodes - cd := chainlink.New(0, defaultAutomationSettings) - - testEnvironment := environment. - New(&environment.Config{ - NamespacePrefix: fmt.Sprintf("automation-reorg-%d", automationReorgBlocks), - TTL: time.Hour * 1, - Test: t}). - AddHelm(reorg.New(defaultReorgEthereumSettings)). - AddChart(blockscout.New(&blockscout.Props{ - Name: "geth-blockscout", - WsURL: activeEVMNetwork.URL, - HttpURL: activeEVMNetwork.HTTPURLs[0]})). - AddHelm(cd) - err := testEnvironment.Run() - require.NoError(t, err, "Error setting up test environment") - - if testEnvironment.WillUseRemoteRunner() { - return - } - chainClient, err := blockchain.NewEVMClient(network, testEnvironment, l) - require.NoError(t, err, "Error connecting to blockchain") - contractDeployer, err := contracts.NewContractDeployer(chainClient, l) - require.NoError(t, err, "Error building contract deployer") - chainlinkNodes, err := client.ConnectChainlinkNodes(testEnvironment) - require.NoError(t, err, "Error connecting to Chainlink nodes") - chainClient.ParallelTransactions(true) - - // Register cleanup for any test - t.Cleanup(func() { - err := actions.TeardownSuite(t, testEnvironment, utils.ProjectRoot, chainlinkNodes, nil, zapcore.PanicLevel, chainClient) - require.NoError(t, err, "Error tearing down environment") - }) - - txCost, err := chainClient.EstimateCostForChainlinkOperations(1000) - require.NoError(t, err, "Error estimating cost for Chainlink Operations") - err = actions.FundChainlinkNodes(chainlinkNodes, chainClient, txCost) - require.NoError(t, err, "Error funding Chainlink nodes") - - linkToken, err := contractDeployer.DeployLinkTokenContract() - require.NoError(t, err, "Error deploying LINK token") - - registry, registrar := actions.DeployAutoOCRRegistryAndRegistrar( - t, - ethereum.RegistryVersion_2_0, - defaultOCRRegistryConfig, - linkToken, - contractDeployer, - chainClient, - ) - - // Fund the registry with LINK - err = linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(numberOfUpkeeps)))) - require.NoError(t, err, "Funding keeper registry contract shouldn't fail") - - actions.CreateOCRKeeperJobs(t, chainlinkNodes, registry.Address(), network.ChainID, 0, ethereum.RegistryVersion_2_0) - nodesWithoutBootstrap := chainlinkNodes[1:] - ocrConfig, err := actions.BuildAutoOCR2ConfigVars(t, nodesWithoutBootstrap, defaultOCRRegistryConfig, registrar.Address(), 30*time.Second) - require.NoError(t, err, "OCR2 config should be built successfully") - err = registry.SetConfig(defaultOCRRegistryConfig, ocrConfig) - require.NoError(t, err, "Registry config should be be set successfully") - require.NoError(t, chainClient.WaitForEvents(), "Waiting for config to be set") - - consumers, upkeepIDs := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, numberOfUpkeeps, big.NewInt(defaultLinkFunds), defaultUpkeepGasLimit, false) - - l.Info().Msg("Waiting for all upkeeps to be performed") - - gom := gomega.NewGomegaWithT(t) - gom.Eventually(func(g gomega.Gomega) { - // Check if the upkeeps are performing multiple times by analyzing their counters and checking they are greater than 5 - for i := 0; i < len(upkeepIDs); i++ { - counter, err := consumers[i].Counter(context.Background()) - require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i) - expect := 5 - l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep ID", i).Msg("Number of upkeeps performed") - g.Expect(counter.Int64()).Should(gomega.BeNumerically(">=", int64(expect)), - "Expected consumer counter to be greater than %d, but got %d", expect, counter.Int64()) - } - }, "7m", "1s").Should(gomega.Succeed()) // ~1m for cluster setup, ~3m for performing each upkeep 5 times, ~3m buffer - - l.Info().Msg("All upkeeps performed under happy path. Starting reorg") - - rc, err := NewReorgController( - &ReorgConfig{ - FromPodLabel: reorg.TXNodesAppLabel, - ToPodLabel: reorg.MinerNodesAppLabel, - Network: chainClient, - Env: testEnvironment, - BlockConsensusThreshold: 3, - Timeout: 1800 * time.Second, - }, - ) - - require.NoError(t, err, "Error getting reorg controller") - rc.ReOrg(automationReorgBlocks) - rc.WaitReorgStarted() - - l.Info().Msg("Reorg started. Expecting chain to become unstable and upkeeps to still getting performed") - - gom.Eventually(func(g gomega.Gomega) { - // Check if the upkeeps are performing multiple times by analyzing their counters and checking they reach 10 - for i := 0; i < len(upkeepIDs); i++ { - counter, err := consumers[i].Counter(context.Background()) - require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i) - expect := 10 - l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep ID", i).Msg("Number of upkeeps performed") - g.Expect(counter.Int64()).Should(gomega.BeNumerically(">=", int64(expect)), - "Expected consumer counter to be greater than %d, but got %d", expect, counter.Int64()) - } - }, "5m", "1s").Should(gomega.Succeed()) - - l.Info().Msg("Upkeep performed during unstable chain, waiting for reorg to finish") - rc.WaitDepthReached() - - l.Info().Msg("Reorg finished, chain should be stable now. Expecting upkeeps to keep getting performed") - gom.Eventually(func(g gomega.Gomega) { - // Check if the upkeeps are performing multiple times by analyzing their counters and checking they reach 20 - for i := 0; i < len(upkeepIDs); i++ { - counter, err := consumers[i].Counter(context.Background()) - require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i) - expect := 20 - l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep ID", i).Msg("Number of upkeeps performed") - g.Expect(counter.Int64()).Should(gomega.BeNumerically(">=", int64(expect)), - "Expected consumer counter to be greater than %d, but got %d", expect, counter.Int64()) - } - }, "10m", "1s").Should(gomega.Succeed()) + registryVersions := map[string]ethereum.KeeperRegistryVersion{ + "registry_2_0": ethereum.RegistryVersion_2_0, + "registry_2_1_conditional": ethereum.RegistryVersion_2_1, + "registry_2_1_logtrigger": ethereum.RegistryVersion_2_1, + } + for name, registryVersion := range registryVersions { + t.Run(name, func(t *testing.T) { + t.Parallel() + network := networks.SelectedNetwork + + defaultAutomationSettings["replicas"] = numberOfNodes + cd := chainlink.New(0, defaultAutomationSettings) + testEnvironment := environment. + New(&environment.Config{ + NamespacePrefix: fmt.Sprintf("automation-reorg-%d", automationReorgBlocks), + TTL: time.Hour * 1, + Test: t}). + AddHelm(reorg.New(defaultReorgEthereumSettings)). + AddChart(blockscout.New(&blockscout.Props{ + Name: "geth-blockscout", + WsURL: activeEVMNetwork.URL, + HttpURL: activeEVMNetwork.HTTPURLs[0]})). + AddHelm(cd) + err := testEnvironment.Run() + require.NoError(t, err, "Error setting up test environment") + + if testEnvironment.WillUseRemoteRunner() { + return + } + + chainClient, err := blockchain.NewEVMClient(network, testEnvironment, l) + require.NoError(t, err, "Error connecting to blockchain") + contractDeployer, err := contracts.NewContractDeployer(chainClient, l) + require.NoError(t, err, "Error building contract deployer") + chainlinkNodes, err := client.ConnectChainlinkNodes(testEnvironment) + require.NoError(t, err, "Error connecting to Chainlink nodes") + chainClient.ParallelTransactions(true) + + // Register cleanup for any test + t.Cleanup(func() { + err := actions.TeardownSuite(t, testEnvironment, utils.ProjectRoot, chainlinkNodes, nil, zapcore.PanicLevel, chainClient) + require.NoError(t, err, "Error tearing down environment") + }) + + txCost, err := chainClient.EstimateCostForChainlinkOperations(1000) + require.NoError(t, err, "Error estimating cost for Chainlink Operations") + err = actions.FundChainlinkNodes(chainlinkNodes, chainClient, txCost) + require.NoError(t, err, "Error funding Chainlink nodes") + + linkToken, err := contractDeployer.DeployLinkTokenContract() + require.NoError(t, err, "Error deploying LINK token") + + registry, registrar := actions.DeployAutoOCRRegistryAndRegistrar( + t, + registryVersion, + defaultOCRRegistryConfig, + linkToken, + contractDeployer, + chainClient, + ) + // Fund the registry with LINK + err = linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(numberOfUpkeeps)))) + require.NoError(t, err, "Funding keeper registry contract shouldn't fail") + + actions.CreateOCRKeeperJobs(t, chainlinkNodes, registry.Address(), network.ChainID, 0, registryVersion) + nodesWithoutBootstrap := chainlinkNodes[1:] + ocrConfig, err := actions.BuildAutoOCR2ConfigVars(t, nodesWithoutBootstrap, defaultOCRRegistryConfig, registrar.Address(), 5*time.Second) + require.NoError(t, err, "OCR2 config should be built successfully") + err = registry.SetConfig(defaultOCRRegistryConfig, ocrConfig) + require.NoError(t, err, "Registry config should be be set successfully") + require.NoError(t, chainClient.WaitForEvents(), "Waiting for config to be set") + + // Use the name to determine if this is a log trigger or not + isLogTrigger := name == "registry_2_1_logtrigger" + consumers, upkeepIDs := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, numberOfUpkeeps, big.NewInt(defaultLinkFunds), defaultUpkeepGasLimit, isLogTrigger, false) + + l.Info().Msg("Waiting for all upkeeps to be performed") + + gom := gomega.NewGomegaWithT(t) + gom.Eventually(func(g gomega.Gomega) { + // Check if the upkeeps are performing multiple times by analyzing their counters and checking they are greater than 5 + for i := 0; i < len(upkeepIDs); i++ { + counter, err := consumers[i].Counter(context.Background()) + require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i) + expect := 5 + l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep ID", i).Msg("Number of upkeeps performed") + g.Expect(counter.Int64()).Should(gomega.BeNumerically(">=", int64(expect)), + "Expected consumer counter to be greater than %d, but got %d", expect, counter.Int64()) + } + }, "7m", "1s").Should(gomega.Succeed()) // ~1m for cluster setup, ~3m for performing each upkeep 5 times, ~3m buffer + + l.Info().Msg("All upkeeps performed under happy path. Starting reorg") + + rc, err := NewReorgController( + &ReorgConfig{ + FromPodLabel: reorg.TXNodesAppLabel, + ToPodLabel: reorg.MinerNodesAppLabel, + Network: chainClient, + Env: testEnvironment, + BlockConsensusThreshold: 3, + Timeout: 1800 * time.Second, + }, + ) + + require.NoError(t, err, "Error getting reorg controller") + rc.ReOrg(automationReorgBlocks) + rc.WaitReorgStarted() + + l.Info().Msg("Reorg started. Expecting chain to become unstable and upkeeps to still getting performed") + + gom.Eventually(func(g gomega.Gomega) { + // Check if the upkeeps are performing multiple times by analyzing their counters and checking they reach 10 + for i := 0; i < len(upkeepIDs); i++ { + counter, err := consumers[i].Counter(context.Background()) + require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i) + expect := 10 + l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep ID", i).Msg("Number of upkeeps performed") + g.Expect(counter.Int64()).Should(gomega.BeNumerically(">=", int64(expect)), + "Expected consumer counter to be greater than %d, but got %d", expect, counter.Int64()) + } + }, "5m", "1s").Should(gomega.Succeed()) + + l.Info().Msg("Upkeep performed during unstable chain, waiting for reorg to finish") + rc.WaitDepthReached() + + l.Info().Msg("Reorg finished, chain should be stable now. Expecting upkeeps to keep getting performed") + gom.Eventually(func(g gomega.Gomega) { + // Check if the upkeeps are performing multiple times by analyzing their counters and checking they reach 20 + for i := 0; i < len(upkeepIDs); i++ { + counter, err := consumers[i].Counter(context.Background()) + require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i) + expect := 20 + l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep ID", i).Msg("Number of upkeeps performed") + g.Expect(counter.Int64()).Should(gomega.BeNumerically(">=", int64(expect)), + "Expected consumer counter to be greater than %d, but got %d", expect, counter.Int64()) + } + }, "10m", "1s").Should(gomega.Succeed()) + }) + } } diff --git a/integration-tests/scripts/buildTests b/integration-tests/scripts/buildTests index c487521519..edf4043ce1 100755 --- a/integration-tests/scripts/buildTests +++ b/integration-tests/scripts/buildTests @@ -8,9 +8,7 @@ set -ex # get this scripts directory SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) -cd "$SCRIPT_DIR"/../../ || exit 1 -make test_need_operator_assets -cd ./integration-tests +cd "$SCRIPT_DIR"/../ || exit 1 helm repo update diff --git a/integration-tests/scripts/entrypoint b/integration-tests/scripts/entrypoint index 3955023685..cb5c98fde6 100755 --- a/integration-tests/scripts/entrypoint +++ b/integration-tests/scripts/entrypoint @@ -21,7 +21,9 @@ exit_code=$? echo "Test exit code: ${exit_code}" -if [ $exit_code -eq 2 ]; then # 2 is the code for an interrupted test, we only want to restart the test when the test is interrupted +# 3 is the code for an interrupted test, we only want to restart the test when the test is interrupted and in a state +# that it can recover from. Otherwise we mark the test as "passed" as far as K8s is concerned so it doesn't restart it. +if [ $exit_code -eq 3 ]; then exit 1 # Exiting with non-zero status to trigger pod restart fi diff --git a/integration-tests/smoke/automation_test.go b/integration-tests/smoke/automation_test.go index 0eabac7844..1c5d0c5052 100644 --- a/integration-tests/smoke/automation_test.go +++ b/integration-tests/smoke/automation_test.go @@ -2,8 +2,10 @@ package smoke import ( "context" + "encoding/json" "fmt" "math/big" + "net/http" "os" "strconv" "testing" @@ -16,7 +18,12 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/utils" + + cltypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1" + "github.com/smartcontractkit/chainlink/v2/core/store/models" + + evm21 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evm21" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" @@ -25,9 +32,6 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils" - cltypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1" - "github.com/smartcontractkit/chainlink/v2/core/store/models" ) var utilsABI = cltypes.MustGetABI(automation_utils_2_1.AutomationUtilsABI) @@ -89,6 +93,7 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { "registry_2_0": ethereum.RegistryVersion_2_0, "registry_2_1_conditional": ethereum.RegistryVersion_2_1, "registry_2_1_logtrigger": ethereum.RegistryVersion_2_1, + "registry_2_1_mercury": ethereum.RegistryVersion_2_1, } for n, rv := range registryVersions { @@ -105,18 +110,21 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { testName = "basic-upkeep" ) if nodeUpgrade { - upgradeImage, err = utils.GetEnv("UPGRADE_IMAGE") - require.NoError(t, err, "Error getting upgrade image") - upgradeVersion, err = utils.GetEnv("UPGRADE_VERSION") - require.NoError(t, err, "Error getting upgrade version") + upgradeImage = os.Getenv("UPGRADE_IMAGE") + upgradeVersion = os.Getenv("UPGRADE_VERSION") + if len(upgradeImage) == 0 || len(upgradeVersion) == 0 { + t.Fatal("UPGRADE_IMAGE and UPGRADE_VERSION must be set to upgrade nodes") + } testName = "node-upgrade" } - chainClient, _, contractDeployer, linkToken, registry, registrar, testEnv := setupAutomationTestDocker( - t, testName, registryVersion, defaultOCRRegistryConfig, nodeUpgrade, - ) - // Use the name to determine if this is a log trigger or not + // Use the name to determine if this is a log trigger or mercury isLogTrigger := name == "registry_2_1_logtrigger" + isMercury := name == "registry_2_1_mercury" + + chainClient, _, contractDeployer, linkToken, registry, registrar, testEnv := setupAutomationTestDocker( + t, testName, registryVersion, defaultOCRRegistryConfig, nodeUpgrade, isMercury, + ) consumers, upkeepIDs := actions.DeployConsumers( t, @@ -129,18 +137,27 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { big.NewInt(automationDefaultLinkFunds), automationDefaultUpkeepGasLimit, isLogTrigger, + isMercury, ) - l.Info().Msg("Waiting for all upkeeps to be performed") - gom := gomega.NewGomegaWithT(t) - for i := 0; i < len(upkeepIDs); i++ { - err := consumers[i].Start() - if err != nil { + if err := consumers[i].Start(); err != nil { return } + + if isMercury { + // Set privilege config to enable mercury + privilegeConfigBytes, _ := json.Marshal(evm21.UpkeepPrivilegeConfig{ + MercuryEnabled: true, + }) + if err := registry.SetUpkeepPrivilegeConfig(upkeepIDs[i], privilegeConfigBytes); err != nil { + return + } + } } + l.Info().Msg("Waiting for all upkeeps to be performed") + gom := gomega.NewGomegaWithT(t) startTime := time.Now() // TODO Tune this timeout window after stress testing gom.Eventually(func(g gomega.Gomega) { @@ -161,7 +178,7 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { expect := 5 // Upgrade the nodes one at a time and check that the upkeeps are still being performed for i := 0; i < 5; i++ { - actions.UpgradeChainlinkNodeVersionsLocal(upgradeImage, upgradeVersion, testEnv.CLNodes[i]) + actions.UpgradeChainlinkNodeVersionsLocal(upgradeImage, upgradeVersion, testEnv.ClCluster.Nodes[i]) time.Sleep(time.Second * 10) expect = expect + 5 gom.Eventually(func(g gomega.Gomega) { @@ -215,7 +232,7 @@ func TestSetUpkeepTriggerConfig(t *testing.T) { l := logging.GetTestLogger(t) chainClient, _, contractDeployer, linkToken, registry, registrar, _ := setupAutomationTestDocker( - t, "set-trigger-config", ethereum.RegistryVersion_2_1, defaultOCRRegistryConfig, false, + t, "set-trigger-config", ethereum.RegistryVersion_2_1, defaultOCRRegistryConfig, false, false, ) consumers, upkeepIDs := actions.DeployConsumers( @@ -229,6 +246,7 @@ func TestSetUpkeepTriggerConfig(t *testing.T) { big.NewInt(automationDefaultLinkFunds), automationDefaultUpkeepGasLimit, true, + false, ) // Start log trigger based upkeeps for all consumers @@ -389,10 +407,10 @@ func TestAutomationAddFunds(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() chainClient, _, contractDeployer, linkToken, registry, registrar, _ := setupAutomationTestDocker( - t, "add-funds", registryVersion, defaultOCRRegistryConfig, false, + t, "add-funds", registryVersion, defaultOCRRegistryConfig, false, false, ) - consumers, upkeepIDs := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, defaultAmountOfUpkeeps, big.NewInt(1), automationDefaultUpkeepGasLimit, false) + consumers, upkeepIDs := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, defaultAmountOfUpkeeps, big.NewInt(1), automationDefaultUpkeepGasLimit, false, false) gom := gomega.NewGomegaWithT(t) // Since the upkeep is currently underfunded, check that it doesn't get executed @@ -440,10 +458,10 @@ func TestAutomationPauseUnPause(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) chainClient, _, contractDeployer, linkToken, registry, registrar, _ := setupAutomationTestDocker( - t, "pause-unpause", registryVersion, defaultOCRRegistryConfig, false, + t, "pause-unpause", registryVersion, defaultOCRRegistryConfig, false, false, ) - consumers, upkeepIDs := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, defaultAmountOfUpkeeps, big.NewInt(automationDefaultLinkFunds), automationDefaultUpkeepGasLimit, false) + consumers, upkeepIDs := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, defaultAmountOfUpkeeps, big.NewInt(automationDefaultLinkFunds), automationDefaultUpkeepGasLimit, false, false) gom := gomega.NewGomegaWithT(t) gom.Eventually(func(g gomega.Gomega) { @@ -523,10 +541,10 @@ func TestAutomationRegisterUpkeep(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) chainClient, _, contractDeployer, linkToken, registry, registrar, _ := setupAutomationTestDocker( - t, "register-upkeep", registryVersion, defaultOCRRegistryConfig, false, + t, "register-upkeep", registryVersion, defaultOCRRegistryConfig, false, false, ) - consumers, upkeepIDs := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, defaultAmountOfUpkeeps, big.NewInt(automationDefaultLinkFunds), automationDefaultUpkeepGasLimit, false) + consumers, upkeepIDs := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, defaultAmountOfUpkeeps, big.NewInt(automationDefaultLinkFunds), automationDefaultUpkeepGasLimit, false, false) var initialCounters = make([]*big.Int, len(upkeepIDs)) gom := gomega.NewGomegaWithT(t) @@ -594,10 +612,10 @@ func TestAutomationPauseRegistry(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() chainClient, _, contractDeployer, linkToken, registry, registrar, _ := setupAutomationTestDocker( - t, "pause-registry", registryVersion, defaultOCRRegistryConfig, false, + t, "pause-registry", registryVersion, defaultOCRRegistryConfig, false, false, ) - consumers, upkeepIDs := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, defaultAmountOfUpkeeps, big.NewInt(automationDefaultLinkFunds), automationDefaultUpkeepGasLimit, false) + consumers, upkeepIDs := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, defaultAmountOfUpkeeps, big.NewInt(automationDefaultLinkFunds), automationDefaultUpkeepGasLimit, false, false) gom := gomega.NewGomegaWithT(t) // Observe that the upkeeps which are initially registered are performing @@ -652,10 +670,10 @@ func TestAutomationKeeperNodesDown(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) chainClient, chainlinkNodes, contractDeployer, linkToken, registry, registrar, _ := setupAutomationTestDocker( - t, "keeper-nodes-down", registryVersion, defaultOCRRegistryConfig, false, + t, "keeper-nodes-down", registryVersion, defaultOCRRegistryConfig, false, false, ) - consumers, upkeepIDs := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, defaultAmountOfUpkeeps, big.NewInt(automationDefaultLinkFunds), automationDefaultUpkeepGasLimit, false) + consumers, upkeepIDs := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, defaultAmountOfUpkeeps, big.NewInt(automationDefaultLinkFunds), automationDefaultUpkeepGasLimit, false, false) gom := gomega.NewGomegaWithT(t) nodesWithoutBootstrap := chainlinkNodes[1:] @@ -737,7 +755,7 @@ func TestAutomationPerformSimulation(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() chainClient, _, contractDeployer, linkToken, registry, registrar, _ := setupAutomationTestDocker( - t, "perform-simulation", registryVersion, defaultOCRRegistryConfig, false, + t, "perform-simulation", registryVersion, defaultOCRRegistryConfig, false, false, ) consumersPerformance, _ := actions.DeployPerformanceConsumers( @@ -801,7 +819,7 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) chainClient, chainlinkNodes, contractDeployer, linkToken, registry, registrar, _ := setupAutomationTestDocker( - t, "gas-limit", registryVersion, defaultOCRRegistryConfig, false, + t, "gas-limit", registryVersion, defaultOCRRegistryConfig, false, false, ) consumersPerformance, upkeepIDs := actions.DeployPerformanceConsumers( @@ -880,7 +898,8 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) { highCheckGasLimit := automationDefaultRegistryConfig highCheckGasLimit.CheckGasLimit = uint32(5000000) highCheckGasLimit.RegistryVersion = registryVersion - ocrConfig, err := actions.BuildAutoOCR2ConfigVarsLocal(l, nodesWithoutBootstrap, highCheckGasLimit, registrar.Address(), 30*time.Second) + + ocrConfig, err := actions.BuildAutoOCR2ConfigVarsLocal(l, nodesWithoutBootstrap, highCheckGasLimit, registrar.Address(), 30*time.Second, registry.RegistryOwnerAddress()) require.NoError(t, err, "Error building OCR config") err = registry.SetConfig(highCheckGasLimit, ocrConfig) @@ -914,7 +933,7 @@ func TestUpdateCheckData(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) chainClient, _, contractDeployer, linkToken, registry, registrar, _ := setupAutomationTestDocker( - t, "update-check-data", registryVersion, defaultOCRRegistryConfig, false, + t, "update-check-data", registryVersion, defaultOCRRegistryConfig, false, false, ) performDataChecker, upkeepIDs := actions.DeployPerformDataCheckerConsumers( @@ -979,6 +998,7 @@ func setupAutomationTestDocker( registryVersion ethereum.KeeperRegistryVersion, registryConfig contracts.KeeperRegistrySettings, statefulDb bool, + isMercury bool, ) ( blockchain.EVMClient, []*client.ChainlinkClient, @@ -1005,32 +1025,60 @@ func setupAutomationTestDocker( clNodeConfig.P2P.V2.AnnounceAddresses = &[]string{"0.0.0.0:6690"} clNodeConfig.P2P.V2.ListenAddresses = &[]string{"0.0.0.0:6690"} - secretsConfig := ` - [Mercury.Credentials.cred1] - LegacyURL = 'http://localhost:53299' - URL = 'http://localhost:53299' - Username = 'node' - Password = 'nodepass' - ` - //launch the environment - env, err := test_env.NewCLTestEnvBuilder(). - WithTestLogger(t). - WithGeth(). - WithMockServer(1). - WithCLNodes(5). - WithCLNodeConfig(clNodeConfig). - WithSecretsConfig(secretsConfig). - WithFunding(big.NewFloat(.5)). - Build() - require.NoError(t, err, "Error deploying test environment") - env.ParallelTransactions(true) + var env *test_env.CLClusterTestEnv + var err error + clNodesCount := 5 + if isMercury { + env, err = test_env.NewCLTestEnvBuilder(). + WithTestLogger(t). + WithGeth(). + WithMockAdapter(). + WithFunding(big.NewFloat(.5)). + Build() + require.NoError(t, err, "Error deploying test environment for Mercury") + + secretsConfig := ` + [Mercury.Credentials.cred1] + LegacyURL = '%s' + URL = '%s' + Username = 'node' + Password = 'nodepass'` + secretsConfig = fmt.Sprintf(secretsConfig, env.MockAdapter.InternalEndpoint, env.MockAdapter.InternalEndpoint) + + var httpUrls []string + var wsUrls []string + if network.Simulated { + httpUrls = []string{env.Geth.InternalHttpUrl} + wsUrls = []string{env.Geth.InternalWsUrl} + } else { + httpUrls = network.HTTPURLs + wsUrls = network.URLs + } - txCost, err := env.EVMClient.EstimateCostForChainlinkOperations(1000) - require.NoError(t, err, "Error estimating cost for Chainlink Operations") - nodeClients := env.GetAPIs() + node.SetChainConfig(clNodeConfig, wsUrls, httpUrls, network, false) + + err = env.StartClCluster(clNodeConfig, clNodesCount, secretsConfig) + require.NoError(t, err, "Error starting CL nodes test environment for Mercury") + + output := `{"chainlinkBlob":"0x0001c38d71fed6c320b90e84b6f559459814d068e2a1700adc931ca9717d4fe70000000000000000000000000000000000000000000000000000000001a80b52b4bf1233f9cb71144a253a1791b202113c4ab4a92fa1b176d684b4959666ff8200000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001004254432d5553442d415242495452554d2d544553544e4554000000000000000000000000000000000000000000000000000000000000000000000000645570be000000000000000000000000000000000000000000000000000002af2b818dc5000000000000000000000000000000000000000000000000000002af2426faf3000000000000000000000000000000000000000000000000000002af32dc209700000000000000000000000000000000000000000000000000000000012130f8df0a9745bb6ad5e2df605e158ba8ad8a33ef8a0acf9851f0f01668a3a3f2b68600000000000000000000000000000000000000000000000000000000012130f60000000000000000000000000000000000000000000000000000000000000002c4a7958dce105089cf5edb68dad7dcfe8618d7784eb397f97d5a5fade78c11a58275aebda478968e545f7e3657aba9dcbe8d44605e4c6fde3e24edd5e22c94270000000000000000000000000000000000000000000000000000000000000002459c12d33986018a8959566d145225f0c4a4e61a9a3f50361ccff397899314f0018162cf10cd89897635a0bb62a822355bd199d09f4abe76e4d05261bb44733d"}` + env.MockAdapter.SetStringValuePath("/client", []string{http.MethodGet, http.MethodPost}, map[string]string{"Content-Type": "application/json"}, output) + } else { + env, err = test_env.NewCLTestEnvBuilder(). + WithTestLogger(t). + WithGeth(). + WithMockAdapter(). + WithCLNodes(clNodesCount). + WithCLNodeConfig(clNodeConfig). + WithFunding(big.NewFloat(.5)). + Build() + require.NoError(t, err, "Error deploying test environment") + } + + env.ParallelTransactions(true) + nodeClients := env.ClCluster.NodeAPIs() workerNodes := nodeClients[1:] - err = actions.FundChainlinkNodesLocal(workerNodes, env.EVMClient, txCost) + err = actions.FundChainlinkNodesLocal(workerNodes, env.EVMClient, big.NewFloat(1.0)) require.NoError(t, err, "Error funding Chainlink nodes") linkToken, err := env.ContractDeployer.DeployLinkTokenContract() @@ -1051,7 +1099,7 @@ func setupAutomationTestDocker( err = actions.CreateOCRKeeperJobsLocal(l, nodeClients, registry.Address(), network.ChainID, 0, registryVersion) require.NoError(t, err, "Error creating OCR Keeper Jobs") - ocrConfig, err := actions.BuildAutoOCR2ConfigVarsLocal(l, workerNodes, registryConfig, registrar.Address(), 30*time.Second) + ocrConfig, err := actions.BuildAutoOCR2ConfigVarsLocal(l, workerNodes, registryConfig, registrar.Address(), 30*time.Second, registry.RegistryOwnerAddress()) require.NoError(t, err, "Error building OCR config vars") err = registry.SetConfig(automationDefaultRegistryConfig, ocrConfig) require.NoError(t, err, "Registry config should be set successfully") diff --git a/integration-tests/smoke/automation_test.go_test_list.json b/integration-tests/smoke/automation_test.go_test_list.json index d5311641ce..143dfcd5ed 100644 --- a/integration-tests/smoke/automation_test.go_test_list.json +++ b/integration-tests/smoke/automation_test.go_test_list.json @@ -3,7 +3,7 @@ { "name": "TestAutomationBasic", "label": "ubuntu20.04-32cores-128GB", - "nodes": 3 + "nodes": 4 }, { "name": "TestSetUpkeepTriggerConfig" diff --git a/integration-tests/smoke/cron_test.go b/integration-tests/smoke/cron_test.go index 717ff8db1e..0da9d6461c 100644 --- a/integration-tests/smoke/cron_test.go +++ b/integration-tests/smoke/cron_test.go @@ -2,6 +2,7 @@ package smoke import ( "fmt" + "net/http" "testing" "github.com/google/uuid" @@ -21,28 +22,23 @@ func TestCronBasic(t *testing.T) { env, err := test_env.NewCLTestEnvBuilder(). WithTestLogger(t). WithGeth(). - WithMockServer(1). + WithMockAdapter(). WithCLNodes(1). Build() require.NoError(t, err) - t.Cleanup(func() { - if err := env.Cleanup(t); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - }) - err = env.MockServer.Client.SetValuePath("/variable", 5) - require.NoError(t, err, "Setting value path in mockserver shouldn't fail") + err = env.MockAdapter.SetAdapterBasedIntValuePath("/variable", []string{http.MethodGet, http.MethodPost}, 5) + require.NoError(t, err, "Setting value path in mock adapter shouldn't fail") bta := &client.BridgeTypeAttributes{ Name: fmt.Sprintf("variable-%s", uuid.NewString()), - URL: fmt.Sprintf("%s/variable", env.MockServer.InternalEndpoint), + URL: fmt.Sprintf("%s/variable", env.MockAdapter.InternalEndpoint), RequestData: "{}", } - err = env.CLNodes[0].API.MustCreateBridge(bta) + err = env.ClCluster.Nodes[0].API.MustCreateBridge(bta) require.NoError(t, err, "Creating bridge in chainlink node shouldn't fail") - job, err := env.CLNodes[0].API.MustCreateJob(&client.CronJobSpec{ + job, err := env.ClCluster.Nodes[0].API.MustCreateJob(&client.CronJobSpec{ Schedule: "CRON_TZ=UTC * * * * * *", ObservationSource: client.ObservationSourceSpecBridge(bta), }) @@ -50,7 +46,10 @@ func TestCronBasic(t *testing.T) { gom := gomega.NewGomegaWithT(t) gom.Eventually(func(g gomega.Gomega) { - jobRuns, err := env.CLNodes[0].API.MustReadRunsByJob(job.Data.ID) + jobRuns, err := env.ClCluster.Nodes[0].API.MustReadRunsByJob(job.Data.ID) + if err != nil { + l.Info().Err(err).Msg("error while waiting for job runs") + } g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Reading Job run data shouldn't fail") g.Expect(len(jobRuns.Data)).Should(gomega.BeNumerically(">=", 5), "Expected number of job runs to be greater than 5, but got %d", len(jobRuns.Data)) @@ -58,5 +57,5 @@ func TestCronBasic(t *testing.T) { for _, jr := range jobRuns.Data { g.Expect(jr.Attributes.Errors).Should(gomega.Equal([]interface{}{nil}), "Job run %s shouldn't have errors", jr.ID) } - }, "20m", "3s").Should(gomega.Succeed()) + }, "2m", "3s").Should(gomega.Succeed()) } diff --git a/integration-tests/smoke/flux_test.go b/integration-tests/smoke/flux_test.go index ed907e9e46..a9a9e84811 100644 --- a/integration-tests/smoke/flux_test.go +++ b/integration-tests/smoke/flux_test.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "math/big" + "net/http" "strings" "testing" "time" @@ -27,24 +28,19 @@ func TestFluxBasic(t *testing.T) { env, err := test_env.NewCLTestEnvBuilder(). WithTestLogger(t). WithGeth(). - WithMockServer(1). + WithMockAdapter(). WithCLNodes(3). Build() require.NoError(t, err) - t.Cleanup(func() { - if err := env.Cleanup(t); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - }) - nodeAddresses, err := env.ChainlinkNodeAddresses() + nodeAddresses, err := env.ClCluster.NodeAddresses() require.NoError(t, err, "Retrieving on-chain wallet addresses for chainlink nodes shouldn't fail") env.EVMClient.ParallelTransactions(true) adapterUUID := uuid.NewString() adapterPath := fmt.Sprintf("/variable-%s", adapterUUID) - err = env.MockServer.Client.SetValuePath(adapterPath, 1e5) - require.NoError(t, err, "Setting mockserver value path shouldn't fail") + err = env.MockAdapter.SetAdapterBasedIntValuePath(adapterPath, []string{http.MethodPost}, 1e5) + require.NoError(t, err, "Setting mock adapter value path shouldn't fail") lt, err := actions.DeployLINKToken(env.ContractDeployer) require.NoError(t, err, "Deploying Link Token Contract shouldn't fail") @@ -81,13 +77,13 @@ func TestFluxBasic(t *testing.T) { require.NoError(t, err, "Getting oracle details from the Flux aggregator contract shouldn't fail") l.Info().Str("Oracles", strings.Join(oracles, ",")).Msg("Oracles set") - adapterFullURL := fmt.Sprintf("%s%s", env.MockServer.Client.Config.ClusterURL, adapterPath) + adapterFullURL := fmt.Sprintf("%s%s", env.MockAdapter.InternalEndpoint, adapterPath) l.Info().Str("AdapterFullURL", adapterFullURL).Send() bta := &client.BridgeTypeAttributes{ Name: fmt.Sprintf("variable-%s", adapterUUID), URL: adapterFullURL, } - for i, n := range env.CLNodes { + for i, n := range env.ClCluster.Nodes { err = n.API.MustCreateBridge(bta) require.NoError(t, err, "Creating bridge shouldn't fail for node %d", i+1) @@ -126,7 +122,7 @@ func TestFluxBasic(t *testing.T) { fluxRound = contracts.NewFluxAggregatorRoundConfirmer(fluxInstance, big.NewInt(2), fluxRoundTimeout, l) env.EVMClient.AddHeaderEventSubscription(fluxInstance.Address(), fluxRound) - err = env.MockServer.Client.SetValuePath(adapterPath, 1e10) + err = env.MockAdapter.SetAdapterBasedIntValuePath(adapterPath, []string{http.MethodPost}, 1e10) require.NoError(t, err, "Setting value path in mock server shouldn't fail") err = env.EVMClient.WaitForEvents() require.NoError(t, err, "Waiting for event subscriptions in nodes shouldn't fail") diff --git a/integration-tests/smoke/forwarder_ocr_test.go b/integration-tests/smoke/forwarder_ocr_test.go index f0d20e5245..705ae7cd1a 100644 --- a/integration-tests/smoke/forwarder_ocr_test.go +++ b/integration-tests/smoke/forwarder_ocr_test.go @@ -21,21 +21,16 @@ func TestForwarderOCRBasic(t *testing.T) { env, err := test_env.NewCLTestEnvBuilder(). WithTestLogger(t). WithGeth(). - WithMockServer(1). + WithMockAdapter(). WithForwarders(). WithCLNodes(6). WithFunding(big.NewFloat(.1)). Build() require.NoError(t, err) - t.Cleanup(func() { - if err := env.Cleanup(t); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - }) env.ParallelTransactions(true) - nodeClients := env.GetAPIs() + nodeClients := env.ClCluster.NodeAPIs() bootstrapNode, workerNodes := nodeClients[0], nodeClients[1:] workerNodeAddresses, err := actions.ChainlinkNodeAddressesLocal(workerNodes) @@ -69,19 +64,18 @@ func TestForwarderOCRBasic(t *testing.T) { ) require.NoError(t, err, "Error deploying OCR contracts") - err = actions.CreateOCRJobsWithForwarderLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockServer.Client, env.EVMClient.GetChainID().String()) + err = actions.CreateOCRJobsWithForwarderLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockAdapter, env.EVMClient.GetChainID().String()) require.NoError(t, err, "failed to setup forwarder jobs") err = actions.StartNewRound(1, ocrInstances, env.EVMClient, l) require.NoError(t, err) err = env.EVMClient.WaitForEvents() require.NoError(t, err, "Error waiting for events") - //time.Sleep(999 * time.Second) answer, err := ocrInstances[0].GetLatestAnswer(context.Background()) require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail") require.Equal(t, int64(5), answer.Int64(), "Expected latest answer from OCR contract to be 5 but got %d", answer.Int64()) - err = actions.SetAllAdapterResponsesToTheSameValueLocal(10, ocrInstances, workerNodes, env.MockServer.Client) + err = actions.SetAllAdapterResponsesToTheSameValueLocal(10, ocrInstances, workerNodes, env.MockAdapter) require.NoError(t, err) err = actions.StartNewRound(2, ocrInstances, env.EVMClient, l) require.NoError(t, err) diff --git a/integration-tests/smoke/forwarders_ocr2_test.go b/integration-tests/smoke/forwarders_ocr2_test.go index 48d1d20b4d..be26fd6213 100644 --- a/integration-tests/smoke/forwarders_ocr2_test.go +++ b/integration-tests/smoke/forwarders_ocr2_test.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "math/big" + "net/http" "testing" "time" @@ -25,7 +26,7 @@ func TestForwarderOCR2Basic(t *testing.T) { env, err := test_env.NewCLTestEnvBuilder(). WithTestLogger(t). WithGeth(). - WithMockServer(1). + WithMockAdapter(). WithCLNodeConfig(node.NewConfig(node.NewBaseConfig(), node.WithOCR2(), node.WithP2Pv2(), @@ -35,15 +36,10 @@ func TestForwarderOCR2Basic(t *testing.T) { WithFunding(big.NewFloat(.1)). Build() require.NoError(t, err) - t.Cleanup(func() { - if err := env.Cleanup(t); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - }) env.ParallelTransactions(true) - nodeClients := env.GetAPIs() + nodeClients := env.ClCluster.NodeAPIs() bootstrapNode, workerNodes := nodeClients[0], nodeClients[1:] workerNodeAddresses, err := actions.ChainlinkNodeAddressesLocal(workerNodes) @@ -80,7 +76,7 @@ func TestForwarderOCR2Basic(t *testing.T) { err = env.EVMClient.WaitForEvents() require.NoError(t, err, "Error waiting for events") - err = actions.CreateOCRv2JobsLocal(ocrInstances, bootstrapNode, workerNodes, env.MockServer.Client, "ocr2", 5, env.EVMClient.GetChainID().Uint64(), true) + err = actions.CreateOCRv2JobsLocal(ocrInstances, bootstrapNode, workerNodes, env.MockAdapter, "ocr2", 5, env.EVMClient.GetChainID().Uint64(), true) require.NoError(t, err, "Error creating OCRv2 jobs with forwarders") err = env.EVMClient.WaitForEvents() require.NoError(t, err, "Error waiting for events") @@ -101,7 +97,7 @@ func TestForwarderOCR2Basic(t *testing.T) { for i := 2; i <= 3; i++ { ocrRoundVal := (5 + i) % 10 - err = env.MockServer.Client.SetValuePath("ocr2", ocrRoundVal) + err = env.MockAdapter.SetAdapterBasedIntValuePath("ocr2", []string{http.MethodGet, http.MethodPost}, ocrRoundVal) require.NoError(t, err) err = actions.StartNewOCR2Round(int64(i), ocrInstances, env.EVMClient, time.Minute*10, l) require.NoError(t, err) diff --git a/integration-tests/smoke/keeper_test.go b/integration-tests/smoke/keeper_test.go index 0e4cb7ce04..4f1a4fde14 100644 --- a/integration-tests/smoke/keeper_test.go +++ b/integration-tests/smoke/keeper_test.go @@ -1105,22 +1105,15 @@ func setupKeeperTest(t *testing.T) ( clNodeConfig.Keeper.TurnLookBack = &turnLookBack clNodeConfig.Keeper.Registry.SyncInterval = &syncInterval clNodeConfig.Keeper.Registry.PerformGasOverhead = &performGasOverhead - l := logging.GetTestLogger(t) env, err := test_env.NewCLTestEnvBuilder(). WithTestLogger(t). WithGeth(). - WithMockServer(1). WithCLNodes(5). WithCLNodeConfig(clNodeConfig). WithFunding(big.NewFloat(.5)). Build() require.NoError(t, err, "Error deploying test environment") - t.Cleanup(func() { - if err := env.Cleanup(t); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - }) env.ParallelTransactions(true) @@ -1130,5 +1123,5 @@ func setupKeeperTest(t *testing.T) ( err = env.EVMClient.WaitForEvents() require.NoError(t, err, "Error waiting for events") - return env.EVMClient, env.GetAPIs(), env.ContractDeployer, linkTokenContract, env + return env.EVMClient, env.ClCluster.NodeAPIs(), env.ContractDeployer, linkTokenContract, env } diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go index c6804e48d0..e32d86bef8 100644 --- a/integration-tests/smoke/ocr2_test.go +++ b/integration-tests/smoke/ocr2_test.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "math/big" + "net/http" "strings" "testing" "time" @@ -34,7 +35,7 @@ func TestOCRv2Basic(t *testing.T) { env, err := test_env.NewCLTestEnvBuilder(). WithTestLogger(t). WithGeth(). - WithMockServer(1). + WithMockAdapter(). WithCLNodeConfig(node.NewConfig(node.NewBaseConfig(), node.WithOCR2(), node.WithP2Pv2(), @@ -43,15 +44,10 @@ func TestOCRv2Basic(t *testing.T) { WithFunding(big.NewFloat(.1)). Build() require.NoError(t, err) - t.Cleanup(func() { - if err := env.Cleanup(t); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - }) env.ParallelTransactions(true) - nodeClients := env.GetAPIs() + nodeClients := env.ClCluster.NodeAPIs() bootstrapNode, workerNodes := nodeClients[0], nodeClients[1:] linkToken, err := env.ContractDeployer.DeployLinkTokenContract() @@ -74,7 +70,7 @@ func TestOCRv2Basic(t *testing.T) { aggregatorContracts, err := actions.DeployOCRv2Contracts(1, linkToken, env.ContractDeployer, transmitters, env.EVMClient, ocrOffchainOptions) require.NoError(t, err, "Error deploying OCRv2 aggregator contracts") - err = actions.CreateOCRv2JobsLocal(aggregatorContracts, bootstrapNode, workerNodes, env.MockServer.Client, "ocr2", 5, env.EVMClient.GetChainID().Uint64(), false) + err = actions.CreateOCRv2JobsLocal(aggregatorContracts, bootstrapNode, workerNodes, env.MockAdapter, "ocr2", 5, env.EVMClient.GetChainID().Uint64(), false) require.NoError(t, err, "Error creating OCRv2 jobs") ocrv2Config, err := actions.BuildMedianOCR2ConfigLocal(workerNodes, ocrOffchainOptions) @@ -92,7 +88,7 @@ func TestOCRv2Basic(t *testing.T) { roundData.Answer.Int64(), ) - err = env.MockServer.Client.SetValuePath("ocr2", 10) + err = env.MockAdapter.SetAdapterBasedIntValuePath("ocr2", []string{http.MethodGet, http.MethodPost}, 10) require.NoError(t, err) err = actions.StartNewOCR2Round(2, aggregatorContracts, env.EVMClient, time.Minute*5, l) require.NoError(t, err) diff --git a/integration-tests/smoke/ocr_test.go b/integration-tests/smoke/ocr_test.go index 56d045fa09..cba5935cd0 100644 --- a/integration-tests/smoke/ocr_test.go +++ b/integration-tests/smoke/ocr_test.go @@ -20,20 +20,15 @@ func TestOCRBasic(t *testing.T) { env, err := test_env.NewCLTestEnvBuilder(). WithTestLogger(t). WithGeth(). - WithMockServer(1). + WithMockAdapter(). WithCLNodes(6). WithFunding(big.NewFloat(.1)). Build() require.NoError(t, err) - t.Cleanup(func() { - if err := env.Cleanup(t); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - }) env.ParallelTransactions(true) - nodeClients := env.GetAPIs() + nodeClients := env.ClCluster.NodeAPIs() bootstrapNode, workerNodes := nodeClients[0], nodeClients[1:] linkTokenContract, err := env.ContractDeployer.DeployLinkTokenContract() @@ -44,7 +39,7 @@ func TestOCRBasic(t *testing.T) { err = env.EVMClient.WaitForEvents() require.NoError(t, err, "Error waiting for events") - err = actions.CreateOCRJobsLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockServer.Client, env.EVMClient.GetChainID().String()) + err = actions.CreateOCRJobsLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockAdapter, env.EVMClient.GetChainID().String()) require.NoError(t, err) err = actions.StartNewRound(1, ocrInstances, env.EVMClient, l) @@ -54,7 +49,7 @@ func TestOCRBasic(t *testing.T) { require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail") require.Equal(t, int64(5), answer.Int64(), "Expected latest answer from OCR contract to be 5 but got %d", answer.Int64()) - err = actions.SetAllAdapterResponsesToTheSameValueLocal(10, ocrInstances, workerNodes, env.MockServer.Client) + err = actions.SetAllAdapterResponsesToTheSameValueLocal(10, ocrInstances, workerNodes, env.MockAdapter) require.NoError(t, err) err = actions.StartNewRound(2, ocrInstances, env.EVMClient, l) require.NoError(t, err) diff --git a/integration-tests/smoke/runlog_test.go b/integration-tests/smoke/runlog_test.go index 0bfc41eca7..99d3a4f6c2 100644 --- a/integration-tests/smoke/runlog_test.go +++ b/integration-tests/smoke/runlog_test.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "math/big" + "net/http" "strings" "testing" @@ -24,16 +25,11 @@ func TestRunLogBasic(t *testing.T) { env, err := test_env.NewCLTestEnvBuilder(). WithTestLogger(t). WithGeth(). - WithMockServer(1). + WithMockAdapter(). WithCLNodes(1). WithFunding(big.NewFloat(.1)). Build() require.NoError(t, err) - t.Cleanup(func() { - if err := env.Cleanup(t); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - }) lt, err := env.ContractDeployer.DeployLinkTokenContract() require.NoError(t, err, "Deploying Link Token Contract shouldn't fail") @@ -46,16 +42,16 @@ func TestRunLogBasic(t *testing.T) { err = lt.Transfer(consumer.Address(), big.NewInt(2e18)) require.NoError(t, err, "Transferring %d to consumer contract shouldn't fail", big.NewInt(2e18)) - err = env.MockServer.Client.SetValuePath("/variable", 5) - require.NoError(t, err, "Setting mockserver value path shouldn't fail") + err = env.MockAdapter.SetAdapterBasedIntValuePath("/variable", []string{http.MethodPost}, 5) + require.NoError(t, err, "Setting mock adapter value path shouldn't fail") jobUUID := uuid.New() bta := client.BridgeTypeAttributes{ Name: fmt.Sprintf("five-%s", jobUUID.String()), - URL: fmt.Sprintf("%s/variable", env.MockServer.Client.Config.ClusterURL), + URL: fmt.Sprintf("%s/variable", env.MockAdapter.InternalEndpoint), } - err = env.CLNodes[0].API.MustCreateBridge(&bta) + err = env.ClCluster.Nodes[0].API.MustCreateBridge(&bta) require.NoError(t, err, "Creating bridge shouldn't fail") os := &client.DirectRequestTxPipelineSpec{ @@ -65,7 +61,7 @@ func TestRunLogBasic(t *testing.T) { ost, err := os.String() require.NoError(t, err, "Building observation source spec shouldn't fail") - _, err = env.CLNodes[0].API.MustCreateJob(&client.DirectRequestJobSpec{ + _, err = env.ClCluster.Nodes[0].API.MustCreateJob(&client.DirectRequestJobSpec{ Name: fmt.Sprintf("direct-request-%s", uuid.NewString()), MinIncomingConfirmations: "1", ContractAddress: oracle.Address(), @@ -82,7 +78,7 @@ func TestRunLogBasic(t *testing.T) { oracle.Address(), jobID, big.NewInt(1e18), - fmt.Sprintf("%s/variable", env.MockServer.Client.Config.ClusterURL), + fmt.Sprintf("%s/variable", env.MockAdapter.InternalEndpoint), "data,result", big.NewInt(100), ) diff --git a/integration-tests/smoke/vrf_test.go b/integration-tests/smoke/vrf_test.go index 47f8cd8e30..ba7e2f17a4 100644 --- a/integration-tests/smoke/vrf_test.go +++ b/integration-tests/smoke/vrf_test.go @@ -26,16 +26,10 @@ func TestVRFBasic(t *testing.T) { env, err := test_env.NewCLTestEnvBuilder(). WithTestLogger(t). WithGeth(). - WithMockServer(1). WithCLNodes(1). WithFunding(big.NewFloat(.1)). Build() require.NoError(t, err) - t.Cleanup(func() { - if err := env.Cleanup(t); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - }) env.ParallelTransactions(true) lt, err := actions.DeployLINKToken(env.ContractDeployer) @@ -50,7 +44,7 @@ func TestVRFBasic(t *testing.T) { err = env.EVMClient.WaitForEvents() require.NoError(t, err, "Waiting for event subscriptions in nodes shouldn't fail") - for _, n := range env.CLNodes { + for _, n := range env.ClCluster.Nodes { nodeKey, err := n.API.MustCreateVRFKey() require.NoError(t, err, "Creating VRF key shouldn't fail") l.Debug().Interface("Key JSON", nodeKey).Msg("Created proving key") @@ -94,7 +88,7 @@ func TestVRFBasic(t *testing.T) { gom := gomega.NewGomegaWithT(t) timeout := time.Minute * 2 gom.Eventually(func(g gomega.Gomega) { - jobRuns, err := env.CLNodes[0].API.MustReadRunsByJob(job.Data.ID) + jobRuns, err := env.ClCluster.Nodes[0].API.MustReadRunsByJob(job.Data.ID) g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Job execution shouldn't fail") out, err := contracts.Consumer.RandomnessOutput(context.Background()) diff --git a/integration-tests/smoke/vrfv2_test.go b/integration-tests/smoke/vrfv2_test.go index 18e9efeae4..8d3868f851 100644 --- a/integration-tests/smoke/vrfv2_test.go +++ b/integration-tests/smoke/vrfv2_test.go @@ -29,11 +29,6 @@ func TestVRFv2Basic(t *testing.T) { WithFunding(vrfConst.ChainlinkNodeFundingAmountEth). Build() require.NoError(t, err) - t.Cleanup(func() { - if err := env.Cleanup(t); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - }) env.ParallelTransactions(true) mockFeed, err := actions.DeployMockETHLinkFeed(env.ContractDeployer, vrfConst.LinkEthFeedResponse) @@ -69,18 +64,18 @@ func TestVRFv2Basic(t *testing.T) { err = vrfv2_actions.FundVRFCoordinatorV2Subscription(lt, vrfv2Contracts.Coordinator, env.EVMClient, vrfConst.SubID, vrfConst.VRFSubscriptionFundingAmountLink) require.NoError(t, err) - vrfV2jobs, err := vrfv2_actions.CreateVRFV2Jobs(env.GetAPIs(), vrfv2Contracts.Coordinator, env.EVMClient, vrfConst.MinimumConfirmations) + vrfV2jobs, err := vrfv2_actions.CreateVRFV2Jobs(env.ClCluster.NodeAPIs(), vrfv2Contracts.Coordinator, env.EVMClient, vrfConst.MinimumConfirmations) require.NoError(t, err) // this part is here because VRFv2 can work with only a specific key // [[EVM.KeySpecific]] // Key = '...' - addr, err := env.CLNodes[0].API.PrimaryEthAddress() + addr, err := env.ClCluster.Nodes[0].API.PrimaryEthAddress() require.NoError(t, err) - nodeConfig := node.NewConfig(env.CLNodes[0].NodeConfig, + nodeConfig := node.NewConfig(env.ClCluster.Nodes[0].NodeConfig, node.WithVRFv2EVMEstimator(addr), ) - err = env.CLNodes[0].Restart(nodeConfig) + err = env.ClCluster.Nodes[0].Restart(nodeConfig) require.NoError(t, err) // test and assert @@ -98,7 +93,7 @@ func TestVRFv2Basic(t *testing.T) { timeout := time.Minute * 2 var lastRequestID *big.Int gom.Eventually(func(g gomega.Gomega) { - jobRuns, err := env.CLNodes[0].API.MustReadRunsByJob(vrfV2jobs[0].Job.Data.ID) + jobRuns, err := env.ClCluster.Nodes[0].API.MustReadRunsByJob(vrfV2jobs[0].Job.Data.ID) g.Expect(err).ShouldNot(gomega.HaveOccurred()) g.Expect(len(jobRuns.Data)).Should(gomega.BeNumerically("==", 1)) lastRequestID, err = vrfv2Contracts.LoadTestConsumer.GetLastRequestId(context.Background()) diff --git a/integration-tests/smoke/vrfv2plus_test.go b/integration-tests/smoke/vrfv2plus_test.go index e26a4ed6b1..bb363ed2eb 100644 --- a/integration-tests/smoke/vrfv2plus_test.go +++ b/integration-tests/smoke/vrfv2plus_test.go @@ -6,63 +6,58 @@ import ( "testing" "time" + "github.com/kelseyhightower/envconfig" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_upgraded_version" + "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" - "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus" - "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus/vrfv2plus_constants" + "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2plus/vrfv2plus_config" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" ) -func TestVRFv2PlusBilling(t *testing.T) { +func TestVRFv2Plus(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + var vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig + err := envconfig.Process("VRFV2PLUS", &vrfv2PlusConfig) + require.NoError(t, err) + env, err := test_env.NewCLTestEnvBuilder(). WithTestLogger(t). WithGeth(). WithCLNodes(1). - WithFunding(vrfv2plus_constants.ChainlinkNodeFundingAmountNative). + WithFunding(big.NewFloat(vrfv2PlusConfig.ChainlinkNodeFunding)). Build() require.NoError(t, err, "error creating test env") - t.Cleanup(func() { - if err := env.Cleanup(t); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - }) env.ParallelTransactions(true) - mockETHLinkFeed, err := actions.DeployMockETHLinkFeed(env.ContractDeployer, vrfv2plus_constants.LinkNativeFeedResponse) + mockETHLinkFeed, err := actions.DeployMockETHLinkFeed(env.ContractDeployer, big.NewInt(vrfv2PlusConfig.LinkNativeFeedResponse)) require.NoError(t, err, "error deploying mock ETH/LINK feed") linkToken, err := actions.DeployLINKToken(env.ContractDeployer) require.NoError(t, err, "error deploying LINK contract") - vrfv2PlusContracts, subID, vrfv2PlusData, err := vrfv2plus.SetupVRFV2_5Environment(env, linkToken, mockETHLinkFeed, 1) + vrfv2PlusContracts, subID, vrfv2PlusData, err := vrfv2plus.SetupVRFV2_5Environment(env, vrfv2PlusConfig, linkToken, mockETHLinkFeed, 1) require.NoError(t, err, "error setting up VRF v2_5 env") subscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), subID) require.NoError(t, err, "error getting subscription information") - l.Debug(). - Str("Juels Balance", subscription.Balance.String()). - Str("Native Token Balance", subscription.NativeBalance.String()). - Str("Subscription ID", subID.String()). - Str("Subscription Owner", subscription.Owner.String()). - Interface("Subscription Consumers", subscription.Consumers). - Msg("Subscription Data") + vrfv2plus.LogSubDetails(l, subscription, subID, vrfv2PlusContracts.Coordinator) t.Run("VRFV2 Plus With Link Billing", func(t *testing.T) { var isNativeBilling = false subBalanceBeforeRequest := subscription.Balance - jobRunsBeforeTest, err := env.CLNodes[0].API.MustReadRunsByJob(vrfv2PlusData.VRFJob.Data.ID) + jobRunsBeforeTest, err := env.ClCluster.Nodes[0].API.MustReadRunsByJob(vrfv2PlusData.VRFJob.Data.ID) require.NoError(t, err, "error reading job runs") // test and assert @@ -72,6 +67,7 @@ func TestVRFv2PlusBilling(t *testing.T) { vrfv2PlusData, subID, isNativeBilling, + vrfv2PlusConfig, l, ) require.NoError(t, err, "error requesting randomness and waiting for fulfilment") @@ -82,7 +78,7 @@ func TestVRFv2PlusBilling(t *testing.T) { subBalanceAfterRequest := subscription.Balance require.Equal(t, expectedSubBalanceJuels, subBalanceAfterRequest) - jobRuns, err := env.CLNodes[0].API.MustReadRunsByJob(vrfv2PlusData.VRFJob.Data.ID) + jobRuns, err := env.ClCluster.Nodes[0].API.MustReadRunsByJob(vrfv2PlusData.VRFJob.Data.ID) require.NoError(t, err, "error reading job runs") require.Equal(t, len(jobRunsBeforeTest.Data)+1, len(jobRuns.Data)) @@ -91,7 +87,7 @@ func TestVRFv2PlusBilling(t *testing.T) { require.True(t, status.Fulfilled) l.Debug().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") - require.Equal(t, vrfv2plus_constants.NumberOfWords, uint32(len(status.RandomWords))) + require.Equal(t, vrfv2PlusConfig.NumberOfWords, uint32(len(status.RandomWords))) for _, w := range status.RandomWords { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") @@ -102,7 +98,7 @@ func TestVRFv2PlusBilling(t *testing.T) { var isNativeBilling = true subNativeTokenBalanceBeforeRequest := subscription.NativeBalance - jobRunsBeforeTest, err := env.CLNodes[0].API.MustReadRunsByJob(vrfv2PlusData.VRFJob.Data.ID) + jobRunsBeforeTest, err := env.ClCluster.Nodes[0].API.MustReadRunsByJob(vrfv2PlusData.VRFJob.Data.ID) require.NoError(t, err, "error reading job runs") // test and assert @@ -112,6 +108,7 @@ func TestVRFv2PlusBilling(t *testing.T) { vrfv2PlusData, subID, isNativeBilling, + vrfv2PlusConfig, l, ) require.NoError(t, err, "error requesting randomness and waiting for fulfilment") @@ -121,7 +118,7 @@ func TestVRFv2PlusBilling(t *testing.T) { subBalanceAfterRequest := subscription.NativeBalance require.Equal(t, expectedSubBalanceWei, subBalanceAfterRequest) - jobRuns, err := env.CLNodes[0].API.MustReadRunsByJob(vrfv2PlusData.VRFJob.Data.ID) + jobRuns, err := env.ClCluster.Nodes[0].API.MustReadRunsByJob(vrfv2PlusData.VRFJob.Data.ID) require.NoError(t, err, "error reading job runs") require.Equal(t, len(jobRunsBeforeTest.Data)+1, len(jobRuns.Data)) @@ -130,7 +127,7 @@ func TestVRFv2PlusBilling(t *testing.T) { require.True(t, status.Fulfilled) l.Debug().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") - require.Equal(t, vrfv2plus_constants.NumberOfWords, uint32(len(status.RandomWords))) + require.Equal(t, vrfv2PlusConfig.NumberOfWords, uint32(len(status.RandomWords))) for _, w := range status.RandomWords { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") @@ -139,6 +136,7 @@ func TestVRFv2PlusBilling(t *testing.T) { wrapperContracts, wrapperSubID, err := vrfv2plus.SetupVRFV2PlusWrapperEnvironment( env, + vrfv2PlusConfig, linkToken, mockETHLinkFeed, vrfv2PlusContracts.Coordinator, @@ -163,6 +161,7 @@ func TestVRFv2PlusBilling(t *testing.T) { vrfv2PlusData, wrapperSubID, isNativeBilling, + vrfv2PlusConfig, l, ) require.NoError(t, err, "error requesting randomness and waiting for fulfilment") @@ -185,20 +184,9 @@ func TestVRFv2PlusBilling(t *testing.T) { //todo: uncomment when VRF-651 will be fixed //require.Equal(t, 1, consumerStatus.Paid.Cmp(randomWordsFulfilledEvent.Payment), "Expected Consumer contract pay more than the Coordinator Sub") - l.Debug(). - Str("Consumer Balance Before Request (Juels)", wrapperConsumerJuelsBalanceBeforeRequest.String()). - Str("Consumer Balance After Request (Juels)", wrapperConsumerJuelsBalanceAfterRequest.String()). - Bool("Fulfilment Status", consumerStatus.Fulfilled). - Str("Paid in Juels by Consumer Contract", consumerStatus.Paid.String()). - Str("Paid in Juels by Coordinator Sub", randomWordsFulfilledEvent.Payment.String()). - Str("RequestTimestamp", consumerStatus.RequestTimestamp.String()). - Str("FulfilmentTimestamp", consumerStatus.FulfilmentTimestamp.String()). - Str("RequestBlockNumber", consumerStatus.RequestBlockNumber.String()). - Str("FulfilmentBlockNumber", consumerStatus.FulfilmentBlockNumber.String()). - Str("TX Hash", randomWordsFulfilledEvent.Raw.TxHash.String()). - Msg("Random Words Request Fulfilment Status") - - require.Equal(t, vrfv2plus_constants.NumberOfWords, uint32(len(consumerStatus.RandomWords))) + vrfv2plus.LogFulfillmentDetailsLinkBilling(l, wrapperConsumerJuelsBalanceBeforeRequest, wrapperConsumerJuelsBalanceAfterRequest, consumerStatus, randomWordsFulfilledEvent) + + require.Equal(t, vrfv2PlusConfig.NumberOfWords, uint32(len(consumerStatus.RandomWords))) for _, w := range consumerStatus.RandomWords { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") @@ -221,6 +209,7 @@ func TestVRFv2PlusBilling(t *testing.T) { vrfv2PlusData, wrapperSubID, isNativeBilling, + vrfv2PlusConfig, l, ) require.NoError(t, err, "error requesting randomness and waiting for fulfilment") @@ -243,20 +232,9 @@ func TestVRFv2PlusBilling(t *testing.T) { //todo: uncomment when VRF-651 will be fixed //require.Equal(t, 1, consumerStatus.Paid.Cmp(randomWordsFulfilledEvent.Payment), "Expected Consumer contract pay more than the Coordinator Sub") - l.Debug(). - Str("Consumer Balance Before Request (WEI)", wrapperConsumerBalanceBeforeRequestWei.String()). - Str("Consumer Balance After Request (WEI)", wrapperConsumerBalanceAfterRequestWei.String()). - Bool("Fulfilment Status", consumerStatus.Fulfilled). - Str("Paid in Juels by Consumer Contract", consumerStatus.Paid.String()). - Str("Paid in Juels by Coordinator Sub", randomWordsFulfilledEvent.Payment.String()). - Str("RequestTimestamp", consumerStatus.RequestTimestamp.String()). - Str("FulfilmentTimestamp", consumerStatus.FulfilmentTimestamp.String()). - Str("RequestBlockNumber", consumerStatus.RequestBlockNumber.String()). - Str("FulfilmentBlockNumber", consumerStatus.FulfilmentBlockNumber.String()). - Str("TX Hash", randomWordsFulfilledEvent.Raw.TxHash.String()). - Msg("Random Words Request Fulfilment Status") - - require.Equal(t, vrfv2plus_constants.NumberOfWords, uint32(len(consumerStatus.RandomWords))) + vrfv2plus.LogFulfillmentDetailsNativeBilling(l, wrapperConsumerBalanceBeforeRequestWei, wrapperConsumerBalanceAfterRequestWei, consumerStatus, randomWordsFulfilledEvent) + + require.Equal(t, vrfv2PlusConfig.NumberOfWords, uint32(len(consumerStatus.RandomWords))) for _, w := range consumerStatus.RandomWords { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") @@ -264,44 +242,36 @@ func TestVRFv2PlusBilling(t *testing.T) { }) } + func TestVRFv2PlusMigration(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) + var vrfv2PlusConfig vrfv2plus_config.VRFV2PlusConfig + err := envconfig.Process("VRFV2PLUS", &vrfv2PlusConfig) + require.NoError(t, err) env, err := test_env.NewCLTestEnvBuilder(). WithTestLogger(t). WithGeth(). WithCLNodes(1). - WithFunding(vrfv2plus_constants.ChainlinkNodeFundingAmountNative). + WithFunding(big.NewFloat(vrfv2PlusConfig.ChainlinkNodeFunding)). Build() require.NoError(t, err, "error creating test env") - t.Cleanup(func() { - if err := env.Cleanup(t); err != nil { - l.Error().Err(err).Msg("Error cleaning up test environment") - } - }) - env.ParallelTransactions(true) - mockETHLinkFeedAddress, err := actions.DeployMockETHLinkFeed(env.ContractDeployer, vrfv2plus_constants.LinkNativeFeedResponse) + mockETHLinkFeedAddress, err := actions.DeployMockETHLinkFeed(env.ContractDeployer, big.NewInt(vrfv2PlusConfig.LinkNativeFeedResponse)) require.NoError(t, err, "error deploying mock ETH/LINK feed") linkAddress, err := actions.DeployLINKToken(env.ContractDeployer) require.NoError(t, err, "error deploying LINK contract") - vrfv2PlusContracts, subID, vrfv2PlusData, err := vrfv2plus.SetupVRFV2_5Environment(env, linkAddress, mockETHLinkFeedAddress, 2) + vrfv2PlusContracts, subID, vrfv2PlusData, err := vrfv2plus.SetupVRFV2_5Environment(env, vrfv2PlusConfig, linkAddress, mockETHLinkFeedAddress, 2) require.NoError(t, err, "error setting up VRF v2_5 env") subscription, err := vrfv2PlusContracts.Coordinator.GetSubscription(context.Background(), subID) require.NoError(t, err, "error getting subscription information") - l.Debug(). - Str("Juels Balance", subscription.Balance.String()). - Str("Native Token Balance", subscription.NativeBalance.String()). - Str("Subscription ID", subID.String()). - Str("Subscription Owner", subscription.Owner.String()). - Interface("Subscription Consumers", subscription.Consumers). - Msg("Subscription Data") + vrfv2plus.LogSubDetails(l, subscription, subID, vrfv2PlusContracts.Coordinator) activeSubIdsOldCoordinatorBeforeMigration, err := vrfv2PlusContracts.Coordinator.GetActiveSubscriptionIds(context.Background(), big.NewInt(0), big.NewInt(0)) require.NoError(t, err, "error occurred getting active sub ids") @@ -322,12 +292,15 @@ func TestVRFv2PlusMigration(t *testing.T) { require.NoError(t, err, errors.Wrap(err, vrfv2plus.ErrRegisteringProvingKey)) err = newCoordinator.SetConfig( - vrfv2plus_constants.MinimumConfirmations, - vrfv2plus_constants.MaxGasLimitVRFCoordinatorConfig, - vrfv2plus_constants.StalenessSeconds, - vrfv2plus_constants.GasAfterPaymentCalculation, - vrfv2plus_constants.LinkNativeFeedResponse, - vrfv2plus_constants.VRFCoordinatorV2PlusUpgradedVersionFeeConfig, + vrfv2PlusConfig.MinimumConfirmations, + vrfv2PlusConfig.MaxGasLimitCoordinatorConfig, + vrfv2PlusConfig.StalenessSeconds, + vrfv2PlusConfig.GasAfterPaymentCalculation, + big.NewInt(vrfv2PlusConfig.LinkNativeFeedResponse), + vrf_v2plus_upgraded_version.VRFCoordinatorV2PlusUpgradedVersionFeeConfig{ + FulfillmentFlatFeeLinkPPM: vrfv2PlusConfig.FulfillmentFlatFeeLinkPPM, + FulfillmentFlatFeeNativePPM: vrfv2PlusConfig.FulfillmentFlatFeeNativePPM, + }, ) err = newCoordinator.SetLINKAndLINKNativeFeed(linkAddress.Address(), mockETHLinkFeedAddress.Address()) @@ -336,12 +309,12 @@ func TestVRFv2PlusMigration(t *testing.T) { require.NoError(t, err, vrfv2plus.ErrWaitTXsComplete) _, err = vrfv2plus.CreateVRFV2PlusJob( - env.GetAPIs()[0], + env.ClCluster.NodeAPIs()[0], newCoordinator.Address(), vrfv2PlusData.PrimaryEthAddress, vrfv2PlusData.VRFKey.Data.ID, vrfv2PlusData.ChainID.String(), - vrfv2plus_constants.MinimumConfirmations, + vrfv2PlusConfig.MinimumConfirmations, ) require.NoError(t, err, vrfv2plus.ErrCreateVRFV2PlusJobs) @@ -367,11 +340,7 @@ func TestVRFv2PlusMigration(t *testing.T) { err = env.EVMClient.WaitForEvents() require.NoError(t, err, vrfv2plus.ErrWaitTXsComplete) - l.Debug(). - Str("Subscription ID", migrationCompletedEvent.SubId.String()). - Str("Migrated From Coordinator", vrfv2PlusContracts.Coordinator.Address()). - Str("Migrated To Coordinator", migrationCompletedEvent.NewCoordinator.String()). - Msg("MigrationCompleted Event") + vrfv2plus.LogMigrationCompletedEvent(l, migrationCompletedEvent, vrfv2PlusContracts) oldCoordinatorLinkTotalBalanceAfterMigration, oldCoordinatorEthTotalBalanceAfterMigration, err := vrfv2plus.GetCoordinatorTotalBalance(vrfv2PlusContracts.Coordinator) require.NoError(t, err) @@ -382,14 +351,7 @@ func TestVRFv2PlusMigration(t *testing.T) { migratedSubscription, err := newCoordinator.GetSubscription(context.Background(), subID) require.NoError(t, err, "error getting subscription information") - l.Debug(). - Str("New Coordinator", newCoordinator.Address()). - Str("Subscription ID", subID.String()). - Str("Juels Balance", migratedSubscription.Balance.String()). - Str("Native Token Balance", migratedSubscription.NativeBalance.String()). - Str("Subscription Owner", migratedSubscription.Owner.String()). - Interface("Subscription Consumers", migratedSubscription.Consumers). - Msg("Subscription Data After Migration to New Coordinator") + vrfv2plus.LogSubDetailsAfterMigration(l, newCoordinator, subID, migratedSubscription) //Verify that Coordinators were updated in Consumers for _, consumer := range vrfv2PlusContracts.LoadTestConsumers { @@ -438,6 +400,7 @@ func TestVRFv2PlusMigration(t *testing.T) { vrfv2PlusData, subID, false, + vrfv2PlusConfig, l, ) require.NoError(t, err, "error requesting randomness and waiting for fulfilment") @@ -449,6 +412,7 @@ func TestVRFv2PlusMigration(t *testing.T) { vrfv2PlusData, subID, true, + vrfv2PlusConfig, l, ) require.NoError(t, err, "error requesting randomness and waiting for fulfilment") diff --git a/integration-tests/testsetups/keeper_benchmark.go b/integration-tests/testsetups/keeper_benchmark.go index ba0cc23b23..0cc3d98437 100644 --- a/integration-tests/testsetups/keeper_benchmark.go +++ b/integration-tests/testsetups/keeper_benchmark.go @@ -5,6 +5,9 @@ import ( "fmt" "math" "math/big" + "os" + "os/signal" + "syscall" "testing" "time" @@ -13,6 +16,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" + "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/slack-go/slack" "github.com/stretchr/testify/require" @@ -41,6 +45,10 @@ type KeeperBenchmarkTest struct { Inputs KeeperBenchmarkTestInputs TestReporter testreporters.KeeperBenchmarkTestReporter + t *testing.T + log zerolog.Logger + startingBlock *big.Int + keeperRegistries []contracts.KeeperRegistry keeperRegistrars []contracts.KeeperRegistrar keeperConsumerContracts []contracts.AutomationConsumerBenchmark @@ -57,6 +65,7 @@ type KeeperBenchmarkTest struct { gasFeed contracts.MockGasFeed } +// UpkeepConfig dictates details of how the test's upkeep contracts should be called and configured type UpkeepConfig struct { NumberOfUpkeeps int // Number of upkeep contracts BlockRange int64 // How many blocks to run the test for @@ -67,6 +76,8 @@ type UpkeepConfig struct { FirstEligibleBuffer int64 // How many blocks to add to randomised first eligible block, set to 0 to disable randomised first eligible block } +// PreDeployedContracts are contracts that are already deployed on a (usually) live testnet chain, so re-deployment +// in unnecessary type PreDeployedContracts struct { RegistryAddress string RegistrarAddress string @@ -92,18 +103,19 @@ type KeeperBenchmarkTestInputs struct { } // NewKeeperBenchmarkTest prepares a new keeper benchmark test to be run -func NewKeeperBenchmarkTest(inputs KeeperBenchmarkTestInputs) *KeeperBenchmarkTest { +func NewKeeperBenchmarkTest(t *testing.T, inputs KeeperBenchmarkTestInputs) *KeeperBenchmarkTest { return &KeeperBenchmarkTest{ Inputs: inputs, + t: t, + log: logging.GetTestLogger(t), } } // Setup prepares contracts for the test -func (k *KeeperBenchmarkTest) Setup(t *testing.T, env *environment.Environment) { - l := logging.GetTestLogger(t) +func (k *KeeperBenchmarkTest) Setup(env *environment.Environment) { startTime := time.Now() k.TestReporter.Summary.StartTime = startTime.UnixMilli() - k.ensureInputValues(t) + k.ensureInputValues() k.env = env k.namespace = k.env.Cfg.Namespace inputs := k.Inputs @@ -112,70 +124,65 @@ func (k *KeeperBenchmarkTest) Setup(t *testing.T, env *environment.Environment) k.keeperRegistrars = make([]contracts.KeeperRegistrar, len(inputs.RegistryVersions)) k.keeperConsumerContracts = make([]contracts.AutomationConsumerBenchmark, len(inputs.RegistryVersions)) k.upkeepIDs = make([][]*big.Int, len(inputs.RegistryVersions)) - l.Debug().Interface("TestInputs", inputs).Msg("Setting up benchmark test") + k.log.Debug().Interface("TestInputs", inputs).Msg("Setting up benchmark test") var err error // Connect to networks and prepare for contract deployment - k.contractDeployer, err = contracts.NewContractDeployer(k.chainClient, l) - require.NoError(t, err, "Building a new contract deployer shouldn't fail") + k.contractDeployer, err = contracts.NewContractDeployer(k.chainClient, k.log) + require.NoError(k.t, err, "Building a new contract deployer shouldn't fail") k.chainlinkNodes, err = client.ConnectChainlinkNodes(k.env) - require.NoError(t, err, "Connecting to chainlink nodes shouldn't fail") + require.NoError(k.t, err, "Connecting to chainlink nodes shouldn't fail") k.chainClient.ParallelTransactions(true) if len(inputs.RegistryVersions) > 1 && !inputs.ForceSingleTxnKey { for nodeIndex, node := range k.chainlinkNodes { for registryIndex := 1; registryIndex < len(inputs.RegistryVersions); registryIndex++ { - l.Debug().Str("URL", node.URL()).Int("NodeIndex", nodeIndex).Int("RegistryIndex", registryIndex).Msg("Create Tx key") + k.log.Debug().Str("URL", node.URL()).Int("NodeIndex", nodeIndex).Int("RegistryIndex", registryIndex).Msg("Create Tx key") _, _, err := node.CreateTxKey("evm", k.Inputs.BlockchainClient.GetChainID().String()) - require.NoError(t, err, "Creating transaction key shouldn't fail") + require.NoError(k.t, err, "Creating transaction key shouldn't fail") } } } - var () - c := inputs.Contracts if common.IsHexAddress(c.LinkTokenAddress) { k.linkToken, err = k.contractDeployer.LoadLinkToken(common.HexToAddress(c.LinkTokenAddress)) - require.NoError(t, err, "Loading Link Token Contract shouldn't fail") + require.NoError(k.t, err, "Loading Link Token Contract shouldn't fail") } else { k.linkToken, err = k.contractDeployer.DeployLinkTokenContract() - require.NoError(t, err, "Deploying Link Token Contract shouldn't fail") + require.NoError(k.t, err, "Deploying Link Token Contract shouldn't fail") err = k.chainClient.WaitForEvents() - require.NoError(t, err, "Failed waiting for LINK Contract deployment") + require.NoError(k.t, err, "Failed waiting for LINK Contract deployment") } if common.IsHexAddress(c.EthFeedAddress) { k.ethFeed, err = k.contractDeployer.LoadETHLINKFeed(common.HexToAddress(c.EthFeedAddress)) - require.NoError(t, err, "Loading ETH-Link feed Contract shouldn't fail") + require.NoError(k.t, err, "Loading ETH-Link feed Contract shouldn't fail") } else { k.ethFeed, err = k.contractDeployer.DeployMockETHLINKFeed(big.NewInt(2e18)) - require.NoError(t, err, "Deploying mock ETH-Link feed shouldn't fail") + require.NoError(k.t, err, "Deploying mock ETH-Link feed shouldn't fail") err = k.chainClient.WaitForEvents() - require.NoError(t, err, "Failed waiting for ETH-Link feed Contract deployment") + require.NoError(k.t, err, "Failed waiting for ETH-Link feed Contract deployment") } if common.IsHexAddress(c.GasFeedAddress) { k.gasFeed, err = k.contractDeployer.LoadGasFeed(common.HexToAddress(c.GasFeedAddress)) - require.NoError(t, err, "Loading Gas feed Contract shouldn't fail") + require.NoError(k.t, err, "Loading Gas feed Contract shouldn't fail") } else { k.gasFeed, err = k.contractDeployer.DeployMockGasFeed(big.NewInt(2e11)) - require.NoError(t, err, "Deploying mock gas feed shouldn't fail") + require.NoError(k.t, err, "Deploying mock gas feed shouldn't fail") err = k.chainClient.WaitForEvents() - require.NoError(t, err, "Failed waiting for mock gas feed Contract deployment") + require.NoError(k.t, err, "Failed waiting for mock gas feed Contract deployment") } err = k.chainClient.WaitForEvents() - require.NoError(t, err, "Failed waiting for mock feeds to deploy") + require.NoError(k.t, err, "Failed waiting for mock feeds to deploy") for index := range inputs.RegistryVersions { - l.Info().Int("Index", index).Msg("Starting Test Setup") + k.log.Info().Int("Index", index).Msg("Starting Test Setup") - k.DeployBenchmarkKeeperContracts( - t, - index, - ) + k.DeployBenchmarkKeeperContracts(index) } var keysToFund = inputs.RegistryVersions @@ -190,19 +197,18 @@ func (k *KeeperBenchmarkTest) Setup(t *testing.T, env *environment.Environment) nodesToFund = k.chainlinkNodes[1:] } err = actions.FundChainlinkNodesAddress(nodesToFund, k.chainClient, k.Inputs.ChainlinkNodeFunding, index) - require.NoError(t, err, "Funding Chainlink nodes shouldn't fail") + require.NoError(k.t, err, "Funding Chainlink nodes shouldn't fail") } - l.Info().Str("Setup Time", time.Since(startTime).String()).Msg("Finished Keeper Benchmark Test Setup") + k.log.Info().Str("Setup Time", time.Since(startTime).String()).Msg("Finished Keeper Benchmark Test Setup") err = k.SendSlackNotification(nil) if err != nil { - l.Warn().Msg("Sending test start slack notification failed") + k.log.Warn().Msg("Sending test start slack notification failed") } } // Run runs the keeper benchmark test -func (k *KeeperBenchmarkTest) Run(t *testing.T) { - l := logging.GetTestLogger(t) +func (k *KeeperBenchmarkTest) Run() { u := k.Inputs.Upkeeps k.TestReporter.Summary.Load.TotalCheckGasPerBlock = int64(u.NumberOfUpkeeps) * u.CheckGasToBurn k.TestReporter.Summary.Load.TotalPerformGasPerBlock = int64((float64(u.NumberOfUpkeeps) / @@ -223,6 +229,9 @@ func (k *KeeperBenchmarkTest) Run(t *testing.T) { "NumberOfRegistries": len(k.keeperRegistries), } inputs := k.Inputs + startingBlock, err := k.chainClient.LatestBlockNumber(context.Background()) + require.NoError(k.t, err, "Error getting latest block number") + k.startingBlock = big.NewInt(0).SetUint64(startingBlock) startTime := time.Now() nodesWithoutBootstrap := k.chainlinkNodes[1:] @@ -234,22 +243,22 @@ func (k *KeeperBenchmarkTest) Run(t *testing.T) { txKeyId = 0 } ocrConfig, err := actions.BuildAutoOCR2ConfigVarsWithKeyIndex( - t, nodesWithoutBootstrap, *inputs.KeeperRegistrySettings, k.keeperRegistrars[rIndex].Address(), k.Inputs.DeltaStage, txKeyId, + k.t, nodesWithoutBootstrap, *inputs.KeeperRegistrySettings, k.keeperRegistrars[rIndex].Address(), k.Inputs.DeltaStage, txKeyId, common.Address{}, ) - require.NoError(t, err, "Building OCR config shouldn't fail") + require.NoError(k.t, err, "Building OCR config shouldn't fail") // Send keeper jobs to registry and chainlink nodes if inputs.RegistryVersions[rIndex] == ethereum.RegistryVersion_2_0 || inputs.RegistryVersions[rIndex] == ethereum.RegistryVersion_2_1 { - actions.CreateOCRKeeperJobs(t, k.chainlinkNodes, k.keeperRegistries[rIndex].Address(), k.chainClient.GetChainID().Int64(), txKeyId, inputs.RegistryVersions[rIndex]) + actions.CreateOCRKeeperJobs(k.t, k.chainlinkNodes, k.keeperRegistries[rIndex].Address(), k.chainClient.GetChainID().Int64(), txKeyId, inputs.RegistryVersions[rIndex]) err = k.keeperRegistries[rIndex].SetConfig(*inputs.KeeperRegistrySettings, ocrConfig) - require.NoError(t, err, "Registry config should be be set successfully") + require.NoError(k.t, err, "Registry config should be be set successfully") // Give time for OCR nodes to bootstrap time.Sleep(1 * time.Minute) } else { - actions.CreateKeeperJobsWithKeyIndex(t, k.chainlinkNodes, k.keeperRegistries[rIndex], txKeyId, ocrConfig, k.chainClient.GetChainID().String()) + actions.CreateKeeperJobsWithKeyIndex(k.t, k.chainlinkNodes, k.keeperRegistries[rIndex], txKeyId, ocrConfig, k.chainClient.GetChainID().String()) } err = k.chainClient.WaitForEvents() - require.NoError(t, err, "Error waiting for registry setConfig") + require.NoError(k.t, err, "Error waiting for registry setConfig") } for rIndex := range k.keeperRegistries { @@ -264,7 +273,7 @@ func (k *KeeperBenchmarkTest) Run(t *testing.T) { &k.TestReporter, int64(index), inputs.Upkeeps.FirstEligibleBuffer, - l, + k.log, ), ) } @@ -275,32 +284,83 @@ func (k *KeeperBenchmarkTest) Run(t *testing.T) { k.chainClient.DeleteHeaderEventSubscription(fmt.Sprintf("Keeper Tracker %d %d", rIndex, index)) } } - }() - logSubscriptionStop := make(chan bool) + + // Main test loop + k.observeUpkeepEvents() + err = k.chainClient.WaitForEvents() + require.NoError(k.t, err, "Error waiting for keeper subscriptions") + + // Collect logs for each registry to calculate test metrics + registryLogs := make([][]types.Log, len(k.keeperRegistries)) + for rIndex := range k.keeperRegistries { + var ( + logs []types.Log + timeout = 5 * time.Second + addr = k.keeperRegistries[rIndex].Address() + filterQuery = geth.FilterQuery{ + Addresses: []common.Address{common.HexToAddress(addr)}, + FromBlock: k.startingBlock, + } + err = fmt.Errorf("initial error") // to ensure our for loop runs at least once + ) + for err != nil { // This RPC call can possibly time out or otherwise die. Failure is not an option, keep retrying to get our stats. + ctx, cancel := context.WithTimeout(context.Background(), timeout) + logs, err = k.chainClient.FilterLogs(ctx, filterQuery) + cancel() + if err != nil { + k.log.Error().Err(err). + Interface("Filter Query", filterQuery). + Str("Timeout", timeout.String()). + Msg("Error getting logs from chain, trying again") + } else { + k.log.Info().Int("Log Count", len(logs)).Str("Registry Address", addr).Msg("Collected logs") + } + } + registryLogs[rIndex] = logs + } + + // Count reverts and stale upkeeps for rIndex := range k.keeperRegistries { - k.subscribeToUpkeepPerformedEvent(t, logSubscriptionStop, &k.TestReporter, rIndex) + contractABI := k.contractABI(rIndex) + for _, l := range registryLogs[rIndex] { + log := l + eventDetails, err := contractABI.EventByID(log.Topics[0]) + if err != nil { + k.log.Error().Err(err).Str("Log Hash", log.TxHash.Hex()).Msg("Error getting event details for log, report data inaccurate") + break + } + if eventDetails.Name == "UpkeepPerformed" { + parsedLog, err := k.keeperRegistries[rIndex].ParseUpkeepPerformedLog(&log) + if err != nil { + k.log.Error().Err(err).Str("Log Hash", log.TxHash.Hex()).Msg("Error parsing upkeep performed log, report data inaccurate") + break + } + if !parsedLog.Success { + k.TestReporter.NumRevertedUpkeeps++ + } + } else if eventDetails.Name == "StaleUpkeepReport" { + k.TestReporter.NumStaleUpkeepReports++ + } + } } - err := k.chainClient.WaitForEvents() - require.NoError(t, err, "Error waiting for keeper subscriptions") - close(logSubscriptionStop) for _, chainlinkNode := range k.chainlinkNodes { txData, err := chainlinkNode.MustReadTransactionAttempts() if err != nil { - l.Error().Err(err).Msg("Error reading transaction attempts from Chainlink Node") + k.log.Error().Err(err).Msg("Error reading transaction attempts from Chainlink Node") } k.TestReporter.AttemptedChainlinkTransactions = append(k.TestReporter.AttemptedChainlinkTransactions, txData) } k.TestReporter.Summary.Config.Chainlink, err = k.env.ResourcesSummary("app=chainlink-0") if err != nil { - l.Error().Err(err).Msg("Error getting resource summary of chainlink node") + k.log.Error().Err(err).Msg("Error getting resource summary of chainlink node") } k.TestReporter.Summary.Config.Geth, err = k.env.ResourcesSummary("app=geth") if err != nil && k.Inputs.BlockchainClient.NetworkSimulated() { - l.Error().Err(err).Msg("Error getting resource summary of geth node") + k.log.Error().Err(err).Msg("Error getting resource summary of geth node") } endTime := time.Now() @@ -309,139 +369,178 @@ func (k *KeeperBenchmarkTest) Run(t *testing.T) { for rIndex := range k.keeperRegistries { if inputs.DeleteJobsOnEnd { // Delete keeper jobs on chainlink nodes - actions.DeleteKeeperJobsWithId(t, k.chainlinkNodes, rIndex+1) + actions.DeleteKeeperJobsWithId(k.t, k.chainlinkNodes, rIndex+1) } } - l.Info().Str("Run Time", endTime.Sub(startTime).String()).Msg("Finished Keeper Benchmark Test") + k.log.Info().Str("Run Time", endTime.Sub(startTime).String()).Msg("Finished Keeper Benchmark Test") } -// subscribeToUpkeepPerformedEvent subscribes to the event log for UpkeepPerformed event and -// counts the number of times it was unsuccessful -func (k *KeeperBenchmarkTest) subscribeToUpkeepPerformedEvent( - t *testing.T, - doneChan chan bool, - metricsReporter *testreporters.KeeperBenchmarkTestReporter, - rIndex int, +// TearDownVals returns the networks that the test is running on +func (k *KeeperBenchmarkTest) TearDownVals(t *testing.T) ( + *testing.T, + string, + []*client.ChainlinkK8sClient, + reportModel.TestReporter, + blockchain.EVMClient, ) { - l := logging.GetTestLogger(t) - contractABI, err := keeper_registry_wrapper1_1.KeeperRegistryMetaData.GetAbi() - require.NoError(t, err, "Error getting ABI") - switch k.Inputs.RegistryVersions[rIndex] { - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1: - contractABI, err = keeper_registry_wrapper1_1.KeeperRegistryMetaData.GetAbi() - case ethereum.RegistryVersion_1_2: - contractABI, err = keeper_registry_wrapper1_2.KeeperRegistryMetaData.GetAbi() - case ethereum.RegistryVersion_1_3: - contractABI, err = keeper_registry_wrapper1_3.KeeperRegistryMetaData.GetAbi() - case ethereum.RegistryVersion_2_0: - contractABI, err = keeper_registry_wrapper2_0.KeeperRegistryMetaData.GetAbi() - case ethereum.RegistryVersion_2_1: - contractABI, err = iregistry21.IKeeperRegistryMasterMetaData.GetAbi() - default: - contractABI, err = keeper_registry_wrapper2_0.KeeperRegistryMetaData.GetAbi() - } + return t, k.namespace, k.chainlinkNodes, &k.TestReporter, k.chainClient +} - require.NoError(t, err, "Getting contract abi for registry shouldn't fail") - query := geth.FilterQuery{ - Addresses: []common.Address{common.HexToAddress(k.keeperRegistries[rIndex].Address())}, - } +// ********************* +// ****** Helpers ****** +// ********************* + +// observeUpkeepEvents subscribes to Upkeep events on deployed registries and logs them +// WARNING: This should only be used for observation and logging. This isn't a reliable way to build a final report +// due to how fragile subscriptions can be +func (k *KeeperBenchmarkTest) observeUpkeepEvents() { eventLogs := make(chan types.Log) - sub, err := k.chainClient.SubscribeFilterLogs(context.Background(), query, eventLogs) - require.NoError(t, err, "Subscribing to upkeep performed events log shouldn't fail") + registryAddresses := make([]common.Address, len(k.keeperRegistries)) + addressIndexMap := map[common.Address]int{} + for index, registry := range k.keeperRegistries { + registryAddresses[index] = common.HexToAddress(registry.Address()) + addressIndexMap[registryAddresses[index]] = index + } + filterQuery := geth.FilterQuery{ + Addresses: registryAddresses, + FromBlock: k.startingBlock, + } + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + sub, err := k.chainClient.SubscribeFilterLogs(ctx, filterQuery, eventLogs) + cancel() + require.NoError(k.t, err, "Subscribing to upkeep performed events log shouldn't fail") + + interruption := make(chan os.Signal, 1) + signal.Notify(interruption, os.Kill, os.Interrupt, syscall.SIGTERM) + go func() { - var numRevertedUpkeeps int64 - var numStaleReports int64 for { select { + case <-interruption: + k.log.Warn().Msg("Received interrupt signal, test container restarting. Dashboard view will be inaccurate.") case err := <-sub.Err(): - l.Error().Err(err).Msg("Error while subscribing to Keeper Event Logs. Resubscribing...") - sub.Unsubscribe() - - sub, err = k.chainClient.SubscribeFilterLogs(context.Background(), query, eventLogs) - require.NoError(t, err, "Error re-subscribing to event logs") + backoff := time.Second + for err != nil { // Keep retrying until we get a successful subscription + k.log.Error(). + Err(err). + Interface("Query", filterQuery). + Str("Backoff", backoff.String()). + Msg("Error while subscribing to Keeper Event Logs. Resubscribing...") + + ctx, cancel := context.WithTimeout(context.Background(), backoff) + sub, err = k.chainClient.SubscribeFilterLogs(ctx, filterQuery, eventLogs) + cancel() + if err != nil { + time.Sleep(backoff) + backoff = time.Duration(math.Min(float64(backoff)*2, float64(30*time.Second))) + } + } + log.Info().Msg("Resubscribed to Keeper Event Logs") case vLog := <-eventLogs: + rIndex, ok := addressIndexMap[vLog.Address] + if !ok { + k.log.Error().Str("Address", vLog.Address.Hex()).Msg("Received log from unknown registry") + continue + } + contractABI := k.contractABI(rIndex) eventDetails, err := contractABI.EventByID(vLog.Topics[0]) - require.NoError(t, err, "Getting event details for subscribed log shouldn't fail") + require.NoError(k.t, err, "Getting event details for subscribed log shouldn't fail") if eventDetails.Name != "UpkeepPerformed" && eventDetails.Name != "StaleUpkeepReport" { // Skip non upkeepPerformed Logs continue } + if vLog.Removed { + k.log.Warn(). + Str("Name", eventDetails.Name). + Str("Registry", k.keeperRegistries[rIndex].Address()). + Msg("Got removed log") + } if eventDetails.Name == "UpkeepPerformed" { parsedLog, err := k.keeperRegistries[rIndex].ParseUpkeepPerformedLog(&vLog) - require.NoError(t, err, "Parsing upkeep performed log shouldn't fail") + require.NoError(k.t, err, "Parsing upkeep performed log shouldn't fail") if parsedLog.Success { - l.Info(). + k.log.Info(). Str("Upkeep ID", parsedLog.Id.String()). Bool("Success", parsedLog.Success). Str("From", parsedLog.From.String()). Str("Registry", k.keeperRegistries[rIndex].Address()). Msg("Got successful Upkeep Performed log on Registry") - } else { - l.Warn(). + k.log.Warn(). Str("Upkeep ID", parsedLog.Id.String()). Bool("Success", parsedLog.Success). Str("From", parsedLog.From.String()). Str("Registry", k.keeperRegistries[rIndex].Address()). Msg("Got reverted Upkeep Performed log on Registry") - numRevertedUpkeeps++ } } else if eventDetails.Name == "StaleUpkeepReport" { parsedLog, err := k.keeperRegistries[rIndex].ParseStaleUpkeepReportLog(&vLog) - require.NoError(t, err, "Parsing stale upkeep report log shouldn't fail") - l.Warn(). + require.NoError(k.t, err, "Parsing stale upkeep report log shouldn't fail") + k.log.Warn(). Str("Upkeep ID", parsedLog.Id.String()). Str("Registry", k.keeperRegistries[rIndex].Address()). Msg("Got stale Upkeep report log on Registry") - numStaleReports++ } - - case <-doneChan: - metricsReporter.NumRevertedUpkeeps = numRevertedUpkeeps - metricsReporter.NumStaleUpkeepReports = numStaleReports - return + case <-k.chainClient.ConnectionIssue(): + k.log.Warn().Msg("RPC connection issue detected.") + case <-k.chainClient.ConnectionRestored(): + k.log.Info().Msg("RPC connection restored.") } } }() } -// TearDownVals returns the networks that the test is running on -func (k *KeeperBenchmarkTest) TearDownVals(t *testing.T) ( - *testing.T, - string, - []*client.ChainlinkK8sClient, - reportModel.TestReporter, - blockchain.EVMClient, -) { - return t, k.namespace, k.chainlinkNodes, &k.TestReporter, k.chainClient +// contractABI returns the ABI of the proper keeper registry contract +func (k *KeeperBenchmarkTest) contractABI(rIndex int) *abi.ABI { + var ( + contractABI *abi.ABI + err error + ) + switch k.Inputs.RegistryVersions[rIndex] { + case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1: + contractABI, err = keeper_registry_wrapper1_1.KeeperRegistryMetaData.GetAbi() + case ethereum.RegistryVersion_1_2: + contractABI, err = keeper_registry_wrapper1_2.KeeperRegistryMetaData.GetAbi() + case ethereum.RegistryVersion_1_3: + contractABI, err = keeper_registry_wrapper1_3.KeeperRegistryMetaData.GetAbi() + case ethereum.RegistryVersion_2_0: + contractABI, err = keeper_registry_wrapper2_0.KeeperRegistryMetaData.GetAbi() + case ethereum.RegistryVersion_2_1: + contractABI, err = iregistry21.IKeeperRegistryMasterMetaData.GetAbi() + default: + contractABI, err = keeper_registry_wrapper2_0.KeeperRegistryMetaData.GetAbi() + } + require.NoError(k.t, err, "Getting contract ABI shouldn't fail") + return contractABI } // ensureValues ensures that all values needed to run the test are present -func (k *KeeperBenchmarkTest) ensureInputValues(t *testing.T) { +func (k *KeeperBenchmarkTest) ensureInputValues() { inputs := k.Inputs - require.NotNil(t, inputs.BlockchainClient, "Need a valid blockchain client to use for the test") + require.NotNil(k.t, inputs.BlockchainClient, "Need a valid blockchain client to use for the test") k.chainClient = inputs.BlockchainClient - require.GreaterOrEqual(t, inputs.Upkeeps.NumberOfUpkeeps, 1, "Expecting at least 1 keeper contracts") + require.GreaterOrEqual(k.t, inputs.Upkeeps.NumberOfUpkeeps, 1, "Expecting at least 1 keeper contracts") if inputs.Timeout == 0 { - require.Greater(t, inputs.Upkeeps.BlockRange, int64(0), "If no `timeout` is provided, a `testBlockRange` is required") + require.Greater(k.t, inputs.Upkeeps.BlockRange, int64(0), "If no `timeout` is provided, a `testBlockRange` is required") } else if inputs.Upkeeps.BlockRange <= 0 { - require.GreaterOrEqual(t, inputs.Timeout, time.Second, "If no `testBlockRange` is provided a `timeout` is required") + require.GreaterOrEqual(k.t, inputs.Timeout, time.Second, "If no `testBlockRange` is provided a `timeout` is required") } - require.NotNil(t, inputs.KeeperRegistrySettings, "You need to set KeeperRegistrySettings") - require.NotNil(t, k.Inputs.ChainlinkNodeFunding, "You need to set a funding amount for chainlink nodes") + require.NotNil(k.t, inputs.KeeperRegistrySettings, "You need to set KeeperRegistrySettings") + require.NotNil(k.t, k.Inputs.ChainlinkNodeFunding, "You need to set a funding amount for chainlink nodes") clFunds, _ := k.Inputs.ChainlinkNodeFunding.Float64() - require.GreaterOrEqual(t, clFunds, 0.0, "Expecting Chainlink node funding to be more than 0 ETH") - require.Greater(t, inputs.Upkeeps.CheckGasToBurn, int64(0), "You need to set an expected amount of gas to burn on checkUpkeep()") + require.GreaterOrEqual(k.t, clFunds, 0.0, "Expecting Chainlink node funding to be more than 0 ETH") + require.Greater(k.t, inputs.Upkeeps.CheckGasToBurn, int64(0), "You need to set an expected amount of gas to burn on checkUpkeep()") require.GreaterOrEqual( - t, int64(inputs.KeeperRegistrySettings.CheckGasLimit), inputs.Upkeeps.CheckGasToBurn, "CheckGasLimit should be >= CheckGasToBurn", + k.t, int64(inputs.KeeperRegistrySettings.CheckGasLimit), inputs.Upkeeps.CheckGasToBurn, "CheckGasLimit should be >= CheckGasToBurn", ) - require.Greater(t, inputs.Upkeeps.PerformGasToBurn, int64(0), "You need to set an expected amount of gas to burn on performUpkeep()") - require.NotNil(t, inputs.UpkeepSLA, "Expected UpkeepSLA to be set") - require.NotNil(t, inputs.Upkeeps.FirstEligibleBuffer, "You need to set FirstEligibleBuffer") - require.NotNil(t, inputs.RegistryVersions[0], "You need to set RegistryVersion") - require.NotNil(t, inputs.BlockTime, "You need to set BlockTime") + require.Greater(k.t, inputs.Upkeeps.PerformGasToBurn, int64(0), "You need to set an expected amount of gas to burn on performUpkeep()") + require.NotNil(k.t, inputs.UpkeepSLA, "Expected UpkeepSLA to be set") + require.NotNil(k.t, inputs.Upkeeps.FirstEligibleBuffer, "You need to set FirstEligibleBuffer") + require.NotNil(k.t, inputs.RegistryVersions[0], "You need to set RegistryVersion") + require.NotNil(k.t, inputs.BlockTime, "You need to set BlockTime") if k.Inputs.DeltaStage == 0 { k.Inputs.DeltaStage = k.Inputs.BlockTime * 5 @@ -473,11 +572,7 @@ func (k *KeeperBenchmarkTest) SendSlackNotification(slackClient *slack.Client) e } // DeployBenchmarkKeeperContracts deploys a set amount of keeper Benchmark contracts registered to a single registry -func (k *KeeperBenchmarkTest) DeployBenchmarkKeeperContracts( - t *testing.T, - index int, -) { - l := logging.GetTestLogger(t) +func (k *KeeperBenchmarkTest) DeployBenchmarkKeeperContracts(index int) { registryVersion := k.Inputs.RegistryVersions[index] k.Inputs.KeeperRegistrySettings.RegistryVersion = registryVersion upkeep := k.Inputs.Upkeeps @@ -488,7 +583,7 @@ func (k *KeeperBenchmarkTest) DeployBenchmarkKeeperContracts( // Contract deployment is different for legacy keepers and OCR automation if registryVersion <= ethereum.RegistryVersion_1_3 { // Legacy keeper - v1.X - registry = actions.DeployKeeperRegistry(t, k.contractDeployer, k.chainClient, + registry = actions.DeployKeeperRegistry(k.t, k.contractDeployer, k.chainClient, &contracts.KeeperRegistryOpts{ RegistryVersion: registryVersion, LinkAddr: k.linkToken.Address(), @@ -502,7 +597,7 @@ func (k *KeeperBenchmarkTest) DeployBenchmarkKeeperContracts( // Fund the registry with 1 LINK * amount of AutomationConsumerBenchmark contracts err := k.linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(k.Inputs.Upkeeps.NumberOfUpkeeps)))) - require.NoError(t, err, "Funding keeper registry contract shouldn't fail") + require.NoError(k.t, err, "Funding keeper registry contract shouldn't fail") registrarSettings := contracts.KeeperRegistrarSettings{ AutoApproveConfigType: 2, @@ -510,29 +605,30 @@ func (k *KeeperBenchmarkTest) DeployBenchmarkKeeperContracts( RegistryAddr: registry.Address(), MinLinkJuels: big.NewInt(0), } - registrar = actions.DeployKeeperRegistrar(t, registryVersion, k.linkToken, registrarSettings, k.contractDeployer, k.chainClient, registry) + registrar = actions.DeployKeeperRegistrar(k.t, registryVersion, k.linkToken, registrarSettings, k.contractDeployer, k.chainClient, registry) } else { // OCR automation - v2.X registry, registrar = actions.DeployAutoOCRRegistryAndRegistrar( - t, registryVersion, *k.Inputs.KeeperRegistrySettings, k.linkToken, k.contractDeployer, k.chainClient) + k.t, registryVersion, *k.Inputs.KeeperRegistrySettings, k.linkToken, k.contractDeployer, k.chainClient, + ) // Fund the registry with LINK err := k.linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(k.Inputs.Upkeeps.NumberOfUpkeeps)))) - require.NoError(t, err, "Funding keeper registry contract shouldn't fail") - ocrConfig, err := actions.BuildAutoOCR2ConfigVars(t, k.chainlinkNodes[1:], *k.Inputs.KeeperRegistrySettings, registrar.Address(), k.Inputs.DeltaStage) - l.Debug().Interface("KeeperRegistrySettings", *k.Inputs.KeeperRegistrySettings).Interface("OCRConfig", ocrConfig).Msg("Config") - require.NoError(t, err, "Error building OCR config vars") + require.NoError(k.t, err, "Funding keeper registry contract shouldn't fail") + ocrConfig, err := actions.BuildAutoOCR2ConfigVars(k.t, k.chainlinkNodes[1:], *k.Inputs.KeeperRegistrySettings, registrar.Address(), k.Inputs.DeltaStage) + k.log.Debug().Interface("KeeperRegistrySettings", *k.Inputs.KeeperRegistrySettings).Interface("OCRConfig", ocrConfig).Msg("Config") + require.NoError(k.t, err, "Error building OCR config vars") err = registry.SetConfig(*k.Inputs.KeeperRegistrySettings, ocrConfig) - require.NoError(t, err, "Registry config should be be set successfully") + require.NoError(k.t, err, "Registry config should be be set successfully") } - consumer := DeployKeeperConsumersBenchmark(t, k.contractDeployer, k.chainClient) + consumer := k.DeployKeeperConsumersBenchmark() var upkeepAddresses []string checkData := make([][]byte, 0) uint256Ty, err := abi.NewType("uint256", "uint256", nil) - require.NoError(t, err) + require.NoError(k.t, err) var data []byte checkDataAbi := abi.Arguments{ { @@ -560,8 +656,8 @@ func (k *KeeperBenchmarkTest) DeployBenchmarkKeeperContracts( data, err = checkDataAbi.Pack( big.NewInt(int64(i)), big.NewInt(upkeep.BlockInterval), big.NewInt(upkeep.BlockRange), big.NewInt(upkeep.CheckGasToBurn), big.NewInt(upkeep.PerformGasToBurn), big.NewInt(upkeep.FirstEligibleBuffer)) - require.NoError(t, err) - l.Debug().Str("checkData: ", hexutil.Encode(data)).Int("id", i).Msg("checkData computed") + require.NoError(k.t, err) + k.log.Debug().Str("checkData: ", hexutil.Encode(data)).Int("id", i).Msg("checkData computed") checkData = append(checkData, data) } linkFunds := big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(upkeep.BlockRange/upkeep.BlockInterval)) @@ -575,7 +671,7 @@ func (k *KeeperBenchmarkTest) DeployBenchmarkKeeperContracts( linkFunds = big.NewInt(0).Add(linkFunds, minLinkBalance) - upkeepIds := actions.RegisterUpkeepContractsWithCheckData(t, k.linkToken, linkFunds, k.chainClient, uint32(upkeep.UpkeepGasLimit), registry, registrar, upkeep.NumberOfUpkeeps, upkeepAddresses, checkData, false) + upkeepIds := actions.RegisterUpkeepContractsWithCheckData(k.t, k.linkToken, linkFunds, k.chainClient, uint32(upkeep.UpkeepGasLimit), registry, registrar, upkeep.NumberOfUpkeeps, upkeepAddresses, checkData, false) k.keeperRegistries[index] = registry k.keeperRegistrars[index] = registrar @@ -583,27 +679,21 @@ func (k *KeeperBenchmarkTest) DeployBenchmarkKeeperContracts( k.keeperConsumerContracts[index] = consumer } -func DeployKeeperConsumersBenchmark( - t *testing.T, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, -) contracts.AutomationConsumerBenchmark { - l := logging.GetTestLogger(t) - +func (k *KeeperBenchmarkTest) DeployKeeperConsumersBenchmark() contracts.AutomationConsumerBenchmark { // Deploy consumer - keeperConsumerInstance, err := contractDeployer.DeployKeeperConsumerBenchmark() + keeperConsumerInstance, err := k.contractDeployer.DeployKeeperConsumerBenchmark() if err != nil { - l.Error().Err(err).Msg("Deploying AutomationConsumerBenchmark instance %d shouldn't fail") - keeperConsumerInstance, err = contractDeployer.DeployKeeperConsumerBenchmark() - require.NoError(t, err, "Error deploying AutomationConsumerBenchmark") + k.log.Error().Err(err).Msg("Deploying AutomationConsumerBenchmark instance %d shouldn't fail") + keeperConsumerInstance, err = k.contractDeployer.DeployKeeperConsumerBenchmark() + require.NoError(k.t, err, "Error deploying AutomationConsumerBenchmark") } - l.Debug(). + k.log.Debug(). Str("Contract Address", keeperConsumerInstance.Address()). Msg("Deployed Keeper Benchmark Contract") - err = client.WaitForEvents() - require.NoError(t, err, "Failed waiting for to deploy all keeper consumer contracts") - l.Info().Msg("Successfully deployed all Keeper Consumer Contracts") + err = k.chainClient.WaitForEvents() + require.NoError(k.t, err, "Failed waiting for to deploy all keeper consumer contracts") + k.log.Info().Msg("Successfully deployed all Keeper Consumer Contracts") return keeperConsumerInstance } diff --git a/integration-tests/testsetups/ocr.go b/integration-tests/testsetups/ocr.go index b53fe9a797..048f3124ad 100644 --- a/integration-tests/testsetups/ocr.go +++ b/integration-tests/testsetups/ocr.go @@ -4,7 +4,7 @@ package testsetups import ( "context" "fmt" - "io/ioutil" + "math" "math/big" "math/rand" "os" @@ -24,6 +24,8 @@ import ( "github.com/rs/zerolog" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator" + "github.com/smartcontractkit/chainlink-env/environment" "github.com/smartcontractkit/chainlink-env/pkg/helm/chainlink" "github.com/smartcontractkit/chainlink-env/pkg/helm/ethereum" @@ -32,10 +34,8 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/blockchain" ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" "github.com/smartcontractkit/chainlink-testing-framework/logging" - reportModel "github.com/smartcontractkit/chainlink-testing-framework/testreporters" - "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator" - "github.com/smartcontractkit/chainlink-testing-framework/networks" + reportModel "github.com/smartcontractkit/chainlink-testing-framework/testreporters" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" @@ -44,7 +44,10 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/testreporters" ) -const saveFileLocation = "/persistence/ocr-soak-test-state.toml" +const ( + saveFileLocation = "/persistence/ocr-soak-test-state.toml" + interruptedExitCode = 3 +) // OCRSoakTest defines a typical OCR soak test type OCRSoakTest struct { @@ -118,8 +121,7 @@ func NewOCRSoakTest(t *testing.T, forwarderFlow bool) (*OCRSoakTest, error) { ocrRoundStates: make([]*testreporters.OCRRoundState, 0), ocrInstanceMap: make(map[string]contracts.OffchainAggregator), } - test.ensureInputValues() - return test, nil + return test, test.ensureInputValues() } // DeployEnvironment deploys the test environment, starting all Chainlink nodes and other components for the test @@ -131,9 +133,10 @@ func (o *OCRSoakTest) DeployEnvironment(customChainlinkNetworkTOML string) { } nsPre = fmt.Sprintf("%s%s", nsPre, strings.ReplaceAll(strings.ToLower(network.Name), " ", "-")) baseEnvironmentConfig := &environment.Config{ - TTL: time.Hour * 720, // 30 days, - NamespacePrefix: nsPre, - Test: o.t, + TTL: time.Hour * 720, // 30 days, + NamespacePrefix: nsPre, + Test: o.t, + PreventPodEviction: true, } cd := chainlink.New(0, map[string]any{ @@ -359,7 +362,7 @@ func (o *OCRSoakTest) LoadState() error { } testState := &OCRSoakTestState{} - saveData, err := ioutil.ReadFile(saveFileLocation) + saveData, err := os.ReadFile(saveFileLocation) if err != nil { return err } @@ -486,7 +489,7 @@ func (o *OCRSoakTest) testLoop(testDuration time.Duration, newValue int) { o.log.Error().Err(err).Msg("Error saving state") } o.log.Warn().Str("Time Taken", time.Since(saveStart).String()).Msg("Saved state") - os.Exit(2) // Exit with code 2 to indicate test was interrupted, not just a normal failure + os.Exit(interruptedExitCode) // Exit with interrupted code to indicate test was interrupted, not just a normal failure case <-endTest: return case <-newRoundTrigger.C: @@ -582,14 +585,20 @@ func (o *OCRSoakTest) observeOCREvents() error { Int64("Answer", answerUpdated.Current.Int64()). Msg("Answer Updated Event") case err = <-eventSub.Err(): + backoff := time.Second for err != nil { o.log.Info(). Err(err). + Str("Backoff", backoff.String()). Interface("Query", o.filterQuery). Msg("Error while subscribed to OCR Logs. Resubscribing") - ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second) + ctx, cancel = context.WithTimeout(context.Background(), backoff) eventSub, err = o.chainClient.SubscribeFilterLogs(ctx, o.filterQuery, eventLogs) cancel() + if err != nil { + time.Sleep(backoff) + backoff = time.Duration(math.Min(float64(backoff)*2, float64(30*time.Second))) + } } } }