From 50d5570b2bc9863c8898a60604a8404f4ecd3c24 Mon Sep 17 00:00:00 2001 From: Adam Hamrick Date: Fri, 1 Sep 2023 16:49:05 -0400 Subject: [PATCH 01/14] [TT-549] Renable Live Test Runs (#10379) * Debug on * Bypass build test * Change secret names * Strip Private Keys * Fix strip * Fix funding * Clean imports * Cleanup * Formatting * Remove if check * Regularly Scheduled Programming --- .github/workflows/integration-tests.yml | 10 ++--- integration-tests/actions/actions.go | 9 ++-- .../actions/automation_ocr_helpers.go | 16 +++---- integration-tests/docker/test_env/cl_node.go | 7 ++- integration-tests/docker/test_env/test_env.go | 43 +++++++++++++++++- .../docker/test_env/test_env_builder.go | 3 +- integration-tests/networks/known_networks.go | 13 +++--- integration-tests/smoke/automation_test.go | 44 ++++++++++++++----- integration-tests/smoke/cron_test.go | 15 ++++++- integration-tests/smoke/flux_test.go | 19 +++++--- integration-tests/smoke/forwarder_ocr_test.go | 18 ++++++-- .../smoke/forwarders_ocr2_test.go | 12 ++++- integration-tests/smoke/keeper_test.go | 10 ++++- integration-tests/smoke/ocr2_test.go | 17 +++++-- integration-tests/smoke/ocr_test.go | 24 ++++++---- integration-tests/smoke/runlog_test.go | 19 +++++--- integration-tests/smoke/vrf_test.go | 19 +++++--- integration-tests/smoke/vrfv2_test.go | 8 +++- integration-tests/smoke/vrfv2plus_test.go | 19 +++++--- integration-tests/types/config/node/core.go | 3 +- 20 files changed, 244 insertions(+), 84 deletions(-) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 74ce6edac25..8c1d5be828c 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -803,7 +803,7 @@ jobs: pull-requests: write id-token: write contents: read - needs: [build-chainlink, build-test-image] + needs: [build-chainlink] env: SELECTED_NETWORKS: ${{ matrix.testnet }} CHAINLINK_COMMIT_SHA: ${{ github.sha }} @@ -812,11 +812,11 @@ jobs: EVM_KEYS: ${{ secrets.QA_EVM_KEYS }} TEST_EVM_KEYS: ${{ secrets.QA_EVM_KEYS }} - TEST_OPTIMISM_GOERLI_URLS: ${{ secrets.QA_OPTIMISM_GOERLI_URLS }} - TEST_OPTIMISM_GOERLI_HTTP_URLS: ${{ secrets.QA_OPTIMISM_GOERLI_HTTP_URLS }} + OPTIMISM_GOERLI_URLS: ${{ secrets.QA_OPTIMISM_GOERLI_URLS }} + OPTIMISM_GOERLI_HTTP_URLS: ${{ secrets.QA_OPTIMISM_GOERLI_HTTP_URLS }} - TEST_ARBITRUM_GOERLI_URLS: ${{ secrets.QA_ARBITRUM_GOERLI_URLS }} - TEST_ARBITRUM_GOERLI_HTTP_URLS: ${{ secrets.QA_ARBITRUM_GOERLI_HTTP_URLS }} + ARBITRUM_GOERLI_URLS: ${{ secrets.QA_ARBITRUM_GOERLI_URLS }} + ARBITRUM_GOERLI_HTTP_URLS: ${{ secrets.QA_ARBITRUM_GOERLI_HTTP_URLS }} strategy: fail-fast: false matrix: diff --git a/integration-tests/actions/actions.go b/integration-tests/actions/actions.go index ffb71cb7424..82187fd0cb8 100644 --- a/integration-tests/actions/actions.go +++ b/integration-tests/actions/actions.go @@ -263,7 +263,7 @@ func TeardownSuite( for _, c := range clients { if c != nil && chainlinkNodes != nil && len(chainlinkNodes) > 0 { - if err := returnFunds(chainlinkNodes, c); err != nil { + if err := ReturnFunds(chainlinkNodes, c); err != nil { // This printed line is required for tests that use real funds to propagate the failure // out to the system running the test. Do not remove fmt.Println(environment.FAILED_FUND_RETURN) @@ -306,7 +306,7 @@ func TeardownRemoteSuite( l.Warn().Msgf("Error deleting jobs %+v", err) } - if err = returnFunds(chainlinkNodes, client); err != nil { + if err = ReturnFunds(chainlinkNodes, client); err != nil { l.Error().Err(err).Str("Namespace", namespace). Msg("Error attempting to return funds from chainlink nodes to network's default wallet. " + "Environment is left running so you can try manually!") @@ -337,8 +337,9 @@ func DeleteAllJobs(chainlinkNodes []*client.ChainlinkK8sClient) error { return nil } -// Returns all the funds from the chainlink nodes to the networks default address -func returnFunds(chainlinkNodes []*client.ChainlinkK8sClient, blockchainClient blockchain.EVMClient) error { +// ReturnFunds attempts to return all the funds from the chainlink nodes to the network's default address +// all from a remote, k8s style environment +func ReturnFunds(chainlinkNodes []*client.ChainlinkK8sClient, blockchainClient blockchain.EVMClient) error { if blockchainClient == nil { return errors.New("blockchain client is nil, unable to return funds from chainlink nodes") } diff --git a/integration-tests/actions/automation_ocr_helpers.go b/integration-tests/actions/automation_ocr_helpers.go index a2f2633f68d..bfea6ec302c 100644 --- a/integration-tests/actions/automation_ocr_helpers.go +++ b/integration-tests/actions/automation_ocr_helpers.go @@ -11,25 +11,23 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/lib/pq" - ocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" - "github.com/stretchr/testify/require" - "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink-testing-framework/utils" + "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/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" - - "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - - "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" ) func BuildAutoOCR2ConfigVars( diff --git a/integration-tests/docker/test_env/cl_node.go b/integration-tests/docker/test_env/cl_node.go index 0ec62808feb..a78f9e52ad6 100644 --- a/integration-tests/docker/test_env/cl_node.go +++ b/integration-tests/docker/test_env/cl_node.go @@ -18,17 +18,16 @@ import ( "github.com/pelletier/go-toml/v2" "github.com/pkg/errors" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" tc "github.com/testcontainers/testcontainers-go" tcwait "github.com/testcontainers/testcontainers-go/wait" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" "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" diff --git a/integration-tests/docker/test_env/test_env.go b/integration-tests/docker/test_env/test_env.go index c056e92b9fc..e90bf5618ab 100644 --- a/integration-tests/docker/test_env/test_env.go +++ b/integration-tests/docker/test_env/test_env.go @@ -1,8 +1,10 @@ package test_env import ( + "encoding/json" "math/big" + "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" "github.com/rs/zerolog/log" @@ -12,7 +14,6 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" "github.com/smartcontractkit/chainlink-testing-framework/logwatch" - "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/integration-tests/client" @@ -194,3 +195,43 @@ func (te *CLClusterTestEnv) Terminate() error { // 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() error { + log.Info().Msg("Attempting to return Chainlink node funds to default network wallets") + if te.EVMClient == nil { + return errors.New("blockchain client is nil, unable to return funds from chainlink nodes") + } + if te.CLNodes == nil { + return errors.New("chainlink nodes are nil, unable to return funds from chainlink nodes") + } + if te.EVMClient.NetworkSimulated() { + log.Info().Str("Network Name", te.EVMClient.GetNetworkName()). + Msg("Network is a simulated network. Skipping fund return.") + return nil + } + + for _, chainlinkNode := range te.CLNodes { + 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 + } + if err = te.EVMClient.ReturnFunds(decryptedKey.PrivateKey); err != nil { + return err + } + } + } + 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 bacee0c956f..27f98b36139 100644 --- a/integration-tests/docker/test_env/test_env_builder.go +++ b/integration-tests/docker/test_env/test_env_builder.go @@ -6,11 +6,10 @@ import ( "github.com/pkg/errors" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" "github.com/smartcontractkit/chainlink-testing-framework/logwatch" - "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/integration-tests/contracts" diff --git a/integration-tests/networks/known_networks.go b/integration-tests/networks/known_networks.go index 41148ba2043..4d12d6b5b60 100644 --- a/integration-tests/networks/known_networks.go +++ b/integration-tests/networks/known_networks.go @@ -558,17 +558,18 @@ func setKeys(prefix string, network *blockchain.EVMNetwork) { } envVar := fmt.Sprintf("%s_KEYS", prefix) - keysEnv, err := utils.GetEnv(envVar) + keysFromEnv, err := utils.GetEnv(envVar) if err != nil { log.Fatal().Err(err).Str("env var", envVar).Msg("Error getting env var") } - if keysEnv == "" { - keys := strings.Split(os.Getenv("EVM_KEYS"), ",") + if keysFromEnv == "" { log.Warn().Msg(fmt.Sprintf("No '%s' env var defined, defaulting to 'EVM_KEYS'", envVar)) - network.PrivateKeys = keys - return + keysFromEnv = os.Getenv("EVM_KEYS") + } + keys := strings.Split(keysFromEnv, ",") + for i, key := range keys { + keys[i] = strings.TrimPrefix(key, "0x") } - keys := strings.Split(keysEnv, ",") network.PrivateKeys = keys // log public keys for debugging diff --git a/integration-tests/smoke/automation_test.go b/integration-tests/smoke/automation_test.go index 8855a8a125d..5aa7668d151 100644 --- a/integration-tests/smoke/automation_test.go +++ b/integration-tests/smoke/automation_test.go @@ -11,6 +11,7 @@ import ( "time" "github.com/onsi/gomega" + "github.com/rs/zerolog/log" "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" @@ -108,7 +109,9 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { "registry_2_1_logtrigger": ethereum.RegistryVersion_2_1, } - for name, registryVersion := range registryVersions { + for n, rv := range registryVersions { + name := n + registryVersion := rv t.Run(name, func(t *testing.T) { t.Parallel() @@ -234,7 +237,9 @@ func TestAutomationAddFunds(t *testing.T) { "registry_2_1": ethereum.RegistryVersion_2_1, } - for name, registryVersion := range registryVersions { + for n, rv := range registryVersions { + name := n + registryVersion := rv t.Run(name, func(t *testing.T) { t.Parallel() @@ -288,7 +293,9 @@ func TestAutomationPauseUnPause(t *testing.T) { "registry_2_1": ethereum.RegistryVersion_2_1, } - for name, registryVersion := range registryVersions { + for n, rv := range registryVersions { + name := n + registryVersion := rv t.Run(name, func(t *testing.T) { t.Parallel() @@ -303,7 +310,7 @@ func TestAutomationPauseUnPause(t *testing.T) { gom := gomega.NewGomegaWithT(t) gom.Eventually(func(g gomega.Gomega) { - // Check if the upkeeps are performing multiple times by analysing their counters and checking they are greater than 5 + // 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()) g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i) @@ -374,7 +381,9 @@ func TestAutomationRegisterUpkeep(t *testing.T) { "registry_2_1": ethereum.RegistryVersion_2_1, } - for name, registryVersion := range registryVersions { + for n, rv := range registryVersions { + name := n + registryVersion := rv t.Run(name, func(t *testing.T) { t.Parallel() @@ -448,7 +457,9 @@ func TestAutomationPauseRegistry(t *testing.T) { "registry_2_1": ethereum.RegistryVersion_2_1, } - for name, registryVersion := range registryVersions { + for n, rv := range registryVersions { + name := n + registryVersion := rv t.Run(name, func(t *testing.T) { t.Parallel() chainClient, _, contractDeployer, linkToken, registry, registrar, onlyStartRunner, _ := setupAutomationTest( @@ -508,7 +519,9 @@ func TestAutomationKeeperNodesDown(t *testing.T) { "registry_2_1": ethereum.RegistryVersion_2_1, } - for name, registryVersion := range registryVersions { + for n, rv := range registryVersions { + name := n + registryVersion := rv t.Run(name, func(t *testing.T) { t.Parallel() @@ -596,7 +609,9 @@ func TestAutomationPerformSimulation(t *testing.T) { "registry_2_1": ethereum.RegistryVersion_2_1, } - for name, registryVersion := range registryVersions { + for n, rv := range registryVersions { + name := n + registryVersion := rv t.Run(name, func(t *testing.T) { t.Parallel() @@ -663,7 +678,9 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) { "registry_2_1": ethereum.RegistryVersion_2_1, } - for name, registryVersion := range registryVersions { + for n, rv := range registryVersions { + name := n + registryVersion := rv t.Run(name, func(t *testing.T) { t.Parallel() @@ -779,7 +796,9 @@ func TestUpdateCheckData(t *testing.T) { "registry_2_1": ethereum.RegistryVersion_2_1, } - for name, registryVersion := range registryVersions { + for n, rv := range registryVersions { + name := n + registryVersion := rv t.Run(name, func(t *testing.T) { t.Parallel() @@ -902,6 +921,11 @@ func setupAutomationTest( require.NoError(t, err, "Error building contract deployer") chainlinkNodes, err = client.ConnectChainlinkNodes(testEnvironment) require.NoError(t, err, "Error connecting to Chainlink nodes") + t.Cleanup(func() { + if err := actions.ReturnFunds(chainlinkNodes, chainClient); err != nil { + log.Error().Err(err).Msg("Error returning funds") + } + }) chainClient.ParallelTransactions(true) txCost, err := chainClient.EstimateCostForChainlinkOperations(1000) diff --git a/integration-tests/smoke/cron_test.go b/integration-tests/smoke/cron_test.go index 30eadb8f16b..0285e2d23c7 100644 --- a/integration-tests/smoke/cron_test.go +++ b/integration-tests/smoke/cron_test.go @@ -2,16 +2,21 @@ package smoke import ( "fmt" + "testing" + "github.com/google/uuid" "github.com/onsi/gomega" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-testing-framework/utils" + "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" - "github.com/stretchr/testify/require" - "testing" ) func TestCronBasic(t *testing.T) { t.Parallel() + l := utils.GetTestLogger(t) env, err := test_env.NewCLTestEnvBuilder(). WithGeth(). @@ -19,6 +24,12 @@ func TestCronBasic(t *testing.T) { WithCLNodes(1). Build() require.NoError(t, err) + t.Cleanup(func() { + if err := env.Cleanup(); 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") diff --git a/integration-tests/smoke/flux_test.go b/integration-tests/smoke/flux_test.go index da06fc4b57a..c4cd02b857d 100644 --- a/integration-tests/smoke/flux_test.go +++ b/integration-tests/smoke/flux_test.go @@ -3,18 +3,21 @@ package smoke import ( "context" "fmt" + "math/big" + "strings" + "testing" + "time" + "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" + "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-testing-framework/utils" + "github.com/smartcontractkit/chainlink/integration-tests/actions" "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/stretchr/testify/require" - "math/big" - "strings" - "testing" - "time" ) func TestFluxBasic(t *testing.T) { @@ -27,6 +30,12 @@ func TestFluxBasic(t *testing.T) { WithCLNodes(3). Build() require.NoError(t, err) + t.Cleanup(func() { + if err := env.Cleanup(); err != nil { + l.Error().Err(err).Msg("Error cleaning up test environment") + } + }) + nodeAddresses, err := env.ChainlinkNodeAddresses() require.NoError(t, err, "Retrieving on-chain wallet addresses for chainlink nodes shouldn't fail") env.EVMClient.ParallelTransactions(true) diff --git a/integration-tests/smoke/forwarder_ocr_test.go b/integration-tests/smoke/forwarder_ocr_test.go index 0b58be41d74..e4cf5cb0527 100644 --- a/integration-tests/smoke/forwarder_ocr_test.go +++ b/integration-tests/smoke/forwarder_ocr_test.go @@ -1,26 +1,37 @@ package smoke import ( + "context" "math/big" "testing" - "context" "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-testing-framework/utils" + "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" - "github.com/stretchr/testify/require" ) func TestForwarderOCRBasic(t *testing.T) { t.Parallel() + l := utils.GetTestLogger(t) + env, err := test_env.NewCLTestEnvBuilder(). WithGeth(). WithMockServer(1). WithForwarders(). WithCLNodes(6). - WithFunding(big.NewFloat(10)). + WithFunding(big.NewFloat(.1)). Build() require.NoError(t, err) + t.Cleanup(func() { + if err := env.Cleanup(); err != nil { + l.Error().Err(err).Msg("Error cleaning up test environment") + } + }) + env.ParallelTransactions(true) nodeClients := env.GetAPIs() @@ -55,6 +66,7 @@ func TestForwarderOCRBasic(t *testing.T) { authorizedForwarders, env.EVMClient, ) + require.NoError(t, err, "Error deploying OCR contracts") err = actions.CreateOCRJobsWithForwarderLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockServer.Client) require.NoError(t, err, "failed to setup forwarder jobs") diff --git a/integration-tests/smoke/forwarders_ocr2_test.go b/integration-tests/smoke/forwarders_ocr2_test.go index cb6a3f0556d..81c521ff387 100644 --- a/integration-tests/smoke/forwarders_ocr2_test.go +++ b/integration-tests/smoke/forwarders_ocr2_test.go @@ -10,6 +10,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-testing-framework/utils" + "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" @@ -17,6 +19,8 @@ import ( func TestForwarderOCR2Basic(t *testing.T) { t.Parallel() + l := utils.GetTestLogger(t) + env, err := test_env.NewCLTestEnvBuilder(). WithGeth(). WithMockServer(1). @@ -26,9 +30,15 @@ func TestForwarderOCR2Basic(t *testing.T) { )). WithForwarders(). WithCLNodes(6). - WithFunding(big.NewFloat(10)). + WithFunding(big.NewFloat(.1)). Build() require.NoError(t, err) + t.Cleanup(func() { + if err := env.Cleanup(); err != nil { + l.Error().Err(err).Msg("Error cleaning up test environment") + } + }) + env.ParallelTransactions(true) nodeClients := env.GetAPIs() diff --git a/integration-tests/smoke/keeper_test.go b/integration-tests/smoke/keeper_test.go index 00cbe07eb0f..f07c42ab3d8 100644 --- a/integration-tests/smoke/keeper_test.go +++ b/integration-tests/smoke/keeper_test.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink-testing-framework/utils" + "github.com/smartcontractkit/chainlink/v2/core/store/models" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" @@ -21,7 +22,6 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" - "github.com/smartcontractkit/chainlink/v2/core/store/models" ) const ( @@ -105,7 +105,7 @@ func TestKeeperBasicSmoke(t *testing.T) { require.NoError(t, err, "Error creating keeper jobs") gom.Eventually(func(g gomega.Gomega) error { - // Check if the upkeeps are performing multiple times by analysing their counters and checking they are greater than 10 + // 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()) g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i) @@ -1089,6 +1089,7 @@ func setupKeeperTest(t *testing.T) ( clNodeConfig.Keeper.TurnLookBack = &turnLookBack clNodeConfig.Keeper.Registry.SyncInterval = &syncInterval clNodeConfig.Keeper.Registry.PerformGasOverhead = &performGasOverhead + l := utils.GetTestLogger(t) env, err := test_env.NewCLTestEnvBuilder(). WithGeth(). @@ -1098,6 +1099,11 @@ func setupKeeperTest(t *testing.T) ( WithFunding(big.NewFloat(.5)). Build() require.NoError(t, err, "Error deploying test environment") + t.Cleanup(func() { + if err := env.Cleanup(); err != nil { + l.Error().Err(err).Msg("Error cleaning up test environment") + } + }) env.ParallelTransactions(true) diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go index 7dd0b23223c..6588586c39d 100644 --- a/integration-tests/smoke/ocr2_test.go +++ b/integration-tests/smoke/ocr2_test.go @@ -4,27 +4,32 @@ import ( "context" "fmt" "math/big" + "strings" "testing" "time" + "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-env/environment" "github.com/smartcontractkit/chainlink-env/pkg/helm/chainlink" "github.com/smartcontractkit/chainlink-env/pkg/helm/ethereum" "github.com/smartcontractkit/chainlink-env/pkg/helm/mockserver" mockservercfg "github.com/smartcontractkit/chainlink-env/pkg/helm/mockserver-cfg" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/utils" + "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/config" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" "github.com/smartcontractkit/chainlink/integration-tests/networks" "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" - "github.com/stretchr/testify/require" - "strings" ) // Tests a basic OCRv2 median feed func TestOCRv2Basic(t *testing.T) { + l := utils.GetTestLogger(t) + env, err := test_env.NewCLTestEnvBuilder(). WithGeth(). WithMockServer(1). @@ -33,9 +38,15 @@ func TestOCRv2Basic(t *testing.T) { node.WithP2Pv2(), )). WithCLNodes(6). - WithFunding(big.NewFloat(10)). + WithFunding(big.NewFloat(.1)). Build() require.NoError(t, err) + t.Cleanup(func() { + if err := env.Cleanup(); err != nil { + l.Error().Err(err).Msg("Error cleaning up test environment") + } + }) + env.ParallelTransactions(true) nodeClients := env.GetAPIs() diff --git a/integration-tests/smoke/ocr_test.go b/integration-tests/smoke/ocr_test.go index 1ae52ade305..50d6abe662b 100644 --- a/integration-tests/smoke/ocr_test.go +++ b/integration-tests/smoke/ocr_test.go @@ -1,24 +1,35 @@ package smoke import ( + "context" + "math/big" "testing" - "context" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-testing-framework/utils" + "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" - "github.com/stretchr/testify/require" - "math/big" ) func TestOCRBasic(t *testing.T) { t.Parallel() + l := utils.GetTestLogger(t) + env, err := test_env.NewCLTestEnvBuilder(). WithGeth(). WithMockServer(1). WithCLNodes(6). - WithFunding(big.NewFloat(10)). + WithFunding(big.NewFloat(.1)). Build() require.NoError(t, err) + t.Cleanup(func() { + if err := env.Cleanup(); err != nil { + l.Error().Err(err).Msg("Error cleaning up test environment") + } + }) + env.ParallelTransactions(true) nodeClients := env.GetAPIs() @@ -27,9 +38,6 @@ func TestOCRBasic(t *testing.T) { linkTokenContract, err := env.ContractDeployer.DeployLinkTokenContract() require.NoError(t, err, "Deploying Link Token Contract shouldn't fail") - err = actions.FundChainlinkNodesLocal(workerNodes, env.EVMClient, big.NewFloat(.05)) - require.NoError(t, err, "Error funding Chainlink nodes") - ocrInstances, err := actions.DeployOCRContractsLocal(1, linkTokenContract, env.ContractDeployer, workerNodes, env.EVMClient) require.NoError(t, err) err = env.EVMClient.WaitForEvents() @@ -38,7 +46,7 @@ func TestOCRBasic(t *testing.T) { err = actions.CreateOCRJobsLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockServer.Client) require.NoError(t, err) - _ = actions.StartNewRound(1, ocrInstances, env.EVMClient) + err = actions.StartNewRound(1, ocrInstances, env.EVMClient) require.NoError(t, err) answer, err := ocrInstances[0].GetLatestAnswer(context.Background()) diff --git a/integration-tests/smoke/runlog_test.go b/integration-tests/smoke/runlog_test.go index d40d5677fde..cd2a099b142 100644 --- a/integration-tests/smoke/runlog_test.go +++ b/integration-tests/smoke/runlog_test.go @@ -3,27 +3,36 @@ package smoke import ( "context" "fmt" + "math/big" + "strings" + "testing" + "github.com/google/uuid" "github.com/onsi/gomega" + "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-testing-framework/utils" + "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" - "github.com/stretchr/testify/require" - "math/big" - "strings" - "testing" ) func TestRunLogBasic(t *testing.T) { t.Parallel() l := utils.GetTestLogger(t) + env, err := test_env.NewCLTestEnvBuilder(). WithGeth(). WithMockServer(1). WithCLNodes(1). - WithFunding(big.NewFloat(1)). + WithFunding(big.NewFloat(.1)). Build() require.NoError(t, err) + t.Cleanup(func() { + if err := env.Cleanup(); 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") diff --git a/integration-tests/smoke/vrf_test.go b/integration-tests/smoke/vrf_test.go index 2f3a8bb40f5..0e12b185a6a 100644 --- a/integration-tests/smoke/vrf_test.go +++ b/integration-tests/smoke/vrf_test.go @@ -3,29 +3,38 @@ package smoke import ( "context" "fmt" + "math/big" + "testing" + "time" + "github.com/google/uuid" "github.com/onsi/gomega" + "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-testing-framework/utils" + "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv1" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" - "github.com/stretchr/testify/require" - "math/big" - "testing" - "time" ) func TestVRFBasic(t *testing.T) { t.Parallel() l := utils.GetTestLogger(t) + env, err := test_env.NewCLTestEnvBuilder(). WithGeth(). WithMockServer(1). WithCLNodes(1). - WithFunding(big.NewFloat(1)). + WithFunding(big.NewFloat(.1)). Build() require.NoError(t, err) + t.Cleanup(func() { + if err := env.Cleanup(); err != nil { + l.Error().Err(err).Msg("Error cleaning up test environment") + } + }) env.ParallelTransactions(true) lt, err := actions.DeployLINKToken(env.ContractDeployer) diff --git a/integration-tests/smoke/vrfv2_test.go b/integration-tests/smoke/vrfv2_test.go index ed9b9f16318..41f9d2ee5ee 100644 --- a/integration-tests/smoke/vrfv2_test.go +++ b/integration-tests/smoke/vrfv2_test.go @@ -7,9 +7,10 @@ import ( "time" "github.com/onsi/gomega" - "github.com/smartcontractkit/chainlink-testing-framework/utils" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-testing-framework/utils" + "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions" vrfConst "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions/vrfv2_constants" @@ -27,6 +28,11 @@ func TestVRFv2Basic(t *testing.T) { WithFunding(vrfConst.ChainlinkNodeFundingAmountEth). Build() require.NoError(t, err) + t.Cleanup(func() { + if err := env.Cleanup(); err != nil { + l.Error().Err(err).Msg("Error cleaning up test environment") + } + }) env.ParallelTransactions(true) mockFeed, err := actions.DeployMockETHLinkFeed(env.ContractDeployer, vrfConst.LinkEthFeedResponse) diff --git a/integration-tests/smoke/vrfv2plus_test.go b/integration-tests/smoke/vrfv2plus_test.go index b3a99f8ca4e..9b6dc5a8626 100644 --- a/integration-tests/smoke/vrfv2plus_test.go +++ b/integration-tests/smoke/vrfv2plus_test.go @@ -2,16 +2,18 @@ package smoke import ( "context" - "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/docker/test_env" "math/big" "testing" "time" - "github.com/smartcontractkit/chainlink-testing-framework/utils" "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-testing-framework/utils" + + "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/docker/test_env" ) func TestVRFv2PlusBilling(t *testing.T) { @@ -23,8 +25,12 @@ func TestVRFv2PlusBilling(t *testing.T) { WithCLNodes(1). WithFunding(vrfv2plus_constants.ChainlinkNodeFundingAmountEth). Build() - require.NoError(t, err, "error creating test env") + t.Cleanup(func() { + if err := env.Cleanup(); err != nil { + l.Error().Err(err).Msg("Error cleaning up test environment") + } + }) env.ParallelTransactions(true) @@ -51,6 +57,7 @@ func TestVRFv2PlusBilling(t *testing.T) { subBalanceBeforeRequest := subscription.Balance jobRunsBeforeTest, err := env.CLNodes[0].API.MustReadRunsByJob(job.Job.Data.ID) + require.NoError(t, err, "error reading job runs") // test and assert err = vrfv2PlusContracts.LoadTestConsumer.RequestRandomness( diff --git a/integration-tests/types/config/node/core.go b/integration-tests/types/config/node/core.go index 4e60e1ece5c..0d433daa1b4 100644 --- a/integration-tests/types/config/node/core.go +++ b/integration-tests/types/config/node/core.go @@ -10,8 +10,6 @@ import ( "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - - utils2 "github.com/smartcontractkit/chainlink/integration-tests/utils" "github.com/smartcontractkit/chainlink/v2/core/assets" evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/config/toml" @@ -22,6 +20,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/utils/config" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrfv2_actions/vrfv2_constants" + utils2 "github.com/smartcontractkit/chainlink/integration-tests/utils" ) var ( From ceea5fb045b644af9985e925703209852b0684c7 Mon Sep 17 00:00:00 2001 From: jinhoonbang Date: Fri, 1 Sep 2023 22:52:49 -0700 Subject: [PATCH 02/14] =?UTF-8?q?remove=20check=20for=20finality=20depth?= =?UTF-8?q?=20in=20bhs=20and=20bhf.=20Do=20not=20update=20interna=E2=80=A6?= =?UTF-8?q?=20(#10391)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * remove check for finality depth in bhs and bhf. Do not update internal stored mapping based on IsStored() * fix delegate_test.go * address comments for trusted bhs. revert blockheaderfeeder changes * add a debug log * fix failing test --- core/services/blockhashstore/delegate.go | 6 - core/services/blockhashstore/delegate_test.go | 8 - core/services/blockhashstore/feeder.go | 48 ++-- core/services/blockhashstore/feeder_test.go | 210 ++++++++++-------- 4 files changed, 140 insertions(+), 132 deletions(-) diff --git a/core/services/blockhashstore/delegate.go b/core/services/blockhashstore/delegate.go index f3008af7b8b..0342dff78b7 100644 --- a/core/services/blockhashstore/delegate.go +++ b/core/services/blockhashstore/delegate.go @@ -65,12 +65,6 @@ func (d *Delegate) ServicesForSpec(jb job.Job, qopts ...pg.QOpt) ([]job.ServiceC return nil, errors.New("log poller must be enabled to run blockhashstore") } - if jb.BlockhashStoreSpec.WaitBlocks < int32(chain.Config().EVM().FinalityDepth()) { - return nil, fmt.Errorf( - "waitBlocks must be greater than or equal to chain's finality depth (%d), currently %d", - chain.Config().EVM().FinalityDepth(), jb.BlockhashStoreSpec.WaitBlocks) - } - keys, err := d.ks.EnabledKeysForChain(chain.ID()) if err != nil { return nil, errors.Wrap(err, "getting sending keys") diff --git a/core/services/blockhashstore/delegate_test.go b/core/services/blockhashstore/delegate_test.go index b0456206861..3a9c01ae399 100644 --- a/core/services/blockhashstore/delegate_test.go +++ b/core/services/blockhashstore/delegate_test.go @@ -128,14 +128,6 @@ func TestDelegate_ServicesForSpec(t *testing.T) { assert.Error(t, err) }) - t.Run("WaitBlocks less than EvmFinalityDepth", func(t *testing.T) { - spec := job.Job{BlockhashStoreSpec: &job.BlockhashStoreSpec{ - WaitBlocks: defaultWaitBlocks - 1, - }} - _, err := delegate.ServicesForSpec(spec) - assert.Error(t, err) - }) - t.Run("missing EnabledKeysForChain", func(t *testing.T) { _, err := testData.ethKeyStore.Delete(testData.sendingKey.ID()) require.NoError(t, err) diff --git a/core/services/blockhashstore/feeder.go b/core/services/blockhashstore/feeder.go index 22bbf7f163d..14e51e68394 100644 --- a/core/services/blockhashstore/feeder.go +++ b/core/services/blockhashstore/feeder.go @@ -37,6 +37,7 @@ func NewFeeder( lookbackBlocks: lookbackBlocks, latestBlock: latestBlock, stored: make(map[uint64]struct{}), + storedTrusted: make(map[uint64]common.Hash), lastRunBlock: 0, wgStored: sync.WaitGroup{}, } @@ -54,12 +55,12 @@ type Feeder struct { lookbackBlocks int latestBlock func(ctx context.Context) (uint64, error) - stored map[uint64]struct{} - lastRunBlock uint64 - wgStored sync.WaitGroup - batchLock sync.Mutex - storedLock sync.RWMutex - errsLock sync.Mutex + stored map[uint64]struct{} // used for trustless feeder + storedTrusted map[uint64]common.Hash // used for trusted feeder + lastRunBlock uint64 + wgStored sync.WaitGroup + batchLock sync.Mutex + errsLock sync.Mutex } // Run the feeder. @@ -103,10 +104,10 @@ func (f *Feeder) Run(ctx context.Context) error { "block", block) errs = multierr.Append(errs, errors.Wrap(err, "checking if stored")) } else if stored { + // IsStored() can be based on unfinalized blocks. Therefore, f.stored mapping is not updated f.lggr.Infow("Blockhash already stored", "block", block, "latestBlock", latestBlock, "unfulfilledReqIDs", LimitReqIDs(unfulfilledReqs, 50)) - f.stored[block] = struct{}{} continue } @@ -161,13 +162,6 @@ func (f *Feeder) runTrusted( if len(unfulfilled) == 0 { return } - f.storedLock.RLock() - if _, ok := f.stored[block]; ok { - // Already stored - f.storedLock.RUnlock() - return - } - f.storedLock.RUnlock() // Do not store a block if it has been marked as stored; otherwise, store it even // if the RPC call errors, as to be conservative. @@ -185,9 +179,6 @@ func (f *Feeder) runTrusted( f.lggr.Infow("Blockhash already stored", "block", block, "latestBlock", latestBlock, "unfulfilledReqIDs", LimitReqIDs(unfulfilled, 50)) - f.storedLock.Lock() - f.stored[block] = struct{}{} - f.storedLock.Unlock() return } @@ -224,15 +215,23 @@ func (f *Feeder) runTrusted( // append its blockhash to our blockhashes we want to store. // If it is the log poller block pertaining to our recent block number, assig it. for _, b := range lpBlocks { + if b.BlockNumber == int64(latestBlock) { + latestBlockhash = b.BlockHash + } + if f.storedTrusted[uint64(b.BlockNumber)] == b.BlockHash { + // blockhash is already stored. skip to save gas + continue + } if _, ok := batch[uint64(b.BlockNumber)]; ok { blocksToStore = append(blocksToStore, uint64(b.BlockNumber)) blockhashesToStore = append(blockhashesToStore, b.BlockHash) } - if b.BlockNumber == int64(latestBlock) { - latestBlockhash = b.BlockHash - } } + if len(blocksToStore) == 0 { + f.lggr.Debugw("no blocks to store", "latestBlock", latestBlock) + return errs + } // Store the batch of blocks and their blockhashes. err = f.bhs.StoreTrusted(ctx, blocksToStore, blockhashesToStore, latestBlock, latestBlockhash) if err != nil { @@ -246,12 +245,15 @@ func (f *Feeder) runTrusted( errs = multierr.Append(errs, errors.Wrap(err, "checking if stored")) return errs } + for i, block := range blocksToStore { + f.storedTrusted[block] = blockhashesToStore[i] + } } - // Prune stored, anything older than fromBlock can be discarded. - for b := range f.stored { + // Prune storedTrusted, anything older than fromBlock can be discarded. + for b := range f.storedTrusted { if b < fromBlock { - delete(f.stored, b) + delete(f.storedTrusted, b) } } diff --git a/core/services/blockhashstore/feeder_test.go b/core/services/blockhashstore/feeder_test.go index 7efb7052985..e015253ba28 100644 --- a/core/services/blockhashstore/feeder_test.go +++ b/core/services/blockhashstore/feeder_test.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "golang.org/x/exp/maps" mocklp "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -46,61 +47,67 @@ var ( _ Coordinator = &TestCoordinator{} _ BHS = &TestBHS{} tests = []struct { - name string - requests []Event - fulfillments []Event - wait int - lookback int - latest uint64 - bhs TestBHS - expectedStored []uint64 - expectedErrMsg string + name string + requests []Event + fulfillments []Event + wait int + lookback int + latest uint64 + bhs TestBHS + expectedStored []uint64 + expectedStoredMapBlocks []uint64 // expected state of stored map in Feeder struct + expectedErrMsg string }{ { - name: "single unfulfilled request", - requests: []Event{{Block: 150, ID: "1000"}}, - wait: 25, - lookback: 100, - latest: 200, - expectedStored: []uint64{150}, + name: "single unfulfilled request", + requests: []Event{{Block: 150, ID: "1000"}}, + wait: 25, + lookback: 100, + latest: 200, + expectedStored: []uint64{150}, + expectedStoredMapBlocks: []uint64{150}, }, { - name: "single fulfilled request", - requests: []Event{{Block: 150, ID: "1000"}}, - fulfillments: []Event{{Block: 155, ID: "1000"}}, - wait: 25, - lookback: 100, - latest: 200, - expectedStored: []uint64{}, + name: "single fulfilled request", + requests: []Event{{Block: 150, ID: "1000"}}, + fulfillments: []Event{{Block: 155, ID: "1000"}}, + wait: 25, + lookback: 100, + latest: 200, + expectedStored: []uint64{}, + expectedStoredMapBlocks: []uint64{}, }, { - name: "single already fulfilled", - requests: []Event{{Block: 150, ID: "1000"}}, - wait: 25, - lookback: 100, - latest: 200, - bhs: TestBHS{Stored: []uint64{150}}, - expectedStored: []uint64{150}, + name: "single already fulfilled", + requests: []Event{{Block: 150, ID: "1000"}}, + wait: 25, + lookback: 100, + latest: 200, + bhs: TestBHS{Stored: []uint64{150}}, + expectedStored: []uint64{150}, + expectedStoredMapBlocks: []uint64{}, }, { - name: "error checking if stored, store anyway", - requests: []Event{{Block: 150, ID: "1000"}}, - wait: 25, - lookback: 100, - latest: 200, - bhs: TestBHS{ErrorsIsStored: []uint64{150}}, - expectedStored: []uint64{150}, - expectedErrMsg: "checking if stored: error checking if stored", + name: "error checking if stored, store anyway", + requests: []Event{{Block: 150, ID: "1000"}}, + wait: 25, + lookback: 100, + latest: 200, + bhs: TestBHS{ErrorsIsStored: []uint64{150}}, + expectedStored: []uint64{150}, + expectedStoredMapBlocks: []uint64{150}, + expectedErrMsg: "checking if stored: error checking if stored", }, { - name: "error storing, continue to next block anyway", - requests: []Event{{Block: 150, ID: "1000"}, {Block: 151, ID: "1000"}}, - wait: 25, - lookback: 100, - latest: 200, - bhs: TestBHS{ErrorsStore: []uint64{150}}, - expectedStored: []uint64{151}, - expectedErrMsg: "storing block: error storing", + name: "error storing, continue to next block anyway", + requests: []Event{{Block: 150, ID: "1000"}, {Block: 151, ID: "1000"}}, + wait: 25, + lookback: 100, + latest: 200, + bhs: TestBHS{ErrorsStore: []uint64{150}}, + expectedStored: []uint64{151}, + expectedStoredMapBlocks: []uint64{151}, + expectedErrMsg: "storing block: error storing", }, { name: "multiple requests same block, some fulfilled", @@ -111,10 +118,11 @@ var ( fulfillments: []Event{ {Block: 150, ID: "10001"}, {Block: 150, ID: "10003"}}, - wait: 25, - lookback: 100, - latest: 200, - expectedStored: []uint64{150}, + wait: 25, + lookback: 100, + latest: 200, + expectedStored: []uint64{150}, + expectedStoredMapBlocks: []uint64{150}, }, { name: "multiple requests same block, all fulfilled", @@ -126,52 +134,58 @@ var ( {Block: 150, ID: "10001"}, {Block: 150, ID: "10002"}, {Block: 150, ID: "10003"}}, - wait: 25, - lookback: 100, - latest: 200, - expectedStored: []uint64{}, + wait: 25, + lookback: 100, + latest: 200, + expectedStored: []uint64{}, + expectedStoredMapBlocks: []uint64{}, }, { - name: "fulfillment no matching request no error", - requests: []Event{{Block: 150, ID: "1000"}}, - fulfillments: []Event{{Block: 199, ID: "10002"}}, - wait: 25, - lookback: 100, - latest: 200, - expectedStored: []uint64{150}, + name: "fulfillment no matching request no error", + requests: []Event{{Block: 150, ID: "1000"}}, + fulfillments: []Event{{Block: 199, ID: "10002"}}, + wait: 25, + lookback: 100, + latest: 200, + expectedStored: []uint64{150}, + expectedStoredMapBlocks: []uint64{150}, }, { - name: "multiple unfulfilled requests", - requests: []Event{{Block: 150, ID: "10001"}, {Block: 151, ID: "10002"}}, - wait: 25, - lookback: 100, - latest: 200, - expectedStored: []uint64{150, 151}, + name: "multiple unfulfilled requests", + requests: []Event{{Block: 150, ID: "10001"}, {Block: 151, ID: "10002"}}, + wait: 25, + lookback: 100, + latest: 200, + expectedStored: []uint64{150, 151}, + expectedStoredMapBlocks: []uint64{150, 151}, }, { - name: "multiple fulfilled requests", - requests: []Event{{Block: 150, ID: "10001"}, {Block: 151, ID: "10002"}}, - fulfillments: []Event{{Block: 150, ID: "10001"}, {Block: 151, ID: "10002"}}, - wait: 25, - lookback: 100, - latest: 200, - expectedStored: []uint64{}, + name: "multiple fulfilled requests", + requests: []Event{{Block: 150, ID: "10001"}, {Block: 151, ID: "10002"}}, + fulfillments: []Event{{Block: 150, ID: "10001"}, {Block: 151, ID: "10002"}}, + wait: 25, + lookback: 100, + latest: 200, + expectedStored: []uint64{}, + expectedStoredMapBlocks: []uint64{}, }, { - name: "recent unfulfilled request do not store", - requests: []Event{{Block: 185, ID: "1000"}}, - wait: 25, - lookback: 100, - latest: 200, - expectedStored: []uint64{}, + name: "recent unfulfilled request do not store", + requests: []Event{{Block: 185, ID: "1000"}}, + wait: 25, + lookback: 100, + latest: 200, + expectedStored: []uint64{}, + expectedStoredMapBlocks: []uint64{}, }, { - name: "old unfulfilled request do not store", - requests: []Event{{Block: 99, ID: "1000"}, {Block: 57, ID: "1000"}}, - wait: 25, - lookback: 100, - latest: 200, - expectedStored: []uint64{}, + name: "old unfulfilled request do not store", + requests: []Event{{Block: 99, ID: "1000"}, {Block: 57, ID: "1000"}}, + wait: 25, + lookback: 100, + latest: 200, + expectedStored: []uint64{}, + expectedStoredMapBlocks: []uint64{}, }, { name: "mixed", @@ -204,18 +218,20 @@ var ( // Block 154 {Block: 154, ID: "10007"}}, - wait: 25, - lookback: 100, - latest: 200, - expectedStored: []uint64{150, 153}, + wait: 25, + lookback: 100, + latest: 200, + expectedStored: []uint64{150, 153}, + expectedStoredMapBlocks: []uint64{150, 153}, }, { - name: "lookback before 0th block", - requests: []Event{{Block: 20, ID: "1000"}}, - wait: 25, - lookback: 100, - latest: 50, - expectedStored: []uint64{20}, + name: "lookback before 0th block", + requests: []Event{{Block: 20, ID: "1000"}}, + wait: 25, + lookback: 100, + latest: 50, + expectedStored: []uint64{20}, + expectedStoredMapBlocks: []uint64{20}, }, } ) @@ -250,6 +266,7 @@ func TestFeeder(t *testing.T) { } require.ElementsMatch(t, test.expectedStored, test.bhs.Stored) + require.ElementsMatch(t, test.expectedStoredMapBlocks, maps.Keys(feeder.stored)) }) } } @@ -341,6 +358,7 @@ func TestFeederWithLogPollerVRFv1(t *testing.T) { require.EqualError(t, err, test.expectedErrMsg) } require.ElementsMatch(t, test.expectedStored, test.bhs.Stored) + require.ElementsMatch(t, test.expectedStoredMapBlocks, maps.Keys(feeder.stored)) }) } } @@ -436,6 +454,7 @@ func TestFeederWithLogPollerVRFv2(t *testing.T) { require.EqualError(t, err, test.expectedErrMsg) } require.ElementsMatch(t, test.expectedStored, test.bhs.Stored) + require.ElementsMatch(t, test.expectedStoredMapBlocks, maps.Keys(feeder.stored)) }) } } @@ -531,6 +550,7 @@ func TestFeederWithLogPollerVRFv2Plus(t *testing.T) { require.EqualError(t, err, test.expectedErrMsg) } require.ElementsMatch(t, test.expectedStored, test.bhs.Stored) + require.ElementsMatch(t, test.expectedStoredMapBlocks, maps.Keys(feeder.stored)) }) } } From 2d574bec1c3d188aadd670516d6ae0554acbefd9 Mon Sep 17 00:00:00 2001 From: Justin Kaseman Date: Sat, 2 Sep 2023 02:12:57 -0400 Subject: [PATCH 03/14] Upgrade forge-std to 1.6.0 (#10459) --- contracts/foundry-lib/forge-std | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/foundry-lib/forge-std b/contracts/foundry-lib/forge-std index f4264050aca..1d9650e9512 160000 --- a/contracts/foundry-lib/forge-std +++ b/contracts/foundry-lib/forge-std @@ -1 +1 @@ -Subproject commit f4264050aca5a2eedf243f9bd54b544c5a373bd2 +Subproject commit 1d9650e951204a0ddce9ff89c32f1997984cef4d From 5b78a81aba14db55aecd6bb41e936c8cf39b3f6d Mon Sep 17 00:00:00 2001 From: Rens Rooimans Date: Sat, 2 Sep 2023 08:13:10 +0200 Subject: [PATCH 04/14] add foundry refresh make command (#10442) --- contracts/GNUmakefile | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/contracts/GNUmakefile b/contracts/GNUmakefile index ea70ae43f93..501ef968482 100644 --- a/contracts/GNUmakefile +++ b/contracts/GNUmakefile @@ -31,6 +31,15 @@ pnpmdep: ## Install solidity contract dependencies through pnpm abigen: ## Build & install abigen. ../tools/bin/build_abigen +.PHONY: mockery +mockery: $(mockery) ## Install mockery. + go install github.com/vektra/mockery/v2@v2.28.1 + +.PHONY: foundry-refresh +foundry-refresh: + foundryup + git submodule deinit -f . + git submodule update --init --recursive # To generate gethwrappers for a specific product, either set the `FOUNDRY_PROFILE` # env var or call the target with `FOUNDRY_PROFILE=product` @@ -43,7 +52,7 @@ abigen: ## Build & install abigen. # make call example # make FOUNDRY_PROFILE=llo-feeds wrappers .PHONY: wrappers -wrappers: pnpmdep abigen ## Recompiles solidity contracts and their go wrappers. +wrappers: pnpmdep mockery abigen ## Recompiles solidity contracts and their go wrappers. ./scripts/native_solc_compile_all_$(FOUNDRY_PROFILE) go generate ../core/gethwrappers/$(FOUNDRY_PROFILE) @@ -51,7 +60,7 @@ wrappers: pnpmdep abigen ## Recompiles solidity contracts and their go wrappers. # assumption that native_solc_compile_all contains sub-calls to each product, and # go_generate does the same. .PHONY: wrappers-all -wrappers-all: pnpmdep abigen ## Recompiles solidity contracts and their go wrappers. +wrappers-all: pnpmdep mockery abigen ## Recompiles solidity contracts and their go wrappers. # go_generate contains a call to compile all contracts before generating wrappers go generate ../core/gethwrappers/go_generate.go From 6954c90b8df07fc115563a319bf9d794f3ab8057 Mon Sep 17 00:00:00 2001 From: Akshay Aggarwal <71980293+infiloop2@users.noreply.github.com> Date: Sat, 2 Sep 2023 20:57:20 +0100 Subject: [PATCH 05/14] Add debug logs when updating lastPoll / lastRepoll block (#10461) * Add debug logs when updating lastPoll / lastRepoll block * update to use uf1 --- .../ocr2/plugins/ocr2keeper/evm21/logprovider/provider.go | 1 + .../ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer.go | 1 + 2 files changed, 2 insertions(+) diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider.go index 84d373f03b6..acb3e2eaff1 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider.go +++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider.go @@ -318,6 +318,7 @@ func (p *logEventProvider) updateFiltersLastPoll(entries []upkeepFilter) { p.filterStore.UpdateFilters(func(orig, f upkeepFilter) upkeepFilter { if f.lastPollBlock > orig.lastPollBlock { orig.lastPollBlock = f.lastPollBlock + p.lggr.Debugw("Updated lastPollBlock", "lastPollBlock", f.lastPollBlock, "upkeepID", f.upkeepID) } return orig }, entries...) diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer.go index 7ac981e9952..5acfa1ee0c8 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer.go +++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/recoverer.go @@ -355,6 +355,7 @@ func (r *logRecoverer) recoverFilter(ctx context.Context, f upkeepFilter, startB } r.filterStore.UpdateFilters(func(uf1, uf2 upkeepFilter) upkeepFilter { uf1.lastRePollBlock = end + r.lggr.Debugw("Updated lastRePollBlock", "lastRePollBlock", end, "upkeepID", uf1.upkeepID) return uf1 }, f) From 2837bafb411e26192a309b62c29e2775a71c0a8f Mon Sep 17 00:00:00 2001 From: Jordan Krage Date: Sun, 3 Sep 2023 11:11:38 -0500 Subject: [PATCH 06/14] bump pyroscope; use new import paths (#10463) --- core/logger/pyroscope.go | 2 +- core/scripts/go.mod | 4 ++-- core/scripts/go.sum | 8 ++++---- core/services/chainlink/application.go | 2 +- go.mod | 4 ++-- go.sum | 8 ++++---- integration-tests/go.mod | 3 ++- integration-tests/go.sum | 5 ++++- 8 files changed, 20 insertions(+), 16 deletions(-) diff --git a/core/logger/pyroscope.go b/core/logger/pyroscope.go index 3303fe51dee..226c241d36d 100644 --- a/core/logger/pyroscope.go +++ b/core/logger/pyroscope.go @@ -3,7 +3,7 @@ package logger import ( "runtime" - "github.com/pyroscope-io/client/pyroscope" + "github.com/grafana/pyroscope-go" "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/static" diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 2a81e2bb05b..8966ac2d2f4 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -147,6 +147,8 @@ require ( github.com/gorilla/securecookie v1.1.1 // indirect github.com/gorilla/sessions v1.2.1 // indirect github.com/gorilla/websocket v1.5.0 // indirect + github.com/grafana/pyroscope-go v1.0.2 // indirect + github.com/grafana/pyroscope-go/godeltaprof v0.1.3 // indirect github.com/graph-gophers/dataloader v5.0.0+incompatible // indirect github.com/graph-gophers/graphql-go v1.3.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect @@ -283,8 +285,6 @@ require ( github.com/prometheus/common v0.44.0 // indirect github.com/prometheus/procfs v0.11.0 // indirect github.com/prometheus/prometheus v0.46.0 // indirect - github.com/pyroscope-io/client v0.7.1 // indirect - github.com/pyroscope-io/godeltaprof v0.1.2 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/rjeczalik/notify v0.9.3 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 708688e5e1f..1a4bba2fccc 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -570,6 +570,10 @@ github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +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/graph-gophers/dataloader v5.0.0+incompatible h1:R+yjsbrNq1Mo3aPG+Z/EKYrXrXXUNJHOgbRt+U6jOug= github.com/graph-gophers/dataloader v5.0.0+incompatible/go.mod h1:jk4jk0c5ZISbKaMe8WsVopGB5/15GvGHMdMdPtwlRp4= github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= @@ -1308,10 +1312,6 @@ github.com/prometheus/procfs v0.11.0/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPH github.com/prometheus/prometheus v0.46.0 h1:9JSdXnsuT6YsbODEhSQMwxNkGwPExfmzqG73vCMk/Kw= github.com/prometheus/prometheus v0.46.0/go.mod h1:10L5IJE5CEsjee1FnOcVswYXlPIscDWWt3IJ2UDYrz4= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -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= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index d56f4d3f257..b2e8719e607 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -11,8 +11,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/google/uuid" + "github.com/grafana/pyroscope-go" "github.com/pkg/errors" - "github.com/pyroscope-io/client/pyroscope" "go.uber.org/multierr" "go.uber.org/zap/zapcore" diff --git a/go.mod b/go.mod index 6cb4b175cb1..a2007f5bac3 100644 --- a/go.mod +++ b/go.mod @@ -29,6 +29,7 @@ require ( github.com/gorilla/securecookie v1.1.1 github.com/gorilla/sessions v1.2.1 github.com/gorilla/websocket v1.5.0 + github.com/grafana/pyroscope-go v1.0.2 github.com/graph-gophers/dataloader v5.0.0+incompatible github.com/graph-gophers/graphql-go v1.3.0 github.com/hashicorp/go-plugin v1.4.10 @@ -58,7 +59,6 @@ require ( github.com/prometheus/client_model v0.4.0 github.com/prometheus/common v0.44.0 github.com/prometheus/prometheus v0.46.0 - github.com/pyroscope-io/client v0.7.1 github.com/robfig/cron/v3 v3.0.1 github.com/rogpeppe/go-internal v1.11.0 github.com/scylladb/go-reflectx v1.0.1 @@ -195,6 +195,7 @@ require ( github.com/google/gofuzz v1.2.0 // indirect github.com/google/gopacket v1.1.19 // indirect github.com/gorilla/context v1.1.1 // indirect + github.com/grafana/pyroscope-go/godeltaprof v0.1.3 // 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/v2 v2.0.0-rc.3 // indirect @@ -308,7 +309,6 @@ require ( 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/prometheus/procfs v0.11.0 // indirect - github.com/pyroscope-io/godeltaprof v0.1.0 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect diff --git a/go.sum b/go.sum index 4c07fe3735b..4deab41bc40 100644 --- a/go.sum +++ b/go.sum @@ -565,6 +565,10 @@ github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +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/graph-gophers/dataloader v5.0.0+incompatible h1:R+yjsbrNq1Mo3aPG+Z/EKYrXrXXUNJHOgbRt+U6jOug= github.com/graph-gophers/dataloader v5.0.0+incompatible/go.mod h1:jk4jk0c5ZISbKaMe8WsVopGB5/15GvGHMdMdPtwlRp4= github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= @@ -1310,10 +1314,6 @@ github.com/prometheus/procfs v0.11.0/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPH github.com/prometheus/prometheus v0.46.0 h1:9JSdXnsuT6YsbODEhSQMwxNkGwPExfmzqG73vCMk/Kw= github.com/prometheus/prometheus v0.46.0/go.mod h1:10L5IJE5CEsjee1FnOcVswYXlPIscDWWt3IJ2UDYrz4= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -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.0 h1:UBqtjt0yZi4jTxqZmLAs34XG6ycS3vUTlhEUSq4NHLE= -github.com/pyroscope-io/godeltaprof v0.1.0/go.mod h1:psMITXp90+8pFenXkKIpNhrfmI9saQnPbba27VIaiQE= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index bb9bf9cfff0..32e13bbd80e 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -202,6 +202,8 @@ 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/regexp v0.0.0-20221122212121-6b5c0a4cb7fd // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect @@ -366,7 +368,6 @@ require ( github.com/prometheus/procfs v0.11.0 // indirect github.com/prometheus/prometheus v0.46.0 // indirect github.com/pyroscope-io/client v0.7.1 // indirect - github.com/pyroscope-io/godeltaprof v0.1.2 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 87b904bceb4..b5948436181 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1289,6 +1289,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/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= @@ -2166,7 +2170,6 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T 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= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= From 528dfc608f9f84a4eeaab3efb2e559f41cb85f34 Mon Sep 17 00:00:00 2001 From: Anirudh Warrier Date: Mon, 4 Sep 2023 10:53:15 +0530 Subject: [PATCH 07/14] [AUTO-4790] increase delta stage for integration-tests (#10398) * Update keeper_test.go * set deltaStage 30s * automation tests - set deltaStage 30s --- integration-tests/benchmark/keeper_test.go | 4 ++-- integration-tests/chaos/automation_chaos_test.go | 2 +- integration-tests/reorg/automation_reorg_test.go | 2 +- integration-tests/smoke/automation_test.go | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/integration-tests/benchmark/keeper_test.go b/integration-tests/benchmark/keeper_test.go index 491d4fe1f3d..6ce0fb7138f 100644 --- a/integration-tests/benchmark/keeper_test.go +++ b/integration-tests/benchmark/keeper_test.go @@ -244,13 +244,13 @@ var networkConfig = map[string]NetworkConfig{ "SimulatedGeth": { upkeepSLA: int64(20), blockTime: time.Second, - deltaStage: time.Duration(0), + deltaStage: 30 * time.Second, funding: big.NewFloat(100_000), }, "geth": { upkeepSLA: int64(20), blockTime: time.Second, - deltaStage: time.Duration(0), + deltaStage: 30 * time.Second, funding: big.NewFloat(100_000), }, "GoerliTestnet": { diff --git a/integration-tests/chaos/automation_chaos_test.go b/integration-tests/chaos/automation_chaos_test.go index ee6562aa5b4..0da3271785e 100644 --- a/integration-tests/chaos/automation_chaos_test.go +++ b/integration-tests/chaos/automation_chaos_test.go @@ -240,7 +240,7 @@ func TestAutomationChaos(t *testing.T) { 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(), 5*time.Second) + 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") diff --git a/integration-tests/reorg/automation_reorg_test.go b/integration-tests/reorg/automation_reorg_test.go index f1a1bfcc6ad..4a75d92d5d1 100644 --- a/integration-tests/reorg/automation_reorg_test.go +++ b/integration-tests/reorg/automation_reorg_test.go @@ -183,7 +183,7 @@ func TestAutomationReorg(t *testing.T) { 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(), 5*time.Second) + 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") diff --git a/integration-tests/smoke/automation_test.go b/integration-tests/smoke/automation_test.go index 5aa7668d151..57ca733b594 100644 --- a/integration-tests/smoke/automation_test.go +++ b/integration-tests/smoke/automation_test.go @@ -767,7 +767,7 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) { highCheckGasLimit := automationDefaultRegistryConfig highCheckGasLimit.CheckGasLimit = uint32(5000000) highCheckGasLimit.RegistryVersion = registryVersion - ocrConfig, err := actions.BuildAutoOCR2ConfigVars(t, nodesWithoutBootstrap, highCheckGasLimit, registrar.Address(), 5*time.Second) + ocrConfig, err := actions.BuildAutoOCR2ConfigVars(t, nodesWithoutBootstrap, highCheckGasLimit, registrar.Address(), 30*time.Second) require.NoError(t, err, "Error building OCR config") err = registry.SetConfig(highCheckGasLimit, ocrConfig) @@ -951,7 +951,7 @@ func setupAutomationTest( actions.CreateOCRKeeperJobs(t, chainlinkNodes, registry.Address(), network.ChainID, 0, registryVersion) nodesWithoutBootstrap := chainlinkNodes[1:] - ocrConfig, err := actions.BuildAutoOCR2ConfigVars(t, nodesWithoutBootstrap, registryConfig, registrar.Address(), 5*time.Second) + ocrConfig, err := actions.BuildAutoOCR2ConfigVars(t, nodesWithoutBootstrap, registryConfig, registrar.Address(), 30*time.Second) require.NoError(t, err, "Error building OCR config vars") err = registry.SetConfig(automationDefaultRegistryConfig, ocrConfig) require.NoError(t, err, "Registry config should be set successfully") From 39f7cde8e3a03697b427611fd820c295605fcf16 Mon Sep 17 00:00:00 2001 From: Makram Date: Mon, 4 Sep 2023 12:07:22 +0300 Subject: [PATCH 08/14] chore: skip ocr2vrf tests (#10448) due to flakiness --- .../plugins/ocr2vrf/internal/ocr2vrf_integration_test.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go b/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go index dbd8f830f79..c6a4552683a 100644 --- a/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go +++ b/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go @@ -8,7 +8,6 @@ import ( "fmt" "math/big" "net" - "os" "testing" "time" @@ -323,16 +322,12 @@ func setupNodeOCR2( } func TestIntegration_OCR2VRF_ForwarderFlow(t *testing.T) { - if os.Getenv("CI") == "" && os.Getenv("VRF_LOCAL_TESTING") == "" { - t.Skip("Skipping test locally.") - } + t.Skip() runOCR2VRFTest(t, true) } func TestIntegration_OCR2VRF(t *testing.T) { - if os.Getenv("CI") == "" && os.Getenv("VRF_LOCAL_TESTING") == "" { - t.Skip("Skipping test locally.") - } + t.Skip() runOCR2VRFTest(t, false) } From fe6fd64a912dfcd75e203550fefac6514faf95a6 Mon Sep 17 00:00:00 2001 From: Akshay Aggarwal <71980293+infiloop2@users.noreply.github.com> Date: Mon, 4 Sep 2023 11:37:00 +0100 Subject: [PATCH 09/14] Fix bug in updating last poll block for filter (#10462) --- .../plugins/ocr2keeper/evm21/logprovider/provider.go | 6 ++++-- .../ocr2keeper/evm21/logprovider/provider_test.go | 12 +++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider.go index acb3e2eaff1..8fbbb1e0a9d 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider.go +++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider.go @@ -363,7 +363,7 @@ func (p *logEventProvider) readLogs(ctx context.Context, latest int64, filters [ // maxBurst will be used to increase the burst limit to allow a long range scan maxBurst := int(lookbackBlocks + 1) - for _, filter := range filters { + for i, filter := range filters { if len(filter.addr) == 0 { continue } @@ -408,7 +408,9 @@ func (p *logEventProvider) readLogs(ctx context.Context, latest int64, filters [ p.buffer.enqueue(filter.upkeepID, filteredLogs...) - filter.lastPollBlock = latest + // Update the lastPollBlock for filter in slice this is then + // updated into filter store in updateFiltersLastPoll + filters[i].lastPollBlock = latest } return merr diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_test.go index 9e3eb8565c3..159e229a2ff 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/provider_test.go @@ -255,7 +255,8 @@ func TestLogEventProvider_ReadLogs(t *testing.T) { }, }, nil) - p := NewLogProvider(logger.TestLogger(t), mp, &mockedPacker{}, NewUpkeepFilterStore(), NewOptions(200)) + filterStore := NewUpkeepFilterStore() + p := NewLogProvider(logger.TestLogger(t), mp, &mockedPacker{}, filterStore, NewOptions(200)) var ids []*big.Int for i := 0; i < 10; i++ { @@ -277,6 +278,15 @@ func TestLogEventProvider_ReadLogs(t *testing.T) { require.NoError(t, p.ReadLogs(ctx, ids[:2]...)) logs := p.buffer.peek(10) require.Len(t, logs, 2) + + var updatedFilters []upkeepFilter + filterStore.RangeFiltersByIDs(func(i int, f upkeepFilter) { + updatedFilters = append(updatedFilters, f.Clone()) + }, ids[:2]...) + for _, f := range updatedFilters { + // Last poll block should be updated + require.Equal(t, int64(1), f.lastPollBlock) + } }) // TODO: test rate limiting From f07c491fd7ae3bb0b966ff6d12c4a4f83a4934ef Mon Sep 17 00:00:00 2001 From: Makram Date: Mon, 4 Sep 2023 19:59:40 +0400 Subject: [PATCH 10/14] chore: fix shared snapshot (#10471) * chore: fix shared snapshot * empty commit to trigger CI again * another empty to trigger ci * fix: add snapshots to filters * chore: update all snapshots * chore: add .gitmodules and foundry-lib to filters --- .github/workflows/solidity-foundry.yml | 3 + .../gas-snapshots/automation-dev.gas-snapshot | 4 +- .../gas-snapshots/automation.gas-snapshot | 8 +- .../gas-snapshots/functions.gas-snapshot | 16 +- .../gas-snapshots/llo-feeds.gas-snapshot | 432 +++++++++--------- contracts/gas-snapshots/shared.gas-snapshot | 38 +- contracts/gas-snapshots/vrf.gas-snapshot | 28 +- 7 files changed, 266 insertions(+), 263 deletions(-) diff --git a/.github/workflows/solidity-foundry.yml b/.github/workflows/solidity-foundry.yml index 45f1d8e9d79..abdb64d1763 100644 --- a/.github/workflows/solidity-foundry.yml +++ b/.github/workflows/solidity-foundry.yml @@ -23,6 +23,9 @@ jobs: - 'contracts/src/v0.8/**/*' - '.github/workflows/solidity-foundry.yml' - 'contracts/foundry.toml' + - 'contracts/gas-snapshots/*.gas-snapshot' + - '.gitmodules' + - 'contracts/foundry-lib' tests: strategy: diff --git a/contracts/gas-snapshots/automation-dev.gas-snapshot b/contracts/gas-snapshots/automation-dev.gas-snapshot index 1a939d69e19..badbfba604c 100644 --- a/contracts/gas-snapshots/automation-dev.gas-snapshot +++ b/contracts/gas-snapshots/automation-dev.gas-snapshot @@ -1,5 +1,5 @@ AutomationForwarder_forward:testBasicSuccess() (gas: 87630) -AutomationForwarder_forward:testNotAuthorizedReverts() (gas: 21681) +AutomationForwarder_forward:testNotAuthorizedReverts() (gas: 25427) AutomationForwarder_forward:testWrongFunctionSelectorSuccess() (gas: 17958) AutomationForwarder_updateRegistry:testBasicSuccess() (gas: 14577) -AutomationForwarder_updateRegistry:testNotFromRegistryNotAuthorizedReverts() (gas: 13893) \ No newline at end of file +AutomationForwarder_updateRegistry:testNotFromRegistryNotAuthorizedReverts() (gas: 17665) \ No newline at end of file diff --git a/contracts/gas-snapshots/automation.gas-snapshot b/contracts/gas-snapshots/automation.gas-snapshot index 934aebf982d..a90453b1029 100644 --- a/contracts/gas-snapshots/automation.gas-snapshot +++ b/contracts/gas-snapshots/automation.gas-snapshot @@ -1,8 +1,8 @@ HeartbeatRequester_getAggregatorRequestHeartbeat:testBasicSuccess() (gas: 75412) HeartbeatRequester_getAggregatorRequestHeartbeat:testHeartbeatNotPermittedReverts() (gas: 21730) -HeartbeatRequester_permitHeartbeat:testBasicDeployerSuccess() (gas: 48280) -HeartbeatRequester_permitHeartbeat:testBasicSuccess() (gas: 45856) -HeartbeatRequester_permitHeartbeat:testOnlyCallableByOwnerReverts() (gas: 13796) +HeartbeatRequester_permitHeartbeat:testBasicDeployerSuccess() (gas: 48229) +HeartbeatRequester_permitHeartbeat:testBasicSuccess() (gas: 45844) +HeartbeatRequester_permitHeartbeat:testOnlyCallableByOwnerReverts() (gas: 17584) HeartbeatRequester_removeHeartbeat:testBasicSuccess() (gas: 30192) -HeartbeatRequester_removeHeartbeat:testOnlyCallableByOwnerReverts() (gas: 11629) +HeartbeatRequester_removeHeartbeat:testOnlyCallableByOwnerReverts() (gas: 15417) HeartbeatRequester_removeHeartbeat:testRemoveNoPermitsSuccess() (gas: 15660) \ No newline at end of file diff --git a/contracts/gas-snapshots/functions.gas-snapshot b/contracts/gas-snapshots/functions.gas-snapshot index fa2c9dba497..7ee4f779d6a 100644 --- a/contracts/gas-snapshots/functions.gas-snapshot +++ b/contracts/gas-snapshots/functions.gas-snapshot @@ -1,17 +1,17 @@ -FunctionsOracle_sendRequest:testEmptyRequestDataReverts() (gas: 13430) +FunctionsOracle_sendRequest:testEmptyRequestDataReverts() (gas: 13452) FunctionsOracle_setDONPublicKey:testEmptyPublicKeyReverts() (gas: 10974) FunctionsOracle_setDONPublicKey:testOnlyOwnerReverts() (gas: 11255) FunctionsOracle_setDONPublicKey:testSetDONPublicKeySuccess() (gas: 126453) -FunctionsOracle_setDONPublicKey:testSetDONPublicKey_gas() (gas: 97558) +FunctionsOracle_setDONPublicKey:testSetDONPublicKey_gas() (gas: 97580) FunctionsOracle_setRegistry:testEmptyPublicKeyReverts() (gas: 10635) FunctionsOracle_setRegistry:testOnlyOwnerReverts() (gas: 10927) FunctionsOracle_setRegistry:testSetRegistrySuccess() (gas: 35791) FunctionsOracle_setRegistry:testSetRegistry_gas() (gas: 31987) FunctionsOracle_typeAndVersion:testTypeAndVersionSuccess() (gas: 6905) -FunctionsRouter_Pause:test_Pause_RevertIfNotOwner() (gas: 13293) -FunctionsRouter_Pause:test_Pause_Success() (gas: 20205) -FunctionsRouter_Unpause:test_Unpause_RevertIfNotOwner() (gas: 13338) -FunctionsRouter_Unpause:test_Unpause_Success() (gas: 77279) -FunctionsSubscriptions_createSubscription:test_CreateSubscription_RevertIfNotAllowedSender() (gas: 26347) -FunctionsSubscriptions_createSubscription:test_CreateSubscription_RevertIfPaused() (gas: 15699) +FunctionsRouter_Pause:test_Pause_RevertIfNotOwner() (gas: 13315) +FunctionsRouter_Pause:test_Pause_Success() (gas: 20254) +FunctionsRouter_Unpause:test_Unpause_RevertIfNotOwner() (gas: 13294) +FunctionsRouter_Unpause:test_Unpause_Success() (gas: 77334) +FunctionsSubscriptions_createSubscription:test_CreateSubscription_RevertIfNotAllowedSender() (gas: 26368) +FunctionsSubscriptions_createSubscription:test_CreateSubscription_RevertIfPaused() (gas: 15714) FunctionsSubscriptions_createSubscription:test_CreateSubscription_Success() (gas: 152436) \ No newline at end of file diff --git a/contracts/gas-snapshots/llo-feeds.gas-snapshot b/contracts/gas-snapshots/llo-feeds.gas-snapshot index 482b3edc12b..18499e0f6c2 100644 --- a/contracts/gas-snapshots/llo-feeds.gas-snapshot +++ b/contracts/gas-snapshots/llo-feeds.gas-snapshot @@ -1,255 +1,255 @@ -FeeManagerProcessFeeTest:test_DiscountIsAppliedForNative() (gas: 47621) -FeeManagerProcessFeeTest:test_V1PayloadVerifies() (gas: 21051) -FeeManagerProcessFeeTest:test_V1PayloadVerifiesAndReturnsChange() (gas: 52298) -FeeManagerProcessFeeTest:test_V2PayloadVerifies() (gas: 112748) -FeeManagerProcessFeeTest:test_V2PayloadWithoutQuoteFails() (gas: 23646) -FeeManagerProcessFeeTest:test_V2PayloadWithoutZeroFee() (gas: 69576) -FeeManagerProcessFeeTest:test_WithdrawERC20() (gas: 63969) -FeeManagerProcessFeeTest:test_WithdrawNonAdminAddr() (gas: 48730) -FeeManagerProcessFeeTest:test_WithdrawUnwrappedNative() (gas: 20326) +FeeManagerProcessFeeTest:test_DiscountIsAppliedForNative() (gas: 52609) +FeeManagerProcessFeeTest:test_V1PayloadVerifies() (gas: 25927) +FeeManagerProcessFeeTest:test_V1PayloadVerifiesAndReturnsChange() (gas: 57240) +FeeManagerProcessFeeTest:test_V2PayloadVerifies() (gas: 120182) +FeeManagerProcessFeeTest:test_V2PayloadWithoutQuoteFails() (gas: 28588) +FeeManagerProcessFeeTest:test_V2PayloadWithoutZeroFee() (gas: 74518) +FeeManagerProcessFeeTest:test_WithdrawERC20() (gas: 71365) +FeeManagerProcessFeeTest:test_WithdrawNonAdminAddr() (gas: 56167) +FeeManagerProcessFeeTest:test_WithdrawUnwrappedNative() (gas: 25300) FeeManagerProcessFeeTest:test_baseFeeIsAppliedForLink() (gas: 14621) FeeManagerProcessFeeTest:test_baseFeeIsAppliedForNative() (gas: 17579) -FeeManagerProcessFeeTest:test_correctDiscountIsAppliedWhenBothTokensAreDiscounted() (gas: 83432) -FeeManagerProcessFeeTest:test_discountAIsNotAppliedWhenSetForOtherUsers() (gas: 51511) -FeeManagerProcessFeeTest:test_discountFeeRoundsDownWhenUneven() (gas: 47789) -FeeManagerProcessFeeTest:test_discountIsAppliedForLink() (gas: 44614) -FeeManagerProcessFeeTest:test_discountIsAppliedWith100PercentSurcharge() (gas: 71358) -FeeManagerProcessFeeTest:test_discountIsNoLongerAppliedAfterRemoving() (gas: 40470) -FeeManagerProcessFeeTest:test_discountIsNotAppliedForInvalidTokenAddress() (gas: 12600) -FeeManagerProcessFeeTest:test_discountIsNotAppliedToOtherFeeds() (gas: 49535) -FeeManagerProcessFeeTest:test_emptyQuoteRevertsWithError() (gas: 12339) -FeeManagerProcessFeeTest:test_eventIsEmittedAfterSurchargeIsSet() (gas: 36370) -FeeManagerProcessFeeTest:test_eventIsEmittedIfNotEnoughLink() (gas: 251051) -FeeManagerProcessFeeTest:test_eventIsEmittedUponWithdraw() (gas: 61024) -FeeManagerProcessFeeTest:test_feeIsUpdatedAfterDiscountIsRemoved() (gas: 43696) -FeeManagerProcessFeeTest:test_feeIsUpdatedAfterNewDiscountIsApplied() (gas: 60080) -FeeManagerProcessFeeTest:test_feeIsUpdatedAfterNewSurchargeIsApplied() (gas: 56719) -FeeManagerProcessFeeTest:test_feeIsZeroWith100PercentDiscount() (gas: 47021) +FeeManagerProcessFeeTest:test_correctDiscountIsAppliedWhenBothTokensAreDiscounted() (gas: 90869) +FeeManagerProcessFeeTest:test_discountAIsNotAppliedWhenSetForOtherUsers() (gas: 56477) +FeeManagerProcessFeeTest:test_discountFeeRoundsDownWhenUneven() (gas: 52755) +FeeManagerProcessFeeTest:test_discountIsAppliedForLink() (gas: 49580) +FeeManagerProcessFeeTest:test_discountIsAppliedWith100PercentSurcharge() (gas: 78792) +FeeManagerProcessFeeTest:test_discountIsNoLongerAppliedAfterRemoving() (gas: 46384) +FeeManagerProcessFeeTest:test_discountIsNotAppliedForInvalidTokenAddress() (gas: 17568) +FeeManagerProcessFeeTest:test_discountIsNotAppliedToOtherFeeds() (gas: 54523) +FeeManagerProcessFeeTest:test_emptyQuoteRevertsWithError() (gas: 12361) +FeeManagerProcessFeeTest:test_eventIsEmittedAfterSurchargeIsSet() (gas: 41347) +FeeManagerProcessFeeTest:test_eventIsEmittedIfNotEnoughLink() (gas: 260960) +FeeManagerProcessFeeTest:test_eventIsEmittedUponWithdraw() (gas: 68464) +FeeManagerProcessFeeTest:test_feeIsUpdatedAfterDiscountIsRemoved() (gas: 49645) +FeeManagerProcessFeeTest:test_feeIsUpdatedAfterNewDiscountIsApplied() (gas: 67562) +FeeManagerProcessFeeTest:test_feeIsUpdatedAfterNewSurchargeIsApplied() (gas: 64156) +FeeManagerProcessFeeTest:test_feeIsZeroWith100PercentDiscount() (gas: 51987) FeeManagerProcessFeeTest:test_getBaseRewardWithLinkQuote() (gas: 14641) -FeeManagerProcessFeeTest:test_getLinkFeeIsRoundedUp() (gas: 44805) -FeeManagerProcessFeeTest:test_getLinkRewardIsSameAsFee() (gas: 50542) -FeeManagerProcessFeeTest:test_getLinkRewardWithNativeQuoteAndSurchargeWithLinkDiscount() (gas: 75290) -FeeManagerProcessFeeTest:test_getRewardWithLinkDiscount() (gas: 44657) -FeeManagerProcessFeeTest:test_getRewardWithLinkQuoteAndLinkDiscount() (gas: 44615) +FeeManagerProcessFeeTest:test_getLinkFeeIsRoundedUp() (gas: 49771) +FeeManagerProcessFeeTest:test_getLinkRewardIsSameAsFee() (gas: 55510) +FeeManagerProcessFeeTest:test_getLinkRewardWithNativeQuoteAndSurchargeWithLinkDiscount() (gas: 82724) +FeeManagerProcessFeeTest:test_getRewardWithLinkDiscount() (gas: 49623) +FeeManagerProcessFeeTest:test_getRewardWithLinkQuoteAndLinkDiscount() (gas: 49581) FeeManagerProcessFeeTest:test_getRewardWithNativeQuote() (gas: 17579) -FeeManagerProcessFeeTest:test_getRewardWithNativeQuoteAndSurcharge() (gas: 45838) -FeeManagerProcessFeeTest:test_linkAvailableForPaymentReturnsLinkBalance() (gas: 47404) -FeeManagerProcessFeeTest:test_nativeSurcharge0Percent() (gas: 25823) -FeeManagerProcessFeeTest:test_nativeSurcharge100Percent() (gas: 45814) -FeeManagerProcessFeeTest:test_nativeSurchargeCannotExceed100Percent() (gas: 12211) -FeeManagerProcessFeeTest:test_nativeSurchargeEventIsEmittedOnUpdate() (gas: 36393) -FeeManagerProcessFeeTest:test_noFeeIsAppliedWhenReportHasZeroFee() (gas: 46866) -FeeManagerProcessFeeTest:test_noFeeIsAppliedWhenReportHasZeroFeeAndDiscountAndSurchargeIsSet() (gas: 70581) -FeeManagerProcessFeeTest:test_nonAdminProxyUserCannotProcessFee() (gas: 19160) -FeeManagerProcessFeeTest:test_nonAdminUserCanNotSetDiscount() (gas: 14846) -FeeManagerProcessFeeTest:test_payLinkDeficit() (gas: 187316) -FeeManagerProcessFeeTest:test_payLinkDeficitOnlyCallableByAdmin() (gas: 12367) -FeeManagerProcessFeeTest:test_payLinkDeficitPaysAllFeesProcessed() (gas: 206512) -FeeManagerProcessFeeTest:test_payLinkDeficitTwice() (gas: 189668) -FeeManagerProcessFeeTest:test_processFeeAsProxy() (gas: 113142) -FeeManagerProcessFeeTest:test_processFeeDefaultReportsStillVerifiesWithEmptyQuote() (gas: 21857) -FeeManagerProcessFeeTest:test_processFeeEmitsEventIfNotEnoughLink() (gas: 153995) -FeeManagerProcessFeeTest:test_processFeeIfSubscriberIsSelf() (gas: 22485) -FeeManagerProcessFeeTest:test_processFeeNative() (gas: 166691) -FeeManagerProcessFeeTest:test_processFeeUsesCorrectDigest() (gas: 114102) -FeeManagerProcessFeeTest:test_processFeeWithDefaultReportPayloadAndQuoteStillVerifies() (gas: 24176) -FeeManagerProcessFeeTest:test_processFeeWithInvalidReportVersionFailsToDecode() (gas: 25660) -FeeManagerProcessFeeTest:test_processFeeWithUnwrappedNative() (gas: 176693) -FeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeLinkAddress() (gas: 128211) -FeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeLinkAddressExcessiveFee() (gas: 152075) -FeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeShortFunds() (gas: 87203) -FeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeWithExcessiveFee() (gas: 183653) -FeeManagerProcessFeeTest:test_processFeeWithWithCorruptQuotePayload() (gas: 23529) -FeeManagerProcessFeeTest:test_processFeeWithWithEmptyQuotePayload() (gas: 23997) -FeeManagerProcessFeeTest:test_processFeeWithWithZeroQuotePayload() (gas: 24986) -FeeManagerProcessFeeTest:test_processFeeWithZeroLinkNonZeroNativeWithLinkQuote() (gas: 30202) -FeeManagerProcessFeeTest:test_processFeeWithZeroLinkNonZeroNativeWithNativeQuote() (gas: 146602) -FeeManagerProcessFeeTest:test_processFeeWithZeroNativeNonZeroLinkReturnsChange() (gas: 50621) -FeeManagerProcessFeeTest:test_processFeeWithZeroNativeNonZeroLinkWithLinkQuote() (gas: 113108) -FeeManagerProcessFeeTest:test_processFeeWithZeroNativeNonZeroLinkWithNativeQuote() (gas: 32904) -FeeManagerProcessFeeTest:test_processMultipleLinkAndNativeUnwrappedReports() (gas: 286610) -FeeManagerProcessFeeTest:test_processMultipleLinkAndNativeWrappedReports() (gas: 267369) -FeeManagerProcessFeeTest:test_processMultipleLinkReports() (gas: 229026) -FeeManagerProcessFeeTest:test_processMultipleUnwrappedNativeReports() (gas: 262798) -FeeManagerProcessFeeTest:test_processMultipleV1Reports() (gas: 66250) -FeeManagerProcessFeeTest:test_processMultipleWrappedNativeReports() (gas: 243449) -FeeManagerProcessFeeTest:test_processV1V2V3Reports() (gas: 271565) -FeeManagerProcessFeeTest:test_processV1V2V3ReportsWithUnwrapped() (gas: 290783) +FeeManagerProcessFeeTest:test_getRewardWithNativeQuoteAndSurcharge() (gas: 50760) +FeeManagerProcessFeeTest:test_linkAvailableForPaymentReturnsLinkBalance() (gas: 52375) +FeeManagerProcessFeeTest:test_nativeSurcharge0Percent() (gas: 30789) +FeeManagerProcessFeeTest:test_nativeSurcharge100Percent() (gas: 50802) +FeeManagerProcessFeeTest:test_nativeSurchargeCannotExceed100Percent() (gas: 17188) +FeeManagerProcessFeeTest:test_nativeSurchargeEventIsEmittedOnUpdate() (gas: 41370) +FeeManagerProcessFeeTest:test_noFeeIsAppliedWhenReportHasZeroFee() (gas: 51832) +FeeManagerProcessFeeTest:test_noFeeIsAppliedWhenReportHasZeroFeeAndDiscountAndSurchargeIsSet() (gas: 78015) +FeeManagerProcessFeeTest:test_nonAdminProxyUserCannotProcessFee() (gas: 24103) +FeeManagerProcessFeeTest:test_nonAdminUserCanNotSetDiscount() (gas: 19814) +FeeManagerProcessFeeTest:test_payLinkDeficit() (gas: 197190) +FeeManagerProcessFeeTest:test_payLinkDeficitOnlyCallableByAdmin() (gas: 17338) +FeeManagerProcessFeeTest:test_payLinkDeficitPaysAllFeesProcessed() (gas: 218523) +FeeManagerProcessFeeTest:test_payLinkDeficitTwice() (gas: 201471) +FeeManagerProcessFeeTest:test_processFeeAsProxy() (gas: 120576) +FeeManagerProcessFeeTest:test_processFeeDefaultReportsStillVerifiesWithEmptyQuote() (gas: 26799) +FeeManagerProcessFeeTest:test_processFeeEmitsEventIfNotEnoughLink() (gas: 163879) +FeeManagerProcessFeeTest:test_processFeeIfSubscriberIsSelf() (gas: 27360) +FeeManagerProcessFeeTest:test_processFeeNative() (gas: 176574) +FeeManagerProcessFeeTest:test_processFeeUsesCorrectDigest() (gas: 121514) +FeeManagerProcessFeeTest:test_processFeeWithDefaultReportPayloadAndQuoteStillVerifies() (gas: 29118) +FeeManagerProcessFeeTest:test_processFeeWithInvalidReportVersionFailsToDecode() (gas: 30602) +FeeManagerProcessFeeTest:test_processFeeWithUnwrappedNative() (gas: 184105) +FeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeLinkAddress() (gas: 135624) +FeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeLinkAddressExcessiveFee() (gas: 159487) +FeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeShortFunds() (gas: 94615) +FeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeWithExcessiveFee() (gas: 191065) +FeeManagerProcessFeeTest:test_processFeeWithWithCorruptQuotePayload() (gas: 28471) +FeeManagerProcessFeeTest:test_processFeeWithWithEmptyQuotePayload() (gas: 28939) +FeeManagerProcessFeeTest:test_processFeeWithWithZeroQuotePayload() (gas: 29928) +FeeManagerProcessFeeTest:test_processFeeWithZeroLinkNonZeroNativeWithLinkQuote() (gas: 35144) +FeeManagerProcessFeeTest:test_processFeeWithZeroLinkNonZeroNativeWithNativeQuote() (gas: 156485) +FeeManagerProcessFeeTest:test_processFeeWithZeroNativeNonZeroLinkReturnsChange() (gas: 55585) +FeeManagerProcessFeeTest:test_processFeeWithZeroNativeNonZeroLinkWithLinkQuote() (gas: 120542) +FeeManagerProcessFeeTest:test_processFeeWithZeroNativeNonZeroLinkWithNativeQuote() (gas: 37846) +FeeManagerProcessFeeTest:test_processMultipleLinkAndNativeUnwrappedReports() (gas: 296517) +FeeManagerProcessFeeTest:test_processMultipleLinkAndNativeWrappedReports() (gas: 279759) +FeeManagerProcessFeeTest:test_processMultipleLinkReports() (gas: 236449) +FeeManagerProcessFeeTest:test_processMultipleUnwrappedNativeReports() (gas: 270220) +FeeManagerProcessFeeTest:test_processMultipleV1Reports() (gas: 71195) +FeeManagerProcessFeeTest:test_processMultipleWrappedNativeReports() (gas: 253350) +FeeManagerProcessFeeTest:test_processV1V2V3Reports() (gas: 283979) +FeeManagerProcessFeeTest:test_processV1V2V3ReportsWithUnwrapped() (gas: 300708) FeeManagerProcessFeeTest:test_reportWithNoExpiryOrFeeReturnsZero() (gas: 11011) -FeeManagerProcessFeeTest:test_setDiscountOver100Percent() (gas: 14580) -FeeManagerProcessFeeTest:test_subscriberDiscountEventIsEmittedOnUpdate() (gas: 41313) -FeeManagerProcessFeeTest:test_surchargeFeeRoundsUpWhenUneven() (gas: 46123) -FeeManagerProcessFeeTest:test_surchargeIsApplied() (gas: 46091) -FeeManagerProcessFeeTest:test_surchargeIsAppliedForNativeFeeWithDiscount() (gas: 71754) -FeeManagerProcessFeeTest:test_surchargeIsNoLongerAppliedAfterRemoving() (gas: 41011) -FeeManagerProcessFeeTest:test_surchargeIsNotAppliedForLinkFee() (gas: 44871) -FeeManagerProcessFeeTest:test_surchargeIsNotAppliedWith100PercentDiscount() (gas: 70774) +FeeManagerProcessFeeTest:test_setDiscountOver100Percent() (gas: 19570) +FeeManagerProcessFeeTest:test_subscriberDiscountEventIsEmittedOnUpdate() (gas: 46281) +FeeManagerProcessFeeTest:test_surchargeFeeRoundsUpWhenUneven() (gas: 51089) +FeeManagerProcessFeeTest:test_surchargeIsApplied() (gas: 51057) +FeeManagerProcessFeeTest:test_surchargeIsAppliedForNativeFeeWithDiscount() (gas: 79188) +FeeManagerProcessFeeTest:test_surchargeIsNoLongerAppliedAfterRemoving() (gas: 46960) +FeeManagerProcessFeeTest:test_surchargeIsNotAppliedForLinkFee() (gas: 49837) +FeeManagerProcessFeeTest:test_surchargeIsNotAppliedWith100PercentDiscount() (gas: 78208) FeeManagerProcessFeeTest:test_testRevertIfReportHasExpired() (gas: 15198) -RewardManagerClaimTest:test_claimAllRecipients() (gas: 263344) -RewardManagerClaimTest:test_claimMultipleRecipients() (gas: 145864) -RewardManagerClaimTest:test_claimRewardsWithDuplicatePoolIdsDoesNotPayoutTwice() (gas: 315564) -RewardManagerClaimTest:test_claimSingleRecipient() (gas: 83367) -RewardManagerClaimTest:test_claimUnevenAmountRoundsDown() (gas: 300721) -RewardManagerClaimTest:test_claimUnregisteredPoolId() (gas: 29488) -RewardManagerClaimTest:test_claimUnregisteredRecipient() (gas: 35524) -RewardManagerClaimTest:test_eventIsEmittedUponClaim() (gas: 81096) -RewardManagerClaimTest:test_eventIsNotEmittedUponUnsuccessfulClaim() (gas: 19727) -RewardManagerClaimTest:test_recipientsClaimMultipleDeposits() (gas: 360373) -RewardManagerClaimTest:test_singleRecipientClaimMultipleDeposits() (gas: 128499) -RewardManagerNoRecipientSet:test_claimAllRecipientsAfterRecipientsSet() (gas: 464475) +RewardManagerClaimTest:test_claimAllRecipients() (gas: 275763) +RewardManagerClaimTest:test_claimMultipleRecipients() (gas: 153306) +RewardManagerClaimTest:test_claimRewardsWithDuplicatePoolIdsDoesNotPayoutTwice() (gas: 330467) +RewardManagerClaimTest:test_claimSingleRecipient() (gas: 88340) +RewardManagerClaimTest:test_claimUnevenAmountRoundsDown() (gas: 315671) +RewardManagerClaimTest:test_claimUnregisteredPoolId() (gas: 34461) +RewardManagerClaimTest:test_claimUnregisteredRecipient() (gas: 40491) +RewardManagerClaimTest:test_eventIsEmittedUponClaim() (gas: 86069) +RewardManagerClaimTest:test_eventIsNotEmittedUponUnsuccessfulClaim() (gas: 24700) +RewardManagerClaimTest:test_recipientsClaimMultipleDeposits() (gas: 385336) +RewardManagerClaimTest:test_singleRecipientClaimMultipleDeposits() (gas: 138411) +RewardManagerNoRecipientSet:test_claimAllRecipientsAfterRecipientsSet() (gas: 489469) RewardManagerPayRecipientsTest:test_addFundsToPoolAsNonOwnerOrFeeManager() (gas: 13550) -RewardManagerPayRecipientsTest:test_addFundsToPoolAsOwner() (gas: 51601) -RewardManagerPayRecipientsTest:test_payAllRecipients() (gas: 244544) -RewardManagerPayRecipientsTest:test_payAllRecipientsFromNonAdminUser() (gas: 15559) -RewardManagerPayRecipientsTest:test_payAllRecipientsFromRecipientInPool() (gas: 244790) -RewardManagerPayRecipientsTest:test_payAllRecipientsWithAdditionalInvalidRecipient() (gas: 255968) -RewardManagerPayRecipientsTest:test_payAllRecipientsWithAdditionalUnregisteredRecipient() (gas: 259108) -RewardManagerPayRecipientsTest:test_payRecipientWithInvalidPool() (gas: 23623) -RewardManagerPayRecipientsTest:test_payRecipientsEmptyRecipientList() (gas: 20065) -RewardManagerPayRecipientsTest:test_payRecipientsWithInvalidPoolId() (gas: 26139) -RewardManagerPayRecipientsTest:test_paySingleRecipient() (gas: 79428) -RewardManagerPayRecipientsTest:test_paySubsetOfRecipientsInPool() (gas: 192529) -RewardManagerRecipientClaimDifferentWeightsTest:test_allRecipientsClaimingReceiveExpectedAmount() (gas: 267295) -RewardManagerRecipientClaimMultiplePoolsTest:test_claimAllRecipientsMultiplePools() (gas: 487453) -RewardManagerRecipientClaimMultiplePoolsTest:test_claimAllRecipientsSinglePool() (gas: 269391) -RewardManagerRecipientClaimMultiplePoolsTest:test_claimEmptyPoolWhenSecondPoolContainsFunds() (gas: 276703) -RewardManagerRecipientClaimMultiplePoolsTest:test_claimMultipleRecipientsMultiplePools() (gas: 249180) -RewardManagerRecipientClaimMultiplePoolsTest:test_claimMultipleRecipientsSinglePool() (gas: 145948) -RewardManagerRecipientClaimMultiplePoolsTest:test_claimSingleRecipientMultiplePools() (gas: 124471) -RewardManagerRecipientClaimMultiplePoolsTest:test_claimSingleUniqueRecipient() (gas: 97872) -RewardManagerRecipientClaimMultiplePoolsTest:test_claimUnevenAmountRoundsDown() (gas: 551064) -RewardManagerRecipientClaimMultiplePoolsTest:test_claimUnregisteredRecipient() (gas: 56091) +RewardManagerPayRecipientsTest:test_addFundsToPoolAsOwner() (gas: 55574) +RewardManagerPayRecipientsTest:test_payAllRecipients() (gas: 249515) +RewardManagerPayRecipientsTest:test_payAllRecipientsFromNonAdminUser() (gas: 20518) +RewardManagerPayRecipientsTest:test_payAllRecipientsFromRecipientInPool() (gas: 249761) +RewardManagerPayRecipientsTest:test_payAllRecipientsWithAdditionalInvalidRecipient() (gas: 260965) +RewardManagerPayRecipientsTest:test_payAllRecipientsWithAdditionalUnregisteredRecipient() (gas: 264101) +RewardManagerPayRecipientsTest:test_payRecipientWithInvalidPool() (gas: 28592) +RewardManagerPayRecipientsTest:test_payRecipientsEmptyRecipientList() (gas: 25013) +RewardManagerPayRecipientsTest:test_payRecipientsWithInvalidPoolId() (gas: 31098) +RewardManagerPayRecipientsTest:test_paySingleRecipient() (gas: 84397) +RewardManagerPayRecipientsTest:test_paySubsetOfRecipientsInPool() (gas: 197492) +RewardManagerRecipientClaimDifferentWeightsTest:test_allRecipientsClaimingReceiveExpectedAmount() (gas: 279714) +RewardManagerRecipientClaimMultiplePoolsTest:test_claimAllRecipientsMultiplePools() (gas: 509889) +RewardManagerRecipientClaimMultiplePoolsTest:test_claimAllRecipientsSinglePool() (gas: 281833) +RewardManagerRecipientClaimMultiplePoolsTest:test_claimEmptyPoolWhenSecondPoolContainsFunds() (gas: 291618) +RewardManagerRecipientClaimMultiplePoolsTest:test_claimMultipleRecipientsMultiplePools() (gas: 261589) +RewardManagerRecipientClaimMultiplePoolsTest:test_claimMultipleRecipientsSinglePool() (gas: 153390) +RewardManagerRecipientClaimMultiplePoolsTest:test_claimSingleRecipientMultiplePools() (gas: 131911) +RewardManagerRecipientClaimMultiplePoolsTest:test_claimSingleUniqueRecipient() (gas: 105334) +RewardManagerRecipientClaimMultiplePoolsTest:test_claimUnevenAmountRoundsDown() (gas: 578510) +RewardManagerRecipientClaimMultiplePoolsTest:test_claimUnregisteredRecipient() (gas: 63533) RewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInBothPools() (gas: 28864) -RewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInBothPoolsWhereAlreadyClaimed() (gas: 139395) +RewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInBothPoolsWhereAlreadyClaimed() (gas: 146842) RewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInNoPools() (gas: 18363) RewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInSinglePool() (gas: 24381) -RewardManagerRecipientClaimMultiplePoolsTest:test_recipientsClaimMultipleDeposits() (gas: 364823) -RewardManagerRecipientClaimMultiplePoolsTest:test_singleRecipientClaimMultipleDeposits() (gas: 128515) -RewardManagerRecipientClaimUnevenWeightTest:test_allRecipientsClaimingReceiveExpectedAmount() (gas: 190638) -RewardManagerRecipientClaimUnevenWeightTest:test_allRecipientsClaimingReceiveExpectedAmountWithSmallDeposit() (gas: 210530) -RewardManagerSetRecipientsTest:test_eventIsEmittedUponSetRecipients() (gas: 186872) -RewardManagerSetRecipientsTest:test_setRecipientContainsDuplicateRecipients() (gas: 121134) -RewardManagerSetRecipientsTest:test_setRewardRecipientFromManagerAddress() (gas: 186535) -RewardManagerSetRecipientsTest:test_setRewardRecipientFromNonOwnerOrFeeManagerAddress() (gas: 16504) -RewardManagerSetRecipientsTest:test_setRewardRecipientTwice() (gas: 185999) -RewardManagerSetRecipientsTest:test_setRewardRecipientWeights() (gas: 175763) -RewardManagerSetRecipientsTest:test_setRewardRecipientWithZeroAddress() (gas: 85276) -RewardManagerSetRecipientsTest:test_setRewardRecipientWithZeroWeight() (gas: 178782) -RewardManagerSetRecipientsTest:test_setRewardRecipients() (gas: 180711) -RewardManagerSetRecipientsTest:test_setRewardRecipientsIsEmpty() (gas: 82166) -RewardManagerSetRecipientsTest:test_setSingleRewardRecipient() (gas: 105471) -RewardManagerSetupTest:test_eventEmittedUponFeeManagerUpdate() (gas: 16367) -RewardManagerSetupTest:test_eventEmittedUponFeePaid() (gas: 255602) +RewardManagerRecipientClaimMultiplePoolsTest:test_recipientsClaimMultipleDeposits() (gas: 389786) +RewardManagerRecipientClaimMultiplePoolsTest:test_singleRecipientClaimMultipleDeposits() (gas: 138427) +RewardManagerRecipientClaimUnevenWeightTest:test_allRecipientsClaimingReceiveExpectedAmount() (gas: 200572) +RewardManagerRecipientClaimUnevenWeightTest:test_allRecipientsClaimingReceiveExpectedAmountWithSmallDeposit() (gas: 220442) +RewardManagerSetRecipientsTest:test_eventIsEmittedUponSetRecipients() (gas: 191821) +RewardManagerSetRecipientsTest:test_setRecipientContainsDuplicateRecipients() (gas: 126091) +RewardManagerSetRecipientsTest:test_setRewardRecipientFromManagerAddress() (gas: 193950) +RewardManagerSetRecipientsTest:test_setRewardRecipientFromNonOwnerOrFeeManagerAddress() (gas: 21452) +RewardManagerSetRecipientsTest:test_setRewardRecipientTwice() (gas: 193416) +RewardManagerSetRecipientsTest:test_setRewardRecipientWeights() (gas: 180711) +RewardManagerSetRecipientsTest:test_setRewardRecipientWithZeroAddress() (gas: 90224) +RewardManagerSetRecipientsTest:test_setRewardRecipientWithZeroWeight() (gas: 183724) +RewardManagerSetRecipientsTest:test_setRewardRecipients() (gas: 185681) +RewardManagerSetRecipientsTest:test_setRewardRecipientsIsEmpty() (gas: 87113) +RewardManagerSetRecipientsTest:test_setSingleRewardRecipient() (gas: 110394) +RewardManagerSetupTest:test_eventEmittedUponFeeManagerUpdate() (gas: 21366) +RewardManagerSetupTest:test_eventEmittedUponFeePaid() (gas: 259335) RewardManagerSetupTest:test_rejectsZeroLinkAddressOnConstruction() (gas: 59390) -RewardManagerSetupTest:test_setFeeManagerZeroAddress() (gas: 12039) -RewardManagerUpdateRewardRecipientsMultiplePoolsTest:test_updatePrimaryRecipientWeights() (gas: 356489) -RewardManagerUpdateRewardRecipientsTest:test_eventIsEmittedUponUpdateRecipients() (gas: 274297) -RewardManagerUpdateRewardRecipientsTest:test_onlyAdminCanUpdateRecipients() (gas: 14757) -RewardManagerUpdateRewardRecipientsTest:test_partialUpdateRecipientWeights() (gas: 206711) -RewardManagerUpdateRewardRecipientsTest:test_updateAllRecipientsWithSameAddressAndWeight() (gas: 268121) -RewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsToSubset() (gas: 240361) -RewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithExcessiveWeight() (gas: 254433) -RewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithSameAddressAndWeight() (gas: 144023) -RewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithUnderWeightSet() (gas: 254507) -RewardManagerUpdateRewardRecipientsTest:test_updateRecipientWeights() (gas: 351970) -RewardManagerUpdateRewardRecipientsTest:test_updateRecipientWithNewZeroAddress() (gas: 253649) -RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsContainsDuplicateRecipients() (gas: 283778) -RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentLargerSet() (gas: 256457) -RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentPartialSet() (gas: 254436) -RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentSet() (gas: 255845) -RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentSetWithInvalidWeights() (gas: 254576) -RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsUpdateAndRemoveExistingForLargerSet() (gas: 246971) -RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsUpdateAndRemoveExistingForSmallerSet() (gas: 245257) +RewardManagerSetupTest:test_setFeeManagerZeroAddress() (gas: 17016) +RewardManagerUpdateRewardRecipientsMultiplePoolsTest:test_updatePrimaryRecipientWeights() (gas: 373819) +RewardManagerUpdateRewardRecipientsTest:test_eventIsEmittedUponUpdateRecipients() (gas: 279281) +RewardManagerUpdateRewardRecipientsTest:test_onlyAdminCanUpdateRecipients() (gas: 19727) +RewardManagerUpdateRewardRecipientsTest:test_partialUpdateRecipientWeights() (gas: 219095) +RewardManagerUpdateRewardRecipientsTest:test_updateAllRecipientsWithSameAddressAndWeight() (gas: 273103) +RewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsToSubset() (gas: 245309) +RewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithExcessiveWeight() (gas: 259381) +RewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithSameAddressAndWeight() (gas: 148982) +RewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithUnderWeightSet() (gas: 259455) +RewardManagerUpdateRewardRecipientsTest:test_updateRecipientWeights() (gas: 369300) +RewardManagerUpdateRewardRecipientsTest:test_updateRecipientWithNewZeroAddress() (gas: 258597) +RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsContainsDuplicateRecipients() (gas: 288735) +RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentLargerSet() (gas: 261406) +RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentPartialSet() (gas: 259384) +RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentSet() (gas: 260794) +RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentSetWithInvalidWeights() (gas: 259524) +RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsUpdateAndRemoveExistingForLargerSet() (gas: 251916) +RewardManagerUpdateRewardRecipientsTest:test_updateRecipientsUpdateAndRemoveExistingForSmallerSet() (gas: 250201) VerificationdeactivateConfigWhenThereAreMultipleDigestsTest:test_correctlyRemovesAMiddleDigest() (gas: 24155) VerificationdeactivateConfigWhenThereAreMultipleDigestsTest:test_correctlyRemovesTheFirstDigest() (gas: 24122) VerificationdeactivateConfigWhenThereAreMultipleDigestsTest:test_correctlyUnsetsDigestsInSequence() (gas: 44043) -VerificationdeactivateConfigWhenThereAreMultipleDigestsTest:test_revertsIfCalledByNonOwner() (gas: 11278) +VerificationdeactivateConfigWhenThereAreMultipleDigestsTest:test_revertsIfCalledByNonOwner() (gas: 15016) VerificationdeactivateConfigWhenThereAreMultipleDigestsTest:test_revertsIfRemovingAnEmptyDigest() (gas: 10907) VerificationdeactivateConfigWhenThereAreMultipleDigestsTest:test_revertsIfRemovingAnNonExistentDigest() (gas: 13381) -VerifierActivateConfigTest:test_revertsIfDigestIsEmpty() (gas: 10962) +VerifierActivateConfigTest:test_revertsIfDigestIsEmpty() (gas: 10984) VerifierActivateConfigTest:test_revertsIfDigestNotSet() (gas: 13394) -VerifierActivateConfigTest:test_revertsIfNotOwner() (gas: 13433) -VerifierActivateConfigWithDeactivatedConfigTest:test_allowsVerification() (gas: 93473) +VerifierActivateConfigTest:test_revertsIfNotOwner() (gas: 17171) +VerifierActivateConfigWithDeactivatedConfigTest:test_allowsVerification() (gas: 97164) VerifierActivateFeedTest:test_revertsIfNoFeedExistsActivate() (gas: 13179) VerifierActivateFeedTest:test_revertsIfNoFeedExistsDeactivate() (gas: 13157) -VerifierActivateFeedTest:test_revertsIfNotOwnerActivateFeed() (gas: 13360) -VerifierActivateFeedTest:test_revertsIfNotOwnerDeactivateFeed() (gas: 13415) -VerifierBulkVerifyBillingReport:test_verifyBulkReportWithUnwrappedAndWrappedNativeDefaultsToUnwrapped() (gas: 386271) -VerifierBulkVerifyBillingReport:test_verifyBulkWithLinkAndUnwrappedNative() (gas: 694977) -VerifierBulkVerifyBillingReport:test_verifyBulkWithLinkAndWrappedNative() (gas: 677095) -VerifierBulkVerifyBillingReport:test_verifyMultiVersions() (gas: 560297) -VerifierBulkVerifyBillingReport:test_verifyMultiVersionsReturnsVerifiedReports() (gas: 773047) -VerifierBulkVerifyBillingReport:test_verifyWithBulkLink() (gas: 572112) -VerifierBulkVerifyBillingReport:test_verifyWithBulkNative() (gas: 573880) -VerifierBulkVerifyBillingReport:test_verifyWithBulkNativeUnwrapped() (gas: 583847) -VerifierBulkVerifyBillingReport:test_verifyWithBulkNativeUnwrappedReturnsChange() (gas: 590874) +VerifierActivateFeedTest:test_revertsIfNotOwnerActivateFeed() (gas: 17098) +VerifierActivateFeedTest:test_revertsIfNotOwnerDeactivateFeed() (gas: 17153) +VerifierBulkVerifyBillingReport:test_verifyBulkReportWithUnwrappedAndWrappedNativeDefaultsToUnwrapped() (gas: 391227) +VerifierBulkVerifyBillingReport:test_verifyBulkWithLinkAndUnwrappedNative() (gas: 702466) +VerifierBulkVerifyBillingReport:test_verifyBulkWithLinkAndWrappedNative() (gas: 687045) +VerifierBulkVerifyBillingReport:test_verifyMultiVersions() (gas: 570309) +VerifierBulkVerifyBillingReport:test_verifyMultiVersionsReturnsVerifiedReports() (gas: 783120) +VerifierBulkVerifyBillingReport:test_verifyWithBulkLink() (gas: 579516) +VerifierBulkVerifyBillingReport:test_verifyWithBulkNative() (gas: 581327) +VerifierBulkVerifyBillingReport:test_verifyWithBulkNativeUnwrapped() (gas: 588801) +VerifierBulkVerifyBillingReport:test_verifyWithBulkNativeUnwrappedReturnsChange() (gas: 595828) VerifierConstructorTest:test_revertsIfInitializedWithEmptyVerifierProxy() (gas: 59939) VerifierConstructorTest:test_setsTheCorrectProperties() (gas: 1788491) -VerifierDeactivateFeedWithVerifyTest:test_currentReportAllowsVerification() (gas: 188300) -VerifierDeactivateFeedWithVerifyTest:test_currentReportFailsVerification() (gas: 109631) -VerifierDeactivateFeedWithVerifyTest:test_previousReportAllowsVerification() (gas: 95877) -VerifierDeactivateFeedWithVerifyTest:test_previousReportFailsVerification() (gas: 66189) -VerifierProxyAccessControlledVerificationTest:test_proxiesToTheVerifierIfHasAccess() (gas: 201062) -VerifierProxyAccessControlledVerificationTest:test_revertsIfNoAccess() (gas: 105778) -VerifierProxyConstructorTest:test_correctlySetsTheCorrectAccessControllerInterface() (gas: 1357277) +VerifierDeactivateFeedWithVerifyTest:test_currentReportAllowsVerification() (gas: 192062) +VerifierDeactivateFeedWithVerifyTest:test_currentReportFailsVerification() (gas: 113377) +VerifierDeactivateFeedWithVerifyTest:test_previousReportAllowsVerification() (gas: 99613) +VerifierDeactivateFeedWithVerifyTest:test_previousReportFailsVerification() (gas: 69932) +VerifierProxyAccessControlledVerificationTest:test_proxiesToTheVerifierIfHasAccess() (gas: 204824) +VerifierProxyAccessControlledVerificationTest:test_revertsIfNoAccess() (gas: 109546) +VerifierProxyConstructorTest:test_correctlySetsTheCorrectAccessControllerInterface() (gas: 1357299) VerifierProxyConstructorTest:test_correctlySetsTheOwner() (gas: 1337313) -VerifierProxyConstructorTest:test_correctlySetsVersion() (gas: 6939) -VerifierProxyInitializeVerifierTest:test_revertsIfDigestAlreadySet() (gas: 50333) +VerifierProxyConstructorTest:test_correctlySetsVersion() (gas: 6873) +VerifierProxyInitializeVerifierTest:test_revertsIfDigestAlreadySet() (gas: 54085) VerifierProxyInitializeVerifierTest:test_revertsIfNotCorrectVerifier() (gas: 13572) -VerifierProxyInitializeVerifierTest:test_revertsIfNotOwner() (gas: 13441) -VerifierProxyInitializeVerifierTest:test_revertsIfVerifierAlreadyInitialized() (gas: 42047) +VerifierProxyInitializeVerifierTest:test_revertsIfNotOwner() (gas: 17179) +VerifierProxyInitializeVerifierTest:test_revertsIfVerifierAlreadyInitialized() (gas: 42069) VerifierProxyInitializeVerifierTest:test_revertsIfZeroAddress() (gas: 10970) -VerifierProxyInitializeVerifierTest:test_setFeeManagerZeroAddress() (gas: 10913) -VerifierProxyInitializeVerifierTest:test_updatesVerifierIfVerifier() (gas: 49583) +VerifierProxyInitializeVerifierTest:test_setFeeManagerZeroAddress() (gas: 10935) +VerifierProxyInitializeVerifierTest:test_updatesVerifierIfVerifier() (gas: 53315) VerifierProxySetAccessControllerTest:test_emitsTheCorrectEvent() (gas: 35384) -VerifierProxySetAccessControllerTest:test_revertsIfCalledByNonOwner() (gas: 11367) +VerifierProxySetAccessControllerTest:test_revertsIfCalledByNonOwner() (gas: 15105) VerifierProxySetAccessControllerTest:test_successfullySetsNewAccessController() (gas: 32120) VerifierProxySetAccessControllerTest:test_successfullySetsNewAccessControllerIsEmpty() (gas: 12219) VerifierProxyUnsetVerifierTest:test_revertsIfDigestDoesNotExist() (gas: 13141) -VerifierProxyUnsetVerifierTest:test_revertsIfNotAdmin() (gas: 11227) +VerifierProxyUnsetVerifierTest:test_revertsIfNotAdmin() (gas: 14965) VerifierProxyUnsetVerifierWithPreviouslySetVerifierTest:test_correctlyUnsetsVerifier() (gas: 12697) -VerifierProxyUnsetVerifierWithPreviouslySetVerifierTest:test_emitsAnEventAfterUnsettingVerifier() (gas: 17943) +VerifierProxyUnsetVerifierWithPreviouslySetVerifierTest:test_emitsAnEventAfterUnsettingVerifier() (gas: 17965) VerifierProxyVerifyTest:test_proxiesToTheCorrectVerifier() (gas: 198408) -VerifierProxyVerifyTest:test_revertsIfNoVerifierConfigured() (gas: 116352) -VerifierSetConfigFromSourceMultipleDigestsTest:test_correctlySetsConfigWhenDigestsAreRemoved() (gas: 538560) -VerifierSetConfigFromSourceMultipleDigestsTest:test_correctlyUpdatesDigestsOnMultipleVerifiersInTheProxy() (gas: 964093) -VerifierSetConfigFromSourceMultipleDigestsTest:test_correctlyUpdatesTheDigestInTheProxy() (gas: 520118) -VerifierSetConfigFromSourceTest:test_revertsIfCalledByNonOwner() (gas: 179353) +VerifierProxyVerifyTest:test_revertsIfNoVerifierConfigured() (gas: 116307) +VerifierSetConfigFromSourceMultipleDigestsTest:test_correctlySetsConfigWhenDigestsAreRemoved() (gas: 538582) +VerifierSetConfigFromSourceMultipleDigestsTest:test_correctlyUpdatesDigestsOnMultipleVerifiersInTheProxy() (gas: 964048) +VerifierSetConfigFromSourceMultipleDigestsTest:test_correctlyUpdatesTheDigestInTheProxy() (gas: 520140) +VerifierSetConfigFromSourceTest:test_revertsIfCalledByNonOwner() (gas: 183115) VerifierSetConfigTest:test_correctlyUpdatesTheConfig() (gas: 1057669) -VerifierSetConfigTest:test_revertsIfCalledByNonOwner() (gas: 179222) -VerifierSetConfigTest:test_revertsIfDuplicateSigners() (gas: 251572) +VerifierSetConfigTest:test_revertsIfCalledByNonOwner() (gas: 182962) +VerifierSetConfigTest:test_revertsIfDuplicateSigners() (gas: 251529) VerifierSetConfigTest:test_revertsIfFaultToleranceIsZero() (gas: 176521) VerifierSetConfigTest:test_revertsIfNotEnoughSigners() (gas: 15813) -VerifierSetConfigTest:test_revertsIfSetWithTooManySigners() (gas: 22169) +VerifierSetConfigTest:test_revertsIfSetWithTooManySigners() (gas: 22191) VerifierSetConfigTest:test_revertsIfSignerContainsZeroAddress() (gas: 228002) -VerifierSetConfigWhenThereAreMultipleDigestsTest:test_correctlySetsConfigWhenDigestsAreRemoved() (gas: 538347) -VerifierSetConfigWhenThereAreMultipleDigestsTest:test_correctlyUpdatesDigestsOnMultipleVerifiersInTheProxy() (gas: 963662) -VerifierSetConfigWhenThereAreMultipleDigestsTest:test_correctlyUpdatesTheDigestInTheProxy() (gas: 519899) +VerifierSetConfigWhenThereAreMultipleDigestsTest:test_correctlySetsConfigWhenDigestsAreRemoved() (gas: 538369) +VerifierSetConfigWhenThereAreMultipleDigestsTest:test_correctlyUpdatesDigestsOnMultipleVerifiersInTheProxy() (gas: 963617) +VerifierSetConfigWhenThereAreMultipleDigestsTest:test_correctlyUpdatesTheDigestInTheProxy() (gas: 519921) VerifierSupportsInterfaceTest:test_falseIfIsNotCorrectInterface() (gas: 5590) -VerifierSupportsInterfaceTest:test_trueIfIsCorrectInterface() (gas: 5611) -VerifierTestBillingReport:test_verifyWithLink() (gas: 273128) -VerifierTestBillingReport:test_verifyWithNative() (gas: 313819) -VerifierTestBillingReport:test_verifyWithNativeUnwrapped() (gas: 318543) -VerifierTestBillingReport:test_verifyWithNativeUnwrappedReturnsChange() (gas: 325609) -VerifierVerifyMultipleConfigDigestTest:test_canVerifyNewerReportsWithNewerConfigs() (gas: 127491) -VerifierVerifyMultipleConfigDigestTest:test_canVerifyOlderReportsWithOlderConfigs() (gas: 183370) -VerifierVerifyMultipleConfigDigestTest:test_revertsIfAReportIsVerifiedWithAnExistingButIncorrectDigest() (gas: 84461) -VerifierVerifyMultipleConfigDigestTest:test_revertsIfVerifyingWithAnUnsetDigest() (gas: 124325) -VerifierVerifySingleConfigDigestTest:test_emitsAnEventIfReportVerified() (gas: 183205) -VerifierVerifySingleConfigDigestTest:test_returnsThePriceAndBlockNumIfReportVerified() (gas: 183374) -VerifierVerifySingleConfigDigestTest:test_revertsIfConfigDigestNotSet() (gas: 112427) -VerifierVerifySingleConfigDigestTest:test_revertsIfDuplicateSignersHaveSigned() (gas: 178569) -VerifierVerifySingleConfigDigestTest:test_revertsIfMismatchedSignatureLength() (gas: 49272) -VerifierVerifySingleConfigDigestTest:test_revertsIfReportHasUnconfiguredFeedID() (gas: 100230) +VerifierSupportsInterfaceTest:test_trueIfIsCorrectInterface() (gas: 5633) +VerifierTestBillingReport:test_verifyWithLink() (gas: 280557) +VerifierTestBillingReport:test_verifyWithNative() (gas: 321248) +VerifierTestBillingReport:test_verifyWithNativeUnwrapped() (gas: 323491) +VerifierTestBillingReport:test_verifyWithNativeUnwrappedReturnsChange() (gas: 330557) +VerifierVerifyMultipleConfigDigestTest:test_canVerifyNewerReportsWithNewerConfigs() (gas: 131228) +VerifierVerifyMultipleConfigDigestTest:test_canVerifyOlderReportsWithOlderConfigs() (gas: 187132) +VerifierVerifyMultipleConfigDigestTest:test_revertsIfAReportIsVerifiedWithAnExistingButIncorrectDigest() (gas: 88205) +VerifierVerifyMultipleConfigDigestTest:test_revertsIfVerifyingWithAnUnsetDigest() (gas: 128062) +VerifierVerifySingleConfigDigestTest:test_emitsAnEventIfReportVerified() (gas: 186945) +VerifierVerifySingleConfigDigestTest:test_returnsThePriceAndBlockNumIfReportVerified() (gas: 187114) +VerifierVerifySingleConfigDigestTest:test_revertsIfConfigDigestNotSet() (gas: 116130) +VerifierVerifySingleConfigDigestTest:test_revertsIfDuplicateSignersHaveSigned() (gas: 182315) +VerifierVerifySingleConfigDigestTest:test_revertsIfMismatchedSignatureLength() (gas: 53037) +VerifierVerifySingleConfigDigestTest:test_revertsIfReportHasUnconfiguredFeedID() (gas: 103976) VerifierVerifySingleConfigDigestTest:test_revertsIfVerifiedByNonProxy() (gas: 100992) -VerifierVerifySingleConfigDigestTest:test_revertsIfVerifiedWithIncorrectAddresses() (gas: 180320) -VerifierVerifySingleConfigDigestTest:test_revertsIfWrongNumberOfSigners() (gas: 106285) -VerifierVerifySingleConfigDigestTest:test_setsTheCorrectEpoch() (gas: 190530) -Verifier_accessControlledVerify:testVerifyWithAccessControl_gas() (gas: 205085) +VerifierVerifySingleConfigDigestTest:test_revertsIfVerifiedWithIncorrectAddresses() (gas: 184066) +VerifierVerifySingleConfigDigestTest:test_revertsIfWrongNumberOfSigners() (gas: 110031) +VerifierVerifySingleConfigDigestTest:test_setsTheCorrectEpoch() (gas: 194270) +Verifier_accessControlledVerify:testVerifyWithAccessControl_gas() (gas: 208841) Verifier_bulkVerifyWithFee:testBulkVerifyProxyWithLinkFeeSuccess_gas() (gas: 542038) Verifier_bulkVerifyWithFee:testBulkVerifyProxyWithNativeFeeSuccess_gas() (gas: 565410) -Verifier_setConfig:testSetConfigSuccess_gas() (gas: 922406) +Verifier_setConfig:testSetConfigSuccess_gas() (gas: 922428) Verifier_verify:testVerifyProxySuccess_gas() (gas: 195530) -Verifier_verify:testVerifySuccess_gas() (gas: 182991) -Verifier_verifyWithFee:testVerifyProxyWithLinkFeeSuccess_gas() (gas: 244551) -Verifier_verifyWithFee:testVerifyProxyWithNativeFeeSuccess_gas() (gas: 262962) \ No newline at end of file +Verifier_verify:testVerifySuccess_gas() (gas: 186725) +Verifier_verifyWithFee:testVerifyProxyWithLinkFeeSuccess_gas() (gas: 244506) +Verifier_verifyWithFee:testVerifyProxyWithNativeFeeSuccess_gas() (gas: 262984) \ No newline at end of file diff --git a/contracts/gas-snapshots/shared.gas-snapshot b/contracts/gas-snapshots/shared.gas-snapshot index cb2e8defe4a..cf003c5a26d 100644 --- a/contracts/gas-snapshots/shared.gas-snapshot +++ b/contracts/gas-snapshots/shared.gas-snapshot @@ -1,32 +1,32 @@ -BurnMintERC677_approve:testApproveSuccess() (gas: 52254) -BurnMintERC677_approve:testInvalidAddressReverts() (gas: 10641) -BurnMintERC677_burn:testBasicBurnSuccess() (gas: 164344) -BurnMintERC677_burn:testBurnFromZeroAddressReverts() (gas: 43462) -BurnMintERC677_burn:testExceedsBalanceReverts() (gas: 18035) +BurnMintERC677_approve:testApproveSuccess() (gas: 55248) +BurnMintERC677_approve:testInvalidAddressReverts() (gas: 10663) +BurnMintERC677_burn:testBasicBurnSuccess() (gas: 164342) +BurnMintERC677_burn:testBurnFromZeroAddressReverts() (gas: 47201) +BurnMintERC677_burn:testExceedsBalanceReverts() (gas: 21841) BurnMintERC677_burn:testSenderNotBurnerReverts() (gas: 13359) -BurnMintERC677_burnFrom:testBurnFromSuccess() (gas: 54662) -BurnMintERC677_burnFrom:testExceedsBalanceReverts() (gas: 32873) -BurnMintERC677_burnFrom:testInsufficientAllowanceReverts() (gas: 18107) +BurnMintERC677_burnFrom:testBurnFromSuccess() (gas: 57658) +BurnMintERC677_burnFrom:testExceedsBalanceReverts() (gas: 35864) +BurnMintERC677_burnFrom:testInsufficientAllowanceReverts() (gas: 21849) BurnMintERC677_burnFrom:testSenderNotBurnerReverts() (gas: 13359) -BurnMintERC677_burnFromAlias:testBurnFromSuccess() (gas: 54688) -BurnMintERC677_burnFromAlias:testExceedsBalanceReverts() (gas: 32889) -BurnMintERC677_burnFromAlias:testInsufficientAllowanceReverts() (gas: 18127) +BurnMintERC677_burnFromAlias:testBurnFromSuccess() (gas: 57684) +BurnMintERC677_burnFromAlias:testExceedsBalanceReverts() (gas: 35880) +BurnMintERC677_burnFromAlias:testInsufficientAllowanceReverts() (gas: 21869) BurnMintERC677_burnFromAlias:testSenderNotBurnerReverts() (gas: 13379) BurnMintERC677_constructor:testConstructorSuccess() (gas: 1669109) -BurnMintERC677_decreaseApproval:testDecreaseApprovalSuccess() (gas: 28520) -BurnMintERC677_grantMintAndBurnRoles:testGrantMintAndBurnRolesSuccess() (gas: 120049) -BurnMintERC677_grantRole:testGrantBurnAccessSuccess() (gas: 52707) +BurnMintERC677_decreaseApproval:testDecreaseApprovalSuccess() (gas: 28537) +BurnMintERC677_grantMintAndBurnRoles:testGrantMintAndBurnRolesSuccess() (gas: 120071) +BurnMintERC677_grantRole:testGrantBurnAccessSuccess() (gas: 52724) BurnMintERC677_grantRole:testGrantManySuccess() (gas: 935521) -BurnMintERC677_grantRole:testGrantMintAccessSuccess() (gas: 93588) +BurnMintERC677_grantRole:testGrantMintAccessSuccess() (gas: 93605) BurnMintERC677_increaseApproval:testIncreaseApprovalSuccess() (gas: 40911) BurnMintERC677_mint:testBasicMintSuccess() (gas: 149365) -BurnMintERC677_mint:testMaxSupplyExceededReverts() (gas: 46627) +BurnMintERC677_mint:testMaxSupplyExceededReverts() (gas: 50385) BurnMintERC677_mint:testSenderNotMinterReverts() (gas: 11195) BurnMintERC677_supportsInterface:testConstructorSuccess() (gas: 8685) -BurnMintERC677_transfer:testInvalidAddressReverts() (gas: 10617) +BurnMintERC677_transfer:testInvalidAddressReverts() (gas: 10639) BurnMintERC677_transfer:testTransferSuccess() (gas: 39462) OpStackBurnMintERC677_constructor:testConstructorSuccess() (gas: 1739317) -OpStackBurnMintERC677_interfaceCompatibility:testBurnCompatibility() (gas: 259440) -OpStackBurnMintERC677_interfaceCompatibility:testMintCompatibility() (gas: 137935) +OpStackBurnMintERC677_interfaceCompatibility:testBurnCompatibility() (gas: 263373) +OpStackBurnMintERC677_interfaceCompatibility:testMintCompatibility() (gas: 137957) OpStackBurnMintERC677_interfaceCompatibility:testStaticFunctionsCompatibility() (gas: 10622) OpStackBurnMintERC677_supportsInterface:testConstructorSuccess() (gas: 8961) \ No newline at end of file diff --git a/contracts/gas-snapshots/vrf.gas-snapshot b/contracts/gas-snapshots/vrf.gas-snapshot index 29053204765..44145caadaa 100644 --- a/contracts/gas-snapshots/vrf.gas-snapshot +++ b/contracts/gas-snapshots/vrf.gas-snapshot @@ -1,18 +1,18 @@ TrustedBlockhashStoreTest:testGenericBHSFunctions() (gas: 53507) -TrustedBlockhashStoreTest:testTrustedBHSFunctions() (gas: 49536) +TrustedBlockhashStoreTest:testTrustedBHSFunctions() (gas: 54617) VRFCoordinatorV2Plus_Migration:testDeregister() (gas: 101083) -VRFCoordinatorV2Plus_Migration:testMigrateRevertsWhenInvalidCaller() (gas: 29421) -VRFCoordinatorV2Plus_Migration:testMigrateRevertsWhenInvalidCoordinator() (gas: 19855) -VRFCoordinatorV2Plus_Migration:testMigrateRevertsWhenPendingFulfillment() (gas: 237702) -VRFCoordinatorV2Plus_Migration:testMigrateRevertsWhenReentrant() (gas: 354749) -VRFCoordinatorV2Plus_Migration:testMigration() (gas: 471631) -VRFCoordinatorV2Plus_Migration:testMigrationNoLink() (gas: 431052) -VRFV2Plus:testCancelSubWithNoLink() (gas: 160261) +VRFCoordinatorV2Plus_Migration:testMigrateRevertsWhenInvalidCaller() (gas: 33190) +VRFCoordinatorV2Plus_Migration:testMigrateRevertsWhenInvalidCoordinator() (gas: 19877) +VRFCoordinatorV2Plus_Migration:testMigrateRevertsWhenPendingFulfillment() (gas: 237679) +VRFCoordinatorV2Plus_Migration:testMigrateRevertsWhenReentrant() (gas: 357765) +VRFCoordinatorV2Plus_Migration:testMigration() (gas: 471605) +VRFCoordinatorV2Plus_Migration:testMigrationNoLink() (gas: 431075) +VRFV2Plus:testCancelSubWithNoLink() (gas: 160279) VRFV2Plus:testCreateSubscription() (gas: 181127) -VRFV2Plus:testGetActiveSubscriptionIds() (gas: 3453659) -VRFV2Plus:testRegisterProvingKey() (gas: 101025) -VRFV2Plus:testRequestAndFulfillRandomWordsLINK() (gas: 755178) -VRFV2Plus:testRequestAndFulfillRandomWordsNative() (gas: 705581) +VRFV2Plus:testGetActiveSubscriptionIds() (gas: 3453681) +VRFV2Plus:testRegisterProvingKey() (gas: 101085) +VRFV2Plus:testRequestAndFulfillRandomWordsLINK() (gas: 755144) +VRFV2Plus:testRequestAndFulfillRandomWordsNative() (gas: 705591) VRFV2Plus:testSetConfig() (gas: 73032) -VRFV2PlusWrapperTest:testRequestAndFulfillRandomWordsLINKWrapper() (gas: 390063) -VRFV2PlusWrapperTest:testRequestAndFulfillRandomWordsNativeWrapper() (gas: 290612) \ No newline at end of file +VRFV2PlusWrapperTest:testRequestAndFulfillRandomWordsLINKWrapper() (gas: 393885) +VRFV2PlusWrapperTest:testRequestAndFulfillRandomWordsNativeWrapper() (gas: 294434) \ No newline at end of file From 200970a568d644defac958de3212d38fd384da24 Mon Sep 17 00:00:00 2001 From: george-dorin <120329946+george-dorin@users.noreply.github.com> Date: Mon, 4 Sep 2023 19:21:35 +0300 Subject: [PATCH 11/14] Show job runs for disabled chains (#10401) * Show job runs for disabled chains * Add changelog --- core/services/job/job_orm_test.go | 23 +++++++++++++++++++++++ core/services/job/orm.go | 4 +++- docs/CHANGELOG.md | 4 +++- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go index 0f70e74b247..de2ee44c2ce 100644 --- a/core/services/job/job_orm_test.go +++ b/core/services/job/job_orm_test.go @@ -1248,6 +1248,7 @@ func Test_FindJobsByPipelineSpecIDs(t *testing.T) { jb, err := directrequest.ValidatedDirectRequestSpec(testspecs.DirectRequestSpec) require.NoError(t, err) + jb.DirectRequestSpec.EVMChainID = utils.NewBigI(0) err = orm.CreateJob(&jb) require.NoError(t, err) @@ -1270,6 +1271,28 @@ func Test_FindJobsByPipelineSpecIDs(t *testing.T) { require.NoError(t, err) assert.Len(t, jbs, 0) }) + + t.Run("with chainID disabled", func(t *testing.T) { + newCfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.EVM[0] = &evmcfg.EVMConfig{ + ChainID: utils.NewBigI(0), + Enabled: ptr(false), + } + c.EVM = append(c.EVM, &evmcfg.EVMConfig{ + ChainID: utils.NewBigI(123123123), + Enabled: ptr(true), + }) + }) + relayExtenders2 := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: newCfg, KeyStore: keyStore.Eth()}) + legacyChains2, err := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders2) + + require.NoError(t, err) + orm2 := NewTestORM(t, db, legacyChains2, pipelineORM, bridgesORM, keyStore, config.Database()) + + jbs, err := orm2.FindJobsByPipelineSpecIDs([]int32{jb.PipelineSpecID}) + require.NoError(t, err) + assert.Len(t, jbs, 1) + }) } func Test_FindPipelineRuns(t *testing.T) { diff --git a/core/services/job/orm.go b/core/services/job/orm.go index d7cfbd0fc4a..277b03b24dd 100644 --- a/core/services/job/orm.go +++ b/core/services/job/orm.go @@ -20,6 +20,7 @@ import ( "github.com/smartcontractkit/sqlx" "github.com/smartcontractkit/chainlink/v2/core/bridges" + "github.com/smartcontractkit/chainlink/v2/core/chains" "github.com/smartcontractkit/chainlink/v2/core/chains/evm" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" "github.com/smartcontractkit/chainlink/v2/core/config" @@ -1185,7 +1186,8 @@ func (o *orm) FindJobsByPipelineSpecIDs(ids []int32) ([]Job, error) { } for i := range jbs { err = o.LoadEnvConfigVars(&jbs[i]) - if err != nil { + //We must return the jobs even if the chainID is disabled + if err != nil && !errors.Is(err, chains.ErrNoSuchChainID) { return err } } diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 90d619cd19e..93ae8b611f5 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -9,7 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [dev] -... +### Fixed + - Fixed a bug that was preventing job runs to be displayed when the job `chainID` was disabled. + ## 2.5.0 - UNRELEASED From 2afd9c259658f2a4d857493a92059bfd16608603 Mon Sep 17 00:00:00 2001 From: ferglor <19188060+ferglor@users.noreply.github.com> Date: Mon, 4 Sep 2023 19:16:03 +0100 Subject: [PATCH 12/14] Return all logs even if seen before (#10473) --- .../evm21/transmit/event_provider.go | 84 ++++++++++--------- 1 file changed, 43 insertions(+), 41 deletions(-) diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider.go b/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider.go index eccc9304d99..a21cdd25eb0 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider.go +++ b/core/services/ocr2/plugins/ocr2keeper/evm21/transmit/event_provider.go @@ -170,52 +170,54 @@ func (c *TransmitEventProvider) processLogs(latestBlock int64, logs ...logpoller // ensure we don't have duplicates continue } - if _, ok := c.cache.get(ocr2keepers.BlockNumber(log.BlockNumber), k); ok { - // ensure we return only unseen logs - continue - } - l, err := c.parseLog(c.registry, log) - if err != nil { - c.logger.Debugw("failed to parse log", "err", err) - continue - } - id := l.Id() - upkeepId := &ocr2keepers.UpkeepIdentifier{} - ok := upkeepId.FromBigInt(id) + + transmitEvent, ok := c.cache.get(ocr2keepers.BlockNumber(log.BlockNumber), k) if !ok { - return nil, core.ErrInvalidUpkeepID + l, err := c.parseLog(c.registry, log) + if err != nil { + c.logger.Debugw("failed to parse log", "err", err) + continue + } + id := l.Id() + upkeepId := &ocr2keepers.UpkeepIdentifier{} + ok := upkeepId.FromBigInt(id) + if !ok { + return nil, core.ErrInvalidUpkeepID + } + triggerW, err := core.UnpackTrigger(id, l.Trigger()) + if err != nil { + return nil, fmt.Errorf("%w: failed to unpack trigger", err) + } + trigger := ocr2keepers.NewTrigger( + ocr2keepers.BlockNumber(triggerW.BlockNum), + triggerW.BlockHash, + ) + switch core.GetUpkeepType(*upkeepId) { + case ocr2keepers.LogTrigger: + trigger.LogTriggerExtension = &ocr2keepers.LogTriggerExtension{} + trigger.LogTriggerExtension.TxHash = triggerW.TxHash + trigger.LogTriggerExtension.Index = triggerW.LogIndex + default: + } + workID := core.UpkeepWorkID(*upkeepId, trigger) + transmitEvent = ocr2keepers.TransmitEvent{ + Type: l.TransmitEventType(), + TransmitBlock: ocr2keepers.BlockNumber(l.BlockNumber), + TransactionHash: l.TxHash, + WorkID: workID, + UpkeepID: *upkeepId, + CheckBlock: trigger.BlockNumber, + } } - triggerW, err := core.UnpackTrigger(id, l.Trigger()) - if err != nil { - return nil, fmt.Errorf("%w: failed to unpack trigger", err) - } - trigger := ocr2keepers.NewTrigger( - ocr2keepers.BlockNumber(triggerW.BlockNum), - triggerW.BlockHash, - ) - switch core.GetUpkeepType(*upkeepId) { - case ocr2keepers.LogTrigger: - trigger.LogTriggerExtension = &ocr2keepers.LogTriggerExtension{} - trigger.LogTriggerExtension.TxHash = triggerW.TxHash - trigger.LogTriggerExtension.Index = triggerW.LogIndex - default: - } - workID := core.UpkeepWorkID(*upkeepId, trigger) - e := ocr2keepers.TransmitEvent{ - Type: l.TransmitEventType(), - TransmitBlock: ocr2keepers.BlockNumber(l.BlockNumber), - Confirmations: latestBlock - l.BlockNumber, - TransactionHash: l.TxHash, - WorkID: workID, - UpkeepID: *upkeepId, - CheckBlock: trigger.BlockNumber, - } - vals = append(vals, e) - visited[k] = e + + transmitEvent.Confirmations = latestBlock - int64(transmitEvent.TransmitBlock) + + vals = append(vals, transmitEvent) + visited[k] = transmitEvent } // adding to the cache only after we've processed all the logs - // the next time we call processLogs we don't want to return these logs + // the next time we call processLogs we don't want to process these logs for k, e := range visited { c.cache.add(k, e) } From c38b8621d3f923082673686bb1ac56940e71702a Mon Sep 17 00:00:00 2001 From: amit-momin <108959691+amit-momin@users.noreply.github.com> Date: Tue, 5 Sep 2023 00:58:40 -0500 Subject: [PATCH 13/14] Add RequestID field to Transactions (#10363) * Added request_id field to eth_txes to track external component requests * Rearranged logic, added missing validation, and linted * Fixed mocks * Added new TxStore tests * Addressed PR feedback * Updated migration sequencing * Changed RequestID name to IdempotencyKey and updated type to UUID * Switched IdempotencyKey type back to string --- common/txmgr/txmgr.go | 15 +++++++ common/txmgr/types/mocks/tx_store.go | 26 +++++++++++ common/txmgr/types/tx.go | 9 ++++ common/txmgr/types/tx_store.go | 3 ++ core/chains/evm/txmgr/evm_tx_store.go | 23 ++++++++-- core/chains/evm/txmgr/evm_tx_store_test.go | 29 ++++++++++++ core/chains/evm/txmgr/mocks/evm_tx_store.go | 26 +++++++++++ core/chains/evm/txmgr/txmgr_test.go | 45 +++++++++++++++++++ core/internal/cltest/factories.go | 6 +++ ...2_add_request_id_column_eth_txes_table.sql | 7 +++ 10 files changed, 186 insertions(+), 3 deletions(-) create mode 100644 core/store/migrate/migrations/0192_add_request_id_column_eth_txes_table.sql diff --git a/common/txmgr/txmgr.go b/common/txmgr/txmgr.go index 422e1a364b5..0bcf3e482ee 100644 --- a/common/txmgr/txmgr.go +++ b/common/txmgr/txmgr.go @@ -2,6 +2,7 @@ package txmgr import ( "context" + "database/sql" "fmt" "math/big" "sync" @@ -435,6 +436,20 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Trigger(ad // CreateTransaction inserts a new transaction func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) CreateTransaction(txRequest txmgrtypes.TxRequest[ADDR, TX_HASH], qs ...pg.QOpt) (tx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) { + // Check for existing Tx with IdempotencyKey. If found, return the Tx and do nothing + // Skipping CreateTransaction to avoid double send + if txRequest.IdempotencyKey != nil { + var existingTx *txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] + existingTx, err = b.txStore.FindTxWithIdempotencyKey(*txRequest.IdempotencyKey, b.chainID) + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return tx, errors.Wrap(err, "Failed to search for transaction with IdempotencyKey") + } + if existingTx != nil { + b.logger.Infow("Found a Tx with IdempotencyKey. Returning existing Tx without creating a new one.", "IdempotencyKey", *txRequest.IdempotencyKey) + return *existingTx, nil + } + } + if err = b.checkEnabled(txRequest.FromAddress); err != nil { return tx, err } diff --git a/common/txmgr/types/mocks/tx_store.go b/common/txmgr/types/mocks/tx_store.go index 055d7852bfd..9c812788bf6 100644 --- a/common/txmgr/types/mocks/tx_store.go +++ b/common/txmgr/types/mocks/tx_store.go @@ -322,6 +322,32 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxAttem return r0, r1 } +// FindTxWithIdempotencyKey provides a mock function with given fields: idempotencyKey, chainID +func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxWithIdempotencyKey(idempotencyKey string, chainID CHAIN_ID) (*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) { + ret := _m.Called(idempotencyKey, chainID) + + var r0 *txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] + var r1 error + if rf, ok := ret.Get(0).(func(string, CHAIN_ID) (*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error)); ok { + return rf(idempotencyKey, chainID) + } + if rf, ok := ret.Get(0).(func(string, CHAIN_ID) *txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]); ok { + r0 = rf(idempotencyKey, chainID) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) + } + } + + if rf, ok := ret.Get(1).(func(string, CHAIN_ID) error); ok { + r1 = rf(idempotencyKey, chainID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // FindTxWithSequence provides a mock function with given fields: fromAddress, seq func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxWithSequence(fromAddress ADDR, seq SEQ) (*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) { ret := _m.Called(fromAddress, seq) diff --git a/common/txmgr/types/tx.go b/common/txmgr/types/tx.go index a28c72fd363..a0faa81c3aa 100644 --- a/common/txmgr/types/tx.go +++ b/common/txmgr/types/tx.go @@ -66,6 +66,14 @@ func (s TxAttemptState) String() (str string) { } type TxRequest[ADDR types.Hashable, TX_HASH types.Hashable] struct { + // IdempotencyKey is a globally unique ID set by the caller, to prevent accidental creation of duplicated Txs during retries or crash recovery. + // If this field is set, the TXM will first search existing Txs with this field. + // If found, it will return the existing Tx, without creating a new one. TXM will not validate or ensure that existing Tx is same as the incoming TxRequest. + // If not found, TXM will create a new Tx. + // If IdempotencyKey is set to null, TXM will always create a new Tx. + // Since IdempotencyKey has to be globally unique, consider prepending the service or component's name it is being used by + // Such as {service}-{ID}. E.g vrf-12345 + IdempotencyKey *string FromAddress ADDR ToAddress ADDR EncodedPayload []byte @@ -178,6 +186,7 @@ type Tx[ FEE feetypes.Fee, ] struct { ID int64 + IdempotencyKey *string Sequence *SEQ FromAddress ADDR ToAddress ADDR diff --git a/common/txmgr/types/tx_store.go b/common/txmgr/types/tx_store.go index 41a989fc769..8c56b8a6ed6 100644 --- a/common/txmgr/types/tx_store.go +++ b/common/txmgr/types/tx_store.go @@ -64,6 +64,9 @@ type TransactionStore[ FindTxAttemptsConfirmedMissingReceipt(chainID CHAIN_ID) (attempts []TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) FindTxAttemptsRequiringReceiptFetch(chainID CHAIN_ID) (attempts []TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) FindTxAttemptsRequiringResend(olderThan time.Time, maxInFlightTransactions uint32, chainID CHAIN_ID, address ADDR) (attempts []TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) + // Search for Tx using the idempotencyKey and chainID + FindTxWithIdempotencyKey(idempotencyKey string, chainID CHAIN_ID) (tx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) + // Search for Tx using the fromAddress and sequence FindTxWithSequence(fromAddress ADDR, seq SEQ) (etx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) FindNextUnstartedTransactionFromAddress(etx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], fromAddress ADDR, chainID CHAIN_ID, qopts ...pg.QOpt) error FindTransactionsConfirmedInBlockRange(highBlockNumber, lowBlockNumber int64, chainID CHAIN_ID) (etxs []*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index 1df4073e528..dbd3437aa82 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -152,6 +152,7 @@ func toOnchainReceipt(rs []*evmtypes.Receipt) []rawOnchainReceipt { // This is exported, as tests and other external code still directly reads DB using this schema. type DbEthTx struct { ID int64 + IdempotencyKey *string Nonce *int64 FromAddress common.Address ToAddress common.Address @@ -218,6 +219,7 @@ func DbEthTxToEthTx(dbEthTx DbEthTx, evmEthTx *Tx) { n := evmtypes.Nonce(*dbEthTx.Nonce) evmEthTx.Sequence = &n } + evmEthTx.IdempotencyKey = dbEthTx.IdempotencyKey evmEthTx.FromAddress = dbEthTx.FromAddress evmEthTx.ToAddress = dbEthTx.ToAddress evmEthTx.EncodedPayload = dbEthTx.EncodedPayload @@ -906,6 +908,21 @@ func (o *evmTxStore) FindReceiptsPendingConfirmation(ctx context.Context, blockN return } +// FindTxWithIdempotencyKey returns any broadcast ethtx with the given idempotencyKey and chainID +func (o *evmTxStore) FindTxWithIdempotencyKey(idempotencyKey string, chainID *big.Int) (etx *Tx, err error) { + var dbEtx DbEthTx + err = o.q.Get(&dbEtx, `SELECT * FROM eth_txes WHERE idempotency_key = $1 and evm_chain_id = $2`, idempotencyKey, chainID.String()) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + return nil, nil + } + return nil, pkgerrors.Wrap(err, "FindTxWithIdempotencyKey failed to load eth_txes") + } + etx = new(Tx) + DbEthTxToEthTx(dbEtx, etx) + return +} + // FindTxWithSequence returns any broadcast ethtx with the given nonce func (o *evmTxStore) FindTxWithSequence(fromAddress common.Address, nonce evmtypes.Nonce) (etx *Tx, err error) { etx = new(Tx) @@ -1501,12 +1518,12 @@ func (o *evmTxStore) CreateTransaction(txRequest TxRequest, chainID *big.Int, qo } } err = tx.Get(&dbEtx, ` -INSERT INTO eth_txes (from_address, to_address, encoded_payload, value, gas_limit, state, created_at, meta, subject, evm_chain_id, min_confirmations, pipeline_task_run_id, transmit_checker) +INSERT INTO eth_txes (from_address, to_address, encoded_payload, value, gas_limit, state, created_at, meta, subject, evm_chain_id, min_confirmations, pipeline_task_run_id, transmit_checker, idempotency_key) VALUES ( -$1,$2,$3,$4,$5,'unstarted',NOW(),$6,$7,$8,$9,$10,$11 +$1,$2,$3,$4,$5,'unstarted',NOW(),$6,$7,$8,$9,$10,$11,$12 ) RETURNING "eth_txes".* -`, txRequest.FromAddress, txRequest.ToAddress, txRequest.EncodedPayload, assets.Eth(txRequest.Value), txRequest.FeeLimit, txRequest.Meta, txRequest.Strategy.Subject(), chainID.String(), txRequest.MinConfirmations, txRequest.PipelineTaskRunID, txRequest.Checker) +`, txRequest.FromAddress, txRequest.ToAddress, txRequest.EncodedPayload, assets.Eth(txRequest.Value), txRequest.FeeLimit, txRequest.Meta, txRequest.Strategy.Subject(), chainID.String(), txRequest.MinConfirmations, txRequest.PipelineTaskRunID, txRequest.Checker, txRequest.IdempotencyKey) if err != nil { return pkgerrors.Wrap(err, "CreateEthTransaction failed to insert eth_tx") } diff --git a/core/chains/evm/txmgr/evm_tx_store_test.go b/core/chains/evm/txmgr/evm_tx_store_test.go index b4be30063b5..777a179be45 100644 --- a/core/chains/evm/txmgr/evm_tx_store_test.go +++ b/core/chains/evm/txmgr/evm_tx_store_test.go @@ -666,6 +666,35 @@ func TestORM_FindReceiptsPendingConfirmation(t *testing.T) { assert.Equal(t, tr.ID, receiptsPlus[0].ID) } +func Test_FindTxWithIdempotencyKey(t *testing.T) { + t.Parallel() + db := pgtest.NewSqlxDB(t) + cfg := newTestChainScopedConfig(t) + txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) + + t.Run("returns nil if no results", func(t *testing.T) { + idempotencyKey := "777" + etx, err := txStore.FindTxWithIdempotencyKey(idempotencyKey, big.NewInt(0)) + require.NoError(t, err) + assert.Nil(t, etx) + }) + + t.Run("returns transaction if it exists", func(t *testing.T) { + idempotencyKey := "777" + cfg.EVM().ChainID() + etx := cltest.MustCreateUnstartedGeneratedTx(t, txStore, fromAddress, big.NewInt(0), + cltest.EvmTxRequestWithIdempotencyKey(idempotencyKey)) + require.Equal(t, idempotencyKey, *etx.IdempotencyKey) + + res, err := txStore.FindTxWithIdempotencyKey(idempotencyKey, big.NewInt(0)) + require.NoError(t, err) + assert.Equal(t, etx.Sequence, res.Sequence) + require.Equal(t, idempotencyKey, *res.IdempotencyKey) + }) +} + func TestORM_FindTxWithSequence(t *testing.T) { t.Parallel() diff --git a/core/chains/evm/txmgr/mocks/evm_tx_store.go b/core/chains/evm/txmgr/mocks/evm_tx_store.go index ef481df3b70..4a06741a2f3 100644 --- a/core/chains/evm/txmgr/mocks/evm_tx_store.go +++ b/core/chains/evm/txmgr/mocks/evm_tx_store.go @@ -428,6 +428,32 @@ func (_m *EvmTxStore) FindTxWithAttempts(etxID int64) (types.Tx[*big.Int, common return r0, r1 } +// FindTxWithIdempotencyKey provides a mock function with given fields: idempotencyKey, chainID +func (_m *EvmTxStore) FindTxWithIdempotencyKey(idempotencyKey string, chainID *big.Int) (*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) { + ret := _m.Called(idempotencyKey, chainID) + + var r0 *types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee] + var r1 error + if rf, ok := ret.Get(0).(func(string, *big.Int) (*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)); ok { + return rf(idempotencyKey, chainID) + } + if rf, ok := ret.Get(0).(func(string, *big.Int) *types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]); ok { + r0 = rf(idempotencyKey, chainID) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) + } + } + + if rf, ok := ret.Get(1).(func(string, *big.Int) error); ok { + r1 = rf(idempotencyKey, chainID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // FindTxWithSequence provides a mock function with given fields: fromAddress, seq func (_m *EvmTxStore) FindTxWithSequence(fromAddress common.Address, seq evmtypes.Nonce) (*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) { ret := _m.Called(fromAddress, seq) diff --git a/core/chains/evm/txmgr/txmgr_test.go b/core/chains/evm/txmgr/txmgr_test.go index 00333d7df87..854ccd6a4af 100644 --- a/core/chains/evm/txmgr/txmgr_test.go +++ b/core/chains/evm/txmgr/txmgr_test.go @@ -323,6 +323,51 @@ func TestTxm_CreateTransaction(t *testing.T) { require.NotNil(t, m.FwdrDestAddress) require.Equal(t, etx.ToAddress.String(), fwdrAddr.String()) }) + + t.Run("insert Tx successfully with a IdempotencyKey", func(t *testing.T) { + evmConfig.maxQueued = uint64(3) + id := uuid.New() + idempotencyKey := "1" + _, err := txm.CreateTransaction(txmgr.TxRequest{ + IdempotencyKey: &idempotencyKey, + FromAddress: fromAddress, + ToAddress: testutils.NewAddress(), + EncodedPayload: []byte{1, 2, 3}, + FeeLimit: 21000, + PipelineTaskRunID: &id, + Strategy: txmgrcommon.NewSendEveryStrategy(), + }) + assert.NoError(t, err) + }) + + t.Run("doesn't insert eth_tx if a matching tx already exists for that IdempotencyKey", func(t *testing.T) { + evmConfig.maxQueued = uint64(3) + id := uuid.New() + idempotencyKey := "2" + tx1, err := txm.CreateTransaction(txmgr.TxRequest{ + IdempotencyKey: &idempotencyKey, + FromAddress: fromAddress, + ToAddress: testutils.NewAddress(), + EncodedPayload: []byte{1, 2, 3}, + FeeLimit: 21000, + PipelineTaskRunID: &id, + Strategy: txmgrcommon.NewSendEveryStrategy(), + }) + assert.NoError(t, err) + + tx2, err := txm.CreateTransaction(txmgr.TxRequest{ + IdempotencyKey: &idempotencyKey, + FromAddress: fromAddress, + ToAddress: testutils.NewAddress(), + EncodedPayload: []byte{1, 2, 3}, + FeeLimit: 21000, + PipelineTaskRunID: &id, + Strategy: txmgrcommon.NewSendEveryStrategy(), + }) + assert.NoError(t, err) + + assert.Equal(t, tx1.GetID(), tx2.GetID()) + }) } func newMockTxStrategy(t *testing.T) *commontxmmocks.TxStrategy { diff --git a/core/internal/cltest/factories.go b/core/internal/cltest/factories.go index 800731f74a4..bfa479af624 100644 --- a/core/internal/cltest/factories.go +++ b/core/internal/cltest/factories.go @@ -348,6 +348,12 @@ func EvmTxRequestWithValue(value big.Int) func(*txmgr.TxRequest) { } } +func EvmTxRequestWithIdempotencyKey(idempotencyKey string) func(*txmgr.TxRequest) { + return func(tx *txmgr.TxRequest) { + tx.IdempotencyKey = &idempotencyKey + } +} + func MustCreateUnstartedTx(t testing.TB, txStore txmgr.EvmTxStore, fromAddress common.Address, toAddress common.Address, encodedPayload []byte, gasLimit uint32, value big.Int, chainID *big.Int, opts ...interface{}) (tx txmgr.Tx) { txRequest := txmgr.TxRequest{ FromAddress: fromAddress, diff --git a/core/store/migrate/migrations/0192_add_request_id_column_eth_txes_table.sql b/core/store/migrate/migrations/0192_add_request_id_column_eth_txes_table.sql new file mode 100644 index 00000000000..6a9ab7846d1 --- /dev/null +++ b/core/store/migrate/migrations/0192_add_request_id_column_eth_txes_table.sql @@ -0,0 +1,7 @@ +-- +goose Up + +ALTER TABLE eth_txes ADD COLUMN idempotency_key varchar(2000) UNIQUE; + +-- +goose Down + +ALTER TABLE eth_txes DROP COLUMN idempotency_key; From 0e2d15a6ce5479c3d5109d0864fe737b0fbc5826 Mon Sep 17 00:00:00 2001 From: Akshay Aggarwal <71980293+infiloop2@users.noreply.github.com> Date: Tue, 5 Sep 2023 12:58:55 +0100 Subject: [PATCH 14/14] Increase block time sample size (#10482) --- .../ocr2/plugins/ocr2keeper/evm21/logprovider/block_time.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/block_time.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/block_time.go index 1d8500bcc61..3af93f873c1 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/block_time.go +++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/block_time.go @@ -11,7 +11,7 @@ import ( ) var ( - defaultSampleSize = int64(10) + defaultSampleSize = int64(200) defaultBlockTime = time.Second * 1 )