diff --git a/.changeset/dark-jays-hit.md b/.changeset/dark-jays-hit.md new file mode 100644 index 00000000000..bed308f04cb --- /dev/null +++ b/.changeset/dark-jays-hit.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Support for SVR multiplexing #added diff --git a/.changeset/fancy-apples-dance.md b/.changeset/fancy-apples-dance.md new file mode 100644 index 00000000000..782e09f63e7 --- /dev/null +++ b/.changeset/fancy-apples-dance.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Emit beholder message for Atlas userOp #added diff --git a/.changeset/fluffy-beans-camp.md b/.changeset/fluffy-beans-camp.md new file mode 100644 index 00000000000..5919ebadf56 --- /dev/null +++ b/.changeset/fluffy-beans-camp.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Send dualBroadcastParams in TxMessage #added diff --git a/.changeset/soft-sheep-fish.md b/.changeset/soft-sheep-fish.md new file mode 100644 index 00000000000..d463c71b3ac --- /dev/null +++ b/.changeset/soft-sheep-fish.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Fix overactive logging of submitted transactions #fixed diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 799d9df513d..4550d55b3ae 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -48,7 +48,6 @@ /core/scripts/vrf*/ @smartcontractkit/dev-services # Keeper/Automation-related services -/core/services/keeper/ @smartcontractkit/dev-services /core/services/ocr2/plugins/ocr2keeper/ @smartcontractkit/dev-services # Chainlink Functions diff --git a/.github/integration-in-memory-tests.yml b/.github/integration-in-memory-tests.yml index 135765c6de6..0a8a436b110 100644 --- a/.github/integration-in-memory-tests.yml +++ b/.github/integration-in-memory-tests.yml @@ -54,22 +54,6 @@ runner-test-matrix: -- -v -run "Test_CCIPMessaging_EVM2EVM" -timeout 18m -count=1 -parallel=4 ./smoke/ccip test_go_project_path: integration-tests - - id: smoke/ccip/ccip_messaging_test.go:Test_CCIPMessaging_EVM2Solana - path: integration-tests/smoke/ccip/ccip_messaging_test.go - test_env_type: in-memory - runs_on: ubuntu-latest - runs_on_self_hosted: runs-on/cpu=8/ram=32/family=m6i+m5.*/spot=false/image=ubuntu24-full-x64/extras=s3-cache+tmpfs - triggers: - - PR Integration CCIP Tests - - Nightly Integration CCIP Tests - test_cmd: | - gotestsum \ - --junitfile=/tmp/junit.xml \ - --jsonfile=/tmp/gotest.log \ - --format=github-actions \ - -- -v -run "Test_CCIPMessaging_EVM2Solana" -timeout 18m -count=1 -parallel=4 ./smoke/ccip - test_go_project_path: integration-tests - - id: smoke/ccip/ccip_messaging_test.go:Test_CCIPMessaging_EVM2Solana_LOOPP path: integration-tests/smoke/ccip/ccip_messaging_test.go test_env_type: in-memory @@ -86,24 +70,6 @@ runner-test-matrix: -- -v -run "Test_CCIPMessaging_EVM2Solana" -timeout 18m -count=1 -parallel=4 ./smoke/ccip test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - - - id: smoke/ccip/ccip_messaging_test.go:Test_CCIPMessaging_Solana2EVM - path: integration-tests/smoke/ccip/ccip_messaging_test.go - test_env_type: in-memory - runs_on: ubuntu-latest - runs_on_self_hosted: runs-on/cpu=8/ram=32/family=m6i+m5.*/spot=false/image=ubuntu24-full-x64/extras=s3-cache+tmpfs - triggers: - - PR Integration CCIP Tests - - Nightly Integration CCIP Tests - test_cmd: | - gotestsum \ - --junitfile=/tmp/junit.xml \ - --jsonfile=/tmp/gotest.log \ - --format=github-actions \ - -- -v -run "Test_CCIPMessaging_Solana2EVM" -timeout 18m -count=1 -parallel=4 ./smoke/ccip - test_go_project_path: integration-tests - id: smoke/ccip/ccip_messaging_test.go:Test_CCIPMessaging_Solana2EVM_LOOPP path: integration-tests/smoke/ccip/ccip_messaging_test.go @@ -121,8 +87,6 @@ runner-test-matrix: -- -v -run "Test_CCIPMessaging_Solana2EVM" -timeout 18m -count=1 -parallel=4 ./smoke/ccip test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_messaging_test.go:Test_CCIPMessaging_Revert_EVM2Solana_LOOPP path: integration-tests/smoke/ccip/ccip_messaging_test.go @@ -140,8 +104,6 @@ runner-test-matrix: -- -v -run "Test_CCIPMessaging_Revert_EVM2Solana" -timeout 18m -count=1 -parallel=4 ./smoke/ccip test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_messaging_test.go:Test_CCIPMessaging_MultiExecReports_EVM2Solana path: integration-tests/smoke/ccip/ccip_messaging_test.go @@ -399,6 +361,7 @@ runner-test-matrix: --format=github-actions \ -- -v -run ".*" -timeout 16m -count=1 -parallel=2 smoke/ccip/ccip_token_transfer_test.go test_go_project_path: integration-tests + install_plugins_public: true - id: smoke/ccip/ccip_token_transfer_test.go:*_LOOPP path: integration-tests/smoke/ccip/ccip_token_transfer_test.go @@ -416,8 +379,6 @@ runner-test-matrix: -- -v -run ".*" -timeout 16m -count=1 -parallel=2 smoke/ccip/ccip_token_transfer_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_update_rmn_config_test.go:* path: integration-tests/smoke/ccip/ccip_cs_update_rmn_config_test.go @@ -449,6 +410,7 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNCurse$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseUncurseAptos path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -482,6 +444,7 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNCurseMCMS$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseBypass path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -498,6 +461,7 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNCurseBypass$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseIdempotent path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -513,6 +477,7 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNCurseIdempotent$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNUncurseIdempotent path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -528,6 +493,7 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNUncurseIdempotent$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNUncurse path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -544,6 +510,7 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNUncurse$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNUncurseMCMS path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -560,6 +527,7 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNUncurseMCMS$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNUncurseBypass path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -576,6 +544,7 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNUncurseBypass$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseConfigValidate path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -592,6 +561,7 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNCurseConfigValidate$" -timeout 20m -count=1 -parallel=2 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseNoConnectedLanes path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -607,6 +577,7 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNCurseNoConnectedLanes$" -timeout 20m -count=1 -parallel=1 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseOneConnectedLanes path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -622,6 +593,7 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNCurseOneConnectedLanes$" -timeout 20m -count=1 -parallel=1 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseOneConnectedLanesSolana path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -637,6 +609,7 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNCurseOneConnectedLanesSolana$" -timeout 20m -count=1 -parallel=1 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseOneConnectedLanesGlobalOnly path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -652,6 +625,7 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNCurseOneConnectedLanesGlobalOnly$" -timeout 20m -count=1 -parallel=1 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseOneConnectedLanesLaneOnlyOnSource path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -667,6 +641,7 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNCurseOneConnectedLanesLaneOnlyOnSource$" -timeout 20m -count=1 -parallel=1 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNUncurseForceOption path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -683,6 +658,7 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNUncurseForceOption$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true - id: smoke/ccip/ccip_disable_lane_test.go:* path: integration-tests/smoke/ccip/ccip_disable_lane_test.go diff --git a/.github/workflows/legacy-system-tests.yml b/.github/workflows/legacy-system-tests.yml index 63e2a072715..2d7d15e9fc3 100644 --- a/.github/workflows/legacy-system-tests.yml +++ b/.github/workflows/legacy-system-tests.yml @@ -177,30 +177,6 @@ jobs: runner: "ubuntu24.04-16cores-64GB" tests_dir: "automation" logs_archive_name: "automation-smoke-2_3" - - display_name: "Keepers Smoke Tests 1" - testcmd: "go test -v -timeout 1h -run TestKeeperBasic\\|TestKeeperSimulation\\|TestKeeperCheckPerformGasLimit\\|TestKeeperRegisterUpkeep\\|TestKeeperAddFunds\\|TestKeeperRemove\\|TestKeeperPauseRegistry\\|TestKeeperMigrateRegistry\\|TestKeeperJobReplacement" - envcmd: "cl u env.toml,products/keepers/basic.toml" - runner: "ubuntu24.04-16cores-64GB" - tests_dir: "keepers" - logs_archive_name: "keepers-smoke-1" - - display_name: "Keepers Smoke Tests 2" - testcmd: "go test -v -timeout 1h -run TestKeeperNodeDown" - envcmd: "cl u env.toml,products/keepers/low_bcptr.toml" - runner: "ubuntu24.04-16cores-64GB" - tests_dir: "keepers" - logs_archive_name: "keepers-smoke-2" - - display_name: "Keepers Smoke Tests 3" - testcmd: "go test -v -timeout 1h -run TestKeeperPauseUnPauseUpkeep\\|TestKeeperUpdateCheckData" - envcmd: "cl u env.toml,products/keepers/low_bcptr.toml" - runner: "ubuntu24.04-16cores-64GB" - tests_dir: "keepers" - logs_archive_name: "keepers-smoke-3" - - display_name: "Keepers Smoke Tests 4" - testcmd: "go test -v -timeout 1h -run TestKeeperBlockCountPerTurn" - envcmd: "cl u env.toml,env-geth.toml,products/keepers/high_bcptr.toml" - runner: "ubuntu24.04-16cores-64GB" - tests_dir: "keepers" - logs_archive_name: "keepers-smoke-4" - display_name: "Test VRFv2Plus Smoke" testcmd: "go test -v -timeout 30m -run TestVRFv2PlusSmoke" envcmd: "cl u env-vrf2plus.toml,products/vrfv2plus/basic.toml" diff --git a/common/txmgr/mocks/evm_tx_store.go b/common/txmgr/mocks/evm_tx_store.go index da1ea938e11..594590e8352 100644 --- a/common/txmgr/mocks/evm_tx_store.go +++ b/common/txmgr/mocks/evm_tx_store.go @@ -2336,6 +2336,63 @@ func (_c *EvmTxStore_LoadTxAttempts_Call) RunAndReturn(run func(context.Context, return _c } +// OldestNonTerminalTxAgeSeconds provides a mock function with given fields: ctx, chainID +func (_m *EvmTxStore) OldestNonTerminalTxAgeSeconds(ctx context.Context, chainID *big.Int) (float64, error) { + ret := _m.Called(ctx, chainID) + + if len(ret) == 0 { + panic("no return value specified for OldestNonTerminalTxAgeSeconds") + } + + var r0 float64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *big.Int) (float64, error)); ok { + return rf(ctx, chainID) + } + if rf, ok := ret.Get(0).(func(context.Context, *big.Int) float64); ok { + r0 = rf(ctx, chainID) + } else { + r0 = ret.Get(0).(float64) + } + + if rf, ok := ret.Get(1).(func(context.Context, *big.Int) error); ok { + r1 = rf(ctx, chainID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// EvmTxStore_OldestNonTerminalTxAgeSeconds_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'OldestNonTerminalTxAgeSeconds' +type EvmTxStore_OldestNonTerminalTxAgeSeconds_Call struct { + *mock.Call +} + +// OldestNonTerminalTxAgeSeconds is a helper method to define mock.On call +// - ctx context.Context +// - chainID *big.Int +func (_e *EvmTxStore_Expecter) OldestNonTerminalTxAgeSeconds(ctx interface{}, chainID interface{}) *EvmTxStore_OldestNonTerminalTxAgeSeconds_Call { + return &EvmTxStore_OldestNonTerminalTxAgeSeconds_Call{Call: _e.mock.On("OldestNonTerminalTxAgeSeconds", ctx, chainID)} +} + +func (_c *EvmTxStore_OldestNonTerminalTxAgeSeconds_Call) Run(run func(ctx context.Context, chainID *big.Int)) *EvmTxStore_OldestNonTerminalTxAgeSeconds_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*big.Int)) + }) + return _c +} + +func (_c *EvmTxStore_OldestNonTerminalTxAgeSeconds_Call) Return(seconds float64, err error) *EvmTxStore_OldestNonTerminalTxAgeSeconds_Call { + _c.Call.Return(seconds, err) + return _c +} + +func (_c *EvmTxStore_OldestNonTerminalTxAgeSeconds_Call) RunAndReturn(run func(context.Context, *big.Int) (float64, error)) *EvmTxStore_OldestNonTerminalTxAgeSeconds_Call { + _c.Call.Return(run) + return _c +} + // PreloadTxes provides a mock function with given fields: ctx, attempts func (_m *EvmTxStore) PreloadTxes(ctx context.Context, attempts []types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, pkgtypes.Nonce, gas.EvmFee]) error { ret := _m.Called(ctx, attempts) diff --git a/core/capabilities/ccip/ccipsolana/pluginconfig.go b/core/capabilities/ccip/ccipsolana/pluginconfig.go index ca70b3774b9..919ffe9d6e3 100644 --- a/core/capabilities/ccip/ccipsolana/pluginconfig.go +++ b/core/capabilities/ccip/ccipsolana/pluginconfig.go @@ -6,8 +6,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/types/ccip/consts" "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink/v2/core/config/env" - ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ocrimpls" ) @@ -26,7 +24,7 @@ func InitializePluginConfig(lggr logger.Logger, extraDataCodec ccipocr3.ExtraDat ChainRW: ChainRWProvider{}, ExtraDataCodec: ExtraDataDecoder{}, PriceOnlyCommitFn: consts.MethodCommitPriceOnly, - CCIPProviderSupported: env.SolanaPlugin.Cmd.Get() != "", + CCIPProviderSupported: true, } } diff --git a/core/cmd/blocks_commands_integration_test.go b/core/cmd/blocks_commands_integration_test.go new file mode 100644 index 00000000000..ebe246d2d6b --- /dev/null +++ b/core/cmd/blocks_commands_integration_test.go @@ -0,0 +1,37 @@ +//go:build integration + +package cmd_test + +import ( + "flag" + "testing" + + "github.com/stretchr/testify/require" + "github.com/urfave/cli" + + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" +) + +func Test_ReplayFromBlock_Solana(t *testing.T) { + t.Parallel() + + chain := chainlink.RawConfig{ + "ChainID": "devnet", + "Enabled": true, + "Nodes": []map[string]any{{ + "Name": "primary", + "URL": "http://solana.example", + }}, + } + app := solanaStartNewApplication(t, chain) + client, _ := app.NewShellAndRenderer() + + set := flag.NewFlagSet("test", 0) + flagSetApplyFromAction(client.ReplayFromBlock, set, "") + + require.NoError(t, set.Set("block-number", "1")) + require.NoError(t, set.Set("chain-id", "devnet")) + require.NoError(t, set.Set("family", "solana")) + c := cli.NewContext(nil, set, nil) + require.NoError(t, client.ReplayFromBlock(c)) +} diff --git a/core/cmd/blocks_commands_test.go b/core/cmd/blocks_commands_test.go index a510df01054..da50bc03060 100644 --- a/core/cmd/blocks_commands_test.go +++ b/core/cmd/blocks_commands_test.go @@ -9,7 +9,6 @@ import ( "github.com/urfave/cli" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" ) @@ -19,13 +18,6 @@ func Test_ReplayFromBlock(t *testing.T) { app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].ChainID = (*sqlutil.Big)(big.NewInt(5)) c.EVM[0].Enabled = ptr(true) - - solCfg := &config.TOMLConfig{ - ChainID: ptr("devnet"), - Enabled: ptr(true), - } - solCfg.SetDefaults() - c.Solana = config.TOMLConfigs{solCfg} }) client, _ := app.NewShellAndRenderer() @@ -59,14 +51,6 @@ func Test_ReplayFromBlock(t *testing.T) { c := cli.NewContext(nil, set, nil) require.NoError(t, client.ReplayFromBlock(c)) }) - - t.Run("solana replay", func(t *testing.T) { - require.NoError(t, set.Set("block-number", "1")) - require.NoError(t, set.Set("chain-id", "devnet")) - require.NoError(t, set.Set("family", "solana")) - c := cli.NewContext(nil, set, nil) - require.NoError(t, client.ReplayFromBlock(c)) - }) } func Test_FindLCA(t *testing.T) { diff --git a/core/cmd/chains_commands_integration_test.go b/core/cmd/chains_commands_integration_test.go index 8427f483b3e..c173b28e9b6 100644 --- a/core/cmd/chains_commands_integration_test.go +++ b/core/cmd/chains_commands_integration_test.go @@ -11,6 +11,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/cosmostest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/solanatest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" ) @@ -35,3 +36,26 @@ func TestShell_IndexCosmosChains(t *testing.T) { assert.Equal(t, chainID, c.ID) assertTableRenders(t, r) } + +func TestShell_IndexSolanaChains(t *testing.T) { + t.Parallel() + + id := solanatest.RandomChainID() + chain := chainlink.RawConfig{ + "ChainID": id, + "Enabled": true, + "Nodes": []map[string]any{{ + "Name": "primary", + "URL": "http://solana.example", + }}, + } + app := solanaStartNewApplication(t, chain) + client, r := app.NewShellAndRenderer() + + require.NoError(t, cmd.NewChainClient(client, "solana").IndexChains(cltest.EmptyCLIContext())) + chains := *r.Renders[0].(*cmd.ChainPresenters) + require.Len(t, chains, 1) + c := chains[0] + assert.Equal(t, id, c.ID) + assertTableRenders(t, r) +} diff --git a/core/cmd/chains_commands_test.go b/core/cmd/chains_commands_test.go index c509cf7f5eb..645b0d4551e 100644 --- a/core/cmd/chains_commands_test.go +++ b/core/cmd/chains_commands_test.go @@ -7,14 +7,11 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" client2 "github.com/smartcontractkit/chainlink-evm/pkg/client" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/solanatest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" ) @@ -39,22 +36,3 @@ func TestShell_IndexEVMChains(t *testing.T) { assert.Equal(t, strconv.Itoa(client2.NullClientChainID), c.ID) assertTableRenders(t, r) } - -func TestShell_IndexSolanaChains(t *testing.T) { - t.Parallel() - - id := solanatest.RandomChainID() - cfg := solcfg.TOMLConfig{ - ChainID: &id, - Enabled: ptr(true), - } - app := solanaStartNewApplication(t, &cfg) - client, r := app.NewShellAndRenderer() - - require.NoError(t, cmd.NewChainClient(client, "solana").IndexChains(cltest.EmptyCLIContext())) - chains := *r.Renders[0].(*cmd.ChainPresenters) - require.Len(t, chains, 1) - c := chains[0] - assert.Equal(t, id, c.ID) - assertTableRenders(t, r) -} diff --git a/core/cmd/jobs_commands.go b/core/cmd/jobs_commands.go index 9af68926191..67e60ed7050 100644 --- a/core/cmd/jobs_commands.go +++ b/core/cmd/jobs_commands.go @@ -132,10 +132,6 @@ func (p JobPresenter) FriendlyCreatedAt() string { if p.OffChainReportingSpec != nil { return p.OffChainReportingSpec.CreatedAt.Format(time.RFC3339) } - case presenters.KeeperJobSpec: - if p.KeeperSpec != nil { - return p.KeeperSpec.CreatedAt.Format(time.RFC3339) - } case presenters.CronJobSpec: if p.CronSpec != nil { return p.CronSpec.CreatedAt.Format(time.RFC3339) diff --git a/core/cmd/jobs_commands_test.go b/core/cmd/jobs_commands_test.go index 8dc5686f567..1d6b10a65e0 100644 --- a/core/cmd/jobs_commands_test.go +++ b/core/cmd/jobs_commands_test.go @@ -54,7 +54,6 @@ func TestJobPresenter_RenderTable(t *testing.T) { UpdatedAt: updatedAt, }, OffChainReportingSpec: nil, - KeeperSpec: nil, PipelineSpec: presenters.PipelineSpec{ ID: 1, DotDAGSource: "ds1 [type=http method=GET url=\"example.com\" allowunrestrictednetworkaccess=\"true\"];\n ds1_parse [type=jsonparse path=\"USD\"];\n ds1_multiply [type=multiply times=100];\n ds1 -\u003e ds1_parse -\u003e ds1_multiply;\n", diff --git a/core/cmd/node_commands_integration_test.go b/core/cmd/node_commands_integration_test.go index 5e81319ae54..6ac3c3e60c6 100644 --- a/core/cmd/node_commands_integration_test.go +++ b/core/cmd/node_commands_integration_test.go @@ -12,9 +12,11 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/cosmostest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/solanatest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" ) @@ -25,6 +27,13 @@ func cosmosStartNewApplication(t *testing.T, cfgs ...chainlink.RawConfig) *cltes }) } +func solanaStartNewApplication(t *testing.T, cfgs ...chainlink.RawConfig) *cltest.TestApplication { + return startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.Solana = cfgs + c.EVM = nil + }) +} + func TestShell_IndexCosmosNodes(t *testing.T) { t.Parallel() @@ -132,3 +141,60 @@ func TestShell_IndexStarkNetNodes(t *testing.T) { assert.Contains(t, renderLines[11], "State") assert.Contains(t, renderLines[11], n2.State) } + +func TestShell_IndexSolanaNodes(t *testing.T) { + t.Parallel() + + id := solanatest.RandomChainID() + node1 := map[string]any{ + "Name": ptr("first"), + "URL": config.MustParseURL("https://solana1.example"), + "SendOnly": false, + } + node2 := map[string]any{ + "Name": ptr("second"), + "URL": config.MustParseURL("https://solana2.example"), + "SendOnly": false, + } + chain := chainlink.RawConfig{ + "ChainID": id, + "Nodes": []any{node1, node2}, + } + app := solanaStartNewApplication(t, chain) + client, r := app.NewShellAndRenderer() + + require.NoError(t, cmd.NewNodeClient(client, "solana").IndexNodes(cltest.EmptyCLIContext())) + require.NotEmpty(t, r.Renders) + nodes := *r.Renders[0].(*cmd.NodePresenters) + require.Len(t, nodes, 2) + n1 := nodes[0] + n2 := nodes[1] + assert.Equal(t, id, n1.ChainID) + assert.Equal(t, cltest.FormatWithPrefixedChainID(id, "first"), n1.ID) + assert.Equal(t, "first", n1.Name) + assert.Equal(t, "Name = 'first'\nURL = 'https://solana1.example'\nSendOnly = false\n", n1.Config) + assert.Equal(t, id, n2.ChainID) + assert.Equal(t, cltest.FormatWithPrefixedChainID(id, "second"), n2.ID) + assert.Equal(t, "second", n2.Name) + assert.Equal(t, "Name = 'second'\nURL = 'https://solana2.example'\nSendOnly = false\n", n2.Config) + assertTableRenders(t, r) + + // Render table and check the fields order + b := new(bytes.Buffer) + rt := cmd.RendererTable{b} + require.NoError(t, nodes.RenderTable(rt)) + renderLines := strings.Split(b.String(), "\n") + assert.Len(t, renderLines, 19) + assert.Contains(t, renderLines[2], "Name") + assert.Contains(t, renderLines[2], n1.Name) + assert.Contains(t, renderLines[3], "Chain ID") + assert.Contains(t, renderLines[3], n1.ChainID) + assert.Contains(t, renderLines[4], "State") + assert.Contains(t, renderLines[4], n1.State) + assert.Contains(t, renderLines[10], "Name") + assert.Contains(t, renderLines[10], n2.Name) + assert.Contains(t, renderLines[11], "Chain ID") + assert.Contains(t, renderLines[11], n2.ChainID) + assert.Contains(t, renderLines[12], "State") + assert.Contains(t, renderLines[12], n2.State) +} diff --git a/core/cmd/node_commands_test.go b/core/cmd/node_commands_test.go index 53021b33216..3841d8ddece 100644 --- a/core/cmd/node_commands_test.go +++ b/core/cmd/node_commands_test.go @@ -10,12 +10,10 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/config" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" configtoml "github.com/smartcontractkit/chainlink-evm/pkg/config/toml" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/solanatest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" ) @@ -96,71 +94,3 @@ func TestShell_IndexEVMNodes(t *testing.T) { assert.Contains(t, renderLines[14], n2.State) } -func solanaStartNewApplication(t *testing.T, cfgs ...*solcfg.TOMLConfig) *cltest.TestApplication { - for i := range cfgs { - cfgs[i].SetDefaults() - } - return startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Solana = cfgs - c.EVM = nil - }) -} - -func TestShell_IndexSolanaNodes(t *testing.T) { - t.Parallel() - - id := solanatest.RandomChainID() - node1 := solcfg.Node{ - Name: ptr("first"), - URL: config.MustParseURL("https://solana1.example"), - } - node2 := solcfg.Node{ - Name: ptr("second"), - URL: config.MustParseURL("https://solana2.example"), - } - chain := solcfg.TOMLConfig{ - ChainID: &id, - Nodes: solcfg.Nodes{&node1, &node2}, - } - app := solanaStartNewApplication(t, &chain) - client, r := app.NewShellAndRenderer() - - require.NoError(t, cmd.NewNodeClient(client, "solana").IndexNodes(cltest.EmptyCLIContext())) - require.NotEmpty(t, r.Renders) - nodes := *r.Renders[0].(*cmd.NodePresenters) - require.Len(t, nodes, 2) - n1 := nodes[0] - n2 := nodes[1] - assert.Equal(t, id, n1.ChainID) - assert.Equal(t, cltest.FormatWithPrefixedChainID(id, *node1.Name), n1.ID) - assert.Equal(t, *node1.Name, n1.Name) - wantConfig, err := toml.Marshal(node1) - require.NoError(t, err) - assert.Equal(t, string(wantConfig), n1.Config) - assert.Equal(t, id, n2.ChainID) - assert.Equal(t, cltest.FormatWithPrefixedChainID(id, *node2.Name), n2.ID) - assert.Equal(t, *node2.Name, n2.Name) - wantConfig2, err := toml.Marshal(node2) - require.NoError(t, err) - assert.Equal(t, string(wantConfig2), n2.Config) - assertTableRenders(t, r) - - // Render table and check the fields order - b := new(bytes.Buffer) - rt := cmd.RendererTable{b} - require.NoError(t, nodes.RenderTable(rt)) - renderLines := strings.Split(b.String(), "\n") - assert.Len(t, renderLines, 19) - assert.Contains(t, renderLines[2], "Name") - assert.Contains(t, renderLines[2], n1.Name) - assert.Contains(t, renderLines[3], "Chain ID") - assert.Contains(t, renderLines[3], n1.ChainID) - assert.Contains(t, renderLines[4], "State") - assert.Contains(t, renderLines[4], n1.State) - assert.Contains(t, renderLines[10], "Name") - assert.Contains(t, renderLines[10], n2.Name) - assert.Contains(t, renderLines[11], "Chain ID") - assert.Contains(t, renderLines[11], n2.ChainID) - assert.Contains(t, renderLines[12], "State") - assert.Contains(t, renderLines[12], n2.State) -} diff --git a/core/cmd/shell_remote_test.go b/core/cmd/shell_remote_test.go index 4c110cced8d..319dcbe0c47 100644 --- a/core/cmd/shell_remote_test.go +++ b/core/cmd/shell_remote_test.go @@ -24,7 +24,7 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-evm/pkg/client/clienttest" - "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" + "github.com/smartcontractkit/chainlink/v2/core/auth" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/cmd" @@ -122,13 +122,6 @@ func TestShell_ReplayBlocks(t *testing.T) { c.EVM[0].NonceAutoSync = ptr(false) c.EVM[0].BalanceMonitor.Enabled = ptr(false) c.EVM[0].GasEstimator.Mode = ptr("FixedPrice") - - solCfg := &config.TOMLConfig{ - ChainID: ptr("devnet"), - Enabled: ptr(true), - } - solCfg.SetDefaults() - c.Solana = config.TOMLConfigs{solCfg} }) client, _ := app.NewShellAndRenderer() @@ -144,10 +137,6 @@ func TestShell_ReplayBlocks(t *testing.T) { require.NoError(t, set.Set("chain-id", testutils.FixtureChainID.String())) c = cli.NewContext(nil, set, nil) assert.NoError(t, client.ReplayFromBlock(c)) - - require.NoError(t, set.Set("chain-id", "devnet")) - require.NoError(t, set.Set("family", "solana")) - assert.NoError(t, client.ReplayFromBlock(c)) } func TestShell_CreateExternalInitiator(t *testing.T) { diff --git a/core/cmd/shell_test.go b/core/cmd/shell_test.go index c5a72a93a1d..905b57501b4 100644 --- a/core/cmd/shell_test.go +++ b/core/cmd/shell_test.go @@ -20,9 +20,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/beholder/beholdertest" commoncfg "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil/sqltest" commonevents "github.com/smartcontractkit/chainlink-protos/workflows/go/common" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" @@ -358,45 +356,36 @@ func TestNewUserCache(t *testing.T) { func TestSetupSolanaRelayer(t *testing.T) { lggr := logger.TestLogger(t) reg := plugins.NewTestLoopRegistry(lggr) - ks := &keystore.StarknetLooppSigner{StarkNet: mocks.NewStarkNet(t)} + ks := &keystore.SolanaLooppSigner{Solana: mocks.NewSolana(t)} ksCSA := &keystore.CSASigner{CSA: mocks.NewCSA(t)} - ds := sqltest.NewNoOpDataSource() // config 3 chains but only enable 2 => should only be 2 relayer nEnabledChains := 2 tConfig := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Solana = solcfg.TOMLConfigs{ - &solcfg.TOMLConfig{ - ChainID: ptr[string]("solana-id-1"), - Enabled: ptr(true), - Nodes: []*solcfg.Node{}, + c.Solana = chainlink.RawConfigs{ + { + "ChainID": "solana-id-1", + "Enabled": true, }, - &solcfg.TOMLConfig{ - ChainID: ptr[string]("solana-id-2"), - Enabled: ptr(true), - Nodes: []*solcfg.Node{}, + { + "ChainID": "solana-id-2", + "Enabled": true, }, - &solcfg.TOMLConfig{ - ChainID: ptr[string]("disabled-solana-id-1"), - Enabled: ptr(false), - Nodes: []*solcfg.Node{}, + { + "ChainID": "disabled-solana-id-1", + "Enabled": false, }, } - for i := range c.Solana { - c.Solana[i].SetDefaults() - } }) t2Config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Solana = solcfg.TOMLConfigs{ - &solcfg.TOMLConfig{ - ChainID: ptr[string]("solana-id-1"), - Enabled: ptr(true), - Nodes: []*solcfg.Node{}, + c.Solana = chainlink.RawConfigs{ + { + "ChainID": "solana-id-1", + "Enabled": true, }, } - c.Solana[0].SetDefaults() }) rf := chainlink.RelayerFactory{ @@ -404,24 +393,10 @@ func TestSetupSolanaRelayer(t *testing.T) { LoopRegistry: reg, } - cfg := chainlink.SolanaFactoryConfig{ - TOMLConfigs: tConfig.SolanaConfigs(), - DS: ds} - - // not parallel; shared state - t.Run("no plugin", func(t *testing.T) { - relayers, err := rf.NewSolana(ks, ksCSA, cfg) - require.NoError(t, err) - require.NotNil(t, relayers) - require.Len(t, relayers, nEnabledChains) - // no using plugin, so registry should be empty - require.Empty(t, reg.List()) - }) - t.Run("plugin", func(t *testing.T) { t.Setenv("CL_SOLANA_CMD", "phony_solana_cmd") - relayers, err := rf.NewSolana(ks, ksCSA, cfg) + relayers, err := rf.NewSolana(ks, ksCSA, tConfig.SolanaConfigs()) require.NoError(t, err) require.NotNil(t, relayers) require.Len(t, relayers, nEnabledChains) @@ -431,34 +406,21 @@ func TestSetupSolanaRelayer(t *testing.T) { // test that duplicate enabled chains is an error when duplicateConfig := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Solana = solcfg.TOMLConfigs{ - &solcfg.TOMLConfig{ - ChainID: ptr[string]("dupe"), - Enabled: ptr(true), + c.Solana = chainlink.RawConfigs{ + { + "ChainID": "dupe", + "Enabled": true, }, - &solcfg.TOMLConfig{ - ChainID: ptr[string]("dupe"), - Enabled: ptr(true), + { + "ChainID": "dupe", + "Enabled": true, }, } - for i := range c.Solana { - c.Solana[i].SetDefaults() - } - }) - dupCfg := chainlink.SolanaFactoryConfig{ - TOMLConfigs: duplicateConfig.SolanaConfigs(), - DS: ds, - } - - // not parallel; shared state - t.Run("no plugin, duplicate chains", func(t *testing.T) { - _, err := rf.NewSolana(ks, ksCSA, dupCfg) - require.Error(t, err) }) t.Run("plugin, duplicate chains", func(t *testing.T) { t.Setenv("CL_SOLANA_CMD", "phony_solana_cmd") - _, err := rf.NewSolana(ks, ksCSA, dupCfg) + _, err := rf.NewSolana(ks, ksCSA, duplicateConfig.SolanaConfigs()) require.Error(t, err) }) @@ -466,20 +428,17 @@ func TestSetupSolanaRelayer(t *testing.T) { t.Setenv("CL_SOLANA_CMD", "phony_solana_cmd") t.Setenv("CL_SOLANA_ENV", "fake_path") - _, err := rf.NewSolana(ks, ksCSA, chainlink.SolanaFactoryConfig{ - TOMLConfigs: t2Config.SolanaConfigs(), - DS: ds, - }) + _, err := rf.NewSolana(ks, ksCSA, t2Config.SolanaConfigs()) require.Error(t, err) - require.Contains(t, err.Error(), "failed to parse Solana env file") + require.Contains(t, err.Error(), "failed to parse env file") }) t.Run("plugin already registered", func(t *testing.T) { t.Setenv("CL_SOLANA_CMD", "phony_solana_cmd") - _, err := rf.NewSolana(ks, ksCSA, cfg) + _, err := rf.NewSolana(ks, ksCSA, tConfig.SolanaConfigs()) require.Error(t, err) - require.Contains(t, err.Error(), "failed to create Solana LOOP command") + require.Contains(t, err.Error(), "failed to create LOOP command") }) } diff --git a/core/cmd/solana_transaction_commands_test.go b/core/cmd/solana_transaction_commands_test.go index b7623840095..7d4031d7d2a 100644 --- a/core/cmd/solana_transaction_commands_test.go +++ b/core/cmd/solana_transaction_commands_test.go @@ -15,10 +15,9 @@ import ( "github.com/stretchr/testify/require" "github.com/urfave/cli" - "github.com/smartcontractkit/chainlink-common/pkg/config" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" solanatesting "github.com/smartcontractkit/chainlink-solana/pkg/solana/testing" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/cmd" ) @@ -28,16 +27,14 @@ func TestShell_SolanaSendSol(t *testing.T) { ctx := testutils.Context(t) chainID := "localnet" url := solanatesting.SetupLocalSolNode(t) - node := solcfg.Node{ - Name: ptr(t.Name()), - URL: config.MustParseURL(url), + chain := chainlink.RawConfig{ + "ChainID": chainID, + "Enabled": true, + "Nodes": []any{ + map[string]any{"Name": t.Name(), "URL": url}, + }, } - cfg := solcfg.TOMLConfig{ - ChainID: &chainID, - Nodes: solcfg.Nodes{&node}, - Enabled: ptr(true), - } - app := solanaStartNewApplication(t, &cfg) + app := solanaStartNewApplication(t, chain) from, err := app.GetKeyStore().Solana().Create(ctx) require.NoError(t, err) to, err := solanago.NewRandomPrivateKey() diff --git a/core/config/app_config.go b/core/config/app_config.go index 107cf7def88..37755cbb265 100644 --- a/core/config/app_config.go +++ b/core/config/app_config.go @@ -45,7 +45,6 @@ type AppConfig interface { Insecure() Insecure JobDistributor() JobDistributor JobPipeline() JobPipeline - Keeper() Keeper Log() Log Mercury() Mercury OCR() OCR diff --git a/core/config/docs/core.toml b/core/config/docs/core.toml index 31a0b510fbd..62d666b08d2 100644 --- a/core/config/docs/core.toml +++ b/core/config/docs/core.toml @@ -684,42 +684,6 @@ RegistryBasedLaunchAllowlist = [] # Default # proxyMode = 'gateway' # Example # allowedPorts = '443,8443' # Example -[Keeper] -# **ADVANCED** -# DefaultTransactionQueueDepth controls the queue size for `DropOldestStrategy` in Keeper. Set to 0 to use `SendEvery` strategy instead. -DefaultTransactionQueueDepth = 1 # Default -# **ADVANCED** -# GasPriceBufferPercent specifies the percentage to add to the gas price used for checking whether to perform an upkeep. Only applies in legacy mode (EIP-1559 off). -GasPriceBufferPercent = 20 # Default -# **ADVANCED** -# GasTipCapBufferPercent specifies the percentage to add to the gas price used for checking whether to perform an upkeep. Only applies in EIP-1559 mode. -GasTipCapBufferPercent = 20 # Default -# **ADVANCED** -# BaseFeeBufferPercent specifies the percentage to add to the base fee used for checking whether to perform an upkeep. Applies only in EIP-1559 mode. -BaseFeeBufferPercent = 20 # Default -# **ADVANCED** -# MaxGracePeriod is the maximum number of blocks that a keeper will wait after performing an upkeep before it resumes checking that upkeep -MaxGracePeriod = 100 # Default -# TurnLookBack is the number of blocks in the past to look back when getting a block for a turn. -TurnLookBack = 1_000 # Default - -[Keeper.Registry] -# **ADVANCED** -# CheckGasOverhead is the amount of extra gas to provide checkUpkeep() calls to account for the gas consumed by the keeper registry. -CheckGasOverhead = 200_000 # Default -# **ADVANCED** -# PerformGasOverhead is the amount of extra gas to provide performUpkeep() calls to account for the gas consumed by the keeper registry -PerformGasOverhead = 300_000 # Default -# **ADVANCED** -# SyncInterval is the interval in which the RegistrySynchronizer performs a full sync of the keeper registry contract it is tracking. -SyncInterval = '30m' # Default -# **ADVANCED** -# MaxPerformDataSize is the max size of perform data. -MaxPerformDataSize = 5_000 # Default -# **ADVANCED** -# SyncUpkeepQueueSize represents the maximum number of upkeeps that can be synced in parallel. -SyncUpkeepQueueSize = 10 # Default - # The Chainlink node is equipped with an internal "nurse" service that can perform automatic `pprof` profiling when the certain resource thresholds are exceeded, such as memory and goroutine count. These profiles are saved to disk to facilitate fine-grained debugging of performance-related issues. In general, if you notice that your node has begun to accumulate profiles, forward them to the Chainlink team. # # To learn more about these profiles, read the [Profiling Go programs with pprof](https://jvns.ca/blog/2017/09/24/profiling-go-with-pprof/) guide. diff --git a/core/config/keeper_config.go b/core/config/keeper_config.go deleted file mode 100644 index 565e70dc25d..00000000000 --- a/core/config/keeper_config.go +++ /dev/null @@ -1,21 +0,0 @@ -package config - -import "time" - -type Registry interface { - CheckGasOverhead() uint32 - PerformGasOverhead() uint32 - MaxPerformDataSize() uint32 - SyncInterval() time.Duration - SyncUpkeepQueueSize() uint32 -} - -type Keeper interface { - DefaultTransactionQueueDepth() uint32 - GasPriceBufferPercent() uint16 - GasTipCapBufferPercent() uint16 - BaseFeeBufferPercent() uint16 - MaxGracePeriod() int64 - TurnLookBack() int64 - Registry() Registry -} diff --git a/core/config/toml/types.go b/core/config/toml/types.go index af9cf192255..57afac2a40c 100644 --- a/core/config/toml/types.go +++ b/core/config/toml/types.go @@ -52,7 +52,6 @@ type Core struct { OCR2 OCR2 `toml:",omitempty"` OCR OCR `toml:",omitempty"` P2P P2P `toml:",omitempty"` - Keeper Keeper `toml:",omitempty"` AutoPprof AutoPprof `toml:",omitempty"` Pyroscope Pyroscope `toml:",omitempty"` Sentry Sentry `toml:",omitempty"` @@ -97,7 +96,6 @@ func (c *Core) SetFrom(f *Core) { c.OCR2.setFrom(&f.OCR2) c.OCR.setFrom(&f.OCR) c.P2P.setFrom(&f.P2P) - c.Keeper.setFrom(&f.Keeper) c.Mercury.setFrom(&f.Mercury) c.Capabilities.setFrom(&f.Capabilities) c.Workflows.setFrom(&f.Workflows) @@ -1615,66 +1613,6 @@ func (p *P2PV2) setFrom(f *P2PV2) { } } -type Keeper struct { - DefaultTransactionQueueDepth *uint32 - GasPriceBufferPercent *uint16 - GasTipCapBufferPercent *uint16 - BaseFeeBufferPercent *uint16 - MaxGracePeriod *int64 - TurnLookBack *int64 - - Registry KeeperRegistry `toml:",omitempty"` -} - -func (k *Keeper) setFrom(f *Keeper) { - if v := f.DefaultTransactionQueueDepth; v != nil { - k.DefaultTransactionQueueDepth = v - } - if v := f.GasPriceBufferPercent; v != nil { - k.GasPriceBufferPercent = v - } - if v := f.GasTipCapBufferPercent; v != nil { - k.GasTipCapBufferPercent = v - } - if v := f.BaseFeeBufferPercent; v != nil { - k.BaseFeeBufferPercent = v - } - if v := f.MaxGracePeriod; v != nil { - k.MaxGracePeriod = v - } - if v := f.TurnLookBack; v != nil { - k.TurnLookBack = v - } - - k.Registry.setFrom(&f.Registry) -} - -type KeeperRegistry struct { - CheckGasOverhead *uint32 - PerformGasOverhead *uint32 - MaxPerformDataSize *uint32 - SyncInterval *commonconfig.Duration - SyncUpkeepQueueSize *uint32 -} - -func (k *KeeperRegistry) setFrom(f *KeeperRegistry) { - if v := f.CheckGasOverhead; v != nil { - k.CheckGasOverhead = v - } - if v := f.PerformGasOverhead; v != nil { - k.PerformGasOverhead = v - } - if v := f.MaxPerformDataSize; v != nil { - k.MaxPerformDataSize = v - } - if v := f.SyncInterval; v != nil { - k.SyncInterval = v - } - if v := f.SyncUpkeepQueueSize; v != nil { - k.SyncUpkeepQueueSize = v - } -} - type AutoPprof struct { Enabled *bool ProfileRoot *string diff --git a/core/internal/cltest/factories.go b/core/internal/cltest/factories.go index b408f37814a..96c9c0d0294 100644 --- a/core/internal/cltest/factories.go +++ b/core/internal/cltest/factories.go @@ -5,7 +5,6 @@ import ( "flag" "fmt" "math/big" - mathrand "math/rand" "net/url" "testing" @@ -27,10 +26,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/auth" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/keeper" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/store/models" @@ -216,82 +212,6 @@ func MakeDirectRequestJobSpec(t *testing.T) *job.Job { return spec } -func MustInsertKeeperJob(t *testing.T, db *sqlx.DB, korm *keeper.ORM, from evmtypes.EIP55Address, contract evmtypes.EIP55Address) job.Job { - t.Helper() - ctx := testutils.Context(t) - - var keeperSpec job.KeeperSpec - err := korm.DataSource().GetContext(ctx, &keeperSpec, `INSERT INTO keeper_specs (contract_address, from_address, created_at, updated_at,evm_chain_id) VALUES ($1, $2, NOW(), NOW(), $3) RETURNING *`, contract, from, testutils.SimulatedChainID.Int64()) - require.NoError(t, err) - - var pipelineSpec pipeline.Spec - err = korm.DataSource().GetContext(ctx, &pipelineSpec, `INSERT INTO pipeline_specs (dot_dag_source,created_at) VALUES ('',NOW()) RETURNING *`) - require.NoError(t, err) - - jb := job.Job{ - KeeperSpec: &keeperSpec, - KeeperSpecID: &keeperSpec.ID, - ExternalJobID: uuid.New(), - Type: job.Keeper, - SchemaVersion: 1, - PipelineSpec: &pipelineSpec, - PipelineSpecID: pipelineSpec.ID, - } - - cfg := configtest.NewTestGeneralConfig(t) - tlg := logger.TestLogger(t) - prm := pipeline.NewORM(db, tlg, cfg.JobPipeline().MaxSuccessfulRuns()) - btORM := bridges.NewORM(db) - jrm := job.NewORM(db, prm, btORM, nil, tlg) - err = jrm.InsertJob(testutils.Context(t), &jb) - require.NoError(t, err) - jb.PipelineSpec.JobID = jb.ID - return jb -} - -func MustInsertKeeperRegistry(t *testing.T, db *sqlx.DB, korm *keeper.ORM, ethKeyStore keystore.Eth, keeperIndex, numKeepers, blockCountPerTurn int32) (keeper.Registry, job.Job) { - t.Helper() - ctx := testutils.Context(t) - key, _ := MustInsertRandomKey(t, ethKeyStore, *sqlutil.New(testutils.SimulatedChainID)) - from := key.EIP55Address - contractAddress := NewEIP55Address() - jb := MustInsertKeeperJob(t, db, korm, from, contractAddress) - registry := keeper.Registry{ - ContractAddress: contractAddress, - BlockCountPerTurn: blockCountPerTurn, - CheckGas: 150_000, - FromAddress: from, - JobID: jb.ID, - KeeperIndex: keeperIndex, - NumKeepers: numKeepers, - KeeperIndexMap: map[evmtypes.EIP55Address]int32{ - from: keeperIndex, - }, - } - err := korm.UpsertRegistry(ctx, ®istry) - require.NoError(t, err) - return registry, jb -} - -func MustInsertUpkeepForRegistry(t *testing.T, db *sqlx.DB, registry keeper.Registry) keeper.UpkeepRegistration { - ctx := testutils.Context(t) - korm := keeper.NewORM(db, logger.TestLogger(t)) - upkeepID := sqlutil.NewI(int64(mathrand.Uint32())) - upkeep := keeper.UpkeepRegistration{ - UpkeepID: upkeepID, - ExecuteGas: uint32(150_000), - Registry: registry, - RegistryID: registry.ID, - CheckData: common.Hex2Bytes("ABC123"), - } - positioningConstant, err := keeper.CalcPositioningConstant(upkeepID, registry.ContractAddress) - require.NoError(t, err) - upkeep.PositioningConstant = positioningConstant - err = korm.UpsertUpkeep(ctx, &upkeep) - require.NoError(t, err) - return upkeep -} - func MustInsertExternalInitiator(t *testing.T, orm bridges.ORM) (ei bridges.ExternalInitiator) { return MustInsertExternalInitiatorWithOpts(t, orm, ExternalInitiatorOpts{}) } diff --git a/core/scripts/chaincli/command/keeper/upkeep.go b/core/scripts/chaincli/command/keeper/upkeep.go index 90f4bf63716..df295e821d0 100644 --- a/core/scripts/chaincli/command/keeper/upkeep.go +++ b/core/scripts/chaincli/command/keeper/upkeep.go @@ -11,7 +11,6 @@ import ( "github.com/smartcontractkit/chainlink/core/scripts/chaincli/config" "github.com/smartcontractkit/chainlink/core/scripts/chaincli/handler" - "github.com/smartcontractkit/chainlink/v2/core/services/keeper" ) // upkeepEventsCmd represents the command to run the upkeep events counter command @@ -42,11 +41,11 @@ var upkeepHistoryCmd = &cobra.Command{ Short: "Print checkUpkeep history", Long: `Print checkUpkeep status and keeper responsibility for a given upkeep in a set block range`, Run: func(cmd *cobra.Command, args []string) { - upkeepIdStr, err := cmd.Flags().GetString("upkeep-id") + upkeepIDStr, err := cmd.Flags().GetString("upkeep-id") if err != nil { log.Fatal("failed to get 'upkeep-id' flag: ", err) } - upkeepId, ok := keeper.ParseUpkeepId(upkeepIdStr) + upkeepID, ok := handler.ParseUpkeepID(upkeepIDStr) if !ok { log.Fatal("failed to parse upkeep-id") } @@ -69,7 +68,7 @@ var upkeepHistoryCmd = &cobra.Command{ cfg := config.New() hdlr := handler.NewKeeper(cfg) - hdlr.UpkeepHistory(cmd.Context(), upkeepId, fromBlock, toBlock, gasPrice) + hdlr.UpkeepHistory(cmd.Context(), upkeepID, fromBlock, toBlock, gasPrice) }, } diff --git a/core/scripts/chaincli/config/config.go b/core/scripts/chaincli/config/config.go index a5fbcb187d3..f3c06bfcb04 100644 --- a/core/scripts/chaincli/config/config.go +++ b/core/scripts/chaincli/config/config.go @@ -6,8 +6,6 @@ import ( "log" "github.com/spf13/viper" - - "github.com/smartcontractkit/chainlink/v2/core/services/keeper" ) // UpkeepType represents an upkeep type @@ -66,7 +64,7 @@ type Config struct { UpkeepPrivilegeManager string `mapstructure:"UPKEEP_PRIVILEGE_MANAGER"` // Upkeep Config - RegistryVersion keeper.RegistryVersion `mapstructure:"KEEPER_REGISTRY_VERSION"` + RegistryVersion RegistryVersion `mapstructure:"KEEPER_REGISTRY_VERSION"` RegistryAddress string `mapstructure:"KEEPER_REGISTRY_ADDRESS"` RegistryConfigUpdate bool `mapstructure:"KEEPER_CONFIG_UPDATE"` KeepersCount int `mapstructure:"KEEPERS_COUNT"` @@ -130,7 +128,7 @@ func New() *Config { // Validate validates the given config func (c *Config) Validate() error { // OCR2Keeper job could be ran only with the registry 2.0 - if c.OCR2Keepers && c.RegistryVersion < keeper.RegistryVersion_2_0 { + if c.OCR2Keepers && c.RegistryVersion < RegistryVersion2_0 { return fmt.Errorf("ocr2keeper job could be ran only with the registry 2.0, but %s specified", c.RegistryVersion) } @@ -179,6 +177,6 @@ func init() { viper.SetDefault("MAX_PERFORM_GAS", 5000000) viper.SetDefault("TRANSCODER", "0x0000000000000000000000000000000000000000") viper.SetDefault("REGISTRAR", "0x0000000000000000000000000000000000000000") - viper.SetDefault("KEEPER_REGISTRY_VERSION", 2) + viper.SetDefault("KEEPER_REGISTRY_VERSION", 4) viper.SetDefault("FUND_CHAINLINK_NODE", "20000000000000000000") } diff --git a/core/scripts/chaincli/config/registry_version.go b/core/scripts/chaincli/config/registry_version.go new file mode 100644 index 00000000000..119ab961463 --- /dev/null +++ b/core/scripts/chaincli/config/registry_version.go @@ -0,0 +1,20 @@ +package config + +// RegistryVersion identifies a keeper registry contract version for chaincli tooling. +type RegistryVersion int32 + +const ( + RegistryVersion2_0 RegistryVersion = 4 + RegistryVersion2_1 RegistryVersion = 5 +) + +func (rv RegistryVersion) String() string { + switch rv { + case RegistryVersion2_0: + return "v2.0" + case RegistryVersion2_1: + return "v2.1" + default: + return "unknown registry version" + } +} diff --git a/core/scripts/chaincli/handler/keeper.go b/core/scripts/chaincli/handler/keeper.go index c93e8e2c780..d52e138fb19 100644 --- a/core/scripts/chaincli/handler/keeper.go +++ b/core/scripts/chaincli/handler/keeper.go @@ -21,8 +21,6 @@ import ( registrylogic20 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_logic2_0" registrylogica21 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_logic_a_wrapper_2_1" registrylogicb21 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_logic_b_wrapper_2_1" - registry11 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_1" - registry12 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_2" registry20 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper2_0" registry21 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper_2_1" "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/log_upkeep_counter_wrapper" @@ -35,7 +33,6 @@ import ( helpers "github.com/smartcontractkit/chainlink/core/scripts/common" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/keeper" ) // Keeper is the keepers commands handler @@ -101,7 +98,7 @@ func (k *Keeper) DeployKeepers(ctx context.Context) { // DeployRegistry deploys a new keeper registry. func (k *Keeper) DeployRegistry(ctx context.Context, verify bool) { if verify { - if k.cfg.RegistryVersion != keeper.RegistryVersion_2_1 && k.cfg.RegistryVersion != keeper.RegistryVersion_2_0 { + if k.cfg.RegistryVersion != config.RegistryVersion2_1 && k.cfg.RegistryVersion != config.RegistryVersion2_0 { log.Fatal("keeper registry verification is only supported for version 2.0 and 2.1") } if k.cfg.ExplorerAPIKey == "" || k.cfg.ExplorerAPIKey == "" || k.cfg.NetworkName == "" || k.cfg.NetworkName == "" { @@ -121,13 +118,9 @@ func (k *Keeper) DeployRegistry(ctx context.Context, verify bool) { } switch k.cfg.RegistryVersion { - case keeper.RegistryVersion_1_1: - k.deployRegistry11(ctx) - case keeper.RegistryVersion_1_2: - k.deployRegistry12(ctx) - case keeper.RegistryVersion_2_0: + case config.RegistryVersion2_0: k.deployRegistry20(ctx, verify) - case keeper.RegistryVersion_2_1: + case config.RegistryVersion2_1: k.deployRegistry21(ctx, verify) default: panic("unsupported registry version") @@ -138,8 +131,6 @@ func (k *Keeper) prepareRegistry(ctx context.Context) (int64, common.Address, ke var upkeepCount int64 var registryAddr common.Address var deployer keepersDeployer - var keeperRegistry11 *registry11.KeeperRegistry - var keeperRegistry12 *registry12.KeeperRegistry var keeperRegistry20 *registry20.KeeperRegistry var keeperRegistry21 *iregistry21.IKeeperRegistryMaster if k.cfg.RegistryAddress != "" { @@ -150,23 +141,7 @@ func (k *Keeper) prepareRegistry(ctx context.Context) (int64, common.Address, ke // Get existing keeper registry switch k.cfg.RegistryVersion { - case keeper.RegistryVersion_1_1: - registryAddr, keeperRegistry11 = k.getRegistry11(ctx) - count, err := keeperRegistry11.GetUpkeepCount(&callOpts) - if err != nil { - log.Fatal(registryAddr.Hex(), ": UpkeepCount failed - ", err) - } - upkeepCount = count.Int64() - deployer = &v11KeeperDeployer{keeperRegistry11} - case keeper.RegistryVersion_1_2: - registryAddr, keeperRegistry12 = k.getRegistry12(ctx) - state, err := keeperRegistry12.GetState(&callOpts) - if err != nil { - log.Fatal(registryAddr.Hex(), ": failed to getState - ", err) - } - upkeepCount = state.State.NumUpkeeps.Int64() - deployer = &v12KeeperDeployer{keeperRegistry12} - case keeper.RegistryVersion_2_0: + case config.RegistryVersion2_0: registryAddr, keeperRegistry20 = k.getRegistry20(ctx) state, err := keeperRegistry20.GetState(&callOpts) if err != nil { @@ -174,7 +149,7 @@ func (k *Keeper) prepareRegistry(ctx context.Context) (int64, common.Address, ke } upkeepCount = state.State.NumUpkeeps.Int64() deployer = &v20KeeperDeployer{KeeperRegistryInterface: keeperRegistry20, cfg: k.cfg} - case keeper.RegistryVersion_2_1: + case config.RegistryVersion2_1: registryAddr, keeperRegistry21 = k.getRegistry21(ctx) state, err := keeperRegistry21.GetState(&callOpts) if err != nil { @@ -188,16 +163,10 @@ func (k *Keeper) prepareRegistry(ctx context.Context) (int64, common.Address, ke } else { // Deploy keeper registry switch k.cfg.RegistryVersion { - case keeper.RegistryVersion_1_1: - registryAddr, keeperRegistry11 = k.deployRegistry11(ctx) - deployer = &v11KeeperDeployer{keeperRegistry11} - case keeper.RegistryVersion_1_2: - registryAddr, keeperRegistry12 = k.deployRegistry12(ctx) - deployer = &v12KeeperDeployer{keeperRegistry12} - case keeper.RegistryVersion_2_0: + case config.RegistryVersion2_0: registryAddr, keeperRegistry20 = k.deployRegistry20(ctx, true) deployer = &v20KeeperDeployer{KeeperRegistryInterface: keeperRegistry20, cfg: k.cfg} - case keeper.RegistryVersion_2_1: + case config.RegistryVersion2_1: registryAddr, keeperRegistry21 = k.deployRegistry21(ctx, false) deployer = &v21KeeperDeployer{IKeeperRegistryMasterInterface: keeperRegistry21, cfg: k.cfg} default: @@ -363,58 +332,13 @@ func (k *Keeper) deployRegistry20(ctx context.Context, verify bool) (common.Addr return registryAddr, registryInstance } -// deployRegistry12 deploys a version 1.2 keeper registry -func (k *Keeper) deployRegistry12(ctx context.Context) (common.Address, *registry12.KeeperRegistry) { - registryAddr, deployKeeperRegistryTx, registryInstance, err := registry12.DeployKeeperRegistry( - k.buildTxOpts(ctx), - k.client, - common.HexToAddress(k.cfg.LinkTokenAddr), - common.HexToAddress(k.cfg.LinkETHFeedAddr), - common.HexToAddress(k.cfg.FastGasFeedAddr), - *k.getConfigForRegistry12(), - ) - if err != nil { - log.Fatal("DeployAbi failed: ", err) - } - k.waitDeployment(ctx, deployKeeperRegistryTx) - log.Println("KeeperRegistry1.2 deployed:", registryAddr.Hex(), "-", helpers.ExplorerLink(k.cfg.ChainID, deployKeeperRegistryTx.Hash())) - return registryAddr, registryInstance -} - -// deployRegistry11 deploys a version 1.1 keeper registry -func (k *Keeper) deployRegistry11(ctx context.Context) (common.Address, *registry11.KeeperRegistry) { - registryAddr, deployKeeperRegistryTx, registryInstance, err := registry11.DeployKeeperRegistry(k.buildTxOpts(ctx), k.client, - common.HexToAddress(k.cfg.LinkTokenAddr), - common.HexToAddress(k.cfg.LinkETHFeedAddr), - common.HexToAddress(k.cfg.FastGasFeedAddr), - k.cfg.PaymentPremiumPBB, - k.cfg.FlatFeeMicroLink, - big.NewInt(k.cfg.BlockCountPerTurn), - k.cfg.CheckGasLimit, - big.NewInt(k.cfg.StalenessSeconds), - k.cfg.GasCeilingMultiplier, - big.NewInt(k.cfg.FallbackGasPrice), - big.NewInt(k.cfg.FallbackLinkPrice), - ) - if err != nil { - log.Fatal("DeployAbi failed: ", err) - } - k.waitDeployment(ctx, deployKeeperRegistryTx) - log.Println("KeeperRegistry1.1 deployed:", registryAddr.Hex(), "-", helpers.ExplorerLink(k.cfg.ChainID, deployKeeperRegistryTx.Hash())) - return registryAddr, registryInstance -} - // UpdateRegistry attaches to an existing registry and possibly updates registry config func (k *Keeper) UpdateRegistry(ctx context.Context) { var registryAddr common.Address switch k.cfg.RegistryVersion { - case keeper.RegistryVersion_1_1: - registryAddr, _ = k.getRegistry11(ctx) - case keeper.RegistryVersion_1_2: - registryAddr, _ = k.getRegistry12(ctx) - case keeper.RegistryVersion_2_0: + case config.RegistryVersion2_0: registryAddr, _ = k.getRegistry20(ctx) - case keeper.RegistryVersion_2_1: + case config.RegistryVersion2_1: registryAddr, _ = k.getRegistry21(ctx) default: panic("unexpected registry address") @@ -456,64 +380,6 @@ func (k *Keeper) getRegistry21(ctx context.Context) (common.Address, *iregistry2 return registryAddr, keeperRegistry21 } -// getRegistry12 attaches to an existing 1.2 registry and possibly updates registry config -func (k *Keeper) getRegistry12(ctx context.Context) (common.Address, *registry12.KeeperRegistry) { - registryAddr := common.HexToAddress(k.cfg.RegistryAddress) - keeperRegistry12, err := registry12.NewKeeperRegistry( - registryAddr, - k.client, - ) - if err != nil { - log.Fatal("Registry failed: ", err) - } - if k.cfg.RegistryConfigUpdate { - transaction, err := keeperRegistry12.SetConfig(k.buildTxOpts(ctx), *k.getConfigForRegistry12()) - if err != nil { - log.Fatal("Registry config update: ", err) - } - - if err := k.waitTx(ctx, transaction); err != nil { - log.Fatalf("KeeperRegistry config update failed on registry address: %s, error is: %s", k.cfg.RegistryAddress, err.Error()) - } - log.Println("KeeperRegistry config update:", k.cfg.RegistryAddress, "-", helpers.ExplorerLink(k.cfg.ChainID, transaction.Hash())) - } - log.Println("KeeperRegistry config not updated: KEEPER_CONFIG_UPDATE=false") - return registryAddr, keeperRegistry12 -} - -// getRegistry11 attaches to an existing 1.1 registry and possibly updates registry config -func (k *Keeper) getRegistry11(ctx context.Context) (common.Address, *registry11.KeeperRegistry) { - registryAddr := common.HexToAddress(k.cfg.RegistryAddress) - keeperRegistry11, err := registry11.NewKeeperRegistry( - registryAddr, - k.client, - ) - if err != nil { - log.Fatal("Registry failed: ", err) - } - if k.cfg.RegistryConfigUpdate { - transaction, err := keeperRegistry11.SetConfig(k.buildTxOpts(ctx), - k.cfg.PaymentPremiumPBB, - k.cfg.FlatFeeMicroLink, - big.NewInt(k.cfg.BlockCountPerTurn), - k.cfg.CheckGasLimit, - big.NewInt(k.cfg.StalenessSeconds), - k.cfg.GasCeilingMultiplier, - big.NewInt(k.cfg.FallbackGasPrice), - big.NewInt(k.cfg.FallbackLinkPrice)) - if err != nil { - log.Fatal("Registry config update: ", err) - } - - if err := k.waitTx(ctx, transaction); err != nil { - log.Fatalf("KeeperRegistry config update failed on registry address: %s, error is %s", k.cfg.RegistryAddress, err.Error()) - } - log.Println("KeeperRegistry config update:", k.cfg.RegistryAddress, "-", helpers.ExplorerLink(k.cfg.ChainID, transaction.Hash())) - } - log.Println("KeeperRegistry config not updated: KEEPER_CONFIG_UPDATE=false") - return registryAddr, keeperRegistry11 -} - // deployUpkeeps deploys upkeeps and funds upkeeps func (k *Keeper) deployUpkeeps(ctx context.Context, registryAddr common.Address, deployer upkeepDeployer, existingCount int64) { fmt.Println() @@ -654,19 +520,12 @@ func (k *Keeper) deployUpkeeps(ctx context.Context, registryAddr common.Address, { var err error switch k.cfg.RegistryVersion { - case keeper.RegistryVersion_1_1: - panic("not supported 1.1 registry") - case keeper.RegistryVersion_1_2: - upkeepGetter, err = registry12.NewKeeperRegistry( - registryAddr, - k.client, - ) - case keeper.RegistryVersion_2_0: + case config.RegistryVersion2_0: upkeepGetter, err = registry20.NewKeeperRegistry( registryAddr, k.client, ) - case keeper.RegistryVersion_2_1: + case config.RegistryVersion2_1: upkeepGetter, err = iregistry21.NewIKeeperRegistryMaster( registryAddr, k.client, @@ -702,7 +561,7 @@ func (k *Keeper) deployUpkeeps(ctx context.Context, registryAddr common.Address, } // set administrative offchain config for mercury upkeeps - if (k.cfg.UpkeepType == config.Mercury || k.cfg.UpkeepType == config.LogTriggeredFeedLookup) && k.cfg.RegistryVersion == keeper.RegistryVersion_2_1 { + if (k.cfg.UpkeepType == config.Mercury || k.cfg.UpkeepType == config.LogTriggeredFeedLookup) && k.cfg.RegistryVersion == config.RegistryVersion2_1 { reg21, err := iregistry21.NewIKeeperRegistryMaster(registryAddr, k.client) if err != nil { log.Fatalf("cannot create registry 2.1: %v", err) @@ -792,21 +651,3 @@ func (k *Keeper) getActiveUpkeepIds(ctx context.Context, registry activeUpkeepGe }, from, to) return activeUpkeepIds } - -// getConfigForRegistry12 returns a config object for registry 1.2 -func (k *Keeper) getConfigForRegistry12() *registry12.Config { - return ®istry12.Config{ - PaymentPremiumPPB: k.cfg.PaymentPremiumPBB, - FlatFeeMicroLink: k.cfg.FlatFeeMicroLink, - BlockCountPerTurn: big.NewInt(k.cfg.BlockCountPerTurn), - CheckGasLimit: k.cfg.CheckGasLimit, - StalenessSeconds: big.NewInt(k.cfg.StalenessSeconds), - GasCeilingMultiplier: k.cfg.GasCeilingMultiplier, - MinUpkeepSpend: big.NewInt(k.cfg.MinUpkeepSpend), - MaxPerformGas: k.cfg.MaxPerformGas, - FallbackGasPrice: big.NewInt(k.cfg.FallbackGasPrice), - FallbackLinkPrice: big.NewInt(k.cfg.FallbackLinkPrice), - Transcoder: common.HexToAddress(k.cfg.Transcoder), - Registrar: common.HexToAddress(k.cfg.Registrar), - } -} diff --git a/core/scripts/chaincli/handler/keeper_deployer.go b/core/scripts/chaincli/handler/keeper_deployer.go index 7b70f12f4a4..08cfe0c7692 100644 --- a/core/scripts/chaincli/handler/keeper_deployer.go +++ b/core/scripts/chaincli/handler/keeper_deployer.go @@ -26,8 +26,6 @@ import ( offchain20config "github.com/smartcontractkit/chainlink-automation/pkg/v2/config" iregistry21 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" - registry11 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_1" - registry12 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_2" registry20 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper2_0" "github.com/smartcontractkit/chainlink/v2/core/cmd" ) @@ -53,38 +51,6 @@ type keepersDeployer interface { SetKeepers(ctx context.Context, opts *bind.TransactOpts, _ []cmd.HTTPClient, keepers []common.Address, payees []common.Address) (*types.Transaction, error) } -type v11KeeperDeployer struct { - registry11.KeeperRegistryInterface -} - -func (d *v11KeeperDeployer) SetKeepers(ctx context.Context, opts *bind.TransactOpts, _ []cmd.HTTPClient, keepers []common.Address, payees []common.Address) (*types.Transaction, error) { - return d.KeeperRegistryInterface.SetKeepers(opts, keepers, payees) -} - -func (d *v11KeeperDeployer) RegisterUpkeep(opts *bind.TransactOpts, target common.Address, gasLimit uint32, admin common.Address, checkData []byte, offchainConfig []byte) (*types.Transaction, error) { - return d.KeeperRegistryInterface.RegisterUpkeep(opts, target, gasLimit, admin, checkData) -} - -func (d *v11KeeperDeployer) RegisterUpkeepV2(opts *bind.TransactOpts, target common.Address, gasLimit uint32, admin common.Address, triggerType uint8, pipelineData []byte, triggerConfig []byte, offchainConfig []byte) (*types.Transaction, error) { - panic("not implemented") -} - -type v12KeeperDeployer struct { - registry12.KeeperRegistryInterface -} - -func (d *v12KeeperDeployer) SetKeepers(ctx context.Context, opts *bind.TransactOpts, _ []cmd.HTTPClient, keepers []common.Address, payees []common.Address) (*types.Transaction, error) { - return d.KeeperRegistryInterface.SetKeepers(opts, keepers, payees) -} - -func (d *v12KeeperDeployer) RegisterUpkeep(opts *bind.TransactOpts, target common.Address, gasLimit uint32, admin common.Address, checkData []byte, offchainConfig []byte) (*types.Transaction, error) { - return d.KeeperRegistryInterface.RegisterUpkeep(opts, target, gasLimit, admin, checkData) -} - -func (d *v12KeeperDeployer) RegisterUpkeepV2(opts *bind.TransactOpts, target common.Address, gasLimit uint32, admin common.Address, triggerType uint8, pipelineData []byte, triggerConfig []byte, offchainConfig []byte) (*types.Transaction, error) { - panic("not implemented") -} - type v20KeeperDeployer struct { registry20.KeeperRegistryInterface cfg *config.Config diff --git a/core/scripts/chaincli/handler/keeper_launch.go b/core/scripts/chaincli/handler/keeper_launch.go index 51d928dcc0b..a44fc43cd5f 100644 --- a/core/scripts/chaincli/handler/keeper_launch.go +++ b/core/scripts/chaincli/handler/keeper_launch.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" "io" "log" @@ -16,7 +17,6 @@ import ( "syscall" "github.com/ethereum/go-ethereum/common" - ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/smartcontractkit/chainlink-common/keystore" @@ -24,12 +24,10 @@ import ( "github.com/smartcontractkit/chainlink-common/keystore/corekeys/ethkey" iregistry21 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" - registry12 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_2" registry20 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper2_0" + "github.com/smartcontractkit/chainlink/core/scripts/chaincli/config" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/keeper" - "github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs" "github.com/smartcontractkit/chainlink/v2/core/web" ) @@ -170,24 +168,7 @@ func (k *Keeper) LaunchAndTest(ctx context.Context, withdraw, printLogs, force, if withdraw { log.Println("Canceling upkeeps...") switch k.cfg.RegistryVersion { - case keeper.RegistryVersion_1_1: - if err := k.cancelAndWithdrawUpkeeps(ctx, big.NewInt(upkeepCount), deployer); err != nil { - log.Fatal("Failed to cancel upkeeps: ", err) - } - case keeper.RegistryVersion_1_2: - registry, err := registry12.NewKeeperRegistry( - registryAddr, - k.client, - ) - if err != nil { - log.Fatal("Registry failed: ", err) - } - - activeUpkeepIds := k.getActiveUpkeepIds(ctx, registry, big.NewInt(0), big.NewInt(0)) - if err := k.cancelAndWithdrawActiveUpkeeps(ctx, activeUpkeepIds, deployer); err != nil { - log.Fatal("Failed to cancel upkeeps: ", err) - } - case keeper.RegistryVersion_2_0: + case config.RegistryVersion2_0: registry, err := registry20.NewKeeperRegistry( registryAddr, k.client, @@ -200,7 +181,7 @@ func (k *Keeper) LaunchAndTest(ctx context.Context, withdraw, printLogs, force, if err := k.cancelAndWithdrawActiveUpkeeps(ctx, activeUpkeepIds, deployer); err != nil { log.Fatal("Failed to cancel upkeeps: ", err) } - case keeper.RegistryVersion_2_1: + case config.RegistryVersion2_1: registry, err := iregistry21.NewIKeeperRegistryMaster( registryAddr, k.client, @@ -219,7 +200,7 @@ func (k *Keeper) LaunchAndTest(ctx context.Context, withdraw, printLogs, force, } } -// cancelAndWithdrawActiveUpkeeps cancels all active upkeeps and withdraws funds for registry 1.2 +// cancelAndWithdrawActiveUpkeeps cancels all active upkeeps and withdraws funds via the registry canceller interface. func (k *Keeper) cancelAndWithdrawActiveUpkeeps(ctx context.Context, activeUpkeepIds []*big.Int, canceller canceller) error { for i := range activeUpkeepIds { upkeepId := activeUpkeepIds[i] @@ -256,88 +237,15 @@ func (k *Keeper) cancelAndWithdrawActiveUpkeeps(ctx context.Context, activeUpkee return nil } -// cancelAndWithdrawUpkeeps cancels all upkeeps for 1.1 registry and withdraws funds -func (k *Keeper) cancelAndWithdrawUpkeeps(ctx context.Context, upkeepCount *big.Int, canceller canceller) error { - var err error - for i := int64(0); i < upkeepCount.Int64(); i++ { - var tx *ethtypes.Transaction - if tx, err = canceller.CancelUpkeep(k.buildTxOpts(ctx), big.NewInt(i)); err != nil { - return fmt.Errorf("failed to cancel upkeep %d: %w", i, err) - } - - if err = k.waitTx(ctx, tx); err != nil { - log.Fatalf("failed to cancel upkeep, error is: %s", err.Error()) - } - - if tx, err = canceller.WithdrawFunds(k.buildTxOpts(ctx), big.NewInt(i), k.fromAddr); err != nil { - return fmt.Errorf("failed to withdraw upkeep %d: %w", i, err) - } - - if err = k.waitTx(ctx, tx); err != nil { - log.Fatalf("failed to withdraw upkeep, error is: %s", err.Error()) - } - - log.Println("Upkeep successfully canceled and refunded: ", i) - } - - var tx *ethtypes.Transaction - if tx, err = canceller.RecoverFunds(k.buildTxOpts(ctx)); err != nil { - return fmt.Errorf("failed to recover funds: %w", err) - } - - if err = k.waitTx(ctx, tx); err != nil { - log.Fatalf("failed to recover funds, error is: %s", err.Error()) - } - - return nil -} - // createKeeperJob creates a keeper job in the chainlink node by the given address func (k *Keeper) createKeeperJob(ctx context.Context, client cmd.HTTPClient, registryAddr, nodeAddr string) error { - var err error - if k.cfg.OCR2Keepers { - err = k.createOCR2KeeperJob(ctx, client, registryAddr, nodeAddr) - } else { - err = k.createLegacyKeeperJob(ctx, client, registryAddr, nodeAddr) + if !k.cfg.OCR2Keepers { + return errors.New("legacy keeper jobs are no longer supported; set KEEPER_OCR2=true and configure OCR2 automation") } - if err != nil { + if err := k.createOCR2KeeperJob(ctx, client, registryAddr, nodeAddr); err != nil { return err } - log.Println("Keeper job has been successfully created in the Chainlink node with address: ", nodeAddr) - - return nil -} - -// createLegacyKeeperJob creates a legacy keeper job in the chainlink node by the given address -func (k *Keeper) createLegacyKeeperJob(ctx context.Context, client cmd.HTTPClient, registryAddr, nodeAddr string) error { - request, err := json.Marshal(web.CreateJobRequest{ - TOML: testspecs.GenerateKeeperSpec(testspecs.KeeperSpecParams{ - Name: "keeper job - registry " + registryAddr, - ContractAddress: registryAddr, - FromAddress: nodeAddr, - EvmChainID: int(k.cfg.ChainID), - }).Toml(), - }) - if err != nil { - return fmt.Errorf("failed to marshal request: %w", err) - } - - resp, err := client.Post(ctx, "/v2/jobs", bytes.NewReader(request)) - if err != nil { - return fmt.Errorf("failed to create keeper job: %w", err) - } - defer resp.Body.Close() - - if resp.StatusCode >= 400 { - body, err := io.ReadAll(resp.Body) - if err != nil { - return fmt.Errorf("failed to read error response body: %w", err) - } - - return fmt.Errorf("unable to create keeper job: '%v' [%d]", string(body), resp.StatusCode) - } - return nil } @@ -373,7 +281,7 @@ func (k *Keeper) createOCR2KeeperJob(ctx context.Context, client cmd.HTTPClient, // Correctly assign contract version in OCR job spec. contractVersion := "v2.0" - if k.cfg.RegistryVersion == keeper.RegistryVersion_2_1 { + if k.cfg.RegistryVersion == config.RegistryVersion2_1 { contractVersion = "v2.1" } diff --git a/core/scripts/chaincli/handler/keeper_upkeep_history.go b/core/scripts/chaincli/handler/keeper_upkeep_history.go index 88293d46cad..c8665cba4f4 100644 --- a/core/scripts/chaincli/handler/keeper_upkeep_history.go +++ b/core/scripts/chaincli/handler/keeper_upkeep_history.go @@ -2,276 +2,13 @@ package handler import ( "context" - "encoding/hex" - "fmt" "log" "math/big" - "os" - "strings" - "text/tabwriter" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/rpc" - - registry11 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_1" - registry12 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_2" - "github.com/smartcontractkit/chainlink/v2/core/services/keeper" -) - -const ( - defaultMaxBlocksRange = 1000 - defaultLookBackRange = 1000 -) - -var ( - checkUpkeepArguments1 abi.Arguments - checkUpkeepArguments2 abi.Arguments - registry11ABI = keeper.Registry1_1ABI - registry12ABI = keeper.Registry1_2ABI ) -type result struct { - block uint64 - checkUpkeep bool - keeperIndex uint64 - keeperAddress common.Address - reason string - performData string - maxLinkPayment *big.Int - gasLimit *big.Int - adjustedGasWei *big.Int - linkEth *big.Int -} - -func init() { - checkUpkeepArguments1 = registry11ABI.Methods["checkUpkeep"].Outputs - checkUpkeepArguments2 = registry12ABI.Methods["checkUpkeep"].Outputs -} - -// UpkeepHistory prints the checkUpkeep status and keeper responsibility for a given upkeep in a set block range +// UpkeepHistory prints the checkUpkeep status and keeper responsibility for a given upkeep in a set block range. +// Legacy keeper registry 1.1/1.2 support has been removed. func (k *Keeper) UpkeepHistory(ctx context.Context, upkeepId *big.Int, from, to, gasPrice uint64) { - // There must not be a large different between boundaries - if to-from > defaultMaxBlocksRange { - log.Fatalf("blocks range difference must not more than %d", defaultMaxBlocksRange) - } - - var keeperRegistry11 *registry11.KeeperRegistry - var keeperRegistry12 *registry12.KeeperRegistry - // var keeperRegistry20 *registry20.KeeperRegistry - - switch k.cfg.RegistryVersion { - case keeper.RegistryVersion_1_1: - _, keeperRegistry11 = k.getRegistry11(ctx) - case keeper.RegistryVersion_1_2: - _, keeperRegistry12 = k.getRegistry12(ctx) - default: - panic("unsupported registry version") - } - - log.Println("Preparing a batch call request") - var reqs []rpc.BatchElem - var results []*string - var keeperPerBlockIndex []uint64 - var keeperPerBlockAddress []common.Address - for block := from; block <= to; block++ { - callOpts := &bind.CallOpts{ - Context: ctx, - BlockNumber: big.NewInt(0).SetUint64(block), - } - - var keepers []common.Address - var bcpt uint64 - var payload []byte - var keeperIndex uint64 - var lastKeeper common.Address - - switch k.cfg.RegistryVersion { - case keeper.RegistryVersion_1_1: - config, err2 := keeperRegistry11.GetConfig(callOpts) - if err2 != nil { - log.Fatal("failed to fetch registry config: ", err2) - } - - bcpt = config.BlockCountPerTurn.Uint64() - keepers, err2 = keeperRegistry11.GetKeeperList(callOpts) - if err2 != nil { - log.Fatal("failed to fetch keepers list: ", err2) - } - - upkeep, err2 := keeperRegistry11.GetUpkeep(callOpts, upkeepId) - if err2 != nil { - log.Fatal("failed to fetch the upkeep: ", err2) - } - lastKeeper = upkeep.LastKeeper - - case keeper.RegistryVersion_1_2: - state, err2 := keeperRegistry12.GetState(callOpts) - if err2 != nil { - log.Fatal("failed to fetch registry state: ", err2) - } - bcpt = state.Config.BlockCountPerTurn.Uint64() - keepers = state.Keepers - - upkeep, err2 := keeperRegistry12.GetUpkeep(callOpts, upkeepId) - if err2 != nil { - log.Fatal("failed to fetch the upkeep: ", err2) - } - lastKeeper = upkeep.LastKeeper - - default: - panic("unsupported registry version") - } - - turnBinary, err2 := turnBlockHashBinary(ctx, block, bcpt, defaultLookBackRange, k.client) - if err2 != nil { - log.Fatal("failed to calculate turn block hash: ", err2) - } - - // least significant 32 bits of upkeep id - lhs := keeper.LeastSignificant32(upkeepId) - - // least significant 32 bits of the turn block hash - turnBinaryPtr, ok := math.ParseBig256(string([]byte(turnBinary)[len(turnBinary)-32:])) - if !ok { - log.Fatal("failed to parse turn binary ", turnBinary) - } - rhs := keeper.LeastSignificant32(turnBinaryPtr) - - // bitwise XOR - turn := lhs ^ rhs - - keepersCnt := uint64(len(keepers)) - keeperIndex = turn % keepersCnt - if keepers[keeperIndex] == lastKeeper { - keeperIndex = (keeperIndex + keepersCnt - 1) % keepersCnt - } - - switch k.cfg.RegistryVersion { - case keeper.RegistryVersion_1_1: - payload, err2 = registry11ABI.Pack("checkUpkeep", upkeepId, keepers[keeperIndex]) - if err2 != nil { - log.Fatal("failed to pack checkUpkeep: ", err2) - } - case keeper.RegistryVersion_1_2: - payload, err2 = registry12ABI.Pack("checkUpkeep", upkeepId, keepers[keeperIndex]) - if err2 != nil { - log.Fatal("failed to pack checkUpkeep: ", err2) - } - default: - panic("unsupported registry version") - } - - args := map[string]any{ - "to": k.cfg.RegistryAddress, - "data": hexutil.Bytes(payload), - } - if gasPrice > 0 { - args["gasPrice"] = hexutil.EncodeUint64(gasPrice) - } - - var res string - reqs = append(reqs, rpc.BatchElem{ - Method: "eth_call", - Args: []any{ - args, - // The block at which we want to inspect the upkeep state - hexutil.EncodeUint64(block), - }, - Result: &res, - }) - - results = append(results, &res) - keeperPerBlockIndex = append(keeperPerBlockIndex, keeperIndex) - keeperPerBlockAddress = append(keeperPerBlockAddress, keepers[keeperIndex]) - } - - k.batchProcess(ctx, reqs, from, keeperPerBlockIndex, keeperPerBlockAddress, results) -} - -func (k *Keeper) batchProcess(ctx context.Context, reqs []rpc.BatchElem, from uint64, keeperPerBlockIndex []uint64, keeperPerBlockAddress []common.Address, results []*string) { - log.Println("Doing batch call to check upkeeps") - if err := k.rpcClient.BatchCallContext(ctx, reqs); err != nil { - log.Fatal("failed to batch call checkUpkeep: ", err) - } - - log.Println("Parsing batch call response") - var parsedResults []result - isVersion12 := k.cfg.RegistryVersion == keeper.RegistryVersion_1_2 - for i, req := range reqs { - if req.Error != nil { - parsedResults = append(parsedResults, result{ - block: uint64(i) + from, - checkUpkeep: false, - keeperIndex: keeperPerBlockIndex[i], - keeperAddress: keeperPerBlockAddress[i], - reason: strings.TrimPrefix(req.Error.Error(), "execution reverted: "), - }) - continue - } - - var returnValues []any - var err error - if isVersion12 { - returnValues, err = checkUpkeepArguments2.UnpackValues(hexutil.MustDecode(*results[i])) - } else { - returnValues, err = checkUpkeepArguments1.UnpackValues(hexutil.MustDecode(*results[i])) - } - if err != nil { - log.Fatal("unpack checkUpkeep return: ", err, *results[i]) - } - - parsedResults = append(parsedResults, result{ - block: uint64(i) + from, - checkUpkeep: true, - keeperIndex: keeperPerBlockIndex[i], - keeperAddress: keeperPerBlockAddress[i], - performData: "0x" + hex.EncodeToString(*abi.ConvertType(returnValues[0], new([]byte)).(*[]byte)), - maxLinkPayment: *abi.ConvertType(returnValues[1], new(*big.Int)).(**big.Int), - gasLimit: *abi.ConvertType(returnValues[2], new(*big.Int)).(**big.Int), - adjustedGasWei: *abi.ConvertType(returnValues[3], new(*big.Int)).(**big.Int), - linkEth: *abi.ConvertType(returnValues[4], new(*big.Int)).(**big.Int), - }) - } - - printResultsToConsole(parsedResults) -} - -// printResultsToConsole writes parsed results to the console -func printResultsToConsole(parsedResults []result) { - writer := tabwriter.NewWriter(os.Stdout, 8, 8, 0, '\t', 0) - defer writer.Flush() - - fmt.Fprintf(writer, "\n %s\t\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t", "Block", "checkUpkeep", "Keeper Index", "Keeper Address", "Max LINK Payment", "Gas Limit", "Adjusted Gas", "LINK ETH", "Perform Data", "Reason") - fmt.Fprintf(writer, "\n %s\t\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t", "----", "----", "----", "----", "----", "----", "----", "----", "----", "----") - for _, res := range parsedResults { - fmt.Fprintf(writer, "\n %d\t\t%t\t%d\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t", - res.block, - res.checkUpkeep, - res.keeperIndex, - res.keeperAddress, - res.maxLinkPayment, - res.gasLimit, - res.adjustedGasWei, - res.linkEth, - res.performData, - res.reason, - ) - } - fmt.Fprintf(writer, "\n %s\t\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n", "----", "----", "----", "----", "----", "----", "----", "----", "----", "----") -} - -func turnBlockHashBinary(ctx context.Context, blockNum, bcpt, lookback uint64, ethClient *ethclient.Client) (string, error) { - turnBlock := blockNum - (blockNum % bcpt) - lookback - block, err := ethClient.BlockByNumber(ctx, big.NewInt(int64(turnBlock))) - if err != nil { - return "", err - } - hashAtHeight := block.Hash() - binaryString := fmt.Sprintf("%b", hashAtHeight.Big()) - return binaryString, nil + _, _, _, _, _ = ctx, upkeepId, from, to, gasPrice + log.Fatal("upkeep-history was only implemented for keeper registry 1.1/1.2, which are no longer supported") } diff --git a/core/scripts/chaincli/handler/keeper_withdraw.go b/core/scripts/chaincli/handler/keeper_withdraw.go index e3321a83426..151acd7a5ba 100644 --- a/core/scripts/chaincli/handler/keeper_withdraw.go +++ b/core/scripts/chaincli/handler/keeper_withdraw.go @@ -5,54 +5,18 @@ import ( "log" "math/big" - registry20 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper2_0" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - registry11 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_1" - registry12 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_2" - "github.com/smartcontractkit/chainlink/v2/core/services/keeper" + registry20 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper2_0" + + "github.com/smartcontractkit/chainlink/core/scripts/chaincli/config" ) // Withdraw takes a keeper registry address, cancels all upkeeps and withdraws the funds func (k *Keeper) Withdraw(ctx context.Context, hexAddr string) { registryAddr := common.HexToAddress(hexAddr) switch k.cfg.RegistryVersion { - case keeper.RegistryVersion_1_1: - keeperRegistry11, err := registry11.NewKeeperRegistry( - registryAddr, - k.client, - ) - if err != nil { - log.Fatal("Registry failed: ", err) - } - - upkeepCount, err := keeperRegistry11.GetUpkeepCount(&bind.CallOpts{Context: ctx}) - if err != nil { - log.Fatal("failed to get upkeeps count: ", err) - } - - log.Println("Canceling upkeeps...") - if err = k.cancelAndWithdrawUpkeeps(ctx, upkeepCount, keeperRegistry11); err != nil { - log.Fatal("Failed to cancel upkeeps: ", err) - } - case keeper.RegistryVersion_1_2: - keeperRegistry12, err := registry12.NewKeeperRegistry( - registryAddr, - k.client, - ) - if err != nil { - log.Fatal("Registry failed: ", err) - } - - activeUpkeepIds := k.getActiveUpkeepIds(ctx, keeperRegistry12, big.NewInt(0), big.NewInt(0)) - - log.Println("Canceling upkeeps...") - if err = k.cancelAndWithdrawActiveUpkeeps(ctx, activeUpkeepIds, keeperRegistry12); err != nil { - log.Fatal("Failed to cancel upkeeps: ", err) - } - case keeper.RegistryVersion_2_0: + case config.RegistryVersion2_0: keeperRegistry20, err := registry20.NewKeeperRegistry( registryAddr, k.client, diff --git a/core/scripts/chaincli/handler/upkeep_util.go b/core/scripts/chaincli/handler/upkeep_util.go new file mode 100644 index 00000000000..39e190e0eaf --- /dev/null +++ b/core/scripts/chaincli/handler/upkeep_util.go @@ -0,0 +1,33 @@ +package handler + +import ( + "math" + "math/big" + "strings" + + ethmath "github.com/ethereum/go-ethereum/common/math" +) + +const ( + zeroPrefix = "0x" + upkeepPrefix = "UPx" +) + +// LeastSignificant32 returns the least significant 32 bits of the input as a uint64. +func LeastSignificant32(num *big.Int) uint64 { + max32 := big.NewInt(math.MaxUint32) + return big.NewInt(0).And(num, max32).Uint64() +} + +// ParseUpkeepID parses the upkeep id input string to a big int pointer. +func ParseUpkeepID(upkeepIDStr string) (*big.Int, bool) { + if strings.HasPrefix(upkeepIDStr, upkeepPrefix) { + upkeepIDStr = zeroPrefix + upkeepIDStr[len(upkeepPrefix):] + } + + upkeepID, ok := ethmath.ParseBig256(upkeepIDStr) + if !ok { + return ethmath.ParseBig256(zeroPrefix + upkeepIDStr) + } + return upkeepID, ok +} diff --git a/core/scripts/go.mod b/core/scripts/go.mod index e4a0486e2ce..e15cb58e8df 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -45,12 +45,12 @@ require ( github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chain-selectors v1.0.98 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260415165642-49f23e4d76cc + github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260428205619-2db1389501a1 github.com/smartcontractkit/chainlink-common v0.11.2-0.20260428192532-b1f4aebef94a github.com/smartcontractkit/chainlink-common/keystore v1.1.0 github.com/smartcontractkit/chainlink-data-streams v0.1.13 github.com/smartcontractkit/chainlink-deployments-framework v0.98.0 - github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260428180431-40447a80e681 + github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429123911-44d13c62c6e1 github.com/smartcontractkit/chainlink-evm/gethwrappers v0.0.0-20260421142741-9c7fbaf7c828 github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260420204255-a3f3bdd56877 github.com/smartcontractkit/chainlink-protos/job-distributor v0.18.0 @@ -488,11 +488,11 @@ require ( github.com/smartcontractkit/ccip-contract-examples/chains/evm v0.0.0-20260129135848-c86808ba5cb9 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect github.com/smartcontractkit/chainlink-aptos v0.0.0-20260424112027-f932111b88ac // indirect - github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260423164805-f44aeafa2aaa // indirect + github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260428205619-2db1389501a1 // indirect github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm v0.0.0-20260408145530-22e2d05695cd // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260415165642-49f23e4d76cc // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260415165642-49f23e4d76cc // indirect - github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260415165642-49f23e4d76cc // indirect + github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260428205619-2db1389501a1 // indirect github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260428133800-3b1484e8b1fd // indirect github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20251211140724-319861e514c4 // indirect github.com/smartcontractkit/chainlink-evm/contracts/cre/gobindings v0.0.0-20260403151002-2c91155b5501 // indirect @@ -512,9 +512,9 @@ require ( github.com/smartcontractkit/chainlink-protos/ring/go v0.0.0-20260331131315-f08a616d8dcd // indirect github.com/smartcontractkit/chainlink-protos/rmn/v1.6/go v0.0.0-20250131130834-15e0d4cde2a6 // indirect github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0 // indirect - github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3 // indirect + github.com/smartcontractkit/chainlink-protos/svr v1.2.0 // indirect github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428015924-9456bb6d8932 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428170719-7ad4e58aaacf // indirect github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c // indirect github.com/smartcontractkit/chainlink-sui v0.0.0-20260427132612-76b9f754a556 // indirect github.com/smartcontractkit/chainlink-sui/deployment v0.0.0-20260427132612-76b9f754a556 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index e70cc7a0db5..9c94c5b0db0 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1639,18 +1639,18 @@ github.com/smartcontractkit/chainlink-aptos v0.0.0-20260424112027-f932111b88ac h github.com/smartcontractkit/chainlink-aptos v0.0.0-20260424112027-f932111b88ac/go.mod h1:ZU57FhGIb+m20yysn2fw+vLh3qB5hcgd06RXEUEDBck= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260423164805-f44aeafa2aaa h1:GE4B480m+/OMgkmZ9mEI1Abh927N7oW+Ruq9uuKIFQw= -github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260423164805-f44aeafa2aaa/go.mod h1:1XxxpkgCmG/z6y30yRuVrcxre6zixIVX3xzi706Db/8= +github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260428205619-2db1389501a1 h1:p0nFrTYrOQzDhWYm6suaM5CoWiXV5NV7llHnp6/Kn/8= +github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260428205619-2db1389501a1/go.mod h1:1XxxpkgCmG/z6y30yRuVrcxre6zixIVX3xzi706Db/8= github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm v0.0.0-20260408145530-22e2d05695cd h1:Jtw6p5iisjXZyFOcBvWh6PDQKtvryrRU2JMmezdutjo= github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm v0.0.0-20260408145530-22e2d05695cd/go.mod h1:zLqdD2kBX7NsntBneclb2yrHhjFaJdoyA8dK5eimlrE= -github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260415165642-49f23e4d76cc h1:dP1ERzdTbiJbHVXfHYdBAi1+8NjgkyQuY2oFNWWWDsQ= -github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:7XR5wfgT8hjSsiV+t0EAWvna+rYQeMPaoZf/0g+dios= +github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260428205619-2db1389501a1 h1:wfiut4oWMcpJmTEl/1ShwMBxwTQEv0wV4/YTma9Otxk= +github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260428205619-2db1389501a1/go.mod h1:hrNuLHgDa2f47WVO6+KgSxM1/SI1M8npQnaiv4kw3xo= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260415165642-49f23e4d76cc h1:mvobZx5JV5PhG/9IXPReV+8mAGnupl0HIWQZ43zxzd4= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:gzCVLUlNov/zFXSC7G6zcGkZU1IfNOHaakbAPDe5Woc= github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260415165642-49f23e4d76cc h1:War93neyFmv7pzuElZeZC3qc/OfGtLvEXvqL3qeBfM0= github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:67YbnoglYD61Pz/jTVCgav9wFq7S35OU8UyQSvPllRw= -github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260415165642-49f23e4d76cc h1:entc0pB4VQEkhJf/ymOfnUh6zcu1sj1OU4YW3iPEW4s= -github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:Ex2OUp35VJuCcRAjuBKwP+cevEPOSjy1pZXm3ncV4kQ= +github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260428205619-2db1389501a1 h1:TEdRdqbGFizjLKI16HiETpzUwyxSYhsJGX+NPk9Tv+o= +github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260428205619-2db1389501a1/go.mod h1:1rndR7UVFakZ6kMWZm1Vs6fFtrroJ4tny66U90fH6FE= github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260428133800-3b1484e8b1fd h1:IMopuENFVS63AerRELdfWo6o60UNUidcldJOxJLmk24= github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260428133800-3b1484e8b1fd/go.mod h1:SBN8Urnh5sQvrQRbSo1Nr8coWatHg8LZoPw3R/42sho= github.com/smartcontractkit/chainlink-common v0.11.2-0.20260428192532-b1f4aebef94a h1:uuJRUD/MHY2hX/f8k8MteJo9jA1+/8KLOCeJOCRSblg= @@ -1665,8 +1665,8 @@ github.com/smartcontractkit/chainlink-data-streams v0.1.13 h1:YOmt545DW6U0SyaqBf github.com/smartcontractkit/chainlink-data-streams v0.1.13/go.mod h1:00aL7OK0BJdF9gn/4t4f/pctUu2VLwwfA8G/tl9rCrM= github.com/smartcontractkit/chainlink-deployments-framework v0.98.0 h1:Ov/KOEtubOHXX8oa9UtARhHmkQNCOIjWNt+Zi0AuzHM= github.com/smartcontractkit/chainlink-deployments-framework v0.98.0/go.mod h1:24dwRW1PYolrlxSth///ddG3auGqR+50xaJiXfUHhkg= -github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260428180431-40447a80e681 h1:ehv4ucho8t5/E/Xg3u7qomdC4gB6IkSHlZx2ZrySaH8= -github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260428180431-40447a80e681/go.mod h1:eOx+FhknhG1+K/pKN77IR/UKmU3WDVaGci64VCGlCUc= +github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429123911-44d13c62c6e1 h1:7H7hiN8Q/bHvsprmA8OqiELGkJmMHYc+MTTOCDKIzm8= +github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429123911-44d13c62c6e1/go.mod h1:lhxIJe+Qy8duvf20q4D8ewfJzwHfvxK/s4s0exG1zEQ= github.com/smartcontractkit/chainlink-evm/contracts/cre/gobindings v0.0.0-20260403151002-2c91155b5501 h1:QJiXTG9CmaQAuMRn5JGi+Jhji7fSkehVnKpjc8oNJJY= github.com/smartcontractkit/chainlink-evm/contracts/cre/gobindings v0.0.0-20260403151002-2c91155b5501/go.mod h1:4cT1BeNF8DAn6In9zr3LayVCv1KzFeuxT7zcuNkfIb0= github.com/smartcontractkit/chainlink-evm/gethwrappers v0.0.0-20260421142741-9c7fbaf7c828 h1:BmsFk/TSHL6dPPR86GTqgSrUXLSINNFC6cfpFRrQX+4= @@ -1709,12 +1709,12 @@ github.com/smartcontractkit/chainlink-protos/rmn/v1.6/go v0.0.0-20250131130834-1 github.com/smartcontractkit/chainlink-protos/rmn/v1.6/go v0.0.0-20250131130834-15e0d4cde2a6/go.mod h1:FRwzI3hGj4CJclNS733gfcffmqQ62ONCkbGi49s658w= github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0 h1:B7itmjy+CMJ26elVw/cAJqqhBQ3Xa/mBYWK0/rQ5MuI= github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0/go.mod h1:h6kqaGajbNRrezm56zhx03p0mVmmA2xxj7E/M4ytLUA= -github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3 h1:X8Pekpv+cy0eW1laZTwATuYLTLZ6gRTxz1ZWOMtU74o= -github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= +github.com/smartcontractkit/chainlink-protos/svr v1.2.0 h1:7jjgqRgORQS/ikL3z0ZgJy95pzjhR9LuU1TVWg4BZ78= +github.com/smartcontractkit/chainlink-protos/svr v1.2.0/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997 h1:W0HKHO8eE8BckTRnhSdqjHKbJcnk068nEWYnWRu6tJY= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997/go.mod h1:GTpDgyK0OObf7jpch6p8N281KxN92wbB8serZhU9yRc= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428015924-9456bb6d8932 h1:aD5KjYqbHiL6OJl3f8tsopVkkAG68UsRJCKjDIACO6w= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428015924-9456bb6d8932/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428170719-7ad4e58aaacf h1:GyBD65Cc4HuwRKZ6k4UCtFaG7njGTnZyR+z3VPm3Vyo= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428170719-7ad4e58aaacf/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c h1:Hn/80PyYFrQhRlNSaq9HY4cjc/7AuP9zyWLle22t34A= github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c/go.mod h1:C5pZsbYX3qkhZTYWr1aYJi9QMfonFAun+Jl1npQ7UJA= github.com/smartcontractkit/chainlink-sui v0.0.0-20260427132612-76b9f754a556 h1:Nz70a+A7aNnWRYdLpGdUf8NeauMvZFOBEPfZTm8vxwI= diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index b9f70144d12..7220df1deb7 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -67,7 +67,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/gateway" "github.com/smartcontractkit/chainlink/v2/core/services/headreporter" "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/keeper" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/llo/retirement" "github.com/smartcontractkit/chainlink/v2/core/services/nodestatusreporter/bridgestatus" @@ -327,11 +326,7 @@ func NewApplication(ctx context.Context, opts ApplicationOpts) (Application, err initOps = append(initOps, InitCosmos(relayerFactory, keyStore.Cosmos(), keyStore.CSA(), cfg.CosmosConfigs())) } if cfg.SolanaEnabled() { - solanaCfg := SolanaFactoryConfig{ - TOMLConfigs: cfg.SolanaConfigs(), - DS: opts.DS, - } - initOps = append(initOps, InitSolana(relayerFactory, keyStore.Solana(), keyStore.CSA(), solanaCfg)) + initOps = append(initOps, InitSolana(relayerFactory, keyStore.Solana(), keyStore.CSA(), cfg.SolanaConfigs())) } if cfg.StarkNetEnabled() { initOps = append(initOps, InitStarknet(relayerFactory, keyStore.StarkNet(), keyStore.CSA(), cfg.StarknetConfigs())) @@ -564,14 +559,6 @@ func NewApplication(ctx context.Context, opts ApplicationOpts) (Application, err pipelineORM, legacyEVMChains, mailMon), - job.Keeper: keeper.NewDelegate( - cfg, - opts.DS, - jobORM, - pipelineRunner, - globalLogger, - legacyEVMChains, - mailMon), job.VRF: vrf.NewDelegate( opts.DS, keyStore, diff --git a/core/services/chainlink/config.go b/core/services/chainlink/config.go index 160beb95e30..e65da56a227 100644 --- a/core/services/chainlink/config.go +++ b/core/services/chainlink/config.go @@ -10,7 +10,6 @@ import ( gotoml "github.com/pelletier/go-toml/v2" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" configtoml "github.com/smartcontractkit/chainlink-evm/pkg/config/toml" "github.com/smartcontractkit/chainlink/v2/core/config/docs" @@ -37,7 +36,7 @@ type Config struct { Cosmos RawConfigs `toml:",omitempty"` - Solana solcfg.TOMLConfigs `toml:",omitempty"` + Solana RawConfigs `toml:",omitempty"` Starknet RawConfigs `toml:",omitempty"` @@ -334,12 +333,7 @@ func (c *Config) setDefaults() { c.Cosmos.SetDefaults() - for i := range c.Solana { - if c.Solana[i] == nil { - c.Solana[i] = new(solcfg.TOMLConfig) - } - c.Solana[i].SetDefaults() - } + c.Solana.SetDefaults() c.Starknet.SetDefaults() @@ -361,7 +355,7 @@ func (c *Config) SetFrom(f *Config) (err error) { appendErr(c.EVM.SetFrom(&f.EVM), "EVM") appendErr(c.Cosmos.SetFrom(f.Cosmos), "Cosmos") - appendErr(c.Solana.SetFrom(&f.Solana), "Solana") + appendErr(c.Solana.SetFrom(f.Solana), "Solana") appendErr(c.Starknet.SetFrom(f.Starknet), "Starknet") appendErr(c.Aptos.SetFrom(f.Aptos), "Aptos") appendErr(c.Tron.SetFrom(f.Tron), "Tron") diff --git a/core/services/chainlink/config_general.go b/core/services/chainlink/config_general.go index ed18c6ca7a0..3eb77367607 100644 --- a/core/services/chainlink/config_general.go +++ b/core/services/chainlink/config_general.go @@ -15,7 +15,6 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" evmcfg "github.com/smartcontractkit/chainlink-evm/pkg/config/toml" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" "github.com/smartcontractkit/chainlink-common/keystore/corekeys" "github.com/smartcontractkit/chainlink-common/keystore/corekeys/p2pkey" @@ -202,7 +201,7 @@ func (g *generalConfig) CosmosConfigs() RawConfigs { return g.c.Cosmos } -func (g *generalConfig) SolanaConfigs() solcfg.TOMLConfigs { +func (g *generalConfig) SolanaConfigs() RawConfigs { return g.c.Solana } @@ -470,10 +469,6 @@ func (g *generalConfig) JobPipeline() coreconfig.JobPipeline { return &jobPipelineConfig{c: g.c.JobPipeline} } -func (g *generalConfig) Keeper() config.Keeper { - return &keeperConfig{c: g.c.Keeper} -} - func (g *generalConfig) Log() config.Log { return &logConfig{c: g.c.Log, rootDir: g.RootDir, level: g.logLevel, defaultLevel: g.logLevelDefault} } diff --git a/core/services/chainlink/config_keeper.go b/core/services/chainlink/config_keeper.go deleted file mode 100644 index e56de0a69d1..00000000000 --- a/core/services/chainlink/config_keeper.go +++ /dev/null @@ -1,66 +0,0 @@ -package chainlink - -import ( - "time" - - "github.com/smartcontractkit/chainlink/v2/core/config" - "github.com/smartcontractkit/chainlink/v2/core/config/toml" -) - -var _ config.Keeper = (*keeperConfig)(nil) - -type registryConfig struct { - c toml.KeeperRegistry -} - -func (r *registryConfig) CheckGasOverhead() uint32 { - return *r.c.CheckGasOverhead -} - -func (r *registryConfig) PerformGasOverhead() uint32 { - return *r.c.PerformGasOverhead -} - -func (r *registryConfig) MaxPerformDataSize() uint32 { - return *r.c.MaxPerformDataSize -} - -func (r *registryConfig) SyncInterval() time.Duration { - return r.c.SyncInterval.Duration() -} - -func (r *registryConfig) SyncUpkeepQueueSize() uint32 { - return *r.c.SyncUpkeepQueueSize -} - -type keeperConfig struct { - c toml.Keeper -} - -func (k *keeperConfig) Registry() config.Registry { - return ®istryConfig{c: k.c.Registry} -} - -func (k *keeperConfig) DefaultTransactionQueueDepth() uint32 { - return *k.c.DefaultTransactionQueueDepth -} - -func (k *keeperConfig) GasPriceBufferPercent() uint16 { - return *k.c.GasPriceBufferPercent -} - -func (k *keeperConfig) GasTipCapBufferPercent() uint16 { - return *k.c.GasTipCapBufferPercent -} - -func (k *keeperConfig) BaseFeeBufferPercent() uint16 { - return *k.c.BaseFeeBufferPercent -} - -func (k *keeperConfig) MaxGracePeriod() int64 { - return *k.c.MaxGracePeriod -} - -func (k *keeperConfig) TurnLookBack() int64 { - return *k.c.TurnLookBack -} diff --git a/core/services/chainlink/config_keeper_test.go b/core/services/chainlink/config_keeper_test.go deleted file mode 100644 index 7fd571c8880..00000000000 --- a/core/services/chainlink/config_keeper_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package chainlink - -import ( - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestKeeperConfig(t *testing.T) { - opts := GeneralConfigOpts{ - ConfigStrings: []string{fullTOML}, - } - cfg, err := opts.New() - require.NoError(t, err) - - keeper := cfg.Keeper() - - assert.Equal(t, uint32(17), keeper.DefaultTransactionQueueDepth()) - assert.Equal(t, uint16(12), keeper.GasPriceBufferPercent()) - assert.Equal(t, uint16(43), keeper.GasTipCapBufferPercent()) - assert.Equal(t, uint16(89), keeper.BaseFeeBufferPercent()) - assert.Equal(t, int64(91), keeper.TurnLookBack()) - assert.Equal(t, int64(31), keeper.MaxGracePeriod()) - - registry := keeper.Registry() - assert.Equal(t, uint32(90), registry.CheckGasOverhead()) - assert.Equal(t, uint32(4294967295), registry.PerformGasOverhead()) - assert.Equal(t, uint32(5000), registry.MaxPerformDataSize()) - assert.Equal(t, 1*time.Hour, registry.SyncInterval()) - assert.Equal(t, uint32(31), registry.SyncUpkeepQueueSize()) -} diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index d0e668897b9..e15be99bcb2 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -9,7 +9,6 @@ import ( "testing" "time" - "github.com/gagliardetto/solana-go" "github.com/kylelemons/godebug/diff" "github.com/shopspring/decimal" "github.com/stretchr/testify/assert" @@ -25,8 +24,6 @@ import ( commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" "github.com/smartcontractkit/chainlink-framework/multinode" - mnCfg "github.com/smartcontractkit/chainlink-framework/multinode/config" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" "github.com/smartcontractkit/chainlink-evm/pkg/assets" "github.com/smartcontractkit/chainlink-evm/pkg/config/chaintype" @@ -95,9 +92,6 @@ var ( P2P: toml.P2P{ IncomingMessageBufferSize: ptr[int64](999), }, - Keeper: toml.Keeper{ - GasPriceBufferPercent: ptr[uint16](10), - }, AutoPprof: toml.AutoPprof{ CPUProfileRate: ptr[int64](7), }, @@ -156,68 +150,6 @@ var ( }, }}, }, - Solana: []*solcfg.TOMLConfig{ - { - ChainID: ptr("mainnet"), - Chain: solcfg.Chain{ - MaxRetries: ptr[int64](12), - }, - MultiNode: mnCfg.MultiNodeConfig{ - MultiNode: mnCfg.MultiNode{ - Enabled: ptr(false), - PollFailureThreshold: ptr[uint32](5), - PollInterval: &second, - SelectionMode: &selectionMode, - SyncThreshold: ptr[uint32](5), - NodeIsSyncingEnabled: ptr(false), - LeaseDuration: &minute, - NewHeadsPollInterval: &second, - FinalizedBlockPollInterval: &second, - EnforceRepeatableRead: ptr(true), - DeathDeclarationDelay: &minute, - VerifyChainID: ptr(true), - NodeNoNewHeadsThreshold: &minute, - NoNewFinalizedHeadsThreshold: &minute, - FinalityDepth: ptr[uint32](0), - FinalityTagEnabled: ptr(true), - FinalizedBlockOffset: ptr[uint32](0), - }, - }, - Nodes: []*solcfg.Node{ - {Name: ptr("primary"), URL: commoncfg.MustParseURL("http://mainnet.solana.com"), Order: ptr(int32(1))}, - }, - }, - { - ChainID: ptr("testnet"), - Chain: solcfg.Chain{ - OCR2CachePollPeriod: commoncfg.MustNewDuration(time.Minute), - }, - MultiNode: mnCfg.MultiNodeConfig{ - MultiNode: mnCfg.MultiNode{ - Enabled: ptr(false), - PollFailureThreshold: ptr[uint32](5), - PollInterval: &second, - SelectionMode: &selectionMode, - SyncThreshold: ptr[uint32](5), - NodeIsSyncingEnabled: ptr(false), - LeaseDuration: &minute, - NewHeadsPollInterval: &second, - FinalizedBlockPollInterval: &second, - EnforceRepeatableRead: ptr(true), - DeathDeclarationDelay: &minute, - VerifyChainID: ptr(true), - NodeNoNewHeadsThreshold: &minute, - NoNewFinalizedHeadsThreshold: &minute, - FinalityDepth: ptr[uint32](0), - FinalityTagEnabled: ptr(true), - FinalizedBlockOffset: ptr[uint32](0), - }, - }, - Nodes: []*solcfg.Node{ - {Name: ptr("secondary"), URL: commoncfg.MustParseURL("http://testnet.solana.com"), Order: ptr(int32(2))}, - }, - }, - }, } ) @@ -587,21 +519,6 @@ func TestConfig_Marshal(t *testing.T) { PerOwner: ptr(int32(200)), }, } - full.Keeper = toml.Keeper{ - DefaultTransactionQueueDepth: ptr[uint32](17), - GasPriceBufferPercent: ptr[uint16](12), - GasTipCapBufferPercent: ptr[uint16](43), - BaseFeeBufferPercent: ptr[uint16](89), - MaxGracePeriod: ptr[int64](31), - TurnLookBack: ptr[int64](91), - Registry: toml.KeeperRegistry{ - CheckGasOverhead: ptr[uint32](90), - PerformGasOverhead: ptr[uint32](math.MaxUint32), - SyncInterval: commoncfg.MustNewDuration(time.Hour), - SyncUpkeepQueueSize: ptr[uint32](31), - MaxPerformDataSize: ptr[uint32](5000), - }, - } full.AutoPprof = toml.AutoPprof{ Enabled: ptr(true), ProfileRoot: ptr("prof/root"), @@ -880,76 +797,6 @@ func TestConfig_Marshal(t *testing.T) { }, }}, } - full.Solana = []*solcfg.TOMLConfig{ - { - ChainID: ptr("mainnet"), - Enabled: ptr(false), - Chain: solcfg.Chain{ - BlockTime: commoncfg.MustNewDuration(500 * time.Millisecond), - BalancePollPeriod: commoncfg.MustNewDuration(time.Minute), - ConfirmPollPeriod: commoncfg.MustNewDuration(time.Second), - OCR2CachePollPeriod: commoncfg.MustNewDuration(time.Minute), - OCR2CacheTTL: commoncfg.MustNewDuration(time.Hour), - TxTimeout: commoncfg.MustNewDuration(time.Hour), - TxRetryTimeout: commoncfg.MustNewDuration(time.Minute), - TxConfirmTimeout: commoncfg.MustNewDuration(time.Second), - TxExpirationRebroadcast: ptr(false), - TxRetentionTimeout: commoncfg.MustNewDuration(0 * time.Second), - SkipPreflight: ptr(true), - Commitment: ptr("banana"), - MaxRetries: ptr[int64](7), - FeeEstimatorMode: ptr("fixed"), - ComputeUnitPriceMax: ptr[uint64](1000), - ComputeUnitPriceMin: ptr[uint64](10), - ComputeUnitPriceDefault: ptr[uint64](100), - FeeBumpPeriod: commoncfg.MustNewDuration(time.Minute), - BlockHistoryPollPeriod: commoncfg.MustNewDuration(time.Minute), - BlockHistorySize: ptr[uint64](1), - BlockHistoryBatchLoadSize: ptr[uint64](20), - ComputeUnitLimitDefault: ptr[uint32](100_000), - EstimateComputeUnitLimit: ptr(false), - LogPollerStartingLookback: commoncfg.MustNewDuration(24 * time.Hour), - LogPollerCPIEventsEnabled: ptr(true), - LogPollerSlotsBatchSize: ptr[int64](100), - }, - MultiNode: mnCfg.MultiNodeConfig{ - MultiNode: mnCfg.MultiNode{ - Enabled: ptr(false), - PollFailureThreshold: ptr[uint32](5), - PollInterval: &second, - SelectionMode: &selectionMode, - SyncThreshold: ptr[uint32](5), - NodeIsSyncingEnabled: ptr(false), - LeaseDuration: &minute, - NewHeadsPollInterval: &second, - FinalizedBlockPollInterval: &second, - EnforceRepeatableRead: ptr(true), - DeathDeclarationDelay: &minute, - VerifyChainID: ptr(true), - NodeNoNewHeadsThreshold: &minute, - NoNewFinalizedHeadsThreshold: &minute, - FinalityDepth: ptr[uint32](0), - FinalityTagEnabled: ptr(true), - FinalizedBlockOffset: ptr[uint32](0), - }, - }, - Nodes: []*solcfg.Node{ - {Name: ptr("primary"), URL: commoncfg.MustParseURL("http://solana.web"), Order: ptr(int32(1))}, - {Name: ptr("foo"), URL: commoncfg.MustParseURL("http://solana.foo"), SendOnly: true, Order: ptr(int32(2))}, - {Name: ptr("bar"), URL: commoncfg.MustParseURL("http://solana.bar"), SendOnly: true, Order: ptr(int32(3))}, - }, - Workflow: solcfg.WorkflowConfig{ - AcceptanceTimeout: commoncfg.MustNewDuration(time.Second * 45), - FromAddress: ptr(solana.MustPublicKeyFromBase58("4BJXYkfvg37zEmBbsacZjeQDpTNx91KppxFJxRqrz48e")), - ForwarderAddress: ptr(solana.MustPublicKeyFromBase58("14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5")), - ForwarderState: ptr(solana.MustPublicKeyFromBase58("14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5")), - TxAcceptanceState: ptr(commontypes.Finalized), - PollPeriod: commoncfg.MustNewDuration(time.Second * 3), - Local: ptr(true), - GasLimitDefault: ptr(uint64(0)), - }, - }, - } full.Mercury = toml.Mercury{ Cache: toml.MercuryCache{ LatestReportTTL: commoncfg.MustNewDuration(100 * time.Second), @@ -1195,21 +1042,6 @@ DefaultBootstrappers = ['12D3KooWMoejJznyDuEk5aX6GvbjaG12UzeornPCBNzMRqdwrFJw@fo DeltaDial = '1m0s' DeltaReconcile = '1s' ListenAddresses = ['foo', 'bar'] -`}, - {"Keeper", Config{Core: toml.Core{Keeper: full.Keeper}}, `[Keeper] -DefaultTransactionQueueDepth = 17 -GasPriceBufferPercent = 12 -GasTipCapBufferPercent = 43 -BaseFeeBufferPercent = 89 -MaxGracePeriod = 31 -TurnLookBack = 91 - -[Keeper.Registry] -CheckGasOverhead = 90 -PerformGasOverhead = 4294967295 -MaxPerformDataSize = 5000 -SyncInterval = '1h0m0s' -SyncUpkeepQueueSize = 31 `}, {"AutoPprof", Config{Core: toml.Core{AutoPprof: full.AutoPprof}}, `[AutoPprof] Enabled = true @@ -1406,83 +1238,6 @@ HTTPURL = 'https://bar.com' Name = 'broadcast' HTTPURL = 'http://broadcast.mirror' SendOnly = true -`}, - {"Solana", Config{Solana: full.Solana}, `[[Solana]] -ChainID = 'mainnet' -Enabled = false -BlockTime = '500ms' -BalancePollPeriod = '1m0s' -ConfirmPollPeriod = '1s' -OCR2CachePollPeriod = '1m0s' -OCR2CacheTTL = '1h0m0s' -TxTimeout = '1h0m0s' -TxRetryTimeout = '1m0s' -TxConfirmTimeout = '1s' -TxExpirationRebroadcast = false -TxRetentionTimeout = '0s' -SkipPreflight = true -Commitment = 'banana' -MaxRetries = 7 -FeeEstimatorMode = 'fixed' -ComputeUnitPriceMax = 1000 -ComputeUnitPriceMin = 10 -ComputeUnitPriceDefault = 100 -FeeBumpPeriod = '1m0s' -BlockHistoryPollPeriod = '1m0s' -BlockHistorySize = 1 -BlockHistoryBatchLoadSize = 20 -ComputeUnitLimitDefault = 100000 -EstimateComputeUnitLimit = false -LogPollerStartingLookback = '24h0m0s' -LogPollerCPIEventsEnabled = true -LogPollerSlotsBatchSize = 100 - -[Solana.Workflow] -AcceptanceTimeout = '45s' -ForwarderAddress = '14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5' -ForwarderState = '14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5' -FromAddress = '4BJXYkfvg37zEmBbsacZjeQDpTNx91KppxFJxRqrz48e' -GasLimitDefault = 0 -Local = true -PollPeriod = '3s' -TxAcceptanceState = 3 - -[Solana.MultiNode] -Enabled = false -PollFailureThreshold = 5 -PollInterval = '1s' -SelectionMode = 'HighestHead' -SyncThreshold = 5 -NodeIsSyncingEnabled = false -LeaseDuration = '1m0s' -NewHeadsPollInterval = '1s' -FinalizedBlockPollInterval = '1s' -EnforceRepeatableRead = true -DeathDeclarationDelay = '1m0s' -VerifyChainID = true -NodeNoNewHeadsThreshold = '1m0s' -NoNewFinalizedHeadsThreshold = '1m0s' -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 - -[[Solana.Nodes]] -Name = 'primary' -URL = 'http://solana.web' -SendOnly = false -Order = 1 - -[[Solana.Nodes]] -Name = 'foo' -URL = 'http://solana.foo' -SendOnly = true -Order = 2 - -[[Solana.Nodes]] -Name = 'bar' -URL = 'http://solana.bar' -SendOnly = true -Order = 3 `}, {"Mercury", Config{Core: toml.Core{Mercury: full.Mercury}}, `[Mercury] VerboseLogging = true @@ -1597,14 +1352,6 @@ func TestConfig_full(t *testing.T) { } } - for c := range got.Solana { - for n := range got.Solana[c].Nodes { - if got.Solana[c].Nodes[n].IsLoadBalancedRPC == nil { - got.Solana[c].Nodes[n].IsLoadBalancedRPC = ptr(false) - } - } - } - configtest.AssertFieldsNotNil(t, got) } @@ -1695,11 +1442,11 @@ func TestConfig_Validate(t *testing.T) { - Nodes: missing: expected at least one node - Solana: 4 errors: - 1.ChainID: invalid value (mainnet): duplicate - must be unique - - 0.Nodes: missing: must have at least one node - - 1.Nodes.0.URL: missing: required for all nodes + - 1.Nodes.1.Name: invalid value (bar): duplicate - must be unique + - 0.Nodes: missing: expected at least one node - 2: 2 errors: - - ChainID: empty: required for all chains - - Nodes: missing: must have at least one node + - ChainID: missing: required for all chains + - Nodes: missing: expected at least one node - Starknet: 3 errors: - 0.Nodes.1.Name: invalid value (primary): duplicate - must be unique - 0.ChainID: missing: required for all chains @@ -1947,7 +1694,7 @@ func TestConfig_setDefaults(t *testing.T) { var c Config c.EVM = evmcfg.EVMConfigs{{ChainID: sqlutil.NewI(99999133712345)}} c.Cosmos = RawConfigs{{"ChainID": ptr("unknown cosmos chain")}} - c.Solana = solcfg.TOMLConfigs{{ChainID: ptr("unknown solana chain")}} + c.Solana = RawConfigs{{"ChainID": ptr("unknown solana chain")}} c.Starknet = RawConfigs{{"ChainID": ptr("unknown starknet chain")}} c.setDefaults() diff --git a/core/services/chainlink/mocks/general_config.go b/core/services/chainlink/mocks/general_config.go index d6d602c9899..a7fbb69d415 100644 --- a/core/services/chainlink/mocks/general_config.go +++ b/core/services/chainlink/mocks/general_config.go @@ -7,7 +7,6 @@ import ( uuid "github.com/google/uuid" toml "github.com/smartcontractkit/chainlink-evm/pkg/config/toml" - solanaconfig "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" config "github.com/smartcontractkit/chainlink/v2/core/config" chainlink "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" mock "github.com/stretchr/testify/mock" @@ -1296,53 +1295,6 @@ func (_c *GeneralConfig_JobPipeline_Call) RunAndReturn(run func() config.JobPipe return _c } -// Keeper provides a mock function with no fields -func (_m *GeneralConfig) Keeper() config.Keeper { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Keeper") - } - - var r0 config.Keeper - if rf, ok := ret.Get(0).(func() config.Keeper); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(config.Keeper) - } - } - - return r0 -} - -// GeneralConfig_Keeper_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Keeper' -type GeneralConfig_Keeper_Call struct { - *mock.Call -} - -// Keeper is a helper method to define mock.On call -func (_e *GeneralConfig_Expecter) Keeper() *GeneralConfig_Keeper_Call { - return &GeneralConfig_Keeper_Call{Call: _e.mock.On("Keeper")} -} - -func (_c *GeneralConfig_Keeper_Call) Run(run func()) *GeneralConfig_Keeper_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *GeneralConfig_Keeper_Call) Return(_a0 config.Keeper) *GeneralConfig_Keeper_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *GeneralConfig_Keeper_Call) RunAndReturn(run func() config.Keeper) *GeneralConfig_Keeper_Call { - _c.Call.Return(run) - return _c -} - // LOOPP provides a mock function with no fields func (_m *GeneralConfig) LOOPP() config.LOOPP { ret := _m.Called() @@ -2098,19 +2050,19 @@ func (_c *GeneralConfig_ShutdownGracePeriod_Call) RunAndReturn(run func() time.D } // SolanaConfigs provides a mock function with no fields -func (_m *GeneralConfig) SolanaConfigs() solanaconfig.TOMLConfigs { +func (_m *GeneralConfig) SolanaConfigs() chainlink.RawConfigs { ret := _m.Called() if len(ret) == 0 { panic("no return value specified for SolanaConfigs") } - var r0 solanaconfig.TOMLConfigs - if rf, ok := ret.Get(0).(func() solanaconfig.TOMLConfigs); ok { + var r0 chainlink.RawConfigs + if rf, ok := ret.Get(0).(func() chainlink.RawConfigs); ok { r0 = rf() } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(solanaconfig.TOMLConfigs) + r0 = ret.Get(0).(chainlink.RawConfigs) } } @@ -2134,12 +2086,12 @@ func (_c *GeneralConfig_SolanaConfigs_Call) Run(run func()) *GeneralConfig_Solan return _c } -func (_c *GeneralConfig_SolanaConfigs_Call) Return(_a0 solanaconfig.TOMLConfigs) *GeneralConfig_SolanaConfigs_Call { +func (_c *GeneralConfig_SolanaConfigs_Call) Return(_a0 chainlink.RawConfigs) *GeneralConfig_SolanaConfigs_Call { _c.Call.Return(_a0) return _c } -func (_c *GeneralConfig_SolanaConfigs_Call) RunAndReturn(run func() solanaconfig.TOMLConfigs) *GeneralConfig_SolanaConfigs_Call { +func (_c *GeneralConfig_SolanaConfigs_Call) RunAndReturn(run func() chainlink.RawConfigs) *GeneralConfig_SolanaConfigs_Call { _c.Call.Return(run) return _c } diff --git a/core/services/chainlink/relayer_chain_interoperators.go b/core/services/chainlink/relayer_chain_interoperators.go index b585b6e7ad6..ce4ea40e818 100644 --- a/core/services/chainlink/relayer_chain_interoperators.go +++ b/core/services/chainlink/relayer_chain_interoperators.go @@ -158,9 +158,9 @@ func InitCosmos(factory RelayerFactory, ks keystore.Cosmos, csaKS keystore.CSA, } // InitSolana is a option for instantiating Solana relayers -func InitSolana(factory RelayerFactory, ks keystore.Solana, csaKS keystore.CSA, config SolanaFactoryConfig) CoreRelayerChainInitFunc { +func InitSolana(factory RelayerFactory, ks keystore.Solana, csaKS keystore.CSA, chainCfgs RawConfigs) CoreRelayerChainInitFunc { return func(op *CoreRelayerChainInteroperators) error { - solRelayers, err := factory.NewSolana(&keystore.SolanaLooppSigner{Solana: ks}, &keystore.CSASigner{CSA: csaKS}, config) + solRelayers, err := factory.NewSolana(&keystore.SolanaLooppSigner{Solana: ks}, &keystore.CSASigner{CSA: csaKS}, chainCfgs) if err != nil { return fmt.Errorf("failed to setup Solana relayer: %w", err) } diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go index 54d8b7ab747..6d52913f107 100644 --- a/core/services/chainlink/relayer_chain_interoperators_test.go +++ b/core/services/chainlink/relayer_chain_interoperators_test.go @@ -16,8 +16,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" - "github.com/smartcontractkit/chainlink-evm/pkg/chains/legacyevm" "github.com/smartcontractkit/chainlink-evm/pkg/config/toml" @@ -34,7 +32,6 @@ import ( func TestCoreRelayerChainInteroperators(t *testing.T) { evmChainID1, evmChainID2 := sqlutil.New(big.NewInt(1)), sqlutil.New(big.NewInt(2)) - solanaChainID1, solanaChainID2 := "solana-id-1", "solana-id-2" newConfig := func() chainlink.GeneralConfig { return configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { @@ -75,28 +72,6 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { Enabled: ptr(true), Nodes: toml.EVMNodes{&node2_1}, }) - - c.Solana = solcfg.TOMLConfigs{ - &solcfg.TOMLConfig{ - ChainID: &solanaChainID1, - Enabled: ptr(true), - Nodes: []*solcfg.Node{{ - Name: ptr("solana chain 1 node 1"), - URL: commonconfig.MustParseURL("http://localhost:8547"), - }}, - }, - &solcfg.TOMLConfig{ - ChainID: &solanaChainID2, - Enabled: ptr(true), - Nodes: []*solcfg.Node{{ - Name: ptr("solana chain 2 node 1"), - URL: commonconfig.MustParseURL("http://localhost:8527"), - }}, - }, - } - for i := range c.Solana { - c.Solana[i].SetDefaults() - } }) } @@ -124,10 +99,6 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { expectedEVMNodeCnt int expectedEVMRelayerIds []types.RelayID - expectedSolanaChainCnt int - expectedSolanaNodeCnt int - expectedSolanaRelayerIds []types.RelayID - expectedStarknetChainCnt int expectedStarknetNodeCnt int @@ -137,6 +108,9 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { expectedCosmosChainCnt int expectedCosmosNodeCnt int + + expectedSolanaChainCnt int + expectedSolanaNodeCnt int }{ {name: "2 evm chains with 3 nodes", @@ -163,23 +137,8 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { expectedRelayerNetworks: map[string]struct{}{relay.NetworkEVM: {}}, }, - {name: "2 solana chain with 2 node", - initFuncs: []chainlink.CoreRelayerChainInitFunc{ - chainlink.InitSolana(factory, keyStore.Solana(), keyStore.CSA(), chainlink.SolanaFactoryConfig{ - TOMLConfigs: newConfig().SolanaConfigs()}), - }, - expectedSolanaChainCnt: 2, - expectedSolanaNodeCnt: 2, - expectedSolanaRelayerIds: []types.RelayID{ - {Network: relay.NetworkSolana, ChainID: solanaChainID1}, - {Network: relay.NetworkSolana, ChainID: solanaChainID2}, - }, - expectedRelayerNetworks: map[string]struct{}{relay.NetworkSolana: {}}, - }, - {name: "all chains", - initFuncs: []chainlink.CoreRelayerChainInitFunc{chainlink.InitSolana(factory, keyStore.Solana(), keyStore.CSA(), chainlink.SolanaFactoryConfig{ - TOMLConfigs: newConfig().SolanaConfigs()}), + initFuncs: []chainlink.CoreRelayerChainInitFunc{ chainlink.InitEVM(factory, chainlink.EVMFactoryConfig{ ChainOpts: legacyevm.ChainOpts{ ChainConfigs: cfg.EVMConfigs(), @@ -195,6 +154,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { }), chainlink.InitStarknet(factory, keyStore.StarkNet(), keyStore.CSA(), cfg.StarknetConfigs()), chainlink.InitCosmos(factory, keyStore.Cosmos(), keyStore.CSA(), cfg.CosmosConfigs()), + chainlink.InitSolana(factory, keyStore.Solana(), keyStore.CSA(), cfg.SolanaConfigs()), }, expectedEVMChainCnt: 2, expectedEVMNodeCnt: 3, @@ -203,13 +163,6 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { {Network: relay.NetworkEVM, ChainID: evmChainID2.String()}, }, - expectedSolanaChainCnt: 2, - expectedSolanaNodeCnt: 2, - expectedSolanaRelayerIds: []types.RelayID{ - {Network: relay.NetworkSolana, ChainID: solanaChainID1}, - {Network: relay.NetworkSolana, ChainID: solanaChainID2}, - }, - expectedRelayerNetworks: map[string]struct{}{relay.NetworkEVM: {}, relay.NetworkCosmos: {}, relay.NetworkSolana: {}, relay.NetworkStarkNet: {}}, }, } @@ -293,7 +246,6 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { allRelayerIds := [][]types.RelayID{ tt.expectedEVMRelayerIds, - tt.expectedSolanaRelayerIds, } for _, chainSpecificRelayerIds := range allRelayerIds { diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go index 2b391e52556..1ddb0867c56 100644 --- a/core/services/chainlink/relayer_factory.go +++ b/core/services/chainlink/relayer_factory.go @@ -12,15 +12,12 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/loop" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/types" coretypes "github.com/smartcontractkit/chainlink-common/pkg/types/core" "github.com/smartcontractkit/chainlink-data-streams/mercury/wsrpc" "github.com/smartcontractkit/chainlink-evm/pkg/chains/legacyevm" evmtoml "github.com/smartcontractkit/chainlink-evm/pkg/config/toml" "github.com/smartcontractkit/chainlink-evm/pkg/keys" - "github.com/smartcontractkit/chainlink-solana/pkg/solana" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" coreconfig "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/config/env" @@ -137,72 +134,8 @@ func (r *RelayerFactory) NewEVM(config EVMFactoryConfig) (map[types.RelayID]evmr return relayers, nil } -type SolanaFactoryConfig struct { - solcfg.TOMLConfigs - DS sqlutil.DataSource -} - -func (r *RelayerFactory) NewSolana(ks, ksCSA coretypes.Keystore, config SolanaFactoryConfig) (map[types.RelayID]loop.Relayer, error) { - chainCfgs, ds := config.TOMLConfigs, config.DS - solanaRelayers := make(map[types.RelayID]loop.Relayer) - var solLggr = logger.Named(r.Logger, "Solana") - - unique := make(map[string]struct{}) - // create one relayer per chain id - for _, chainCfg := range chainCfgs { - relayID := types.RelayID{Network: relay.NetworkSolana, ChainID: *chainCfg.ChainID} - _, alreadyExists := unique[relayID.Name()] - if alreadyExists { - return nil, fmt.Errorf("duplicate chain definitions for %s", relayID.Name()) - } - unique[relayID.Name()] = struct{}{} - - // skip disabled chains from further processing - if !chainCfg.IsEnabled() { - solLggr.Warnw("Skipping disabled chain", "id", chainCfg.ChainID) - continue - } - - lggr := logger.Named(solLggr, relayID.ChainID) - - if cmdName := env.SolanaPlugin.Cmd.Get(); cmdName != "" { - // setup the solana relayer to be a LOOP - cfgTOML, err := toml.Marshal(struct { - Solana solcfg.TOMLConfig - }{Solana: *chainCfg}) - if err != nil { - return nil, fmt.Errorf("failed to marshal Solana configs: %w", err) - } - envVars, err := plugins.ParseEnvFile(env.SolanaPlugin.Env.Get()) - if err != nil { - return nil, fmt.Errorf("failed to parse Solana env file: %w", err) - } - solCmdFn, err := plugins.NewCmdFactory(r.Register, plugins.CmdConfig{ - ID: relayID.Name(), - Cmd: cmdName, - Env: envVars, - }) - if err != nil { - return nil, fmt.Errorf("failed to create Solana LOOP command: %w", err) - } - - solanaRelayers[relayID] = loop.NewRelayerService(lggr, r.GRPCOpts, solCmdFn, string(cfgTOML), ks, ksCSA, r.CapabilitiesRegistry) - } else { - // fallback to embedded chain - opts := solana.ChainOpts{ - Logger: lggr, - KeyStore: ks, - DS: ds, - } - - chain, err := solana.NewChain(chainCfg, opts) - if err != nil { - return nil, err - } - solanaRelayers[relayID] = relay.NewServerAdapter(solana.NewRelayer(lggr, chain, r.CapabilitiesRegistry, ks)) - } - } - return solanaRelayers, nil +func (r *RelayerFactory) NewSolana(ks, ksCSA coretypes.Keystore, chainCfgs RawConfigs) (map[types.RelayID]loop.Relayer, error) { + return r.NewLOOPRelayer("Solana", relay.NetworkSolana, env.SolanaPlugin, ks, ksCSA, chainCfgs) } func (r *RelayerFactory) NewStarkNet(ks, ksCSA coretypes.Keystore, chainCfgs RawConfigs) (map[types.RelayID]loop.Relayer, error) { diff --git a/core/services/chainlink/testdata/config-empty-effective.toml b/core/services/chainlink/testdata/config-empty-effective.toml index bd00ab34ccb..a073a30ed45 100644 --- a/core/services/chainlink/testdata/config-empty-effective.toml +++ b/core/services/chainlink/testdata/config-empty-effective.toml @@ -193,21 +193,6 @@ DeltaDial = '15s' DeltaReconcile = '1m0s' ListenAddresses = [] -[Keeper] -DefaultTransactionQueueDepth = 1 -GasPriceBufferPercent = 20 -GasTipCapBufferPercent = 20 -BaseFeeBufferPercent = 20 -MaxGracePeriod = 100 -TurnLookBack = 1000 - -[Keeper.Registry] -CheckGasOverhead = 200000 -PerformGasOverhead = 300000 -MaxPerformDataSize = 5000 -SyncInterval = '30m0s' -SyncUpkeepQueueSize = 10 - [AutoPprof] Enabled = false ProfileRoot = '' diff --git a/core/services/chainlink/testdata/config-full.toml b/core/services/chainlink/testdata/config-full.toml index 2ebb20cc5a6..7583f0ec595 100644 --- a/core/services/chainlink/testdata/config-full.toml +++ b/core/services/chainlink/testdata/config-full.toml @@ -199,21 +199,6 @@ DeltaDial = '1m0s' DeltaReconcile = '1s' ListenAddresses = ['foo', 'bar'] -[Keeper] -DefaultTransactionQueueDepth = 17 -GasPriceBufferPercent = 12 -GasTipCapBufferPercent = 43 -BaseFeeBufferPercent = 89 -MaxGracePeriod = 31 -TurnLookBack = 91 - -[Keeper.Registry] -CheckGasOverhead = 90 -PerformGasOverhead = 4294967295 -MaxPerformDataSize = 5000 -SyncInterval = '1h0m0s' -SyncUpkeepQueueSize = 31 - [AutoPprof] Enabled = true ProfileRoot = 'prof/root' @@ -619,80 +604,3 @@ HTTPURL = 'https://bar.com' Name = 'broadcast' HTTPURL = 'http://broadcast.mirror' SendOnly = true - -[[Solana]] -ChainID = 'mainnet' -Enabled = false -BlockTime = '500ms' -BalancePollPeriod = '1m0s' -ConfirmPollPeriod = '1s' -OCR2CachePollPeriod = '1m0s' -OCR2CacheTTL = '1h0m0s' -TxTimeout = '1h0m0s' -TxRetryTimeout = '1m0s' -TxConfirmTimeout = '1s' -TxExpirationRebroadcast = false -TxRetentionTimeout = '0s' -SkipPreflight = true -Commitment = 'banana' -MaxRetries = 7 -FeeEstimatorMode = 'fixed' -ComputeUnitPriceMax = 1000 -ComputeUnitPriceMin = 10 -ComputeUnitPriceDefault = 100 -FeeBumpPeriod = '1m0s' -BlockHistoryPollPeriod = '1m0s' -BlockHistorySize = 1 -BlockHistoryBatchLoadSize = 20 -ComputeUnitLimitDefault = 100000 -EstimateComputeUnitLimit = false -LogPollerStartingLookback = '24h0m0s' -LogPollerCPIEventsEnabled = true -LogPollerSlotsBatchSize = 100 - -[Solana.Workflow] -AcceptanceTimeout = '45s' -ForwarderAddress = '14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5' -ForwarderState = '14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5' -FromAddress = '4BJXYkfvg37zEmBbsacZjeQDpTNx91KppxFJxRqrz48e' -GasLimitDefault = 0 -Local = true -PollPeriod = '3s' -TxAcceptanceState = 3 - -[Solana.MultiNode] -Enabled = false -PollFailureThreshold = 5 -PollInterval = '1s' -SelectionMode = 'HighestHead' -SyncThreshold = 5 -NodeIsSyncingEnabled = false -LeaseDuration = '1m0s' -NewHeadsPollInterval = '1s' -FinalizedBlockPollInterval = '1s' -EnforceRepeatableRead = true -DeathDeclarationDelay = '1m0s' -VerifyChainID = true -NodeNoNewHeadsThreshold = '1m0s' -NoNewFinalizedHeadsThreshold = '1m0s' -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 - -[[Solana.Nodes]] -Name = 'primary' -URL = 'http://solana.web' -SendOnly = false -Order = 1 - -[[Solana.Nodes]] -Name = 'foo' -URL = 'http://solana.foo' -SendOnly = true -Order = 2 - -[[Solana.Nodes]] -Name = 'bar' -URL = 'http://solana.bar' -SendOnly = true -Order = 3 diff --git a/core/services/chainlink/testdata/config-multi-chain-effective.toml b/core/services/chainlink/testdata/config-multi-chain-effective.toml index d9b08fd9d15..ad20742feed 100644 --- a/core/services/chainlink/testdata/config-multi-chain-effective.toml +++ b/core/services/chainlink/testdata/config-multi-chain-effective.toml @@ -193,21 +193,6 @@ DeltaDial = '15s' DeltaReconcile = '1m0s' ListenAddresses = [] -[Keeper] -DefaultTransactionQueueDepth = 1 -GasPriceBufferPercent = 10 -GasTipCapBufferPercent = 20 -BaseFeeBufferPercent = 20 -MaxGracePeriod = 100 -TurnLookBack = 1000 - -[Keeper.Registry] -CheckGasOverhead = 200000 -PerformGasOverhead = 300000 -MaxPerformDataSize = 5000 -SyncInterval = '30m0s' -SyncUpkeepQueueSize = 10 - [AutoPprof] Enabled = false ProfileRoot = '' @@ -774,133 +759,3 @@ AcceptanceTimeout = '30s' [[EVM.Nodes]] Name = 'bar' WSURL = 'wss://web.socket/test/bar' - -[[Solana]] -ChainID = 'mainnet' -Enabled = true -BlockTime = '500ms' -BalancePollPeriod = '5s' -ConfirmPollPeriod = '500ms' -OCR2CachePollPeriod = '1s' -OCR2CacheTTL = '1m0s' -TxTimeout = '1m0s' -TxRetryTimeout = '10s' -TxConfirmTimeout = '30s' -TxExpirationRebroadcast = false -TxRetentionTimeout = '0s' -SkipPreflight = true -Commitment = 'confirmed' -MaxRetries = 12 -FeeEstimatorMode = 'fixed' -ComputeUnitPriceMax = 1000 -ComputeUnitPriceMin = 0 -ComputeUnitPriceDefault = 0 -FeeBumpPeriod = '3s' -BlockHistoryPollPeriod = '5s' -BlockHistorySize = 1 -BlockHistoryBatchLoadSize = 20 -ComputeUnitLimitDefault = 200000 -EstimateComputeUnitLimit = false -LogPollerStartingLookback = '24h0m0s' -LogPollerCPIEventsEnabled = true -LogPollerSlotsBatchSize = 1000 - -[Solana.Workflow] -AcceptanceTimeout = '45s' -ForwarderAddress = '11111111111111111111111111111111' -ForwarderState = '11111111111111111111111111111111' -FromAddress = '11111111111111111111111111111111' -GasLimitDefault = 300000 -Local = false -PollPeriod = '3s' -TxAcceptanceState = 3 - -[Solana.MultiNode] -Enabled = false -PollFailureThreshold = 5 -PollInterval = '1s' -SelectionMode = 'HighestHead' -SyncThreshold = 5 -NodeIsSyncingEnabled = false -LeaseDuration = '1m0s' -NewHeadsPollInterval = '1s' -FinalizedBlockPollInterval = '1s' -EnforceRepeatableRead = true -DeathDeclarationDelay = '1m0s' -VerifyChainID = true -NodeNoNewHeadsThreshold = '1m0s' -NoNewFinalizedHeadsThreshold = '1m0s' -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 - -[[Solana.Nodes]] -Name = 'primary' -URL = 'http://mainnet.solana.com' -SendOnly = false -Order = 1 - -[[Solana]] -ChainID = 'testnet' -Enabled = true -BlockTime = '500ms' -BalancePollPeriod = '5s' -ConfirmPollPeriod = '500ms' -OCR2CachePollPeriod = '1m0s' -OCR2CacheTTL = '1m0s' -TxTimeout = '1m0s' -TxRetryTimeout = '10s' -TxConfirmTimeout = '30s' -TxExpirationRebroadcast = false -TxRetentionTimeout = '0s' -SkipPreflight = true -Commitment = 'confirmed' -MaxRetries = 0 -FeeEstimatorMode = 'fixed' -ComputeUnitPriceMax = 1000 -ComputeUnitPriceMin = 0 -ComputeUnitPriceDefault = 0 -FeeBumpPeriod = '3s' -BlockHistoryPollPeriod = '5s' -BlockHistorySize = 1 -BlockHistoryBatchLoadSize = 20 -ComputeUnitLimitDefault = 200000 -EstimateComputeUnitLimit = false -LogPollerStartingLookback = '24h0m0s' -LogPollerCPIEventsEnabled = true -LogPollerSlotsBatchSize = 1000 - -[Solana.Workflow] -AcceptanceTimeout = '45s' -ForwarderAddress = '11111111111111111111111111111111' -ForwarderState = '11111111111111111111111111111111' -FromAddress = '11111111111111111111111111111111' -GasLimitDefault = 300000 -Local = false -PollPeriod = '3s' -TxAcceptanceState = 3 - -[Solana.MultiNode] -Enabled = false -PollFailureThreshold = 5 -PollInterval = '1s' -SelectionMode = 'HighestHead' -SyncThreshold = 5 -NodeIsSyncingEnabled = false -LeaseDuration = '1m0s' -NewHeadsPollInterval = '1s' -FinalizedBlockPollInterval = '1s' -EnforceRepeatableRead = true -DeathDeclarationDelay = '1m0s' -VerifyChainID = true -NodeNoNewHeadsThreshold = '1m0s' -NoNewFinalizedHeadsThreshold = '1m0s' -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 - -[[Solana.Nodes]] -Name = 'secondary' -URL = 'http://testnet.solana.com' -SendOnly = false -Order = 2 diff --git a/core/services/chainlink/testdata/config-multi-chain.toml b/core/services/chainlink/testdata/config-multi-chain.toml index 7db000b7c85..b9e1c100dbc 100644 --- a/core/services/chainlink/testdata/config-multi-chain.toml +++ b/core/services/chainlink/testdata/config-multi-chain.toml @@ -29,9 +29,6 @@ BlockchainTimeout = '5s' [P2P] IncomingMessageBufferSize = 999 -[Keeper] -GasPriceBufferPercent = 10 - [AutoPprof] CPUProfileRate = 7 @@ -76,61 +73,3 @@ Mode = 'FixedPrice' [[EVM.Nodes]] Name = 'bar' WSURL = 'wss://web.socket/test/bar' - -[[Solana]] -ChainID = 'mainnet' -MaxRetries = 12 - -[Solana.MultiNode] -Enabled = false -PollFailureThreshold = 5 -PollInterval = '1s' -SelectionMode = 'HighestHead' -SyncThreshold = 5 -NodeIsSyncingEnabled = false -LeaseDuration = '1m0s' -NewHeadsPollInterval = '1s' -FinalizedBlockPollInterval = '1s' -EnforceRepeatableRead = true -DeathDeclarationDelay = '1m0s' -VerifyChainID = true -NodeNoNewHeadsThreshold = '1m0s' -NoNewFinalizedHeadsThreshold = '1m0s' -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 - -[[Solana.Nodes]] -Name = 'primary' -URL = 'http://mainnet.solana.com' -SendOnly = false -Order = 1 - -[[Solana]] -ChainID = 'testnet' -OCR2CachePollPeriod = '1m0s' - -[Solana.MultiNode] -Enabled = false -PollFailureThreshold = 5 -PollInterval = '1s' -SelectionMode = 'HighestHead' -SyncThreshold = 5 -NodeIsSyncingEnabled = false -LeaseDuration = '1m0s' -NewHeadsPollInterval = '1s' -FinalizedBlockPollInterval = '1s' -EnforceRepeatableRead = true -DeathDeclarationDelay = '1m0s' -VerifyChainID = true -NodeNoNewHeadsThreshold = '1m0s' -NoNewFinalizedHeadsThreshold = '1m0s' -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 - -[[Solana.Nodes]] -Name = 'secondary' -URL = 'http://testnet.solana.com' -SendOnly = false -Order = 2 diff --git a/core/services/chainlink/types.go b/core/services/chainlink/types.go index 037ee88019f..ea7f196461c 100644 --- a/core/services/chainlink/types.go +++ b/core/services/chainlink/types.go @@ -1,8 +1,6 @@ package chainlink import ( - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" - "github.com/smartcontractkit/chainlink-evm/pkg/config/toml" "github.com/smartcontractkit/chainlink/v2/core/config" coreconfig "github.com/smartcontractkit/chainlink/v2/core/config" @@ -12,7 +10,7 @@ type GeneralConfig interface { config.AppConfig toml.HasEVMConfigs CosmosConfigs() RawConfigs - SolanaConfigs() solcfg.TOMLConfigs + SolanaConfigs() RawConfigs StarknetConfigs() RawConfigs AptosConfigs() RawConfigs TronConfigs() RawConfigs diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go index c9f9b2aeec6..24455b054e3 100644 --- a/core/services/job/job_orm_test.go +++ b/core/services/job/job_orm_test.go @@ -43,7 +43,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/directrequest" "github.com/smartcontractkit/chainlink/v2/core/services/gateway" "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/keeper" "github.com/smartcontractkit/chainlink/v2/core/services/ocr" ocr2validate "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" @@ -376,7 +375,6 @@ func TestORM_DeleteJob_DeletesAssociatedRecords(t *testing.T) { pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) - korm := keeper.NewORM(db, logger.TestLogger(t)) t.Run("it deletes records for offchainreporting jobs", func(t *testing.T) { ctx := testutils.Context(t) @@ -412,23 +410,6 @@ func TestORM_DeleteJob_DeletesAssociatedRecords(t *testing.T) { cltest.AssertCount(t, db, "jobs", 0) }) - t.Run("it deletes records for keeper jobs", func(t *testing.T) { - ctx := testutils.Context(t) - registry, keeperJob := cltest.MustInsertKeeperRegistry(t, db, korm, keyStore.Eth(), 0, 1, 20) - cltest.MustInsertUpkeepForRegistry(t, db, registry) - - cltest.AssertCount(t, db, "keeper_specs", 1) - cltest.AssertCount(t, db, "keeper_registries", 1) - cltest.AssertCount(t, db, "upkeep_registrations", 1) - - err := jobORM.DeleteJob(ctx, keeperJob.ID, keeperJob.Type) - require.NoError(t, err) - cltest.AssertCount(t, db, "keeper_specs", 0) - cltest.AssertCount(t, db, "keeper_registries", 0) - cltest.AssertCount(t, db, "upkeep_registrations", 0) - cltest.AssertCount(t, db, "jobs", 0) - }) - t.Run("it creates and deletes records for vrf jobs", func(t *testing.T) { ctx := testutils.Context(t) key, err := keyStore.VRF().Create(ctx) @@ -762,14 +743,6 @@ func TestORM_CreateJob_EVMChainID_Validation(t *testing.T) { assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(testutils.Context(t), &jb).Error()) }) - t.Run("evm chain id validation for keepers works", func(t *testing.T) { - jb := job.Job{ - Type: job.Keeper, - KeeperSpec: &job.KeeperSpec{}, - } - assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(testutils.Context(t), &jb).Error()) - }) - t.Run("evm chain id validation for vrf works", func(t *testing.T) { jb := job.Job{ Type: job.VRF, diff --git a/core/services/job/models.go b/core/services/job/models.go index 2d257a33ca5..13b896b59a7 100644 --- a/core/services/job/models.go +++ b/core/services/job/models.go @@ -48,7 +48,6 @@ const ( DirectRequest Type = (Type)(pipeline.DirectRequestJobType) FluxMonitor Type = (Type)(pipeline.FluxMonitorJobType) Gateway Type = (Type)(pipeline.GatewayJobType) - Keeper Type = (Type)(pipeline.KeeperJobType) LegacyGasStationServer Type = (Type)(pipeline.LegacyGasStationServerJobType) LegacyGasStationSidecar Type = (Type)(pipeline.LegacyGasStationSidecarJobType) OffchainReporting Type = (Type)(pipeline.OffchainReportingJobType) @@ -92,7 +91,6 @@ var ( DirectRequest: true, FluxMonitor: true, Gateway: false, - Keeper: false, // observationSource is injected in the upkeep executor LegacyGasStationServer: false, LegacyGasStationSidecar: false, OffchainReporting2: false, // bootstrap jobs do not require it @@ -115,7 +113,6 @@ var ( DirectRequest: true, FluxMonitor: false, Gateway: false, - Keeper: true, LegacyGasStationServer: false, LegacyGasStationSidecar: false, OffchainReporting2: false, @@ -138,7 +135,6 @@ var ( DirectRequest: 1, FluxMonitor: 1, Gateway: 1, - Keeper: 1, LegacyGasStationServer: 1, LegacyGasStationSidecar: 1, OffchainReporting2: 1, @@ -165,8 +161,6 @@ type Job struct { DirectRequestSpec *DirectRequestSpec FluxMonitorSpecID *int32 FluxMonitorSpec *FluxMonitorSpec - KeeperSpecID *int32 - KeeperSpec *KeeperSpec VRFSpecID *int32 VRFSpec *VRFSpec WebhookSpecID *int32 @@ -559,16 +553,6 @@ type FluxMonitorSpec struct { UpdatedAt time.Time `toml:"-"` } -type KeeperSpec struct { - ID int32 `toml:"-"` - ContractAddress evmtypes.EIP55Address `toml:"contractAddress"` - MinIncomingConfirmations *uint32 `toml:"minIncomingConfirmations"` - FromAddress evmtypes.EIP55Address `toml:"fromAddress"` - EVMChainID *sqlutil.Big `toml:"evmChainID"` - CreatedAt time.Time `toml:"-"` - UpdatedAt time.Time `toml:"-"` -} - type VRFSpec struct { ID int32 diff --git a/core/services/job/orm.go b/core/services/job/orm.go index e425942901b..6f11f3f90c6 100644 --- a/core/services/job/orm.go +++ b/core/services/job/orm.go @@ -362,15 +362,6 @@ func (o *orm) CreateJob(ctx context.Context, jb *Job) error { return fmt.Errorf("failed to create OCR2OracleSpec for jobSpec: %w", err) } jb.OCR2OracleSpecID = &specID - case Keeper: - if jb.KeeperSpec.EVMChainID == nil { - return errors.New("evm chain id must be defined") - } - specID, err := tx.insertKeeperSpec(ctx, jb.KeeperSpec) - if err != nil { - return fmt.Errorf("failed to create KeeperSpec for jobSpec: %w", err) - } - jb.KeeperSpecID = &specID case CRESettings: specID, err := tx.insertCRESettingsSpec(ctx, jb.CRESettingsSpec) if err != nil { @@ -597,12 +588,6 @@ func (o *orm) insertOCR2OracleSpec(ctx context.Context, spec *OCR2OracleSpec) (s RETURNING id;`, spec) } -func (o *orm) insertKeeperSpec(ctx context.Context, spec *KeeperSpec) (specID int32, err error) { - return o.prepareQuerySpecID(ctx, `INSERT INTO keeper_specs (contract_address, from_address, evm_chain_id, created_at, updated_at) - VALUES (:contract_address, :from_address, :evm_chain_id, NOW(), NOW()) - RETURNING id;`, spec) -} - func (o *orm) insertCRESettingsSpec(ctx context.Context, spec *CRESettingsSpec) (specID int32, err error) { return o.prepareQuerySpecID(ctx, `INSERT INTO cre_settings_specs (settings, hash, created_at, updated_at) VALUES (:settings, :hash, NOW(), NOW()) RETURNING id;`, spec) } @@ -766,18 +751,18 @@ func (o *orm) InsertJob(ctx context.Context, job *Job) error { // if job has id, emplace otherwise insert with a new id. if job.ID == 0 { query = `INSERT INTO jobs (name, stream_id, schema_version, type, max_task_duration, ocr_oracle_spec_id, ocr2_oracle_spec_id, direct_request_spec_id, flux_monitor_spec_id, - keeper_spec_id, cre_settings_spec_id, cron_spec_id, vrf_spec_id, webhook_spec_id, blockhash_store_spec_id, bootstrap_spec_id, block_header_feeder_spec_id, gateway_spec_id, + cre_settings_spec_id, cron_spec_id, vrf_spec_id, webhook_spec_id, blockhash_store_spec_id, bootstrap_spec_id, block_header_feeder_spec_id, gateway_spec_id, legacy_gas_station_server_spec_id, legacy_gas_station_sidecar_spec_id, workflow_spec_id, standard_capabilities_spec_id, ccip_spec_id, ccv_committee_verifier_spec_id, ccv_executor_spec_id, external_job_id, gas_limit, forwarding_allowed, created_at) VALUES (:name, :stream_id, :schema_version, :type, :max_task_duration, :ocr_oracle_spec_id, :ocr2_oracle_spec_id, :direct_request_spec_id, :flux_monitor_spec_id, - :keeper_spec_id, :cre_settings_spec_id, :cron_spec_id, :vrf_spec_id, :webhook_spec_id, :blockhash_store_spec_id, :bootstrap_spec_id, :block_header_feeder_spec_id, :gateway_spec_id, + :cre_settings_spec_id, :cron_spec_id, :vrf_spec_id, :webhook_spec_id, :blockhash_store_spec_id, :bootstrap_spec_id, :block_header_feeder_spec_id, :gateway_spec_id, :legacy_gas_station_server_spec_id, :legacy_gas_station_sidecar_spec_id, :workflow_spec_id, :standard_capabilities_spec_id, :ccip_spec_id, :ccv_committee_verifier_spec_id, :ccv_executor_spec_id, :external_job_id, :gas_limit, :forwarding_allowed, NOW()) RETURNING *;` } else { query = `INSERT INTO jobs (id, name, stream_id, schema_version, type, max_task_duration, ocr_oracle_spec_id, ocr2_oracle_spec_id, direct_request_spec_id, flux_monitor_spec_id, - keeper_spec_id, cre_settings_spec_id, cron_spec_id, vrf_spec_id, webhook_spec_id, blockhash_store_spec_id, bootstrap_spec_id, block_header_feeder_spec_id, gateway_spec_id, + cre_settings_spec_id, cron_spec_id, vrf_spec_id, webhook_spec_id, blockhash_store_spec_id, bootstrap_spec_id, block_header_feeder_spec_id, gateway_spec_id, legacy_gas_station_server_spec_id, legacy_gas_station_sidecar_spec_id, workflow_spec_id, standard_capabilities_spec_id, ccip_spec_id, ccv_committee_verifier_spec_id, ccv_executor_spec_id, external_job_id, gas_limit, forwarding_allowed, created_at) VALUES (:id, :name, :stream_id, :schema_version, :type, :max_task_duration, :ocr_oracle_spec_id, :ocr2_oracle_spec_id, :direct_request_spec_id, :flux_monitor_spec_id, - :keeper_spec_id, :cre_settings_spec_id, :cron_spec_id, :vrf_spec_id, :webhook_spec_id, :blockhash_store_spec_id, :bootstrap_spec_id, :block_header_feeder_spec_id, :gateway_spec_id, + :cre_settings_spec_id, :cron_spec_id, :vrf_spec_id, :webhook_spec_id, :blockhash_store_spec_id, :bootstrap_spec_id, :block_header_feeder_spec_id, :gateway_spec_id, :legacy_gas_station_server_spec_id, :legacy_gas_station_sidecar_spec_id, :workflow_spec_id, :standard_capabilities_spec_id, :ccip_spec_id, :ccv_committee_verifier_spec_id, :ccv_executor_spec_id, :external_job_id, :gas_limit, :forwarding_allowed, NOW()) RETURNING *;` } @@ -805,7 +790,6 @@ func (o *orm) DeleteJob(ctx context.Context, id int32, jobType Type) error { FluxMonitor: `DELETE FROM flux_monitor_specs WHERE id IN (SELECT flux_monitor_spec_id FROM deleted_jobs)`, OffchainReporting: `DELETE FROM ocr_oracle_specs WHERE id IN (SELECT ocr_oracle_spec_id FROM deleted_jobs)`, OffchainReporting2: `DELETE FROM ocr2_oracle_specs WHERE id IN (SELECT ocr2_oracle_spec_id FROM deleted_jobs)`, - Keeper: `DELETE FROM keeper_specs WHERE id IN (SELECT keeper_spec_id FROM deleted_jobs)`, CRESettings: `DELETE FROM cre_settings_specs WHERE id IN (SELECT cre_settings_spec_id FROM deleted_jobs)`, Cron: `DELETE FROM cron_specs WHERE id IN (SELECT cron_spec_id FROM deleted_jobs)`, VRF: `DELETE FROM vrf_specs WHERE id IN (SELECT vrf_spec_id FROM deleted_jobs)`, @@ -836,7 +820,6 @@ func (o *orm) DeleteJob(ctx context.Context, id int32, jobType Type) error { id, ocr_oracle_spec_id, ocr2_oracle_spec_id, - keeper_spec_id, cre_settings_spec_id, cron_spec_id, flux_monitor_spec_id, @@ -1555,7 +1538,6 @@ func (o *orm) loadAllJobTypes(ctx context.Context, job *Job) error { o.loadJobType(ctx, job, "DirectRequestSpec", "direct_request_specs", job.DirectRequestSpecID), o.loadJobType(ctx, job, "OCROracleSpec", "ocr_oracle_specs", job.OCROracleSpecID), o.loadJobType(ctx, job, "OCR2OracleSpec", "ocr2_oracle_specs", job.OCR2OracleSpecID), - o.loadJobType(ctx, job, "KeeperSpec", "keeper_specs", job.KeeperSpecID), o.loadJobType(ctx, job, "CRESettingsSpec", "cre_settings_specs", job.CRESettingsSpecID), o.loadJobType(ctx, job, "CronSpec", "cron_specs", job.CronSpecID), o.loadJobType(ctx, job, "WebhookSpec", "webhook_specs", job.WebhookSpecID), diff --git a/core/services/job/validate.go b/core/services/job/validate.go index e4da7eb7d37..e058a577dde 100644 --- a/core/services/job/validate.go +++ b/core/services/job/validate.go @@ -20,7 +20,6 @@ var ( DirectRequest: {}, FluxMonitor: {}, Gateway: {}, - Keeper: {}, LegacyGasStationServer: {}, LegacyGasStationSidecar: {}, OffchainReporting2: {}, diff --git a/core/services/keeper/common.go b/core/services/keeper/common.go deleted file mode 100644 index d0c480c12d2..00000000000 --- a/core/services/keeper/common.go +++ /dev/null @@ -1,18 +0,0 @@ -package keeper - -import ( - "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_1" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_2" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_3" - "github.com/smartcontractkit/chainlink-evm/pkg/types" -) - -var Registry1_1ABI = types.MustGetABI(keeper_registry_wrapper1_1.KeeperRegistryABI) -var Registry1_2ABI = types.MustGetABI(keeper_registry_wrapper1_2.KeeperRegistryABI) -var Registry1_3ABI = types.MustGetABI(keeper_registry_wrapper1_3.KeeperRegistryABI) - -type RegistryGasChecker interface { - CheckGasOverhead() uint32 - PerformGasOverhead() uint32 - MaxPerformDataSize() uint32 -} diff --git a/core/services/keeper/delegate.go b/core/services/keeper/delegate.go deleted file mode 100644 index 958cc9d0219..00000000000 --- a/core/services/keeper/delegate.go +++ /dev/null @@ -1,141 +0,0 @@ -package keeper - -import ( - "context" - stderrors "errors" - "fmt" - - "github.com/pkg/errors" - - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" - "github.com/smartcontractkit/chainlink-evm/pkg/chains/legacyevm" - "github.com/smartcontractkit/chainlink/v2/core/config" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" -) - -// To make sure Delegate struct implements job.Delegate interface -var _ job.Delegate = (*Delegate)(nil) - -type DelegateConfig interface { - Keeper() config.Keeper -} - -type Delegate struct { - cfg DelegateConfig - logger logger.Logger - ds sqlutil.DataSource - jrm job.ORM - pr pipeline.Runner - legacyChains legacyevm.LegacyChainContainer - mailMon *mailbox.Monitor -} - -// NewDelegate is the constructor of Delegate -func NewDelegate( - cfg DelegateConfig, - ds sqlutil.DataSource, - jrm job.ORM, - pr pipeline.Runner, - logger logger.Logger, - legacyChains legacyevm.LegacyChainContainer, - mailMon *mailbox.Monitor, -) *Delegate { - return &Delegate{ - cfg: cfg, - logger: logger, - ds: ds, - jrm: jrm, - pr: pr, - legacyChains: legacyChains, - mailMon: mailMon, - } -} - -// JobType returns job type -func (d *Delegate) JobType() job.Type { - return job.Keeper -} - -func (d *Delegate) BeforeJobCreated(spec job.Job) {} -func (d *Delegate) AfterJobCreated(spec job.Job) {} -func (d *Delegate) BeforeJobDeleted(spec job.Job) {} -func (d *Delegate) OnDeleteJob(ctx context.Context, spec job.Job) error { return nil } - -// ServicesForSpec satisfies the job.Delegate interface. -func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services []job.ServiceCtx, err error) { - if spec.KeeperSpec == nil { - return nil, errors.Errorf("Delegate expects a *job.KeeperSpec to be present, got %v", spec) - } - chainService, err := d.legacyChains.Get(spec.KeeperSpec.EVMChainID.String()) - if err != nil { - return nil, err - } - chain, ok := chainService.(legacyevm.Chain) - if !ok { - return nil, fmt.Errorf("keeper is not available in LOOP Plugin mode: %w", stderrors.ErrUnsupported) - } - registryAddress := spec.KeeperSpec.ContractAddress - orm := NewORM(d.ds, d.logger) - svcLogger := d.logger.With( - "jobID", spec.ID, - "registryAddress", registryAddress.Hex(), - ) - - registryWrapper, err := NewRegistryWrapper(registryAddress, chain.Client()) - if err != nil { - return nil, errors.Wrap(err, "unable to create keeper registry wrapper") - } - svcLogger.Info("Registry version is: ", registryWrapper.Version) - - minIncomingConfirmations := chain.Config().EVM().MinIncomingConfirmations() - if spec.KeeperSpec.MinIncomingConfirmations != nil { - minIncomingConfirmations = *spec.KeeperSpec.MinIncomingConfirmations - } - - // effectiveKeeperAddress is the keeper address registered on the registry. This is by default the EOA account on the node. - // In the case of forwarding, the keeper address is the forwarder contract deployed onchain between EOA and Registry. - effectiveKeeperAddress := spec.KeeperSpec.FromAddress.Address() - if spec.ForwardingAllowed { - fwdrAddress, fwderr := chain.TxManager().GetForwarderForEOA(ctx, spec.KeeperSpec.FromAddress.Address()) - if fwderr == nil { - effectiveKeeperAddress = fwdrAddress - } else { - svcLogger.Warnw("Skipping forwarding for job, will fallback to default behavior", "job", spec.Name, "err", fwderr) - } - } - - keeper := d.cfg.Keeper() - registry := keeper.Registry() - registrySynchronizer := NewRegistrySynchronizer(RegistrySynchronizerOptions{ - Job: spec, - RegistryWrapper: *registryWrapper, - ORM: orm, - JRM: d.jrm, - LogBroadcaster: chain.LogBroadcaster(), - MailMon: d.mailMon, - SyncInterval: registry.SyncInterval(), - MinIncomingConfirmations: minIncomingConfirmations, - Logger: svcLogger, - SyncUpkeepQueueSize: registry.SyncUpkeepQueueSize(), - EffectiveKeeperAddress: effectiveKeeperAddress, - }) - upkeepExecuter := NewUpkeepExecuter( - spec, - orm, - d.pr, - chain.Client(), - chain.HeadBroadcaster(), - chain.GasEstimator(), - svcLogger, - d.cfg.Keeper(), - effectiveKeeperAddress, - ) - - return []job.ServiceCtx{ - registrySynchronizer, - upkeepExecuter, - }, nil -} diff --git a/core/services/keeper/errors.go b/core/services/keeper/errors.go deleted file mode 100644 index d003fcc9101..00000000000 --- a/core/services/keeper/errors.go +++ /dev/null @@ -1,7 +0,0 @@ -package keeper - -import "github.com/pkg/errors" - -var ( - ErrContractCallFailure = errors.New("failure in calling contract") -) diff --git a/core/services/keeper/helpers_test.go b/core/services/keeper/helpers_test.go deleted file mode 100644 index a10c3a48aff..00000000000 --- a/core/services/keeper/helpers_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package keeper - -import ( - "context" - "math/big" - - "github.com/ethereum/go-ethereum/core/types" - "github.com/pkg/errors" -) - -func (rs *RegistrySynchronizer) ExportedFullSync(ctx context.Context) { - rs.fullSync(ctx) -} - -func (rs *RegistrySynchronizer) ExportedProcessLogs(ctx context.Context) { - rs.processLogs(ctx) -} - -func (rw *RegistryWrapper) GetUpkeepIdFromRawRegistrationLog(rawLog types.Log) (*big.Int, error) { - switch rw.Version { - case RegistryVersion_1_0, RegistryVersion_1_1: - parsedLog, err := rw.contract1_1.ParseUpkeepRegistered(rawLog) - if err != nil { - return nil, errors.Wrap(err, "failed to get parse UpkeepRegistered log") - } - return parsedLog.Id, nil - case RegistryVersion_1_2: - parsedLog, err := rw.contract1_2.ParseUpkeepRegistered(rawLog) - if err != nil { - return nil, errors.Wrap(err, "failed to get parse UpkeepRegistered log") - } - return parsedLog.Id, nil - case RegistryVersion_1_3: - parsedLog, err := rw.contract1_3.ParseUpkeepRegistered(rawLog) - if err != nil { - return nil, errors.Wrap(err, "failed to get parse UpkeepRegistered log") - } - return parsedLog.Id, nil - default: - return nil, newUnsupportedVersionError("GetUpkeepIdFromRawRegistrationLog", rw.Version) - } -} diff --git a/core/services/keeper/integration_test.go b/core/services/keeper/integration_test.go deleted file mode 100644 index 9d83eeca254..00000000000 --- a/core/services/keeper/integration_test.go +++ /dev/null @@ -1,633 +0,0 @@ -package keeper_test - -import ( - "fmt" - "math/big" - "net/http" - "testing" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth/ethconfig" - "github.com/jmoiron/sqlx" - "github.com/onsi/gomega" - "github.com/pkg/errors" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/libocr/gethwrappers/link_token_interface" - "github.com/smartcontractkit/quarantine" - - commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink/v2/core/bridges" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - - "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/basic_upkeep_contract" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_logic1_3" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_1" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_2" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_3" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/mock_v3_aggregator_contract" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/operatorforwarder/generated/authorized_forwarder" - "github.com/smartcontractkit/chainlink-evm/pkg/assets" - "github.com/smartcontractkit/chainlink-evm/pkg/chains/legacyevm" - "github.com/smartcontractkit/chainlink-evm/pkg/client" - "github.com/smartcontractkit/chainlink-evm/pkg/forwarders" - evmtestutils "github.com/smartcontractkit/chainlink-evm/pkg/testutils" - evmtypes "github.com/smartcontractkit/chainlink-evm/pkg/types" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/keeper" - "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" - webpresenters "github.com/smartcontractkit/chainlink/v2/core/web/presenters" -) - -var ( - oneEth = big.NewInt(1000000000000000000) - tenEth = big.NewInt(0).Mul(oneEth, big.NewInt(10)) - oneHunEth = big.NewInt(0).Mul(oneEth, big.NewInt(100)) - - payload1 = common.Hex2Bytes("1234") - payload2 = common.Hex2Bytes("ABCD") - payload3 = common.Hex2Bytes("6789") -) - -func deployKeeperRegistry( - t *testing.T, - version keeper.RegistryVersion, - auth *bind.TransactOpts, - backend *client.SimulatedBackendClient, - linkAddr, linkFeedAddr, gasFeedAddr common.Address, -) (regAddr common.Address, wrapper *keeper.RegistryWrapper) { - switch version { - case keeper.RegistryVersion_1_1: - var err error - regAddr, _, _, err = keeper_registry_wrapper1_1.DeployKeeperRegistry( - auth, - backend, - linkAddr, - linkFeedAddr, - gasFeedAddr, - 250_000_000, - 0, - big.NewInt(1), - 20_000_000, - big.NewInt(3600), - 1, - big.NewInt(60000000000), - big.NewInt(20000000000000000), - ) - require.NoError(t, err) - case keeper.RegistryVersion_1_2: - var err error - regAddr, _, _, err = keeper_registry_wrapper1_2.DeployKeeperRegistry( - auth, - backend, - linkAddr, - linkFeedAddr, - gasFeedAddr, - keeper_registry_wrapper1_2.Config{ - PaymentPremiumPPB: 250_000_000, - FlatFeeMicroLink: 0, - BlockCountPerTurn: big.NewInt(1), - CheckGasLimit: 20_000_000, - StalenessSeconds: big.NewInt(3600), - GasCeilingMultiplier: 1, - MinUpkeepSpend: big.NewInt(0), - MaxPerformGas: 5_000_000, - FallbackGasPrice: big.NewInt(60000000000), - FallbackLinkPrice: big.NewInt(20000000000000000), - Transcoder: testutils.NewAddress(), - Registrar: testutils.NewAddress(), - }, - ) - require.NoError(t, err) - case keeper.RegistryVersion_1_3: - logicAddr, _, _, err := keeper_registry_logic1_3.DeployKeeperRegistryLogic( - auth, - backend, - 0, - big.NewInt(80000), - linkAddr, - linkFeedAddr, - gasFeedAddr) - require.NoError(t, err) - backend.Commit() - - regAddr, _, _, err = keeper_registry_wrapper1_3.DeployKeeperRegistry( - auth, - backend, - logicAddr, - keeper_registry_wrapper1_3.Config{ - PaymentPremiumPPB: 250_000_000, - FlatFeeMicroLink: 0, - BlockCountPerTurn: big.NewInt(1), - CheckGasLimit: 20_000_000, - StalenessSeconds: big.NewInt(3600), - GasCeilingMultiplier: 1, - MinUpkeepSpend: big.NewInt(0), - MaxPerformGas: 5_000_000, - FallbackGasPrice: big.NewInt(60000000000), - FallbackLinkPrice: big.NewInt(20000000000000000), - Transcoder: testutils.NewAddress(), - Registrar: testutils.NewAddress(), - }, - ) - require.NoError(t, err) - default: - panic(errors.Errorf("Deployment of registry verdion %d not defined", version)) - } - backend.Commit() - wrapper, err := keeper.NewRegistryWrapper(evmtypes.EIP55AddressFromAddress(regAddr), backend) - require.NoError(t, err) - return -} - -func getUpkeepIDFromTx(t *testing.T, registryWrapper *keeper.RegistryWrapper, registrationTx *types.Transaction, backend *client.SimulatedBackendClient) *big.Int { - receipt, err := backend.TransactionReceipt(testutils.Context(t), registrationTx.Hash()) - require.NoError(t, err) - upkeepID, err := registryWrapper.GetUpkeepIdFromRawRegistrationLog(*receipt.Logs[0]) - require.NoError(t, err) - return upkeepID -} - -func TestKeeperEthIntegration(t *testing.T) { - tests.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/DX-400") - - t.Parallel() - tests := []struct { - name string - eip1559 bool - registryVersion keeper.RegistryVersion - }{ - // name should be a valid ORM name, only containing alphanumeric/underscore - {"legacy_registry1_1", false, keeper.RegistryVersion_1_1}, - {"eip1559_registry1_1", true, keeper.RegistryVersion_1_1}, - {"legacy_registry1_2", false, keeper.RegistryVersion_1_2}, - {"eip1559_registry1_2", true, keeper.RegistryVersion_1_2}, - {"legacy_registry1_3", false, keeper.RegistryVersion_1_3}, - {"eip1559_registry1_3", true, keeper.RegistryVersion_1_3}, - } - - for _, tt := range tests { - test := tt - t.Run(test.name, func(t *testing.T) { - t.Parallel() - ctx := testutils.Context(t) - g := gomega.NewWithT(t) - - // setup node key - nodeKey := cltest.MustGenerateRandomKey(t) - nodeAddress := nodeKey.Address - nodeAddressEIP55 := evmtypes.EIP55AddressFromAddress(nodeAddress) - - // setup blockchain - sergey := evmtestutils.MustNewSimTransactor(t) // owns all the link - steve := evmtestutils.MustNewSimTransactor(t) // registry owner - carrol := evmtestutils.MustNewSimTransactor(t) // client - nelly := evmtestutils.MustNewSimTransactor(t) // other keeper operator 1 - nick := evmtestutils.MustNewSimTransactor(t) // other keeper operator 2 - genesisData := types.GenesisAlloc{ - sergey.From: {Balance: assets.Ether(1000).ToInt()}, - steve.From: {Balance: assets.Ether(1000).ToInt()}, - carrol.From: {Balance: assets.Ether(1000).ToInt()}, - nelly.From: {Balance: assets.Ether(1000).ToInt()}, - nick.From: {Balance: assets.Ether(1000).ToInt()}, - nodeAddress: {Balance: assets.Ether(1000).ToInt()}, - } - - b := cltest.NewSimulatedBackend(t, genesisData, 2*ethconfig.Defaults.Miner.GasCeil) - backend := client.NewSimulatedBackendClient(t, b, testutils.SimulatedChainID) - - _, stopMining := cltest.Mine(backend.Backend(), 1*time.Second) // >> 2 seconds and the test gets slow, << 1 second and the app may miss heads - defer stopMining() - - linkAddr, _, linkToken, err := link_token_interface.DeployLinkToken(sergey, backend) - require.NoError(t, err) - backend.Commit() - gasFeedAddr, _, _, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(steve, backend, 18, big.NewInt(60000000000)) - require.NoError(t, err) - backend.Commit() - linkFeedAddr, _, _, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(steve, backend, 18, big.NewInt(20000000000000000)) - require.NoError(t, err) - backend.Commit() - - regAddr, registryWrapper := deployKeeperRegistry(t, test.registryVersion, steve, backend, linkAddr, linkFeedAddr, gasFeedAddr) - - upkeepAddr, _, upkeepContract, err := basic_upkeep_contract.DeployBasicUpkeepContract(carrol, backend) - require.NoError(t, err) - _, err = linkToken.Transfer(sergey, carrol.From, oneHunEth) - require.NoError(t, err) - _, err = linkToken.Approve(carrol, regAddr, oneHunEth) - require.NoError(t, err) - _, err = registryWrapper.SetKeepers(steve, []common.Address{nodeAddress, nelly.From}, []common.Address{nodeAddress, nelly.From}) - require.NoError(t, err) - backend.Commit() - registrationTx, err := registryWrapper.RegisterUpkeep(steve, upkeepAddr, 2_500_000, carrol.From, []byte{}) - require.NoError(t, err) - backend.Commit() - upkeepID := getUpkeepIDFromTx(t, registryWrapper, registrationTx, backend) - - _, err = upkeepContract.SetBytesToSend(carrol, payload1) - require.NoError(t, err) - _, err = upkeepContract.SetShouldPerformUpkeep(carrol, true) - require.NoError(t, err) - _, err = registryWrapper.AddFunds(carrol, upkeepID, tenEth) - require.NoError(t, err) - backend.Commit() - - // setup app - config, db := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.EVM[0].GasEstimator.EIP1559DynamicFees = &test.eip1559 - c.Keeper.MaxGracePeriod = ptr[int64](0) // avoid waiting to re-submit for upkeeps - c.Keeper.Registry.SyncInterval = commonconfig.MustNewDuration(24 * time.Hour) // disable full sync ticker for test - - c.Keeper.TurnLookBack = ptr[int64](0) // testing doesn't need to do far look back - - c.EVM[0].BlockBackfillDepth = ptr[uint32](0) // backfill will trigger sync on startup - c.EVM[0].MinIncomingConfirmations = ptr[uint32](1) // disable reorg protection for this test - c.EVM[0].HeadTracker.MaxBufferSize = ptr[uint32](100) // helps prevent missed heads - }) - korm := keeper.NewORM(db, logger.TestLogger(t)) - - app := cltest.NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain(t, config, b, nodeKey) - require.NoError(t, app.Start(ctx)) - - // create job - regAddrEIP55 := evmtypes.EIP55AddressFromAddress(regAddr) - job := cltest.MustInsertKeeperJob(t, db, korm, nodeAddressEIP55, regAddrEIP55) - err = app.JobSpawner().StartService(ctx, job) - require.NoError(t, err) - - // keeper job is triggered and payload is received - receivedBytes := func() []byte { - received, err2 := upkeepContract.ReceivedBytes(nil) - require.NoError(t, err2) - return received - } - g.Eventually(receivedBytes, 20*time.Second, time.Second).Should(gomega.Equal(payload1)) - - // submit from other keeper (because keepers must alternate) - _, err = registryWrapper.PerformUpkeep(nelly, upkeepID, []byte{}) - require.NoError(t, err) - - // change payload - _, err = upkeepContract.SetBytesToSend(carrol, payload2) - require.NoError(t, err) - _, err = upkeepContract.SetShouldPerformUpkeep(carrol, true) - require.NoError(t, err) - - // observe 2nd job run and received payload changes - g.Eventually(receivedBytes, 20*time.Second, cltest.DBPollingInterval).Should(gomega.Equal(payload2)) - - // cancel upkeep - _, err = registryWrapper.CancelUpkeep(carrol, upkeepID) - require.NoError(t, err) - backend.Commit() - - cltest.WaitForCount(t, app.GetDB(), "upkeep_registrations", 0) - - // add new upkeep (same target contract) - registrationTx, err = registryWrapper.RegisterUpkeep(steve, upkeepAddr, 2_500_000, carrol.From, []byte{}) - require.NoError(t, err) - backend.Commit() - - upkeepID = getUpkeepIDFromTx(t, registryWrapper, registrationTx, backend) - _, err = upkeepContract.SetBytesToSend(carrol, payload3) - require.NoError(t, err) - _, err = upkeepContract.SetShouldPerformUpkeep(carrol, true) - require.NoError(t, err) - _, err = registryWrapper.AddFunds(carrol, upkeepID, tenEth) - require.NoError(t, err) - backend.Commit() - - // observe update - g.Eventually(receivedBytes, 20*time.Second, cltest.DBPollingInterval).Should(gomega.Equal(payload3)) - - // remove this node from keeper list - _, err = registryWrapper.SetKeepers(steve, []common.Address{nick.From, nelly.From}, []common.Address{nick.From, nelly.From}) - require.NoError(t, err) - - var registry keeper.Registry - require.NoError(t, app.GetDB().GetContext(ctx, ®istry, `SELECT * FROM keeper_registries`)) - cltest.AssertRecordEventually(t, app.GetDB(), ®istry, fmt.Sprintf("SELECT * FROM keeper_registries WHERE id = %d", registry.ID), func() bool { - return registry.KeeperIndex == -1 - }) - runs, err := app.PipelineORM().GetAllRuns(ctx) - require.NoError(t, err) - // Since we set grace period to 0, we can have more than 1 pipeline run per perform - // This happens in case we start a pipeline run before previous perform tx is committed to chain - require.GreaterOrEqual(t, len(runs), 3) - prr := webpresenters.NewPipelineRunResource(runs[0], logger.TestLogger(t)) - require.Len(t, prr.Outputs, 1) - require.Nil(t, prr.Outputs[0]) - }) - } -} - -func TestKeeperForwarderEthIntegration(t *testing.T) { - quarantine.Flaky(t, "DX-2042") - t.Parallel() - t.Run("keeper_forwarder_flow", func(t *testing.T) { - ctx := testutils.Context(t) - g := gomega.NewWithT(t) - - // setup node key - nodeKey := cltest.MustGenerateRandomKey(t) - nodeAddress := nodeKey.Address - nodeAddressEIP55 := evmtypes.EIP55AddressFromAddress(nodeAddress) - - // setup blockchain - sergey := evmtestutils.MustNewSimTransactor(t) // owns all the link - steve := evmtestutils.MustNewSimTransactor(t) // registry owner - carrol := evmtestutils.MustNewSimTransactor(t) // client - nelly := evmtestutils.MustNewSimTransactor(t) // other keeper operator 1 - nick := evmtestutils.MustNewSimTransactor(t) // other keeper operator 2 - genesisData := types.GenesisAlloc{ - sergey.From: {Balance: assets.Ether(1000).ToInt()}, - steve.From: {Balance: assets.Ether(1000).ToInt()}, - carrol.From: {Balance: assets.Ether(1000).ToInt()}, - nelly.From: {Balance: assets.Ether(1000).ToInt()}, - nick.From: {Balance: assets.Ether(1000).ToInt()}, - nodeAddress: {Balance: assets.Ether(1000).ToInt()}, - } - - b := cltest.NewSimulatedBackend(t, genesisData, 2*ethconfig.Defaults.Miner.GasCeil) - backend := client.NewSimulatedBackendClient(t, b, testutils.SimulatedChainID) - - commit, stopMining := cltest.Mine(backend.Backend(), 1*time.Second) // >> 2 seconds and the test gets slow, << 1 second and the app may miss heads - defer stopMining() - - linkAddr, _, linkToken, err := link_token_interface.DeployLinkToken(sergey, backend) - require.NoError(t, err) - commit() - gasFeedAddr, _, _, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(steve, backend, 18, big.NewInt(60000000000)) - require.NoError(t, err) - commit() - linkFeedAddr, _, _, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(steve, backend, 18, big.NewInt(20000000000000000)) - require.NoError(t, err) - commit() - - regAddr, registryWrapper := deployKeeperRegistry(t, keeper.RegistryVersion_1_3, steve, backend, linkAddr, linkFeedAddr, gasFeedAddr) - commit() - fwdrAddress, _, authorizedForwarder, err := authorized_forwarder.DeployAuthorizedForwarder(sergey, backend, linkAddr, sergey.From, steve.From, []byte{}) - require.NoError(t, err) - commit() - _, err = authorizedForwarder.SetAuthorizedSenders(sergey, []common.Address{nodeAddress}) - require.NoError(t, err) - commit() - - upkeepAddr, _, upkeepContract, err := basic_upkeep_contract.DeployBasicUpkeepContract(carrol, backend) - require.NoError(t, err) - commit() - _, err = linkToken.Transfer(sergey, carrol.From, oneHunEth) - require.NoError(t, err) - _, err = linkToken.Approve(carrol, regAddr, oneHunEth) - require.NoError(t, err) - _, err = registryWrapper.SetKeepers(steve, []common.Address{fwdrAddress, nelly.From}, []common.Address{nodeAddress, nelly.From}) - require.NoError(t, err) - registrationTx, err := registryWrapper.RegisterUpkeep(steve, upkeepAddr, 2_500_000, carrol.From, []byte{}) - require.NoError(t, err) - commit() - upkeepID := getUpkeepIDFromTx(t, registryWrapper, registrationTx, backend) - - _, err = upkeepContract.SetBytesToSend(carrol, payload1) - require.NoError(t, err) - _, err = upkeepContract.SetShouldPerformUpkeep(carrol, true) - require.NoError(t, err) - _, err = registryWrapper.AddFunds(carrol, upkeepID, tenEth) - require.NoError(t, err) - commit() - - // setup app - config, db := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Feature.LogPoller = ptr(true) - c.EVM[0].GasEstimator.EIP1559DynamicFees = ptr(true) - c.Keeper.MaxGracePeriod = ptr[int64](0) // avoid waiting to re-submit for upkeeps - c.Keeper.Registry.SyncInterval = commonconfig.MustNewDuration(24 * time.Hour) // disable full sync ticker for test - - c.Keeper.TurnLookBack = ptr[int64](0) // testing doesn't need to do far look back - - c.EVM[0].BlockBackfillDepth = ptr[uint32](0) // backfill will trigger sync on startup - c.EVM[0].MinIncomingConfirmations = ptr[uint32](1) // disable reorg protection for this test - c.EVM[0].HeadTracker.MaxBufferSize = ptr[uint32](100) // helps prevent missed heads - c.EVM[0].Transactions.ForwardersEnabled = ptr(true) // Enable Operator Forwarder flow - c.EVM[0].ChainID = (*sqlutil.Big)(testutils.SimulatedChainID) - }) - korm := keeper.NewORM(db, logger.TestLogger(t)) - - app := cltest.NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain(t, config, b, nodeKey) - require.NoError(t, app.Start(ctx)) - - forwarderORM := forwarders.NewORM(db) - chainID := sqlutil.Big(*backend.ConfiguredChainID()) - _, err = forwarderORM.CreateForwarder(ctx, fwdrAddress, chainID) - require.NoError(t, err) - - chain, ok := app.GetRelayers().LegacyEVMChains().Slice()[0].(legacyevm.Chain) - require.True(t, ok) - addr, err := chain.TxManager().GetForwarderForEOA(ctx, nodeAddress) - require.NoError(t, err) - require.Equal(t, addr, fwdrAddress) - - // create job - regAddrEIP55 := evmtypes.EIP55AddressFromAddress(regAddr) - - jb := job.Job{ - ID: 1, - Type: job.Keeper, - KeeperSpec: &job.KeeperSpec{ - FromAddress: nodeAddressEIP55, - ContractAddress: regAddrEIP55, - EVMChainID: (*sqlutil.Big)(testutils.SimulatedChainID), - }, - SchemaVersion: 1, - ForwardingAllowed: true, - } - err = app.JobORM().CreateJob(testutils.Context(t), &jb) - require.NoError(t, err) - - registry := keeper.Registry{ - ContractAddress: regAddrEIP55, - BlockCountPerTurn: 1, - CheckGas: 150_000, - FromAddress: nodeAddressEIP55, - JobID: jb.ID, - KeeperIndex: 0, - NumKeepers: 2, - KeeperIndexMap: map[evmtypes.EIP55Address]int32{ - nodeAddressEIP55: 0, - evmtypes.EIP55AddressFromAddress(nelly.From): 1, - }, - } - err = korm.UpsertRegistry(ctx, ®istry) - require.NoError(t, err) - - callOpts := bind.CallOpts{From: nodeAddress} - // Read last keeper on the upkeep contract - lastKeeper := func() common.Address { - upkeepCfg, err2 := registryWrapper.GetUpkeep(&callOpts, upkeepID) - require.NoError(t, err2) - return upkeepCfg.LastKeeper - } - require.Equal(t, common.Address{}, lastKeeper()) - - err = app.JobSpawner().StartService(ctx, jb) - require.NoError(t, err) - - // keeper job is triggered and payload is received - receivedBytes := func() []byte { - received, err2 := upkeepContract.ReceivedBytes(nil) - require.NoError(t, err2) - return received - } - g.Eventually(receivedBytes, 20*time.Second, time.Second).Should(gomega.Equal(payload1)) - - // Upkeep performed by the node through the forwarder - g.Eventually(lastKeeper, 20*time.Second, time.Second).Should(gomega.Equal(fwdrAddress)) - }) -} - -func TestMaxPerformDataSize(t *testing.T) { - t.Parallel() - t.Run("max_perform_data_size_test", func(t *testing.T) { - ctx := testutils.Context(t) - maxPerformDataSize := 1000 // Will be set as config override - g := gomega.NewWithT(t) - - // setup node key - nodeKey := cltest.MustGenerateRandomKey(t) - nodeAddress := nodeKey.Address - nodeAddressEIP55 := evmtypes.EIP55AddressFromAddress(nodeAddress) - - // setup blockchain - sergey := evmtestutils.MustNewSimTransactor(t) // owns all the link - steve := evmtestutils.MustNewSimTransactor(t) // registry owner - carrol := evmtestutils.MustNewSimTransactor(t) // client - nelly := evmtestutils.MustNewSimTransactor(t) // other keeper operator 1 - nick := evmtestutils.MustNewSimTransactor(t) // other keeper operator 2 - genesisData := types.GenesisAlloc{ - sergey.From: {Balance: assets.Ether(1000).ToInt()}, - steve.From: {Balance: assets.Ether(1000).ToInt()}, - carrol.From: {Balance: assets.Ether(1000).ToInt()}, - nelly.From: {Balance: assets.Ether(1000).ToInt()}, - nick.From: {Balance: assets.Ether(1000).ToInt()}, - nodeAddress: {Balance: assets.Ether(1000).ToInt()}, - } - - b := cltest.NewSimulatedBackend(t, genesisData, 2*ethconfig.Defaults.Miner.GasCeil) - backend := client.NewSimulatedBackendClient(t, b, testutils.SimulatedChainID) - - commit, stopMining := cltest.Mine(backend.Backend(), 1*time.Second) // >> 2 seconds and the test gets slow, << 1 second and the app may miss heads - defer stopMining() - - linkAddr, _, linkToken, err := link_token_interface.DeployLinkToken(sergey, backend) - require.NoError(t, err) - commit() - gasFeedAddr, _, _, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(steve, backend, 18, big.NewInt(60000000000)) - require.NoError(t, err) - commit() - linkFeedAddr, _, _, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(steve, backend, 18, big.NewInt(20000000000000000)) - require.NoError(t, err) - commit() - - regAddr, registryWrapper := deployKeeperRegistry(t, keeper.RegistryVersion_1_3, steve, backend, linkAddr, linkFeedAddr, gasFeedAddr) - - upkeepAddr, _, upkeepContract, err := basic_upkeep_contract.DeployBasicUpkeepContract(carrol, backend) - require.NoError(t, err) - commit() - _, err = linkToken.Transfer(sergey, carrol.From, oneHunEth) - require.NoError(t, err) - _, err = linkToken.Approve(carrol, regAddr, oneHunEth) - require.NoError(t, err) - _, err = registryWrapper.SetKeepers(steve, []common.Address{nodeAddress, nelly.From}, []common.Address{nodeAddress, nelly.From}) - require.NoError(t, err) - commit() - registrationTx, err := registryWrapper.RegisterUpkeep(steve, upkeepAddr, 2_500_000, carrol.From, []byte{}) - require.NoError(t, err) - commit() - upkeepID := getUpkeepIDFromTx(t, registryWrapper, registrationTx, backend) - - _, err = registryWrapper.AddFunds(carrol, upkeepID, tenEth) - require.NoError(t, err) - commit() - - // setup app - config, db := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Keeper.MaxGracePeriod = ptr[int64](0) // avoid waiting to re-submit for upkeeps - c.Keeper.Registry.SyncInterval = commonconfig.MustNewDuration(24 * time.Hour) // disable full sync ticker for test - c.Keeper.Registry.MaxPerformDataSize = ptr(uint32(maxPerformDataSize)) // set the max perform data size - - c.Keeper.TurnLookBack = ptr[int64](0) // testing doesn't need to do far look back - - c.EVM[0].BlockBackfillDepth = ptr[uint32](0) // backfill will trigger sync on startup - c.EVM[0].MinIncomingConfirmations = ptr[uint32](1) // disable reorg protection for this test - c.EVM[0].HeadTracker.MaxBufferSize = ptr[uint32](100) // helps prevent missed heads - }) - korm := keeper.NewORM(db, logger.TestLogger(t)) - - app := cltest.NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain(t, config, b, nodeKey) - require.NoError(t, app.Start(ctx)) - - // create job - regAddrEIP55 := evmtypes.EIP55AddressFromAddress(regAddr) - job := cltest.MustInsertKeeperJob(t, db, korm, nodeAddressEIP55, regAddrEIP55) - err = app.JobSpawner().StartService(ctx, job) - require.NoError(t, err) - - // keeper job is triggered - receivedBytes := func() []byte { - received, err2 := upkeepContract.ReceivedBytes(nil) - require.NoError(t, err2) - return received - } - - hugePayload := make([]byte, maxPerformDataSize) - _, err = upkeepContract.SetBytesToSend(carrol, hugePayload) - require.NoError(t, err) - _, err = upkeepContract.SetShouldPerformUpkeep(carrol, true) - require.NoError(t, err) - commit() - - // Huge payload should not result in a perform - g.Consistently(receivedBytes, 20*time.Second, cltest.DBPollingInterval).Should(gomega.Equal([]byte{})) - - // Set payload to be small and it should get received - smallPayload := make([]byte, maxPerformDataSize-1) - _, err = upkeepContract.SetBytesToSend(carrol, smallPayload) - require.NoError(t, err) - commit() - g.Eventually(receivedBytes, 20*time.Second, cltest.DBPollingInterval).Should(gomega.Equal(smallPayload)) - }) -} - -type JobPipelineV2TestHelper struct { - Prm pipeline.ORM - Jrm job.ORM - Pr pipeline.Runner -} - -type JobPipelineConfig interface { - pipeline.Config - MaxSuccessfulRuns() uint64 -} - -func NewJobPipelineV2(t testing.TB, cfg pipeline.BridgeConfig, jpcfg JobPipelineConfig, legacyChains legacyevm.LegacyChainContainer, db *sqlx.DB, keyStore keystore.Master, restrictedHTTPClient, unrestrictedHTTPClient *http.Client) JobPipelineV2TestHelper { - lggr := logger.TestLogger(t) - prm := pipeline.NewORM(db, lggr, jpcfg.MaxSuccessfulRuns()) - btORM := bridges.NewORM(db) - jrm := job.NewORM(db, prm, btORM, keyStore, lggr) - pr := pipeline.NewRunner(prm, btORM, jpcfg, cfg, legacyChains, keyStore.Eth(), keyStore.VRF(), lggr, restrictedHTTPClient, unrestrictedHTTPClient) - return JobPipelineV2TestHelper{ - prm, - jrm, - pr, - } -} diff --git a/core/services/keeper/models.go b/core/services/keeper/models.go deleted file mode 100644 index 2d2def0f8f9..00000000000 --- a/core/services/keeper/models.go +++ /dev/null @@ -1,79 +0,0 @@ -package keeper - -import ( - "database/sql/driver" - "encoding/hex" - "encoding/json" - "fmt" - - "github.com/pkg/errors" - - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - "github.com/smartcontractkit/chainlink-evm/pkg/types" - "github.com/smartcontractkit/chainlink-evm/pkg/utils" - "github.com/smartcontractkit/chainlink/v2/core/null" -) - -type KeeperIndexMap map[types.EIP55Address]int32 - -type Registry struct { - ID int64 - BlockCountPerTurn int32 - CheckGas uint32 - ContractAddress types.EIP55Address - FromAddress types.EIP55Address - JobID int32 - KeeperIndex int32 - NumKeepers int32 - KeeperIndexMap KeeperIndexMap -} - -type UpkeepRegistration struct { - ID int32 - CheckData []byte - ExecuteGas uint32 - LastRunBlockHeight int64 - RegistryID int64 - Registry Registry - UpkeepID *sqlutil.Big - LastKeeperIndex null.Int64 - PositioningConstant int32 -} - -func (k *KeeperIndexMap) Scan(val any) error { - switch v := val.(type) { - case []byte: - err := json.Unmarshal(v, &k) - return err - case string: - err := json.Unmarshal([]byte(v), &k) - return err - default: - return fmt.Errorf("unsupported type: %T", v) - } -} - -func (k *KeeperIndexMap) Value() (driver.Value, error) { - return json.Marshal(&k) -} - -func (upkeep UpkeepRegistration) PrettyID() string { - return NewUpkeepIdentifier(upkeep.UpkeepID).String() -} - -func NewUpkeepIdentifier(i *sqlutil.Big) *UpkeepIdentifier { - val := UpkeepIdentifier(*i) - return &val -} - -type UpkeepIdentifier sqlutil.Big - -// String produces a hex encoded value, zero padded, prefixed with UpkeepPrefix -func (ui UpkeepIdentifier) String() string { - val := sqlutil.Big(ui) - result, err := utils.Uint256ToBytes(val.ToInt()) - if err != nil { - panic(errors.Wrap(err, "invariant, invalid upkeepID")) - } - return fmt.Sprintf("%s%s", UpkeepPrefix, hex.EncodeToString(result)) -} diff --git a/core/services/keeper/models_test.go b/core/services/keeper/models_test.go deleted file mode 100644 index e1d56e7b696..00000000000 --- a/core/services/keeper/models_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package keeper - -import ( - "math/big" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" -) - -func TestUpkeepIdentifer_String(t *testing.T) { - for _, test := range []struct { - name string - id string - hex string - }{ - {"small", "10", "UPx000000000000000000000000000000000000000000000000000000000000000a"}, - {"large", "1000000000", "UPx000000000000000000000000000000000000000000000000000000003b9aca00"}, - {"big", "5032485723458348569331745", "UPx0000000000000000000000000000000000000000000429ab990419450db80821"}, - } { - t.Run(test.name, func(t *testing.T) { - o, ok := new(big.Int).SetString(test.id, 10) - if !ok { - t.Errorf("%s failed to parse test integer", test.name) - return - } - - result := NewUpkeepIdentifier(sqlutil.New(o)).String() - require.Equal(t, test.hex, result) - }) - } -} diff --git a/core/services/keeper/orm.go b/core/services/keeper/orm.go deleted file mode 100644 index 0a80ba3453d..00000000000 --- a/core/services/keeper/orm.go +++ /dev/null @@ -1,241 +0,0 @@ -package keeper - -import ( - "context" - "math/rand" - - "github.com/lib/pq" - "github.com/pkg/errors" - - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - - "github.com/smartcontractkit/chainlink-evm/pkg/types" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -// ORM implements ORM layer using PostgreSQL -type ORM struct { - ds sqlutil.DataSource - logger logger.Logger -} - -// NewORM is the constructor of postgresORM -func NewORM(ds sqlutil.DataSource, lggr logger.Logger) *ORM { - lggr = lggr.Named("KeeperORM") - return &ORM{ - ds: ds, - logger: lggr, - } -} - -func (o *ORM) DataSource() sqlutil.DataSource { - return o.ds -} - -// Registries returns all registries -func (o *ORM) Registries(ctx context.Context) ([]Registry, error) { - var registries []Registry - err := o.ds.SelectContext(ctx, ®istries, `SELECT * FROM keeper_registries ORDER BY id ASC`) - return registries, errors.Wrap(err, "failed to get registries") -} - -// RegistryByContractAddress returns a single registry based on provided address -func (o *ORM) RegistryByContractAddress(ctx context.Context, registryAddress types.EIP55Address) (Registry, error) { - var registry Registry - err := o.ds.GetContext(ctx, ®istry, `SELECT * FROM keeper_registries WHERE keeper_registries.contract_address = $1`, registryAddress) - return registry, errors.Wrap(err, "failed to get registry") -} - -// RegistryForJob returns a specific registry for a job with the given ID -func (o *ORM) RegistryForJob(ctx context.Context, jobID int32) (Registry, error) { - var registry Registry - err := o.ds.GetContext(ctx, ®istry, `SELECT * FROM keeper_registries WHERE job_id = $1 LIMIT 1`, jobID) - return registry, errors.Wrapf(err, "failed to get registry with job_id %d", jobID) -} - -// UpsertRegistry upserts registry by the given input -func (o *ORM) UpsertRegistry(ctx context.Context, registry *Registry) error { - stmt := ` -INSERT INTO keeper_registries (job_id, keeper_index, contract_address, from_address, check_gas, block_count_per_turn, num_keepers, keeper_index_map) VALUES ( -:job_id, :keeper_index, :contract_address, :from_address, :check_gas, :block_count_per_turn, :num_keepers, :keeper_index_map -) ON CONFLICT (job_id) DO UPDATE SET - keeper_index = :keeper_index, - check_gas = :check_gas, - block_count_per_turn = :block_count_per_turn, - num_keepers = :num_keepers, - keeper_index_map = :keeper_index_map -RETURNING * -` - query, args, err := o.ds.BindNamed(stmt, registry) - if err != nil { - return errors.Wrap(err, "failed to upsert registry") - } - err = o.ds.GetContext(ctx, registry, query, args...) - return errors.Wrap(err, "failed to upsert registry") -} - -// UpsertUpkeep upserts upkeep by the given input -func (o *ORM) UpsertUpkeep(ctx context.Context, registration *UpkeepRegistration) error { - stmt := ` -INSERT INTO upkeep_registrations (registry_id, execute_gas, check_data, upkeep_id, positioning_constant, last_run_block_height) VALUES ( -:registry_id, :execute_gas, :check_data, :upkeep_id, :positioning_constant, :last_run_block_height -) ON CONFLICT (registry_id, upkeep_id) DO UPDATE SET - execute_gas = :execute_gas, - check_data = :check_data, - positioning_constant = :positioning_constant -RETURNING * -` - query, args, err := o.ds.BindNamed(stmt, registration) - if err != nil { - return errors.Wrap(err, "failed to upsert upkeep") - } - err = o.ds.GetContext(ctx, registration, query, args...) - return errors.Wrap(err, "failed to upsert upkeep") -} - -// UpdateUpkeepLastKeeperIndex updates the last keeper index for an upkeep -func (o *ORM) UpdateUpkeepLastKeeperIndex(ctx context.Context, jobID int32, upkeepID *sqlutil.Big, fromAddress types.EIP55Address) error { - _, err := o.ds.ExecContext(ctx, ` - UPDATE upkeep_registrations - SET - last_keeper_index = CAST((SELECT keeper_index_map -> $3 FROM keeper_registries WHERE job_id = $1) AS int) - WHERE upkeep_id = $2 AND - registry_id = (SELECT id FROM keeper_registries WHERE job_id = $1)`, - jobID, upkeepID, fromAddress.Hex()) - return errors.Wrap(err, "UpdateUpkeepLastKeeperIndex failed") -} - -// BatchDeleteUpkeepsForJob deletes all upkeeps by the given IDs for the job with the given ID -func (o *ORM) BatchDeleteUpkeepsForJob(ctx context.Context, jobID int32, upkeepIDs []sqlutil.Big) (int64, error) { - strIds := []string{} - for _, upkeepID := range upkeepIDs { - strIds = append(strIds, upkeepID.String()) - } - res, err := o.ds.ExecContext(ctx, ` -DELETE FROM upkeep_registrations WHERE registry_id IN ( - SELECT id FROM keeper_registries WHERE job_id = $1 -) AND upkeep_id = ANY($2) -`, jobID, strIds) - if err != nil { - return 0, errors.Wrap(err, "BatchDeleteUpkeepsForJob failed to delete") - } - rowsAffected, err := res.RowsAffected() - if err != nil { - return 0, errors.Wrap(err, "BatchDeleteUpkeepsForJob failed to get RowsAffected") - } - return rowsAffected, nil -} - -// EligibleUpkeepsForRegistry fetches eligible upkeeps for processing -// The query checks the following conditions -// - checks the registry address is correct and the registry has some keepers associated -// -- is it my turn AND my keeper was not the last perform for this upkeep OR my keeper was the last before BUT it is past the grace period -// -- OR is it my buddy's turn AND they were the last keeper to do the perform for this upkeep -// DEV: note we cast upkeep_id and binaryHash as 32 bits, even though both are 256 bit numbers when performing XOR. This is enough information -// to distribute the upkeeps over the keepers so long as num keepers < 4294967296 -func (o *ORM) EligibleUpkeepsForRegistry(ctx context.Context, registryAddress types.EIP55Address, blockNumber int64, gracePeriod int64, binaryHash string) (upkeeps []UpkeepRegistration, err error) { - stmt := ` -SELECT upkeep_registrations.* -FROM upkeep_registrations - INNER JOIN keeper_registries ON keeper_registries.id = upkeep_registrations.registry_id, - LATERAL ABS( - (least_significant(uint256_to_bit(upkeep_registrations.upkeep_id), 32) # least_significant($4, 32))::bigint - ) AS turn -WHERE keeper_registries.contract_address = $1 - AND keeper_registries.num_keepers > 0 - AND - ( - ( - -- my turn - keeper_registries.keeper_index = turn % keeper_registries.num_keepers - AND - ( - -- last keeper != me - upkeep_registrations.last_keeper_index IS DISTINCT FROM keeper_registries.keeper_index - OR - -- last keeper == me AND its past the grace period - (upkeep_registrations.last_keeper_index IS NOT DISTINCT FROM - keeper_registries.keeper_index AND - upkeep_registrations.last_run_block_height + $2 < $3) - ) - ) - OR - ( - -- my buddy's turn - (keeper_registries.keeper_index + 1) % keeper_registries.num_keepers = - turn % keeper_registries.num_keepers - AND - -- last keeper == my buddy - upkeep_registrations.last_keeper_index IS NOT DISTINCT FROM - (keeper_registries.keeper_index + 1) % keeper_registries.num_keepers - -- buddy system only active if we have multiple keeper nodes - AND keeper_registries.num_keepers > 1 - ) - ) -` - if err = o.ds.SelectContext(ctx, &upkeeps, stmt, registryAddress, gracePeriod, blockNumber, binaryHash); err != nil { - return upkeeps, errors.Wrap(err, "EligibleUpkeepsForRegistry failed to get upkeep_registrations") - } - if err = o.loadUpkeepsRegistry(ctx, upkeeps); err != nil { - return upkeeps, errors.Wrap(err, "EligibleUpkeepsForRegistry failed to load Registry on upkeeps") - } - - rand.Shuffle(len(upkeeps), func(i, j int) { - upkeeps[i], upkeeps[j] = upkeeps[j], upkeeps[i] - }) - - return upkeeps, err -} - -func (o *ORM) loadUpkeepsRegistry(ctx context.Context, upkeeps []UpkeepRegistration) error { - registryIDM := make(map[int64]*Registry) - var registryIDs []int64 - for _, upkeep := range upkeeps { - if _, exists := registryIDM[upkeep.RegistryID]; !exists { - registryIDM[upkeep.RegistryID] = new(Registry) - registryIDs = append(registryIDs, upkeep.RegistryID) - } - } - var registries []*Registry - err := o.ds.SelectContext(ctx, ®istries, `SELECT * FROM keeper_registries WHERE id = ANY($1)`, pq.Array(registryIDs)) - if err != nil { - return errors.Wrap(err, "loadUpkeepsRegistry failed") - } - for _, reg := range registries { - registryIDM[reg.ID] = reg - } - for i, upkeep := range upkeeps { - upkeeps[i].Registry = *registryIDM[upkeep.RegistryID] - } - return nil -} - -func (o *ORM) AllUpkeepIDsForRegistry(ctx context.Context, regID int64) (upkeeps []sqlutil.Big, err error) { - err = o.ds.SelectContext(ctx, &upkeeps, ` -SELECT upkeep_id -FROM upkeep_registrations -WHERE registry_id = $1 -`, regID) - return upkeeps, errors.Wrap(err, "allUpkeepIDs failed") -} - -// SetLastRunInfoForUpkeepOnJob sets the last run block height and the associated keeper index only if the new block height is greater than the previous. -func (o *ORM) SetLastRunInfoForUpkeepOnJob(ctx context.Context, jobID int32, upkeepID *sqlutil.Big, height int64, fromAddress types.EIP55Address) (int64, error) { - res, err := o.ds.ExecContext(ctx, ` - UPDATE upkeep_registrations - SET last_run_block_height = $1, - last_keeper_index = CAST((SELECT keeper_index_map -> $4 FROM keeper_registries WHERE job_id = $3) AS int) - WHERE upkeep_id = $2 AND - registry_id = (SELECT id FROM keeper_registries WHERE job_id = $3) AND - last_run_block_height <= $1`, height, upkeepID, jobID, fromAddress.Hex()) - - if err != nil { - return 0, errors.Wrap(err, "SetLastRunInfoForUpkeepOnJob failed") - } - - rowsAffected, err := res.RowsAffected() - if err != nil { - return 0, errors.Wrap(err, "SetLastRunInfoForUpkeepOnJob failed to get RowsAffected") - } - return rowsAffected, nil -} diff --git a/core/services/keeper/orm_test.go b/core/services/keeper/orm_test.go deleted file mode 100644 index c9299e9916e..00000000000 --- a/core/services/keeper/orm_test.go +++ /dev/null @@ -1,534 +0,0 @@ -package keeper_test - -import ( - "fmt" - "math/big" - "sort" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/jmoiron/sqlx" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" - "github.com/smartcontractkit/chainlink-evm/pkg/types" - evmutils "github.com/smartcontractkit/chainlink-evm/pkg/utils" - - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - "github.com/smartcontractkit/chainlink/v2/core/services/keeper" - "github.com/smartcontractkit/chainlink/v2/core/utils" -) - -var ( - checkData = common.Hex2Bytes("ABC123") - executeGas = uint32(10_000) -) - -func setupKeeperDB(t *testing.T) ( - *sqlx.DB, - chainlink.GeneralConfig, - *keeper.ORM, -) { - cfg := configtest.NewGeneralConfig(t, nil) - db := pgtest.NewSqlxDB(t) - orm := keeper.NewORM(db, logger.TestLogger(t)) - return db, cfg, orm -} - -func newUpkeep(registry keeper.Registry, upkeepID int64) keeper.UpkeepRegistration { - return keeper.UpkeepRegistration{ - UpkeepID: sqlutil.NewI(upkeepID), - ExecuteGas: executeGas, - Registry: registry, - RegistryID: registry.ID, - CheckData: checkData, - } -} - -func waitLastRunHeight(t *testing.T, db *sqlx.DB, upkeep keeper.UpkeepRegistration, height int64) { - t.Helper() - - require.Eventually(t, func() bool { - err := db.Get(&upkeep, `SELECT * FROM upkeep_registrations WHERE id = $1`, upkeep.ID) - require.NoError(t, err) - return upkeep.LastRunBlockHeight == height - }, time.Second*2, time.Millisecond*100) -} - -func assertLastRunHeight(t *testing.T, db *sqlx.DB, upkeep keeper.UpkeepRegistration, lastRunBlockHeight int64, lastKeeperIndex int64) { - err := db.Get(&upkeep, `SELECT * FROM upkeep_registrations WHERE id = $1`, upkeep.ID) - require.NoError(t, err) - require.Equal(t, lastRunBlockHeight, upkeep.LastRunBlockHeight) - require.Equal(t, lastKeeperIndex, upkeep.LastKeeperIndex.Int64) -} - -func TestKeeperDB_Registries(t *testing.T) { - t.Parallel() - ctx := testutils.Context(t) - db, _, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - - cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 1, 20) - cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 1, 20) - - existingRegistries, err := orm.Registries(ctx) - require.NoError(t, err) - require.Len(t, existingRegistries, 2) -} - -func TestKeeperDB_RegistryByContractAddress(t *testing.T) { - t.Parallel() - ctx := testutils.Context(t) - db, _, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - - registry, _ := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 1, 20) - cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 1, 20) - - registryByContractAddress, err := orm.RegistryByContractAddress(ctx, registry.ContractAddress) - require.NoError(t, err) - require.Equal(t, registry, registryByContractAddress) -} - -func TestKeeperDB_UpsertUpkeep(t *testing.T) { - t.Parallel() - ctx := testutils.Context(t) - db, _, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - - registry, _ := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 1, 20) - upkeep := keeper.UpkeepRegistration{ - UpkeepID: sqlutil.NewI(0), - ExecuteGas: executeGas, - Registry: registry, - RegistryID: registry.ID, - CheckData: checkData, - LastRunBlockHeight: 1, - PositioningConstant: 1, - } - require.NoError(t, orm.UpsertUpkeep(ctx, &upkeep)) - cltest.AssertCount(t, db, "upkeep_registrations", 1) - - // update upkeep - upkeep.ExecuteGas = 20_000 - upkeep.CheckData = common.Hex2Bytes("8888") - upkeep.LastRunBlockHeight = 2 - - err := orm.UpsertUpkeep(ctx, &upkeep) - require.NoError(t, err) - cltest.AssertCount(t, db, "upkeep_registrations", 1) - - var upkeepFromDB keeper.UpkeepRegistration - err = db.Get(&upkeepFromDB, `SELECT * FROM upkeep_registrations ORDER BY id LIMIT 1`) - require.NoError(t, err) - require.Equal(t, uint32(20_000), upkeepFromDB.ExecuteGas) - require.Equal(t, "8888", common.Bytes2Hex(upkeepFromDB.CheckData)) - require.Equal(t, int64(1), upkeepFromDB.LastRunBlockHeight) // shouldn't change on upsert -} - -func TestKeeperDB_BatchDeleteUpkeepsForJob(t *testing.T) { - t.Parallel() - ctx := testutils.Context(t) - db, _, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - - registry, job := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 1, 20) - - expectedUpkeepID := cltest.MustInsertUpkeepForRegistry(t, db, registry).UpkeepID - var upkeepIDs []sqlutil.Big - for range 2 { - upkeep := cltest.MustInsertUpkeepForRegistry(t, db, registry) - upkeepIDs = append(upkeepIDs, *upkeep.UpkeepID) - } - - cltest.AssertCount(t, db, "upkeep_registrations", 3) - - _, err := orm.BatchDeleteUpkeepsForJob(ctx, job.ID, upkeepIDs) - require.NoError(t, err) - cltest.AssertCount(t, db, "upkeep_registrations", 1) - - var remainingUpkeep keeper.UpkeepRegistration - err = db.Get(&remainingUpkeep, `SELECT * FROM upkeep_registrations ORDER BY id LIMIT 1`) - require.NoError(t, err) - require.Equal(t, expectedUpkeepID, remainingUpkeep.UpkeepID) -} - -func TestKeeperDB_EligibleUpkeeps_Shuffle(t *testing.T) { - t.Parallel() - ctx := testutils.Context(t) - db, _, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - - blockheight := int64(63) - gracePeriod := int64(10) - - registry, _ := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 1, 20) - - ordered := [100]int64{} - for i := range 100 { - k := newUpkeep(registry, int64(i)) - ordered[i] = int64(i) - err := orm.UpsertUpkeep(ctx, &k) - require.NoError(t, err) - } - cltest.AssertCount(t, db, "upkeep_registrations", 100) - - eligibleUpkeeps, err := orm.EligibleUpkeepsForRegistry(ctx, registry.ContractAddress, blockheight, gracePeriod, fmt.Sprintf("%b", evmutils.NewHash().Big())) - assert.NoError(t, err) - - require.Len(t, eligibleUpkeeps, 100) - shuffled := [100]*sqlutil.Big{} - for i := range 100 { - shuffled[i] = eligibleUpkeeps[i].UpkeepID - } - assert.NotEqualValues(t, ordered, shuffled) -} - -func TestKeeperDB_NewEligibleUpkeeps_GracePeriod(t *testing.T) { - t.Parallel() - ctx := testutils.Context(t) - db, _, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - - registry, _ := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 2, 20) - - for range 100 { - cltest.MustInsertUpkeepForRegistry(t, db, registry) - } - - cltest.AssertCount(t, db, "keeper_registries", 1) - cltest.AssertCount(t, db, "upkeep_registrations", 100) - - // if current keeper index = 0 and all upkeeps last perform was done by index = 0 and still within grace period - upkeep := keeper.UpkeepRegistration{} - require.NoError(t, db.Get(&upkeep, `UPDATE upkeep_registrations SET last_keeper_index = 0, last_run_block_height = 10 RETURNING *`)) - list0, err := orm.EligibleUpkeepsForRegistry(ctx, registry.ContractAddress, 21, 100, fmt.Sprintf("%b", evmutils.NewHash().Big())) // none eligible - require.NoError(t, err) - require.Empty(t, list0, "should be 0 as all last perform was done by current node") - - // once passed grace period - list1, err := orm.EligibleUpkeepsForRegistry(ctx, registry.ContractAddress, 121, 100, fmt.Sprintf("%b", evmutils.NewHash().Big())) // none eligible - require.NoError(t, err) - require.NotEmpty(t, list1, "should get some eligible upkeeps now that they are outside grace period") -} - -func TestKeeperDB_EligibleUpkeeps_TurnsRandom(t *testing.T) { - t.Parallel() - ctx := testutils.Context(t) - db, _, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - - registry, _ := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 3, 10) - - for range 1000 { - cltest.MustInsertUpkeepForRegistry(t, db, registry) - } - - cltest.AssertCount(t, db, "keeper_registries", 1) - cltest.AssertCount(t, db, "upkeep_registrations", 1000) - - // 3 keepers 10 block turns should be different every turn - list1, err := orm.EligibleUpkeepsForRegistry(ctx, registry.ContractAddress, 20, 100, fmt.Sprintf("%b", evmutils.NewHash().Big())) - require.NoError(t, err) - list2, err := orm.EligibleUpkeepsForRegistry(ctx, registry.ContractAddress, 31, 100, fmt.Sprintf("%b", evmutils.NewHash().Big())) - require.NoError(t, err) - list3, err := orm.EligibleUpkeepsForRegistry(ctx, registry.ContractAddress, 42, 100, fmt.Sprintf("%b", evmutils.NewHash().Big())) - require.NoError(t, err) - list4, err := orm.EligibleUpkeepsForRegistry(ctx, registry.ContractAddress, 53, 100, fmt.Sprintf("%b", evmutils.NewHash().Big())) - require.NoError(t, err) - - // sort before compare - sort.Slice(list1, func(i, j int) bool { - return list1[i].UpkeepID.ToInt().Cmp(list1[j].UpkeepID.ToInt()) == -1 - }) - sort.Slice(list2, func(i, j int) bool { - return list2[i].UpkeepID.ToInt().Cmp(list2[j].UpkeepID.ToInt()) == -1 - }) - sort.Slice(list3, func(i, j int) bool { - return list3[i].UpkeepID.ToInt().Cmp(list3[j].UpkeepID.ToInt()) == -1 - }) - sort.Slice(list4, func(i, j int) bool { - return list4[i].UpkeepID.ToInt().Cmp(list4[j].UpkeepID.ToInt()) == -1 - }) - - assert.NotEqual(t, list1, list2, "list1 vs list2") - assert.NotEqual(t, list1, list3, "list1 vs list3") - assert.NotEqual(t, list1, list4, "list1 vs list4") -} - -func TestKeeperDB_NewEligibleUpkeeps_SkipIfLastPerformedByCurrentKeeper(t *testing.T) { - t.Parallel() - ctx := testutils.Context(t) - db, _, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - - registry, _ := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 2, 20) - - for range 100 { - cltest.MustInsertUpkeepForRegistry(t, db, registry) - } - - cltest.AssertCount(t, db, "keeper_registries", 1) - cltest.AssertCount(t, db, "upkeep_registrations", 100) - - // if current keeper index = 0 and all upkeeps last perform was done by index = 0 then skip as it would not pass required turn taking - upkeep := keeper.UpkeepRegistration{} - require.NoError(t, db.Get(&upkeep, `UPDATE upkeep_registrations SET last_keeper_index = 0 RETURNING *`)) - list0, err := orm.EligibleUpkeepsForRegistry(ctx, registry.ContractAddress, 21, 100, fmt.Sprintf("%b", evmutils.NewHash().Big())) // none eligible - require.NoError(t, err) - require.Empty(t, list0, "should be 0 as all last perform was done by current node") -} - -func TestKeeperDB_NewEligibleUpkeeps_CoverBuddy(t *testing.T) { - t.Parallel() - ctx := testutils.Context(t) - db, _, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - - registry, _ := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 1, 2, 20) - - for range 100 { - cltest.MustInsertUpkeepForRegistry(t, db, registry) - } - - cltest.AssertCount(t, db, "keeper_registries", 1) - cltest.AssertCount(t, db, "upkeep_registrations", 100) - - upkeep := keeper.UpkeepRegistration{} - binaryHash := fmt.Sprintf("%b", evmutils.NewHash().Big()) - listBefore, err := orm.EligibleUpkeepsForRegistry(ctx, registry.ContractAddress, 21, 100, binaryHash) // normal - require.NoError(t, err) - require.NoError(t, db.Get(&upkeep, `UPDATE upkeep_registrations SET last_keeper_index = 0 RETURNING *`)) - listAfter, err := orm.EligibleUpkeepsForRegistry(ctx, registry.ContractAddress, 21, 100, binaryHash) // covering buddy - require.NoError(t, err) - require.Greater(t, len(listAfter), len(listBefore), "after our buddy runs all the performs we should have more eligible then a normal turn") -} - -func TestKeeperDB_NewEligibleUpkeeps_FirstTurn(t *testing.T) { - t.Parallel() - ctx := testutils.Context(t) - db, _, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - - registry, _ := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 2, 20) - - for range 100 { - cltest.MustInsertUpkeepForRegistry(t, db, registry) - } - - cltest.AssertCount(t, db, "keeper_registries", 1) - cltest.AssertCount(t, db, "upkeep_registrations", 100) - - binaryHash := fmt.Sprintf("%b", evmutils.NewHash().Big()) - // last keeper index is null to simulate a normal first run - listKpr0, err := orm.EligibleUpkeepsForRegistry(ctx, registry.ContractAddress, 21, 100, binaryHash) // someone eligible only kpr0 turn - require.NoError(t, err) - require.NotEmpty(t, listKpr0, "kpr0 should have some eligible as a normal turn") -} - -func TestKeeperDB_NewEligibleUpkeeps_FiltersByRegistry(t *testing.T) { - t.Parallel() - ctx := testutils.Context(t) - db, _, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - - registry1, _ := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 1, 20) - registry2, _ := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 1, 20) - - cltest.MustInsertUpkeepForRegistry(t, db, registry1) - cltest.MustInsertUpkeepForRegistry(t, db, registry2) - - cltest.AssertCount(t, db, "keeper_registries", 2) - cltest.AssertCount(t, db, "upkeep_registrations", 2) - - binaryHash := fmt.Sprintf("%b", evmutils.NewHash().Big()) - list1, err := orm.EligibleUpkeepsForRegistry(ctx, registry1.ContractAddress, 20, 100, binaryHash) - require.NoError(t, err) - list2, err := orm.EligibleUpkeepsForRegistry(ctx, registry2.ContractAddress, 20, 100, binaryHash) - require.NoError(t, err) - - assert.Len(t, list1, 1) - assert.Len(t, list2, 1) -} - -func TestKeeperDB_AllUpkeepIDsForRegistry(t *testing.T) { - t.Parallel() - ctx := testutils.Context(t) - db, _, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - registry, _ := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 1, 20) - - upkeepIDs, err := orm.AllUpkeepIDsForRegistry(ctx, registry.ID) - require.NoError(t, err) - // No upkeeps returned - require.Empty(t, upkeepIDs) - - upkeep := newUpkeep(registry, 3) - err = orm.UpsertUpkeep(ctx, &upkeep) - require.NoError(t, err) - - upkeep = newUpkeep(registry, 8) - err = orm.UpsertUpkeep(ctx, &upkeep) - require.NoError(t, err) - - // We should get two upkeeps IDs, 3 & 8 - upkeepIDs, err = orm.AllUpkeepIDsForRegistry(ctx, registry.ID) - require.NoError(t, err) - // No upkeeps returned - require.Len(t, upkeepIDs, 2) - require.Contains(t, upkeepIDs, *sqlutil.New(big.NewInt(3))) - require.Contains(t, upkeepIDs, *sqlutil.New(big.NewInt(8))) -} - -func TestKeeperDB_UpdateUpkeepLastKeeperIndex(t *testing.T) { - t.Parallel() - ctx := testutils.Context(t) - db, _, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - registry, j := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 1, 20) - upkeep := cltest.MustInsertUpkeepForRegistry(t, db, registry) - - require.NoError(t, orm.UpdateUpkeepLastKeeperIndex(ctx, j.ID, upkeep.UpkeepID, registry.FromAddress)) - - err := db.Get(&upkeep, `SELECT * FROM upkeep_registrations WHERE upkeep_id = $1`, upkeep.UpkeepID) - require.NoError(t, err) - require.Equal(t, int64(0), upkeep.LastKeeperIndex.Int64) -} - -func TestKeeperDB_NewSetLastRunInfoForUpkeepOnJob(t *testing.T) { - t.Parallel() - ctx := testutils.Context(t) - db, _, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - - registry, j := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 1, 20) - upkeep := cltest.MustInsertUpkeepForRegistry(t, db, registry) - registry.NumKeepers = 2 - registry.KeeperIndexMap = map[types.EIP55Address]int32{ - registry.FromAddress: 0, - types.EIP55AddressFromAddress(evmutils.ZeroAddress): 1, - } - err := orm.UpsertRegistry(ctx, ®istry) - require.NoError(t, err, "UPDATE keeper_registries") - - // update - rowsAffected, err := orm.SetLastRunInfoForUpkeepOnJob(ctx, j.ID, upkeep.UpkeepID, 100, registry.FromAddress) - require.NoError(t, err) - require.Equal(t, int64(1), rowsAffected) - assertLastRunHeight(t, db, upkeep, 100, 0) - // update to lower block height not allowed - rowsAffected, err = orm.SetLastRunInfoForUpkeepOnJob(ctx, j.ID, upkeep.UpkeepID, 0, registry.FromAddress) - require.NoError(t, err) - require.Equal(t, int64(0), rowsAffected) - assertLastRunHeight(t, db, upkeep, 100, 0) - // update to same block height allowed - rowsAffected, err = orm.SetLastRunInfoForUpkeepOnJob(ctx, j.ID, upkeep.UpkeepID, 100, types.EIP55AddressFromAddress(evmutils.ZeroAddress)) - require.NoError(t, err) - require.Equal(t, int64(1), rowsAffected) - assertLastRunHeight(t, db, upkeep, 100, 1) - // update to higher block height allowed - rowsAffected, err = orm.SetLastRunInfoForUpkeepOnJob(ctx, j.ID, upkeep.UpkeepID, 101, registry.FromAddress) - require.NoError(t, err) - require.Equal(t, int64(1), rowsAffected) - assertLastRunHeight(t, db, upkeep, 101, 0) -} - -func TestKeeperDB_LeastSignificant(t *testing.T) { - t.Parallel() - db, _, _ := setupKeeperDB(t) - sql := `SELECT least_significant($1, $2)` - inputBytes := "10001000101010101101" - for _, test := range []struct { - name string - inputLength int - expectedOutput string - expectedError bool - }{ - { - name: "half slice", - inputLength: 10, - expectedOutput: "1010101101", - }, - { - name: "full slice", - inputLength: 20, - expectedOutput: "10001000101010101101", - }, - { - name: "no slice", - inputLength: 0, - expectedOutput: "", - }, - { - name: "slice too large", - inputLength: 21, - expectedError: true, - }, - } { - t.Run(test.name, func(tt *testing.T) { - var test = test - var result string - err := db.Get(&result, sql, inputBytes, test.inputLength) - if test.expectedError { - assert.Error(t, err) - return - } - assert.NoError(t, err) - assert.Equal(t, test.expectedOutput, result) - }) - } -} - -func TestKeeperDB_Uint256ToBit(t *testing.T) { - t.Parallel() - db, _, _ := setupKeeperDB(t) - sql := `SELECT uint256_to_bit($1)` - for _, test := range []struct { - name string - input *big.Int - errorExpected bool - }{ - { - name: "min", - input: big.NewInt(0), - }, - { - name: "max", - input: evmutils.MaxUint256, - }, - { - name: "rand", - input: evmutils.RandUint256(), - }, - { - name: "needs pading", - input: big.NewInt(1), - }, - { - name: "overflow", - input: bigmath.Add(evmutils.MaxUint256, big.NewInt(1)), - errorExpected: true, - }, - } { - t.Run(test.name, func(tt *testing.T) { - var test = test - var result string - err := db.Get(&result, sql, test.input.String()) - if test.errorExpected { - require.Error(t, err) - return - } - require.NoError(t, err) - expected := utils.LeftPadBitString(fmt.Sprintf("%b", test.input), 256) - require.Equal(t, expected, result) - }) - } -} diff --git a/core/services/keeper/registry1_1_synchronizer_test.go b/core/services/keeper/registry1_1_synchronizer_test.go deleted file mode 100644 index 8e41fda54c1..00000000000 --- a/core/services/keeper/registry1_1_synchronizer_test.go +++ /dev/null @@ -1,428 +0,0 @@ -package keeper_test - -import ( - "fmt" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/onsi/gomega" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - - registry1_1 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_1" - "github.com/smartcontractkit/chainlink-evm/pkg/client/clienttest" - evmtypes "github.com/smartcontractkit/chainlink-evm/pkg/types" - logmocks "github.com/smartcontractkit/chainlink/v2/common/log/mocks" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/keeper" -) - -var registryConfig1_1 = registry1_1.GetConfig{ - PaymentPremiumPPB: 100, - BlockCountPerTurn: big.NewInt(20), - CheckGasLimit: 2_000_000, - StalenessSeconds: big.NewInt(3600), - FallbackGasPrice: big.NewInt(1000000), - FallbackLinkPrice: big.NewInt(1000000), -} - -var upkeepConfig1_1 = registry1_1.GetUpkeep{ - Target: testutils.NewAddress(), - ExecuteGas: 2_000_000, - CheckData: common.Hex2Bytes("1234"), - Balance: big.NewInt(1000000000000000000), - LastKeeper: testutils.NewAddress(), - Admin: testutils.NewAddress(), - MaxValidBlocknumber: 1_000_000_000, -} - -func mockRegistry1_1( - t *testing.T, - ethMock *clienttest.Client, - contractAddress common.Address, - config registry1_1.GetConfig, - keeperList []common.Address, - cancelledUpkeeps []*big.Int, - upkeepCount *big.Int, - upkeepConfig registry1_1.GetUpkeep, - timesGetUpkeepMock int, -) { - registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_1ABI, contractAddress) - - ethMock.On("HeadByNumber", mock.Anything, (*big.Int)(nil)). - Return(&evmtypes.Head{Number: 10}, nil) - registryMock.MockResponse("getConfig", config).Once() - registryMock.MockResponse("getKeeperList", keeperList).Once() - registryMock.MockResponse("getCanceledUpkeepList", cancelledUpkeeps).Once() - registryMock.MockResponse("getUpkeepCount", upkeepCount).Once() - if timesGetUpkeepMock > 0 { - registryMock.MockResponse("getUpkeep", upkeepConfig).Times(timesGetUpkeepMock) - } -} - -func Test_LogListenerOpts1_1(t *testing.T) { - db := pgtest.NewSqlxDB(t) - korm := keeper.NewORM(db, logger.TestLogger(t)) - ethClient := clienttest.NewClientWithDefaultChainID(t) - j := cltest.MustInsertKeeperJob(t, db, korm, cltest.NewEIP55Address(), cltest.NewEIP55Address()) - - contractAddress := j.KeeperSpec.ContractAddress.Address() - registryMock := cltest.NewContractMockReceiver(t, ethClient, keeper.Registry1_1ABI, contractAddress) - registryMock.MockResponse("typeAndVersion", "KeeperRegistry 1.1.0").Once() - - registryWrapper, err := keeper.NewRegistryWrapper(j.KeeperSpec.ContractAddress, ethClient) - require.NoError(t, err) - - logListenerOpts, err := registryWrapper.GetLogListenerOpts(1, nil) - require.NoError(t, err) - - require.Contains(t, logListenerOpts.LogsWithTopics, registry1_1.KeeperRegistryKeepersUpdated{}.Topic(), "Registry should listen to KeeperRegistryKeepersUpdated log") - require.Contains(t, logListenerOpts.LogsWithTopics, registry1_1.KeeperRegistryConfigSet{}.Topic(), "Registry should listen to KeeperRegistryConfigSet log") - require.Contains(t, logListenerOpts.LogsWithTopics, registry1_1.KeeperRegistryUpkeepCanceled{}.Topic(), "Registry should listen to KeeperRegistryUpkeepCanceled log") - require.Contains(t, logListenerOpts.LogsWithTopics, registry1_1.KeeperRegistryUpkeepRegistered{}.Topic(), "Registry should listen to KeeperRegistryUpkeepRegistered log") - require.Contains(t, logListenerOpts.LogsWithTopics, registry1_1.KeeperRegistryUpkeepPerformed{}.Topic(), "Registry should listen to KeeperRegistryUpkeepPerformed log") -} - -func Test_RegistrySynchronizer1_1_Start(t *testing.T) { - db, synchronizer, ethMock, _, job := setupRegistrySync(t, keeper.RegistryVersion_1_1) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - mockRegistry1_1( - t, - ethMock, - contractAddress, - registryConfig1_1, - []common.Address{fromAddress}, - []*big.Int{}, - big.NewInt(0), - upkeepConfig1_1, - 0) - - err := synchronizer.Start(testutils.Context(t)) - require.NoError(t, err) - defer func() { assert.NoError(t, synchronizer.Close()) }() - - cltest.WaitForCount(t, db, "keeper_registries", 1) - - err = synchronizer.Start(testutils.Context(t)) - require.Error(t, err) -} - -func Test_RegistrySynchronizer_CalcPositioningConstant(t *testing.T) { - t.Parallel() - for _, upkeepID := range []int64{0, 1, 100, 10_000} { - _, err := keeper.CalcPositioningConstant(sqlutil.NewI(upkeepID), cltest.NewEIP55Address()) - require.NoError(t, err) - } -} - -func Test_RegistrySynchronizer1_1_FullSync(t *testing.T) { - ctx := testutils.Context(t) - g := gomega.NewWithT(t) - db, synchronizer, ethMock, _, job := setupRegistrySync(t, keeper.RegistryVersion_1_1) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - canceledUpkeeps := []*big.Int{big.NewInt(1)} - - upkeepConfig := upkeepConfig1_1 - upkeepConfig.LastKeeper = fromAddress - mockRegistry1_1( - t, - ethMock, - contractAddress, - registryConfig1_1, - []common.Address{fromAddress}, - canceledUpkeeps, - big.NewInt(3), - upkeepConfig, - 2) // sync only 2 (#0,#2) - - synchronizer.ExportedFullSync(ctx) - - cltest.AssertCount(t, db, "keeper_registries", 1) - cltest.AssertCount(t, db, "upkeep_registrations", 2) - - // Last keeper index should be set correctly on upkeep - g.Eventually(func() bool { - var upkeep keeper.UpkeepRegistration - err := db.Get(&upkeep, `SELECT * FROM upkeep_registrations`) - require.NoError(t, err) - return upkeep.LastKeeperIndex.Valid - }, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.BeTrue()) - g.Eventually(func() int64 { - var upkeep keeper.UpkeepRegistration - err := db.Get(&upkeep, `SELECT * FROM upkeep_registrations`) - require.NoError(t, err) - return upkeep.LastKeeperIndex.Int64 - }, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal(int64(0))) - - var registry keeper.Registry - var upkeepRegistration keeper.UpkeepRegistration - require.NoError(t, db.Get(®istry, `SELECT * FROM keeper_registries`)) - require.NoError(t, db.Get(&upkeepRegistration, `SELECT * FROM upkeep_registrations`)) - require.Equal(t, job.KeeperSpec.ContractAddress, registry.ContractAddress) - require.Equal(t, job.KeeperSpec.FromAddress, registry.FromAddress) - require.Equal(t, int32(20), registry.BlockCountPerTurn) - require.Equal(t, int32(0), registry.KeeperIndex) - require.Equal(t, int32(1), registry.NumKeepers) - require.Equal(t, upkeepConfig1_1.CheckData, upkeepRegistration.CheckData) - require.Equal(t, upkeepConfig1_1.ExecuteGas, upkeepRegistration.ExecuteGas) - - assertUpkeepIDs(t, db, []int64{0, 2}) - - // 2nd sync - canceledUpkeeps = []*big.Int{big.NewInt(0), big.NewInt(1), big.NewInt(3)} - mockRegistry1_1( - t, - ethMock, - contractAddress, - registryConfig1_1, - []common.Address{fromAddress}, - canceledUpkeeps, - big.NewInt(5), - upkeepConfig1_1, - 2) // sync all 2 upkeeps (#2, #4) - synchronizer.ExportedFullSync(ctx) - - cltest.AssertCount(t, db, "keeper_registries", 1) - cltest.AssertCount(t, db, "upkeep_registrations", 2) - assertUpkeepIDs(t, db, []int64{2, 4}) -} - -func Test_RegistrySynchronizer1_1_ConfigSetLog(t *testing.T) { - ctx := testutils.Context(t) - db, synchronizer, ethMock, lb, job := setupRegistrySync(t, keeper.RegistryVersion_1_1) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - - mockRegistry1_1( - t, - ethMock, - contractAddress, - registryConfig1_1, - []common.Address{fromAddress}, - []*big.Int{}, - big.NewInt(0), - upkeepConfig1_1, - 0) - - servicetest.Run(t, synchronizer) - cltest.WaitForCount(t, db, "keeper_registries", 1) - var registry keeper.Registry - require.NoError(t, db.Get(®istry, `SELECT * FROM keeper_registries`)) - - registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_1ABI, contractAddress) - newConfig := registryConfig1_1 - newConfig.BlockCountPerTurn = big.NewInt(40) // change from default - registryMock.MockResponse("getKeeperList", []common.Address{fromAddress}).Once() - registryMock.MockResponse("getConfig", newConfig).Once() - - head := cltest.MustInsertHead(t, db, 1) - rawLog := types.Log{BlockHash: head.Hash} - log := registry1_1.KeeperRegistryConfigSet{} - logBroadcast := logmocks.NewBroadcast(t) - logBroadcast.On("DecodedLog").Return(&log) - logBroadcast.On("RawLog").Return(rawLog) - logBroadcast.On("String").Maybe().Return("") - lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) - - // Do the thing - synchronizer.HandleLog(ctx, logBroadcast) - - cltest.AssertRecordEventually(t, db, ®istry, fmt.Sprintf(`SELECT * FROM keeper_registries WHERE id = %d`, registry.ID), func() bool { - return registry.BlockCountPerTurn == 40 - }) - cltest.AssertCount(t, db, "keeper_registries", 1) -} - -func Test_RegistrySynchronizer1_1_KeepersUpdatedLog(t *testing.T) { - ctx := testutils.Context(t) - db, synchronizer, ethMock, lb, job := setupRegistrySync(t, keeper.RegistryVersion_1_1) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - - mockRegistry1_1( - t, - ethMock, - contractAddress, - registryConfig1_1, - []common.Address{fromAddress}, - []*big.Int{}, - big.NewInt(0), - upkeepConfig1_1, - 0) - - servicetest.Run(t, synchronizer) - cltest.WaitForCount(t, db, "keeper_registries", 1) - var registry keeper.Registry - require.NoError(t, db.Get(®istry, `SELECT * FROM keeper_registries`)) - - addresses := []common.Address{fromAddress, testutils.NewAddress()} // change from default - registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_1ABI, contractAddress) - registryMock.MockResponse("getConfig", registryConfig1_1).Once() - registryMock.MockResponse("getKeeperList", addresses).Once() - - head := cltest.MustInsertHead(t, db, 1) - rawLog := types.Log{BlockHash: head.Hash} - log := registry1_1.KeeperRegistryKeepersUpdated{} - logBroadcast := logmocks.NewBroadcast(t) - logBroadcast.On("DecodedLog").Return(&log) - logBroadcast.On("RawLog").Return(rawLog) - logBroadcast.On("String").Maybe().Return("") - lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) - - // Do the thing - synchronizer.HandleLog(ctx, logBroadcast) - - cltest.AssertRecordEventually(t, db, ®istry, fmt.Sprintf(`SELECT * FROM keeper_registries WHERE id = %d`, registry.ID), func() bool { - return registry.NumKeepers == 2 - }) - cltest.AssertCount(t, db, "keeper_registries", 1) -} -func Test_RegistrySynchronizer1_1_UpkeepCanceledLog(t *testing.T) { - ctx := testutils.Context(t) - db, synchronizer, ethMock, lb, job := setupRegistrySync(t, keeper.RegistryVersion_1_1) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - - mockRegistry1_1( - t, - ethMock, - contractAddress, - registryConfig1_1, - []common.Address{fromAddress}, - []*big.Int{}, - big.NewInt(3), - upkeepConfig1_1, - 3) - - servicetest.Run(t, synchronizer) - cltest.WaitForCount(t, db, "keeper_registries", 1) - cltest.WaitForCount(t, db, "upkeep_registrations", 3) - - head := cltest.MustInsertHead(t, db, 1) - rawLog := types.Log{BlockHash: head.Hash} - log := registry1_1.KeeperRegistryUpkeepCanceled{Id: big.NewInt(1)} - logBroadcast := logmocks.NewBroadcast(t) - logBroadcast.On("DecodedLog").Return(&log) - logBroadcast.On("RawLog").Return(rawLog) - logBroadcast.On("String").Maybe().Return("") - lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) - - // Do the thing - synchronizer.HandleLog(ctx, logBroadcast) - - cltest.WaitForCount(t, db, "upkeep_registrations", 2) -} - -func Test_RegistrySynchronizer1_1_UpkeepRegisteredLog(t *testing.T) { - ctx := testutils.Context(t) - db, synchronizer, ethMock, lb, job := setupRegistrySync(t, keeper.RegistryVersion_1_1) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - - mockRegistry1_1( - t, - ethMock, - contractAddress, - registryConfig1_1, - []common.Address{fromAddress}, - []*big.Int{}, - big.NewInt(1), - upkeepConfig1_1, - 1) - - servicetest.Run(t, synchronizer) - cltest.WaitForCount(t, db, "keeper_registries", 1) - cltest.WaitForCount(t, db, "upkeep_registrations", 1) - - registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_1ABI, contractAddress) - registryMock.MockResponse("getUpkeep", upkeepConfig1_1).Once() - - head := cltest.MustInsertHead(t, db, 1) - rawLog := types.Log{BlockHash: head.Hash} - log := registry1_1.KeeperRegistryUpkeepRegistered{Id: big.NewInt(1)} - logBroadcast := logmocks.NewBroadcast(t) - logBroadcast.On("DecodedLog").Return(&log) - logBroadcast.On("RawLog").Return(rawLog) - logBroadcast.On("String").Maybe().Return("") - lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) - - // Do the thing - synchronizer.HandleLog(ctx, logBroadcast) - - cltest.WaitForCount(t, db, "upkeep_registrations", 2) -} - -func Test_RegistrySynchronizer1_1_UpkeepPerformedLog(t *testing.T) { - ctx := testutils.Context(t) - g := gomega.NewWithT(t) - - db, synchronizer, ethMock, lb, job := setupRegistrySync(t, keeper.RegistryVersion_1_1) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - - mockRegistry1_1( - t, - ethMock, - contractAddress, - registryConfig1_1, - []common.Address{fromAddress}, - []*big.Int{}, - big.NewInt(1), - upkeepConfig1_1, - 1) - - servicetest.Run(t, synchronizer) - cltest.WaitForCount(t, db, "keeper_registries", 1) - cltest.WaitForCount(t, db, "upkeep_registrations", 1) - - pgtest.MustExec(t, db, `UPDATE upkeep_registrations SET last_run_block_height = 100`) - - head := cltest.MustInsertHead(t, db, 1) - rawLog := types.Log{BlockHash: head.Hash, BlockNumber: 200} - log := registry1_1.KeeperRegistryUpkeepPerformed{Id: big.NewInt(0), From: fromAddress} - logBroadcast := logmocks.NewBroadcast(t) - logBroadcast.On("DecodedLog").Return(&log) - logBroadcast.On("RawLog").Return(rawLog) - logBroadcast.On("String").Maybe().Return("") - lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) - - // Do the thing - synchronizer.HandleLog(ctx, logBroadcast) - - g.Eventually(func() int64 { - var upkeep keeper.UpkeepRegistration - err := db.Get(&upkeep, `SELECT * FROM upkeep_registrations`) - require.NoError(t, err) - return upkeep.LastRunBlockHeight - }, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal(int64(200))) - - g.Eventually(func() int64 { - var upkeep keeper.UpkeepRegistration - err := db.Get(&upkeep, `SELECT * FROM upkeep_registrations`) - require.NoError(t, err) - return upkeep.LastKeeperIndex.Int64 - }, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal(int64(0))) -} diff --git a/core/services/keeper/registry1_2_synchronizer_test.go b/core/services/keeper/registry1_2_synchronizer_test.go deleted file mode 100644 index cf2d3805f23..00000000000 --- a/core/services/keeper/registry1_2_synchronizer_test.go +++ /dev/null @@ -1,592 +0,0 @@ -package keeper_test - -import ( - "fmt" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/onsi/gomega" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" - registry1_2 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_2" - "github.com/smartcontractkit/chainlink-evm/pkg/client/clienttest" - evmtypes "github.com/smartcontractkit/chainlink-evm/pkg/types" - logmocks "github.com/smartcontractkit/chainlink/v2/common/log/mocks" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/keeper" -) - -var registryConfig1_2 = registry1_2.Config{ - PaymentPremiumPPB: 100, - FlatFeeMicroLink: uint32(0), - BlockCountPerTurn: big.NewInt(20), - CheckGasLimit: 2_000_000, - StalenessSeconds: big.NewInt(3600), - GasCeilingMultiplier: uint16(2), - MinUpkeepSpend: big.NewInt(0), - MaxPerformGas: uint32(5000000), - FallbackGasPrice: big.NewInt(1000000), - FallbackLinkPrice: big.NewInt(1000000), - Transcoder: cltest.NewEIP55Address().Address(), - Registrar: cltest.NewEIP55Address().Address(), -} - -var registryState1_2 = registry1_2.State{ - Nonce: uint32(0), - OwnerLinkBalance: big.NewInt(1000000000000000000), - ExpectedLinkBalance: big.NewInt(1000000000000000000), - NumUpkeeps: big.NewInt(0), -} - -var upkeepConfig1_2 = registry1_2.GetUpkeep{ - Target: testutils.NewAddress(), - ExecuteGas: 2_000_000, - CheckData: common.Hex2Bytes("1234"), - Balance: big.NewInt(1000000000000000000), - LastKeeper: testutils.NewAddress(), - Admin: testutils.NewAddress(), - MaxValidBlocknumber: 1_000_000_000, - AmountSpent: big.NewInt(0), -} - -func mockRegistry1_2( - t *testing.T, - ethMock *clienttest.Client, - contractAddress common.Address, - config registry1_2.Config, - activeUpkeepIDs []*big.Int, - keeperList []common.Address, - upkeepConfig registry1_2.GetUpkeep, - timesGetUpkeepMock int, - getStateTime int, - getActiveUpkeepIDsTime int, -) { - registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_2ABI, contractAddress) - - state := registryState1_2 - state.NumUpkeeps = big.NewInt(int64(len(activeUpkeepIDs))) - var getState = registry1_2.GetState{ - State: state, - Config: config, - Keepers: keeperList, - } - ethMock.On("HeadByNumber", mock.Anything, (*big.Int)(nil)). - Return(&evmtypes.Head{Number: 10}, nil) - if getStateTime > 0 { - registryMock.MockResponse("getState", getState).Times(getStateTime) - } - if getActiveUpkeepIDsTime > 0 { - registryMock.MockResponse("getActiveUpkeepIDs", activeUpkeepIDs).Times(getActiveUpkeepIDsTime) - } - if timesGetUpkeepMock > 0 { - registryMock.MockResponse("getUpkeep", upkeepConfig).Times(timesGetUpkeepMock) - } -} - -func Test_LogListenerOpts1_2(t *testing.T) { - db := pgtest.NewSqlxDB(t) - korm := keeper.NewORM(db, logger.TestLogger(t)) - ethClient := clienttest.NewClientWithDefaultChainID(t) - j := cltest.MustInsertKeeperJob(t, db, korm, cltest.NewEIP55Address(), cltest.NewEIP55Address()) - - contractAddress := j.KeeperSpec.ContractAddress.Address() - registryMock := cltest.NewContractMockReceiver(t, ethClient, keeper.Registry1_1ABI, contractAddress) - registryMock.MockResponse("typeAndVersion", "KeeperRegistry 1.2.0").Once() - - registryWrapper, err := keeper.NewRegistryWrapper(j.KeeperSpec.ContractAddress, ethClient) - require.NoError(t, err) - - logListenerOpts, err := registryWrapper.GetLogListenerOpts(1, nil) - require.NoError(t, err) - - require.Contains(t, logListenerOpts.LogsWithTopics, registry1_2.KeeperRegistryKeepersUpdated{}.Topic(), "Registry should listen to KeeperRegistryKeepersUpdated log") - require.Contains(t, logListenerOpts.LogsWithTopics, registry1_2.KeeperRegistryConfigSet{}.Topic(), "Registry should listen to KeeperRegistryConfigSet log") - require.Contains(t, logListenerOpts.LogsWithTopics, registry1_2.KeeperRegistryUpkeepCanceled{}.Topic(), "Registry should listen to KeeperRegistryUpkeepCanceled log") - require.Contains(t, logListenerOpts.LogsWithTopics, registry1_2.KeeperRegistryUpkeepRegistered{}.Topic(), "Registry should listen to KeeperRegistryUpkeepRegistered log") - require.Contains(t, logListenerOpts.LogsWithTopics, registry1_2.KeeperRegistryUpkeepPerformed{}.Topic(), "Registry should listen to KeeperRegistryUpkeepPerformed log") - require.Contains(t, logListenerOpts.LogsWithTopics, registry1_2.KeeperRegistryUpkeepGasLimitSet{}.Topic(), "Registry should listen to KeeperRegistryUpkeepGasLimitSet log") - require.Contains(t, logListenerOpts.LogsWithTopics, registry1_2.KeeperRegistryUpkeepMigrated{}.Topic(), "Registry should listen to KeeperRegistryUpkeepMigrated log") - require.Contains(t, logListenerOpts.LogsWithTopics, registry1_2.KeeperRegistryUpkeepReceived{}.Topic(), "Registry should listen to KeeperRegistryUpkeepReceived log") -} - -func Test_RegistrySynchronizer1_2_Start(t *testing.T) { - db, synchronizer, ethMock, _, job := setupRegistrySync(t, keeper.RegistryVersion_1_2) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - mockRegistry1_2( - t, - ethMock, - contractAddress, - registryConfig1_2, - []*big.Int{}, - []common.Address{fromAddress}, - upkeepConfig1_2, - 0, - 2, - 0) - - err := synchronizer.Start(testutils.Context(t)) - require.NoError(t, err) - defer func() { assert.NoError(t, synchronizer.Close()) }() - - cltest.WaitForCount(t, db, "keeper_registries", 1) - - err = synchronizer.Start(testutils.Context(t)) - require.Error(t, err) -} - -func Test_RegistrySynchronizer1_2_FullSync(t *testing.T) { - ctx := testutils.Context(t) - g := gomega.NewWithT(t) - db, synchronizer, ethMock, _, job := setupRegistrySync(t, keeper.RegistryVersion_1_2) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - - upkeepConfig := upkeepConfig1_2 - upkeepConfig.LastKeeper = fromAddress - mockRegistry1_2( - t, - ethMock, - contractAddress, - registryConfig1_2, - []*big.Int{big.NewInt(3), big.NewInt(69), big.NewInt(420)}, // Upkeep IDs - []common.Address{fromAddress}, - upkeepConfig, - 3, // sync all 3 - 2, - 1) - synchronizer.ExportedFullSync(ctx) - - cltest.AssertCount(t, db, "keeper_registries", 1) - cltest.AssertCount(t, db, "upkeep_registrations", 3) - - // Last keeper index should be set correctly on upkeep - g.Eventually(func() bool { - var upkeep keeper.UpkeepRegistration - err := db.Get(&upkeep, `SELECT * FROM upkeep_registrations`) - require.NoError(t, err) - return upkeep.LastKeeperIndex.Valid - }, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.BeTrue()) - g.Eventually(func() int64 { - var upkeep keeper.UpkeepRegistration - err := db.Get(&upkeep, `SELECT * FROM upkeep_registrations`) - require.NoError(t, err) - return upkeep.LastKeeperIndex.Int64 - }, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal(int64(0))) - - var registry keeper.Registry - var upkeepRegistration keeper.UpkeepRegistration - require.NoError(t, db.Get(®istry, `SELECT * FROM keeper_registries`)) - require.Equal(t, job.KeeperSpec.ContractAddress, registry.ContractAddress) - require.Equal(t, job.KeeperSpec.FromAddress, registry.FromAddress) - require.Equal(t, int32(20), registry.BlockCountPerTurn) - require.Equal(t, int32(0), registry.KeeperIndex) - require.Equal(t, int32(1), registry.NumKeepers) - - require.NoError(t, db.Get(&upkeepRegistration, `SELECT * FROM upkeep_registrations`)) - require.Equal(t, upkeepConfig1_2.CheckData, upkeepRegistration.CheckData) - require.Equal(t, upkeepConfig1_2.ExecuteGas, upkeepRegistration.ExecuteGas) - - assertUpkeepIDs(t, db, []int64{3, 69, 420}) - - // 2nd sync. Cancel upkeep (id 3) and add a new upkeep (id 2022) - mockRegistry1_2( - t, - ethMock, - contractAddress, - registryConfig1_2, - []*big.Int{big.NewInt(69), big.NewInt(420), big.NewInt(2022)}, // Upkeep IDs - []common.Address{fromAddress}, - upkeepConfig1_2, - 3, // sync all 3 active upkeeps - 2, - 1) - synchronizer.ExportedFullSync(ctx) - - cltest.AssertCount(t, db, "keeper_registries", 1) - cltest.AssertCount(t, db, "upkeep_registrations", 3) - assertUpkeepIDs(t, db, []int64{69, 420, 2022}) -} - -func Test_RegistrySynchronizer1_2_ConfigSetLog(t *testing.T) { - ctx := testutils.Context(t) - db, synchronizer, ethMock, lb, job := setupRegistrySync(t, keeper.RegistryVersion_1_2) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - - mockRegistry1_2( - t, - ethMock, - contractAddress, - registryConfig1_2, - []*big.Int{}, // Upkeep IDs - []common.Address{fromAddress}, - upkeepConfig1_2, - 0, - 2, - 0) - - servicetest.Run(t, synchronizer) - cltest.WaitForCount(t, db, "keeper_registries", 1) - var registry keeper.Registry - require.NoError(t, db.Get(®istry, `SELECT * FROM keeper_registries`)) - - registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_2ABI, contractAddress) - newConfig := registryConfig1_2 - newConfig.BlockCountPerTurn = big.NewInt(40) // change from default - registryMock.MockResponse("getState", registry1_2.GetState{ - State: registryState1_2, - Config: newConfig, - Keepers: []common.Address{fromAddress}, - }).Once() - - head := cltest.MustInsertHead(t, db, 1) - rawLog := types.Log{BlockHash: head.Hash} - log := registry1_2.KeeperRegistryConfigSet{} - logBroadcast := logmocks.NewBroadcast(t) - logBroadcast.On("DecodedLog").Return(&log) - logBroadcast.On("RawLog").Return(rawLog) - logBroadcast.On("String").Maybe().Return("") - lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) - - // Do the thing - synchronizer.HandleLog(ctx, logBroadcast) - - cltest.AssertRecordEventually(t, db, ®istry, fmt.Sprintf(`SELECT * FROM keeper_registries WHERE id = %d`, registry.ID), func() bool { - return registry.BlockCountPerTurn == 40 - }) - cltest.AssertCount(t, db, "keeper_registries", 1) -} - -func Test_RegistrySynchronizer1_2_KeepersUpdatedLog(t *testing.T) { - ctx := testutils.Context(t) - db, synchronizer, ethMock, lb, job := setupRegistrySync(t, keeper.RegistryVersion_1_2) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - - mockRegistry1_2( - t, - ethMock, - contractAddress, - registryConfig1_2, - []*big.Int{}, // Upkeep IDs - []common.Address{fromAddress}, - upkeepConfig1_2, - 0, - 2, - 0) - - servicetest.Run(t, synchronizer) - cltest.WaitForCount(t, db, "keeper_registries", 1) - var registry keeper.Registry - require.NoError(t, db.Get(®istry, `SELECT * FROM keeper_registries`)) - - addresses := []common.Address{fromAddress, testutils.NewAddress()} // change from default - registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_2ABI, contractAddress) - registryMock.MockResponse("getState", registry1_2.GetState{ - State: registryState1_2, - Config: registryConfig1_2, - Keepers: addresses, - }).Once() - - head := cltest.MustInsertHead(t, db, 1) - rawLog := types.Log{BlockHash: head.Hash} - log := registry1_2.KeeperRegistryKeepersUpdated{} - logBroadcast := logmocks.NewBroadcast(t) - logBroadcast.On("DecodedLog").Return(&log) - logBroadcast.On("RawLog").Return(rawLog) - logBroadcast.On("String").Maybe().Return("") - lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) - - // Do the thing - synchronizer.HandleLog(ctx, logBroadcast) - - cltest.AssertRecordEventually(t, db, ®istry, fmt.Sprintf(`SELECT * FROM keeper_registries WHERE id = %d`, registry.ID), func() bool { - return registry.NumKeepers == 2 - }) - cltest.AssertCount(t, db, "keeper_registries", 1) -} - -func Test_RegistrySynchronizer1_2_UpkeepCanceledLog(t *testing.T) { - ctx := testutils.Context(t) - db, synchronizer, ethMock, lb, job := setupRegistrySync(t, keeper.RegistryVersion_1_2) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - - mockRegistry1_2( - t, - ethMock, - contractAddress, - registryConfig1_2, - []*big.Int{big.NewInt(3), big.NewInt(69), big.NewInt(420)}, // Upkeep IDs - []common.Address{fromAddress}, - upkeepConfig1_2, - 3, - 2, - 1) - - servicetest.Run(t, synchronizer) - cltest.WaitForCount(t, db, "keeper_registries", 1) - cltest.WaitForCount(t, db, "upkeep_registrations", 3) - - head := cltest.MustInsertHead(t, db, 1) - rawLog := types.Log{BlockHash: head.Hash} - log := registry1_2.KeeperRegistryUpkeepCanceled{Id: big.NewInt(3)} - logBroadcast := logmocks.NewBroadcast(t) - logBroadcast.On("DecodedLog").Return(&log) - logBroadcast.On("RawLog").Return(rawLog) - logBroadcast.On("String").Maybe().Return("") - lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) - - // Do the thing - synchronizer.HandleLog(ctx, logBroadcast) - - cltest.WaitForCount(t, db, "upkeep_registrations", 2) -} - -func Test_RegistrySynchronizer1_2_UpkeepRegisteredLog(t *testing.T) { - ctx := testutils.Context(t) - db, synchronizer, ethMock, lb, job := setupRegistrySync(t, keeper.RegistryVersion_1_2) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - - mockRegistry1_2( - t, - ethMock, - contractAddress, - registryConfig1_2, - []*big.Int{big.NewInt(3)}, // Upkeep IDs - []common.Address{fromAddress}, - upkeepConfig1_2, - 1, - 2, - 1) - - servicetest.Run(t, synchronizer) - cltest.WaitForCount(t, db, "keeper_registries", 1) - cltest.WaitForCount(t, db, "upkeep_registrations", 1) - - registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_2ABI, contractAddress) - registryMock.MockResponse("getUpkeep", upkeepConfig1_2).Once() - - head := cltest.MustInsertHead(t, db, 1) - rawLog := types.Log{BlockHash: head.Hash} - log := registry1_2.KeeperRegistryUpkeepRegistered{Id: big.NewInt(420)} - logBroadcast := logmocks.NewBroadcast(t) - logBroadcast.On("DecodedLog").Return(&log) - logBroadcast.On("RawLog").Return(rawLog) - logBroadcast.On("String").Maybe().Return("") - lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) - - // Do the thing - synchronizer.HandleLog(ctx, logBroadcast) - - cltest.WaitForCount(t, db, "upkeep_registrations", 2) -} - -func Test_RegistrySynchronizer1_2_UpkeepPerformedLog(t *testing.T) { - ctx := testutils.Context(t) - g := gomega.NewWithT(t) - - db, synchronizer, ethMock, lb, job := setupRegistrySync(t, keeper.RegistryVersion_1_2) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - - mockRegistry1_2( - t, - ethMock, - contractAddress, - registryConfig1_2, - []*big.Int{big.NewInt(3)}, // Upkeep IDs - []common.Address{fromAddress}, - upkeepConfig1_2, - 1, - 2, - 1) - - servicetest.Run(t, synchronizer) - cltest.WaitForCount(t, db, "keeper_registries", 1) - cltest.WaitForCount(t, db, "upkeep_registrations", 1) - - pgtest.MustExec(t, db, `UPDATE upkeep_registrations SET last_run_block_height = 100`) - - head := cltest.MustInsertHead(t, db, 1) - rawLog := types.Log{BlockHash: head.Hash, BlockNumber: 200} - log := registry1_2.KeeperRegistryUpkeepPerformed{Id: big.NewInt(3), From: fromAddress} - logBroadcast := logmocks.NewBroadcast(t) - logBroadcast.On("DecodedLog").Return(&log) - logBroadcast.On("RawLog").Return(rawLog) - logBroadcast.On("String").Maybe().Return("") - lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) - - // Do the thing - synchronizer.HandleLog(ctx, logBroadcast) - - g.Eventually(func() int64 { - var upkeep keeper.UpkeepRegistration - err := db.Get(&upkeep, `SELECT * FROM upkeep_registrations`) - require.NoError(t, err) - return upkeep.LastRunBlockHeight - }, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal(int64(200))) - - g.Eventually(func() int64 { - var upkeep keeper.UpkeepRegistration - err := db.Get(&upkeep, `SELECT * FROM upkeep_registrations`) - require.NoError(t, err) - return upkeep.LastKeeperIndex.Int64 - }, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal(int64(0))) -} - -func Test_RegistrySynchronizer1_2_UpkeepGasLimitSetLog(t *testing.T) { - ctx := testutils.Context(t) - g := gomega.NewWithT(t) - db, synchronizer, ethMock, lb, job := setupRegistrySync(t, keeper.RegistryVersion_1_2) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - - mockRegistry1_2( - t, - ethMock, - contractAddress, - registryConfig1_2, - []*big.Int{big.NewInt(3)}, // Upkeep IDs - []common.Address{fromAddress}, - upkeepConfig1_2, - 1, - 2, - 1) - - servicetest.Run(t, synchronizer) - cltest.WaitForCount(t, db, "keeper_registries", 1) - cltest.WaitForCount(t, db, "upkeep_registrations", 1) - - getExecuteGas := func() uint32 { - var upkeep keeper.UpkeepRegistration - err := db.Get(&upkeep, `SELECT * FROM upkeep_registrations`) - require.NoError(t, err) - return upkeep.ExecuteGas - } - g.Eventually(getExecuteGas, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal(uint32(2_000_000))) - - registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_2ABI, contractAddress) - newConfig := upkeepConfig1_2 - newConfig.ExecuteGas = 4_000_000 // change from default - registryMock.MockResponse("getUpkeep", newConfig).Once() - - head := cltest.MustInsertHead(t, db, 1) - rawLog := types.Log{BlockHash: head.Hash} - log := registry1_2.KeeperRegistryUpkeepGasLimitSet{Id: big.NewInt(3), GasLimit: big.NewInt(4_000_000)} - logBroadcast := logmocks.NewBroadcast(t) - logBroadcast.On("DecodedLog").Return(&log) - logBroadcast.On("RawLog").Return(rawLog) - logBroadcast.On("String").Maybe().Return("") - lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) - - // Do the thing - synchronizer.HandleLog(ctx, logBroadcast) - - g.Eventually(getExecuteGas, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal(uint32(4_000_000))) -} - -func Test_RegistrySynchronizer1_2_UpkeepReceivedLog(t *testing.T) { - ctx := testutils.Context(t) - db, synchronizer, ethMock, lb, job := setupRegistrySync(t, keeper.RegistryVersion_1_2) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - - mockRegistry1_2( - t, - ethMock, - contractAddress, - registryConfig1_2, - []*big.Int{big.NewInt(3)}, // Upkeep IDs - []common.Address{fromAddress}, - upkeepConfig1_2, - 1, - 2, - 1) - - servicetest.Run(t, synchronizer) - cltest.WaitForCount(t, db, "keeper_registries", 1) - cltest.WaitForCount(t, db, "upkeep_registrations", 1) - - registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_2ABI, contractAddress) - registryMock.MockResponse("getUpkeep", upkeepConfig1_2).Once() - - head := cltest.MustInsertHead(t, db, 1) - rawLog := types.Log{BlockHash: head.Hash} - log := registry1_2.KeeperRegistryUpkeepReceived{Id: big.NewInt(420)} - logBroadcast := logmocks.NewBroadcast(t) - logBroadcast.On("DecodedLog").Return(&log) - logBroadcast.On("RawLog").Return(rawLog) - logBroadcast.On("String").Maybe().Return("") - lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) - - // Do the thing - synchronizer.HandleLog(ctx, logBroadcast) - - cltest.WaitForCount(t, db, "upkeep_registrations", 2) -} - -func Test_RegistrySynchronizer1_2_UpkeepMigratedLog(t *testing.T) { - ctx := testutils.Context(t) - db, synchronizer, ethMock, lb, job := setupRegistrySync(t, keeper.RegistryVersion_1_2) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - - mockRegistry1_2( - t, - ethMock, - contractAddress, - registryConfig1_2, - []*big.Int{big.NewInt(3), big.NewInt(69), big.NewInt(420)}, // Upkeep IDs - []common.Address{fromAddress}, - upkeepConfig1_2, - 3, - 2, - 1) - - servicetest.Run(t, synchronizer) - cltest.WaitForCount(t, db, "keeper_registries", 1) - cltest.WaitForCount(t, db, "upkeep_registrations", 3) - - head := cltest.MustInsertHead(t, db, 1) - rawLog := types.Log{BlockHash: head.Hash} - log := registry1_2.KeeperRegistryUpkeepMigrated{Id: big.NewInt(3)} - logBroadcast := logmocks.NewBroadcast(t) - logBroadcast.On("DecodedLog").Return(&log) - logBroadcast.On("RawLog").Return(rawLog) - logBroadcast.On("String").Maybe().Return("") - lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) - - // Do the thing - synchronizer.HandleLog(ctx, logBroadcast) - - cltest.WaitForCount(t, db, "upkeep_registrations", 2) -} diff --git a/core/services/keeper/registry1_3_synchronizer_test.go b/core/services/keeper/registry1_3_synchronizer_test.go deleted file mode 100644 index fb4c0997649..00000000000 --- a/core/services/keeper/registry1_3_synchronizer_test.go +++ /dev/null @@ -1,738 +0,0 @@ -package keeper_test - -import ( - "fmt" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/onsi/gomega" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - - registry1_3 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_3" - "github.com/smartcontractkit/chainlink-evm/pkg/client/clienttest" - evmtypes "github.com/smartcontractkit/chainlink-evm/pkg/types" - logmocks "github.com/smartcontractkit/chainlink/v2/common/log/mocks" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/keeper" -) - -var registryConfig1_3 = registry1_3.Config{ - PaymentPremiumPPB: 100, - FlatFeeMicroLink: uint32(0), - BlockCountPerTurn: big.NewInt(20), - CheckGasLimit: 2_000_000, - StalenessSeconds: big.NewInt(3600), - GasCeilingMultiplier: uint16(2), - MinUpkeepSpend: big.NewInt(0), - MaxPerformGas: uint32(5000000), - FallbackGasPrice: big.NewInt(1000000), - FallbackLinkPrice: big.NewInt(1000000), - Transcoder: cltest.NewEIP55Address().Address(), - Registrar: cltest.NewEIP55Address().Address(), -} - -var registryState1_3 = registry1_3.State{ - Nonce: uint32(0), - OwnerLinkBalance: big.NewInt(1000000000000000000), - ExpectedLinkBalance: big.NewInt(1000000000000000000), - NumUpkeeps: big.NewInt(0), -} - -var upkeepConfig1_3 = registry1_3.GetUpkeep{ - Target: testutils.NewAddress(), - ExecuteGas: 2_000_000, - CheckData: common.Hex2Bytes("1234"), - Balance: big.NewInt(1000000000000000000), - LastKeeper: testutils.NewAddress(), - Admin: testutils.NewAddress(), - MaxValidBlocknumber: 1_000_000_000, - AmountSpent: big.NewInt(0), -} - -func mockRegistry1_3( - t *testing.T, - ethMock *clienttest.Client, - contractAddress common.Address, - config registry1_3.Config, - activeUpkeepIDs []*big.Int, - keeperList []common.Address, - upkeepConfig registry1_3.GetUpkeep, - timesGetUpkeepMock int, - getStateTime int, - getActiveUpkeepIDsTime int, -) { - registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_3ABI, contractAddress) - - state := registryState1_3 - state.NumUpkeeps = big.NewInt(int64(len(activeUpkeepIDs))) - var getState = registry1_3.GetState{ - State: state, - Config: config, - Keepers: keeperList, - } - ethMock.On("HeadByNumber", mock.Anything, (*big.Int)(nil)). - Return(&evmtypes.Head{Number: 10}, nil) - if getStateTime > 0 { - registryMock.MockResponse("getState", getState).Times(getStateTime) - } - if getActiveUpkeepIDsTime > 0 { - registryMock.MockResponse("getActiveUpkeepIDs", activeUpkeepIDs).Times(getActiveUpkeepIDsTime) - } - if timesGetUpkeepMock > 0 { - registryMock.MockResponse("getUpkeep", upkeepConfig).Times(timesGetUpkeepMock) - } -} - -func Test_LogListenerOpts1_3(t *testing.T) { - db := pgtest.NewSqlxDB(t) - korm := keeper.NewORM(db, logger.TestLogger(t)) - ethClient := clienttest.NewClientWithDefaultChainID(t) - j := cltest.MustInsertKeeperJob(t, db, korm, cltest.NewEIP55Address(), cltest.NewEIP55Address()) - - contractAddress := j.KeeperSpec.ContractAddress.Address() - registryMock := cltest.NewContractMockReceiver(t, ethClient, keeper.Registry1_1ABI, contractAddress) - registryMock.MockResponse("typeAndVersion", "KeeperRegistry 1.3.0").Once() - - registryWrapper, err := keeper.NewRegistryWrapper(j.KeeperSpec.ContractAddress, ethClient) - require.NoError(t, err) - - logListenerOpts, err := registryWrapper.GetLogListenerOpts(1, nil) - require.NoError(t, err) - - require.Contains(t, logListenerOpts.LogsWithTopics, registry1_3.KeeperRegistryKeepersUpdated{}.Topic(), "Registry should listen to KeeperRegistryKeepersUpdated log") - require.Contains(t, logListenerOpts.LogsWithTopics, registry1_3.KeeperRegistryConfigSet{}.Topic(), "Registry should listen to KeeperRegistryConfigSet log") - require.Contains(t, logListenerOpts.LogsWithTopics, registry1_3.KeeperRegistryUpkeepCanceled{}.Topic(), "Registry should listen to KeeperRegistryUpkeepCanceled log") - require.Contains(t, logListenerOpts.LogsWithTopics, registry1_3.KeeperRegistryUpkeepRegistered{}.Topic(), "Registry should listen to KeeperRegistryUpkeepRegistered log") - require.Contains(t, logListenerOpts.LogsWithTopics, registry1_3.KeeperRegistryUpkeepPerformed{}.Topic(), "Registry should listen to KeeperRegistryUpkeepPerformed log") - require.Contains(t, logListenerOpts.LogsWithTopics, registry1_3.KeeperRegistryUpkeepGasLimitSet{}.Topic(), "Registry should listen to KeeperRegistryUpkeepGasLimitSet log") - require.Contains(t, logListenerOpts.LogsWithTopics, registry1_3.KeeperRegistryUpkeepMigrated{}.Topic(), "Registry should listen to KeeperRegistryUpkeepMigrated log") - require.Contains(t, logListenerOpts.LogsWithTopics, registry1_3.KeeperRegistryUpkeepReceived{}.Topic(), "Registry should listen to KeeperRegistryUpkeepReceived log") - require.Contains(t, logListenerOpts.LogsWithTopics, registry1_3.KeeperRegistryUpkeepPaused{}.Topic(), "Registry should listen to KeeperRegistryUpkeepPaused log") - require.Contains(t, logListenerOpts.LogsWithTopics, registry1_3.KeeperRegistryUpkeepUnpaused{}.Topic(), "Registry should listen to KeeperRegistryUpkeepUnpaused log") - require.Contains(t, logListenerOpts.LogsWithTopics, registry1_3.KeeperRegistryUpkeepCheckDataUpdated{}.Topic(), "Registry should listen to KeeperRegistryUpkeepCheckDataUpdated log") -} - -func Test_RegistrySynchronizer1_3_Start(t *testing.T) { - db, synchronizer, ethMock, _, job := setupRegistrySync(t, keeper.RegistryVersion_1_3) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - mockRegistry1_3( - t, - ethMock, - contractAddress, - registryConfig1_3, - []*big.Int{}, - []common.Address{fromAddress}, - upkeepConfig1_3, - 0, - 2, - 0) - - err := synchronizer.Start(testutils.Context(t)) - require.NoError(t, err) - defer func() { assert.NoError(t, synchronizer.Close()) }() - - cltest.WaitForCount(t, db, "keeper_registries", 1) - - err = synchronizer.Start(testutils.Context(t)) - require.Error(t, err) -} - -func Test_RegistrySynchronizer1_3_FullSync(t *testing.T) { - ctx := testutils.Context(t) - g := gomega.NewWithT(t) - db, synchronizer, ethMock, _, job := setupRegistrySync(t, keeper.RegistryVersion_1_3) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - - upkeepConfig := upkeepConfig1_3 - upkeepConfig.LastKeeper = fromAddress - mockRegistry1_3( - t, - ethMock, - contractAddress, - registryConfig1_3, - []*big.Int{big.NewInt(3), big.NewInt(69), big.NewInt(420)}, // Upkeep IDs - []common.Address{fromAddress}, - upkeepConfig, - 3, // sync all 3 - 2, - 1) - synchronizer.ExportedFullSync(ctx) - - cltest.AssertCount(t, db, "keeper_registries", 1) - cltest.AssertCount(t, db, "upkeep_registrations", 3) - - // Last keeper index should be set correctly on upkeep - g.Eventually(func() bool { - var upkeep keeper.UpkeepRegistration - err := db.Get(&upkeep, `SELECT * FROM upkeep_registrations`) - require.NoError(t, err) - return upkeep.LastKeeperIndex.Valid - }, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.BeTrue()) - g.Eventually(func() int64 { - var upkeep keeper.UpkeepRegistration - err := db.Get(&upkeep, `SELECT * FROM upkeep_registrations`) - require.NoError(t, err) - return upkeep.LastKeeperIndex.Int64 - }, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal(int64(0))) - - var registry keeper.Registry - var upkeepRegistration keeper.UpkeepRegistration - require.NoError(t, db.Get(®istry, `SELECT * FROM keeper_registries`)) - require.Equal(t, job.KeeperSpec.ContractAddress, registry.ContractAddress) - require.Equal(t, job.KeeperSpec.FromAddress, registry.FromAddress) - require.Equal(t, int32(20), registry.BlockCountPerTurn) - require.Equal(t, int32(0), registry.KeeperIndex) - require.Equal(t, int32(1), registry.NumKeepers) - - require.NoError(t, db.Get(&upkeepRegistration, `SELECT * FROM upkeep_registrations`)) - require.Equal(t, upkeepConfig1_3.CheckData, upkeepRegistration.CheckData) - require.Equal(t, upkeepConfig1_3.ExecuteGas, upkeepRegistration.ExecuteGas) - - assertUpkeepIDs(t, db, []int64{3, 69, 420}) - - // 2nd sync. Cancel upkeep (id 3) and add a new upkeep (id 2022) - mockRegistry1_3( - t, - ethMock, - contractAddress, - registryConfig1_3, - []*big.Int{big.NewInt(69), big.NewInt(420), big.NewInt(2022)}, // Upkeep IDs - []common.Address{fromAddress}, - upkeepConfig1_3, - 3, // sync all 3 upkeeps - 2, - 1) - synchronizer.ExportedFullSync(ctx) - - cltest.AssertCount(t, db, "keeper_registries", 1) - cltest.AssertCount(t, db, "upkeep_registrations", 3) - assertUpkeepIDs(t, db, []int64{69, 420, 2022}) -} - -func Test_RegistrySynchronizer1_3_ConfigSetLog(t *testing.T) { - ctx := testutils.Context(t) - db, synchronizer, ethMock, lb, job := setupRegistrySync(t, keeper.RegistryVersion_1_3) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - - mockRegistry1_3( - t, - ethMock, - contractAddress, - registryConfig1_3, - []*big.Int{}, // Upkeep IDs - []common.Address{fromAddress}, - upkeepConfig1_3, - 0, - 2, - 0) - - servicetest.Run(t, synchronizer) - cltest.WaitForCount(t, db, "keeper_registries", 1) - var registry keeper.Registry - require.NoError(t, db.Get(®istry, `SELECT * FROM keeper_registries`)) - - registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_3ABI, contractAddress) - newConfig := registryConfig1_3 - newConfig.BlockCountPerTurn = big.NewInt(40) // change from default - registryMock.MockResponse("getState", registry1_3.GetState{ - State: registryState1_3, - Config: newConfig, - Keepers: []common.Address{fromAddress}, - }).Once() - - head := cltest.MustInsertHead(t, db, 1) - rawLog := types.Log{BlockHash: head.Hash} - log := registry1_3.KeeperRegistryConfigSet{} - logBroadcast := logmocks.NewBroadcast(t) - logBroadcast.On("Start").Return(nil).Maybe() - logBroadcast.On("Close").Return(nil).Maybe() - logBroadcast.On("DecodedLog").Return(&log) - logBroadcast.On("RawLog").Return(rawLog) - logBroadcast.On("String").Maybe().Return("") - lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) - - // Do the thing - synchronizer.HandleLog(ctx, logBroadcast) - - cltest.AssertRecordEventually(t, db, ®istry, fmt.Sprintf(`SELECT * FROM keeper_registries WHERE id = %d`, registry.ID), func() bool { - return registry.BlockCountPerTurn == 40 - }) - cltest.AssertCount(t, db, "keeper_registries", 1) -} - -func Test_RegistrySynchronizer1_3_KeepersUpdatedLog(t *testing.T) { - ctx := testutils.Context(t) - db, synchronizer, ethMock, lb, job := setupRegistrySync(t, keeper.RegistryVersion_1_3) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - - mockRegistry1_3( - t, - ethMock, - contractAddress, - registryConfig1_3, - []*big.Int{}, // Upkeep IDs - []common.Address{fromAddress}, - upkeepConfig1_3, - 0, - 2, - 0) - - servicetest.Run(t, synchronizer) - cltest.WaitForCount(t, db, "keeper_registries", 1) - var registry keeper.Registry - require.NoError(t, db.Get(®istry, `SELECT * FROM keeper_registries`)) - - addresses := []common.Address{fromAddress, testutils.NewAddress()} // change from default - registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_3ABI, contractAddress) - registryMock.MockResponse("getState", registry1_3.GetState{ - State: registryState1_3, - Config: registryConfig1_3, - Keepers: addresses, - }).Once() - - head := cltest.MustInsertHead(t, db, 1) - rawLog := types.Log{BlockHash: head.Hash} - log := registry1_3.KeeperRegistryKeepersUpdated{} - logBroadcast := logmocks.NewBroadcast(t) - logBroadcast.On("Start").Return(nil).Maybe() - logBroadcast.On("Close").Return(nil).Maybe() - logBroadcast.On("DecodedLog").Return(&log) - logBroadcast.On("RawLog").Return(rawLog) - logBroadcast.On("String").Maybe().Return("") - lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) - - // Do the thing - synchronizer.HandleLog(ctx, logBroadcast) - - cltest.AssertRecordEventually(t, db, ®istry, fmt.Sprintf(`SELECT * FROM keeper_registries WHERE id = %d`, registry.ID), func() bool { - return registry.NumKeepers == 2 - }) - cltest.AssertCount(t, db, "keeper_registries", 1) -} - -func Test_RegistrySynchronizer1_3_UpkeepCanceledLog(t *testing.T) { - ctx := testutils.Context(t) - db, synchronizer, ethMock, lb, job := setupRegistrySync(t, keeper.RegistryVersion_1_3) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - - mockRegistry1_3( - t, - ethMock, - contractAddress, - registryConfig1_3, - []*big.Int{big.NewInt(3), big.NewInt(69), big.NewInt(420)}, // Upkeep IDs - []common.Address{fromAddress}, - upkeepConfig1_3, - 3, - 2, - 1) - - servicetest.Run(t, synchronizer) - cltest.WaitForCount(t, db, "keeper_registries", 1) - cltest.WaitForCount(t, db, "upkeep_registrations", 3) - - head := cltest.MustInsertHead(t, db, 1) - rawLog := types.Log{BlockHash: head.Hash} - log := registry1_3.KeeperRegistryUpkeepCanceled{Id: big.NewInt(3)} - logBroadcast := logmocks.NewBroadcast(t) - logBroadcast.On("Start").Return(nil).Maybe() - logBroadcast.On("Close").Return(nil).Maybe() - logBroadcast.On("DecodedLog").Return(&log) - logBroadcast.On("RawLog").Return(rawLog) - logBroadcast.On("String").Maybe().Return("") - lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) - - // Do the thing - synchronizer.HandleLog(ctx, logBroadcast) - - cltest.WaitForCount(t, db, "upkeep_registrations", 2) -} - -func Test_RegistrySynchronizer1_3_UpkeepRegisteredLog(t *testing.T) { - ctx := testutils.Context(t) - db, synchronizer, ethMock, lb, job := setupRegistrySync(t, keeper.RegistryVersion_1_3) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - - mockRegistry1_3( - t, - ethMock, - contractAddress, - registryConfig1_3, - []*big.Int{big.NewInt(3)}, // Upkeep IDs - []common.Address{fromAddress}, - upkeepConfig1_3, - 1, - 2, - 1) - - servicetest.Run(t, synchronizer) - cltest.WaitForCount(t, db, "keeper_registries", 1) - cltest.WaitForCount(t, db, "upkeep_registrations", 1) - - registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_3ABI, contractAddress) - registryMock.MockResponse("getUpkeep", upkeepConfig1_3).Once() - - head := cltest.MustInsertHead(t, db, 1) - rawLog := types.Log{BlockHash: head.Hash} - log := registry1_3.KeeperRegistryUpkeepRegistered{Id: big.NewInt(420)} - logBroadcast := logmocks.NewBroadcast(t) - logBroadcast.On("Start").Return(nil).Maybe() - logBroadcast.On("Close").Return(nil).Maybe() - logBroadcast.On("DecodedLog").Return(&log) - logBroadcast.On("RawLog").Return(rawLog) - logBroadcast.On("String").Maybe().Return("") - lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) - - // Do the thing - synchronizer.HandleLog(ctx, logBroadcast) - - cltest.WaitForCount(t, db, "upkeep_registrations", 2) -} - -func Test_RegistrySynchronizer1_3_UpkeepPerformedLog(t *testing.T) { - ctx := testutils.Context(t) - g := gomega.NewWithT(t) - - db, synchronizer, ethMock, lb, job := setupRegistrySync(t, keeper.RegistryVersion_1_3) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - - mockRegistry1_3( - t, - ethMock, - contractAddress, - registryConfig1_3, - []*big.Int{big.NewInt(3)}, // Upkeep IDs - []common.Address{fromAddress}, - upkeepConfig1_3, - 1, - 2, - 1) - - servicetest.Run(t, synchronizer) - cltest.WaitForCount(t, db, "keeper_registries", 1) - cltest.WaitForCount(t, db, "upkeep_registrations", 1) - - pgtest.MustExec(t, db, `UPDATE upkeep_registrations SET last_run_block_height = 100`) - - head := cltest.MustInsertHead(t, db, 1) - rawLog := types.Log{BlockHash: head.Hash, BlockNumber: 200} - log := registry1_3.KeeperRegistryUpkeepPerformed{Id: big.NewInt(3), From: fromAddress} - logBroadcast := logmocks.NewBroadcast(t) - logBroadcast.On("Start").Return(nil).Maybe() - logBroadcast.On("Close").Return(nil).Maybe() - logBroadcast.On("DecodedLog").Return(&log) - logBroadcast.On("RawLog").Return(rawLog) - logBroadcast.On("String").Maybe().Return("") - lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) - - // Do the thing - synchronizer.HandleLog(ctx, logBroadcast) - - g.Eventually(func() int64 { - var upkeep keeper.UpkeepRegistration - err := db.Get(&upkeep, `SELECT * FROM upkeep_registrations`) - require.NoError(t, err) - return upkeep.LastRunBlockHeight - }, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal(int64(200))) - - g.Eventually(func() int64 { - var upkeep keeper.UpkeepRegistration - err := db.Get(&upkeep, `SELECT * FROM upkeep_registrations`) - require.NoError(t, err) - return upkeep.LastKeeperIndex.Int64 - }, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal(int64(0))) -} - -func Test_RegistrySynchronizer1_3_UpkeepGasLimitSetLog(t *testing.T) { - ctx := testutils.Context(t) - g := gomega.NewWithT(t) - db, synchronizer, ethMock, lb, job := setupRegistrySync(t, keeper.RegistryVersion_1_3) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - - mockRegistry1_3( - t, - ethMock, - contractAddress, - registryConfig1_3, - []*big.Int{big.NewInt(3)}, // Upkeep IDs - []common.Address{fromAddress}, - upkeepConfig1_3, - 1, - 2, - 1) - - servicetest.Run(t, synchronizer) - cltest.WaitForCount(t, db, "keeper_registries", 1) - cltest.WaitForCount(t, db, "upkeep_registrations", 1) - - getExecuteGas := func() uint32 { - var upkeep keeper.UpkeepRegistration - err := db.Get(&upkeep, `SELECT * FROM upkeep_registrations`) - require.NoError(t, err) - return upkeep.ExecuteGas - } - g.Eventually(getExecuteGas, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal(uint32(2_000_000))) - - registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_3ABI, contractAddress) - newConfig := upkeepConfig1_3 - newConfig.ExecuteGas = 4_000_000 // change from default - registryMock.MockResponse("getUpkeep", newConfig).Once() - - head := cltest.MustInsertHead(t, db, 1) - rawLog := types.Log{BlockHash: head.Hash} - log := registry1_3.KeeperRegistryUpkeepGasLimitSet{Id: big.NewInt(3), GasLimit: big.NewInt(4_000_000)} - logBroadcast := logmocks.NewBroadcast(t) - logBroadcast.On("Start").Return(nil).Maybe() - logBroadcast.On("Close").Return(nil).Maybe() - logBroadcast.On("DecodedLog").Return(&log) - logBroadcast.On("RawLog").Return(rawLog) - logBroadcast.On("String").Maybe().Return("") - lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) - - // Do the thing - synchronizer.HandleLog(ctx, logBroadcast) - - g.Eventually(getExecuteGas, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal(uint32(4_000_000))) -} - -func Test_RegistrySynchronizer1_3_UpkeepReceivedLog(t *testing.T) { - ctx := testutils.Context(t) - db, synchronizer, ethMock, lb, job := setupRegistrySync(t, keeper.RegistryVersion_1_3) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - - mockRegistry1_3( - t, - ethMock, - contractAddress, - registryConfig1_3, - []*big.Int{big.NewInt(3)}, // Upkeep IDs - []common.Address{fromAddress}, - upkeepConfig1_3, - 1, - 2, - 1) - - servicetest.Run(t, synchronizer) - cltest.WaitForCount(t, db, "keeper_registries", 1) - cltest.WaitForCount(t, db, "upkeep_registrations", 1) - - registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_3ABI, contractAddress) - registryMock.MockResponse("getUpkeep", upkeepConfig1_3).Once() - - head := cltest.MustInsertHead(t, db, 1) - rawLog := types.Log{BlockHash: head.Hash} - log := registry1_3.KeeperRegistryUpkeepReceived{Id: big.NewInt(420)} - logBroadcast := logmocks.NewBroadcast(t) - logBroadcast.On("Start").Return(nil).Maybe() - logBroadcast.On("Close").Return(nil).Maybe() - logBroadcast.On("DecodedLog").Return(&log) - logBroadcast.On("RawLog").Return(rawLog) - logBroadcast.On("String").Maybe().Return("") - lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) - - // Do the thing - synchronizer.HandleLog(ctx, logBroadcast) - - cltest.WaitForCount(t, db, "upkeep_registrations", 2) -} - -func Test_RegistrySynchronizer1_3_UpkeepMigratedLog(t *testing.T) { - ctx := testutils.Context(t) - db, synchronizer, ethMock, lb, job := setupRegistrySync(t, keeper.RegistryVersion_1_3) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - - mockRegistry1_3( - t, - ethMock, - contractAddress, - registryConfig1_3, - []*big.Int{big.NewInt(3), big.NewInt(69), big.NewInt(420)}, // Upkeep IDs - []common.Address{fromAddress}, - upkeepConfig1_3, - 3, - 2, - 1) - - servicetest.Run(t, synchronizer) - cltest.WaitForCount(t, db, "keeper_registries", 1) - cltest.WaitForCount(t, db, "upkeep_registrations", 3) - - head := cltest.MustInsertHead(t, db, 1) - rawLog := types.Log{BlockHash: head.Hash} - log := registry1_3.KeeperRegistryUpkeepMigrated{Id: big.NewInt(3)} - logBroadcast := logmocks.NewBroadcast(t) - logBroadcast.On("Start").Return(nil).Maybe() - logBroadcast.On("Close").Return(nil).Maybe() - logBroadcast.On("DecodedLog").Return(&log) - logBroadcast.On("RawLog").Return(rawLog) - logBroadcast.On("String").Maybe().Return("") - lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) - - // Do the thing - synchronizer.HandleLog(ctx, logBroadcast) - - // race condition: "wait for count" - cltest.WaitForCount(t, db, "upkeep_registrations", 2) -} - -func Test_RegistrySynchronizer1_3_UpkeepPausedLog_UpkeepUnpausedLog(t *testing.T) { - ctx := testutils.Context(t) - db, synchronizer, ethMock, lb, job := setupRegistrySync(t, keeper.RegistryVersion_1_3) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - upkeepId := big.NewInt(3) - - mockRegistry1_3( - t, - ethMock, - contractAddress, - registryConfig1_3, - []*big.Int{big.NewInt(3), big.NewInt(69), big.NewInt(420)}, // Upkeep IDs - []common.Address{fromAddress}, - upkeepConfig1_3, - 4, - 2, - 1) - - servicetest.Run(t, synchronizer) - cltest.WaitForCount(t, db, "keeper_registries", 1) - cltest.WaitForCount(t, db, "upkeep_registrations", 3) - - head := cltest.MustInsertHead(t, db, 1) - rawLog := types.Log{BlockHash: head.Hash} - log := registry1_3.KeeperRegistryUpkeepPaused{Id: upkeepId} - logBroadcast := logmocks.NewBroadcast(t) - logBroadcast.On("Start").Return(nil).Maybe() - logBroadcast.On("Close").Return(nil).Maybe() - logBroadcast.On("DecodedLog").Return(&log) - logBroadcast.On("RawLog").Return(rawLog) - logBroadcast.On("String").Maybe().Return("") - lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) - - // Do the thing - synchronizer.HandleLog(ctx, logBroadcast) - - cltest.WaitForCount(t, db, "upkeep_registrations", 2) - - head = cltest.MustInsertHead(t, db, 2) - rawLog = types.Log{BlockHash: head.Hash} - unpausedlog := registry1_3.KeeperRegistryUpkeepUnpaused{Id: upkeepId} - logBroadcast = logmocks.NewBroadcast(t) - logBroadcast.On("DecodedLog").Return(&unpausedlog) - logBroadcast.On("RawLog").Return(rawLog) - logBroadcast.On("String").Maybe().Return("") - lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) - - // Do the thing - synchronizer.HandleLog(ctx, logBroadcast) - - cltest.WaitForCount(t, db, "upkeep_registrations", 3) - var upkeep keeper.UpkeepRegistration - err := db.Get(&upkeep, `SELECT * FROM upkeep_registrations WHERE upkeep_id = $1`, sqlutil.New(upkeepId)) - require.NoError(t, err) - - require.Equal(t, upkeepId.String(), upkeep.UpkeepID.String()) - require.Equal(t, upkeepConfig1_3.CheckData, upkeep.CheckData) - require.Equal(t, upkeepConfig1_3.ExecuteGas, upkeep.ExecuteGas) - - var registryId int64 - err = db.Get(®istryId, `SELECT id from keeper_registries WHERE job_id = $1`, job.ID) - require.NoError(t, err) - require.Equal(t, registryId, upkeep.RegistryID) -} - -func Test_RegistrySynchronizer1_3_UpkeepCheckDataUpdatedLog(t *testing.T) { - ctx := testutils.Context(t) - g := gomega.NewWithT(t) - db, synchronizer, ethMock, lb, job := setupRegistrySync(t, keeper.RegistryVersion_1_3) - - contractAddress := job.KeeperSpec.ContractAddress.Address() - fromAddress := job.KeeperSpec.FromAddress.Address() - upkeepId := big.NewInt(3) - - mockRegistry1_3( - t, - ethMock, - contractAddress, - registryConfig1_3, - []*big.Int{upkeepId}, // Upkeep IDs - []common.Address{fromAddress}, - upkeepConfig1_3, - 1, - 2, - 1) - - servicetest.Run(t, synchronizer) - cltest.WaitForCount(t, db, "keeper_registries", 1) - cltest.WaitForCount(t, db, "upkeep_registrations", 1) - - head := cltest.MustInsertHead(t, db, 1) - rawLog := types.Log{BlockHash: head.Hash} - _ = logmocks.NewBroadcast(t) - newCheckData := []byte("Chainlink") - registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_3ABI, contractAddress) - newConfig := upkeepConfig1_3 - newConfig.CheckData = newCheckData // changed from default - registryMock.MockResponse("getUpkeep", newConfig).Once() - - updatedLog := registry1_3.KeeperRegistryUpkeepCheckDataUpdated{Id: upkeepId, NewCheckData: newCheckData} - logBroadcast := logmocks.NewBroadcast(t) - logBroadcast.On("Start").Return(nil).Maybe() - logBroadcast.On("Close").Return(nil).Maybe() - logBroadcast.On("DecodedLog").Return(&updatedLog) - logBroadcast.On("RawLog").Return(rawLog) - logBroadcast.On("String").Maybe().Return("") - lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) - - // Do the thing - synchronizer.HandleLog(ctx, logBroadcast) - - g.Eventually(func() []byte { - var upkeep keeper.UpkeepRegistration - err := db.Get(&upkeep, `SELECT * FROM upkeep_registrations WHERE upkeep_id = $1`, sqlutil.New(upkeepId)) - require.NoError(t, err) - return upkeep.CheckData - }, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal(newCheckData)) -} diff --git a/core/services/keeper/registry_interface.go b/core/services/keeper/registry_interface.go deleted file mode 100644 index 10ba57c7d1f..00000000000 --- a/core/services/keeper/registry_interface.go +++ /dev/null @@ -1,384 +0,0 @@ -package keeper - -import ( - "context" - "fmt" - "math/big" - "strings" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/pkg/errors" - - registry1_1 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_1" - registry1_2 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_2" - registry1_3 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_3" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/initial/type_and_version" - evmclient "github.com/smartcontractkit/chainlink-evm/pkg/client" - evmtypes "github.com/smartcontractkit/chainlink-evm/pkg/types" -) - -type RegistryVersion int32 - -const ( - RegistryVersion_1_0 RegistryVersion = iota - RegistryVersion_1_1 - RegistryVersion_1_2 - RegistryVersion_1_3 - RegistryVersion_2_0 - RegistryVersion_2_1 -) - -func (rv RegistryVersion) String() string { - switch rv { - case RegistryVersion_1_0, RegistryVersion_1_1, RegistryVersion_1_2, RegistryVersion_1_3: - return fmt.Sprintf("v1.%d", rv) - case RegistryVersion_2_0: - return "v2.0" - default: - return "unknown registry version" - } -} - -const ActiveUpkeepIDBatchSize int64 = 10000 - -// upkeepGetter is declared as a private interface as it is only needed -// internally to the keeper package for now -type upkeepGetter interface { - GetUpkeep(*bind.CallOpts, *big.Int) (*UpkeepConfig, error) -} - -// RegistryWrapper implements a layer on top of different versions of registry wrappers -// to provide a unified layer to rest of the codebase -type RegistryWrapper struct { - Address evmtypes.EIP55Address - Version RegistryVersion - contract1_1 *registry1_1.KeeperRegistry - contract1_2 *registry1_2.KeeperRegistry - contract1_3 *registry1_3.KeeperRegistry - evmClient evmclient.Client -} - -func NewRegistryWrapper(address evmtypes.EIP55Address, evmClient evmclient.Client) (*RegistryWrapper, error) { - interfaceWrapper, err := type_and_version.NewITypeAndVersion( - address.Address(), - evmClient, - ) - if err != nil { - return nil, errors.Wrap(err, "unable to create type and interface wrapper") - } - version, err := getRegistryVersion(interfaceWrapper) - if err != nil { - return nil, errors.Wrap(err, "unable to determine version of keeper registry contract") - } - - contract1_1, err := registry1_1.NewKeeperRegistry( - address.Address(), - evmClient, - ) - if err != nil { - return nil, errors.Wrap(err, "unable to create keeper registry 1_1 contract wrapper") - } - contract1_2, err := registry1_2.NewKeeperRegistry( - address.Address(), - evmClient, - ) - if err != nil { - return nil, errors.Wrap(err, "unable to create keeper registry 1_2 contract wrapper") - } - contract1_3, err := registry1_3.NewKeeperRegistry( - address.Address(), - evmClient, - ) - if err != nil { - return nil, errors.Wrap(err, "unable to create keeper registry 1_3 contract wrapper") - } - - return &RegistryWrapper{ - Address: address, - Version: *version, - contract1_1: contract1_1, - contract1_2: contract1_2, - contract1_3: contract1_3, - evmClient: evmClient, - }, nil -} - -func getRegistryVersion(contract *type_and_version.ITypeAndVersion) (*RegistryVersion, error) { - typeAndVersion, err := contract.TypeAndVersion(nil) - if err != nil { - jsonErr := evmclient.ExtractRPCErrorOrNil(err) - if jsonErr != nil { - // Version 1.0 does not support typeAndVersion interface, hence gives a json error on this call - version := RegistryVersion_1_0 - return &version, nil - } - return nil, errors.Wrap(err, "unable to fetch version of registry") - } - switch { - case strings.HasPrefix(typeAndVersion, "KeeperRegistry 1.1"): - version := RegistryVersion_1_1 - return &version, nil - case strings.HasPrefix(typeAndVersion, "KeeperRegistry 1.2"): - version := RegistryVersion_1_2 - return &version, nil - case strings.HasPrefix(typeAndVersion, "KeeperRegistry 1.3"): - version := RegistryVersion_1_3 - return &version, nil - default: - return nil, errors.Errorf("Registry type and version %s not supported", typeAndVersion) - } -} - -func newUnsupportedVersionError(functionName string, version RegistryVersion) error { - return errors.Errorf("Registry version %d does not support %s", version, functionName) -} - -// getUpkeepCount retrieves the number of upkeeps -func (rw *RegistryWrapper) getUpkeepCount(opts *bind.CallOpts) (*big.Int, error) { - switch rw.Version { - case RegistryVersion_1_0, RegistryVersion_1_1: - upkeepCount, err := rw.contract1_1.GetUpkeepCount(opts) - if err != nil { - return nil, errors.Wrap(err, "failed to get upkeep count") - } - return upkeepCount, nil - case RegistryVersion_1_2: - state, err := rw.contract1_2.GetState(opts) - if err != nil { - return nil, errors.Wrapf(err, "failed to get contract state at block number %d", opts.BlockNumber.Int64()) - } - return state.State.NumUpkeeps, nil - case RegistryVersion_1_3: - state, err := rw.contract1_3.GetState(opts) - if err != nil { - return nil, errors.Wrapf(err, "failed to get contract state at block number %d", opts.BlockNumber.Int64()) - } - return state.State.NumUpkeeps, nil - default: - return nil, newUnsupportedVersionError("getUpkeepCount", rw.Version) - } -} - -func (rw *RegistryWrapper) GetActiveUpkeepIDs(ctx context.Context, opts *bind.CallOpts) ([]*big.Int, error) { - if opts == nil || opts.BlockNumber.Int64() == 0 { - var head *evmtypes.Head - // fetch the current block number so batched GetActiveUpkeepIDs calls can be performed on the same block - head, err := rw.evmClient.HeadByNumber(ctx, nil) - if err != nil { - return nil, errors.Wrap(err, "failed to fetch EVM block header") - } - if opts != nil { - opts.BlockNumber = big.NewInt(head.Number) - } else { - opts = &bind.CallOpts{ - BlockNumber: big.NewInt(head.Number), - } - } - } - - upkeepCount, err := rw.getUpkeepCount(opts) - if err != nil { - return nil, errors.Wrap(err, "failed to get upkeep count") - } - switch rw.Version { - case RegistryVersion_1_0, RegistryVersion_1_1: - cancelledUpkeeps, err2 := rw.contract1_1.GetCanceledUpkeepList(opts) - if err2 != nil { - return nil, errors.Wrap(err2, "failed to get cancelled upkeeps") - } - cancelledSet := make(map[int64]bool) - for _, upkeepID := range cancelledUpkeeps { - cancelledSet[upkeepID.Int64()] = true - } - // Active upkeep IDs are 0,1 ... upkeepCount-1, removing the cancelled ones - activeUpkeeps := make([]*big.Int, 0) - for i := int64(0); i < upkeepCount.Int64(); i++ { - if _, found := cancelledSet[i]; !found { - activeUpkeeps = append(activeUpkeeps, big.NewInt(i)) - } - } - return activeUpkeeps, nil - case RegistryVersion_1_2, RegistryVersion_1_3: - activeUpkeepIDs := make([]*big.Int, 0) - var activeUpkeepIDBatch []*big.Int - for int64(len(activeUpkeepIDs)) < upkeepCount.Int64() { - startIndex := int64(len(activeUpkeepIDs)) - maxCount := min(upkeepCount.Int64()-int64(len(activeUpkeepIDs)), ActiveUpkeepIDBatchSize) - if rw.Version == RegistryVersion_1_2 { - activeUpkeepIDBatch, err = rw.contract1_2.GetActiveUpkeepIDs(opts, big.NewInt(startIndex), big.NewInt(maxCount)) - } else { - activeUpkeepIDBatch, err = rw.contract1_3.GetActiveUpkeepIDs(opts, big.NewInt(startIndex), big.NewInt(maxCount)) - } - if err != nil { - return nil, errors.Wrapf(err, "failed to get active upkeep IDs from index %d to %d (both inclusive)", startIndex, startIndex+maxCount-1) - } - activeUpkeepIDs = append(activeUpkeepIDs, activeUpkeepIDBatch...) - } - - return activeUpkeepIDs, nil - default: - return nil, newUnsupportedVersionError("GetActiveUpkeepIDs", rw.Version) - } -} - -type UpkeepConfig struct { - ExecuteGas uint32 - CheckData []byte - LastKeeper common.Address -} - -func (rw *RegistryWrapper) GetUpkeep(opts *bind.CallOpts, id *big.Int) (*UpkeepConfig, error) { - switch rw.Version { - case RegistryVersion_1_0, RegistryVersion_1_1: - upkeep, err := rw.contract1_1.GetUpkeep(opts, id) - if err != nil { - return nil, errors.Wrap(err, "failed to get upkeep config") - } - return &UpkeepConfig{ - ExecuteGas: upkeep.ExecuteGas, - CheckData: upkeep.CheckData, - LastKeeper: upkeep.LastKeeper, - }, nil - case RegistryVersion_1_2: - upkeep, err := rw.contract1_2.GetUpkeep(opts, id) - if err != nil { - return nil, errors.Wrap(err, "failed to get upkeep config") - } - return &UpkeepConfig{ - ExecuteGas: upkeep.ExecuteGas, - CheckData: upkeep.CheckData, - LastKeeper: upkeep.LastKeeper, - }, nil - case RegistryVersion_1_3: - upkeep, err := rw.contract1_3.GetUpkeep(opts, id) - if err != nil { - return nil, errors.Wrap(err, "failed to get upkeep config") - } - return &UpkeepConfig{ - ExecuteGas: upkeep.ExecuteGas, - CheckData: upkeep.CheckData, - LastKeeper: upkeep.LastKeeper, - }, nil - default: - return nil, newUnsupportedVersionError("GetUpkeep", rw.Version) - } -} - -type RegistryConfig struct { - BlockCountPerTurn int32 - CheckGas uint32 - KeeperAddresses []common.Address -} - -func (rw *RegistryWrapper) GetConfig(opts *bind.CallOpts) (*RegistryConfig, error) { - switch rw.Version { - case RegistryVersion_1_0, RegistryVersion_1_1: - config, err := rw.contract1_1.GetConfig(opts) - if err != nil { - // TODO: error wrapping with %w should be done here to preserve the error type as it bubbles up - // pkg/errors doesn't support the native errors.Is/As capabilities - // using pkg/errors produces a stack trace in the logs and this behavior is too valuable to let go - return nil, errors.Errorf("%s [%s]: getConfig %s", ErrContractCallFailure, err, rw.Version) - } - keeperAddresses, err := rw.contract1_1.GetKeeperList(opts) - if err != nil { - return nil, errors.Errorf("%s [%s]: getKeeperList %s", ErrContractCallFailure, err, rw.Version) - } - return &RegistryConfig{ - BlockCountPerTurn: int32(config.BlockCountPerTurn.Int64()), - CheckGas: config.CheckGasLimit, - KeeperAddresses: keeperAddresses, - }, nil - case RegistryVersion_1_2: - state, err := rw.contract1_2.GetState(opts) - if err != nil { - return nil, errors.Errorf("%s [%s]: getState %s", ErrContractCallFailure, err, rw.Version) - } - - return &RegistryConfig{ - BlockCountPerTurn: int32(state.Config.BlockCountPerTurn.Int64()), - CheckGas: state.Config.CheckGasLimit, - KeeperAddresses: state.Keepers, - }, nil - case RegistryVersion_1_3: - state, err := rw.contract1_3.GetState(opts) - if err != nil { - return nil, errors.Errorf("%s [%s]: getState %s", ErrContractCallFailure, err, rw.Version) - } - - return &RegistryConfig{ - BlockCountPerTurn: int32(state.Config.BlockCountPerTurn.Int64()), - CheckGas: state.Config.CheckGasLimit, - KeeperAddresses: state.Keepers, - }, nil - default: - return nil, newUnsupportedVersionError("GetConfig", rw.Version) - } -} - -func (rw *RegistryWrapper) SetKeepers(opts *bind.TransactOpts, keepers []common.Address, payees []common.Address) (*types.Transaction, error) { - switch rw.Version { - case RegistryVersion_1_0, RegistryVersion_1_1: - return rw.contract1_1.SetKeepers(opts, keepers, payees) - case RegistryVersion_1_2: - return rw.contract1_2.SetKeepers(opts, keepers, payees) - case RegistryVersion_1_3: - return rw.contract1_3.SetKeepers(opts, keepers, payees) - default: - return nil, newUnsupportedVersionError("SetKeepers", rw.Version) - } -} - -func (rw *RegistryWrapper) RegisterUpkeep(opts *bind.TransactOpts, target common.Address, gasLimit uint32, admin common.Address, checkData []byte) (*types.Transaction, error) { - switch rw.Version { - case RegistryVersion_1_0, RegistryVersion_1_1: - return rw.contract1_1.RegisterUpkeep(opts, target, gasLimit, admin, checkData) - case RegistryVersion_1_2: - return rw.contract1_2.RegisterUpkeep(opts, target, gasLimit, admin, checkData) - case RegistryVersion_1_3: - return rw.contract1_3.RegisterUpkeep(opts, target, gasLimit, admin, checkData) - default: - return nil, newUnsupportedVersionError("RegisterUpkeep", rw.Version) - } -} - -func (rw *RegistryWrapper) AddFunds(opts *bind.TransactOpts, id *big.Int, amount *big.Int) (*types.Transaction, error) { - switch rw.Version { - case RegistryVersion_1_0, RegistryVersion_1_1: - return rw.contract1_1.AddFunds(opts, id, amount) - case RegistryVersion_1_2: - return rw.contract1_2.AddFunds(opts, id, amount) - case RegistryVersion_1_3: - return rw.contract1_3.AddFunds(opts, id, amount) - default: - return nil, newUnsupportedVersionError("AddFunds", rw.Version) - } -} - -func (rw *RegistryWrapper) PerformUpkeep(opts *bind.TransactOpts, id *big.Int, performData []byte) (*types.Transaction, error) { - switch rw.Version { - case RegistryVersion_1_0, RegistryVersion_1_1: - return rw.contract1_1.PerformUpkeep(opts, id, performData) - case RegistryVersion_1_2: - return rw.contract1_2.PerformUpkeep(opts, id, performData) - case RegistryVersion_1_3: - return rw.contract1_3.PerformUpkeep(opts, id, performData) - default: - return nil, newUnsupportedVersionError("PerformUpkeep", rw.Version) - } -} - -func (rw *RegistryWrapper) CancelUpkeep(opts *bind.TransactOpts, id *big.Int) (*types.Transaction, error) { - switch rw.Version { - case RegistryVersion_1_0, RegistryVersion_1_1: - return rw.contract1_1.CancelUpkeep(opts, id) - case RegistryVersion_1_2: - return rw.contract1_2.CancelUpkeep(opts, id) - case RegistryVersion_1_3: - return rw.contract1_3.CancelUpkeep(opts, id) - default: - return nil, newUnsupportedVersionError("CancelUpkeep", rw.Version) - } -} diff --git a/core/services/keeper/registry_interface_logs.go b/core/services/keeper/registry_interface_logs.go deleted file mode 100644 index 127ed62b9ec..00000000000 --- a/core/services/keeper/registry_interface_logs.go +++ /dev/null @@ -1,267 +0,0 @@ -package keeper - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/pkg/errors" - - registry1_1 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_1" - registry1_2 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_2" - registry1_3 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_3" - "github.com/smartcontractkit/chainlink-evm/pkg/log" -) - -func (rw *RegistryWrapper) GetLogListenerOpts(minIncomingConfirmations uint32, upkeepPerformedFilter [][]log.Topic) (*log.ListenerOpts, error) { - switch rw.Version { - case RegistryVersion_1_0, RegistryVersion_1_1: - return &log.ListenerOpts{ - Contract: rw.contract1_1.Address(), - ParseLog: rw.contract1_1.ParseLog, - LogsWithTopics: map[common.Hash][][]log.Topic{ - registry1_1.KeeperRegistryKeepersUpdated{}.Topic(): nil, - registry1_1.KeeperRegistryConfigSet{}.Topic(): nil, - registry1_1.KeeperRegistryUpkeepCanceled{}.Topic(): nil, - registry1_1.KeeperRegistryUpkeepRegistered{}.Topic(): nil, - registry1_1.KeeperRegistryUpkeepPerformed{}.Topic(): upkeepPerformedFilter, - }, - MinIncomingConfirmations: minIncomingConfirmations, - }, nil - case RegistryVersion_1_2: - return &log.ListenerOpts{ - Contract: rw.contract1_2.Address(), - ParseLog: rw.contract1_2.ParseLog, - LogsWithTopics: map[common.Hash][][]log.Topic{ - registry1_2.KeeperRegistryKeepersUpdated{}.Topic(): nil, - registry1_2.KeeperRegistryConfigSet{}.Topic(): nil, - registry1_2.KeeperRegistryUpkeepCanceled{}.Topic(): nil, - registry1_2.KeeperRegistryUpkeepRegistered{}.Topic(): nil, - registry1_2.KeeperRegistryUpkeepPerformed{}.Topic(): upkeepPerformedFilter, - registry1_2.KeeperRegistryUpkeepGasLimitSet{}.Topic(): nil, - registry1_2.KeeperRegistryUpkeepMigrated{}.Topic(): nil, - registry1_2.KeeperRegistryUpkeepReceived{}.Topic(): nil, - }, - MinIncomingConfirmations: minIncomingConfirmations, - }, nil - case RegistryVersion_1_3: - return &log.ListenerOpts{ - Contract: rw.contract1_3.Address(), - ParseLog: rw.contract1_3.ParseLog, - LogsWithTopics: map[common.Hash][][]log.Topic{ - registry1_3.KeeperRegistryKeepersUpdated{}.Topic(): nil, - registry1_3.KeeperRegistryConfigSet{}.Topic(): nil, - registry1_3.KeeperRegistryUpkeepCanceled{}.Topic(): nil, - registry1_3.KeeperRegistryUpkeepRegistered{}.Topic(): nil, - registry1_3.KeeperRegistryUpkeepPerformed{}.Topic(): upkeepPerformedFilter, - registry1_3.KeeperRegistryUpkeepGasLimitSet{}.Topic(): nil, - registry1_3.KeeperRegistryUpkeepMigrated{}.Topic(): nil, - registry1_3.KeeperRegistryUpkeepReceived{}.Topic(): nil, - registry1_3.KeeperRegistryUpkeepPaused{}.Topic(): nil, - registry1_3.KeeperRegistryUpkeepUnpaused{}.Topic(): nil, - registry1_3.KeeperRegistryUpkeepCheckDataUpdated{}.Topic(): nil, - }, - MinIncomingConfirmations: minIncomingConfirmations, - }, nil - default: - return nil, newUnsupportedVersionError("GetLogListenerOpts", rw.Version) - } -} - -func (rw *RegistryWrapper) GetCancelledUpkeepIDFromLog(broadcast log.Broadcast) (*big.Int, error) { - switch rw.Version { - case RegistryVersion_1_0, RegistryVersion_1_1: - broadcastedLog, ok := broadcast.DecodedLog().(*registry1_1.KeeperRegistryUpkeepCanceled) - if !ok { - return nil, errors.Errorf("expected UpkeepCanceled log but got %T", broadcastedLog) - } - return broadcastedLog.Id, nil - case RegistryVersion_1_2: - broadcastedLog, ok := broadcast.DecodedLog().(*registry1_2.KeeperRegistryUpkeepCanceled) - if !ok { - return nil, errors.Errorf("expected UpkeepCanceled log but got %T", broadcastedLog) - } - return broadcastedLog.Id, nil - case RegistryVersion_1_3: - broadcastedLog, ok := broadcast.DecodedLog().(*registry1_3.KeeperRegistryUpkeepCanceled) - if !ok { - return nil, errors.Errorf("expected UpkeepCanceled log but got %T", broadcastedLog) - } - return broadcastedLog.Id, nil - default: - return nil, newUnsupportedVersionError("GetCancelledUpkeepIDFromLog", rw.Version) - } -} - -func (rw *RegistryWrapper) GetUpkeepIdFromRegistrationLog(broadcast log.Broadcast) (*big.Int, error) { - switch rw.Version { - case RegistryVersion_1_0, RegistryVersion_1_1: - broadcastedLog, ok := broadcast.DecodedLog().(*registry1_1.KeeperRegistryUpkeepRegistered) - if !ok { - return nil, errors.Errorf("expected UpkeepRegistered log but got %T", broadcastedLog) - } - return broadcastedLog.Id, nil - case RegistryVersion_1_2: - broadcastedLog, ok := broadcast.DecodedLog().(*registry1_2.KeeperRegistryUpkeepRegistered) - if !ok { - return nil, errors.Errorf("expected UpkeepRegistered log but got %T", broadcastedLog) - } - return broadcastedLog.Id, nil - case RegistryVersion_1_3: - broadcastedLog, ok := broadcast.DecodedLog().(*registry1_3.KeeperRegistryUpkeepRegistered) - if !ok { - return nil, errors.Errorf("expected UpkeepRegistered log but got %T", broadcastedLog) - } - return broadcastedLog.Id, nil - default: - return nil, newUnsupportedVersionError("GetUpkeepIdFromRegistrationLog", rw.Version) - } -} - -type UpkeepPerformedLog struct { - UpkeepID *big.Int - FromKeeper common.Address -} - -func (rw *RegistryWrapper) ParseUpkeepPerformedLog(broadcast log.Broadcast) (*UpkeepPerformedLog, error) { - switch rw.Version { - case RegistryVersion_1_0, RegistryVersion_1_1: - broadcastedLog, ok := broadcast.DecodedLog().(*registry1_1.KeeperRegistryUpkeepPerformed) - if !ok { - return nil, errors.Errorf("expected UpkeepPerformed log but got %T", broadcastedLog) - } - return &UpkeepPerformedLog{ - UpkeepID: broadcastedLog.Id, - FromKeeper: broadcastedLog.From, - }, nil - case RegistryVersion_1_2: - broadcastedLog, ok := broadcast.DecodedLog().(*registry1_2.KeeperRegistryUpkeepPerformed) - if !ok { - return nil, errors.Errorf("expected UpkeepPerformed log but got %T", broadcastedLog) - } - return &UpkeepPerformedLog{ - UpkeepID: broadcastedLog.Id, - FromKeeper: broadcastedLog.From, - }, nil - case RegistryVersion_1_3: - broadcastedLog, ok := broadcast.DecodedLog().(*registry1_3.KeeperRegistryUpkeepPerformed) - if !ok { - return nil, errors.Errorf("expected UpkeepPerformed log but got %T", broadcastedLog) - } - return &UpkeepPerformedLog{ - UpkeepID: broadcastedLog.Id, - FromKeeper: broadcastedLog.From, - }, nil - default: - return nil, newUnsupportedVersionError("ParseUpkeepPerformedLog", rw.Version) - } -} - -func (rw *RegistryWrapper) GetIDFromGasLimitSetLog(broadcast log.Broadcast) (*big.Int, error) { - // Only supported on 1.2 and 1.3 - switch rw.Version { - case RegistryVersion_1_2: - broadcastedLog, ok := broadcast.DecodedLog().(*registry1_2.KeeperRegistryUpkeepGasLimitSet) - if !ok { - return nil, errors.Errorf("expected UpkeepGasLimitSetlog but got %T", broadcastedLog) - } - return broadcastedLog.Id, nil - case RegistryVersion_1_3: - broadcastedLog, ok := broadcast.DecodedLog().(*registry1_3.KeeperRegistryUpkeepGasLimitSet) - if !ok { - return nil, errors.Errorf("expected UpkeepGasLimitSetlog but got %T", broadcastedLog) - } - return broadcastedLog.Id, nil - default: - return nil, newUnsupportedVersionError("GetIDFromGasLimitSetLog", rw.Version) - } -} - -func (rw *RegistryWrapper) GetUpkeepIdFromReceivedLog(broadcast log.Broadcast) (*big.Int, error) { - // Only supported on 1.2 and 1.3 - switch rw.Version { - case RegistryVersion_1_2: - broadcastedLog, ok := broadcast.DecodedLog().(*registry1_2.KeeperRegistryUpkeepReceived) - if !ok { - return nil, errors.Errorf("expected UpkeepReceived log but got %T", broadcastedLog) - } - return broadcastedLog.Id, nil - case RegistryVersion_1_3: - broadcastedLog, ok := broadcast.DecodedLog().(*registry1_3.KeeperRegistryUpkeepReceived) - if !ok { - return nil, errors.Errorf("expected UpkeepReceived log but got %T", broadcastedLog) - } - return broadcastedLog.Id, nil - default: - return nil, newUnsupportedVersionError("GetUpkeepIdFromReceivedLog", rw.Version) - } -} - -func (rw *RegistryWrapper) GetUpkeepIdFromMigratedLog(broadcast log.Broadcast) (*big.Int, error) { - // Only supported on 1.2 and 1.3 - switch rw.Version { - case RegistryVersion_1_2: - broadcastedLog, ok := broadcast.DecodedLog().(*registry1_2.KeeperRegistryUpkeepMigrated) - if !ok { - return nil, errors.Errorf("expected UpkeepMigrated log but got %T", broadcastedLog) - } - return broadcastedLog.Id, nil - case RegistryVersion_1_3: - broadcastedLog, ok := broadcast.DecodedLog().(*registry1_3.KeeperRegistryUpkeepMigrated) - if !ok { - return nil, errors.Errorf("expected UpkeepMigrated log but got %T", broadcastedLog) - } - return broadcastedLog.Id, nil - default: - return nil, newUnsupportedVersionError("GetUpkeepIdFromMigratedLog", rw.Version) - } -} - -func (rw *RegistryWrapper) GetUpkeepIdFromUpkeepPausedLog(broadcast log.Broadcast) (*big.Int, error) { - // Only supported on 1.3 - switch rw.Version { - case RegistryVersion_1_3: - broadcastedLog, ok := broadcast.DecodedLog().(*registry1_3.KeeperRegistryUpkeepPaused) - if !ok { - return nil, errors.Errorf("expected UpkeepPaused log but got %T", broadcastedLog) - } - return broadcastedLog.Id, nil - default: - return nil, newUnsupportedVersionError("GetUpkeepIdFromUpkeepPausedLog", rw.Version) - } -} - -func (rw *RegistryWrapper) GetUpkeepIdFromUpkeepUnpausedLog(broadcast log.Broadcast) (*big.Int, error) { - // Only supported on 1.3 - switch rw.Version { - case RegistryVersion_1_3: - broadcastedLog, ok := broadcast.DecodedLog().(*registry1_3.KeeperRegistryUpkeepUnpaused) - if !ok { - return nil, errors.Errorf("expected UpkeepUnpaused log but got %T", broadcastedLog) - } - return broadcastedLog.Id, nil - default: - return nil, newUnsupportedVersionError("GetUpkeepIdFromUpkeepUnpausedLog", rw.Version) - } -} - -type UpkeepCheckDataUpdatedLog struct { - UpkeepID *big.Int - NewCheckData []byte -} - -func (rw *RegistryWrapper) ParseUpkeepCheckDataUpdatedLog(broadcast log.Broadcast) (*UpkeepCheckDataUpdatedLog, error) { - // Only supported on 1.3 - switch rw.Version { - case RegistryVersion_1_3: - broadcastedLog, ok := broadcast.DecodedLog().(*registry1_3.KeeperRegistryUpkeepCheckDataUpdated) - if !ok { - return nil, errors.Errorf("expected UpkeepCheckDataUpdated log but got %T", broadcastedLog) - } - return &UpkeepCheckDataUpdatedLog{ - UpkeepID: broadcastedLog.Id, - NewCheckData: broadcastedLog.NewCheckData, - }, nil - default: - return nil, newUnsupportedVersionError("GetUpkeepIdFromUpkeepPausedLog", rw.Version) - } -} diff --git a/core/services/keeper/registry_synchronizer_core.go b/core/services/keeper/registry_synchronizer_core.go deleted file mode 100644 index 0f05afeafc3..00000000000 --- a/core/services/keeper/registry_synchronizer_core.go +++ /dev/null @@ -1,133 +0,0 @@ -package keeper - -import ( - "context" - "strconv" - "sync" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/pkg/errors" - - "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" - - "github.com/smartcontractkit/chainlink-evm/pkg/log" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/utils" -) - -// RegistrySynchronizer conforms to the Service and Listener interfaces -var ( - _ job.ServiceCtx = (*RegistrySynchronizer)(nil) - _ log.Listener = (*RegistrySynchronizer)(nil) -) - -type RegistrySynchronizerOptions struct { - Job job.Job - RegistryWrapper RegistryWrapper - ORM *ORM - JRM job.ORM - LogBroadcaster log.Broadcaster - MailMon *mailbox.Monitor - SyncInterval time.Duration - MinIncomingConfirmations uint32 - Logger logger.Logger - SyncUpkeepQueueSize uint32 - EffectiveKeeperAddress common.Address -} - -type RegistrySynchronizer struct { - services.StateMachine - chStop services.StopChan - registryWrapper RegistryWrapper - interval time.Duration - job job.Job - jrm job.ORM - logBroadcaster log.Broadcaster - mbLogs *mailbox.Mailbox[log.Broadcast] - minIncomingConfirmations uint32 - effectiveKeeperAddress common.Address - orm *ORM - logger logger.SugaredLogger - wgDone sync.WaitGroup - syncUpkeepQueueSize uint32 // Represents the max number of upkeeps that can be synced in parallel - mailMon *mailbox.Monitor -} - -// NewRegistrySynchronizer is the constructor of RegistrySynchronizer -func NewRegistrySynchronizer(opts RegistrySynchronizerOptions) *RegistrySynchronizer { - return &RegistrySynchronizer{ - chStop: make(chan struct{}), - registryWrapper: opts.RegistryWrapper, - interval: opts.SyncInterval, - job: opts.Job, - jrm: opts.JRM, - logBroadcaster: opts.LogBroadcaster, - mbLogs: mailbox.New[log.Broadcast](5_000), // Arbitrary limit, better to have excess capacity - minIncomingConfirmations: opts.MinIncomingConfirmations, - orm: opts.ORM, - effectiveKeeperAddress: opts.EffectiveKeeperAddress, - logger: logger.Sugared(opts.Logger.Named("RegistrySynchronizer")), - syncUpkeepQueueSize: opts.SyncUpkeepQueueSize, - mailMon: opts.MailMon, - } -} - -// Start starts RegistrySynchronizer. -func (rs *RegistrySynchronizer) Start(context.Context) error { - return rs.StartOnce("RegistrySynchronizer", func() error { - rs.wgDone.Add(2) - go rs.run() - - var upkeepPerformedFilter [][]log.Topic - - logListenerOpts, err := rs.registryWrapper.GetLogListenerOpts(rs.minIncomingConfirmations, upkeepPerformedFilter) - if err != nil { - return errors.Wrap(err, "Unable to fetch log listener opts from wrapper") - } - lbUnsubscribe := rs.logBroadcaster.Register(rs, *logListenerOpts) - - go func() { - defer rs.wgDone.Done() - defer lbUnsubscribe() - <-rs.chStop - }() - - rs.mailMon.Monitor(rs.mbLogs, "RegistrySynchronizer", "Logs", strconv.Itoa(int(rs.job.ID))) - - return nil - }) -} - -func (rs *RegistrySynchronizer) Close() error { - return rs.StopOnce("RegistrySynchronizer", func() error { - close(rs.chStop) - rs.wgDone.Wait() - return rs.mbLogs.Close() - }) -} - -func (rs *RegistrySynchronizer) run() { - syncTicker := utils.NewResettableTimer() - defer rs.wgDone.Done() - defer syncTicker.Stop() - - ctx, cancel := rs.chStop.NewCtx() - defer cancel() - - rs.fullSync(ctx) - - for { - select { - case <-rs.chStop: - return - case <-syncTicker.Ticks(): - rs.fullSync(ctx) - syncTicker.Reset(rs.interval) - case <-rs.mbLogs.Notify(): - rs.processLogs(ctx) - } - } -} diff --git a/core/services/keeper/registry_synchronizer_helper_test.go b/core/services/keeper/registry_synchronizer_helper_test.go deleted file mode 100644 index 08edda55391..00000000000 --- a/core/services/keeper/registry_synchronizer_helper_test.go +++ /dev/null @@ -1,109 +0,0 @@ -package keeper_test - -import ( - "math/big" - "testing" - "time" - - "github.com/onsi/gomega" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - - "github.com/jmoiron/sqlx" - - "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" - "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox/mailboxtest" - "github.com/smartcontractkit/chainlink-evm/pkg/client/clienttest" - "github.com/smartcontractkit/chainlink-evm/pkg/log" - logmocks "github.com/smartcontractkit/chainlink/v2/common/log/mocks" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/keeper" -) - -const syncInterval = 1000 * time.Hour // prevents sync timer from triggering during test -const syncUpkeepQueueSize = 10 - -func setupRegistrySync(t *testing.T, version keeper.RegistryVersion) ( - *sqlx.DB, - *keeper.RegistrySynchronizer, - *clienttest.Client, - *logmocks.Broadcaster, - job.Job, -) { - db := pgtest.NewSqlxDB(t) - cfg := configtest.NewGeneralConfig(t, nil) - korm := keeper.NewORM(db, logger.TestLogger(t)) - ethClient := cltest.NewEthMocksWithStartupAssertions(t) - ethClient.On("ConfiguredChainID").Return(big.NewInt(evmtest.NullClientChainID)).Maybe() - keyStore := cltest.NewKeyStore(t, db) - lbMock := logmocks.NewBroadcaster(t) - servicetest.SetupNoOpMock(lbMock) - lbMock.On("AddDependents", 1).Maybe() - j := cltest.MustInsertKeeperJob(t, db, korm, cltest.NewEIP55Address(), cltest.NewEIP55Address()) - legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{ - DB: db, - Client: ethClient, - LogBroadcaster: lbMock, - ChainConfigs: cfg.EVMConfigs(), - DatabaseConfig: cfg.Database(), - FeatureConfig: cfg.Feature(), - ListenerConfig: cfg.Database().Listener(), - KeyStore: keyStore.Eth(), - }) - jpv2 := NewJobPipelineV2(t, cfg.WebServer(), cfg.JobPipeline(), legacyChains, db, keyStore, nil, nil) - contractAddress := j.KeeperSpec.ContractAddress.Address() - - switch version { - case keeper.RegistryVersion_1_0, keeper.RegistryVersion_1_1: - registryMock := cltest.NewContractMockReceiver(t, ethClient, keeper.Registry1_1ABI, contractAddress) - registryMock.MockResponse("typeAndVersion", "KeeperRegistry 1.1.1").Once() - case keeper.RegistryVersion_1_2: - registryMock := cltest.NewContractMockReceiver(t, ethClient, keeper.Registry1_2ABI, contractAddress) - registryMock.MockResponse("typeAndVersion", "KeeperRegistry 1.2.0").Once() - case keeper.RegistryVersion_1_3: - registryMock := cltest.NewContractMockReceiver(t, ethClient, keeper.Registry1_3ABI, contractAddress) - registryMock.MockResponse("typeAndVersion", "KeeperRegistry 1.3.0").Once() - case keeper.RegistryVersion_2_0, keeper.RegistryVersion_2_1: - t.Fatalf("Unsupported version: %s", version) - } - - registryWrapper, err := keeper.NewRegistryWrapper(j.KeeperSpec.ContractAddress, ethClient) - require.NoError(t, err) - - lbMock.On("Register", mock.Anything, mock.MatchedBy(func(opts log.ListenerOpts) bool { - return opts.Contract == contractAddress - })).Maybe().Return(func() {}) - lbMock.On("IsConnected").Return(true).Maybe() - - mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t)) - - orm := keeper.NewORM(db, logger.TestLogger(t)) - synchronizer := keeper.NewRegistrySynchronizer(keeper.RegistrySynchronizerOptions{ - Job: j, - RegistryWrapper: *registryWrapper, - ORM: orm, - JRM: jpv2.Jrm, - LogBroadcaster: lbMock, - MailMon: mailMon, - SyncInterval: syncInterval, - MinIncomingConfirmations: 1, - Logger: logger.TestLogger(t), - SyncUpkeepQueueSize: syncUpkeepQueueSize, - EffectiveKeeperAddress: j.KeeperSpec.FromAddress.Address(), - }) - return db, synchronizer, ethClient, lbMock, j -} - -func assertUpkeepIDs(t *testing.T, db *sqlx.DB, expected []int64) { - g := gomega.NewWithT(t) - var upkeepIDs []int64 - err := db.Select(&upkeepIDs, `SELECT upkeep_id FROM upkeep_registrations`) - require.NoError(t, err) - require.Len(t, upkeepIDs, len(expected)) - g.Expect(upkeepIDs).To(gomega.ContainElements(expected)) -} diff --git a/core/services/keeper/registry_synchronizer_log_listener.go b/core/services/keeper/registry_synchronizer_log_listener.go deleted file mode 100644 index 49e8425a7c1..00000000000 --- a/core/services/keeper/registry_synchronizer_log_listener.go +++ /dev/null @@ -1,32 +0,0 @@ -package keeper - -import ( - "context" - "reflect" - - "github.com/smartcontractkit/chainlink-evm/pkg/log" -) - -func (rs *RegistrySynchronizer) JobID() int32 { - return rs.job.ID -} - -func (rs *RegistrySynchronizer) HandleLog(ctx context.Context, broadcast log.Broadcast) { - eventLog := broadcast.DecodedLog() - if eventLog == nil || reflect.ValueOf(eventLog).IsNil() { - rs.logger.Panicf("HandleLog: ignoring nil value, type: %T", broadcast) - return - } - - svcLogger := rs.logger.With( - "logType", reflect.TypeOf(eventLog), - "txHash", broadcast.RawLog().TxHash.Hex(), - ) - - svcLogger.Debug("received log, waiting for confirmations") - - wasOverCapacity := rs.mbLogs.Deliver(broadcast) - if wasOverCapacity { - svcLogger.Errorf("mailbox is over capacity - dropped the oldest unprocessed item") - } -} diff --git a/core/services/keeper/registry_synchronizer_process_logs.go b/core/services/keeper/registry_synchronizer_process_logs.go deleted file mode 100644 index 1394fea5ea8..00000000000 --- a/core/services/keeper/registry_synchronizer_process_logs.go +++ /dev/null @@ -1,278 +0,0 @@ -package keeper - -import ( - "context" - "fmt" - "reflect" - - "github.com/pkg/errors" - - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - registry1_1 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_1" - registry1_2 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_2" - registry1_3 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_3" - "github.com/smartcontractkit/chainlink-evm/pkg/log" - "github.com/smartcontractkit/chainlink-evm/pkg/types" -) - -func (rs *RegistrySynchronizer) processLogs(ctx context.Context) { - for _, broadcast := range rs.mbLogs.RetrieveAll() { - eventLog := broadcast.DecodedLog() - if eventLog == nil || reflect.ValueOf(eventLog).IsNil() { - rs.logger.Panicf("processLogs: ignoring nil value, type: %T", eventLog) - continue - } - - was, err := rs.logBroadcaster.WasAlreadyConsumed(ctx, broadcast) - if err != nil { - rs.logger.Warn(errors.Wrap(err, "unable to check if log was consumed")) - continue - } else if was { - continue - } - - switch eventLog.(type) { - case *registry1_1.KeeperRegistryKeepersUpdated, - *registry1_1.KeeperRegistryConfigSet, - *registry1_2.KeeperRegistryKeepersUpdated, - *registry1_2.KeeperRegistryConfigSet, - *registry1_3.KeeperRegistryKeepersUpdated, - *registry1_3.KeeperRegistryConfigSet: - err = rs.handleSyncRegistryLog(ctx, broadcast) - - case *registry1_1.KeeperRegistryUpkeepCanceled, - *registry1_2.KeeperRegistryUpkeepCanceled, - *registry1_3.KeeperRegistryUpkeepCanceled: - err = rs.handleUpkeepCancelled(ctx, broadcast) - - case *registry1_1.KeeperRegistryUpkeepRegistered, - *registry1_2.KeeperRegistryUpkeepRegistered, - *registry1_3.KeeperRegistryUpkeepRegistered: - err = rs.handleUpkeepRegistered(ctx, broadcast) - - case *registry1_1.KeeperRegistryUpkeepPerformed, - *registry1_2.KeeperRegistryUpkeepPerformed, - *registry1_3.KeeperRegistryUpkeepPerformed: - err = rs.handleUpkeepPerformed(ctx, broadcast) - - case *registry1_2.KeeperRegistryUpkeepGasLimitSet, - *registry1_3.KeeperRegistryUpkeepGasLimitSet: - err = rs.handleUpkeepGasLimitSet(ctx, broadcast) - - case *registry1_2.KeeperRegistryUpkeepReceived, - *registry1_3.KeeperRegistryUpkeepReceived: - err = rs.handleUpkeepReceived(ctx, broadcast) - - case *registry1_2.KeeperRegistryUpkeepMigrated, - *registry1_3.KeeperRegistryUpkeepMigrated: - err = rs.handleUpkeepMigrated(ctx, broadcast) - - case *registry1_3.KeeperRegistryUpkeepPaused: - err = rs.handleUpkeepPaused(ctx, broadcast) - - case *registry1_3.KeeperRegistryUpkeepUnpaused: - err = rs.handleUpkeepUnpaused(ctx, broadcast) - - case *registry1_3.KeeperRegistryUpkeepCheckDataUpdated: - err = rs.handleUpkeepCheckDataUpdated(ctx, broadcast) - - default: - rs.logger.Warn("unexpected log type") - // Don't `continue` -- we still want to mark this log as consumed - } - - if err != nil { - if ctx.Err() != nil { - return - } - rs.logger.Error(err) - } - - err = rs.logBroadcaster.MarkConsumed(ctx, nil, broadcast) - if err != nil { - rs.logger.Error(errors.Wrapf(err, "unable to mark %T log as consumed, log: %v", broadcast.RawLog(), broadcast.String())) - } - } -} - -func (rs *RegistrySynchronizer) handleSyncRegistryLog(ctx context.Context, broadcast log.Broadcast) error { - rs.logger.Debugw("processing SyncRegistry log", "txHash", broadcast.RawLog().TxHash.Hex()) - - _, err := rs.syncRegistry(ctx) - if err != nil { - return errors.Wrap(err, "unable to sync registry") - } - return nil -} - -func (rs *RegistrySynchronizer) handleUpkeepCancelled(ctx context.Context, broadcast log.Broadcast) error { - rs.logger.Debugw("processing UpkeepCanceled log", "txHash", broadcast.RawLog().TxHash.Hex()) - - cancelledID, err := rs.registryWrapper.GetCancelledUpkeepIDFromLog(broadcast) - if err != nil { - return errors.Wrap(err, "Unable to fetch cancelled upkeep ID from log") - } - - affected, err := rs.orm.BatchDeleteUpkeepsForJob(ctx, rs.job.ID, []sqlutil.Big{*sqlutil.New(cancelledID)}) - if err != nil { - return errors.Wrap(err, "unable to batch delete upkeeps") - } - rs.logger.Debugw(fmt.Sprintf("deleted %v upkeep registrations", affected), "txHash", broadcast.RawLog().TxHash.Hex()) - return nil -} - -func (rs *RegistrySynchronizer) handleUpkeepRegistered(ctx context.Context, broadcast log.Broadcast) error { - rs.logger.Debugw("processing UpkeepRegistered log", "txHash", broadcast.RawLog().TxHash.Hex()) - - registry, err := rs.orm.RegistryForJob(ctx, rs.job.ID) - if err != nil { - return errors.Wrap(err, "unable to find registry for job") - } - - upkeepID, err := rs.registryWrapper.GetUpkeepIdFromRegistrationLog(broadcast) - if err != nil { - return errors.Wrap(err, "Unable to fetch upkeep ID from registration log") - } - - err = rs.syncUpkeep(ctx, &rs.registryWrapper, registry, sqlutil.New(upkeepID)) - if err != nil { - return errors.Wrapf(err, "failed to sync upkeep, log: %v", broadcast.String()) - } - return nil -} - -func (rs *RegistrySynchronizer) handleUpkeepPerformed(ctx context.Context, broadcast log.Broadcast) error { - rs.logger.Debugw("processing UpkeepPerformed log", "jobID", rs.job.ID, "txHash", broadcast.RawLog().TxHash.Hex()) - - log, err := rs.registryWrapper.ParseUpkeepPerformedLog(broadcast) - if err != nil { - return errors.Wrap(err, "Unable to fetch upkeep ID from performed log") - } - rowsAffected, err := rs.orm.SetLastRunInfoForUpkeepOnJob(ctx, rs.job.ID, sqlutil.New(log.UpkeepID), int64(broadcast.RawLog().BlockNumber), types.EIP55AddressFromAddress(log.FromKeeper)) - if err != nil { - return errors.Wrap(err, "failed to set last run to 0") - } - rs.logger.Debugw("updated db for UpkeepPerformed log", - "jobID", rs.job.ID, - "upkeepID", log.UpkeepID.String(), - "blockNumber", int64(broadcast.RawLog().BlockNumber), - "fromAddr", types.EIP55AddressFromAddress(log.FromKeeper), - "rowsAffected", rowsAffected, - ) - return nil -} - -func (rs *RegistrySynchronizer) handleUpkeepGasLimitSet(ctx context.Context, broadcast log.Broadcast) error { - rs.logger.Debugw("processing UpkeepGasLimitSet log", "jobID", rs.job.ID, "txHash", broadcast.RawLog().TxHash.Hex()) - - registry, err := rs.orm.RegistryForJob(ctx, rs.job.ID) - if err != nil { - return errors.Wrap(err, "unable to find registry for job") - } - - upkeepID, err := rs.registryWrapper.GetIDFromGasLimitSetLog(broadcast) - if err != nil { - return errors.Wrap(err, "Unable to fetch upkeep ID from gas limit set log") - } - - err = rs.syncUpkeep(ctx, &rs.registryWrapper, registry, sqlutil.New(upkeepID)) - if err != nil { - return errors.Wrapf(err, "failed to sync upkeep, log: %v", broadcast.String()) - } - return nil -} - -func (rs *RegistrySynchronizer) handleUpkeepReceived(ctx context.Context, broadcast log.Broadcast) error { - rs.logger.Debugw("processing UpkeepReceived log", "txHash", broadcast.RawLog().TxHash.Hex()) - - registry, err := rs.orm.RegistryForJob(ctx, rs.job.ID) - if err != nil { - return errors.Wrap(err, "unable to find registry for job") - } - - upkeepID, err := rs.registryWrapper.GetUpkeepIdFromReceivedLog(broadcast) - if err != nil { - return errors.Wrap(err, "Unable to fetch upkeep ID from received log") - } - - err = rs.syncUpkeep(ctx, &rs.registryWrapper, registry, sqlutil.New(upkeepID)) - if err != nil { - return errors.Wrapf(err, "failed to sync upkeep, log: %v", broadcast.String()) - } - return nil -} - -func (rs *RegistrySynchronizer) handleUpkeepMigrated(ctx context.Context, broadcast log.Broadcast) error { - rs.logger.Debugw("processing UpkeepMigrated log", "txHash", broadcast.RawLog().TxHash.Hex()) - - migratedID, err := rs.registryWrapper.GetUpkeepIdFromMigratedLog(broadcast) - if err != nil { - return errors.Wrap(err, "Unable to fetch migrated upkeep ID from log") - } - - affected, err := rs.orm.BatchDeleteUpkeepsForJob(ctx, rs.job.ID, []sqlutil.Big{*sqlutil.New(migratedID)}) - if err != nil { - return errors.Wrap(err, "unable to batch delete upkeeps") - } - rs.logger.Debugw(fmt.Sprintf("deleted %v upkeep registrations", affected), "txHash", broadcast.RawLog().TxHash.Hex()) - return nil -} - -func (rs *RegistrySynchronizer) handleUpkeepPaused(ctx context.Context, broadcast log.Broadcast) error { - rs.logger.Debugw("processing UpkeepPaused log", "txHash", broadcast.RawLog().TxHash.Hex()) - - pausedUpkeepId, err := rs.registryWrapper.GetUpkeepIdFromUpkeepPausedLog(broadcast) - if err != nil { - return errors.Wrap(err, "Unable to fetch upkeep ID from upkeep paused log") - } - - _, err = rs.orm.BatchDeleteUpkeepsForJob(ctx, rs.job.ID, []sqlutil.Big{*sqlutil.New(pausedUpkeepId)}) - if err != nil { - return errors.Wrap(err, "unable to batch delete upkeeps") - } - rs.logger.Debugw("paused upkeep "+pausedUpkeepId.String(), "txHash", broadcast.RawLog().TxHash.Hex()) - return nil -} - -func (rs *RegistrySynchronizer) handleUpkeepUnpaused(ctx context.Context, broadcast log.Broadcast) error { - rs.logger.Debugw("processing UpkeepUnpaused log", "txHash", broadcast.RawLog().TxHash.Hex()) - - registry, err := rs.orm.RegistryForJob(ctx, rs.job.ID) - if err != nil { - return errors.Wrap(err, "unable to find registry for job") - } - - unpausedUpkeepId, err := rs.registryWrapper.GetUpkeepIdFromUpkeepUnpausedLog(broadcast) - if err != nil { - return errors.Wrap(err, "Unable to fetch upkeep ID from upkeep unpaused log") - } - - err = rs.syncUpkeep(ctx, &rs.registryWrapper, registry, sqlutil.New(unpausedUpkeepId)) - if err != nil { - return errors.Wrapf(err, "failed to sync upkeep, log: %s", broadcast.String()) - } - rs.logger.Debugw("unpaused upkeep "+unpausedUpkeepId.String(), "txHash", broadcast.RawLog().TxHash.Hex()) - return nil -} - -func (rs *RegistrySynchronizer) handleUpkeepCheckDataUpdated(ctx context.Context, broadcast log.Broadcast) error { - rs.logger.Debugw("processing Upkeep check data updated log", "txHash", broadcast.RawLog().TxHash.Hex()) - - registry, err := rs.orm.RegistryForJob(ctx, rs.job.ID) - if err != nil { - return errors.Wrap(err, "unable to find registry for job") - } - - updateLog, err := rs.registryWrapper.ParseUpkeepCheckDataUpdatedLog(broadcast) - if err != nil { - return errors.Wrap(err, "Unable to parse update log from upkeep check data updated log") - } - - err = rs.syncUpkeep(ctx, &rs.registryWrapper, registry, sqlutil.New(updateLog.UpkeepID)) - if err != nil { - return errors.Wrapf(err, "unable to update check data for upkeep %s", updateLog.UpkeepID.String()) - } - - rs.logger.Debugw("updated check data for upkeep "+updateLog.UpkeepID.String(), "txHash", broadcast.RawLog().TxHash.Hex()) - return nil -} diff --git a/core/services/keeper/registry_synchronizer_sync.go b/core/services/keeper/registry_synchronizer_sync.go deleted file mode 100644 index f5b44a9d4e3..00000000000 --- a/core/services/keeper/registry_synchronizer_sync.go +++ /dev/null @@ -1,189 +0,0 @@ -package keeper - -import ( - "context" - "encoding/binary" - "math" - "math/big" - "sync" - - "github.com/pkg/errors" - - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" - "github.com/smartcontractkit/chainlink-evm/pkg/types" - "github.com/smartcontractkit/chainlink-evm/pkg/utils" -) - -func (rs *RegistrySynchronizer) fullSync(ctx context.Context) { - rs.logger.Debugf("fullSyncing registry %s", rs.job.KeeperSpec.ContractAddress.Hex()) - - registry, err := rs.syncRegistry(ctx) - if err != nil { - rs.logger.Error(errors.Wrap(err, "failed to sync registry during fullSyncing registry")) - return - } - - if err := rs.fullSyncUpkeeps(ctx, registry); err != nil { - rs.logger.Error(errors.Wrap(err, "failed to sync upkeeps during fullSyncing registry")) - return - } - rs.logger.Debugf("fullSyncing registry successful %s", rs.job.KeeperSpec.ContractAddress.Hex()) -} - -func (rs *RegistrySynchronizer) syncRegistry(ctx context.Context) (Registry, error) { - registry, err := rs.newRegistryFromChain(ctx) - if err != nil { - return Registry{}, errors.Wrap(err, "failed to get new registry from chain") - } - - err = rs.orm.UpsertRegistry(ctx, ®istry) - if err != nil { - return Registry{}, errors.Wrap(err, "failed to upsert registry") - } - - return registry, nil -} - -func (rs *RegistrySynchronizer) fullSyncUpkeeps(ctx context.Context, reg Registry) error { - activeUpkeepIDs, err := rs.registryWrapper.GetActiveUpkeepIDs(ctx, nil) - if err != nil { - return errors.Wrap(err, "unable to get active upkeep IDs") - } - - existingUpkeepIDs, err := rs.orm.AllUpkeepIDsForRegistry(ctx, reg.ID) - if err != nil { - return errors.Wrap(err, "unable to fetch existing upkeep IDs from DB") - } - - activeSet := make(map[string]bool) - allActiveUpkeeps := make([]sqlutil.Big, 0) - for _, upkeepID := range activeUpkeepIDs { - activeSet[upkeepID.String()] = true - allActiveUpkeeps = append(allActiveUpkeeps, *sqlutil.New(upkeepID)) - } - rs.batchSyncUpkeepsOnRegistry(ctx, reg, allActiveUpkeeps) - - // All upkeeps in existingUpkeepIDs, not in activeUpkeepIDs should be deleted - canceled := make([]sqlutil.Big, 0) - for _, upkeepID := range existingUpkeepIDs { - if _, found := activeSet[upkeepID.ToInt().String()]; !found { - canceled = append(canceled, upkeepID) - } - } - if _, err := rs.orm.BatchDeleteUpkeepsForJob(ctx, rs.job.ID, canceled); err != nil { - return errors.Wrap(err, "failed to batch delete upkeeps from job") - } - return nil -} - -// batchSyncUpkeepsOnRegistry syncs upkeeps at a time in parallel -// for all the IDs within newUpkeeps slice -func (rs *RegistrySynchronizer) batchSyncUpkeepsOnRegistry(ctx context.Context, reg Registry, newUpkeeps []sqlutil.Big) { - wg := sync.WaitGroup{} - chSyncUpkeepQueue := make(chan struct{}, rs.syncUpkeepQueueSize) - - done := func() { <-chSyncUpkeepQueue; wg.Done() } - for i := range newUpkeeps { - select { - case <-ctx.Done(): - case chSyncUpkeepQueue <- struct{}{}: - wg.Add(1) - go rs.syncUpkeepWithCallback(ctx, &rs.registryWrapper, reg, &newUpkeeps[i], done) - } - } - - wg.Wait() -} - -func (rs *RegistrySynchronizer) syncUpkeepWithCallback(ctx context.Context, getter upkeepGetter, registry Registry, upkeepID *sqlutil.Big, doneCallback func()) { - defer doneCallback() - - if err := rs.syncUpkeep(ctx, getter, registry, upkeepID); err != nil { - rs.logger.With("err", err.Error()).With( - "upkeepID", NewUpkeepIdentifier(upkeepID).String(), - "registryContract", registry.ContractAddress.Hex(), - ).Error("unable to sync upkeep on registry") - } -} - -func (rs *RegistrySynchronizer) syncUpkeep(ctx context.Context, getter upkeepGetter, registry Registry, upkeepID *sqlutil.Big) error { - upkeep, err := getter.GetUpkeep(nil, upkeepID.ToInt()) - if err != nil { - return errors.Wrap(err, "failed to get upkeep config") - } - - if upkeep.ExecuteGas <= uint32(0) { - return errors.Errorf("execute gas is zero for upkeep %s", NewUpkeepIdentifier(upkeepID).String()) - } - - positioningConstant, err := CalcPositioningConstant(upkeepID, registry.ContractAddress) - if err != nil { - return errors.Wrap(err, "failed to calc positioning constant") - } - newUpkeep := UpkeepRegistration{ - CheckData: upkeep.CheckData, - ExecuteGas: upkeep.ExecuteGas, - RegistryID: registry.ID, - PositioningConstant: positioningConstant, - UpkeepID: upkeepID, - } - if err := rs.orm.UpsertUpkeep(ctx, &newUpkeep); err != nil { - return errors.Wrap(err, "failed to upsert upkeep") - } - - if err := rs.orm.UpdateUpkeepLastKeeperIndex(ctx, rs.job.ID, upkeepID, types.EIP55AddressFromAddress(upkeep.LastKeeper)); err != nil { - return errors.Wrap(err, "failed to update upkeep last keeper index") - } - - return nil -} - -// newRegistryFromChain returns a Registry struct with fields synched from those on chain -func (rs *RegistrySynchronizer) newRegistryFromChain(ctx context.Context) (Registry, error) { - fromAddress := rs.effectiveKeeperAddress - contractAddress := rs.job.KeeperSpec.ContractAddress - - registryConfig, err := rs.registryWrapper.GetConfig(nil) - if err != nil { - rs.jrm.TryRecordError(ctx, rs.job.ID, err.Error()) - return Registry{}, errors.Wrap(err, "failed to get contract config") - } - - keeperIndex := int32(-1) - keeperMap := map[types.EIP55Address]int32{} - for idx, address := range registryConfig.KeeperAddresses { - keeperMap[types.EIP55AddressFromAddress(address)] = int32(idx) - if address == fromAddress { - keeperIndex = int32(idx) - } - } - if keeperIndex == -1 { - rs.logger.Warnf("unable to find %s in keeper list on registry %s", fromAddress.Hex(), contractAddress.Hex()) - } - - return Registry{ - BlockCountPerTurn: registryConfig.BlockCountPerTurn, - CheckGas: registryConfig.CheckGas, - ContractAddress: contractAddress, - FromAddress: rs.job.KeeperSpec.FromAddress, - JobID: rs.job.ID, - KeeperIndex: keeperIndex, - NumKeepers: int32(len(registryConfig.KeeperAddresses)), - KeeperIndexMap: keeperMap, - }, nil -} - -// CalcPositioningConstant calculates a positioning constant. -// The positioning constant is fixed because upkeepID and registryAddress are immutable -func CalcPositioningConstant(upkeepID *sqlutil.Big, registryAddress types.EIP55Address) (int32, error) { - upkeepBytes := make([]byte, binary.MaxVarintLen64) - binary.PutVarint(upkeepBytes, bigmath.Mod(upkeepID.ToInt(), big.NewInt(math.MaxInt64)).Int64()) - bytesToHash := utils.ConcatBytes(upkeepBytes, registryAddress.Bytes()) - checksum, err := utils.Keccak256(bytesToHash) - if err != nil { - return 0, err - } - constant := binary.BigEndian.Uint16(checksum[:2]) - return int32(constant), nil -} diff --git a/core/services/keeper/registry_synchronizer_sync_test.go b/core/services/keeper/registry_synchronizer_sync_test.go deleted file mode 100644 index ee636c8bdd7..00000000000 --- a/core/services/keeper/registry_synchronizer_sync_test.go +++ /dev/null @@ -1,77 +0,0 @@ -package keeper - -import ( - "errors" - "fmt" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - "github.com/smartcontractkit/chainlink-evm/pkg/types" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -// GetUpkeepFailure implements the upkeepGetter interface with an induced error and nil -// config response. -type GetUpkeepFailure struct{} - -var errGetUpkeep = errors.New("chain connection error example") - -func (g *GetUpkeepFailure) GetUpkeep(opts *bind.CallOpts, id *big.Int) (*UpkeepConfig, error) { - return nil, fmt.Errorf("%w [%w]: getConfig v1.%d", ErrContractCallFailure, errGetUpkeep, RegistryVersion_1_2) -} - -func TestSyncUpkeepWithCallback_UpkeepNotFound(t *testing.T) { - ctx := testutils.Context(t) - log, logObserver := logger.TestLoggerObserved(t, zapcore.ErrorLevel) - synchronizer := &RegistrySynchronizer{ - logger: log.(logger.SugaredLogger), - } - - addr := types.EIP55Address(testutils.NewAddress().Hex()) - registry := Registry{ - ContractAddress: addr, - } - - o, ok := new(big.Int).SetString("5032485723458348569331745", 10) - if !ok { - t.FailNow() - } - - id := sqlutil.New(o) - count := 0 - doneFunc := func() { - count++ - } - - getter := &GetUpkeepFailure{} - synchronizer.syncUpkeepWithCallback(ctx, getter, registry, id, doneFunc) - - // logs should have the upkeep identifier included in the error context properly formatted - require.Equal(t, 1, logObserver.Len()) - - keys := map[string]bool{} - for _, entry := range logObserver.All() { - for _, field := range entry.Context { - switch field.Key { - case "err": - require.Equal(t, "failed to get upkeep config: failure in calling contract [chain connection error example]: getConfig v1.2", field.String) - case "upkeepID": - require.Equal(t, fmt.Sprintf("UPx%064s", "429ab990419450db80821"), field.String) - case "registryContract": - require.Equal(t, addr.Hex(), field.String) - default: - continue - } - keys[field.Key] = true - } - } - - require.Equal(t, map[string]bool{"upkeepID": true, "err": true, "registryContract": true}, keys) - require.Equal(t, 1, count, "callback function should run") -} diff --git a/core/services/keeper/upkeep_executer.go b/core/services/keeper/upkeep_executer.go deleted file mode 100644 index d5791c5878c..00000000000 --- a/core/services/keeper/upkeep_executer.go +++ /dev/null @@ -1,291 +0,0 @@ -package keeper - -import ( - "context" - "fmt" - "math/big" - "sync" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/pkg/errors" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promauto" - - "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" - - "github.com/smartcontractkit/chainlink-evm/pkg/assets" - evmclient "github.com/smartcontractkit/chainlink-evm/pkg/client" - "github.com/smartcontractkit/chainlink-evm/pkg/gas" - "github.com/smartcontractkit/chainlink-evm/pkg/heads" - evmtypes "github.com/smartcontractkit/chainlink-evm/pkg/types" - - "github.com/smartcontractkit/chainlink/v2/core/config" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" -) - -const ( - executionQueueSize = 10 - maxUpkeepPerformGas = 5_000_000 // Max perform gas for upkeep is 5M on all chains for v1.x -) - -// UpkeepExecuter fulfills Service and HeadTrackable interfaces -var ( - _ job.ServiceCtx = (*UpkeepExecuter)(nil) - _ heads.Trackable = (*UpkeepExecuter)(nil) -) - -var ( - promCheckUpkeepExecutionTime = promauto.NewGaugeVec(prometheus.GaugeOpts{ - Name: "keeper_check_upkeep_execution_time", - Help: "Time taken to fully execute the check upkeep logic", - }, - []string{"upkeepID"}, - ) -) - -type UpkeepExecuterConfig interface { - MaxGracePeriod() int64 - TurnLookBack() int64 - Registry() config.Registry -} - -// UpkeepExecuter implements the logic to communicate with KeeperRegistry -type UpkeepExecuter struct { - services.StateMachine - chStop services.StopChan - ethClient evmclient.Client - config UpkeepExecuterConfig - executionQueue chan struct{} - headBroadcaster heads.Broadcaster - gasEstimator gas.EvmFeeEstimator - job job.Job - mailbox *mailbox.Mailbox[*evmtypes.Head] - orm *ORM - pr pipeline.Runner - logger logger.Logger - wgDone sync.WaitGroup - effectiveKeeperAddress common.Address -} - -// NewUpkeepExecuter is the constructor of UpkeepExecuter -func NewUpkeepExecuter( - job job.Job, - orm *ORM, - pr pipeline.Runner, - ethClient evmclient.Client, - headBroadcaster heads.Broadcaster, - gasEstimator gas.EvmFeeEstimator, - logger logger.Logger, - config UpkeepExecuterConfig, - effectiveKeeperAddress common.Address, -) *UpkeepExecuter { - return &UpkeepExecuter{ - chStop: make(services.StopChan), - ethClient: ethClient, - executionQueue: make(chan struct{}, executionQueueSize), - headBroadcaster: headBroadcaster, - gasEstimator: gasEstimator, - job: job, - mailbox: mailbox.NewSingle[*evmtypes.Head](), - config: config, - orm: orm, - pr: pr, - effectiveKeeperAddress: effectiveKeeperAddress, - logger: logger.Named("UpkeepExecuter"), - } -} - -// Start starts the upkeep executer logic -func (ex *UpkeepExecuter) Start(context.Context) error { - return ex.StartOnce("UpkeepExecuter", func() error { - ex.wgDone.Add(2) - go ex.run() - latestHead, unsubscribeHeads := ex.headBroadcaster.Subscribe(ex) - if latestHead != nil { - ex.mailbox.Deliver(latestHead) - } - go func() { - defer unsubscribeHeads() - defer ex.wgDone.Done() - <-ex.chStop - }() - return nil - }) -} - -// Close stops and closes upkeep executer -func (ex *UpkeepExecuter) Close() error { - return ex.StopOnce("UpkeepExecuter", func() error { - close(ex.chStop) - ex.wgDone.Wait() - return nil - }) -} - -// OnNewLongestChain handles the given head of a new longest chain -func (ex *UpkeepExecuter) OnNewLongestChain(_ context.Context, head *evmtypes.Head) { - ex.mailbox.Deliver(head) -} - -func (ex *UpkeepExecuter) run() { - defer ex.wgDone.Done() - ctx, cancel := ex.chStop.NewCtx() - defer cancel() - for { - select { - case <-ex.chStop: - return - case <-ex.mailbox.Notify(): - ex.processActiveUpkeeps(ctx) - } - } -} - -func (ex *UpkeepExecuter) processActiveUpkeeps(ctx context.Context) { - // Keepers could miss their turn in the turn taking algo if they are too overloaded - // with work because processActiveUpkeeps() blocks - head, exists := ex.mailbox.Retrieve() - if !exists { - ex.logger.Info("no head to retrieve. It might have been skipped") - return - } - - ex.logger.Debugw("checking active upkeeps", "blockheight", head.Number) - - registry, err := ex.orm.RegistryByContractAddress(ctx, ex.job.KeeperSpec.ContractAddress) - if err != nil { - ex.logger.Error(errors.Wrap(err, "unable to load registry")) - return - } - - var activeUpkeeps []UpkeepRegistration - turnBinary, err2 := ex.turnBlockHashBinary(ctx, registry, head, ex.config.TurnLookBack()) - if err2 != nil { - ex.logger.Error(errors.Wrap(err2, "unable to get turn block number hash")) - return - } - activeUpkeeps, err2 = ex.orm.EligibleUpkeepsForRegistry( - ctx, - ex.job.KeeperSpec.ContractAddress, - head.Number, - ex.config.MaxGracePeriod(), - turnBinary) - if err2 != nil { - ex.logger.Error(errors.Wrap(err2, "unable to load active registrations")) - return - } - - if head.Number%10 == 0 { - // Log this once every 10 blocks - fetchedUpkeepIDs := make([]string, len(activeUpkeeps)) - for i, activeUpkeep := range activeUpkeeps { - fetchedUpkeepIDs[i] = NewUpkeepIdentifier(activeUpkeep.UpkeepID).String() - } - ex.logger.Debugw("Fetched list of active upkeeps", "blockNum", head.Number, "active upkeeps list", fetchedUpkeepIDs) - } - - wg := sync.WaitGroup{} - wg.Add(len(activeUpkeeps)) - done := func() { - <-ex.executionQueue - wg.Done() - } - for _, reg := range activeUpkeeps { - ex.executionQueue <- struct{}{} - go ex.execute(reg, head, done) - } - - wg.Wait() - ex.logger.Debugw("Finished checking upkeeps", "blockNum", head.Number) -} - -// execute triggers the pipeline run -func (ex *UpkeepExecuter) execute(upkeep UpkeepRegistration, head *evmtypes.Head, done func()) { - defer done() - - start := time.Now() - svcLogger := ex.logger.With("jobID", ex.job.ID, "blockNum", head.Number, "upkeepID", upkeep.UpkeepID) - svcLogger.Debugw("checking upkeep", "lastRunBlockHeight", upkeep.LastRunBlockHeight, "lastKeeperIndex", upkeep.LastKeeperIndex) - - ctxService, cancel := ex.chStop.CtxWithTimeout(time.Minute) - defer cancel() - - evmChainID := "" - if ex.job.KeeperSpec.EVMChainID != nil { - evmChainID = ex.job.KeeperSpec.EVMChainID.String() - } - - var gasPrice, gasTipCap, gasFeeCap *assets.Wei - // effectiveKeeperAddress is always fromAddress when forwarding is not enabled. - // when forwarding is enabled, effectiveKeeperAddress is on-chain forwarder. - vars := pipeline.NewVarsFrom(buildJobSpec(ex.job, ex.effectiveKeeperAddress, upkeep, ex.config.Registry(), gasPrice, gasTipCap, gasFeeCap, evmChainID)) - - // DotDagSource in database is empty because all the Keeper pipeline runs make use of the same observation source - ex.job.PipelineSpec.DotDagSource = pipeline.KeepersObservationSource - run := pipeline.NewRun(*ex.job.PipelineSpec, vars) - - if _, err := ex.pr.Run(ctxService, run, true, nil); err != nil { - svcLogger.Error(errors.Wrap(err, "failed executing run")) - return - } - - // Only after task runs where a tx was broadcast - if run.State == pipeline.RunStatusCompleted { - rowsAffected, err := ex.orm.SetLastRunInfoForUpkeepOnJob(ctxService, ex.job.ID, upkeep.UpkeepID, head.Number, upkeep.Registry.FromAddress) - if err != nil { - svcLogger.Error(errors.Wrap(err, "failed to set last run height for upkeep")) - } - svcLogger.Debugw("execute pipeline status completed", "fromAddr", upkeep.Registry.FromAddress, "rowsAffected", rowsAffected) - - elapsed := time.Since(start) - promCheckUpkeepExecutionTime. - WithLabelValues(upkeep.PrettyID()). - Set(float64(elapsed)) - } -} - -func (ex *UpkeepExecuter) turnBlockHashBinary(ctx context.Context, registry Registry, head *evmtypes.Head, lookback int64) (string, error) { - turnBlock := head.Number - (head.Number % int64(registry.BlockCountPerTurn)) - lookback - block, err := ex.ethClient.HeadByNumber(ctx, big.NewInt(turnBlock)) - if err != nil { - return "", err - } - hashAtHeight := block.Hash - binaryString := fmt.Sprintf("%b", hashAtHeight.Big()) - return binaryString, nil -} - -func buildJobSpec( - jb job.Job, - effectiveKeeperAddress common.Address, - upkeep UpkeepRegistration, - ormConfig RegistryGasChecker, - gasPrice *assets.Wei, - gasTipCap *assets.Wei, - gasFeeCap *assets.Wei, - chainID string, -) map[string]any { - return map[string]any{ - "jobSpec": map[string]any{ - "jobID": jb.ID, - "fromAddress": upkeep.Registry.FromAddress.String(), - "effectiveKeeperAddress": effectiveKeeperAddress.String(), - "contractAddress": upkeep.Registry.ContractAddress.String(), - "upkeepID": upkeep.UpkeepID.String(), - "prettyID": upkeep.PrettyID(), - "pipelineSpec": &pipeline.Spec{ - ForwardingAllowed: jb.ForwardingAllowed, - }, - "performUpkeepGasLimit": maxUpkeepPerformGas + ormConfig.PerformGasOverhead(), - "maxPerformDataSize": ormConfig.MaxPerformDataSize(), - "gasPrice": gasPrice.ToInt(), - "gasTipCap": gasTipCap.ToInt(), - "gasFeeCap": gasFeeCap.ToInt(), - "evmChainID": chainID, - }, - } -} diff --git a/core/services/keeper/upkeep_executer_test.go b/core/services/keeper/upkeep_executer_test.go deleted file mode 100644 index 1b9b87ee4cc..00000000000 --- a/core/services/keeper/upkeep_executer_test.go +++ /dev/null @@ -1,343 +0,0 @@ -package keeper_test - -import ( - "math/big" - "sync/atomic" - "testing" - "time" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" - "github.com/onsi/gomega" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - - "github.com/jmoiron/sqlx" - - "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - - "github.com/smartcontractkit/chainlink-evm/pkg/chains/legacyevm" - "github.com/smartcontractkit/chainlink-evm/pkg/client/clienttest" - "github.com/smartcontractkit/chainlink-evm/pkg/txmgr" - evmtypes "github.com/smartcontractkit/chainlink-evm/pkg/types" - "github.com/smartcontractkit/chainlink-evm/pkg/utils" - - txmmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/mocks" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/keeper" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore" -) - -func newHead() evmtypes.Head { - return evmtypes.NewHead(big.NewInt(20), utils.NewHash(), utils.NewHash(), sqlutil.NewI(0)) -} - -func setup(t *testing.T, overrideFn func(c *chainlink.Config, s *chainlink.Secrets)) ( - *sqlx.DB, - chainlink.GeneralConfig, - *clienttest.Client, - *keeper.UpkeepExecuter, - keeper.Registry, - keeper.UpkeepRegistration, - job.Job, - JobPipelineV2TestHelper, - *txmmocks.MockEvmTxManager, - keystore.Master, - legacyevm.Chain, - *keeper.ORM, -) { - cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Keeper.TurnLookBack = ptr[int64](0) - if fn := overrideFn; fn != nil { - fn(c, s) - } - }) - db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db) - ethClient := cltest.NewEthMocksWithStartupAssertions(t) - ethClient.On("ConfiguredChainID").Return(cfg.EVMConfigs()[0].ChainID.ToInt()).Maybe() - ethClient.On("IsL2").Return(false).Maybe() - ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Maybe().Return(&evmtypes.Head{Number: 1, Hash: utils.NewHash()}, nil) - txm := txmmocks.NewMockEvmTxManager(t) - servicetest.SetupNoOpMock(txm) - txm.On("OnNewLongestChain", mock.Anything, mock.Anything).Return().Maybe() - legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{ - TxManager: txm, - DB: db, - Client: ethClient, - KeyStore: keyStore.Eth(), - ChainConfigs: cfg.EVMConfigs(), - DatabaseConfig: cfg.Database(), - FeatureConfig: cfg.Feature(), - ListenerConfig: cfg.Database().Listener(), - }) - jpv2 := NewJobPipelineV2(t, cfg.WebServer(), cfg.JobPipeline(), legacyChains, db, keyStore, nil, nil) - ch := evmtest.MustGetDefaultChain(t, legacyChains) - orm := keeper.NewORM(db, logger.TestLogger(t)) - registry, jb := cltest.MustInsertKeeperRegistry(t, db, orm, keyStore.Eth(), 0, 1, 20) - - lggr := logger.TestLogger(t) - executer := keeper.NewUpkeepExecuter(jb, orm, jpv2.Pr, ethClient, ch.HeadBroadcaster(), ch.GasEstimator(), lggr, cfg.Keeper(), jb.KeeperSpec.FromAddress.Address()) - upkeep := cltest.MustInsertUpkeepForRegistry(t, db, registry) - servicetest.Run(t, executer) - return db, cfg, ethClient, executer, registry, upkeep, jb, jpv2, txm, keyStore, ch, orm -} - -var checkUpkeepResponse = struct { - PerformData []byte - MaxLinkPayment *big.Int - GasLimit *big.Int - GasWei *big.Int - LinkEth *big.Int -}{ - PerformData: common.Hex2Bytes("1234"), - MaxLinkPayment: big.NewInt(0), // doesn't matter - GasLimit: big.NewInt(2_000_000), - GasWei: big.NewInt(0), // doesn't matter - LinkEth: big.NewInt(0), // doesn't matter -} - -var checkPerformResponse = struct { - Success bool -}{ - Success: true, -} - -func Test_UpkeepExecuter_ErrorsIfStartedTwice(t *testing.T) { - t.Parallel() - _, _, _, executer, _, _, _, _, _, _, _, _ := setup(t, nil) - err := executer.Start(testutils.Context(t)) // already started in setup() - require.Error(t, err) -} - -func Test_UpkeepExecuter_PerformsUpkeep_Happy(t *testing.T) { - taskRuns := 11 - - t.Parallel() - - t.Run("runs upkeep on triggering block number", func(t *testing.T) { - db, config, ethMock, executer, registry, upkeep, job, jpv2, txm, _, _, _ := setup(t, - func(c *chainlink.Config, s *chainlink.Secrets) { - c.EVM[0].ChainID = (*sqlutil.Big)(testutils.SimulatedChainID) - }) - - gasLimit := uint64(5_000_000 + config.Keeper().Registry().PerformGasOverhead()) - - ethTxCreated := cltest.NewAwaiter() - txm.On("CreateTransaction", - mock.Anything, - mock.MatchedBy(func(txRequest txmgr.TxRequest) bool { return txRequest.FeeLimit == gasLimit }), - ). - Once(). - Return(txmgr.Tx{ - ID: 1, - }, nil). - Run(func(mock.Arguments) { ethTxCreated.ItHappened() }) - - registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_1ABI, registry.ContractAddress.Address()) - registryMock.MockMatchedResponse( - "checkUpkeep", - func(callArgs ethereum.CallMsg) bool { - return callArgs.GasPrice == nil && - callArgs.Gas == 0 - }, - checkUpkeepResponse, - ) - registryMock.MockMatchedResponse( - "performUpkeep", - func(callArgs ethereum.CallMsg) bool { return true }, - checkPerformResponse, - ) - - head := newHead() - executer.OnNewLongestChain(testutils.Context(t), &head) - ethTxCreated.AwaitOrFail(t) - runs := cltest.WaitForPipelineComplete(t, 0, job.ID, 1, taskRuns, jpv2.Jrm, time.Second, 100*time.Millisecond) - require.Len(t, runs, 1) - assert.False(t, runs[0].HasErrors()) - assert.False(t, runs[0].HasFatalErrors()) - waitLastRunHeight(t, db, upkeep, 20) - }) - - t.Run("runs upkeep on triggering block number on EIP1559 and non-EIP1559 chains", func(t *testing.T) { - runTest := func(t *testing.T, eip1559 bool) { - db, config, ethMock, executer, registry, upkeep, job, jpv2, txm, _, _, _ := setup(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.EVM[0].GasEstimator.EIP1559DynamicFees = &eip1559 - c.EVM[0].ChainID = (*sqlutil.Big)(testutils.SimulatedChainID) - }) - - gasLimit := uint64(5_000_000 + config.Keeper().Registry().PerformGasOverhead()) - - ethTxCreated := cltest.NewAwaiter() - txm.On("CreateTransaction", - mock.Anything, - mock.MatchedBy(func(txRequest txmgr.TxRequest) bool { return txRequest.FeeLimit == gasLimit }), - ). - Once(). - Return(txmgr.Tx{ - ID: 1, - }, nil). - Run(func(mock.Arguments) { ethTxCreated.ItHappened() }) - - registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_1ABI, registry.ContractAddress.Address()) - registryMock.MockMatchedResponse( - "checkUpkeep", - func(callArgs ethereum.CallMsg) bool { - return callArgs.GasPrice == nil && - callArgs.Gas == 0 - }, - checkUpkeepResponse, - ) - registryMock.MockMatchedResponse( - "performUpkeep", - func(callArgs ethereum.CallMsg) bool { return true }, - checkPerformResponse, - ) - - head := newHead() - - executer.OnNewLongestChain(testutils.Context(t), &head) - ethTxCreated.AwaitOrFail(t) - runs := cltest.WaitForPipelineComplete(t, 0, job.ID, 1, taskRuns, jpv2.Jrm, time.Second, 100*time.Millisecond) - require.Len(t, runs, 1) - assert.False(t, runs[0].HasErrors()) - assert.False(t, runs[0].HasFatalErrors()) - waitLastRunHeight(t, db, upkeep, 20) - } - - t.Run("EIP1559", func(t *testing.T) { - runTest(t, true) - }) - - t.Run("non-EIP1559", func(t *testing.T) { - runTest(t, false) - }) - }) - - t.Run("errors if submission key not found", func(t *testing.T) { - ctx := testutils.Context(t) - _, _, ethMock, executer, registry, _, job, jpv2, _, keyStore, _, _ := setup(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.EVM[0].ChainID = (*sqlutil.Big)(testutils.SimulatedChainID) - }) - - // replace expected key with random one - _, err := keyStore.Eth().Create(ctx, testutils.SimulatedChainID) - require.NoError(t, err) - _, err = keyStore.Eth().Delete(ctx, job.KeeperSpec.FromAddress.Hex()) - require.NoError(t, err) - - registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_1ABI, registry.ContractAddress.Address()) - registryMock.MockMatchedResponse( - "checkUpkeep", - func(callArgs ethereum.CallMsg) bool { - return callArgs.GasPrice == nil && - callArgs.Gas == 0 - }, - checkUpkeepResponse, - ) - registryMock.MockMatchedResponse( - "performUpkeep", - func(callArgs ethereum.CallMsg) bool { return true }, - checkPerformResponse, - ) - - head := newHead() - executer.OnNewLongestChain(testutils.Context(t), &head) - runs := cltest.WaitForPipelineError(t, 0, job.ID, 1, taskRuns, jpv2.Jrm, time.Second, 100*time.Millisecond) - require.Len(t, runs, 1) - assert.True(t, runs[0].HasErrors()) - assert.True(t, runs[0].HasFatalErrors()) - }) - - t.Run("errors if submission chain not found", func(t *testing.T) { - db, cfg, ethMock, _, _, _, _, jpv2, _, keyStore, ch, orm := setup(t, nil) - - registry, jb := cltest.MustInsertKeeperRegistry(t, db, orm, keyStore.Eth(), 0, 1, 20) - // change chain ID to non-configured chain - jb.KeeperSpec.EVMChainID = (*sqlutil.Big)(big.NewInt(999)) - cltest.MustInsertUpkeepForRegistry(t, db, registry) - lggr := logger.TestLogger(t) - executer := keeper.NewUpkeepExecuter(jb, orm, jpv2.Pr, ethMock, ch.HeadBroadcaster(), ch.GasEstimator(), lggr, cfg.Keeper(), jb.KeeperSpec.FromAddress.Address()) - servicetest.Run(t, executer) - head := newHead() - executer.OnNewLongestChain(testutils.Context(t), &head) - // TODO we want to see an errored run result once this is completed - // https://smartcontract-it.atlassian.net/browse/ARCHIVE-22186 - cltest.AssertPipelineRunsStays(t, jb.PipelineSpecID, db, 0) - }) - - t.Run("triggers if heads are skipped but later heads arrive within range", func(t *testing.T) { - db, config, ethMock, executer, registry, upkeep, job, jpv2, txm, _, _, _ := setup(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.EVM[0].ChainID = (*sqlutil.Big)(testutils.SimulatedChainID) - }) - - etxs := []cltest.Awaiter{ - cltest.NewAwaiter(), - cltest.NewAwaiter(), - } - gasLimit := uint64(5_000_000 + config.Keeper().Registry().PerformGasOverhead()) - txm.On("CreateTransaction", - mock.Anything, - mock.MatchedBy(func(txRequest txmgr.TxRequest) bool { return txRequest.FeeLimit == gasLimit }), - ). - Once(). - Return(txmgr.Tx{}, nil). - Run(func(mock.Arguments) { etxs[0].ItHappened() }) - - registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_1ABI, registry.ContractAddress.Address()) - registryMock.MockResponse("checkUpkeep", checkUpkeepResponse) - registryMock.MockMatchedResponse( - "performUpkeep", - func(callArgs ethereum.CallMsg) bool { return true }, - checkPerformResponse, - ) - // turn falls somewhere between 20-39 (blockCountPerTurn=20) - // heads 20 thru 35 were skipped (e.g. due to node reboot) - head := cltest.Head(36) - - executer.OnNewLongestChain(testutils.Context(t), head) - runs := cltest.WaitForPipelineComplete(t, 0, job.ID, 1, taskRuns, jpv2.Jrm, time.Second, 100*time.Millisecond) - require.Len(t, runs, 1) - assert.False(t, runs[0].HasErrors()) - etxs[0].AwaitOrFail(t) - waitLastRunHeight(t, db, upkeep, 36) - }) -} - -func Test_UpkeepExecuter_PerformsUpkeep_Error(t *testing.T) { - t.Parallel() - - g := gomega.NewWithT(t) - - db, _, ethMock, executer, registry, _, _, _, _, _, _, _ := setup(t, - func(c *chainlink.Config, s *chainlink.Secrets) { - c.EVM[0].ChainID = (*sqlutil.Big)(testutils.SimulatedChainID) - }) - - var wasCalled atomic.Bool - registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_1ABI, registry.ContractAddress.Address()) - registryMock.MockRevertResponse("checkUpkeep").Run(func(args mock.Arguments) { - wasCalled.Store(true) - }) - - head := newHead() - executer.OnNewLongestChain(testutils.Context(t), &head) - - g.Eventually(wasCalled.Load).Should(gomega.BeTrue()) - - txStore := txmgr.NewTxStore(db, logger.TestLogger(t)) - txes, err := txStore.GetAllTxes(testutils.Context(t)) - require.NoError(t, err) - require.Empty(t, txes) -} - -func ptr[T any](t T) *T { return &t } diff --git a/core/services/keeper/upkeep_executer_unit_test.go b/core/services/keeper/upkeep_executer_unit_test.go deleted file mode 100644 index cd9d9750073..00000000000 --- a/core/services/keeper/upkeep_executer_unit_test.go +++ /dev/null @@ -1,79 +0,0 @@ -package keeper - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - "github.com/smartcontractkit/chainlink-evm/pkg/assets" - "github.com/smartcontractkit/chainlink-evm/pkg/types" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" -) - -type registry struct { - pgo uint32 - mpds uint32 -} - -func (r *registry) CheckGasOverhead() uint32 { return uint32(0) } -func (r *registry) PerformGasOverhead() uint32 { return r.pgo } -func (r *registry) MaxPerformDataSize() uint32 { return r.mpds } - -func TestBuildJobSpec(t *testing.T) { - from := types.EIP55Address(testutils.NewAddress().Hex()) - contract := types.EIP55Address(testutils.NewAddress().Hex()) - chainID := "250" - jb := job.Job{ - ID: 10, - KeeperSpec: &job.KeeperSpec{ - FromAddress: from, - ContractAddress: contract, - }} - - upkeepID := sqlutil.NewI(4) - upkeep := UpkeepRegistration{ - Registry: Registry{ - FromAddress: from, - ContractAddress: contract, - CheckGas: 11, - }, - UpkeepID: upkeepID, - ExecuteGas: 12, - } - gasPrice := assets.NewWeiI(24) - gasTipCap := assets.NewWeiI(48) - gasFeeCap := assets.NewWeiI(72) - - r := ®istry{ - pgo: uint32(9), - mpds: uint32(1000), - } - - spec := buildJobSpec(jb, jb.KeeperSpec.FromAddress.Address(), upkeep, r, gasPrice, gasTipCap, gasFeeCap, chainID) - - expected := map[string]any{ - "jobSpec": map[string]any{ - "jobID": int32(10), - "fromAddress": from.String(), - "effectiveKeeperAddress": jb.KeeperSpec.FromAddress.String(), - "contractAddress": contract.String(), - "upkeepID": "4", - "prettyID": fmt.Sprintf("UPx%064d", 4), - "pipelineSpec": &pipeline.Spec{ - ForwardingAllowed: false, - }, - "performUpkeepGasLimit": uint32(5_000_000 + 9), - "maxPerformDataSize": uint32(1000), - "gasPrice": gasPrice.ToInt(), - "gasTipCap": gasTipCap.ToInt(), - "gasFeeCap": gasFeeCap.ToInt(), - "evmChainID": "250", - }, - } - - require.Equal(t, expected, spec) -} diff --git a/core/services/keeper/utils.go b/core/services/keeper/utils.go deleted file mode 100644 index e1b137ae47b..00000000000 --- a/core/services/keeper/utils.go +++ /dev/null @@ -1,39 +0,0 @@ -package keeper - -import ( - "math" - "math/big" - "strings" - - ethmath "github.com/ethereum/go-ethereum/common/math" -) - -const ( - ZeroPrefix = "0x" - UpkeepPrefix = "UPx" -) - -// LeastSignificant32 returns the least significant 32 bits of the input as a big int -func LeastSignificant32(num *big.Int) uint64 { - max32 := big.NewInt(math.MaxUint32) - return big.NewInt(0).And(num, max32).Uint64() -} - -// ParseUpkeepId parses the upkeep id input string to a big int pointer. It can handle the following 4 formats: -// 1. decimal format like 123471239047239047243709... -// 2. hex format like AbC13D354eFF... -// 3. 0x-prefixed hex like 0xAbC13D354eFF... -// 4. Upkeep-prefixed hex like UPxAbC13D354eFF... -func ParseUpkeepId(upkeepIdStr string) (*big.Int, bool) { - if strings.HasPrefix(upkeepIdStr, UpkeepPrefix) { - upkeepIdStr = ZeroPrefix + upkeepIdStr[len(UpkeepPrefix):] - } - - // this handles cases 1, 3, 4 - upkeepId, ok := ethmath.ParseBig256(upkeepIdStr) - if !ok { - // this handles case 2 or returns (nil, false) - return ethmath.ParseBig256(ZeroPrefix + upkeepIdStr) - } - return upkeepId, ok -} diff --git a/core/services/keeper/validate.go b/core/services/keeper/validate.go deleted file mode 100644 index 71c562b8641..00000000000 --- a/core/services/keeper/validate.go +++ /dev/null @@ -1,47 +0,0 @@ -package keeper - -import ( - "strings" - - "github.com/google/uuid" - "github.com/pelletier/go-toml" - "github.com/pkg/errors" - - "github.com/smartcontractkit/chainlink/v2/core/services/job" -) - -// ValidatedKeeperSpec analyses the tomlString passed as parameter and -// returns a newly-created Job if there are no validation errors inside the toml. -func ValidatedKeeperSpec(tomlString string) (job.Job, error) { - // Create a new job with a randomly generated uuid, which can be replaced with the one from tomlString. - var j = job.Job{ - ExternalJobID: uuid.New(), - } - - tree, err := toml.Load(tomlString) - if err != nil { - return j, err - } - - if err := tree.Unmarshal(&j); err != nil { - return j, err - } - - var spec job.KeeperSpec - if err := tree.Unmarshal(&spec); err != nil { - return j, err - } - - j.KeeperSpec = &spec - - if j.Type != job.Keeper { - return j, errors.Errorf("unsupported type %s", j.Type) - } - - if strings.Contains(tomlString, "observationSource") || - strings.Contains(tomlString, "ObservationSource") { - return j, errors.New("There should be no 'observationSource' parameter included in the toml") - } - - return j, nil -} diff --git a/core/services/keeper/validate_test.go b/core/services/keeper/validate_test.go deleted file mode 100644 index cfa6a1520f5..00000000000 --- a/core/services/keeper/validate_test.go +++ /dev/null @@ -1,195 +0,0 @@ -package keeper - -import ( - "testing" - "time" - - "github.com/stretchr/testify/require" -) - -func TestValidatedKeeperSpec(t *testing.T) { - t.Parallel() - - type args struct { - tomlString string - } - - type want struct { - id int32 - contractAddr string - fromAddr string - createdAt time.Time - updatedAt time.Time - } - - tests := []struct { - name string - args args - want want - wantErr bool - }{ - { - name: "valid job spec", - args: args{ - tomlString: ` - type = "keeper" - name = "example keeper spec" - contractAddress = "0x9E40733cC9df84636505f4e6Db28DCa0dC5D1bba" - fromAddress = "0xa8037A20989AFcBC51798de9762b351D63ff462e" - externalJobID = "123e4567-e89b-12d3-a456-426655440002" - `, - }, - want: want{ - id: 0, - contractAddr: "0x9E40733cC9df84636505f4e6Db28DCa0dC5D1bba", - fromAddr: "0xa8037A20989AFcBC51798de9762b351D63ff462e", - createdAt: time.Time{}, - updatedAt: time.Time{}, - }, - wantErr: false, - }, - - { - name: "valid job spec with reordered fields", - args: args{ - tomlString: ` - type = "keeper" - name = "example keeper spec" - contractAddress = "0x9E40733cC9df84636505f4e6Db28DCa0dC5D1bba" - fromAddress = "0xa8037A20989AFcBC51798de9762b351D63ff462e" - evmChainID = 4 - externalJobID = "123e4567-e89b-12d3-a456-426655440002" - `, - }, - want: want{ - id: 0, - contractAddr: "0x9E40733cC9df84636505f4e6Db28DCa0dC5D1bba", - fromAddr: "0xa8037A20989AFcBC51798de9762b351D63ff462e", - createdAt: time.Time{}, - updatedAt: time.Time{}, - }, - wantErr: false, - }, - - { - name: "invalid job spec because of type", - args: args{ - tomlString: ` - type = "vrf" - name = "invalid keeper spec example 1" - contractAddress = "0x9E40733cC9df84636505f4e6Db28DCa0dC5D1bba" - fromAddress = "0xa8037A20989AFcBC51798de9762b351D63ff462e" - evmChainID = 4 - externalJobID = "123e4567-e89b-12d3-a456-426655440002" - `, - }, - want: want{}, - wantErr: true, - }, - - { - name: "invalid job spec because observation source is passed as parameter (lowercase)", - args: args{ - tomlString: ` - type = "keeper" - name = "invalid keeper spec example 2" - contractAddress = "0x9E40733cC9df84636505f4e6Db28DCa0dC5D1bba" - fromAddress = "0xa8037A20989AFcBC51798de9762b351D63ff462e" - evmChainID = 4 - externalJobID = "123e4567-e89b-12d3-a456-426655440002" - observationSource = " - encode_check_upkeep_tx [type=ethabiencode abi="checkUpkeep(uint256 id, address from)" - data="{\"id\":$(jobSpec.upkeepID),\"from\":$(jobSpec.fromAddress)}"] - check_upkeep_tx [type=ethcall - failEarly=false - extractRevertReason=false - evmChainID="$(jobSpec.evmChainID)" - contract="$(jobSpec.contractAddress)" - gas="$(jobSpec.checkUpkeepGasLimit)" - gasPrice="$(jobSpec.gasPrice)" - gasTipCap="$(jobSpec.gasTipCap)" - gasFeeCap="$(jobSpec.gasFeeCap)" - data="$(encode_check_upkeep_tx)"] - decode_check_upkeep_tx [type=ethabidecode - abi="bytes memory performData, uint256 maxLinkPayment, - uint256 gasLimit, uint256 adjustedGasWei, uint256 linkEth"] - encode_perform_upkeep_tx [type=ethabiencode - abi="performUpkeep(uint256 id, bytes calldata performData)" - data="{\"id\": $(jobSpec.upkeepID),\"performData\":$(decode_check_upkeep_tx.performData)}"] - perform_upkeep_tx [type=ethtx - minConfirmations=2 - to="$(jobSpec.contractAddress)" - from="[$(jobSpec.fromAddress)]" - evmChainID="$(jobSpec.evmChainID)" - data="$(encode_perform_upkeep_tx)" - gasLimit="$(jobSpec.performUpkeepGasLimit)" - txMeta="{\"jobID\":$(jobSpec.jobID),\"upkeepID\":$(jobSpec.prettyID)}"] - encode_check_upkeep_tx -> check_upkeep_tx -> decode_check_upkeep_tx -> encode_perform_upkeep_tx -> perform_upkeep_tx" - `, - }, - want: want{}, - wantErr: true, - }, - - { - name: "invalid job spec because observation source is passed as parameter (uppercase)", - args: args{ - tomlString: ` - type = "keeper" - name = "invalid keeper spec example 2" - contractAddress = "0x9E40733cC9df84636505f4e6Db28DCa0dC5D1bba" - fromAddress = "0xa8037A20989AFcBC51798de9762b351D63ff462e" - evmChainID = 4 - externalJobID = "123e4567-e89b-12d3-a456-426655440002" - ObservationSource = " - encode_check_upkeep_tx [type=ethabiencode abi="checkUpkeep(uint256 id, address from)" - data="{\"id\":$(jobSpec.upkeepID),\"from\":$(jobSpec.fromAddress)}"] - check_upkeep_tx [type=ethcall - failEarly=false - extractRevertReason=false - evmChainID="$(jobSpec.evmChainID)" - contract="$(jobSpec.contractAddress)" - gas="$(jobSpec.checkUpkeepGasLimit)" - gasPrice="$(jobSpec.gasPrice)" - gasTipCap="$(jobSpec.gasTipCap)" - gasFeeCap="$(jobSpec.gasFeeCap)" - data="$(encode_check_upkeep_tx)"] - decode_check_upkeep_tx [type=ethabidecode - abi="bytes memory performData, uint256 maxLinkPayment, - uint256 gasLimit, uint256 adjustedGasWei, uint256 linkEth"] - encode_perform_upkeep_tx [type=ethabiencode - abi="performUpkeep(uint256 id, bytes calldata performData)" - data="{\"id\": $(jobSpec.upkeepID),\"performData\":$(decode_check_upkeep_tx.performData)}"] - perform_upkeep_tx [type=ethtx - minConfirmations=2 - to="$(jobSpec.contractAddress)" - from="[$(jobSpec.fromAddress)]" - evmChainID="$(jobSpec.evmChainID)" - data="$(encode_perform_upkeep_tx)" - gasLimit="$(jobSpec.performUpkeepGasLimit)" - txMeta="{\"jobID\":$(jobSpec.jobID),\"upkeepID\":$(jobSpec.prettyID)}"] - encode_check_upkeep_tx -> check_upkeep_tx -> decode_check_upkeep_tx -> encode_perform_upkeep_tx -> perform_upkeep_tx" - `, - }, - want: want{}, - wantErr: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := ValidatedKeeperSpec(tt.args.tomlString) - if tt.wantErr { - require.Error(t, err) - return - } - require.NoError(t, err) - - require.Equal(t, tt.want.id, got.ID) - require.Equal(t, tt.want.contractAddr, got.KeeperSpec.ContractAddress.Hex()) - require.Equal(t, tt.want.fromAddr, got.KeeperSpec.FromAddress.Hex()) - require.Equal(t, tt.want.createdAt, got.KeeperSpec.CreatedAt) - require.Equal(t, tt.want.updatedAt, got.KeeperSpec.UpdatedAt) - }) - } -} diff --git a/core/services/pipeline/common.go b/core/services/pipeline/common.go index a54bc96e477..47486f6dbd5 100644 --- a/core/services/pipeline/common.go +++ b/core/services/pipeline/common.go @@ -37,7 +37,6 @@ const ( DirectRequestJobType string = "directrequest" FluxMonitorJobType string = "fluxmonitor" GatewayJobType string = "gateway" - KeeperJobType string = "keeper" LegacyGasStationServerJobType string = "legacygasstationserver" LegacyGasStationSidecarJobType string = "legacygasstationsidecar" OffchainReporting2JobType string = "offchainreporting2" @@ -539,8 +538,6 @@ func SelectGasLimit(ge config.GasEstimator, jobType string, specGasLimit *uint32 jobTypeGasLimit = jt.OCR() case OffchainReporting2JobType: jobTypeGasLimit = jt.OCR2() - case KeeperJobType: - jobTypeGasLimit = jt.Keeper() case VRFJobType: jobTypeGasLimit = jt.VRF() } diff --git a/core/services/pipeline/common_test.go b/core/services/pipeline/common_test.go index 94b1d1a2f49..af798e158f5 100644 --- a/core/services/pipeline/common_test.go +++ b/core/services/pipeline/common_test.go @@ -242,12 +242,11 @@ func TestSelectGasLimit(t *testing.T) { gcfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].GasEstimator.LimitDefault = ptr(uint64(999)) c.EVM[0].GasEstimator.LimitJobType = toml.GasLimitJobType{ - DR: ptr(uint32(100)), - VRF: ptr(uint32(101)), - FM: ptr(uint32(102)), - OCR: ptr(uint32(103)), - Keeper: ptr(uint32(104)), - OCR2: ptr(uint32(105)), + DR: ptr(uint32(100)), + VRF: ptr(uint32(101)), + FM: ptr(uint32(102)), + OCR: ptr(uint32(103)), + OCR2: ptr(uint32(105)), } }) cfg := evmtest.NewChainScopedConfig(t, gcfg) @@ -283,11 +282,6 @@ func TestSelectGasLimit(t *testing.T) { assert.Equal(t, uint64(102), gasLimit) }) - t.Run("keeper specific gas limit", func(t *testing.T) { - gasLimit := pipeline.SelectGasLimit(cfg.EVM().GasEstimator(), pipeline.KeeperJobType, nil) - assert.Equal(t, uint64(104), gasLimit) - }) - t.Run("fallback to default gas limit", func(t *testing.T) { gasLimit := pipeline.SelectGasLimit(cfg.EVM().GasEstimator(), pipeline.WebhookJobType, nil) assert.Equal(t, uint64(999), gasLimit) diff --git a/core/services/pipeline/orm.go b/core/services/pipeline/orm.go index 4fbb04b101f..fa9c91d776b 100644 --- a/core/services/pipeline/orm.go +++ b/core/services/pipeline/orm.go @@ -18,57 +18,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) -// KeepersObservationSource is the same for all keeper jobs and it is not persisted in DB -const KeepersObservationSource = ` - encode_check_upkeep_tx [type=ethabiencode - abi="checkUpkeep(uint256 id, address from)" - data="{\"id\":$(jobSpec.upkeepID),\"from\":$(jobSpec.effectiveKeeperAddress)}"] - check_upkeep_tx [type=ethcall - failEarly=true - extractRevertReason=true - evmChainID="$(jobSpec.evmChainID)" - contract="$(jobSpec.contractAddress)" - gasUnlimited=true - gasPrice="$(jobSpec.gasPrice)" - gasTipCap="$(jobSpec.gasTipCap)" - gasFeeCap="$(jobSpec.gasFeeCap)" - data="$(encode_check_upkeep_tx)"] - decode_check_upkeep_tx [type=ethabidecode - abi="bytes memory performData, uint256 maxLinkPayment, uint256 gasLimit, uint256 adjustedGasWei, uint256 linkEth"] - calculate_perform_data_len [type=length - input="$(decode_check_upkeep_tx.performData)"] - perform_data_lessthan_limit [type=lessthan - left="$(calculate_perform_data_len)" - right="$(jobSpec.maxPerformDataSize)"] - check_perform_data_limit [type=conditional - failEarly=true - data="$(perform_data_lessthan_limit)"] - encode_perform_upkeep_tx [type=ethabiencode - abi="performUpkeep(uint256 id, bytes calldata performData)" - data="{\"id\": $(jobSpec.upkeepID),\"performData\":$(decode_check_upkeep_tx.performData)}"] - simulate_perform_upkeep_tx [type=ethcall - extractRevertReason=true - evmChainID="$(jobSpec.evmChainID)" - contract="$(jobSpec.contractAddress)" - from="$(jobSpec.effectiveKeeperAddress)" - gasUnlimited=true - data="$(encode_perform_upkeep_tx)"] - decode_check_perform_tx [type=ethabidecode - abi="bool success"] - check_success [type=conditional - failEarly=true - data="$(decode_check_perform_tx.success)"] - perform_upkeep_tx [type=ethtx - minConfirmations=0 - to="$(jobSpec.contractAddress)" - from="[$(jobSpec.fromAddress)]" - evmChainID="$(jobSpec.evmChainID)" - data="$(encode_perform_upkeep_tx)" - gasLimit="$(jobSpec.performUpkeepGasLimit)" - txMeta="{\"jobID\":$(jobSpec.jobID),\"upkeepID\":$(jobSpec.prettyID)}"] - encode_check_upkeep_tx -> check_upkeep_tx -> decode_check_upkeep_tx -> calculate_perform_data_len -> perform_data_lessthan_limit -> check_perform_data_limit -> encode_perform_upkeep_tx -> simulate_perform_upkeep_tx -> decode_check_perform_tx -> check_success -> perform_upkeep_tx -` - type CreateDataSource interface { GetContext(ctx context.Context, dest any, query string, args ...any) error } @@ -655,9 +604,6 @@ func loadAssociations(ctx context.Context, ds sqlutil.DataSource, runs []*Run) e return errors.Wrap(err, "failed to postload pipeline_specs for runs") } for _, spec := range specs { - if spec.JobType == "keeper" { - spec.DotDagSource = KeepersObservationSource - } pipelineSpecIDM[spec.ID] = spec } diff --git a/core/services/pipeline/orm_test.go b/core/services/pipeline/orm_test.go index 6b636d69cf6..00c0f896dc4 100644 --- a/core/services/pipeline/orm_test.go +++ b/core/services/pipeline/orm_test.go @@ -640,109 +640,6 @@ func Test_PipelineORM_DeleteRunsOlderThan(t *testing.T) { } } -func Test_GetUnfinishedRuns_Keepers(t *testing.T) { - t.Parallel() - ctx := testutils.Context(t) - - // The test configures single Keeper job with two running tasks. - // GetUnfinishedRuns() expects to catch both running tasks. - - config := configtest.NewTestGeneralConfig(t) - lggr := logger.TestLogger(t) - db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db) - porm := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) - bridgeORM := bridges.NewORM(db) - - jorm := job.NewORM(db, porm, bridgeORM, keyStore, lggr) - defer func() { assert.NoError(t, jorm.Close()) }() - - timestamp := time.Now() - var keeperJob = job.Job{ - ID: 1, - KeeperSpec: &job.KeeperSpec{ - ContractAddress: cltest.NewEIP55Address(), - FromAddress: cltest.NewEIP55Address(), - CreatedAt: timestamp, - UpdatedAt: timestamp, - EVMChainID: (*sqlutil.Big)(&cltest.FixtureChainID), - }, - ExternalJobID: uuid.MustParse("0EEC7E1D-D0D2-476C-A1A8-72DFB6633F46"), - PipelineSpec: &pipeline.Spec{ - ID: 1, - DotDagSource: "", - }, - Type: job.Keeper, - SchemaVersion: 1, - Name: null.StringFrom("test"), - MaxTaskDuration: sqlutil.Interval(1 * time.Minute), - } - - err := jorm.CreateJob(ctx, &keeperJob) - require.NoError(t, err) - require.Equal(t, job.Keeper, keeperJob.Type) - - runID1 := uuid.New() - runID2 := uuid.New() - - err = porm.CreateRun(ctx, &pipeline.Run{ - PipelineSpecID: keeperJob.PipelineSpecID, - PruningKey: keeperJob.ID, - State: pipeline.RunStatusRunning, - Outputs: jsonserializable.JSONSerializable{}, - CreatedAt: time.Now(), - PipelineTaskRuns: []pipeline.TaskRun{{ - ID: runID1, - Type: pipeline.TaskTypeETHTx, - Index: 0, - Output: jsonserializable.JSONSerializable{}, - CreatedAt: time.Now(), - DotID: "perform_upkeep_tx", - }}, - }) - require.NoError(t, err) - - err = porm.CreateRun(ctx, &pipeline.Run{ - PipelineSpecID: keeperJob.PipelineSpecID, - PruningKey: keeperJob.ID, - State: pipeline.RunStatusRunning, - Outputs: jsonserializable.JSONSerializable{}, - CreatedAt: time.Now(), - PipelineTaskRuns: []pipeline.TaskRun{{ - ID: runID2, - Type: pipeline.TaskTypeETHCall, - Index: 1, - Output: jsonserializable.JSONSerializable{}, - CreatedAt: time.Now(), - DotID: "check_upkeep_tx", - }}, - }) - require.NoError(t, err) - - var counter int - - err = porm.GetUnfinishedRuns(testutils.Context(t), time.Now(), func(run pipeline.Run) error { - counter++ - - require.Equal(t, job.Keeper.String(), run.PipelineSpec.JobType) - require.Equal(t, pipeline.KeepersObservationSource, run.PipelineSpec.DotDagSource) - require.NotEmpty(t, run.PipelineTaskRuns) - - switch run.PipelineTaskRuns[0].ID { - case runID1: - trun := run.ByDotID("perform_upkeep_tx") - require.NotNil(t, trun) - case runID2: - trun := run.ByDotID("check_upkeep_tx") - require.NotNil(t, trun) - } - - return nil - }) - require.NoError(t, err) - require.Equal(t, 2, counter) -} - func Test_GetUnfinishedRuns_DirectRequest(t *testing.T) { t.Parallel() ctx := testutils.Context(t) diff --git a/core/store/migrate/migrate_test.go b/core/store/migrate/migrate_test.go index 77288cb5f64..031a110e592 100644 --- a/core/store/migrate/migrate_test.go +++ b/core/store/migrate/migrate_test.go @@ -96,6 +96,8 @@ func TestMigrate_0100_BootstrapConfigs(t *testing.T) { // Job struct at migration v0099 type Job struct { job.Job + // keeper_spec_id remains on jobs until migration 0296; sqlx requires a field for SELECT * before then. + KeeperSpecID *int32 `db:"keeper_spec_id"` OffchainreportingOracleSpecID *int32 Offchainreporting2OracleSpecID *int32 Offchainreporting2OracleSpec *OffchainReporting2OracleSpec diff --git a/core/store/migrate/migrations/0296_drop_legacy_keeper_job.sql b/core/store/migrate/migrations/0296_drop_legacy_keeper_job.sql new file mode 100644 index 00000000000..e706097b6c5 --- /dev/null +++ b/core/store/migrate/migrations/0296_drop_legacy_keeper_job.sql @@ -0,0 +1,125 @@ +-- +goose Up +-- +goose StatementBegin + +DELETE FROM jobs WHERE type = 'keeper'; + +DROP INDEX IF EXISTS idx_jobs_unique_keeper_spec_id; + +ALTER TABLE jobs DROP CONSTRAINT IF EXISTS jobs_keeper_spec_id_fkey; + +-- chk_specs still references keeper_spec_id from prior migrations; drop it before the column. +ALTER TABLE jobs DROP CONSTRAINT IF EXISTS chk_specs; + +ALTER TABLE jobs DROP COLUMN IF EXISTS keeper_spec_id; + +DROP TABLE IF EXISTS upkeep_registrations; +DROP TABLE IF EXISTS keeper_registries; +DROP TABLE IF EXISTS keeper_specs; + +ALTER TABLE jobs ADD CONSTRAINT chk_specs CHECK ( + num_nonnulls( + ocr_oracle_spec_id, ocr2_oracle_spec_id, + direct_request_spec_id, flux_monitor_spec_id, + cron_spec_id, webhook_spec_id, + vrf_spec_id, blockhash_store_spec_id, + block_header_feeder_spec_id, bootstrap_spec_id, + gateway_spec_id, + legacy_gas_station_server_spec_id, + legacy_gas_station_sidecar_spec_id, + eal_spec_id, + workflow_spec_id, + standard_capabilities_spec_id, + ccip_spec_id, + ccip_bootstrap_spec_id, + cre_settings_spec_id, + ccv_committee_verifier_spec_id, + ccv_executor_spec_id, + CASE "type" + WHEN 'stream' + THEN 1 + ELSE NULL + END + ) = 1 + ); + +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin + +CREATE TABLE keeper_specs ( + id BIGSERIAL PRIMARY KEY, + contract_address bytea NOT NULL, + from_address bytea NOT NULL, + created_at timestamptz NOT NULL, + updated_at timestamptz NOT NULL, + min_incoming_confirmations integer, + evm_chain_id numeric(78,0) NOT NULL, + CONSTRAINT keeper_specs_contract_address_check CHECK ((octet_length(contract_address) = 20)), + CONSTRAINT keeper_specs_from_address_check CHECK ((octet_length(from_address) = 20)) +); + +CREATE TABLE keeper_registries ( + id BIGSERIAL PRIMARY KEY, + job_id int UNIQUE NOT NULL REFERENCES jobs (id) ON DELETE CASCADE DEFERRABLE INITIALLY IMMEDIATE, + keeper_index int NOT NULL, + contract_address bytea UNIQUE NOT NULL, + from_address bytea NOT NULL, + check_gas int NOT NULL, + block_count_per_turn int NOT NULL, + num_keepers int NOT NULL, + keeper_index_map jsonb DEFAULT NULL, + CONSTRAINT keeper_registries_contract_address_check CHECK ((octet_length(contract_address) = 20)), + CONSTRAINT keeper_registries_from_address_check CHECK ((octet_length(from_address) = 20)) +); + +CREATE INDEX idx_keeper_registries_keeper_index ON keeper_registries (keeper_index); + +CREATE TABLE upkeep_registrations ( + id BIGSERIAL PRIMARY KEY, + registry_id bigint NOT NULL REFERENCES keeper_registries (id) ON DELETE CASCADE DEFERRABLE INITIALLY IMMEDIATE, + execute_gas int NOT NULL, + check_data bytea NOT NULL, + upkeep_id numeric(78,0) NOT NULL, + positioning_constant int NOT NULL, + last_run_block_height bigint NOT NULL DEFAULT 0, + last_keeper_index integer DEFAULT NULL +); + +CREATE UNIQUE INDEX idx_upkeep_registrations_unique_upkeep_ids_per_keeper ON upkeep_registrations (registry_id, upkeep_id); +CREATE INDEX idx_upkeep_registrations_upkeep_id ON upkeep_registrations (upkeep_id); + +ALTER TABLE jobs ADD COLUMN keeper_spec_id INT; + +ALTER TABLE jobs DROP CONSTRAINT IF EXISTS chk_specs; +ALTER TABLE jobs ADD CONSTRAINT chk_specs CHECK ( + num_nonnulls( + ocr_oracle_spec_id, ocr2_oracle_spec_id, + direct_request_spec_id, flux_monitor_spec_id, + keeper_spec_id, cron_spec_id, webhook_spec_id, + vrf_spec_id, blockhash_store_spec_id, + block_header_feeder_spec_id, bootstrap_spec_id, + gateway_spec_id, + legacy_gas_station_server_spec_id, + legacy_gas_station_sidecar_spec_id, + eal_spec_id, + workflow_spec_id, + standard_capabilities_spec_id, + ccip_spec_id, + ccip_bootstrap_spec_id, + cre_settings_spec_id, + ccv_committee_verifier_spec_id, + ccv_executor_spec_id, + CASE "type" + WHEN 'stream' + THEN 1 + ELSE NULL + END + ) = 1 + ); + +ALTER TABLE jobs ADD CONSTRAINT jobs_keeper_spec_id_fkey FOREIGN KEY (keeper_spec_id) REFERENCES keeper_specs (id) ON DELETE CASCADE; + +CREATE UNIQUE INDEX idx_jobs_unique_keeper_spec_id ON jobs (keeper_spec_id); + +-- +goose StatementEnd diff --git a/core/testdata/testspecs/v2_specs.go b/core/testdata/testspecs/v2_specs.go index ea03edc0e13..f68aa30bf3e 100644 --- a/core/testdata/testspecs/v2_specs.go +++ b/core/testdata/testspecs/v2_specs.go @@ -291,41 +291,6 @@ func GetWebhookSpecNoBody(u uuid.UUID, fetchBridge, submitBridge string) string return fmt.Sprintf(WebhookSpecNoBodyTemplate, u, fetchBridge, submitBridge) } -type KeeperSpecParams struct { - Name string - ContractAddress string - FromAddress string - EvmChainID int - ObservationSource string -} - -type KeeperSpec struct { - KeeperSpecParams - toml string -} - -func (os KeeperSpec) Toml() string { - return os.toml -} - -func GenerateKeeperSpec(params KeeperSpecParams) KeeperSpec { - template := ` -type = "keeper" -schemaVersion = 1 -name = "%s" -contractAddress = "%s" -fromAddress = "%s" -evmChainID = %d -externalJobID = "123e4567-e89b-12d3-a456-426655440002" -observationSource = """%s""" -` - escapedObvSource := strings.ReplaceAll(params.ObservationSource, `\`, `\\`) - return KeeperSpec{ - KeeperSpecParams: params, - toml: fmt.Sprintf(template, params.Name, params.ContractAddress, params.FromAddress, params.EvmChainID, escapedObvSource), - } -} - type VRFSpecParams struct { JobID string Name string diff --git a/core/web/chains_controller_integration_test.go b/core/web/chains_controller_integration_test.go index 6e80932e1c8..35be8af90f0 100644 --- a/core/web/chains_controller_integration_test.go +++ b/core/web/chains_controller_integration_test.go @@ -5,6 +5,7 @@ package web_test import ( "cmp" "fmt" + "math/rand/v2" "net/http" "testing" @@ -14,6 +15,7 @@ import ( "github.com/stretchr/testify/require" commonTypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" @@ -214,3 +216,217 @@ func setupCosmosChainsControllerTestV2(t *testing.T, cfgs ...chainlink.RawConfig client: client, } } + +func Test_SolanaChainsController_Show(t *testing.T) { + t.Parallel() + + const validID = "Chainlink-12" + + testCases := []struct { + name string + inputID string + wantStatusCode int + want func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus + }{ + { + inputID: validID, + name: "success", + want: func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus { + return &commonTypes.ChainStatus{ + ID: validID, + Enabled: true, + Config: `ChainID = 'Chainlink-12' +Enabled = true +BlockTime = '500ms' +BalancePollPeriod = '5s' +ConfirmPollPeriod = '500ms' +OCR2CachePollPeriod = '1s' +OCR2CacheTTL = '1m0s' +TxTimeout = '1h0m0s' +TxRetryTimeout = '10s' +TxConfirmTimeout = '30s' +TxExpirationRebroadcast = false +TxRetentionTimeout = '0s' +SkipPreflight = false +Commitment = 'confirmed' +MaxRetries = 0 +FeeEstimatorMode = 'fixed' +ComputeUnitPriceMax = 1000 +ComputeUnitPriceMin = 0 +ComputeUnitPriceDefault = 0 +FeeBumpPeriod = '3s' +BlockHistoryPollPeriod = '5s' +BlockHistorySize = 1 +BlockHistoryBatchLoadSize = 20 +ComputeUnitLimitDefault = 200000 +EstimateComputeUnitLimit = false +LogPollerStartingLookback = '24h0m0s' +LogPollerCPIEventsEnabled = true +LogPollerSlotsBatchSize = 1000 + +[Workflow] +AcceptanceTimeout = '45s' +ForwarderAddress = '11111111111111111111111111111111' +ForwarderState = '11111111111111111111111111111111' +FromAddress = '11111111111111111111111111111111' +GasLimitDefault = 300000 +Local = false +PollPeriod = '3s' +TxAcceptanceState = 3 + +[MultiNode] +Enabled = false +PollFailureThreshold = 5 +PollInterval = '15s' +SelectionMode = 'PriorityLevel' +SyncThreshold = 10 +NodeIsSyncingEnabled = false +LeaseDuration = '1m0s' +NewHeadsPollInterval = '5s' +FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '20s' +VerifyChainID = true +NodeNoNewHeadsThreshold = '20s' +NoNewFinalizedHeadsThreshold = '20s' +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 50 + +[[Nodes]] +Name = 'primary' +URL = 'http://solana.example' +SendOnly = false +`, + } + }, + wantStatusCode: http.StatusOK, + }, + { + inputID: "234", + name: "not found", + want: func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus { + return nil + }, + wantStatusCode: http.StatusBadRequest, + }, + } + + for _, testCase := range testCases { + tc := testCase + + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + controller := setupSolanaChainsControllerTestV2(t, chainlink.RawConfig{ + "ChainID": validID, + "SkipPreflight": false, + "TxTimeout": "1h0m0s", + "Nodes": []map[string]any{{ + "Name": "primary", + "URL": "http://solana.example", + }}, + }) + + wantedResult := tc.want(t, controller.app) + resp, cleanup := controller.client.Get( + "/v2/chains/solana/" + tc.inputID, + ) + t.Cleanup(cleanup) + require.Equal(t, tc.wantStatusCode, resp.StatusCode) + + if wantedResult != nil { + resource1 := presenters.ChainResource{} + err := web.ParseJSONAPIResponse(cltest.ParseResponseBody(t, resp), &resource1) + require.NoError(t, err) + + assert.Equal(t, wantedResult.ID, resource1.ID) + assert.Equal(t, wantedResult.Enabled, resource1.Enabled) + assert.Equal(t, wantedResult.Config, resource1.Config) + } + }) + } +} + +func Test_SolanaChainsController_Index(t *testing.T) { + t.Parallel() + + chainA := chainlink.RawConfig{ + "ChainID": fmt.Sprintf("ChainlinktestA-%d", rand.Int32N(999999)), + "TxTimeout": "1h0m0s", + "Nodes": []map[string]any{{ + "Name": "primary", + "URL": "http://solana.example", + }}, + } + chainB := chainlink.RawConfig{ + "ChainID": fmt.Sprintf("ChainlinktestB-%d", rand.Int32N(999999)), + "SkipPreflight": false, + "Nodes": []map[string]any{{ + "Name": "primary", + "URL": "http://solana.example", + }}, + } + controller := setupSolanaChainsControllerTestV2(t, chainA, chainB) + + badResp, cleanup := controller.client.Get("/v2/chains/solana?size=asd") + t.Cleanup(cleanup) + require.Equal(t, http.StatusUnprocessableEntity, badResp.StatusCode) + + resp, cleanup := controller.client.Get("/v2/chains/solana?size=1") + t.Cleanup(cleanup) + require.Equal(t, http.StatusOK, resp.StatusCode) + + body := cltest.ParseResponseBody(t, resp) + + metaCount, err := cltest.ParseJSONAPIResponseMetaCount(body) + require.NoError(t, err) + require.Equal(t, 2, metaCount) + + var links jsonapi.Links + + chains := []presenters.ChainResource{} + err = web.ParsePaginatedResponse(body, &chains, &links) + require.NoError(t, err) + assert.NotEmpty(t, links["next"].Href) + assert.Empty(t, links["prev"].Href) + + assert.Len(t, links, 1) + assert.Equal(t, chainA.ChainID(), chains[0].ID) + assert.NotEmpty(t, chains[0].Config) + + resp, cleanup = controller.client.Get(links["next"].Href) + t.Cleanup(cleanup) + require.Equal(t, http.StatusOK, resp.StatusCode) + + chains = []presenters.ChainResource{} + err = web.ParsePaginatedResponse(cltest.ParseResponseBody(t, resp), &chains, &links) + require.NoError(t, err) + assert.Empty(t, links["next"].Href) + assert.NotEmpty(t, links["prev"].Href) + + assert.Len(t, links, 1) + assert.Equal(t, chainB.ChainID(), chains[0].ID) + assert.NotEmpty(t, chains[0].Config) +} + +type TestSolanaChainsController struct { + app *cltest.TestApplication + client cltest.HTTPClientCleaner +} + +func setupSolanaChainsControllerTestV2(t *testing.T, cfgs ...chainlink.RawConfig) *TestSolanaChainsController { + cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.Solana = cfgs + c.EVM = nil + }) + app := cltest.NewApplicationWithConfig(t, cfg) + require.NoError(t, app.Start(testutils.Context(t))) + + client := app.NewHTTPClient(nil) + + return &TestSolanaChainsController{ + app: app, + client: client, + } +} diff --git a/core/web/chains_controller_test.go b/core/web/chains_controller_test.go index 2b3f14b0ee3..84aa901b9e4 100644 --- a/core/web/chains_controller_test.go +++ b/core/web/chains_controller_test.go @@ -1,24 +1,18 @@ package web_test import ( - "fmt" "math/big" "net/http" "sort" "testing" - "time" "github.com/manyminds/api2go/jsonapi" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/exp/rand" "github.com/smartcontractkit/quarantine" - commoncfg "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - commonTypes "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" "github.com/smartcontractkit/chainlink-evm/pkg/config/toml" "github.com/smartcontractkit/chainlink-evm/pkg/types" @@ -230,167 +224,4 @@ func setupEVMChainsControllerTest(t *testing.T, cfg chainlink.GeneralConfig) *Te } } -func Test_SolanaChainsController_Show(t *testing.T) { - t.Parallel() - - const validID = "Chainlink-12" - - testCases := []struct { - name string - inputID string - wantStatusCode int - want func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus - }{ - { - inputID: validID, - name: "success", - want: func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus { - wc := &config.TOMLConfig{ - ChainID: ptr(validID), - Chain: config.Chain{ - SkipPreflight: ptr(false), - TxTimeout: commoncfg.MustNewDuration(time.Hour), - }, - } - wc.SetDefaults() - cfgStr, err := wc.TOMLString() - require.NoError(t, err) - return &commonTypes.ChainStatus{ - ID: validID, - Enabled: true, - Config: cfgStr, - } - }, - wantStatusCode: http.StatusOK, - }, - { - inputID: "234", - name: "not found", - want: func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus { - return nil - }, - wantStatusCode: http.StatusBadRequest, - }, - } - - for _, testCase := range testCases { - tc := testCase - - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - - controller := setupSolanaChainsControllerTestV2(t, &config.TOMLConfig{ - ChainID: ptr(validID), - Chain: config.Chain{ - SkipPreflight: ptr(false), - TxTimeout: commoncfg.MustNewDuration(time.Hour), - }, - }) - - wantedResult := tc.want(t, controller.app) - resp, cleanup := controller.client.Get( - "/v2/chains/solana/" + tc.inputID, - ) - t.Cleanup(cleanup) - require.Equal(t, tc.wantStatusCode, resp.StatusCode) - - if wantedResult != nil { - resource1 := presenters.ChainResource{} - err := web.ParseJSONAPIResponse(cltest.ParseResponseBody(t, resp), &resource1) - require.NoError(t, err) - - assert.Equal(t, wantedResult.ID, resource1.ID) - assert.Equal(t, wantedResult.Enabled, resource1.Enabled) - assert.Equal(t, wantedResult.Config, resource1.Config) - } - }) - } -} - -func Test_SolanaChainsController_Index(t *testing.T) { - t.Parallel() - - chainA := &config.TOMLConfig{ - ChainID: ptr(fmt.Sprintf("ChainlinktestA-%d", rand.Int31n(999999))), - Chain: config.Chain{ - TxTimeout: commoncfg.MustNewDuration(time.Hour), - }, - } - chainB := &config.TOMLConfig{ - ChainID: ptr(fmt.Sprintf("ChainlinktestB-%d", rand.Int31n(999999))), - Chain: config.Chain{ - SkipPreflight: ptr(false), - }, - } - controller := setupSolanaChainsControllerTestV2(t, chainA, chainB) - - badResp, cleanup := controller.client.Get("/v2/chains/solana?size=asd") - t.Cleanup(cleanup) - require.Equal(t, http.StatusUnprocessableEntity, badResp.StatusCode) - - resp, cleanup := controller.client.Get("/v2/chains/solana?size=1") - t.Cleanup(cleanup) - require.Equal(t, http.StatusOK, resp.StatusCode) - - body := cltest.ParseResponseBody(t, resp) - - metaCount, err := cltest.ParseJSONAPIResponseMetaCount(body) - require.NoError(t, err) - require.Equal(t, 2, metaCount) - - var links jsonapi.Links - - chains := []presenters.ChainResource{} - err = web.ParsePaginatedResponse(body, &chains, &links) - require.NoError(t, err) - assert.NotEmpty(t, links["next"].Href) - assert.Empty(t, links["prev"].Href) - - assert.Len(t, links, 1) - assert.Equal(t, *chainA.ChainID, chains[0].ID) - tomlA, err := chainA.TOMLString() - require.NoError(t, err) - assert.Equal(t, tomlA, chains[0].Config) - - resp, cleanup = controller.client.Get(links["next"].Href) - t.Cleanup(cleanup) - require.Equal(t, http.StatusOK, resp.StatusCode) - - chains = []presenters.ChainResource{} - err = web.ParsePaginatedResponse(cltest.ParseResponseBody(t, resp), &chains, &links) - require.NoError(t, err) - assert.Empty(t, links["next"].Href) - assert.NotEmpty(t, links["prev"].Href) - - assert.Len(t, links, 1) - assert.Equal(t, *chainB.ChainID, chains[0].ID) - tomlB, err := chainB.TOMLString() - require.NoError(t, err) - assert.Equal(t, tomlB, chains[0].Config) -} - -type TestSolanaChainsController struct { - app *cltest.TestApplication - client cltest.HTTPClientCleaner -} - -func setupSolanaChainsControllerTestV2(t *testing.T, cfgs ...*config.TOMLConfig) *TestSolanaChainsController { - for i := range cfgs { - cfgs[i].SetDefaults() - } - cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Solana = cfgs - c.EVM = nil - }) - app := cltest.NewApplicationWithConfig(t, cfg) - require.NoError(t, app.Start(testutils.Context(t))) - - client := app.NewHTTPClient(nil) - - return &TestSolanaChainsController{ - app: app, - client: client, - } -} - func ptr[T any](t T) *T { return &t } diff --git a/core/web/health_controller_test.go b/core/web/health_controller_test.go index 90911991700..78f34df8a9e 100644 --- a/core/web/health_controller_test.go +++ b/core/web/health_controller_test.go @@ -13,8 +13,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-common/pkg/config" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" @@ -136,15 +134,7 @@ func TestHealthController_Health_body(t *testing.T) { {".txt-failing", "/health.txt?failing", nil, bodyTXTFailing}, } { t.Run(tc.name, func(t *testing.T) { - cfg := configtest.NewGeneralConfig(t, func(cfg *chainlink.Config, secrets *chainlink.Secrets) { - cfg.Solana = []*solcfg.TOMLConfig{{ - ChainID: ptr("Bar"), - Nodes: solcfg.Nodes{ - {Name: ptr("primary"), URL: config.MustParseURL("http://solana.web")}, - }, - }} - cfg.Solana[0].SetDefaults() - }) + cfg := configtest.NewGeneralConfig(t, func(cfg *chainlink.Config, secrets *chainlink.Secrets) {}) app := cltest.NewApplicationWithConfigAndKey(t, cfg) require.NoError(t, app.Start(testutils.Context(t))) diff --git a/core/web/jobs_controller.go b/core/web/jobs_controller.go index 5888ccd4d00..7751027ae5c 100644 --- a/core/web/jobs_controller.go +++ b/core/web/jobs_controller.go @@ -25,7 +25,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/fluxmonitorv2" "github.com/smartcontractkit/chainlink/v2/core/services/gateway" "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/keeper" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/ocr" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" @@ -240,8 +239,6 @@ func (jc *JobsController) validateJobSpec(ctx context.Context, tomlString string jb, err = directrequest.ValidatedDirectRequestSpec(tomlString) case job.FluxMonitor: jb, err = fluxmonitorv2.ValidatedFluxMonitorSpec(config.JobPipeline(), tomlString) - case job.Keeper: - jb, err = keeper.ValidatedKeeperSpec(tomlString) case job.CRESettings: jb, err = cresettings.ValidatedCRESettingsSpec(tomlString) case job.Cron: diff --git a/core/web/jobs_controller_test.go b/core/web/jobs_controller_test.go index 737b05a9607..c1192b1bfd2 100644 --- a/core/web/jobs_controller_test.go +++ b/core/web/jobs_controller_test.go @@ -198,43 +198,6 @@ func TestJobController_Create_HappyPath(t *testing.T) { require.NotEmpty(t, jb.OCROracleSpec.ContractAddress) }, }, - { - name: "keeper", - tomlTemplate: func(nameAndExternalJobID string) string { - return fmt.Sprintf(` - type = "keeper" - schemaVersion = 1 - name = "%s" - contractAddress = "0x9E40733cC9df84636505f4e6Db28DCa0dC5D1bba" - fromAddress = "0xa8037A20989AFcBC51798de9762b351D63ff462e" - evmChainID = "%s" - minIncomingConfigurations = 1 - externalJobID = "%s" - `, nameAndExternalJobID, cltest.FixtureChainID.String(), nameAndExternalJobID) - }, - assertion: func(t *testing.T, nameAndExternalJobID string, r *http.Response) { - require.Equal(t, http.StatusInternalServerError, r.StatusCode) - - errs := cltest.ParseJSONAPIErrors(t, r.Body) - require.NotNil(t, errs) - require.Len(t, errs.Errors, 1) - // services failed to start - require.Contains(t, errs.Errors[0].Detail, "no contract code at given address") - // but the job should still exist - ctx := testutils.Context(t) - jb, err := jorm.FindJobByExternalJobID(ctx, uuid.MustParse(nameAndExternalJobID)) - require.NoError(t, err) - require.NotNil(t, jb.KeeperSpec) - - require.Equal(t, types.EIP55Address("0x9E40733cC9df84636505f4e6Db28DCa0dC5D1bba"), jb.KeeperSpec.ContractAddress) - require.Equal(t, types.EIP55Address("0xa8037A20989AFcBC51798de9762b351D63ff462e"), jb.KeeperSpec.FromAddress) - assert.Equal(t, nameAndExternalJobID, jb.Name.ValueOrZero()) - - // Sanity check to make sure it inserted correctly - require.Equal(t, types.EIP55Address("0x9E40733cC9df84636505f4e6Db28DCa0dC5D1bba"), jb.KeeperSpec.ContractAddress) - require.Equal(t, types.EIP55Address("0xa8037A20989AFcBC51798de9762b351D63ff462e"), jb.KeeperSpec.FromAddress) - }, - }, { name: "cron", tomlTemplate: func(nameAndExternalJobID string) string { diff --git a/core/web/presenters/job.go b/core/web/presenters/job.go index 80ed7570e56..595507c2847 100644 --- a/core/web/presenters/job.go +++ b/core/web/presenters/job.go @@ -32,7 +32,6 @@ const ( DirectRequestJobSpec JobSpecType = "directrequest" FluxMonitorJobSpec JobSpecType = "fluxmonitor" OffChainReportingJobSpec JobSpecType = "offchainreporting" - KeeperJobSpec JobSpecType = "keeper" CronJobSpec JobSpecType = "cron" VRFJobSpec JobSpecType = "vrf" WebhookJobSpec JobSpecType = "webhook" @@ -223,26 +222,6 @@ func NewPipelineSpec(spec *pipeline.Spec) PipelineSpec { } } -// KeeperSpec defines the spec details of a Keeper Job -type KeeperSpec struct { - ContractAddress types.EIP55Address `json:"contractAddress"` - FromAddress types.EIP55Address `json:"fromAddress"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - EVMChainID *sqlutil.Big `json:"evmChainID"` -} - -// NewKeeperSpec generates a new KeeperSpec from a job.KeeperSpec -func NewKeeperSpec(spec *job.KeeperSpec) *KeeperSpec { - return &KeeperSpec{ - ContractAddress: spec.ContractAddress, - FromAddress: spec.FromAddress, - CreatedAt: spec.CreatedAt, - UpdatedAt: spec.UpdatedAt, - EVMChainID: spec.EVMChainID, - } -} - // WebhookSpec defines the spec details of a Webhook Job type WebhookSpec struct { CreatedAt time.Time `json:"createdAt"` @@ -575,7 +554,6 @@ type JobResource struct { CronSpec *CronSpec `json:"cronSpec"` OffChainReportingSpec *OffChainReportingSpec `json:"offChainReportingOracleSpec"` OffChainReporting2Spec *OffChainReporting2Spec `json:"offChainReporting2OracleSpec"` - KeeperSpec *KeeperSpec `json:"keeperSpec"` VRFSpec *VRFSpec `json:"vrfSpec"` WebhookSpec *WebhookSpec `json:"webhookSpec"` BlockhashStoreSpec *BlockhashStoreSpec `json:"blockhashStoreSpec"` @@ -619,8 +597,6 @@ func NewJobResource(j job.Job) *JobResource { resource.OffChainReportingSpec = NewOffChainReportingSpec(j.OCROracleSpec) case job.OffchainReporting2: resource.OffChainReporting2Spec = NewOffChainReporting2Spec(j.OCR2OracleSpec) - case job.Keeper: - resource.KeeperSpec = NewKeeperSpec(j.KeeperSpec) case job.VRF: resource.VRFSpec = NewVRFSpec(j.VRFSpec) case job.Webhook: diff --git a/core/web/presenters/job_test.go b/core/web/presenters/job_test.go index 01feeb13f82..2d02582c3a2 100644 --- a/core/web/presenters/job_test.go +++ b/core/web/presenters/job_test.go @@ -120,7 +120,6 @@ func TestJob(t *testing.T) { "fluxMonitorSpec": null, "gasLimit": 1000, "forwardingAllowed": false, - "keeperSpec": null, "cronSpec": null, "vrfSpec": null, "webhookSpec": null, @@ -202,7 +201,6 @@ func TestJob(t *testing.T) { "offChainReportingOracleSpec": null, "offChainReporting2OracleSpec": null, "directRequestSpec": null, - "keeperSpec": null, "cronSpec": null, "vrfSpec": null, "webhookSpec": null, @@ -294,7 +292,6 @@ func TestJob(t *testing.T) { "gasLimit": 123, "forwardingAllowed": true, "directRequestSpec": null, - "keeperSpec": null, "cronSpec": null, "vrfSpec": null, "webhookSpec": null, @@ -313,75 +310,6 @@ func TestJob(t *testing.T) { } }`, contractAddress, ocrKeyBundleID, transmitterAddress), }, - { - name: "keeper spec", - job: job.Job{ - ID: 1, - KeeperSpec: &job.KeeperSpec{ - ContractAddress: contractAddress, - FromAddress: fromAddress, - CreatedAt: timestamp, - UpdatedAt: timestamp, - EVMChainID: evmChainID, - }, - ExternalJobID: uuid.MustParse("0EEC7E1D-D0D2-476C-A1A8-72DFB6633F46"), - PipelineSpec: &pipeline.Spec{ - ID: 1, - DotDagSource: "", - }, - Type: job.Keeper, - SchemaVersion: 1, - Name: null.StringFrom("test"), - MaxTaskDuration: sqlutil.Interval(1 * time.Minute), - }, - want: fmt.Sprintf(` - { - "data":{ - "type":"jobs", - "id":"1", - "attributes":{ - "name": "test", - "schemaVersion": 1, - "type": "keeper", - "maxTaskDuration": "1m0s", - "externalJobID":"0eec7e1d-d0d2-476c-a1a8-72dfb6633f46", - "pipelineSpec": { - "id": 1, - "dotDagSource": "", - "jobID": 0 - }, - "keeperSpec": { - "contractAddress": "%s", - "fromAddress": "%s", - "createdAt":"2000-01-01T00:00:00Z", - "updatedAt":"2000-01-01T00:00:00Z", - "evmChainID": "42" - }, - "fluxMonitorSpec": null, - "gasLimit": null, - "forwardingAllowed": false, - "directRequestSpec": null, - "cronSpec": null, - "webhookSpec": null, - "workflowSpec": null, - "offChainReportingOracleSpec": null, - "offChainReporting2OracleSpec": null, - "cronSpec": null, - "vrfSpec": null, - "blockhashStoreSpec": null, - "blockHeaderFeederSpec": null, - "bootstrapSpec": null, - "gatewaySpec": null, - "standardCapabilitiesSpec": null, - "ccipSpec": null, - "creSettingsSpec": null, - "ccvCommitteeVerifierSpec": null, - "ccvExecutorSpec": null, - "errors": [] - } - } - }`, contractAddress, fromAddress), - }, { name: "cron spec", job: job.Job{ @@ -428,7 +356,6 @@ func TestJob(t *testing.T) { "gasLimit": null, "forwardingAllowed": false, "directRequestSpec": null, - "keeperSpec": null, "offChainReportingOracleSpec": null, "offChainReporting2OracleSpec": null, "vrfSpec": null, @@ -491,7 +418,6 @@ func TestJob(t *testing.T) { "gasLimit": null, "forwardingAllowed": false, "directRequestSpec": null, - "keeperSpec": null, "cronSpec": null, "offChainReportingOracleSpec": null, "offChainReporting2OracleSpec": null, @@ -558,7 +484,6 @@ func TestJob(t *testing.T) { "cronSpec": null, "offChainReportingOracleSpec": null, "offChainReporting2OracleSpec": null, - "keeperSpec": null, "vrfSpec": { "batchCoordinatorAddress": "%s", "batchFulfillmentEnabled": true, @@ -648,7 +573,6 @@ func TestJob(t *testing.T) { "cronSpec": null, "offChainReportingOracleSpec": null, "offChainReporting2OracleSpec": null, - "keeperSpec": null, "vrfSpec": null, "webhookSpec": null, "workflowSpec": null, @@ -734,7 +658,6 @@ func TestJob(t *testing.T) { "cronSpec": null, "offChainReportingOracleSpec": null, "offChainReporting2OracleSpec": null, - "keeperSpec": null, "vrfSpec": null, "webhookSpec": null, "workflowSpec": null, @@ -810,7 +733,6 @@ func TestJob(t *testing.T) { "cronSpec": null, "offChainReportingOracleSpec": null, "offChainReporting2OracleSpec": null, - "keeperSpec": null, "vrfSpec": null, "webhookSpec": null, "workflowSpec": null, @@ -880,7 +802,6 @@ func TestJob(t *testing.T) { "cronSpec": null, "offChainReportingOracleSpec": null, "offChainReporting2OracleSpec": null, - "keeperSpec": null, "vrfSpec": null, "webhookSpec": null, "workflowSpec": null, @@ -948,7 +869,6 @@ func TestJob(t *testing.T) { "cronSpec": null, "offChainReportingOracleSpec": null, "offChainReporting2OracleSpec": null, - "keeperSpec": null, "vrfSpec": null, "webhookSpec": null, "workflowSpec": { @@ -1014,7 +934,6 @@ func TestJob(t *testing.T) { "cronSpec": null, "offChainReportingOracleSpec": null, "offChainReporting2OracleSpec": null, - "keeperSpec": null, "vrfSpec": null, "webhookSpec": null, "workflowSpec": null, @@ -1080,7 +999,6 @@ func TestJob(t *testing.T) { "cronSpec": null, "offChainReportingOracleSpec": null, "offChainReporting2OracleSpec": null, - "keeperSpec": null, "vrfSpec": null, "webhookSpec": null, "workflowSpec": null, @@ -1147,7 +1065,6 @@ func TestJob(t *testing.T) { "cronSpec": null, "offChainReportingOracleSpec": null, "offChainReporting2OracleSpec": null, - "keeperSpec": null, "vrfSpec": null, "webhookSpec": null, "workflowSpec": null, @@ -1211,7 +1128,6 @@ func TestJob(t *testing.T) { "cronSpec": null, "offChainReportingOracleSpec": null, "offChainReporting2OracleSpec": null, - "keeperSpec": null, "vrfSpec": null, "webhookSpec": null, "workflowSpec": null, @@ -1281,7 +1197,6 @@ func TestJob(t *testing.T) { "cronSpec": null, "offChainReportingOracleSpec": null, "offChainReporting2OracleSpec": null, - "keeperSpec": null, "vrfSpec": null, "webhookSpec": null, "workflowSpec": null, @@ -1307,19 +1222,18 @@ func TestJob(t *testing.T) { name: "with errors", job: job.Job{ ID: 1, - KeeperSpec: &job.KeeperSpec{ - ContractAddress: contractAddress, - FromAddress: fromAddress, - CreatedAt: timestamp, - UpdatedAt: timestamp, - EVMChainID: evmChainID, + CronSpec: &job.CronSpec{ + CronSchedule: cronSchedule, + CreatedAt: timestamp, + UpdatedAt: timestamp, + EVMChainID: evmChainID, }, ExternalJobID: uuid.MustParse("0EEC7E1D-D0D2-476C-A1A8-72DFB6633F46"), PipelineSpec: &pipeline.Spec{ ID: 1, DotDagSource: "", }, - Type: job.Keeper, + Type: job.Cron, SchemaVersion: 1, Name: null.StringFrom("test"), MaxTaskDuration: sqlutil.Interval(1 * time.Minute), @@ -1342,7 +1256,7 @@ func TestJob(t *testing.T) { "attributes":{ "name": "test", "schemaVersion": 1, - "type": "keeper", + "type": "cron", "maxTaskDuration": "1m0s", "externalJobID":"0eec7e1d-d0d2-476c-a1a8-72dfb6633f46", "pipelineSpec": { @@ -1350,9 +1264,8 @@ func TestJob(t *testing.T) { "dotDagSource": "", "jobID": 0 }, - "keeperSpec": { - "contractAddress": "%s", - "fromAddress": "%s", + "cronSpec": { + "schedule": "%s", "createdAt":"2000-01-01T00:00:00Z", "updatedAt":"2000-01-01T00:00:00Z", "evmChainID": "42" @@ -1362,7 +1275,6 @@ func TestJob(t *testing.T) { "forwardingAllowed": false, "creSettingsSpec": null, "directRequestSpec": null, - "cronSpec": null, "webhookSpec": null, "workflowSpec": null, "offChainReportingOracleSpec": null, @@ -1385,7 +1297,7 @@ func TestJob(t *testing.T) { }] } } - }`, contractAddress, fromAddress), + }`, cronSchedule), }, } diff --git a/core/web/resolver/mutation.go b/core/web/resolver/mutation.go index 42631d63491..08707393c22 100644 --- a/core/web/resolver/mutation.go +++ b/core/web/resolver/mutation.go @@ -36,7 +36,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/fluxmonitorv2" "github.com/smartcontractkit/chainlink/v2/core/services/gateway" "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/keeper" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/ocr" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" @@ -1093,8 +1092,6 @@ func (r *Resolver) CreateJob(ctx context.Context, args struct { jb, err = directrequest.ValidatedDirectRequestSpec(args.Input.TOML) case job.FluxMonitor: jb, err = fluxmonitorv2.ValidatedFluxMonitorSpec(config.JobPipeline(), args.Input.TOML) - case job.Keeper: - jb, err = keeper.ValidatedKeeperSpec(args.Input.TOML) case job.CRESettings: jb, err = cresettings.ValidatedCRESettingsSpec(args.Input.TOML) case job.Cron: diff --git a/core/web/resolver/spec.go b/core/web/resolver/spec.go index 139ea78e395..ad84e88a1ab 100644 --- a/core/web/resolver/spec.go +++ b/core/web/resolver/spec.go @@ -42,14 +42,6 @@ func (r *SpecResolver) ToFluxMonitorSpec() (*FluxMonitorSpecResolver, bool) { return &FluxMonitorSpecResolver{spec: *r.j.FluxMonitorSpec}, true } -func (r *SpecResolver) ToKeeperSpec() (*KeeperSpecResolver, bool) { - if r.j.Type != job.Keeper { - return nil, false - } - - return &KeeperSpecResolver{spec: *r.j.KeeperSpec}, true -} - func (r *SpecResolver) ToOCRSpec() (*OCRSpecResolver, bool) { if r.j.Type != job.OffchainReporting { return nil, false @@ -344,44 +336,6 @@ func (r *FluxMonitorSpecResolver) Threshold() float64 { return float64(r.spec.Threshold) } -type KeeperSpecResolver struct { - spec job.KeeperSpec -} - -// ContractAddress resolves the spec's contract address. -func (r *KeeperSpecResolver) ContractAddress() string { - return r.spec.ContractAddress.String() -} - -// CreatedAt resolves the spec's created at timestamp. -func (r *KeeperSpecResolver) CreatedAt() graphql.Time { - return graphql.Time{Time: r.spec.CreatedAt} -} - -// EVMChainID resolves the spec's evm chain id. -func (r *KeeperSpecResolver) EVMChainID() *string { - if r.spec.EVMChainID == nil { - return nil - } - - chainID := r.spec.EVMChainID.String() - - return &chainID -} - -// FromAddress resolves the spec's from contract address. -// -// Because VRF has an non required field of the same name, we have to be -// consistent in our return value of using a *string instead of a string even -// though this is a required field for the KeeperSpec. -// -// http://spec.graphql.org/draft/#sec-Field-Selection-Merging -func (r *KeeperSpecResolver) FromAddress() *string { - addr := r.spec.FromAddress.String() - - return &addr -} - type OCRSpecResolver struct { spec job.OCROracleSpec } diff --git a/core/web/resolver/spec_test.go b/core/web/resolver/spec_test.go index 6e11c209a7c..cc85daf95a6 100644 --- a/core/web/resolver/spec_test.go +++ b/core/web/resolver/spec_test.go @@ -298,66 +298,6 @@ func TestResolver_FluxMonitorSpec(t *testing.T) { RunGQLTests(t, testCases) } -func TestResolver_KeeperSpec(t *testing.T) { - var ( - id = int32(1) - fromAddress = common.HexToAddress("0x3cCad4715152693fE3BC4460591e3D3Fbd071b42") - ) - contractAddress, err := evmtypes.NewEIP55Address("0x613a38AC1659769640aaE063C651F48E0250454C") - require.NoError(t, err) - - testCases := []GQLTestCase{ - { - name: "keeper spec", - authenticated: true, - before: func(ctx context.Context, f *gqlTestFramework) { - f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ - Type: job.Keeper, - KeeperSpec: &job.KeeperSpec{ - ContractAddress: contractAddress, - CreatedAt: f.Timestamp(), - EVMChainID: sqlutil.NewI(42), - FromAddress: evmtypes.EIP55AddressFromAddress(fromAddress), - }, - }, nil) - }, - query: ` - query GetJob { - job(id: "1") { - ... on Job { - spec { - __typename - ... on KeeperSpec { - contractAddress - createdAt - evmChainID - fromAddress - } - } - } - } - } - `, - result: ` - { - "job": { - "spec": { - "__typename": "KeeperSpec", - "contractAddress": "0x613a38AC1659769640aaE063C651F48E0250454C", - "createdAt": "2021-01-01T00:00:00Z", - "evmChainID": "42", - "fromAddress": "0x3cCad4715152693fE3BC4460591e3D3Fbd071b42" - } - } - } - `, - }, - } - - RunGQLTests(t, testCases) -} - func TestResolver_OCRSpec(t *testing.T) { var ( id = int32(1) diff --git a/core/web/resolver/testdata/config-empty-effective.toml b/core/web/resolver/testdata/config-empty-effective.toml index bd00ab34ccb..a073a30ed45 100644 --- a/core/web/resolver/testdata/config-empty-effective.toml +++ b/core/web/resolver/testdata/config-empty-effective.toml @@ -193,21 +193,6 @@ DeltaDial = '15s' DeltaReconcile = '1m0s' ListenAddresses = [] -[Keeper] -DefaultTransactionQueueDepth = 1 -GasPriceBufferPercent = 20 -GasTipCapBufferPercent = 20 -BaseFeeBufferPercent = 20 -MaxGracePeriod = 100 -TurnLookBack = 1000 - -[Keeper.Registry] -CheckGasOverhead = 200000 -PerformGasOverhead = 300000 -MaxPerformDataSize = 5000 -SyncInterval = '30m0s' -SyncUpkeepQueueSize = 10 - [AutoPprof] Enabled = false ProfileRoot = '' diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml index e939e064563..9fa49112c07 100644 --- a/core/web/resolver/testdata/config-full.toml +++ b/core/web/resolver/testdata/config-full.toml @@ -199,21 +199,6 @@ DeltaDial = '1m0s' DeltaReconcile = '1s' ListenAddresses = ['foo', 'bar'] -[Keeper] -DefaultTransactionQueueDepth = 17 -GasPriceBufferPercent = 12 -GasTipCapBufferPercent = 43 -BaseFeeBufferPercent = 89 -MaxGracePeriod = 31 -TurnLookBack = 91 - -[Keeper.Registry] -CheckGasOverhead = 90 -PerformGasOverhead = 4294967295 -MaxPerformDataSize = 5000 -SyncInterval = '1h0m0s' -SyncUpkeepQueueSize = 31 - [AutoPprof] Enabled = true ProfileRoot = 'prof/root' @@ -594,77 +579,3 @@ HTTPURL = 'https://bar.com' Name = 'broadcast' HTTPURL = 'http://broadcast.mirror' SendOnly = true - -[[Solana]] -ChainID = 'mainnet' -Enabled = true -BlockTime = '500ms' -BalancePollPeriod = '1m0s' -ConfirmPollPeriod = '1s' -OCR2CachePollPeriod = '1m0s' -OCR2CacheTTL = '1h0m0s' -TxTimeout = '1h0m0s' -TxRetryTimeout = '1m0s' -TxConfirmTimeout = '1s' -TxExpirationRebroadcast = false -TxRetentionTimeout = '0s' -SkipPreflight = true -Commitment = 'banana' -MaxRetries = 7 -FeeEstimatorMode = 'fixed' -ComputeUnitPriceMax = 1000000 -ComputeUnitPriceMin = 0 -ComputeUnitPriceDefault = 0 -FeeBumpPeriod = '3s' -BlockHistoryPollPeriod = '5s' -BlockHistorySize = 1 -BlockHistoryBatchLoadSize = 20 -ComputeUnitLimitDefault = 200000 -EstimateComputeUnitLimit = false -LogPollerStartingLookback = '24h0m0s' -LogPollerCPIEventsEnabled = true -LogPollerSlotsBatchSize = 100 - -[Solana.Workflow] -AcceptanceTimeout = '45s' -ForwarderAddress = '14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5' -ForwarderState = '14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5' -FromAddress = '4BJXYkfvg37zEmBbsacZjeQDpTNx91KppxFJxRqrz48e' -GasLimitDefault = 0 -Local = true -PollPeriod = '3s' -TxAcceptanceState = 3 - -[Solana.MultiNode] -Enabled = false -PollFailureThreshold = 5 -PollInterval = '1s' -SelectionMode = 'HighestHead' -SyncThreshold = 5 -NodeIsSyncingEnabled = false -LeaseDuration = '1m0s' -NewHeadsPollInterval = '5s' -FinalizedBlockPollInterval = '1s' -EnforceRepeatableRead = true -DeathDeclarationDelay = '1m0s' -VerifyChainID = true -NodeNoNewHeadsThreshold = '1m0s' -NoNewFinalizedHeadsThreshold = '1m0s' -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 - -[[Solana.Nodes]] -Name = 'primary' -URL = 'http://solana.web' -SendOnly = false - -[[Solana.Nodes]] -Name = 'foo' -URL = 'http://solana.foo' -SendOnly = false - -[[Solana.Nodes]] -Name = 'bar' -URL = 'http://solana.bar' -SendOnly = false diff --git a/core/web/resolver/testdata/config-multi-chain-effective.toml b/core/web/resolver/testdata/config-multi-chain-effective.toml index 9c6c9b42cda..afe76d5ec60 100644 --- a/core/web/resolver/testdata/config-multi-chain-effective.toml +++ b/core/web/resolver/testdata/config-multi-chain-effective.toml @@ -193,21 +193,6 @@ DeltaDial = '15s' DeltaReconcile = '1m0s' ListenAddresses = [] -[Keeper] -DefaultTransactionQueueDepth = 1 -GasPriceBufferPercent = 10 -GasTipCapBufferPercent = 20 -BaseFeeBufferPercent = 20 -MaxGracePeriod = 100 -TurnLookBack = 1000 - -[Keeper.Registry] -CheckGasOverhead = 200000 -PerformGasOverhead = 300000 -MaxPerformDataSize = 5000 -SyncInterval = '30m0s' -SyncUpkeepQueueSize = 10 - [AutoPprof] Enabled = false ProfileRoot = '' @@ -774,131 +759,3 @@ AcceptanceTimeout = '30s' [[EVM.Nodes]] Name = 'bar' WSURL = 'wss://web.socket/test/bar' - -[[Solana]] -ChainID = 'mainnet' -Enabled = true -BlockTime = '500ms' -BalancePollPeriod = '5s' -ConfirmPollPeriod = '500ms' -OCR2CachePollPeriod = '1s' -OCR2CacheTTL = '1m0s' -TxTimeout = '1m0s' -TxRetryTimeout = '10s' -TxConfirmTimeout = '30s' -TxExpirationRebroadcast = false -TxRetentionTimeout = '0s' -SkipPreflight = true -Commitment = 'confirmed' -MaxRetries = 12 -FeeEstimatorMode = 'fixed' -ComputeUnitPriceMax = 1000 -ComputeUnitPriceMin = 0 -ComputeUnitPriceDefault = 0 -FeeBumpPeriod = '3s' -BlockHistoryPollPeriod = '5s' -BlockHistorySize = 1 -BlockHistoryBatchLoadSize = 20 -ComputeUnitLimitDefault = 200000 -EstimateComputeUnitLimit = false -LogPollerStartingLookback = '24h0m0s' -LogPollerCPIEventsEnabled = true -LogPollerSlotsBatchSize = 1000 - -[Solana.Workflow] -AcceptanceTimeout = '45s' -ForwarderAddress = '11111111111111111111111111111111' -ForwarderState = '11111111111111111111111111111111' -FromAddress = '11111111111111111111111111111111' -GasLimitDefault = 300000 -Local = false -PollPeriod = '3s' -TxAcceptanceState = 3 - -[Solana.MultiNode] -Enabled = false -PollFailureThreshold = 5 -PollInterval = '1s' -SelectionMode = 'HighestHead' -SyncThreshold = 5 -NodeIsSyncingEnabled = false -LeaseDuration = '1m0s' -NewHeadsPollInterval = '5s' -FinalizedBlockPollInterval = '1s' -EnforceRepeatableRead = true -DeathDeclarationDelay = '1m0s' -VerifyChainID = true -NodeNoNewHeadsThreshold = '1m0s' -NoNewFinalizedHeadsThreshold = '1m0s' -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 - -[[Solana.Nodes]] -Name = 'primary' -URL = 'http://mainnet.solana.com' -SendOnly = false - -[[Solana]] -ChainID = 'testnet' -Enabled = true -BlockTime = '500ms' -BalancePollPeriod = '5s' -ConfirmPollPeriod = '500ms' -OCR2CachePollPeriod = '1m0s' -OCR2CacheTTL = '1m0s' -TxTimeout = '1m0s' -TxRetryTimeout = '10s' -TxConfirmTimeout = '30s' -TxExpirationRebroadcast = false -TxRetentionTimeout = '0s' -SkipPreflight = true -Commitment = 'confirmed' -MaxRetries = 0 -FeeEstimatorMode = 'fixed' -ComputeUnitPriceMax = 1000 -ComputeUnitPriceMin = 0 -ComputeUnitPriceDefault = 0 -FeeBumpPeriod = '3s' -BlockHistoryPollPeriod = '5s' -BlockHistorySize = 1 -BlockHistoryBatchLoadSize = 20 -ComputeUnitLimitDefault = 200000 -EstimateComputeUnitLimit = false -LogPollerStartingLookback = '24h0m0s' -LogPollerCPIEventsEnabled = true -LogPollerSlotsBatchSize = 2000 - -[Solana.Workflow] -AcceptanceTimeout = '45s' -ForwarderAddress = '11111111111111111111111111111111' -ForwarderState = '11111111111111111111111111111111' -FromAddress = '11111111111111111111111111111111' -GasLimitDefault = 300000 -Local = false -PollPeriod = '3s' -TxAcceptanceState = 3 - -[Solana.MultiNode] -Enabled = false -PollFailureThreshold = 5 -PollInterval = '1s' -SelectionMode = 'HighestHead' -SyncThreshold = 5 -NodeIsSyncingEnabled = false -LeaseDuration = '1m0s' -NewHeadsPollInterval = '5s' -FinalizedBlockPollInterval = '1s' -EnforceRepeatableRead = true -DeathDeclarationDelay = '1m0s' -VerifyChainID = true -NodeNoNewHeadsThreshold = '1m0s' -NoNewFinalizedHeadsThreshold = '1m0s' -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 - -[[Solana.Nodes]] -Name = 'secondary' -URL = 'http://testnet.solana.com' -SendOnly = false diff --git a/core/web/resolver/testdata/config-multi-chain.toml b/core/web/resolver/testdata/config-multi-chain.toml index 4bb46de4ccb..14047e85a66 100644 --- a/core/web/resolver/testdata/config-multi-chain.toml +++ b/core/web/resolver/testdata/config-multi-chain.toml @@ -32,9 +32,6 @@ BlockchainTimeout = '5s' [P2P] IncomingMessageBufferSize = 999 -[Keeper] -GasPriceBufferPercent = 10 - [AutoPprof] CPUProfileRate = 7 @@ -82,58 +79,3 @@ Mode = 'FixedPrice' [[EVM.Nodes]] Name = 'bar' WSURL = 'wss://web.socket/test/bar' - -[[Solana]] -ChainID = 'mainnet' -MaxRetries = 12 - -[Solana.MultiNode] -Enabled = false -PollFailureThreshold = 5 -PollInterval = '1s' -SelectionMode = 'HighestHead' -SyncThreshold = 5 -NodeIsSyncingEnabled = false -LeaseDuration = '1m0s' -FinalizedBlockPollInterval = '1s' -EnforceRepeatableRead = true -DeathDeclarationDelay = '1m0s' -VerifyChainID = true -NodeNoNewHeadsThreshold = '1m0s' -NoNewFinalizedHeadsThreshold = '1m0s' -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 - -[[Solana.Nodes]] -Name = 'primary' -URL = 'http://mainnet.solana.com' -SendOnly = false - -[[Solana]] -ChainID = 'testnet' -OCR2CachePollPeriod = '1m0s' -LogPollerSlotsBatchSize = 2000 - -[Solana.MultiNode] -Enabled = false -PollFailureThreshold = 5 -PollInterval = '1s' -SelectionMode = 'HighestHead' -SyncThreshold = 5 -NodeIsSyncingEnabled = false -LeaseDuration = '1m0s' -FinalizedBlockPollInterval = '1s' -EnforceRepeatableRead = true -DeathDeclarationDelay = '1m0s' -VerifyChainID = true -NodeNoNewHeadsThreshold = '1m0s' -NoNewFinalizedHeadsThreshold = '1m0s' -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 - -[[Solana.Nodes]] -Name = 'secondary' -URL = 'http://testnet.solana.com' -SendOnly = false diff --git a/core/web/schema/type/spec.graphql b/core/web/schema/type/spec.graphql index dc042537baa..5a54afd93f4 100644 --- a/core/web/schema/type/spec.graphql +++ b/core/web/schema/type/spec.graphql @@ -1,7 +1,6 @@ union JobSpec = CronSpec | DirectRequestSpec | - KeeperSpec | FluxMonitorSpec | OCRSpec | OCR2Spec | @@ -49,13 +48,6 @@ type FluxMonitorSpec { threshold: Float! } -type KeeperSpec { - contractAddress: String! - createdAt: Time! - evmChainID: String - fromAddress: String -} - type OCRSpec { blockchainTimeout: String contractAddress: String! diff --git a/core/web/testdata/body/health.html b/core/web/testdata/body/health.html index cf189621cf5..851f5e6902f 100644 --- a/core/web/testdata/body/health.html +++ b/core/web/testdata/body/health.html @@ -126,24 +126,6 @@
RetirementReportCache
-
- Solana -
- Bar -
- Chain -
- BalanceMonitor -
-
- Txm -
-
-
- Relayer -
-
-
TelemetryManager
diff --git a/core/web/testdata/body/health.json b/core/web/testdata/body/health.json index 31054ef17e7..5f6fae19e30 100644 --- a/core/web/testdata/body/health.json +++ b/core/web/testdata/body/health.json @@ -252,42 +252,6 @@ "output": "" } }, - { - "type": "checks", - "id": "Solana.Bar.Chain", - "attributes": { - "name": "Solana.Bar.Chain", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "Solana.Bar.Chain.BalanceMonitor", - "attributes": { - "name": "Solana.Bar.Chain.BalanceMonitor", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "Solana.Bar.Chain.Txm", - "attributes": { - "name": "Solana.Bar.Chain.Txm", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "Solana.Bar.Relayer", - "attributes": { - "name": "Solana.Bar.Relayer", - "status": "passing", - "output": "" - } - }, { "type": "checks", "id": "TelemetryManager", diff --git a/core/web/testdata/body/health.txt b/core/web/testdata/body/health.txt index 59a77f4a057..1070a89f475 100644 --- a/core/web/testdata/body/health.txt +++ b/core/web/testdata/body/health.txt @@ -27,9 +27,5 @@ ok PipelineORM ok PipelineRunner ok PipelineRunner.BridgeCache ok RetirementReportCache -ok Solana.Bar.Chain -ok Solana.Bar.Chain.BalanceMonitor -ok Solana.Bar.Chain.Txm -ok Solana.Bar.Relayer ok TelemetryManager ok WorkflowStore diff --git a/deployment/cre/jobs/pkg/addresses.go b/deployment/cre/jobs/pkg/addresses.go index 087289cee3f..82fd9f531dc 100644 --- a/deployment/cre/jobs/pkg/addresses.go +++ b/deployment/cre/jobs/pkg/addresses.go @@ -4,6 +4,7 @@ import ( "github.com/Masterminds/semver/v3" "github.com/smartcontractkit/chainlink-deployments-framework/datastore" + "github.com/smartcontractkit/chainlink/deployment/cre/forwarder/solana" ) func GetOCR3CapabilityAddressRefKey(chainSel uint64, qualifier string) datastore.AddressRefKey { @@ -24,6 +25,20 @@ func GetKeystoneForwarderCapabilityAddressRefKey(chainSel uint64, qualifier stri ) } +// Solana CRE forwarder entries match cre/forwarder/solana.DeployForwarder (program + state). +const ( + SolanaForwarderProgramType datastore.ContractType = solana.ForwarderContract + SolanaForwarderStateType datastore.ContractType = solana.ForwarderState +) + +func GetSolanaForwarderProgramRefKey(chainSel uint64, version *semver.Version, qualifier string) datastore.AddressRefKey { + return datastore.NewAddressRefKey(chainSel, SolanaForwarderProgramType, version, qualifier) +} + +func GetSolanaForwarderStateRefKey(chainSel uint64, version *semver.Version, qualifier string) datastore.AddressRefKey { + return datastore.NewAddressRefKey(chainSel, SolanaForwarderStateType, version, qualifier) +} + func GetCapRegAddressRefKey(chainSel uint64, qualifier string, version string) datastore.AddressRefKey { return datastore.NewAddressRefKey( chainSel, diff --git a/deployment/cre/jobs/propose_chain_cap_helpers.go b/deployment/cre/jobs/propose_chain_cap_helpers.go index d16c779b028..2f96c520f21 100644 --- a/deployment/cre/jobs/propose_chain_cap_helpers.go +++ b/deployment/cre/jobs/propose_chain_cap_helpers.go @@ -5,6 +5,8 @@ import ( "fmt" "time" + "github.com/Masterminds/semver/v3" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink-deployments-framework/operations" operations2 "github.com/smartcontractkit/chainlink/deployment/cre/jobs/operations" @@ -85,6 +87,35 @@ func resolveContractAddresses( return resolvedAddresses{ForwarderAddress: fwdAddress.Address}, nil } +// resolveSolanaForwarderAddresses loads the Solana CRE forwarder program id and state account +// from the datastore (same refs as cre/forwarder/solana deploy). versionStr defaults to "1.0.0" when empty. +func resolveSolanaForwarderAddresses(e cldf.Environment, chainSelector uint64, qualifier, versionStr string) (programAddr, stateAddr string, err error) { + if qualifier == "" { + return "", "", errors.New("cre forwarder qualifier is required") + } + if versionStr == "" { + versionStr = "1.0.0" + } + v, err := semver.NewVersion(versionStr) + if err != nil { + return "", "", fmt.Errorf("invalid forwarder version %q: %w", versionStr, err) + } + + progRef := pkg.GetSolanaForwarderProgramRefKey(chainSelector, v, qualifier) + prog, err := e.DataStore.Addresses().Get(progRef) + if err != nil { + return "", "", fmt.Errorf("failed to get Solana forwarder program for ref key %s: %w", progRef, err) + } + + stateRef := pkg.GetSolanaForwarderStateRefKey(chainSelector, v, qualifier) + state, err := e.DataStore.Addresses().Get(stateRef) + if err != nil { + return "", "", fmt.Errorf("failed to get Solana forwarder state for ref key %s: %w", stateRef, err) + } + + return prog.Address, state.Address, nil +} + func validateOverrideNetwork(got, expected, nodeID string) error { if got != "" && got != expected { return fmt.Errorf("network in override config must be %q if set; got %q for node %s", expected, got, nodeID) diff --git a/deployment/cre/jobs/propose_solana_job.go b/deployment/cre/jobs/propose_solana_job.go new file mode 100644 index 00000000000..7bf0502ddf5 --- /dev/null +++ b/deployment/cre/jobs/propose_solana_job.go @@ -0,0 +1,230 @@ +package jobs + +import ( + "encoding/json" + "errors" + "fmt" + "strings" + "time" + + chainselectors "github.com/smartcontractkit/chain-selectors" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/cre/jobs/pkg" +) + +var _ cldf.ChangeSetV2[ProposeSolanaJobSpecInput] = ProposeSolanaJobSpec{} + +const solanaNetwork = "solana" + +// SolanaOverrideDefaultCfg holds optional per-node overrides for the Solana chain capability JSON config. +// JSON field names match capabilities/chain_capabilities/solana/config.Config. +type SolanaOverrideDefaultCfg struct { + CREForwarderAddress string `json:"creForwarderAddress,omitempty" yaml:"creForwarderAddress,omitempty"` + CREForwarderState string `json:"creForwarderState,omitempty" yaml:"creForwarderState,omitempty"` + Transmitter string `json:"transmitter,omitempty" yaml:"transmitter,omitempty"` + IsLocal bool `json:"isLocal,omitempty" yaml:"isLocal,omitempty"` + Network string `json:"network,omitempty" yaml:"network,omitempty"` + ChainID string `json:"chainId,omitempty" yaml:"chainId,omitempty"` + DeltaStage time.Duration `json:"deltaStage,omitempty" yaml:"deltaStage,omitempty"` +} + +// SolanaCapabilityInput configures one worker node. Transmitter may be omitted when the job +// distributor already lists an OCR2 chain config for chainSelector (same idea as EVM nodeAddress). +type SolanaCapabilityInput struct { + NodeID string `json:"nodeID" yaml:"nodeID"` + Transmitter string `json:"transmitter,omitempty" yaml:"transmitter,omitempty"` + OverrideDefaultCfg SolanaOverrideDefaultCfg `json:"overrideDefaultCfg" yaml:"overrideDefaultCfg"` +} + +type ProposeSolanaJobSpecInput struct { + Environment string `json:"environment" yaml:"environment"` + Zone string `json:"zone" yaml:"zone"` + Domain string `json:"domain" yaml:"domain"` + DONName string `json:"donName" yaml:"donName"` + + ChainSelector uint64 `json:"chainSelector" yaml:"chainSelector"` + DeltaStage time.Duration `json:"deltaStage" yaml:"deltaStage,omitempty"` + + // ForwardersQualifier selects Solana forwarder program + state in the datastore (SolanaForwarder / SolanaForwarderState). + ForwardersQualifier string `json:"forwardersContractQualifier" yaml:"forwardersContractQualifier"` + // ForwarderVersion is the semver of the deployed forwarder (e.g. from solana_forwarders_deploy). Defaults to 1.0.0 when empty. + ForwarderVersion string `json:"forwarderVersion,omitempty" yaml:"forwarderVersion,omitempty"` + + SolanaCapabilityInputs []SolanaCapabilityInput `json:"solanaCapabilityInputs" yaml:"solanaCapabilityInputs"` +} + +type ProposeSolanaJobSpec struct{} + +// resolveSolanaTransmitter returns overrideDefaultCfg.transmitter if set, else top-level transmitter, +// else the node's transmit account for this chain from the job distributor (same pattern as EVM nodeAddress). +func resolveSolanaTransmitter(e cldf.Environment, nodeID string, chainSelector uint64, inputLevel, override string) (string, error) { + if s := strings.TrimSpace(override); s != "" { + return s, nil + } + if s := strings.TrimSpace(inputLevel); s != "" { + return s, nil + } + if e.Offchain == nil { + return "", errors.New("offchain client is required to resolve Solana transmitter from the job distributor (set transmitter / overrideDefaultCfg.transmitter or configure the Solana chain on the node in JD)") + } + nodeInfos, err := deployment.NodeInfo([]string{nodeID}, e.Offchain) + if err != nil { + return "", fmt.Errorf("failed to get node info for node %s: %w", nodeID, err) + } + if len(nodeInfos) == 0 { + return "", fmt.Errorf("no node info for node %s", nodeID) + } + solOCR, ok := nodeInfos[0].OCRConfigForChainSelector(chainSelector) + if !ok { + return "", fmt.Errorf("no OCR2 chain config for Solana (chain selector %d) for node %s in job distributor; set transmitter in YAML or register this Solana chain on the node", chainSelector, nodeID) + } + tx := strings.TrimSpace(string(solOCR.TransmitAccount)) + if tx == "" { + return "", fmt.Errorf("empty transmit account for node %s and chain selector %d in job distributor", nodeID, chainSelector) + } + return tx, nil +} + +func validateSolanaJobCommonFields(environment, domain, zone, donName string, chainSelector uint64, deltaStage time.Duration) error { + if environment == "" { + return errors.New("environment is required") + } + if domain == "" { + return errors.New("domain is required") + } + if zone == "" { + return errors.New("zone is required") + } + if donName == "" { + return errors.New("donName is required") + } + if chainSelector == 0 { + return errors.New("chain selector is required") + } + if deltaStage <= 0 { + return fmt.Errorf("deltaStage (%s) must be greater than 0", deltaStage) + } + return nil +} + +func (u ProposeSolanaJobSpec) VerifyPreconditions(e cldf.Environment, input ProposeSolanaJobSpecInput) error { + if len(input.SolanaCapabilityInputs) == 0 { + return errors.New("at least one solana capability input is required") + } + for i, solIn := range input.SolanaCapabilityInputs { + if solIn.NodeID == "" { + return fmt.Errorf("nodeID is required for solana capability input at index %d", i) + } + if _, err := resolveSolanaTransmitter(e, solIn.NodeID, input.ChainSelector, solIn.Transmitter, solIn.OverrideDefaultCfg.Transmitter); err != nil { + return fmt.Errorf("solana capability input at index %d: %w", i, err) + } + } + + if err := validateSolanaJobCommonFields(input.Environment, input.Domain, input.Zone, input.DONName, input.ChainSelector, input.DeltaStage); err != nil { + return err + } + if input.ForwardersQualifier == "" { + return errors.New("cre forwarder qualifier is required") + } + + family, err := chainselectors.GetSelectorFamily(input.ChainSelector) + if err != nil { + return fmt.Errorf("failed to get family for chain selector %d: %w", input.ChainSelector, err) + } + if family != chainselectors.FamilySolana { + return fmt.Errorf("chain selector %d belongs to family %q, expected %q", input.ChainSelector, family, chainselectors.FamilySolana) + } + + programAddr, stateAddr, err := resolveSolanaForwarderAddresses(e, input.ChainSelector, input.ForwardersQualifier, input.ForwarderVersion) + if err != nil { + return err + } + + chainIDStr, err := chainselectors.GetChainIDFromSelector(input.ChainSelector) + if err != nil { + return fmt.Errorf("failed to get chainID from selector: %w", err) + } + + for _, solIn := range input.SolanaCapabilityInputs { + ov := solIn.OverrideDefaultCfg + if ov.ChainID != "" && ov.ChainID != chainIDStr { + return fmt.Errorf( + "chainID in override config (%s) does not match chainID from chain selector (%s) for node %s; "+ + "this field is auto-populated and can be omitted", + ov.ChainID, chainIDStr, solIn.NodeID, + ) + } + if err := validateOverrideNetwork(ov.Network, solanaNetwork, solIn.NodeID); err != nil { + return err + } + if err := validateOverrideForwarder(ov.CREForwarderAddress, programAddr, solIn.NodeID); err != nil { + return err + } + if err := validateOverrideForwarder(ov.CREForwarderState, stateAddr, solIn.NodeID); err != nil { + return err + } + } + + return nil +} + +func (u ProposeSolanaJobSpec) Apply(e cldf.Environment, input ProposeSolanaJobSpecInput) (cldf.ChangesetOutput, error) { + chainName, err := chainselectors.GetChainNameFromSelector(input.ChainSelector) + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to get chain name from selector: %w", err) + } + + chainIDStr, err := chainselectors.GetChainIDFromSelector(input.ChainSelector) + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to get chain ID from selector: %w", err) + } + + programAddr, stateAddr, err := resolveSolanaForwarderAddresses(e, input.ChainSelector, input.ForwardersQualifier, input.ForwarderVersion) + if err != nil { + return cldf.ChangesetOutput{}, err + } + + jobName := fmt.Sprintf("solana-cap-v2-%s-%s", chainName, input.Zone) + job := pkg.StandardCapabilityJob{ + JobName: jobName, + Command: "/usr/local/bin/solana", + GenerateOracleFactory: false, + } + + nodeIDToConfig := make(map[string]string, len(input.SolanaCapabilityInputs)) + for _, solIn := range input.SolanaCapabilityInputs { + if _, exists := nodeIDToConfig[solIn.NodeID]; exists { + return cldf.ChangesetOutput{}, fmt.Errorf("duplicate nodeID %q in solanaCapabilityInputs", solIn.NodeID) + } + + cfg := solIn.OverrideDefaultCfg + if cfg.CREForwarderAddress == "" { + cfg.CREForwarderAddress = programAddr + } + if cfg.CREForwarderState == "" { + cfg.CREForwarderState = stateAddr + } + tx, err := resolveSolanaTransmitter(e, solIn.NodeID, input.ChainSelector, solIn.Transmitter, solIn.OverrideDefaultCfg.Transmitter) + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("node %s: %w", solIn.NodeID, err) + } + cfg.Transmitter = tx + cfg.ChainID = chainIDStr + cfg.Network = solanaNetwork + cfg.DeltaStage = input.DeltaStage + if solIn.OverrideDefaultCfg.DeltaStage != 0 { + cfg.DeltaStage = solIn.OverrideDefaultCfg.DeltaStage + } + + enc, err := json.Marshal(cfg) + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to marshal solana cap config: %w", err) + } + + nodeIDToConfig[solIn.NodeID] = string(enc) + } + + return proposeAndReport(e, job, nodeIDToConfig, input.Domain, input.DONName, input.Zone) +} diff --git a/deployment/cre/jobs/propose_solana_job_test.go b/deployment/cre/jobs/propose_solana_job_test.go new file mode 100644 index 00000000000..16e0fd416a7 --- /dev/null +++ b/deployment/cre/jobs/propose_solana_job_test.go @@ -0,0 +1,269 @@ +package jobs_test + +import ( + "strings" + "testing" + "time" + + "github.com/Masterminds/semver/v3" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/deployment/cre/jobs" + jobspkg "github.com/smartcontractkit/chainlink/deployment/cre/jobs/pkg" + "github.com/smartcontractkit/chainlink/deployment/cre/test" + tenv "github.com/smartcontractkit/chainlink/deployment/environment/test" + + chainsel "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/chainlink-deployments-framework/datastore" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + csav1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/csa" + jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" + "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" +) + +const ( + testSolSolanaFwdQualifier = "test-solana-fwd-qualifier" + testSolanaForwarderProgram = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" + testSolanaForwarderState = "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB" + testSolanaTransmitter = "So11111111111111111111111111111111111111112" + testSolanaForwarderVersion = "1.0.0" +) + +func seedSolanaForwarderAddresses(t *testing.T, ds *datastore.MemoryDataStore, chainSel uint64, qualifier, programAddr, stateAddr string) { + t.Helper() + v := semver.MustParse(testSolanaForwarderVersion) + require.NoError(t, ds.Addresses().Add(datastore.AddressRef{ + ChainSelector: chainSel, + Type: jobspkg.SolanaForwarderProgramType, + Version: v, + Qualifier: qualifier, + Address: programAddr, + })) + require.NoError(t, ds.Addresses().Add(datastore.AddressRef{ + ChainSelector: chainSel, + Type: jobspkg.SolanaForwarderStateType, + Version: v, + Qualifier: qualifier, + Address: stateAddr, + })) +} + +func solanaCapInput(nodeID, transmitter string) jobs.SolanaCapabilityInput { + return jobs.SolanaCapabilityInput{ + NodeID: nodeID, + Transmitter: transmitter, + OverrideDefaultCfg: jobs.SolanaOverrideDefaultCfg{}, + } +} + +func freshSolanaBase(solSel uint64) jobs.ProposeSolanaJobSpecInput { + return jobs.ProposeSolanaJobSpecInput{ + Environment: "test", + Zone: test.Zone, + Domain: "cre", + DONName: test.DONName, + ChainSelector: solSel, + DeltaStage: 10 * time.Second, + ForwardersQualifier: testSolSolanaFwdQualifier, + ForwarderVersion: testSolanaForwarderVersion, + SolanaCapabilityInputs: []jobs.SolanaCapabilityInput{ + solanaCapInput("peer-1", testSolanaTransmitter), + }, + } +} + +func deepCloneSolanaInput(in jobs.ProposeSolanaJobSpecInput) jobs.ProposeSolanaJobSpecInput { + clone := in + if len(in.SolanaCapabilityInputs) > 0 { + clone.SolanaCapabilityInputs = append([]jobs.SolanaCapabilityInput(nil), in.SolanaCapabilityInputs...) + } + return clone +} + +func TestProposeSolanaJobSpec_VerifyPreconditions_success(t *testing.T) { + solSel := chainsel.SOLANA_DEVNET.Selector + ds := datastore.NewMemoryDataStore() + seedSolanaForwarderAddresses(t, ds, solSel, testSolSolanaFwdQualifier, testSolanaForwarderProgram, testSolanaForwarderState) + env := cldf.Environment{DataStore: ds.Seal()} + + in := freshSolanaBase(solSel) + in.SolanaCapabilityInputs = []jobs.SolanaCapabilityInput{ + solanaCapInput("peer-1", testSolanaTransmitter), + solanaCapInput("peer-2", testSolanaTransmitter), + } + + err := jobs.ProposeSolanaJobSpec{}.VerifyPreconditions(env, in) + require.NoError(t, err) +} + +func TestProposeSolanaJobSpec_VerifyPreconditions_requiredFields(t *testing.T) { + solSel := chainsel.SOLANA_DEVNET.Selector + ds := datastore.NewMemoryDataStore() + seedSolanaForwarderAddresses(t, ds, solSel, testSolSolanaFwdQualifier, testSolanaForwarderProgram, testSolanaForwarderState) + env := cldf.Environment{DataStore: ds.Seal()} + base := freshSolanaBase(solSel) + + cases := []struct { + name string + mutate func(*jobs.ProposeSolanaJobSpecInput) + errFrag string + }{ + {"missing environment", func(in *jobs.ProposeSolanaJobSpecInput) { in.Environment = "" }, "environment is required"}, + {"missing domain", func(in *jobs.ProposeSolanaJobSpecInput) { in.Domain = "" }, "domain is required"}, + {"missing zone", func(in *jobs.ProposeSolanaJobSpecInput) { in.Zone = "" }, "zone is required"}, + {"missing don name", func(in *jobs.ProposeSolanaJobSpecInput) { in.DONName = "" }, "donName is required"}, + {"missing chain selector", func(in *jobs.ProposeSolanaJobSpecInput) { in.ChainSelector = 0 }, "chain selector is required"}, + {"missing solana inputs", func(in *jobs.ProposeSolanaJobSpecInput) { in.SolanaCapabilityInputs = nil }, "at least one solana capability input is required"}, + {"missing node id", func(in *jobs.ProposeSolanaJobSpecInput) { in.SolanaCapabilityInputs[0].NodeID = "" }, "nodeID is required for solana capability input"}, + {"missing transmitter without JD", func(in *jobs.ProposeSolanaJobSpecInput) { + in.SolanaCapabilityInputs[0].Transmitter = "" + in.SolanaCapabilityInputs[0].OverrideDefaultCfg.Transmitter = "" + }, "offchain client is required"}, + {"missing delta stage", func(in *jobs.ProposeSolanaJobSpecInput) { in.DeltaStage = 0 }, "deltaStage"}, + {"missing forwarder qualifier", func(in *jobs.ProposeSolanaJobSpecInput) { in.ForwardersQualifier = "" }, "cre forwarder qualifier is required"}, + {"wrong chain family", func(in *jobs.ProposeSolanaJobSpecInput) { + in.ChainSelector = chainsel.ETHEREUM_TESTNET_SEPOLIA.Selector + }, "expected \"solana\""}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + in := deepCloneSolanaInput(base) + tc.mutate(&in) + err := jobs.ProposeSolanaJobSpec{}.VerifyPreconditions(env, in) + require.Error(t, err) + assert.Contains(t, err.Error(), tc.errFrag) + }) + } +} + +func TestProposeSolanaJobSpec_VerifyPreconditions_missingDatastore(t *testing.T) { + solSel := chainsel.SOLANA_DEVNET.Selector + ds := datastore.NewMemoryDataStore() + env := cldf.Environment{DataStore: ds.Seal()} + in := freshSolanaBase(solSel) + + err := jobs.ProposeSolanaJobSpec{}.VerifyPreconditions(env, in) + require.Error(t, err) + assert.Contains(t, err.Error(), "failed to get Solana forwarder program") +} + +func TestProposeSolanaJobSpec_VerifyPreconditions_overrideMismatches(t *testing.T) { + solSel := chainsel.SOLANA_DEVNET.Selector + ds := datastore.NewMemoryDataStore() + seedSolanaForwarderAddresses(t, ds, solSel, testSolSolanaFwdQualifier, testSolanaForwarderProgram, testSolanaForwarderState) + env := cldf.Environment{DataStore: ds.Seal()} + base := freshSolanaBase(solSel) + + t.Run("chainID mismatch when provided", func(t *testing.T) { + in := deepCloneSolanaInput(base) + in.SolanaCapabilityInputs[0].OverrideDefaultCfg.ChainID = "wrong-chain" + err := jobs.ProposeSolanaJobSpec{}.VerifyPreconditions(env, in) + require.Error(t, err) + assert.Contains(t, err.Error(), "chainID in override config") + }) + + t.Run("network must be solana if provided", func(t *testing.T) { + in := deepCloneSolanaInput(base) + in.SolanaCapabilityInputs[0].OverrideDefaultCfg.Network = "evm" + err := jobs.ProposeSolanaJobSpec{}.VerifyPreconditions(env, in) + require.Error(t, err) + assert.Contains(t, err.Error(), "network in override config must be") + }) + + t.Run("forwarder program override mismatch", func(t *testing.T) { + in := deepCloneSolanaInput(base) + in.SolanaCapabilityInputs[0].OverrideDefaultCfg.CREForwarderAddress = "11111111111111111111111111111111" + err := jobs.ProposeSolanaJobSpec{}.VerifyPreconditions(env, in) + require.Error(t, err) + assert.Contains(t, err.Error(), "CRE forwarder address") + }) +} + +type solanaJobTestSetup struct { + env *cldf.Environment + solanaCapInputs []jobs.SolanaCapabilityInput + baseInput jobs.ProposeSolanaJobSpecInput +} + +func setupSolanaJobTest(t *testing.T) solanaJobTestSetup { + t.Helper() + testEnv := test.SetupEnvV2(t, false) + solSel := chainsel.SOLANA_DEVNET.Selector + + ds := datastore.NewMemoryDataStore() + seedSolanaForwarderAddresses(t, ds, solSel, testSolSolanaFwdQualifier, testSolanaForwarderProgram, testSolanaForwarderState) + env := testEnv.Env + env.DataStore = ds.Seal() + + nodes, err := testEnv.TestJD.ListNodes(t.Context(), &node.ListNodesRequest{}) + require.NoError(t, err) + + var solanaCapInputs []jobs.SolanaCapabilityInput + mockGetter := &tenv.MockJobApproverGetter{JobApprovers: make(map[string]*tenv.MockJobApprover)} + for _, n := range nodes.GetNodes() { + if strings.Contains(n.Id, "bootstrap") { + continue + } + mockGetter.JobApprovers[n.Id] = &tenv.MockJobApprover{} + solanaCapInputs = append(solanaCapInputs, solanaCapInput(n.Id, "")) + } + + client := tenv.NewJobServiceClient(mockGetter) + testEnv.TestJD.JobServiceClient = client + + env.Offchain = struct { + jobv1.JobServiceClient + node.NodeServiceClient + csav1.CSAServiceClient + }{ + JobServiceClient: client, + NodeServiceClient: env.Offchain, + CSAServiceClient: env.Offchain, + } + + baseInput := jobs.ProposeSolanaJobSpecInput{ + Environment: "test", + Zone: test.Zone, + Domain: "cre", + DONName: test.DONName, + ChainSelector: solSel, + DeltaStage: time.Second, + ForwardersQualifier: testSolSolanaFwdQualifier, + ForwarderVersion: testSolanaForwarderVersion, + SolanaCapabilityInputs: solanaCapInputs, + } + + return solanaJobTestSetup{ + env: env, + solanaCapInputs: solanaCapInputs, + baseInput: baseInput, + } +} + +func TestProposeSolanaJobSpec_Apply_success(t *testing.T) { + setup := setupSolanaJobTest(t) + input := setup.baseInput + + require.NoError(t, jobs.ProposeSolanaJobSpec{}.VerifyPreconditions(*setup.env, input)) + + out, err := jobs.ProposeSolanaJobSpec{}.Apply(*setup.env, input) + require.NoError(t, err) + assert.Len(t, out.Reports, 1) +} + +func TestProposeSolanaJobSpec_Apply_duplicateNodeIDs(t *testing.T) { + setup := setupSolanaJobTest(t) + input := setup.baseInput + require.GreaterOrEqual(t, len(setup.solanaCapInputs), 2, "need at least 2 nodes") + input.SolanaCapabilityInputs = []jobs.SolanaCapabilityInput{ + setup.solanaCapInputs[0], + setup.solanaCapInputs[0], + } + + _, err := jobs.ProposeSolanaJobSpec{}.Apply(*setup.env, input) + require.Error(t, err) + assert.Contains(t, err.Error(), "duplicate nodeID") +} diff --git a/deployment/cre/test/env_setup.go b/deployment/cre/test/env_setup.go index 5293c8bdead..7b0802a90d5 100644 --- a/deployment/cre/test/env_setup.go +++ b/deployment/cre/test/env_setup.go @@ -285,7 +285,7 @@ func setupViewOnlyNodeTest(t *testing.T, registryChainSel, aptosChainSel uint64, } nCfg := envtest.NodeConfig{ - ChainSelectors: []uint64{registryChainSel, aptosChainSel}, + ChainSelectors: []uint64{registryChainSel, aptosChainSel, chain_selectors.SOLANA_DEVNET.Selector}, Name: fmt.Sprintf("%s-%d", donCfg.Name, i), Labels: labels, } @@ -303,7 +303,7 @@ func setupViewOnlyNodeTest(t *testing.T, registryChainSel, aptosChainSel uint64, maps.Copy(btLabels, donCfg.Labels) } nodesCfg = append(nodesCfg, envtest.NodeConfig{ - ChainSelectors: []uint64{registryChainSel, aptosChainSel}, + ChainSelectors: []uint64{registryChainSel, aptosChainSel, chain_selectors.SOLANA_DEVNET.Selector}, Name: donCfg.Name + "-bootstrap", Labels: btLabels, }) diff --git a/deployment/environment/nodeclient/chainlink_models.go b/deployment/environment/nodeclient/chainlink_models.go index f2f7c6e33ca..9ee979c4efb 100644 --- a/deployment/environment/nodeclient/chainlink_models.go +++ b/deployment/environment/nodeclient/chainlink_models.go @@ -916,32 +916,6 @@ observationSource = """ return MarshallTemplate(f, "Flux Monitor Job", fluxMonitorTemplateString) } -// KeeperJobSpec represents a V2 keeper spec -type KeeperJobSpec struct { - Name string `toml:"name"` - ContractAddress string `toml:"contractAddress"` - FromAddress string `toml:"fromAddress"` // Hex representation of the from address - EVMChainID string `toml:"evmChainID"` // Not optional - MinIncomingConfirmations int `toml:"minIncomingConfirmations"` -} - -// Type returns the type of the job -func (k *KeeperJobSpec) Type() string { return "keeper" } - -// String representation of the job -func (k *KeeperJobSpec) String() (string, error) { - keeperTemplateString := ` -type = "keeper" -schemaVersion = 1 -name = "{{.Name}}" -contractAddress = "{{.ContractAddress}}" -fromAddress = "{{.FromAddress}}" -evmChainID = "{{.EVMChainID}}" -minIncomingConfirmations = {{.MinIncomingConfirmations}} -` - return MarshallTemplate(k, "Keeper Job", keeperTemplateString) -} - // OCRBootstrapJobSpec represents the spec for bootstrapping an OCR job, given to one node that then must be linked // back to by others by OCRTaskJobSpecs type OCRBootstrapJobSpec struct { diff --git a/deployment/environment/test/nodes.go b/deployment/environment/test/nodes.go index b10fb0ac1b6..bbdd32c132c 100644 --- a/deployment/environment/test/nodes.go +++ b/deployment/environment/test/nodes.go @@ -97,6 +97,10 @@ func testOCRConfig(t *testing.T, sel uint64, p2p p2pkey.KeyV2) deployment.OCRCon if f == chain_selectors.FamilyAptos { transmitAccount = types2.Account(hex.EncodeToString(seed[:32])) } + if f == chain_selectors.FamilySolana { + // JD stores Solana account addresses as base58; must be valid for chain capability config parsing. + transmitAccount = types2.Account("So11111111111111111111111111111111111111112") + } return deployment.OCRConfig{ PeerID: p2p.PeerID(), diff --git a/deployment/environment/web/sdk/internal/generated/generated.go b/deployment/environment/web/sdk/internal/generated/generated.go index ca6dcde4ee8..de8fb8616e9 100644 --- a/deployment/environment/web/sdk/internal/generated/generated.go +++ b/deployment/environment/web/sdk/internal/generated/generated.go @@ -2063,6 +2063,12 @@ const ( ErrorCodeUnprocessable ErrorCode = "UNPROCESSABLE" ) +var AllErrorCode = []ErrorCode{ + ErrorCodeNotFound, + ErrorCodeInvalidInput, + ErrorCodeUnprocessable, +} + // FeedsManagerParts includes the GraphQL fields of FeedsManager requested by the fragment FeedsManagerParts. type FeedsManagerParts struct { Id string `json:"id"` @@ -4460,6 +4466,22 @@ func (v *JobPartsSpecCCIPSpec) __premarshalJSON() (*__premarshalJobPartsSpecCCIP return &retval, nil } +// JobPartsSpecCCVCommitteeVerifierSpec includes the requested fields of the GraphQL type CCVCommitteeVerifierSpec. +type JobPartsSpecCCVCommitteeVerifierSpec struct { + Typename string `json:"__typename"` +} + +// GetTypename returns JobPartsSpecCCVCommitteeVerifierSpec.Typename, and is useful for accessing the field via an interface. +func (v *JobPartsSpecCCVCommitteeVerifierSpec) GetTypename() string { return v.Typename } + +// JobPartsSpecCCVExecutorSpec includes the requested fields of the GraphQL type CCVExecutorSpec. +type JobPartsSpecCCVExecutorSpec struct { + Typename string `json:"__typename"` +} + +// GetTypename returns JobPartsSpecCCVExecutorSpec.Typename, and is useful for accessing the field via an interface. +func (v *JobPartsSpecCCVExecutorSpec) GetTypename() string { return v.Typename } + // JobPartsSpecCronSpec includes the requested fields of the GraphQL type CronSpec. type JobPartsSpecCronSpec struct { Typename string `json:"__typename"` @@ -4857,11 +4879,12 @@ func (v *JobPartsSpecGatewaySpec) __premarshalJSON() (*__premarshalJobPartsSpecG // JobPartsSpecBlockhashStoreSpec // JobPartsSpecBootstrapSpec // JobPartsSpecCCIPSpec +// JobPartsSpecCCVCommitteeVerifierSpec +// JobPartsSpecCCVExecutorSpec // JobPartsSpecCronSpec // JobPartsSpecDirectRequestSpec // JobPartsSpecFluxMonitorSpec // JobPartsSpecGatewaySpec -// JobPartsSpecKeeperSpec // JobPartsSpecOCR2Spec // JobPartsSpecOCRSpec // JobPartsSpecStandardCapabilitiesSpec @@ -4879,11 +4902,12 @@ func (v *JobPartsSpecBlockHeaderFeederSpec) implementsGraphQLInterfaceJobPartsSp func (v *JobPartsSpecBlockhashStoreSpec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} func (v *JobPartsSpecBootstrapSpec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} func (v *JobPartsSpecCCIPSpec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} +func (v *JobPartsSpecCCVCommitteeVerifierSpec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} +func (v *JobPartsSpecCCVExecutorSpec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} func (v *JobPartsSpecCronSpec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} func (v *JobPartsSpecDirectRequestSpec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} func (v *JobPartsSpecFluxMonitorSpec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} func (v *JobPartsSpecGatewaySpec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} -func (v *JobPartsSpecKeeperSpec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} func (v *JobPartsSpecOCR2Spec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} func (v *JobPartsSpecOCRSpec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} func (v *JobPartsSpecStandardCapabilitiesSpec) implementsGraphQLInterfaceJobPartsSpecJobSpec() {} @@ -4918,6 +4942,12 @@ func __unmarshalJobPartsSpecJobSpec(b []byte, v *JobPartsSpecJobSpec) error { case "CCIPSpec": *v = new(JobPartsSpecCCIPSpec) return json.Unmarshal(b, *v) + case "CCVCommitteeVerifierSpec": + *v = new(JobPartsSpecCCVCommitteeVerifierSpec) + return json.Unmarshal(b, *v) + case "CCVExecutorSpec": + *v = new(JobPartsSpecCCVExecutorSpec) + return json.Unmarshal(b, *v) case "CronSpec": *v = new(JobPartsSpecCronSpec) return json.Unmarshal(b, *v) @@ -4930,9 +4960,6 @@ func __unmarshalJobPartsSpecJobSpec(b []byte, v *JobPartsSpecJobSpec) error { case "GatewaySpec": *v = new(JobPartsSpecGatewaySpec) return json.Unmarshal(b, *v) - case "KeeperSpec": - *v = new(JobPartsSpecKeeperSpec) - return json.Unmarshal(b, *v) case "OCR2Spec": *v = new(JobPartsSpecOCR2Spec) return json.Unmarshal(b, *v) @@ -5015,6 +5042,22 @@ func __marshalJobPartsSpecJobSpec(v *JobPartsSpecJobSpec) ([]byte, error) { *__premarshalJobPartsSpecCCIPSpec }{typename, premarshaled} return json.Marshal(result) + case *JobPartsSpecCCVCommitteeVerifierSpec: + typename = "CCVCommitteeVerifierSpec" + + result := struct { + TypeName string `json:"__typename"` + *JobPartsSpecCCVCommitteeVerifierSpec + }{typename, v} + return json.Marshal(result) + case *JobPartsSpecCCVExecutorSpec: + typename = "CCVExecutorSpec" + + result := struct { + TypeName string `json:"__typename"` + *JobPartsSpecCCVExecutorSpec + }{typename, v} + return json.Marshal(result) case *JobPartsSpecCronSpec: typename = "CronSpec" @@ -5063,18 +5106,6 @@ func __marshalJobPartsSpecJobSpec(v *JobPartsSpecJobSpec) ([]byte, error) { *__premarshalJobPartsSpecGatewaySpec }{typename, premarshaled} return json.Marshal(result) - case *JobPartsSpecKeeperSpec: - typename = "KeeperSpec" - - premarshaled, err := v.__premarshalJSON() - if err != nil { - return nil, err - } - result := struct { - TypeName string `json:"__typename"` - *__premarshalJobPartsSpecKeeperSpec - }{typename, premarshaled} - return json.Marshal(result) case *JobPartsSpecOCR2Spec: typename = "OCR2Spec" @@ -5167,83 +5198,6 @@ func __marshalJobPartsSpecJobSpec(v *JobPartsSpecJobSpec) ([]byte, error) { } } -// JobPartsSpecKeeperSpec includes the requested fields of the GraphQL type KeeperSpec. -type JobPartsSpecKeeperSpec struct { - Typename string `json:"__typename"` - KeeperSpec `json:"-"` -} - -// GetTypename returns JobPartsSpecKeeperSpec.Typename, and is useful for accessing the field via an interface. -func (v *JobPartsSpecKeeperSpec) GetTypename() string { return v.Typename } - -// GetContractAddress returns JobPartsSpecKeeperSpec.ContractAddress, and is useful for accessing the field via an interface. -func (v *JobPartsSpecKeeperSpec) GetContractAddress() string { return v.KeeperSpec.ContractAddress } - -// GetCreatedAt returns JobPartsSpecKeeperSpec.CreatedAt, and is useful for accessing the field via an interface. -func (v *JobPartsSpecKeeperSpec) GetCreatedAt() string { return v.KeeperSpec.CreatedAt } - -// GetEvmChainID returns JobPartsSpecKeeperSpec.EvmChainID, and is useful for accessing the field via an interface. -func (v *JobPartsSpecKeeperSpec) GetEvmChainID() string { return v.KeeperSpec.EvmChainID } - -// GetFromAddress returns JobPartsSpecKeeperSpec.FromAddress, and is useful for accessing the field via an interface. -func (v *JobPartsSpecKeeperSpec) GetFromAddress() string { return v.KeeperSpec.FromAddress } - -func (v *JobPartsSpecKeeperSpec) UnmarshalJSON(b []byte) error { - - if string(b) == "null" { - return nil - } - - var firstPass struct { - *JobPartsSpecKeeperSpec - graphql.NoUnmarshalJSON - } - firstPass.JobPartsSpecKeeperSpec = v - - err := json.Unmarshal(b, &firstPass) - if err != nil { - return err - } - - err = json.Unmarshal( - b, &v.KeeperSpec) - if err != nil { - return err - } - return nil -} - -type __premarshalJobPartsSpecKeeperSpec struct { - Typename string `json:"__typename"` - - ContractAddress string `json:"contractAddress"` - - CreatedAt string `json:"createdAt"` - - EvmChainID string `json:"evmChainID"` - - FromAddress string `json:"fromAddress"` -} - -func (v *JobPartsSpecKeeperSpec) MarshalJSON() ([]byte, error) { - premarshaled, err := v.__premarshalJSON() - if err != nil { - return nil, err - } - return json.Marshal(premarshaled) -} - -func (v *JobPartsSpecKeeperSpec) __premarshalJSON() (*__premarshalJobPartsSpecKeeperSpec, error) { - var retval __premarshalJobPartsSpecKeeperSpec - - retval.Typename = v.Typename - retval.ContractAddress = v.KeeperSpec.ContractAddress - retval.CreatedAt = v.KeeperSpec.CreatedAt - retval.EvmChainID = v.KeeperSpec.EvmChainID - retval.FromAddress = v.KeeperSpec.FromAddress - return &retval, nil -} - // JobPartsSpecOCR2Spec includes the requested fields of the GraphQL type OCR2Spec. type JobPartsSpecOCR2Spec struct { Typename string `json:"__typename"` @@ -6010,26 +5964,15 @@ const ( JobProposalStatusRevoked JobProposalStatus = "REVOKED" ) -// KeeperSpec includes the GraphQL fields of KeeperSpec requested by the fragment KeeperSpec. -type KeeperSpec struct { - ContractAddress string `json:"contractAddress"` - CreatedAt string `json:"createdAt"` - EvmChainID string `json:"evmChainID"` - FromAddress string `json:"fromAddress"` +var AllJobProposalStatus = []JobProposalStatus{ + JobProposalStatusPending, + JobProposalStatusApproved, + JobProposalStatusRejected, + JobProposalStatusCancelled, + JobProposalStatusDeleted, + JobProposalStatusRevoked, } -// GetContractAddress returns KeeperSpec.ContractAddress, and is useful for accessing the field via an interface. -func (v *KeeperSpec) GetContractAddress() string { return v.ContractAddress } - -// GetCreatedAt returns KeeperSpec.CreatedAt, and is useful for accessing the field via an interface. -func (v *KeeperSpec) GetCreatedAt() string { return v.CreatedAt } - -// GetEvmChainID returns KeeperSpec.EvmChainID, and is useful for accessing the field via an interface. -func (v *KeeperSpec) GetEvmChainID() string { return v.EvmChainID } - -// GetFromAddress returns KeeperSpec.FromAddress, and is useful for accessing the field via an interface. -func (v *KeeperSpec) GetFromAddress() string { return v.FromAddress } - // ListBridgesBridgesBridgesPayload includes the requested fields of the GraphQL type BridgesPayload. type ListBridgesBridgesBridgesPayload struct { Results []ListBridgesBridgesBridgesPayloadResultsBridge `json:"results"` @@ -6456,6 +6399,17 @@ const ( OCR2ChainTypeSui OCR2ChainType = "SUI" ) +var AllOCR2ChainType = []OCR2ChainType{ + OCR2ChainTypeEvm, + OCR2ChainTypeCosmos, + OCR2ChainTypeSolana, + OCR2ChainTypeStarknet, + OCR2ChainTypeAptos, + OCR2ChainTypeTron, + OCR2ChainTypeTon, + OCR2ChainTypeSui, +} + // OCR2Spec includes the GraphQL fields of OCR2Spec requested by the fragment OCR2Spec. type OCR2Spec struct { BlockchainTimeout string `json:"blockchainTimeout"` @@ -6827,6 +6781,15 @@ const ( SpecStatusRevoked SpecStatus = "REVOKED" ) +var AllSpecStatus = []SpecStatus{ + SpecStatusUnknown, + SpecStatusPending, + SpecStatusApproved, + SpecStatusRejected, + SpecStatusCancelled, + SpecStatusRevoked, +} + // StandardCapabilitiesSpec includes the GraphQL fields of StandardCapabilitiesSpec requested by the fragment StandardCapabilitiesSpec. type StandardCapabilitiesSpec struct { Id string `json:"id"` @@ -7693,7 +7656,7 @@ func (v *__UpdateJobProposalSpecDefinitionInput) GetInput() UpdateJobProposalSpe return v.Input } -// The query or mutation executed by ApproveJobProposalSpec. +// The mutation executed by ApproveJobProposalSpec. const ApproveJobProposalSpec_Operation = ` mutation ApproveJobProposalSpec ($id: ID!, $force: Boolean) { approveJobProposalSpec(id: $id, force: $force) { @@ -7726,7 +7689,7 @@ func ApproveJobProposalSpec( client_ graphql.Client, id string, force bool, -) (*ApproveJobProposalSpecResponse, error) { +) (data_ *ApproveJobProposalSpecResponse, err_ error) { req_ := &graphql.Request{ OpName: "ApproveJobProposalSpec", Query: ApproveJobProposalSpec_Operation, @@ -7735,10 +7698,9 @@ func ApproveJobProposalSpec( Force: force, }, } - var err_ error - var data_ ApproveJobProposalSpecResponse - resp_ := &graphql.Response{Data: &data_} + data_ = &ApproveJobProposalSpecResponse{} + resp_ := &graphql.Response{Data: data_} err_ = client_.MakeRequest( ctx_, @@ -7746,10 +7708,10 @@ func ApproveJobProposalSpec( resp_, ) - return &data_, err_ + return data_, err_ } -// The query or mutation executed by CancelJobProposalSpec. +// The mutation executed by CancelJobProposalSpec. const CancelJobProposalSpec_Operation = ` mutation CancelJobProposalSpec ($id: ID!) { cancelJobProposalSpec(id: $id) { @@ -7777,7 +7739,7 @@ func CancelJobProposalSpec( ctx_ context.Context, client_ graphql.Client, id string, -) (*CancelJobProposalSpecResponse, error) { +) (data_ *CancelJobProposalSpecResponse, err_ error) { req_ := &graphql.Request{ OpName: "CancelJobProposalSpec", Query: CancelJobProposalSpec_Operation, @@ -7785,10 +7747,9 @@ func CancelJobProposalSpec( Id: id, }, } - var err_ error - var data_ CancelJobProposalSpecResponse - resp_ := &graphql.Response{Data: &data_} + data_ = &CancelJobProposalSpecResponse{} + resp_ := &graphql.Response{Data: data_} err_ = client_.MakeRequest( ctx_, @@ -7796,10 +7757,10 @@ func CancelJobProposalSpec( resp_, ) - return &data_, err_ + return data_, err_ } -// The query or mutation executed by CreateFeedsManager. +// The mutation executed by CreateFeedsManager. const CreateFeedsManager_Operation = ` mutation CreateFeedsManager ($input: CreateFeedsManagerInput!) { createFeedsManager(input: $input) { @@ -7865,7 +7826,7 @@ func CreateFeedsManager( ctx_ context.Context, client_ graphql.Client, input CreateFeedsManagerInput, -) (*CreateFeedsManagerResponse, error) { +) (data_ *CreateFeedsManagerResponse, err_ error) { req_ := &graphql.Request{ OpName: "CreateFeedsManager", Query: CreateFeedsManager_Operation, @@ -7873,10 +7834,9 @@ func CreateFeedsManager( Input: input, }, } - var err_ error - var data_ CreateFeedsManagerResponse - resp_ := &graphql.Response{Data: &data_} + data_ = &CreateFeedsManagerResponse{} + resp_ := &graphql.Response{Data: data_} err_ = client_.MakeRequest( ctx_, @@ -7884,10 +7844,10 @@ func CreateFeedsManager( resp_, ) - return &data_, err_ + return data_, err_ } -// The query or mutation executed by CreateFeedsManagerChainConfig. +// The mutation executed by CreateFeedsManagerChainConfig. const CreateFeedsManagerChainConfig_Operation = ` mutation CreateFeedsManagerChainConfig ($input: CreateFeedsManagerChainConfigInput!) { createFeedsManagerChainConfig(input: $input) { @@ -7945,7 +7905,7 @@ func CreateFeedsManagerChainConfig( ctx_ context.Context, client_ graphql.Client, input CreateFeedsManagerChainConfigInput, -) (*CreateFeedsManagerChainConfigResponse, error) { +) (data_ *CreateFeedsManagerChainConfigResponse, err_ error) { req_ := &graphql.Request{ OpName: "CreateFeedsManagerChainConfig", Query: CreateFeedsManagerChainConfig_Operation, @@ -7953,10 +7913,9 @@ func CreateFeedsManagerChainConfig( Input: input, }, } - var err_ error - var data_ CreateFeedsManagerChainConfigResponse - resp_ := &graphql.Response{Data: &data_} + data_ = &CreateFeedsManagerChainConfigResponse{} + resp_ := &graphql.Response{Data: data_} err_ = client_.MakeRequest( ctx_, @@ -7964,10 +7923,10 @@ func CreateFeedsManagerChainConfig( resp_, ) - return &data_, err_ + return data_, err_ } -// The query or mutation executed by CreateOCR2KeyBundle. +// The mutation executed by CreateOCR2KeyBundle. const CreateOCR2KeyBundle_Operation = ` mutation CreateOCR2KeyBundle ($chainType: OCR2ChainType!) { createOCR2KeyBundle(chainType: $chainType) { @@ -7990,7 +7949,7 @@ func CreateOCR2KeyBundle( ctx_ context.Context, client_ graphql.Client, chainType OCR2ChainType, -) (*CreateOCR2KeyBundleResponse, error) { +) (data_ *CreateOCR2KeyBundleResponse, err_ error) { req_ := &graphql.Request{ OpName: "CreateOCR2KeyBundle", Query: CreateOCR2KeyBundle_Operation, @@ -7998,10 +7957,9 @@ func CreateOCR2KeyBundle( ChainType: chainType, }, } - var err_ error - var data_ CreateOCR2KeyBundleResponse - resp_ := &graphql.Response{Data: &data_} + data_ = &CreateOCR2KeyBundleResponse{} + resp_ := &graphql.Response{Data: data_} err_ = client_.MakeRequest( ctx_, @@ -8009,10 +7967,10 @@ func CreateOCR2KeyBundle( resp_, ) - return &data_, err_ + return data_, err_ } -// The query or mutation executed by DeleteFeedsManagerChainConfig. +// The mutation executed by DeleteFeedsManagerChainConfig. const DeleteFeedsManagerChainConfig_Operation = ` mutation DeleteFeedsManagerChainConfig ($id: ID!) { deleteFeedsManagerChainConfig(id: $id) { @@ -8034,7 +7992,7 @@ func DeleteFeedsManagerChainConfig( ctx_ context.Context, client_ graphql.Client, id string, -) (*DeleteFeedsManagerChainConfigResponse, error) { +) (data_ *DeleteFeedsManagerChainConfigResponse, err_ error) { req_ := &graphql.Request{ OpName: "DeleteFeedsManagerChainConfig", Query: DeleteFeedsManagerChainConfig_Operation, @@ -8042,10 +8000,9 @@ func DeleteFeedsManagerChainConfig( Id: id, }, } - var err_ error - var data_ DeleteFeedsManagerChainConfigResponse - resp_ := &graphql.Response{Data: &data_} + data_ = &DeleteFeedsManagerChainConfigResponse{} + resp_ := &graphql.Response{Data: data_} err_ = client_.MakeRequest( ctx_, @@ -8053,10 +8010,10 @@ func DeleteFeedsManagerChainConfig( resp_, ) - return &data_, err_ + return data_, err_ } -// The query or mutation executed by FetchAccounts. +// The query executed by FetchAccounts. const FetchAccounts_Operation = ` query FetchAccounts { ethKeys { @@ -8077,15 +8034,14 @@ query FetchAccounts { func FetchAccounts( ctx_ context.Context, client_ graphql.Client, -) (*FetchAccountsResponse, error) { +) (data_ *FetchAccountsResponse, err_ error) { req_ := &graphql.Request{ OpName: "FetchAccounts", Query: FetchAccounts_Operation, } - var err_ error - var data_ FetchAccountsResponse - resp_ := &graphql.Response{Data: &data_} + data_ = &FetchAccountsResponse{} + resp_ := &graphql.Response{Data: data_} err_ = client_.MakeRequest( ctx_, @@ -8093,10 +8049,10 @@ func FetchAccounts( resp_, ) - return &data_, err_ + return data_, err_ } -// The query or mutation executed by FetchCSAKeys. +// The query executed by FetchCSAKeys. const FetchCSAKeys_Operation = ` query FetchCSAKeys { csaKeys { @@ -8112,15 +8068,14 @@ query FetchCSAKeys { func FetchCSAKeys( ctx_ context.Context, client_ graphql.Client, -) (*FetchCSAKeysResponse, error) { +) (data_ *FetchCSAKeysResponse, err_ error) { req_ := &graphql.Request{ OpName: "FetchCSAKeys", Query: FetchCSAKeys_Operation, } - var err_ error - var data_ FetchCSAKeysResponse - resp_ := &graphql.Response{Data: &data_} + data_ = &FetchCSAKeysResponse{} + resp_ := &graphql.Response{Data: data_} err_ = client_.MakeRequest( ctx_, @@ -8128,10 +8083,10 @@ func FetchCSAKeys( resp_, ) - return &data_, err_ + return data_, err_ } -// The query or mutation executed by FetchKeys. +// The query executed by FetchKeys. const FetchKeys_Operation = ` query FetchKeys { solanaKeys { @@ -8157,15 +8112,14 @@ query FetchKeys { func FetchKeys( ctx_ context.Context, client_ graphql.Client, -) (*FetchKeysResponse, error) { +) (data_ *FetchKeysResponse, err_ error) { req_ := &graphql.Request{ OpName: "FetchKeys", Query: FetchKeys_Operation, } - var err_ error - var data_ FetchKeysResponse - resp_ := &graphql.Response{Data: &data_} + data_ = &FetchKeysResponse{} + resp_ := &graphql.Response{Data: data_} err_ = client_.MakeRequest( ctx_, @@ -8173,10 +8127,10 @@ func FetchKeys( resp_, ) - return &data_, err_ + return data_, err_ } -// The query or mutation executed by FetchOCR2KeyBundles. +// The query executed by FetchOCR2KeyBundles. const FetchOCR2KeyBundles_Operation = ` query FetchOCR2KeyBundles { ocr2KeyBundles { @@ -8194,15 +8148,14 @@ query FetchOCR2KeyBundles { func FetchOCR2KeyBundles( ctx_ context.Context, client_ graphql.Client, -) (*FetchOCR2KeyBundlesResponse, error) { +) (data_ *FetchOCR2KeyBundlesResponse, err_ error) { req_ := &graphql.Request{ OpName: "FetchOCR2KeyBundles", Query: FetchOCR2KeyBundles_Operation, } - var err_ error - var data_ FetchOCR2KeyBundlesResponse - resp_ := &graphql.Response{Data: &data_} + data_ = &FetchOCR2KeyBundlesResponse{} + resp_ := &graphql.Response{Data: data_} err_ = client_.MakeRequest( ctx_, @@ -8210,10 +8163,10 @@ func FetchOCR2KeyBundles( resp_, ) - return &data_, err_ + return data_, err_ } -// The query or mutation executed by FetchP2PKeys. +// The query executed by FetchP2PKeys. const FetchP2PKeys_Operation = ` query FetchP2PKeys { p2pKeys { @@ -8229,15 +8182,14 @@ query FetchP2PKeys { func FetchP2PKeys( ctx_ context.Context, client_ graphql.Client, -) (*FetchP2PKeysResponse, error) { +) (data_ *FetchP2PKeysResponse, err_ error) { req_ := &graphql.Request{ OpName: "FetchP2PKeys", Query: FetchP2PKeys_Operation, } - var err_ error - var data_ FetchP2PKeysResponse - resp_ := &graphql.Response{Data: &data_} + data_ = &FetchP2PKeysResponse{} + resp_ := &graphql.Response{Data: data_} err_ = client_.MakeRequest( ctx_, @@ -8245,10 +8197,10 @@ func FetchP2PKeys( resp_, ) - return &data_, err_ + return data_, err_ } -// The query or mutation executed by GetBridge. +// The query executed by GetBridge. const GetBridge_Operation = ` query GetBridge ($id: ID!) { bridge(id: $id) { @@ -8275,7 +8227,7 @@ func GetBridge( ctx_ context.Context, client_ graphql.Client, id string, -) (*GetBridgeResponse, error) { +) (data_ *GetBridgeResponse, err_ error) { req_ := &graphql.Request{ OpName: "GetBridge", Query: GetBridge_Operation, @@ -8283,10 +8235,9 @@ func GetBridge( Id: id, }, } - var err_ error - var data_ GetBridgeResponse - resp_ := &graphql.Response{Data: &data_} + data_ = &GetBridgeResponse{} + resp_ := &graphql.Response{Data: data_} err_ = client_.MakeRequest( ctx_, @@ -8294,10 +8245,10 @@ func GetBridge( resp_, ) - return &data_, err_ + return data_, err_ } -// The query or mutation executed by GetFeedsManager. +// The query executed by GetFeedsManager. const GetFeedsManager_Operation = ` query GetFeedsManager ($id: ID!) { feedsManager(id: $id) { @@ -8348,7 +8299,7 @@ func GetFeedsManager( ctx_ context.Context, client_ graphql.Client, id string, -) (*GetFeedsManagerResponse, error) { +) (data_ *GetFeedsManagerResponse, err_ error) { req_ := &graphql.Request{ OpName: "GetFeedsManager", Query: GetFeedsManager_Operation, @@ -8356,10 +8307,9 @@ func GetFeedsManager( Id: id, }, } - var err_ error - var data_ GetFeedsManagerResponse - resp_ := &graphql.Response{Data: &data_} + data_ = &GetFeedsManagerResponse{} + resp_ := &graphql.Response{Data: data_} err_ = client_.MakeRequest( ctx_, @@ -8367,10 +8317,10 @@ func GetFeedsManager( resp_, ) - return &data_, err_ + return data_, err_ } -// The query or mutation executed by GetJob. +// The query executed by GetJob. const GetJob_Operation = ` query GetJob ($id: ID!) { job(id: $id) { @@ -8402,9 +8352,6 @@ fragment JobParts on Job { ... on FluxMonitorSpec { ... FluxMonitorSpec } - ... on KeeperSpec { - ... KeeperSpec - } ... on DirectRequestSpec { ... DirectRequestSpec } @@ -8499,12 +8446,6 @@ fragment FluxMonitorSpec on FluxMonitorSpec { pollTimerPeriod threshold } -fragment KeeperSpec on KeeperSpec { - contractAddress - createdAt - evmChainID - fromAddress -} fragment DirectRequestSpec on DirectRequestSpec { contractAddress createdAt @@ -8620,7 +8561,7 @@ func GetJob( ctx_ context.Context, client_ graphql.Client, id string, -) (*GetJobResponse, error) { +) (data_ *GetJobResponse, err_ error) { req_ := &graphql.Request{ OpName: "GetJob", Query: GetJob_Operation, @@ -8628,10 +8569,9 @@ func GetJob( Id: id, }, } - var err_ error - var data_ GetJobResponse - resp_ := &graphql.Response{Data: &data_} + data_ = &GetJobResponse{} + resp_ := &graphql.Response{Data: data_} err_ = client_.MakeRequest( ctx_, @@ -8639,10 +8579,10 @@ func GetJob( resp_, ) - return &data_, err_ + return data_, err_ } -// The query or mutation executed by GetJobProposal. +// The query executed by GetJobProposal. const GetJobProposal_Operation = ` query GetJobProposal ($id: ID!) { jobProposal(id: $id) { @@ -8723,7 +8663,7 @@ func GetJobProposal( ctx_ context.Context, client_ graphql.Client, id string, -) (*GetJobProposalResponse, error) { +) (data_ *GetJobProposalResponse, err_ error) { req_ := &graphql.Request{ OpName: "GetJobProposal", Query: GetJobProposal_Operation, @@ -8731,10 +8671,9 @@ func GetJobProposal( Id: id, }, } - var err_ error - var data_ GetJobProposalResponse - resp_ := &graphql.Response{Data: &data_} + data_ = &GetJobProposalResponse{} + resp_ := &graphql.Response{Data: data_} err_ = client_.MakeRequest( ctx_, @@ -8742,10 +8681,10 @@ func GetJobProposal( resp_, ) - return &data_, err_ + return data_, err_ } -// The query or mutation executed by ListBridges. +// The query executed by ListBridges. const ListBridges_Operation = ` query ListBridges ($offset: Int, $limit: Int) { bridges(offset: $offset, limit: $limit) { @@ -8773,7 +8712,7 @@ func ListBridges( client_ graphql.Client, offset int, limit int, -) (*ListBridgesResponse, error) { +) (data_ *ListBridgesResponse, err_ error) { req_ := &graphql.Request{ OpName: "ListBridges", Query: ListBridges_Operation, @@ -8782,10 +8721,9 @@ func ListBridges( Limit: limit, }, } - var err_ error - var data_ ListBridgesResponse - resp_ := &graphql.Response{Data: &data_} + data_ = &ListBridgesResponse{} + resp_ := &graphql.Response{Data: data_} err_ = client_.MakeRequest( ctx_, @@ -8793,10 +8731,10 @@ func ListBridges( resp_, ) - return &data_, err_ + return data_, err_ } -// The query or mutation executed by ListFeedsManagers. +// The query executed by ListFeedsManagers. const ListFeedsManagers_Operation = ` query ListFeedsManagers { feedsManagers { @@ -8843,15 +8781,14 @@ fragment FeedsManagerParts on FeedsManager { func ListFeedsManagers( ctx_ context.Context, client_ graphql.Client, -) (*ListFeedsManagersResponse, error) { +) (data_ *ListFeedsManagersResponse, err_ error) { req_ := &graphql.Request{ OpName: "ListFeedsManagers", Query: ListFeedsManagers_Operation, } - var err_ error - var data_ ListFeedsManagersResponse - resp_ := &graphql.Response{Data: &data_} + data_ = &ListFeedsManagersResponse{} + resp_ := &graphql.Response{Data: data_} err_ = client_.MakeRequest( ctx_, @@ -8859,10 +8796,10 @@ func ListFeedsManagers( resp_, ) - return &data_, err_ + return data_, err_ } -// The query or mutation executed by ListJobs. +// The query executed by ListJobs. const ListJobs_Operation = ` query ListJobs ($offset: Int, $limit: Int) { jobs(offset: $offset, limit: $limit) { @@ -8894,9 +8831,6 @@ fragment JobParts on Job { ... on FluxMonitorSpec { ... FluxMonitorSpec } - ... on KeeperSpec { - ... KeeperSpec - } ... on DirectRequestSpec { ... DirectRequestSpec } @@ -8991,12 +8925,6 @@ fragment FluxMonitorSpec on FluxMonitorSpec { pollTimerPeriod threshold } -fragment KeeperSpec on KeeperSpec { - contractAddress - createdAt - evmChainID - fromAddress -} fragment DirectRequestSpec on DirectRequestSpec { contractAddress createdAt @@ -9113,7 +9041,7 @@ func ListJobs( client_ graphql.Client, offset int, limit int, -) (*ListJobsResponse, error) { +) (data_ *ListJobsResponse, err_ error) { req_ := &graphql.Request{ OpName: "ListJobs", Query: ListJobs_Operation, @@ -9122,10 +9050,9 @@ func ListJobs( Limit: limit, }, } - var err_ error - var data_ ListJobsResponse - resp_ := &graphql.Response{Data: &data_} + data_ = &ListJobsResponse{} + resp_ := &graphql.Response{Data: data_} err_ = client_.MakeRequest( ctx_, @@ -9133,10 +9060,10 @@ func ListJobs( resp_, ) - return &data_, err_ + return data_, err_ } -// The query or mutation executed by RejectJobProposalSpec. +// The mutation executed by RejectJobProposalSpec. const RejectJobProposalSpec_Operation = ` mutation RejectJobProposalSpec ($id: ID!) { rejectJobProposalSpec(id: $id) { @@ -9164,7 +9091,7 @@ func RejectJobProposalSpec( ctx_ context.Context, client_ graphql.Client, id string, -) (*RejectJobProposalSpecResponse, error) { +) (data_ *RejectJobProposalSpecResponse, err_ error) { req_ := &graphql.Request{ OpName: "RejectJobProposalSpec", Query: RejectJobProposalSpec_Operation, @@ -9172,10 +9099,9 @@ func RejectJobProposalSpec( Id: id, }, } - var err_ error - var data_ RejectJobProposalSpecResponse - resp_ := &graphql.Response{Data: &data_} + data_ = &RejectJobProposalSpecResponse{} + resp_ := &graphql.Response{Data: data_} err_ = client_.MakeRequest( ctx_, @@ -9183,10 +9109,10 @@ func RejectJobProposalSpec( resp_, ) - return &data_, err_ + return data_, err_ } -// The query or mutation executed by UpdateFeedsManager. +// The mutation executed by UpdateFeedsManager. const UpdateFeedsManager_Operation = ` mutation UpdateFeedsManager ($id: ID!, $input: UpdateFeedsManagerInput!) { updateFeedsManager(id: $id, input: $input) { @@ -9249,7 +9175,7 @@ func UpdateFeedsManager( client_ graphql.Client, id string, input UpdateFeedsManagerInput, -) (*UpdateFeedsManagerResponse, error) { +) (data_ *UpdateFeedsManagerResponse, err_ error) { req_ := &graphql.Request{ OpName: "UpdateFeedsManager", Query: UpdateFeedsManager_Operation, @@ -9258,10 +9184,9 @@ func UpdateFeedsManager( Input: input, }, } - var err_ error - var data_ UpdateFeedsManagerResponse - resp_ := &graphql.Response{Data: &data_} + data_ = &UpdateFeedsManagerResponse{} + resp_ := &graphql.Response{Data: data_} err_ = client_.MakeRequest( ctx_, @@ -9269,10 +9194,10 @@ func UpdateFeedsManager( resp_, ) - return &data_, err_ + return data_, err_ } -// The query or mutation executed by UpdateJobProposalSpecDefinition. +// The mutation executed by UpdateJobProposalSpecDefinition. const UpdateJobProposalSpecDefinition_Operation = ` mutation UpdateJobProposalSpecDefinition ($id: ID!, $input: UpdateJobProposalSpecDefinitionInput!) { updateJobProposalSpecDefinition(id: $id, input: $input) { @@ -9301,7 +9226,7 @@ func UpdateJobProposalSpecDefinition( client_ graphql.Client, id string, input UpdateJobProposalSpecDefinitionInput, -) (*UpdateJobProposalSpecDefinitionResponse, error) { +) (data_ *UpdateJobProposalSpecDefinitionResponse, err_ error) { req_ := &graphql.Request{ OpName: "UpdateJobProposalSpecDefinition", Query: UpdateJobProposalSpecDefinition_Operation, @@ -9310,10 +9235,9 @@ func UpdateJobProposalSpecDefinition( Input: input, }, } - var err_ error - var data_ UpdateJobProposalSpecDefinitionResponse - resp_ := &graphql.Response{Data: &data_} + data_ = &UpdateJobProposalSpecDefinitionResponse{} + resp_ := &graphql.Response{Data: data_} err_ = client_.MakeRequest( ctx_, @@ -9321,5 +9245,5 @@ func UpdateJobProposalSpecDefinition( resp_, ) - return &data_, err_ + return data_, err_ } diff --git a/deployment/environment/web/sdk/internal/genqlient.graphql b/deployment/environment/web/sdk/internal/genqlient.graphql index 2c9588ecc0b..d417ab0d894 100644 --- a/deployment/environment/web/sdk/internal/genqlient.graphql +++ b/deployment/environment/web/sdk/internal/genqlient.graphql @@ -105,9 +105,6 @@ fragment JobParts on Job { ... on FluxMonitorSpec { ...FluxMonitorSpec } - ... on KeeperSpec { - ...KeeperSpec - } ... on DirectRequestSpec { ...DirectRequestSpec } @@ -215,13 +212,6 @@ fragment FluxMonitorSpec on FluxMonitorSpec { threshold } -fragment KeeperSpec on KeeperSpec { - contractAddress - createdAt - evmChainID - fromAddress -} - fragment DirectRequestSpec on DirectRequestSpec { contractAddress createdAt diff --git a/deployment/environment/web/sdk/internal/schema.graphql b/deployment/environment/web/sdk/internal/schema.graphql index 111cd4b2eff..01e0a9f4958 100644 --- a/deployment/environment/web/sdk/internal/schema.graphql +++ b/deployment/environment/web/sdk/internal/schema.graphql @@ -866,7 +866,6 @@ type SolanaKeysPayload { union JobSpec = CronSpec | DirectRequestSpec | - KeeperSpec | FluxMonitorSpec | OCRSpec | OCR2Spec | @@ -879,7 +878,9 @@ union JobSpec = WorkflowSpec | StandardCapabilitiesSpec | StreamSpec | - CCIPSpec + CCIPSpec | + CCVCommitteeVerifierSpec | + CCVExecutorSpec type CronSpec { schedule: String! @@ -912,13 +913,6 @@ type FluxMonitorSpec { threshold: Float! } -type KeeperSpec { - contractAddress: String! - createdAt: Time! - evmChainID: String - fromAddress: String -} - type OCRSpec { blockchainTimeout: String contractAddress: String! @@ -1060,6 +1054,21 @@ type CCIPSpec { capabilityLabelledName: String! ocrKeyBundleIDs: Map! p2pKeyID: String! + p2pv2Bootstrappers: [String!] + pluginConfig: Map! + relayConfigs: Map! +} + +type CCVCommitteeVerifierSpec { + createdAt: Time! + updatedAt: Time! + committeeVerifierConfig: String! +} + +type CCVExecutorSpec { + createdAt: Time! + updatedAt: Time! + executorConfig: String! } type StarkNetKey { id: ID! diff --git a/deployment/go.mod b/deployment/go.mod index 9d350e1b83d..9be0565cffa 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -37,22 +37,21 @@ require ( github.com/smartcontractkit/ccip-owner-contracts v0.1.0 github.com/smartcontractkit/chain-selectors v1.0.98 github.com/smartcontractkit/chainlink-aptos v0.0.0-20260424112027-f932111b88ac - github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260423164805-f44aeafa2aaa - github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260415165642-49f23e4d76cc + github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260428205619-2db1389501a1 + github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260428205619-2db1389501a1 github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260415165642-49f23e4d76cc github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260415165642-49f23e4d76cc - github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260415165642-49f23e4d76cc + github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260428205619-2db1389501a1 github.com/smartcontractkit/chainlink-common v0.11.2-0.20260428192532-b1f4aebef94a github.com/smartcontractkit/chainlink-common/keystore v1.1.0 github.com/smartcontractkit/chainlink-deployments-framework v0.98.0 - github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260428180431-40447a80e681 + github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429123911-44d13c62c6e1 github.com/smartcontractkit/chainlink-evm/contracts/cre/gobindings v0.0.0-20260403151002-2c91155b5501 github.com/smartcontractkit/chainlink-evm/gethwrappers v0.0.0-20260421142741-9c7fbaf7c828 - github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20260423135514-5b1a7565a99c github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260420204255-a3f3bdd56877 github.com/smartcontractkit/chainlink-protos/job-distributor v0.18.0 github.com/smartcontractkit/chainlink-protos/orchestrator v0.10.0 - github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428015924-9456bb6d8932 + github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428170719-7ad4e58aaacf github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c github.com/smartcontractkit/chainlink-sui v0.0.0-20260427132612-76b9f754a556 github.com/smartcontractkit/chainlink-sui/deployment v0.0.0-20260427132612-76b9f754a556 @@ -432,6 +431,7 @@ require ( github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20260423135514-5b1a7565a99c // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20260423135514-5b1a7565a99c // indirect github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20260423135514-5b1a7565a99c // indirect + github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20260423135514-5b1a7565a99c // indirect github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20251024234028-0988426d98f4 // indirect github.com/smartcontractkit/chainlink-protos/chainlink-ccv/committee-verifier v0.0.0-20251211142334-5c3421fe2c8d // indirect github.com/smartcontractkit/chainlink-protos/chainlink-ccv/heartbeat v0.0.0-20260115142640-f6b99095c12e // indirect @@ -443,7 +443,7 @@ require ( github.com/smartcontractkit/chainlink-protos/ring/go v0.0.0-20260331131315-f08a616d8dcd // indirect github.com/smartcontractkit/chainlink-protos/rmn/v1.6/go v0.0.0-20250131130834-15e0d4cde2a6 // indirect github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0 // indirect - github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3 // indirect + github.com/smartcontractkit/chainlink-protos/svr v1.2.0 // indirect github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997 // indirect github.com/smartcontractkit/chainlink-testing-framework/parrot v0.6.2 // indirect github.com/smartcontractkit/chainlink-testing-framework/seth v1.51.5 // indirect diff --git a/deployment/go.sum b/deployment/go.sum index 6010dc92152..5ac8e28a9b6 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1383,18 +1383,18 @@ github.com/smartcontractkit/chainlink-aptos v0.0.0-20260424112027-f932111b88ac h github.com/smartcontractkit/chainlink-aptos v0.0.0-20260424112027-f932111b88ac/go.mod h1:ZU57FhGIb+m20yysn2fw+vLh3qB5hcgd06RXEUEDBck= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260423164805-f44aeafa2aaa h1:GE4B480m+/OMgkmZ9mEI1Abh927N7oW+Ruq9uuKIFQw= -github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260423164805-f44aeafa2aaa/go.mod h1:1XxxpkgCmG/z6y30yRuVrcxre6zixIVX3xzi706Db/8= +github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260428205619-2db1389501a1 h1:p0nFrTYrOQzDhWYm6suaM5CoWiXV5NV7llHnp6/Kn/8= +github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260428205619-2db1389501a1/go.mod h1:1XxxpkgCmG/z6y30yRuVrcxre6zixIVX3xzi706Db/8= github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm v0.0.0-20260408145530-22e2d05695cd h1:Jtw6p5iisjXZyFOcBvWh6PDQKtvryrRU2JMmezdutjo= github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm v0.0.0-20260408145530-22e2d05695cd/go.mod h1:zLqdD2kBX7NsntBneclb2yrHhjFaJdoyA8dK5eimlrE= -github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260415165642-49f23e4d76cc h1:dP1ERzdTbiJbHVXfHYdBAi1+8NjgkyQuY2oFNWWWDsQ= -github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:7XR5wfgT8hjSsiV+t0EAWvna+rYQeMPaoZf/0g+dios= +github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260428205619-2db1389501a1 h1:wfiut4oWMcpJmTEl/1ShwMBxwTQEv0wV4/YTma9Otxk= +github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260428205619-2db1389501a1/go.mod h1:hrNuLHgDa2f47WVO6+KgSxM1/SI1M8npQnaiv4kw3xo= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260415165642-49f23e4d76cc h1:mvobZx5JV5PhG/9IXPReV+8mAGnupl0HIWQZ43zxzd4= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:gzCVLUlNov/zFXSC7G6zcGkZU1IfNOHaakbAPDe5Woc= github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260415165642-49f23e4d76cc h1:War93neyFmv7pzuElZeZC3qc/OfGtLvEXvqL3qeBfM0= github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:67YbnoglYD61Pz/jTVCgav9wFq7S35OU8UyQSvPllRw= -github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260415165642-49f23e4d76cc h1:entc0pB4VQEkhJf/ymOfnUh6zcu1sj1OU4YW3iPEW4s= -github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:Ex2OUp35VJuCcRAjuBKwP+cevEPOSjy1pZXm3ncV4kQ= +github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260428205619-2db1389501a1 h1:TEdRdqbGFizjLKI16HiETpzUwyxSYhsJGX+NPk9Tv+o= +github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260428205619-2db1389501a1/go.mod h1:1rndR7UVFakZ6kMWZm1Vs6fFtrroJ4tny66U90fH6FE= github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260428133800-3b1484e8b1fd h1:IMopuENFVS63AerRELdfWo6o60UNUidcldJOxJLmk24= github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260428133800-3b1484e8b1fd/go.mod h1:SBN8Urnh5sQvrQRbSo1Nr8coWatHg8LZoPw3R/42sho= github.com/smartcontractkit/chainlink-common v0.11.2-0.20260428192532-b1f4aebef94a h1:uuJRUD/MHY2hX/f8k8MteJo9jA1+/8KLOCeJOCRSblg= @@ -1409,8 +1409,8 @@ github.com/smartcontractkit/chainlink-data-streams v0.1.13 h1:YOmt545DW6U0SyaqBf github.com/smartcontractkit/chainlink-data-streams v0.1.13/go.mod h1:00aL7OK0BJdF9gn/4t4f/pctUu2VLwwfA8G/tl9rCrM= github.com/smartcontractkit/chainlink-deployments-framework v0.98.0 h1:Ov/KOEtubOHXX8oa9UtARhHmkQNCOIjWNt+Zi0AuzHM= github.com/smartcontractkit/chainlink-deployments-framework v0.98.0/go.mod h1:24dwRW1PYolrlxSth///ddG3auGqR+50xaJiXfUHhkg= -github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260428180431-40447a80e681 h1:ehv4ucho8t5/E/Xg3u7qomdC4gB6IkSHlZx2ZrySaH8= -github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260428180431-40447a80e681/go.mod h1:eOx+FhknhG1+K/pKN77IR/UKmU3WDVaGci64VCGlCUc= +github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429123911-44d13c62c6e1 h1:7H7hiN8Q/bHvsprmA8OqiELGkJmMHYc+MTTOCDKIzm8= +github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429123911-44d13c62c6e1/go.mod h1:lhxIJe+Qy8duvf20q4D8ewfJzwHfvxK/s4s0exG1zEQ= github.com/smartcontractkit/chainlink-evm/contracts/cre/gobindings v0.0.0-20260403151002-2c91155b5501 h1:QJiXTG9CmaQAuMRn5JGi+Jhji7fSkehVnKpjc8oNJJY= github.com/smartcontractkit/chainlink-evm/contracts/cre/gobindings v0.0.0-20260403151002-2c91155b5501/go.mod h1:4cT1BeNF8DAn6In9zr3LayVCv1KzFeuxT7zcuNkfIb0= github.com/smartcontractkit/chainlink-evm/gethwrappers v0.0.0-20260421142741-9c7fbaf7c828 h1:BmsFk/TSHL6dPPR86GTqgSrUXLSINNFC6cfpFRrQX+4= @@ -1453,12 +1453,12 @@ github.com/smartcontractkit/chainlink-protos/rmn/v1.6/go v0.0.0-20250131130834-1 github.com/smartcontractkit/chainlink-protos/rmn/v1.6/go v0.0.0-20250131130834-15e0d4cde2a6/go.mod h1:FRwzI3hGj4CJclNS733gfcffmqQ62ONCkbGi49s658w= github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0 h1:B7itmjy+CMJ26elVw/cAJqqhBQ3Xa/mBYWK0/rQ5MuI= github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0/go.mod h1:h6kqaGajbNRrezm56zhx03p0mVmmA2xxj7E/M4ytLUA= -github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3 h1:X8Pekpv+cy0eW1laZTwATuYLTLZ6gRTxz1ZWOMtU74o= -github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= +github.com/smartcontractkit/chainlink-protos/svr v1.2.0 h1:7jjgqRgORQS/ikL3z0ZgJy95pzjhR9LuU1TVWg4BZ78= +github.com/smartcontractkit/chainlink-protos/svr v1.2.0/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997 h1:W0HKHO8eE8BckTRnhSdqjHKbJcnk068nEWYnWRu6tJY= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997/go.mod h1:GTpDgyK0OObf7jpch6p8N281KxN92wbB8serZhU9yRc= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428015924-9456bb6d8932 h1:aD5KjYqbHiL6OJl3f8tsopVkkAG68UsRJCKjDIACO6w= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428015924-9456bb6d8932/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428170719-7ad4e58aaacf h1:GyBD65Cc4HuwRKZ6k4UCtFaG7njGTnZyR+z3VPm3Vyo= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428170719-7ad4e58aaacf/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c h1:Hn/80PyYFrQhRlNSaq9HY4cjc/7AuP9zyWLle22t34A= github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c/go.mod h1:C5pZsbYX3qkhZTYWr1aYJi9QMfonFAun+Jl1npQ7UJA= github.com/smartcontractkit/chainlink-sui v0.0.0-20260427132612-76b9f754a556 h1:Nz70a+A7aNnWRYdLpGdUf8NeauMvZFOBEPfZTm8vxwI= diff --git a/deployment/utils/nodetestutils/node.go b/deployment/utils/nodetestutils/node.go index f01a9daf0ba..586fcc5bd0e 100644 --- a/deployment/utils/nodetestutils/node.go +++ b/deployment/utils/nodetestutils/node.go @@ -38,11 +38,9 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/keys" evmlptesting "github.com/smartcontractkit/chainlink-evm/pkg/logpoller/testing" "github.com/smartcontractkit/chainlink-evm/pkg/testutils" - mnCfg "github.com/smartcontractkit/chainlink-framework/multinode/config" nodev1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/shared/ptypes" pb "github.com/smartcontractkit/chainlink-protos/orchestrator/feedsmanager" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" sollptesting "github.com/smartcontractkit/chainlink-solana/pkg/solana/logpoller/testing" tonlptesting "github.com/smartcontractkit/chainlink-ton/pkg/logpoller/store/postgres/testing" "github.com/smartcontractkit/chainlink/deployment" @@ -437,7 +435,7 @@ func NewNode( } c.EVM = evmConfigs - var solConfigs solcfg.TOMLConfigs + var solConfigs chainlink.RawConfigs for chainID, chain := range nodecfg.BlockChains.SolanaChains() { solanaChainID, err := chainsel.GetChainIDFromSelector(chainID) if err != nil { @@ -822,39 +820,22 @@ func createConfigV2Chain(chainID uint64) *v2toml.EVMConfig { } } -func createSolanaChainConfig(chainID string, chain cldf_solana.Chain) *solcfg.TOMLConfig { - var chainConfig solcfg.Chain - - // CCIP requires a non-zero execution fee estimate - computeUnitPriceDefault := uint64(100) - txRetentionTimeout := config.MustNewDuration(10 * time.Minute) - chainConfig.ComputeUnitPriceDefault = &computeUnitPriceDefault - chainConfig.TxRetentionTimeout = txRetentionTimeout - skip := true - chainConfig.SkipPreflight = &skip - - url, err := config.ParseURL(chain.URL) - if err != nil { - panic(err) - } - - cfg := &solcfg.TOMLConfig{ - ChainID: &chainID, - Enabled: pointer.To(true), - Chain: chainConfig, - MultiNode: mnCfg.MultiNodeConfig{ - MultiNode: mnCfg.MultiNode{ - VerifyChainID: pointer.To(false), - }, +func createSolanaChainConfig(chainID string, chain cldf_solana.Chain) chainlink.RawConfig { + return chainlink.RawConfig{ + "ChainID": chainID, + "Enabled": true, + "ComputeUnitPriceDefault": uint64(100), + "TxRetentionTimeout": "10m0s", + "SkipPreflight": true, + "MultiNode": map[string]any{ + "VerifyChainID": false, }, - Nodes: []*solcfg.Node{{ - Name: pointer.To("primary"), - URL: url, - SendOnly: false, + "Nodes": []map[string]any{{ + "Name": "primary", + "URL": chain.URL, + "SendOnly": false, }}, } - cfg.SetDefaults() - return cfg } func setupJD(t *testing.T, app chainlink.Application) { diff --git a/devenv/README.md b/devenv/README.md index 5d82c65b1c2..8ab9c3b3974 100644 --- a/devenv/README.md +++ b/devenv/README.md @@ -67,7 +67,6 @@ Each row maps to a CI matrix entry in [devenv-nightly.yml](../.github/workflows/ | VRF | `cl u env.toml,products/vrf/basic.toml` | `go test -v -timeout 10m -run TestVRFBasic\|TestVRFJobReplacement` | `vrf` | | Automation 2.0 | `cl u env.toml,products/automation/basic.toml` | `go test -v -timeout 30m -run TestRegistry_2_0` | `automation` | | Automation 2.1 | `cl u env.toml,products/automation/basic.toml` | `go test -v -timeout 30m -run TestRegistry_2_1` | `automation` | -| Keepers | `cl u env.toml,products/keepers/basic.toml` | `go test -v -timeout 1h -run TestKeeperBasic` | `keepers` | | OCR2 Smoke | `cl u env.toml,products/ocr2/basic.toml` | `go test -v -run TestSmoke` | `ocr2` | | OCR2 Soak | `cl u env.toml,products/ocr2/basic.toml,products/ocr2/soak.toml; cl obs up -f` | `go test -v -timeout 4h -run TestOCR2Soak/clean` | `ocr2` | diff --git a/devenv/contracts/automation.go b/devenv/contracts/automation.go index d3312823a91..eba1fab4a20 100644 --- a/devenv/contracts/automation.go +++ b/devenv/contracts/automation.go @@ -36,15 +36,10 @@ import ( "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/i_automation_registry_master_wrapper_2_3" "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/i_chain_module" "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registrar_wrapper1_2" "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registrar_wrapper2_0" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_logic1_3" "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_logic2_0" registrylogica21 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_logic_a_wrapper_2_1" registrylogicb21 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_logic_b_wrapper_2_1" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_1" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_2" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_3" "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper2_0" registry21 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper_2_1" "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/log_triggered_streams_lookup_wrapper" @@ -117,9 +112,6 @@ func LoadUpkeepTranscoder(client *seth.Client, address common.Address) (*Ethereu type EthereumKeeperRegistry struct { client *seth.Client version KeeperRegistryVersion - registry1_1 *keeper_registry_wrapper1_1.KeeperRegistry - registry1_2 *keeper_registry_wrapper1_2.KeeperRegistry - registry1_3 *keeper_registry_wrapper1_3.KeeperRegistry registry2_0 *keeper_registry_wrapper2_0.KeeperRegistry registry2_1 *i_keeper_registry_master_wrapper_2_1.IKeeperRegistryMaster registry2_2 *i_automation_registry_master_wrapper_2_2.IAutomationRegistryMaster @@ -168,8 +160,6 @@ func (v *EthereumKeeperRegistry) RegistryOwnerAddress() common.Address { case RegistryVersion_2_0: ownerAddress, _ := v.registry2_0.Owner(callOpts) return ownerAddress - case RegistryVersion_1_0, RegistryVersion_1_1, RegistryVersion_1_2, RegistryVersion_1_3: - return v.client.MustGetRootKeyAddress() default: return v.client.MustGetRootKeyAddress() } @@ -219,69 +209,8 @@ func (v *EthereumKeeperRegistry) SetConfigTypeSafe(ocrConfig OCRv2Config) error func (v *EthereumKeeperRegistry) SetConfig(config KeeperRegistrySettings, ocrConfig OCRv2Config) error { txOpts := v.client.NewTXOpts() - callOpts := bind.CallOpts{ - From: v.client.MustGetRootKeyAddress(), - Context: nil, - } switch v.version { - case RegistryVersion_1_0, RegistryVersion_1_1: - _, err := v.client.Decode(v.registry1_1.SetConfig( - txOpts, - config.PaymentPremiumPPB, - config.FlatFeeMicroLINK, - config.BlockCountPerTurn, - config.CheckGasLimit, - config.StalenessSeconds, - config.GasCeilingMultiplier, - config.FallbackGasPrice, - config.FallbackLinkPrice, - )) - return err - case RegistryVersion_1_2: - state, err := v.registry1_2.GetState(&callOpts) - if err != nil { - return err - } - - _, err = v.client.Decode(v.registry1_2.SetConfig(txOpts, keeper_registry_wrapper1_2.Config{ - PaymentPremiumPPB: config.PaymentPremiumPPB, - FlatFeeMicroLink: config.FlatFeeMicroLINK, - BlockCountPerTurn: config.BlockCountPerTurn, - CheckGasLimit: config.CheckGasLimit, - StalenessSeconds: config.StalenessSeconds, - GasCeilingMultiplier: config.GasCeilingMultiplier, - MinUpkeepSpend: config.MinUpkeepSpend, - MaxPerformGas: config.MaxPerformGas, - FallbackGasPrice: config.FallbackGasPrice, - FallbackLinkPrice: config.FallbackLinkPrice, - // Keep the transcoder and registrar same. They have separate setters - Transcoder: state.Config.Transcoder, - Registrar: state.Config.Registrar, - })) - return err - case RegistryVersion_1_3: - state, err := v.registry1_3.GetState(&callOpts) - if err != nil { - return err - } - - _, err = v.client.Decode(v.registry1_3.SetConfig(txOpts, keeper_registry_wrapper1_3.Config{ - PaymentPremiumPPB: config.PaymentPremiumPPB, - FlatFeeMicroLink: config.FlatFeeMicroLINK, - BlockCountPerTurn: config.BlockCountPerTurn, - CheckGasLimit: config.CheckGasLimit, - StalenessSeconds: config.StalenessSeconds, - GasCeilingMultiplier: config.GasCeilingMultiplier, - MinUpkeepSpend: config.MinUpkeepSpend, - MaxPerformGas: config.MaxPerformGas, - FallbackGasPrice: config.FallbackGasPrice, - FallbackLinkPrice: config.FallbackLinkPrice, - // Keep the transcoder and registrar same. They have separate setters - Transcoder: state.Config.Transcoder, - Registrar: state.Config.Registrar, - })) - return err case RegistryVersion_2_0: _, err := v.client.Decode(v.registry2_0.SetConfig(txOpts, ocrConfig.Signers, @@ -324,12 +253,6 @@ func (v *EthereumKeeperRegistry) Pause() error { var err error switch v.version { - case RegistryVersion_1_0, RegistryVersion_1_1: - _, err = v.client.Decode(v.registry1_1.Pause(txOpts)) - case RegistryVersion_1_2: - _, err = v.client.Decode(v.registry1_2.Pause(txOpts)) - case RegistryVersion_1_3: - _, err = v.client.Decode(v.registry1_3.Pause(txOpts)) case RegistryVersion_2_0: _, err = v.client.Decode(v.registry2_0.Pause(txOpts)) case RegistryVersion_2_1: @@ -350,12 +273,6 @@ func (v *EthereumKeeperRegistry) Unpause() error { var err error switch v.version { - case RegistryVersion_1_0, RegistryVersion_1_1: - _, err = v.client.Decode(v.registry1_1.Unpause(txOpts)) - case RegistryVersion_1_2: - _, err = v.client.Decode(v.registry1_2.Unpause(txOpts)) - case RegistryVersion_1_3: - _, err = v.client.Decode(v.registry1_3.Unpause(txOpts)) case RegistryVersion_2_0: _, err = v.client.Decode(v.registry2_0.Unpause(txOpts)) case RegistryVersion_2_1: @@ -371,63 +288,23 @@ func (v *EthereumKeeperRegistry) Unpause() error { return err } -// Migrate performs a migration of the given upkeep ids to the specific destination passed as parameter. -func (v *EthereumKeeperRegistry) Migrate(upkeepIDs []*big.Int, destinationAddress common.Address) error { - if v.version != RegistryVersion_1_2 { - return errors.New("migration of upkeeps is only available for version 1.2 of the registries") - } - - _, err := v.client.Decode(v.registry1_2.MigrateUpkeeps(v.client.NewTXOpts(), upkeepIDs, destinationAddress)) - return err +// Migrate performed migrations from keeper registry 1.2, which is no longer supported. +func (v *EthereumKeeperRegistry) Migrate(_ []*big.Int, _ common.Address) error { + return errors.New("migration of upkeeps from keeper registry 1.2 is no longer supported") } -// SetMigrationPermissions sets the permissions of another registry to allow migrations between the two. -func (v *EthereumKeeperRegistry) SetMigrationPermissions(peerAddress common.Address, permission uint8) error { - if v.version != RegistryVersion_1_2 { - return errors.New("migration of upkeeps is only available for version 1.2 of the registries") - } - - _, err := v.client.Decode(v.registry1_2.SetPeerRegistryMigrationPermission(v.client.NewTXOpts(), peerAddress, permission)) - return err +// SetMigrationPermissions was only used for keeper registry 1.2 migrations. +func (v *EthereumKeeperRegistry) SetMigrationPermissions(_ common.Address, _ uint8) error { + return errors.New("migration of upkeeps from keeper registry 1.2 is no longer supported") } -func (v *EthereumKeeperRegistry) SetRegistrar(registrarAddr string) error { +func (v *EthereumKeeperRegistry) SetRegistrar(_ string) error { if v.version == RegistryVersion_2_0 { // we short circuit and exit, so we don't create a new txs messing up the nonce before exiting return errors.New("please use set config") } - txOpts := v.client.NewTXOpts() - callOpts := bind.CallOpts{ - From: v.client.MustGetRootKeyAddress(), - Context: nil, - } - - switch v.version { - case RegistryVersion_1_0, RegistryVersion_1_1: - _, err := v.client.Decode(v.registry1_1.SetRegistrar(txOpts, common.HexToAddress(registrarAddr))) - return err - case RegistryVersion_1_2: - state, err := v.registry1_2.GetState(&callOpts) - if err != nil { - return err - } - newConfig := state.Config - newConfig.Registrar = common.HexToAddress(registrarAddr) - _, err = v.client.Decode(v.registry1_2.SetConfig(txOpts, newConfig)) - return err - case RegistryVersion_1_3: - state, err := v.registry1_3.GetState(&callOpts) - if err != nil { - return err - } - newConfig := state.Config - newConfig.Registrar = common.HexToAddress(registrarAddr) - _, err = v.client.Decode(v.registry1_3.SetConfig(txOpts, newConfig)) - return err - default: - return fmt.Errorf("keeper registry version %d is not supported", v.version) - } + return fmt.Errorf("keeper registry version %d is not supported", v.version) } // AddUpkeepFunds adds link for particular upkeep id @@ -436,12 +313,6 @@ func (v *EthereumKeeperRegistry) AddUpkeepFundsFromKey(id *big.Int, amount *big. var err error switch v.version { - case RegistryVersion_1_0, RegistryVersion_1_1: - _, err = v.client.Decode(v.registry1_1.AddFunds(opts, id, amount)) - case RegistryVersion_1_2: - _, err = v.client.Decode(v.registry1_2.AddFunds(opts, id, amount)) - case RegistryVersion_1_3: - _, err = v.client.Decode(v.registry1_3.AddFunds(opts, id, amount)) case RegistryVersion_2_0: _, err = v.client.Decode(v.registry2_0.AddFunds(opts, id, amount)) case RegistryVersion_2_1: @@ -468,48 +339,6 @@ func (v *EthereumKeeperRegistry) GetUpkeepInfo(ctx context.Context, id *big.Int) } switch v.version { - case RegistryVersion_1_0, RegistryVersion_1_1: - uk, err := v.registry1_1.GetUpkeep(opts, id) - if err != nil { - return nil, err - } - return &UpkeepInfo{ - Target: uk.Target.Hex(), - ExecuteGas: uk.ExecuteGas, - CheckData: uk.CheckData, - Balance: uk.Balance, - LastKeeper: uk.LastKeeper.Hex(), - Admin: uk.Admin.Hex(), - MaxValidBlocknumber: uk.MaxValidBlocknumber, - }, nil - case RegistryVersion_1_2: - uk, err := v.registry1_2.GetUpkeep(opts, id) - if err != nil { - return nil, err - } - return &UpkeepInfo{ - Target: uk.Target.Hex(), - ExecuteGas: uk.ExecuteGas, - CheckData: uk.CheckData, - Balance: uk.Balance, - LastKeeper: uk.LastKeeper.Hex(), - Admin: uk.Admin.Hex(), - MaxValidBlocknumber: uk.MaxValidBlocknumber, - }, nil - case RegistryVersion_1_3: - uk, err := v.registry1_3.GetUpkeep(opts, id) - if err != nil { - return nil, err - } - return &UpkeepInfo{ - Target: uk.Target.Hex(), - ExecuteGas: uk.ExecuteGas, - CheckData: uk.CheckData, - Balance: uk.Balance, - LastKeeper: uk.LastKeeper.Hex(), - Admin: uk.Admin.Hex(), - MaxValidBlocknumber: uk.MaxValidBlocknumber, - }, nil case RegistryVersion_2_0: uk, err := v.registry2_0.GetUpkeep(opts, id) if err != nil { @@ -591,38 +420,8 @@ func (v *EthereumKeeperRegistry) getUpkeepInfo23(opts *bind.CallOpts, id *big.In }, nil } -func (v *EthereumKeeperRegistry) GetKeeperInfo(ctx context.Context, keeperAddr string) (*KeeperInfo, error) { - opts := &bind.CallOpts{ - From: v.client.MustGetRootKeyAddress(), - Context: ctx, - } - var info struct { - Payee common.Address - Active bool - Balance *big.Int - } - var err error - - switch v.version { - case RegistryVersion_1_0, RegistryVersion_1_1: - info, err = v.registry1_1.GetKeeperInfo(opts, common.HexToAddress(keeperAddr)) - case RegistryVersion_1_2: - info, err = v.registry1_2.GetKeeperInfo(opts, common.HexToAddress(keeperAddr)) - case RegistryVersion_1_3: - info, err = v.registry1_3.GetKeeperInfo(opts, common.HexToAddress(keeperAddr)) - case RegistryVersion_2_0, RegistryVersion_2_1, RegistryVersion_2_2, RegistryVersion_2_3: - // this is not used anywhere - return nil, errors.New("not supported") - } - - if err != nil { - return nil, err - } - return &KeeperInfo{ - Payee: info.Payee.Hex(), - Active: info.Active, - Balance: info.Balance, - }, nil +func (v *EthereumKeeperRegistry) GetKeeperInfo(_ context.Context, _ string) (*KeeperInfo, error) { + return nil, errors.New("not supported") } func (v *EthereumKeeperRegistry) SetKeepers(keepers []string, payees []string, ocrConfig OCRv2Config) error { @@ -639,12 +438,6 @@ func (v *EthereumKeeperRegistry) SetKeepers(keepers []string, payees []string, o } switch v.version { - case RegistryVersion_1_0, RegistryVersion_1_1: - _, err = v.client.Decode(v.registry1_1.SetKeepers(opts, keepersAddresses, payeesAddresses)) - case RegistryVersion_1_2: - _, err = v.client.Decode(v.registry1_2.SetKeepers(opts, keepersAddresses, payeesAddresses)) - case RegistryVersion_1_3: - _, err = v.client.Decode(v.registry1_3.SetKeepers(opts, keepersAddresses, payeesAddresses)) case RegistryVersion_2_0: _, err = v.client.Decode(v.registry2_0.SetConfig(opts, ocrConfig.Signers, @@ -667,30 +460,6 @@ func (v *EthereumKeeperRegistry) RegisterUpkeep(target string, gasLimit uint32, var err error switch v.version { - case RegistryVersion_1_0, RegistryVersion_1_1: - _, err = v.client.Decode(v.registry1_1.RegisterUpkeep( - opts, - common.HexToAddress(target), - gasLimit, - common.HexToAddress(admin), - checkData, - )) - case RegistryVersion_1_2: - _, err = v.client.Decode(v.registry1_2.RegisterUpkeep( - opts, - common.HexToAddress(target), - gasLimit, - common.HexToAddress(admin), - checkData, - )) - case RegistryVersion_1_3: - _, err = v.client.Decode(v.registry1_3.RegisterUpkeep( - opts, - common.HexToAddress(target), - gasLimit, - common.HexToAddress(admin), - checkData, - )) case RegistryVersion_2_0: _, err = v.client.Decode(v.registry2_0.RegisterUpkeep( opts, @@ -714,12 +483,6 @@ func (v *EthereumKeeperRegistry) CancelUpkeep(id *big.Int) error { var tx *seth.DecodedTransaction switch v.version { - case RegistryVersion_1_0, RegistryVersion_1_1: - tx, err = v.client.Decode(v.registry1_1.CancelUpkeep(opts, id)) - case RegistryVersion_1_2: - tx, err = v.client.Decode(v.registry1_2.CancelUpkeep(opts, id)) - case RegistryVersion_1_3: - tx, err = v.client.Decode(v.registry1_3.CancelUpkeep(opts, id)) case RegistryVersion_2_0: tx, err = v.client.Decode(v.registry2_0.CancelUpkeep(opts, id)) case RegistryVersion_2_1: @@ -750,10 +513,6 @@ func (v *EthereumKeeperRegistry) SetUpkeepGasLimit(id *big.Int, gas uint32) erro var err error switch v.version { - case RegistryVersion_1_2: - _, err = v.client.Decode(v.registry1_2.SetUpkeepGasLimit(opts, id, gas)) - case RegistryVersion_1_3: - _, err = v.client.Decode(v.registry1_3.SetUpkeepGasLimit(opts, id, gas)) case RegistryVersion_2_0: _, err = v.client.Decode(v.registry2_0.SetUpkeepGasLimit(opts, id, gas)) case RegistryVersion_2_1: @@ -779,20 +538,6 @@ func (v *EthereumKeeperRegistry) GetKeeperList(ctx context.Context) ([]string, e var err error switch v.version { - case RegistryVersion_1_0, RegistryVersion_1_1: - list, err = v.registry1_1.GetKeeperList(opts) - case RegistryVersion_1_2: - state, err := v.registry1_2.GetState(opts) - if err != nil { - return []string{}, err - } - list = state.Keepers - case RegistryVersion_1_3: - state, err := v.registry1_3.GetState(opts) - if err != nil { - return []string{}, err - } - list = state.Keepers case RegistryVersion_2_0: state, err := v.registry2_0.GetState(opts) if err != nil { @@ -801,6 +546,8 @@ func (v *EthereumKeeperRegistry) GetKeeperList(ctx context.Context) ([]string, e list = state.Transmitters case RegistryVersion_2_1, RegistryVersion_2_2, RegistryVersion_2_3: return nil, errors.New("not supported") + default: + return nil, fmt.Errorf("keeper registry version %d is not supported", v.version) } if err != nil { @@ -819,8 +566,6 @@ func (v *EthereumKeeperRegistry) UpdateCheckData(id *big.Int, newCheckData []byt var err error switch v.version { - case RegistryVersion_1_3: - _, err = v.client.Decode(v.registry1_3.UpdateCheckData(opts, id, newCheckData)) case RegistryVersion_2_0: _, err = v.client.Decode(v.registry2_0.UpdateCheckData(opts, id, newCheckData)) case RegistryVersion_2_1: @@ -880,8 +625,6 @@ func (v *EthereumKeeperRegistry) PauseUpkeep(id *big.Int) error { var err error switch v.version { - case RegistryVersion_1_3: - _, err = v.client.Decode(v.registry1_3.PauseUpkeep(opts, id)) case RegistryVersion_2_0: _, err = v.client.Decode(v.registry2_0.PauseUpkeep(opts, id)) case RegistryVersion_2_1: @@ -903,8 +646,6 @@ func (v *EthereumKeeperRegistry) UnpauseUpkeep(id *big.Int) error { var err error switch v.version { - case RegistryVersion_1_3: - _, err = v.client.Decode(v.registry1_3.UnpauseUpkeep(opts, id)) case RegistryVersion_2_0: _, err = v.client.Decode(v.registry2_0.UnpauseUpkeep(opts, id)) case RegistryVersion_2_1: @@ -923,36 +664,6 @@ func (v *EthereumKeeperRegistry) UnpauseUpkeep(id *big.Int) error { // Parses upkeep performed log func (v *EthereumKeeperRegistry) ParseUpkeepPerformedLog(log *types.Log) (*UpkeepPerformedLog, error) { switch v.version { - case RegistryVersion_1_0, RegistryVersion_1_1: - parsedLog, err := v.registry1_1.ParseUpkeepPerformed(*log) - if err != nil { - return nil, err - } - return &UpkeepPerformedLog{ - ID: parsedLog.Id, - Success: parsedLog.Success, - From: parsedLog.From, - }, nil - case RegistryVersion_1_2: - parsedLog, err := v.registry1_2.ParseUpkeepPerformed(*log) - if err != nil { - return nil, err - } - return &UpkeepPerformedLog{ - ID: parsedLog.Id, - Success: parsedLog.Success, - From: parsedLog.From, - }, nil - case RegistryVersion_1_3: - parsedLog, err := v.registry1_3.ParseUpkeepPerformed(*log) - if err != nil { - return nil, err - } - return &UpkeepPerformedLog{ - ID: parsedLog.Id, - Success: parsedLog.Success, - From: parsedLog.From, - }, nil case RegistryVersion_2_0: parsedLog, err := v.registry2_0.ParseUpkeepPerformed(*log) if err != nil { @@ -1040,24 +751,6 @@ func (v *EthereumKeeperRegistry) ParseStaleUpkeepReportLog(log *types.Log) (*Sta // Parses the upkeep ID from an 'UpkeepRegistered' log, returns error on any other log func (v *EthereumKeeperRegistry) ParseUpkeepIDFromRegisteredLog(log *types.Log) (*big.Int, error) { switch v.version { - case RegistryVersion_1_0, RegistryVersion_1_1: - parsedLog, err := v.registry1_1.ParseUpkeepRegistered(*log) - if err != nil { - return nil, err - } - return parsedLog.Id, nil - case RegistryVersion_1_2: - parsedLog, err := v.registry1_2.ParseUpkeepRegistered(*log) - if err != nil { - return nil, err - } - return parsedLog.Id, nil - case RegistryVersion_1_3: - parsedLog, err := v.registry1_3.ParseUpkeepRegistered(*log) - if err != nil { - return nil, err - } - return parsedLog.Id, nil case RegistryVersion_2_0: parsedLog, err := v.registry2_0.ParseUpkeepRegistered(*log) if err != nil { @@ -1105,14 +798,7 @@ func DeployKeeperRegistry( // default: // mode = uint8(0) // } - registryGasOverhead := big.NewInt(80000) switch opts.RegistryVersion { - case RegistryVersion_1_0, RegistryVersion_1_1: - return deployRegistry10_11(client, opts) - case RegistryVersion_1_2: - return deployRegistry12(client, opts) - case RegistryVersion_1_3: - return deployRegistry13(client, opts, mode, registryGasOverhead) case RegistryVersion_2_0: return deployRegistry20(client, opts, mode) case RegistryVersion_2_1: @@ -1126,141 +812,6 @@ func DeployKeeperRegistry( } } -func deployRegistry10_11(client *seth.Client, opts *KeeperRegistryOpts) (KeeperRegistry, error) { - abi, err := keeper_registry_wrapper1_1.KeeperRegistryMetaData.GetAbi() - if err != nil { - return &EthereumKeeperRegistry{}, fmt.Errorf("failed to get KeeperRegistry1_1 ABI: %w", err) - } - data, err := client.DeployContract(client.NewTXOpts(), "KeeperRegistry1_1", *abi, common.FromHex(keeper_registry_wrapper1_1.KeeperRegistryMetaData.Bin), - common.HexToAddress(opts.LinkAddr), - common.HexToAddress(opts.ETHFeedAddr), - common.HexToAddress(opts.GasFeedAddr), - opts.Settings.PaymentPremiumPPB, - opts.Settings.FlatFeeMicroLINK, - opts.Settings.BlockCountPerTurn, - opts.Settings.CheckGasLimit, - opts.Settings.StalenessSeconds, - opts.Settings.GasCeilingMultiplier, - opts.Settings.FallbackGasPrice, - opts.Settings.FallbackLinkPrice, - ) - if err != nil { - return &EthereumKeeperRegistry{}, fmt.Errorf("KeeperRegistry1_1 instance deployment have failed: %w", err) - } - - instance, err := keeper_registry_wrapper1_1.NewKeeperRegistry(data.Address, MustNewWrappedContractBackend(nil, client)) - if err != nil { - return &EthereumKeeperRegistry{}, fmt.Errorf("failed to instantiate KeeperRegistry1_1 instance: %w", err) - } - - return &EthereumKeeperRegistry{ - client: client, - version: RegistryVersion_1_1, - registry1_1: instance, - registry1_2: nil, - registry1_3: nil, - address: &data.Address, - }, err -} - -func deployRegistry12(client *seth.Client, opts *KeeperRegistryOpts) (KeeperRegistry, error) { - abi, err := keeper_registry_wrapper1_2.KeeperRegistryMetaData.GetAbi() - if err != nil { - return &EthereumKeeperRegistry{}, fmt.Errorf("failed to get KeeperRegistry1_2 ABI: %w", err) - } - data, err := client.DeployContract(client.NewTXOpts(), "KeeperRegistry1_2", *abi, common.FromHex(keeper_registry_wrapper1_2.KeeperRegistryMetaData.Bin), - common.HexToAddress(opts.LinkAddr), - common.HexToAddress(opts.ETHFeedAddr), - common.HexToAddress(opts.GasFeedAddr), - keeper_registry_wrapper1_2.Config{ - PaymentPremiumPPB: opts.Settings.PaymentPremiumPPB, - FlatFeeMicroLink: opts.Settings.FlatFeeMicroLINK, - BlockCountPerTurn: opts.Settings.BlockCountPerTurn, - CheckGasLimit: opts.Settings.CheckGasLimit, - StalenessSeconds: opts.Settings.StalenessSeconds, - GasCeilingMultiplier: opts.Settings.GasCeilingMultiplier, - MinUpkeepSpend: opts.Settings.MinUpkeepSpend, - MaxPerformGas: opts.Settings.MaxPerformGas, - FallbackGasPrice: opts.Settings.FallbackGasPrice, - FallbackLinkPrice: opts.Settings.FallbackLinkPrice, - Transcoder: common.HexToAddress(opts.TranscoderAddr), - Registrar: common.HexToAddress(opts.RegistrarAddr), - }, - ) - if err != nil { - return &EthereumKeeperRegistry{}, fmt.Errorf("KeeperRegistry1_2 instance deployment have failed: %w", err) - } - - instance, err := keeper_registry_wrapper1_2.NewKeeperRegistry(data.Address, MustNewWrappedContractBackend(nil, client)) - if err != nil { - return &EthereumKeeperRegistry{}, fmt.Errorf("failed to instantiate KeeperRegistry1_2 instance: %w", err) - } - return &EthereumKeeperRegistry{ - client: client, - version: RegistryVersion_1_2, - registry1_1: nil, - registry1_2: instance, - registry1_3: nil, - address: &data.Address, - }, err -} - -func deployRegistry13(client *seth.Client, opts *KeeperRegistryOpts, mode uint8, registryGasOverhead *big.Int) (KeeperRegistry, error) { - logicAbi, err := keeper_registry_logic1_3.KeeperRegistryLogicMetaData.GetAbi() - if err != nil { - return &EthereumKeeperRegistry{}, fmt.Errorf("failed to get KeeperRegistryLogic1_3 ABI: %w", err) - } - logicData, err := client.DeployContract(client.NewTXOpts(), "KeeperRegistryLogic1_3", *logicAbi, common.FromHex(keeper_registry_logic1_3.KeeperRegistryLogicMetaData.Bin), - mode, // Default payment model - registryGasOverhead, // Registry gas overhead - common.HexToAddress(opts.LinkAddr), - common.HexToAddress(opts.ETHFeedAddr), - common.HexToAddress(opts.GasFeedAddr), - ) - if err != nil { - return &EthereumKeeperRegistry{}, fmt.Errorf("KeeperRegistryLogic1_3 instance deployment have failed: %w", err) - } - - abi, err := keeper_registry_wrapper1_3.KeeperRegistryMetaData.GetAbi() - if err != nil { - return &EthereumKeeperRegistry{}, fmt.Errorf("failed to get KeeperRegistry1_3 ABI: %w", err) - } - data, err := client.DeployContract(client.NewTXOpts(), "KeeperRegistry1_3", *abi, common.FromHex(keeper_registry_wrapper1_3.KeeperRegistryMetaData.Bin), - logicData.Address, - keeper_registry_wrapper1_3.Config{ - PaymentPremiumPPB: opts.Settings.PaymentPremiumPPB, - FlatFeeMicroLink: opts.Settings.FlatFeeMicroLINK, - BlockCountPerTurn: opts.Settings.BlockCountPerTurn, - CheckGasLimit: opts.Settings.CheckGasLimit, - StalenessSeconds: opts.Settings.StalenessSeconds, - GasCeilingMultiplier: opts.Settings.GasCeilingMultiplier, - MinUpkeepSpend: opts.Settings.MinUpkeepSpend, - MaxPerformGas: opts.Settings.MaxPerformGas, - FallbackGasPrice: opts.Settings.FallbackGasPrice, - FallbackLinkPrice: opts.Settings.FallbackLinkPrice, - Transcoder: common.HexToAddress(opts.TranscoderAddr), - Registrar: common.HexToAddress(opts.RegistrarAddr), - }, - ) - if err != nil { - return &EthereumKeeperRegistry{}, fmt.Errorf("KeeperRegistry1_3 instance deployment have failed: %w", err) - } - - instance, err := keeper_registry_wrapper1_3.NewKeeperRegistry(data.Address, MustNewWrappedContractBackend(nil, client)) - if err != nil { - return &EthereumKeeperRegistry{}, fmt.Errorf("failed to instantiate KeeperRegistry1_3 instance: %w", err) - } - - return &EthereumKeeperRegistry{ - client: client, - version: RegistryVersion_1_3, - registry1_1: nil, - registry1_2: nil, - registry1_3: instance, - address: &data.Address, - }, err -} - func deployRegistry20(client *seth.Client, opts *KeeperRegistryOpts, mode uint8) (KeeperRegistry, error) { logicAbi, err := keeper_registry_logic2_0.KeeperRegistryLogicMetaData.GetAbi() if err != nil { @@ -1278,7 +829,7 @@ func deployRegistry20(client *seth.Client, opts *KeeperRegistryOpts, mode uint8) abi, err := keeper_registry_wrapper2_0.KeeperRegistryMetaData.GetAbi() if err != nil { - return &EthereumKeeperRegistry{}, fmt.Errorf("failed to get KeeperRegistry1_3 ABI: %w", err) + return &EthereumKeeperRegistry{}, fmt.Errorf("failed to get KeeperRegistry2_0 ABI: %w", err) } data, err := client.DeployContract(client.NewTXOpts(), "KeeperRegistry2_0", *abi, common.FromHex(keeper_registry_wrapper2_0.KeeperRegistryMetaData.Bin), logicData.Address, @@ -1545,12 +1096,6 @@ func LoadKeeperRegistry(l zerolog.Logger, client *seth.Client, address common.Ad var keeper *EthereumKeeperRegistry var err error switch registryVersion { - case RegistryVersion_1_1: - keeper, err = loadRegistry1_1(client, address) - case RegistryVersion_1_2: - keeper, err = loadRegistry1_2(client, address) - case RegistryVersion_1_3: - keeper, err = loadRegistry1_3(client, address) case RegistryVersion_2_0: keeper, err = loadRegistry2_0(client, address) case RegistryVersion_2_1: @@ -1570,69 +1115,6 @@ func LoadKeeperRegistry(l zerolog.Logger, client *seth.Client, address common.Ad return keeper, err } -func loadRegistry1_1(client *seth.Client, address common.Address) (*EthereumKeeperRegistry, error) { - abi, err := keeper_registry_wrapper1_1.KeeperRegistryMetaData.GetAbi() - if err != nil { - return &EthereumKeeperRegistry{}, fmt.Errorf("failed to get KeeperRegistry1_1 ABI: %w", err) - } - - client.ContractStore.AddABI("KeeperRegistry1_1", *abi) - client.ContractStore.AddBIN("KeeperRegistry1_1", common.FromHex(keeper_registry_wrapper1_1.KeeperRegistryMetaData.Bin)) - - instance, err := keeper_registry_wrapper1_1.NewKeeperRegistry(address, MustNewWrappedContractBackend(nil, client)) - if err != nil { - return &EthereumKeeperRegistry{}, fmt.Errorf("failed to instantiate KeeperRegistry1_1 instance: %w", err) - } - - return &EthereumKeeperRegistry{ - address: &address, - client: client, - registry1_1: instance, - }, nil -} - -func loadRegistry1_2(client *seth.Client, address common.Address) (*EthereumKeeperRegistry, error) { - abi, err := keeper_registry_wrapper1_2.KeeperRegistryMetaData.GetAbi() - if err != nil { - return &EthereumKeeperRegistry{}, fmt.Errorf("failed to get KeeperRegistry1_2 ABI: %w", err) - } - - client.ContractStore.AddABI("KeeperRegistry1_2", *abi) - client.ContractStore.AddBIN("KeeperRegistry1_2", common.FromHex(keeper_registry_wrapper1_2.KeeperRegistryMetaData.Bin)) - - instance, err := keeper_registry_wrapper1_2.NewKeeperRegistry(address, MustNewWrappedContractBackend(nil, client)) - if err != nil { - return &EthereumKeeperRegistry{}, fmt.Errorf("failed to instantiate KeeperRegistry1_2 instance: %w", err) - } - - return &EthereumKeeperRegistry{ - address: &address, - client: client, - registry1_2: instance, - }, nil -} - -func loadRegistry1_3(client *seth.Client, address common.Address) (*EthereumKeeperRegistry, error) { - abi, err := keeper_registry_wrapper1_3.KeeperRegistryMetaData.GetAbi() - if err != nil { - return &EthereumKeeperRegistry{}, fmt.Errorf("failed to get KeeperRegistry1_3 ABI: %w", err) - } - - client.ContractStore.AddABI("KeeperRegistry1_3", *abi) - client.ContractStore.AddBIN("KeeperRegistry1_3", common.FromHex(keeper_registry_wrapper1_3.KeeperRegistryMetaData.Bin)) - - instance, err := keeper_registry_wrapper1_3.NewKeeperRegistry(address, MustNewWrappedContractBackend(nil, client)) - if err != nil { - return &EthereumKeeperRegistry{}, fmt.Errorf("failed to instantiate KeeperRegistry1_3 instance: %w", err) - } - - return &EthereumKeeperRegistry{ - address: &address, - client: client, - registry1_3: instance, - }, nil -} - func loadRegistry2_0(client *seth.Client, address common.Address) (*EthereumKeeperRegistry, error) { abi, err := keeper_registry_wrapper2_0.KeeperRegistryMetaData.GetAbi() if err != nil { @@ -1805,7 +1287,6 @@ func deployBaseModule(client *seth.Client) (common.Address, error) { // registering new upkeeps. type EthereumKeeperRegistrar struct { client *seth.Client - registrar *keeper_registrar_wrapper1_2.KeeperRegistrar registrar20 *keeper_registrar_wrapper2_0.KeeperRegistrar registrar21 *registrar21.AutomationRegistrar registrar23 *registrar23.AutomationRegistrar @@ -2063,29 +1544,8 @@ func (v *EthereumKeeperRegistrar) EncodeRegisterRequest(name string, email []byt return encodedRegistrationParamsStruct, err default: - // ok, nothing to do + return nil, errors.New("EncodeRegisterRequest: no supported automation registrar loaded (expected 2.0/2.1/2.3)") } - - registryABI, err := abi.JSON(strings.NewReader(keeper_registrar_wrapper1_2.KeeperRegistrarMetaData.ABI)) - if err != nil { - return nil, err - } - req, err := registryABI.Pack( - "register", - name, - email, - common.HexToAddress(upkeepAddr), - gasLimit, - common.HexToAddress(adminAddr), - checkData, - amount, - source, - common.HexToAddress(senderAddr), - ) - if err != nil { - return nil, err - } - return req, nil } func DeployKeeperRegistrar(client *seth.Client, registryVersion KeeperRegistryVersion, linkAddr string, registrarSettings KeeperRegistrarSettings) (KeeperRegistrar, error) { @@ -2194,53 +1654,13 @@ func DeployKeeperRegistrar(client *seth.Client, registryVersion KeeperRegistryVe address: &data.Address, }, nil default: - // ok, nothing to do - } - - // non OCR registrar - abi, err := keeper_registrar_wrapper1_2.KeeperRegistrarMetaData.GetAbi() - if err != nil { - return &EthereumKeeperRegistrar{}, fmt.Errorf("failed to get KeeperRegistrar1_2 ABI: %w", err) - } - - data, err := client.DeployContract(client.NewTXOpts(), "KeeperRegistrar1_2", *abi, common.FromHex(keeper_registrar_wrapper1_2.KeeperRegistrarMetaData.Bin), - common.HexToAddress(linkAddr), - registrarSettings.AutoApproveConfigType, - registrarSettings.AutoApproveMaxAllowed, - common.HexToAddress(registrarSettings.RegistryAddr), - registrarSettings.MinLinkJuels, - ) - if err != nil { - return &EthereumKeeperRegistrar{}, fmt.Errorf("KeeperRegistrar1_2 instance deployment have failed: %w", err) + return nil, fmt.Errorf("unsupported keeper registry version for registrar deployment: %v", registryVersion) } - - instance, err := keeper_registrar_wrapper1_2.NewKeeperRegistrar(data.Address, MustNewWrappedContractBackend(nil, client)) - if err != nil { - return &EthereumKeeperRegistrar{}, fmt.Errorf("failed to instantiate KeeperRegistrar1_2 instance: %w", err) - } - - return &EthereumKeeperRegistrar{ - client: client, - registrar: instance, - address: &data.Address, - }, nil } // LoadKeeperRegistrar returns deployed on given address EthereumKeeperRegistrar func LoadKeeperRegistrar(client *seth.Client, address common.Address, registryVersion KeeperRegistryVersion) (KeeperRegistrar, error) { switch registryVersion { - case RegistryVersion_1_1, RegistryVersion_1_2, RegistryVersion_1_3: - loader := seth.NewContractLoader[keeper_registrar_wrapper1_2.KeeperRegistrar](client) - instance, err := loader.LoadContract("KeeperRegistrar1_2", address, keeper_registrar_wrapper1_2.KeeperRegistrarMetaData.GetAbi, keeper_registrar_wrapper1_2.NewKeeperRegistrar) - if err != nil { - return &EthereumKeeperRegistrar{}, fmt.Errorf("failed to load KeeperRegistrar1_2 instance: %w", err) - } - - return &EthereumKeeperRegistrar{ - address: &address, - client: client, - registrar: instance, - }, err case RegistryVersion_2_0: loader := seth.NewContractLoader[keeper_registrar_wrapper2_0.KeeperRegistrar](client) instance, err := loader.LoadContract("KeeperRegistrar2_0", address, keeper_registrar_wrapper2_0.KeeperRegistrarMetaData.GetAbi, keeper_registrar_wrapper2_0.NewKeeperRegistrar) diff --git a/devenv/contracts/ethereum_contracts.go b/devenv/contracts/ethereum_contracts.go index 80bf3d6041d..49a14fb3c0e 100644 --- a/devenv/contracts/ethereum_contracts.go +++ b/devenv/contracts/ethereum_contracts.go @@ -16,9 +16,6 @@ import ( "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/i_automation_registry_master_wrapper_2_2" "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/i_automation_registry_master_wrapper_2_3" "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_1" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_2" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper1_3" "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper2_0" "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/link_token_interface" "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/mock_ethlink_aggregator_wrapper" @@ -56,20 +53,16 @@ func GetRegistryContractABI(version KeeperRegistryVersion) (*abi.ABI, error) { err error ) switch version { - case RegistryVersion_1_0, RegistryVersion_1_1: - contractABI, err = keeper_registry_wrapper1_1.KeeperRegistryMetaData.GetAbi() - case RegistryVersion_1_2: - contractABI, err = keeper_registry_wrapper1_2.KeeperRegistryMetaData.GetAbi() - case RegistryVersion_1_3: - contractABI, err = keeper_registry_wrapper1_3.KeeperRegistryMetaData.GetAbi() case RegistryVersion_2_0: contractABI, err = keeper_registry_wrapper2_0.KeeperRegistryMetaData.GetAbi() case RegistryVersion_2_1: contractABI, err = i_keeper_registry_master_wrapper_2_1.IKeeperRegistryMasterMetaData.GetAbi() case RegistryVersion_2_2: contractABI, err = i_automation_registry_master_wrapper_2_2.IAutomationRegistryMasterMetaData.GetAbi() + case RegistryVersion_2_3: + contractABI, err = i_automation_registry_master_wrapper_2_3.IAutomationRegistryMaster23MetaData.GetAbi() default: - contractABI, err = keeper_registry_wrapper2_0.KeeperRegistryMetaData.GetAbi() + return nil, fmt.Errorf("unsupported keeper registry version: %v", version) } return contractABI, err diff --git a/devenv/contracts/keeper.go b/devenv/contracts/keeper.go index cb888e38afd..66178fd2ab1 100644 --- a/devenv/contracts/keeper.go +++ b/devenv/contracts/keeper.go @@ -29,13 +29,11 @@ type AbigenLog interface { type KeeperRegistryVersion int32 +// Numeric values 4-7 match the historical enum (after removed 1.x variants); do not renumber. +// //nolint:revive // we want to use underscores const ( - RegistryVersion_1_0 KeeperRegistryVersion = iota - RegistryVersion_1_1 - RegistryVersion_1_2 - RegistryVersion_1_3 - RegistryVersion_2_0 + RegistryVersion_2_0 KeeperRegistryVersion = iota + 4 RegistryVersion_2_1 RegistryVersion_2_2 RegistryVersion_2_3 @@ -43,14 +41,6 @@ const ( func (k KeeperRegistryVersion) String() string { switch k { - case RegistryVersion_1_0: - return "1.0" - case RegistryVersion_1_1: - return "1.1" - case RegistryVersion_1_2: - return "1.2" - case RegistryVersion_1_3: - return "1.3" case RegistryVersion_2_0: return "2.0" case RegistryVersion_2_1: diff --git a/devenv/design.md b/devenv/design.md index 3ea386c29b9..6611961d7e1 100644 --- a/devenv/design.md +++ b/devenv/design.md @@ -166,7 +166,6 @@ sequenceDiagram | Flux Monitor | `flux` | `products/flux/` | 5 | LINK, FluxAggregator | | OCR2 | `ocr2` | `products/ocr2/` | 5 | LINK, OCR2Aggregator | | Automation | `automation` | `products/automation/` | 5 | LINK, Registry (2.0-2.3), Registrar, Upkeeps | -| Keepers | `keepers` | `products/keepers/` | 5 | LINK, KeeperRegistry (1.1-1.3), Registrar, Upkeeps | | VRF | `vrf` | `products/vrf/` | 1 | LINK, BlockHashStore, VRFCoordinator, VRFConsumer | ### Adding a New Product diff --git a/devenv/environment.go b/devenv/environment.go index c4647e7f7ee..0436a090e63 100644 --- a/devenv/environment.go +++ b/devenv/environment.go @@ -17,7 +17,6 @@ import ( "github.com/smartcontractkit/chainlink/devenv/products/cron" "github.com/smartcontractkit/chainlink/devenv/products/directrequest" "github.com/smartcontractkit/chainlink/devenv/products/flux" - "github.com/smartcontractkit/chainlink/devenv/products/keepers" "github.com/smartcontractkit/chainlink/devenv/products/ocr2" "github.com/smartcontractkit/chainlink/devenv/products/vrf" "github.com/smartcontractkit/chainlink/devenv/products/vrfv2" @@ -49,8 +48,6 @@ func newProduct(name string) (Product, error) { return ocr2.NewConfigurator(), nil case "automation": return automation.NewConfigurator(), nil - case "keepers": - return keepers.NewConfigurator(), nil case "vrf": return vrf.NewConfigurator(), nil case "vrfv2_plus": diff --git a/devenv/products/automation/configuration.go b/devenv/products/automation/configuration.go index b5738b29b6e..06c72843957 100644 --- a/devenv/products/automation/configuration.go +++ b/devenv/products/automation/configuration.go @@ -420,15 +420,10 @@ func waitForConfigWatcherToBeHealthy(nodes []*clclient.ChainlinkClient) error { func (m *Automation) MustGetRegistryVersion() contracts.KeeperRegistryVersion { version := semver.MustParse(m.RegistryVersion) + if version.LessThan(semver.MustParse("2.0")) { + panic("keeper registry versions below 2.0 are no longer supported: " + m.RegistryVersion) + } switch { - case version.Equal(semver.MustParse("1.0")): - return contracts.RegistryVersion_1_0 - case version.Equal(semver.MustParse("1.1")): - return contracts.RegistryVersion_1_1 - case version.Equal(semver.MustParse("1.2")): - return contracts.RegistryVersion_1_2 - case version.Equal(semver.MustParse("1.3")): - return contracts.RegistryVersion_1_3 case version.Equal(semver.MustParse("2.0")): return contracts.RegistryVersion_2_0 case version.Equal(semver.MustParse("2.1")): diff --git a/devenv/products/keepers/basic.toml b/devenv/products/keepers/basic.toml deleted file mode 100644 index 424ee893712..00000000000 --- a/devenv/products/keepers/basic.toml +++ /dev/null @@ -1,82 +0,0 @@ -[[products]] -name = "keepers" -instances = 3 - -[[keepers]] -registry_version = "1.1" -cl_nodes_funding_eth = 50 - -[keepers.gas_settings] -# EIP1159 fee cap multiplier (default, for all transactions) -fee_cap_multiplier = 2 -# EIP1159 fee cap multiplier (default, for all transactions) -tip_cap_multiplier = 2 - -[keepers.registry_settings] -payment_premium_ppb=200_000_000 -flat_fee_micro_link=0 -block_count_per_turn = 10 -check_gas_limit=2_500_000 -staleness_seconds=90000 -gas_ceiling_multiplier=1 -max_perform_gas=5_000_000 -min_upkeep_spend=0 -fallback_gas_price=200_000_000_000 -fallback_link_price=2_000_000_000_000_000_000 -fallback_native_price=2_000_000_000_000_000_000 -max_check_data_size=5_000 -max_perform_data_size=5_000 -max_revert_data_size=5_000 - - -[[keepers]] -registry_version = "1.2" -cl_nodes_funding_eth = 50 - -[keepers.gas_settings] -# EIP1159 fee cap multiplier (default, for all transactions) -fee_cap_multiplier = 2 -# EIP1159 fee cap multiplier (default, for all transactions) -tip_cap_multiplier = 2 - -[keepers.registry_settings] -payment_premium_ppb=200_000_000 -flat_fee_micro_link=0 -block_count_per_turn = 10 -check_gas_limit=2_500_000 -staleness_seconds=90000 -gas_ceiling_multiplier=1 -max_perform_gas=5_000_000 -min_upkeep_spend=0 -fallback_gas_price=200_000_000_000 -fallback_link_price=2_000_000_000_000_000_000 -fallback_native_price=2_000_000_000_000_000_000 -max_check_data_size=5_000 -max_perform_data_size=5_000 -max_revert_data_size=5_000 - -[[keepers]] -registry_version = "1.3" -cl_nodes_funding_eth = 50 - -[keepers.gas_settings] -# EIP1159 fee cap multiplier (default, for all transactions) -fee_cap_multiplier = 2 -# EIP1159 fee cap multiplier (default, for all transactions) -tip_cap_multiplier = 2 - -[keepers.registry_settings] -payment_premium_ppb=200_000_000 -flat_fee_micro_link=0 -block_count_per_turn = 10 -check_gas_limit=2_500_000 -staleness_seconds=90000 -gas_ceiling_multiplier=1 -max_perform_gas=5_000_000 -min_upkeep_spend=0 -fallback_gas_price=200_000_000_000 -fallback_link_price=2_000_000_000_000_000_000 -fallback_native_price=2_000_000_000_000_000_000 -max_check_data_size=5_000 -max_perform_data_size=5_000 -max_revert_data_size=5_000 \ No newline at end of file diff --git a/devenv/products/keepers/configuration.go b/devenv/products/keepers/configuration.go deleted file mode 100644 index 5342c55f478..00000000000 --- a/devenv/products/keepers/configuration.go +++ /dev/null @@ -1,320 +0,0 @@ -package keepers - -import ( - "bytes" - "context" - "errors" - "fmt" - "math/big" - "os" - "strconv" - "text/template" - - "github.com/Masterminds/semver/v3" - "github.com/ethereum/go-ethereum/common" - "github.com/rs/zerolog" - "github.com/rs/zerolog/log" - - "github.com/smartcontractkit/chainlink-testing-framework/framework/clclient" - "github.com/smartcontractkit/chainlink-testing-framework/framework/components/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/framework/components/fake" - nodeset "github.com/smartcontractkit/chainlink-testing-framework/framework/components/simple_node_set" - "github.com/smartcontractkit/chainlink-testing-framework/seth" - - "github.com/smartcontractkit/chainlink/devenv/contracts" - "github.com/smartcontractkit/chainlink/devenv/products" -) - -var L = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).Level(zerolog.DebugLevel).With().Fields(map[string]any{"component": "keepers"}).Logger() - -type Configurator struct { - Config []*Keepers `toml:"keepers"` -} - -type Keepers struct { - RegistryVersion string `toml:"registry_version"` - RegistrySettings RegistrySettings `toml:"registry_settings"` - - CLNodesFundingETH float64 `toml:"cl_nodes_funding_eth"` - GasSettings products.GasSettings `toml:"gas_settings"` - - DeployedContracts DeployedContracts `toml:"deployed_contracts"` -} - -type DeployedContracts struct { - LinkToken string `toml:"link_token"` - LinkEthFeed string `toml:"link_eth_feed"` - EthGasFeed string `toml:"eth_gas_feed"` - Transcoder string `toml:"transcoder"` - Registry string `toml:"registry"` - Registrar string `toml:"registrar"` - Upkeeps []string `toml:"upkeeps"` -} - -type RegistrySettings struct { - PaymentPremiumPPB *uint32 `toml:"payment_premium_ppb"` - FlatFeeMicroLINK *uint32 `toml:"flat_fee_micro_link"` - CheckGasLimit *uint32 `toml:"check_gas_limit"` - StalenessSeconds *big.Int `toml:"staleness_seconds"` - GasCeilingMultiplier *uint16 `toml:"gas_ceiling_multiplier"` - MaxPerformGas *uint32 `toml:"max_perform_gas"` - MinUpkeepSpend *big.Int `toml:"min_upkeep_spend"` - FallbackGasPrice *big.Int `toml:"fallback_gas_price"` - FallbackLinkPrice *big.Int `toml:"fallback_link_price"` - FallbackNativePrice *big.Int `toml:"fallback_native_price"` - MaxCheckDataSize *uint32 `toml:"max_check_data_size"` - MaxPerformDataSize *uint32 `toml:"max_perform_data_size"` - MaxRevertDataSize *uint32 `toml:"max_revert_data_size"` - BlockCountPerTurn *big.Int `toml:"block_count_per_turn"` -} - -func (m *Keepers) GetRegistryConfig() contracts.KeeperRegistrySettings { - registrySettings := m.RegistrySettings - return contracts.KeeperRegistrySettings{ - PaymentPremiumPPB: *registrySettings.PaymentPremiumPPB, - FlatFeeMicroLINK: *registrySettings.FlatFeeMicroLINK, - CheckGasLimit: *registrySettings.CheckGasLimit, - StalenessSeconds: registrySettings.StalenessSeconds, - GasCeilingMultiplier: *registrySettings.GasCeilingMultiplier, - MinUpkeepSpend: registrySettings.MinUpkeepSpend, - MaxPerformGas: *registrySettings.MaxPerformGas, - FallbackGasPrice: registrySettings.FallbackGasPrice, - FallbackLinkPrice: registrySettings.FallbackLinkPrice, - FallbackNativePrice: registrySettings.FallbackNativePrice, - MaxCheckDataSize: *registrySettings.MaxCheckDataSize, - MaxPerformDataSize: *registrySettings.MaxPerformDataSize, - MaxRevertDataSize: *registrySettings.MaxRevertDataSize, - BlockCountPerTurn: registrySettings.BlockCountPerTurn, - RegistryVersion: m.MustGetRegistryVersion(), - } -} - -func NewConfigurator() *Configurator { - return &Configurator{} -} - -func (m *Configurator) Load() error { - cfg, err := products.Load[Configurator]() - if err != nil { - return fmt.Errorf("failed to load product config: %w", err) - } - m.Config = cfg.Config - return nil -} - -func (m *Configurator) Store(path string, instanceIdx int) error { - if err := products.Store(".", &Configurator{Config: []*Keepers{m.Config[instanceIdx]}}); err != nil { - return fmt.Errorf("failed to store product config: %w", err) - } - return nil -} - -func (m *Configurator) GenerateNodesConfig( - ctx context.Context, - fs *fake.Input, - bc []*blockchain.Input, - ns []*nodeset.Input, -) (string, error) { - L.Info().Msg("Applying default CL nodes configuration") - // configure node set and generate CL nodes configs - config := `[Feature] -FeedsManager = true -LogPoller = true -UICSAKeys = true - -[Log] -Level = 'debug' -JSONConsole = true - -[Log.File] -MaxSize = '0b' - -[WebServer] -AllowOrigins = '*' -HTTPPort = 6688 -SecureCookies = false -HTTPWriteTimeout = '3m' -SessionTimeout = '999h0m0s' - -[WebServer.RateLimit] -Authenticated = 2000 -Unauthenticated = 1000 - -[WebServer.TLS] -HTTPSPort = 0 - -[Keeper] -TurnLookBack = 0 -` - - netConfigTemplate := ` -[[EVM]] -AutoCreateKey = true -MinContractPayment = 0 -BlockBackfillDepth = 100 -MinIncomingConfirmations = 1 - -ChainID = '{{.ChainID}}' - -[[EVM.Nodes]] -Name = 'default' -WsUrl = '{{.WsURL}}' -HttpUrl = '{{.HTTPURL}}' -` - - tmpl, err := template.New("config").Parse(netConfigTemplate) - if err != nil { - return "", fmt.Errorf("failed to parse template: %w", err) - } - - type data struct { - ChainID string - WsURL string - HTTPURL string - } - - d := data{ - ChainID: bc[0].Out.ChainID, - WsURL: bc[0].Out.Nodes[0].InternalWSUrl, - HTTPURL: bc[0].Out.Nodes[0].InternalHTTPUrl, - } - - var buf bytes.Buffer - if err := tmpl.Execute(&buf, d); err != nil { - return "", fmt.Errorf("failed to execute template: %w", err) - } - - L.Info().Msg("Nodes network configuration is finished") - return config + buf.String(), nil -} - -func (m *Configurator) GenerateNodesSecrets( - _ context.Context, - _ *fake.Input, - _ []*blockchain.Input, - _ []*nodeset.Input, -) (string, error) { - return "", nil -} - -func (m *Configurator) ConfigureJobsAndContracts( - ctx context.Context, - instanceIdx int, - fs *fake.Input, - bc []*blockchain.Input, - ns []*nodeset.Input, -) error { - L.Info().Msg("Connecting to CL nodes") - cl, err := clclient.New(ns[0].Out.CLNodes) - if err != nil { - return err - } - pkey := products.NetworkPrivateKey() - if pkey == "" { - return errors.New("PRIVATE_KEY environment variable not set") - } - - ethKeyAddresses := make([]string, 0) - for i, nc := range cl { - addr, cErr := nc.ReadPrimaryETHKey(bc[0].Out.ChainID) - if cErr != nil { - return cErr - } - ethKeyAddresses = append(ethKeyAddresses, addr.Attributes.Address) - L.Info(). - Int("Idx", i). - Str("ETH", addr.Attributes.Address). - Msg("Node info") - } - - bcNode := bc[0].Out.Nodes[0] - c, _, _, err := products.ETHClient( - ctx, - bcNode.ExternalWSUrl, - m.Config[instanceIdx].GasSettings.FeeCapMultiplier, - m.Config[instanceIdx].GasSettings.TipCapMultiplier, - ) - - if err != nil { - return fmt.Errorf("could not create basic eth client: %w", err) - } - for _, addr := range ethKeyAddresses { - if cErr := products.FundAddressEIP1559(ctx, c, pkey, addr, m.Config[instanceIdx].CLNodesFundingETH); cErr != nil { - return cErr - } - } - - chainID, err := strconv.ParseUint(bc[0].Out.ChainID, 10, 64) - if err != nil { - return err - } - - chainClient, err := products.InitSeth(bcNode.ExternalWSUrl, []string{products.NetworkPrivateKey()}, &chainID) - if err != nil { - return err - } - - if err := deployContracts(L, chainClient, m.Config[instanceIdx]); err != nil { - return err - } - - if err := createJobs(L, cl, m.Config[instanceIdx], bc[0].Out.ChainID); err != nil { - return err - } - - return setConfigOnRegistry(L, chainClient, cl, m.Config[instanceIdx]) -} - -func setConfigOnRegistry(l zerolog.Logger, chainClient *seth.Client, chainlinkNodes []*clclient.ChainlinkClient, config *Keepers) error { - registry, err := contracts.LoadKeeperRegistry(L, chainClient, common.HexToAddress(config.DeployedContracts.Registry), config.MustGetRegistryVersion(), ZeroAddress) - if err != nil { - return err - } - - primaryNode := chainlinkNodes[0] - primaryNodeAddress, err := primaryNode.PrimaryEthAddress() - if err != nil { - l.Error().Err(err).Msg("Reading ETH Keys from Chainlink Client shouldn't fail") - return err - } - - nodeAddresses := make([]string, 0) - for _, clNode := range chainlinkNodes { - clNodeAddress, err := clNode.PrimaryEthAddress() - if err != nil { - l.Error().Err(err).Msg("Error retrieving chainlink node address") - return err - } - nodeAddresses = append(nodeAddresses, clNodeAddress) - } - - nodeAddressesStr, payees := make([]string, 0), make([]string, 0) - for _, cla := range nodeAddresses { - nodeAddressesStr = append(nodeAddressesStr, cla) - payees = append(payees, primaryNodeAddress) - } - - err = registry.SetKeepers(nodeAddressesStr, payees, contracts.OCRv2Config{}) - if err != nil { - l.Error().Err(err).Msg("Setting keepers in the registry shouldn't fail") - return err - } - - return nil -} - -func (m *Keepers) MustGetRegistryVersion() contracts.KeeperRegistryVersion { - version := semver.MustParse(m.RegistryVersion) - switch { - case version.Equal(semver.MustParse("1.0")): - return contracts.RegistryVersion_1_0 - case version.Equal(semver.MustParse("1.1")): - return contracts.RegistryVersion_1_1 - case version.Equal(semver.MustParse("1.2")): - return contracts.RegistryVersion_1_2 - case version.Equal(semver.MustParse("1.3")): - return contracts.RegistryVersion_1_3 - default: - panic("unsupported registry version: " + m.RegistryVersion) - } -} diff --git a/devenv/products/keepers/core.go b/devenv/products/keepers/core.go deleted file mode 100644 index 0e4b7e41aed..00000000000 --- a/devenv/products/keepers/core.go +++ /dev/null @@ -1,178 +0,0 @@ -package keepers - -import ( - "bytes" - "fmt" - "math" - "math/big" - "text/template" - - "github.com/ethereum/go-ethereum/common" - "github.com/rs/zerolog" - - "github.com/smartcontractkit/chainlink-testing-framework/framework/clclient" - "github.com/smartcontractkit/chainlink-testing-framework/seth" - "github.com/smartcontractkit/chainlink/devenv/contracts" -) - -var ZeroAddress = common.Address{} - -func deployContracts(l zerolog.Logger, chainClient *seth.Client, config *Keepers) error { - if config.DeployedContracts.LinkToken == "" { - linkToken, err := contracts.DeployLinkTokenContract(l, chainClient) - if err != nil { - return fmt.Errorf("error deploying link token contract: %w", err) - } - config.DeployedContracts.LinkToken = linkToken.Address() - } - - if config.DeployedContracts.LinkEthFeed == "" { - ethLinkFeed, err := contracts.DeployMockLINKETHFeed(chainClient, big.NewInt(2e18)) - if err != nil { - return fmt.Errorf("error deploying mock eth feed contract: %w", err) - } - config.DeployedContracts.LinkEthFeed = ethLinkFeed.Address() - } - - if config.DeployedContracts.EthGasFeed == "" { - gasFeed, err := contracts.DeployMockGASFeed(chainClient, big.NewInt(2e11)) - if err != nil { - return fmt.Errorf("error deploying mock gas feed contract: %w", err) - } - config.DeployedContracts.EthGasFeed = gasFeed.Address() - } - - if config.DeployedContracts.Transcoder == "" { - transcoder, err := contracts.DeployUpkeepTranscoder(chainClient) - if err != nil { - return fmt.Errorf("error deploying transcoder contract: %w", err) - } - config.DeployedContracts.Transcoder = transcoder.Address() - } - - if config.DeployedContracts.Registry == "" { - registry, err := contracts.DeployKeeperRegistry(chainClient, &contracts.KeeperRegistryOpts{ - RegistryVersion: config.MustGetRegistryVersion(), - LinkAddr: config.DeployedContracts.LinkToken, - ETHFeedAddr: config.DeployedContracts.LinkEthFeed, - GasFeedAddr: config.DeployedContracts.EthGasFeed, - TranscoderAddr: config.DeployedContracts.Transcoder, - RegistrarAddr: ZeroAddress.Hex(), - Settings: config.GetRegistryConfig(), - }) - if err != nil { - return fmt.Errorf("error deploying registry contract: %w", err) - } - config.DeployedContracts.Registry = registry.Address() - } - - if config.DeployedContracts.Registrar == "" { - registrarSettings := contracts.KeeperRegistrarSettings{ - AutoApproveConfigType: 2, - AutoApproveMaxAllowed: math.MaxUint16, - RegistryAddr: config.DeployedContracts.Registry, - MinLinkJuels: big.NewInt(0), - } - - registryInstance, err := contracts.LoadKeeperRegistry(l, chainClient, common.HexToAddress(config.DeployedContracts.Registry), config.MustGetRegistryVersion(), ZeroAddress) - if err != nil { - return fmt.Errorf("error loading registry contract: %w", err) - } - - linkInstance, err := contracts.LoadLinkTokenContract(l, chainClient, common.HexToAddress(config.DeployedContracts.LinkToken)) - if err != nil { - return fmt.Errorf("error loading link token contract: %w", err) - } - - registrar, err := DeployKeeperRegistrar(chainClient, config.MustGetRegistryVersion(), linkInstance, registrarSettings, registryInstance) - if err != nil { - return fmt.Errorf("error deploying registrar contract: %w", err) - } - config.DeployedContracts.Registrar = registrar.Address() - } - - return nil -} - -func DeployKeeperRegistrar( - client *seth.Client, - registryVersion contracts.KeeperRegistryVersion, - linkToken contracts.LinkToken, - registrarSettings contracts.KeeperRegistrarSettings, - registry contracts.KeeperRegistry, -) (contracts.KeeperRegistrar, error) { - registrar, err := contracts.DeployKeeperRegistrar(client, registryVersion, linkToken.Address(), registrarSettings) - if err != nil { - return nil, err - } - if registryVersion != contracts.RegistryVersion_2_0 { - err = registry.SetRegistrar(registrar.Address()) - if err != nil { - return nil, err - } - } - - return registrar, nil -} - -func createJobs( - l zerolog.Logger, - chainlinkNodes []*clclient.ChainlinkClient, - config *Keepers, - evmChainID string, -) error { - for _, chainlinkNode := range chainlinkNodes { - chainlinkNodeAddress, err := chainlinkNode.PrimaryEthAddress() - if err != nil { - l.Error().Err(err).Msg("Error retrieving chainlink node address") - return err - } - _, err = chainlinkNode.MustCreateJob(&KeeperJobSpec{ - Name: "keeper-test-" + config.DeployedContracts.Registry, - ContractAddress: config.DeployedContracts.Registry, - FromAddress: chainlinkNodeAddress, - EVMChainID: evmChainID, - MinIncomingConfirmations: 1, - }) - if err != nil { - l.Error().Err(err).Msg("Creating KeeperV2 Job shouldn't fail") - return err - } - } - return nil -} - -// KeeperJobSpec represents a V2 keeper spec -type KeeperJobSpec struct { - Name string `toml:"name"` - ContractAddress string `toml:"contractAddress"` - FromAddress string `toml:"fromAddress"` // Hex representation of the from address - EVMChainID string `toml:"evmChainID"` // Not optional - MinIncomingConfirmations int `toml:"minIncomingConfirmations"` -} - -// Type returns the type of the job -func (k *KeeperJobSpec) Type() string { return "keeper" } - -// String representation of the job -func (k *KeeperJobSpec) String() (string, error) { - keeperTemplateString := ` -type = "keeper" -schemaVersion = 1 -name = "{{.Name}}" -contractAddress = "{{.ContractAddress}}" -fromAddress = "{{.FromAddress}}" -evmChainID = "{{.EVMChainID}}" -minIncomingConfirmations = {{.MinIncomingConfirmations}} -` - var buf bytes.Buffer - tmpl, err := template.New("Keeper Job").Parse(keeperTemplateString) - if err != nil { - return "", err - } - err = tmpl.Execute(&buf, *k) - if err != nil { - return "", err - } - return buf.String(), err -} diff --git a/devenv/products/keepers/helpers.go b/devenv/products/keepers/helpers.go deleted file mode 100644 index 64db7c8951c..00000000000 --- a/devenv/products/keepers/helpers.go +++ /dev/null @@ -1,75 +0,0 @@ -package keepers - -import ( - "math/big" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-testing-framework/framework" - "github.com/smartcontractkit/chainlink-testing-framework/seth" - "github.com/smartcontractkit/chainlink/devenv/contracts" -) - -// DeployKeeperConsumersPerformance sequentially deploys keeper performance consumer contracts. -func DeployKeeperConsumersPerformance( - t *testing.T, - client *seth.Client, - numberOfContracts int, - blockRange, // How many blocks to run the test for - blockInterval, // Interval of blocks that upkeeps are expected to be performed - checkGasToBurn, // How much gas should be burned on checkUpkeep() calls - performGasToBurn int64, // How much gas should be burned on performUpkeep() calls -) []contracts.KeeperConsumerPerformance { - l := framework.L - upkeeps := make([]contracts.KeeperConsumerPerformance, 0) - - for contractCount := range numberOfContracts { - // Deploy consumer - keeperConsumerInstance, err := contracts.DeployKeeperConsumerPerformance( - client, - big.NewInt(blockRange), - big.NewInt(blockInterval), - big.NewInt(checkGasToBurn), - big.NewInt(performGasToBurn), - ) - require.NoError(t, err, "Deploying KeeperConsumerPerformance instance %d shouldn't fail", contractCount+1) - upkeeps = append(upkeeps, keeperConsumerInstance) - l.Debug(). - Str("Contract Address", keeperConsumerInstance.Address()). - Int("Number", contractCount+1). - Int("Out Of", numberOfContracts). - Msg("Deployed Keeper Performance Contract") - } - - require.Len(t, upkeeps, numberOfContracts, "Incorrect number of consumers contracts deployed") - l.Info().Msg("Successfully deployed all Keeper Consumer Contracts") - - return upkeeps -} - -// DeployPerformDataChecker sequentially deploys keeper perform data checker contracts. -func DeployPerformDataChecker( - t *testing.T, - client *seth.Client, - numberOfContracts int, - expectedData []byte, -) []contracts.KeeperPerformDataChecker { - l := framework.L - upkeeps := make([]contracts.KeeperPerformDataChecker, 0) - - for contractCount := range numberOfContracts { - performDataCheckerInstance, err := contracts.DeployKeeperPerformDataChecker(client, expectedData) - require.NoError(t, err, "Deploying KeeperPerformDataChecker instance %d shouldn't fail", contractCount+1) - upkeeps = append(upkeeps, performDataCheckerInstance) - l.Debug(). - Str("Contract Address", performDataCheckerInstance.Address()). - Int("Number", contractCount+1). - Int("Out Of", numberOfContracts). - Msg("Deployed PerformDataChecker Contract") - } - require.Len(t, upkeeps, numberOfContracts, "Incorrect number of PerformDataChecker contracts deployed") - l.Info().Msg("Successfully deployed all PerformDataChecker Contracts") - - return upkeeps -} diff --git a/devenv/products/keepers/high_bcptr.toml b/devenv/products/keepers/high_bcptr.toml deleted file mode 100644 index 5a6b2e7fcff..00000000000 --- a/devenv/products/keepers/high_bcptr.toml +++ /dev/null @@ -1,82 +0,0 @@ -[[products]] -name = "keepers" -instances = 3 - -[[keepers]] -registry_version = "1.1" -cl_nodes_funding_eth = 50 - -[keepers.gas_settings] -# EIP1159 fee cap multiplier (default, for all transactions) -fee_cap_multiplier = 2 -# EIP1159 fee cap multiplier (default, for all transactions) -tip_cap_multiplier = 2 - -[keepers.registry_settings] -payment_premium_ppb=200_000_000 -flat_fee_micro_link=0 -block_count_per_turn = 1000 -check_gas_limit=2_500_000 -staleness_seconds=90000 -gas_ceiling_multiplier=1 -max_perform_gas=5_000_000 -min_upkeep_spend=0 -fallback_gas_price=200_000_000_000 -fallback_link_price=2_000_000_000_000_000_000 -fallback_native_price=2_000_000_000_000_000_000 -max_check_data_size=5_000 -max_perform_data_size=5_000 -max_revert_data_size=5_000 - - -[[keepers]] -registry_version = "1.2" -cl_nodes_funding_eth = 50 - -[keepers.gas_settings] -# EIP1159 fee cap multiplier (default, for all transactions) -fee_cap_multiplier = 2 -# EIP1159 fee cap multiplier (default, for all transactions) -tip_cap_multiplier = 2 - -[keepers.registry_settings] -payment_premium_ppb=200_000_000 -flat_fee_micro_link=0 -block_count_per_turn = 1000 -check_gas_limit=2_500_000 -staleness_seconds=90000 -gas_ceiling_multiplier=1 -max_perform_gas=5_000_000 -min_upkeep_spend=0 -fallback_gas_price=200_000_000_000 -fallback_link_price=2_000_000_000_000_000_000 -fallback_native_price=2_000_000_000_000_000_000 -max_check_data_size=5_000 -max_perform_data_size=5_000 -max_revert_data_size=5_000 - -[[keepers]] -registry_version = "1.3" -cl_nodes_funding_eth = 50 - -[keepers.gas_settings] -# EIP1159 fee cap multiplier (default, for all transactions) -fee_cap_multiplier = 2 -# EIP1159 fee cap multiplier (default, for all transactions) -tip_cap_multiplier = 2 - -[keepers.registry_settings] -payment_premium_ppb=200_000_000 -flat_fee_micro_link=0 -block_count_per_turn = 1000 -check_gas_limit=2_500_000 -staleness_seconds=90000 -gas_ceiling_multiplier=1 -max_perform_gas=5_000_000 -min_upkeep_spend=0 -fallback_gas_price=200_000_000_000 -fallback_link_price=2_000_000_000_000_000_000 -fallback_native_price=2_000_000_000_000_000_000 -max_check_data_size=5_000 -max_perform_data_size=5_000 -max_revert_data_size=5_000 \ No newline at end of file diff --git a/devenv/products/keepers/low_bcptr.toml b/devenv/products/keepers/low_bcptr.toml deleted file mode 100644 index 95f0165f5a8..00000000000 --- a/devenv/products/keepers/low_bcptr.toml +++ /dev/null @@ -1,82 +0,0 @@ -[[products]] -name = "keepers" -instances = 3 - -[[keepers]] -registry_version = "1.1" -cl_nodes_funding_eth = 50 - -[keepers.gas_settings] -# EIP1159 fee cap multiplier (default, for all transactions) -fee_cap_multiplier = 2 -# EIP1159 fee cap multiplier (default, for all transactions) -tip_cap_multiplier = 2 - -[keepers.registry_settings] -payment_premium_ppb=200_000_000 -flat_fee_micro_link=0 -block_count_per_turn = 4 -check_gas_limit=2_500_000 -staleness_seconds=90000 -gas_ceiling_multiplier=1 -max_perform_gas=5_000_000 -min_upkeep_spend=0 -fallback_gas_price=200_000_000_000 -fallback_link_price=2_000_000_000_000_000_000 -fallback_native_price=2_000_000_000_000_000_000 -max_check_data_size=5_000 -max_perform_data_size=5_000 -max_revert_data_size=5_000 - - -[[keepers]] -registry_version = "1.2" -cl_nodes_funding_eth = 50 - -[keepers.gas_settings] -# EIP1159 fee cap multiplier (default, for all transactions) -fee_cap_multiplier = 2 -# EIP1159 fee cap multiplier (default, for all transactions) -tip_cap_multiplier = 2 - -[keepers.registry_settings] -payment_premium_ppb=200_000_000 -flat_fee_micro_link=0 -block_count_per_turn = 4 -check_gas_limit=2_500_000 -staleness_seconds=90000 -gas_ceiling_multiplier=1 -max_perform_gas=5_000_000 -min_upkeep_spend=0 -fallback_gas_price=200_000_000_000 -fallback_link_price=2_000_000_000_000_000_000 -fallback_native_price=2_000_000_000_000_000_000 -max_check_data_size=5_000 -max_perform_data_size=5_000 -max_revert_data_size=5_000 - -[[keepers]] -registry_version = "1.3" -cl_nodes_funding_eth = 50 - -[keepers.gas_settings] -# EIP1159 fee cap multiplier (default, for all transactions) -fee_cap_multiplier = 2 -# EIP1159 fee cap multiplier (default, for all transactions) -tip_cap_multiplier = 2 - -[keepers.registry_settings] -payment_premium_ppb=200_000_000 -flat_fee_micro_link=0 -block_count_per_turn = 4 -check_gas_limit=2_500_000 -staleness_seconds=90000 -gas_ceiling_multiplier=1 -max_perform_gas=5_000_000 -min_upkeep_spend=0 -fallback_gas_price=200_000_000_000 -fallback_link_price=2_000_000_000_000_000_000 -fallback_native_price=2_000_000_000_000_000_000 -max_check_data_size=5_000 -max_perform_data_size=5_000 -max_revert_data_size=5_000 \ No newline at end of file diff --git a/devenv/tests/keepers/load_test.go b/devenv/tests/keepers/load_test.go deleted file mode 100644 index f03e0b7045f..00000000000 --- a/devenv/tests/keepers/load_test.go +++ /dev/null @@ -1,3 +0,0 @@ -package keepers - -// TODO: implement load test diff --git a/devenv/tests/keepers/smoke_test.go b/devenv/tests/keepers/smoke_test.go deleted file mode 100644 index 0b5f6026fff..00000000000 --- a/devenv/tests/keepers/smoke_test.go +++ /dev/null @@ -1,2168 +0,0 @@ -package keepers - -import ( - "math" - "math/big" - "strconv" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/onsi/gomega" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-testing-framework/framework" - "github.com/smartcontractkit/chainlink-testing-framework/framework/clclient" - de "github.com/smartcontractkit/chainlink/devenv" - "github.com/smartcontractkit/chainlink/devenv/contracts" - "github.com/smartcontractkit/chainlink/devenv/products" - "github.com/smartcontractkit/chainlink/devenv/products/automation" - "github.com/smartcontractkit/chainlink/devenv/products/keepers" - - automation_tests "github.com/smartcontractkit/chainlink/devenv/tests/automation" -) - -const ( - defaultUpkeepGasLimit = uint32(2500000) - defaultLinkFunds = 9 - defaultEthFunds = 10.0 - defaultAmountOfUpkeeps = 2 - defaultUpkeepExecutionTimeout = "5m" // ~1m for cluster setup, ~2m for performing each upkeep 5 times, ~2m buffer - defaultExpectedUpkeepExecutions = 10 - - numUpkeepsAllowedForStragglingTxs = 6 - expectedData = "expected data" -) - -type testcase struct { - Name string `toml:"name"` - - RegistryVersion contracts.KeeperRegistryVersion `toml:"registryVersion"` - UpkeepCount int `toml:"upkeepCount,omitempty"` // how many upkeeps to deploy - ExpectedUpkeepExecutions int `toml:"expectedUpkeepExecutions,omitempty"` // how many times each upkeep should execute - UpkeepExecutionTimeout string `toml:"upkeepExecutionTimeout,omitempty"` // "1s", "5m", 1h20m", etc - UpkeepFundingLink int64 `toml:"upkeepFundingLink,omitempty"` - - TestKeyFundingEth float64 `toml:"testKeyFundingEth,omitempty"` -} - -var ( - keeperDefaultRegistryConfig = contracts.KeeperRegistrySettings{ - PaymentPremiumPPB: uint32(200000000), - FlatFeeMicroLINK: uint32(0), - BlockCountPerTurn: big.NewInt(10), - CheckGasLimit: uint32(2500000), - StalenessSeconds: big.NewInt(90000), - GasCeilingMultiplier: uint16(1), - MinUpkeepSpend: big.NewInt(0), - MaxPerformGas: uint32(5000000), - FallbackGasPrice: big.NewInt(2e11), - FallbackLinkPrice: big.NewInt(2e18), - MaxCheckDataSize: uint32(5000), - MaxPerformDataSize: uint32(5000), - } - lowBCPTRegistryConfig = contracts.KeeperRegistrySettings{ - PaymentPremiumPPB: uint32(200000000), - FlatFeeMicroLINK: uint32(0), - BlockCountPerTurn: big.NewInt(4), - CheckGasLimit: uint32(2500000), - StalenessSeconds: big.NewInt(90000), - GasCeilingMultiplier: uint16(1), - MinUpkeepSpend: big.NewInt(0), - MaxPerformGas: uint32(5000000), - FallbackGasPrice: big.NewInt(2e11), - FallbackLinkPrice: big.NewInt(2e18), - } - zeroAddress = common.Address{} -) - -func TestKeeperBasic(t *testing.T) { - testcases := []testcase{ - { - Name: "registry_1_1", - RegistryVersion: contracts.RegistryVersion_1_1, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - ExpectedUpkeepExecutions: defaultExpectedUpkeepExecutions, - UpkeepExecutionTimeout: defaultUpkeepExecutionTimeout, - }, - { - Name: "registry_1_2", - RegistryVersion: contracts.RegistryVersion_1_2, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - ExpectedUpkeepExecutions: defaultExpectedUpkeepExecutions, - UpkeepExecutionTimeout: defaultUpkeepExecutionTimeout, - }, - { - Name: "registry_1_3", - RegistryVersion: contracts.RegistryVersion_1_3, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - ExpectedUpkeepExecutions: defaultExpectedUpkeepExecutions, - UpkeepExecutionTimeout: defaultUpkeepExecutionTimeout, - }, - } - - for _, testcase := range testcases { - t.Run(testcase.Name, func(t *testing.T) { - l := framework.L - t.Cleanup(func() { - cleanupErr := products.CleanupContainerLogs(products.DefaultSettings()) - require.NoError(t, cleanupErr, "failed to process cleanup container logs") - }) - - outputFile := "../../env-out.toml" - in, err := de.LoadOutput[de.Cfg](outputFile) - require.NoError(t, err) - pdConfig, err := products.LoadOutput[keepers.Configurator](outputFile) - require.NoError(t, err) - - var config *keepers.Keepers - for _, candidate := range pdConfig.Config { - if candidate.MustGetRegistryVersion() == testcase.RegistryVersion { - config = candidate - } - } - require.NotNil(t, config, "failed to find matching config with registry version %v", testcase.RegistryVersion.String()) - - pks := []string{products.NetworkPrivateKey()} - - require.Equal(t, "1337", in.Blockchains[0].ChainID, "automation smoke tests can only be run on simulated network. If do want to run on a live network, please read the code, understand the implications (e.g. potential fund loss) and adjust the test accordingly") - - // on simulated network create new ephemeral addresses if insufficient private keys were provided - // we ignore key at index 0, because it is the root key, which is not used during the test - // for contract deployment and interaction - // we create new addresses only on the simulated network to protect against fund loss - if in.Blockchains[0].ChainID == "1337" && len(pks)-1 != testcase.UpkeepCount { - bcNode := in.Blockchains[0].Out.Nodes[0] - c, _, _, err := products.ETHClient( - t.Context(), - bcNode.ExternalWSUrl, - config.GasSettings.FeeCapMultiplier, - config.GasSettings.TipCapMultiplier, - ) - require.NoError(t, err, "Failed to create ETH client") - - newPks, err := products.FundNewAddresses(t.Context(), testcase.UpkeepCount, c, testcase.TestKeyFundingEth) - require.NoError(t, err, "Failed to fund new addresses") - pks = append(pks, newPks...) - } - require.GreaterOrEqual(t, len(pks), testcase.UpkeepCount+1, "you must provide at least %d private keys", testcase.UpkeepCount+1) - chainID, err := strconv.ParseUint(in.Blockchains[0].ChainID, 10, 64) - require.NoError(t, err, "Failed to parse chain ID") - - chainClient, err := products.InitSeth(in.Blockchains[0].Out.Nodes[0].ExternalWSUrl, pks, &chainID) - require.NoError(t, err, "Failed to create chain client") - - test, err := NewTest(l, chainClient, config) - require.NoError(t, err, "Failed to create test") - - // Fund the registry with 1 LINK * amount of KeeperConsumerPerformance contracts - err = test.LinkToken.Transfer(test.Registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(testcase.UpkeepCount)))) - require.NoError(t, err, "Funding keeper registry contract shouldn't fail") - - sb, err := chainClient.Client.BlockNumber(t.Context()) - require.NoError(t, err, "Failed to get start block") - - upkeeps, upkeepIDs := automation.DeployLegacyConsumers(t, chainClient, test.Registry, test.Registrar, test.LinkToken, testcase.UpkeepCount, big.NewInt(0).Mul(big.NewInt(testcase.UpkeepFundingLink), big.NewInt(1e18)), defaultUpkeepGasLimit, false, false, false, nil) - - t.Cleanup(func() { - automation_tests.GetStalenessReportCleanupFn(t, l, chainClient, sb, test.Registry, testcase.RegistryVersion)() - }) - - l.Info().Msgf("Waiting %s for %d upkeeps to be performed by %d contracts", testcase.UpkeepExecutionTimeout, testcase.ExpectedUpkeepExecutions, testcase.UpkeepCount) - - gom := gomega.NewGomegaWithT(t) - gom.Eventually(func(g gomega.Gomega) error { - // Check if the upkeeps are performing multiple times by analyzing their counters and checking they are greater than 10 - for i := range upkeepIDs { - counter, err := upkeeps[i].Counter(t.Context()) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i) - l.Info().Int64("Upkeeps Performed", counter.Int64()).Int("Upkeep Index", i).Msg("Upkeeps performed") - g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(testcase.ExpectedUpkeepExecutions)), - "Expected consumer counter to be greater than %d, but got %d", testcase.ExpectedUpkeepExecutions, counter.Int64()) - l.Info().Int64("Upkeep counter", counter.Int64()).Msg("Number of upkeeps performed") - } - return nil - }, testcase.UpkeepExecutionTimeout, "1s").Should(gomega.Succeed()) - - // Cancel all the registered upkeeps via the registry - for i := range upkeepIDs { - err := test.Registry.CancelUpkeep(upkeepIDs[i]) - require.NoError(t, err, "Could not cancel upkeep at index %d", i) - } - - var countersAfterCancellation = make([]*big.Int, len(upkeepIDs)) - - for i := range upkeepIDs { - // Obtain the amount of times the upkeep has been executed so far - countersAfterCancellation[i], err = upkeeps[i].Counter(t.Context()) - require.NoError(t, err, "Failed to retrieve consumer counter for upkeep at index %d", i) - l.Info().Int("Index", i).Int64("Upkeeps Performed", countersAfterCancellation[i].Int64()).Msg("Cancelled Upkeep") - } - - gom.Consistently(func(g gomega.Gomega) { - for i := range upkeepIDs { - // Expect the counter to remain constant because the upkeep was cancelled, so it shouldn't increase anymore - latestCounter, err := upkeeps[i].Counter(t.Context()) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i) - g.Expect(latestCounter.Int64()).Should(gomega.Equal(countersAfterCancellation[i].Int64()), - "Expected consumer counter to remain constant at %d, but got %d", - countersAfterCancellation[i].Int64(), latestCounter.Int64()) - } - }, "1m", "1s").Should(gomega.Succeed()) - }) - } -} - -func TestKeeperBlockCountPerTurn(t *testing.T) { - testcases := []testcase{ - { - Name: "registry_1_1", - RegistryVersion: contracts.RegistryVersion_1_1, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - UpkeepExecutionTimeout: defaultUpkeepExecutionTimeout, - }, - { - Name: "registry_1_2", - RegistryVersion: contracts.RegistryVersion_1_2, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - UpkeepExecutionTimeout: defaultUpkeepExecutionTimeout, - }, - { - Name: "registry_1_3", - RegistryVersion: contracts.RegistryVersion_1_3, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - UpkeepExecutionTimeout: defaultUpkeepExecutionTimeout, - }, - } - - for _, testcase := range testcases { - t.Run(testcase.Name, func(t *testing.T) { - l := framework.L - t.Cleanup(func() { - cleanupErr := products.CleanupContainerLogs(products.DefaultSettings()) - require.NoError(t, cleanupErr, "failed to process cleanup container logs") - }) - - outputFile := "../../env-out.toml" - in, err := de.LoadOutput[de.Cfg](outputFile) - require.NoError(t, err) - pdConfig, err := products.LoadOutput[keepers.Configurator](outputFile) - require.NoError(t, err) - - var config *keepers.Keepers - for _, candidate := range pdConfig.Config { - if candidate.MustGetRegistryVersion() == testcase.RegistryVersion { - config = candidate - } - } - require.NotNil(t, config, "failed to find matching config with registry version %v", testcase.RegistryVersion.String()) - - pks := []string{products.NetworkPrivateKey()} - - require.Equal(t, "1337", in.Blockchains[0].ChainID, "automation smoke tests can only be run on simulated network. If do want to run on a live network, please read the code, understand the implications (e.g. potential fund loss) and adjust the test accordingly") - - // on simulated network create new ephemeral addresses if insufficient private keys were provided - // we ignore key at index 0, because it is the root key, which is not used during the test - // for contract deployment and interaction - // we create new addresses only on the simulated network to protect against fund loss - if in.Blockchains[0].ChainID == "1337" && len(pks)-1 != testcase.UpkeepCount { - bcNode := in.Blockchains[0].Out.Nodes[0] - c, _, _, err := products.ETHClient( - t.Context(), - bcNode.ExternalWSUrl, - config.GasSettings.FeeCapMultiplier, - config.GasSettings.TipCapMultiplier, - ) - require.NoError(t, err, "Failed to create ETH client") - - newPks, err := products.FundNewAddresses(t.Context(), testcase.UpkeepCount, c, testcase.TestKeyFundingEth) - require.NoError(t, err, "Failed to fund new addresses") - pks = append(pks, newPks...) - } - require.GreaterOrEqual(t, len(pks), testcase.UpkeepCount+1, "you must provide at least %d private keys", testcase.UpkeepCount+1) - chainID, err := strconv.ParseUint(in.Blockchains[0].ChainID, 10, 64) - require.NoError(t, err, "Failed to parse chain ID") - - chainClient, err := products.InitSeth(in.Blockchains[0].Out.Nodes[0].ExternalWSUrl, pks, &chainID) - require.NoError(t, err, "Failed to create chain client") - - test, err := NewTest(l, chainClient, config) - require.NoError(t, err, "Failed to create test") - - // Fund the registry with 1 LINK * amount of KeeperConsumerPerformance contracts - err = test.LinkToken.Transfer(test.Registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(testcase.UpkeepCount)))) - require.NoError(t, err, "Funding keeper registry contract shouldn't fail") - - sb, err := chainClient.Client.BlockNumber(t.Context()) - require.NoError(t, err, "Failed to get start block") - - upkeeps, upkeepIDs := automation.DeployLegacyConsumers(t, chainClient, test.Registry, test.Registrar, test.LinkToken, testcase.UpkeepCount, big.NewInt(0).Mul(big.NewInt(testcase.UpkeepFundingLink), big.NewInt(1e18)), defaultUpkeepGasLimit, false, false, false, nil) - - t.Cleanup(func() { - automation_tests.GetStalenessReportCleanupFn(t, l, chainClient, sb, test.Registry, testcase.RegistryVersion)() - }) - - l.Info().Msg("Waiting for 2m for upkeeps to be performed by different keepers") - ticker := time.NewTicker(1 * time.Second) - defer ticker.Stop() - - stop := time.After(2 * time.Minute) - - keepersPerformedLowFreq := map[*big.Int][]string{} - - LOW_LOOP: - for { - select { - case <-ticker.C: - for i := range upkeepIDs { - counter, err := upkeeps[i].Counter(t.Context()) - require.NoError(t, err, "Calling consumer's counter shouldn't fail") - l.Info().Str("UpkeepId", upkeepIDs[i].String()).Int64("Upkeep counter", counter.Int64()).Msg("Number of upkeeps performed") - - upkeepInfo, err := test.Registry.GetUpkeepInfo(t.Context(), upkeepIDs[i]) - require.NoError(t, err, "Registry's getUpkeep shouldn't fail") - - latestKeeper := upkeepInfo.LastKeeper - if latestKeeper == zeroAddress.String() { - continue - } - - keepersPerformedLowFreq[upkeepIDs[i]] = append(keepersPerformedLowFreq[upkeepIDs[i]], latestKeeper) - } - case <-stop: - ticker.Stop() - break LOW_LOOP - } - } - - require.GreaterOrEqual(t, testcase.UpkeepCount, len(keepersPerformedLowFreq), "At least %d different keepers should have been performing upkeeps", testcase.UpkeepCount) - - // Now set BCPT to be low, so keepers change turn frequently - err = test.Registry.SetConfig(lowBCPTRegistryConfig, contracts.OCRv2Config{}) - require.NoError(t, err, "Error setting registry config") - - keepersPerformedHigherFreq := map[*big.Int][]string{} - - ticker = time.NewTicker(1 * time.Second) - defer ticker.Stop() - - stop = time.After(2 * time.Minute) - - HIGH_LOOP: - for { - select { - case <-ticker.C: - for i := range upkeepIDs { - counter, err := upkeeps[i].Counter(t.Context()) - require.NoError(t, err, "Calling consumer's counter shouldn't fail") - l.Info().Str("UpkeepId", upkeepIDs[i].String()).Int64("Upkeep counter", counter.Int64()).Msg("Number of upkeeps performed") - - upkeepInfo, err := test.Registry.GetUpkeepInfo(t.Context(), upkeepIDs[i]) - require.NoError(t, err, "Registry's getUpkeep shouldn't fail") - - latestKeeper := upkeepInfo.LastKeeper - if latestKeeper == zeroAddress.String() { - continue - } - - keepersPerformedHigherFreq[upkeepIDs[i]] = append(keepersPerformedHigherFreq[upkeepIDs[i]], latestKeeper) - } - case <-stop: - ticker.Stop() - break HIGH_LOOP - } - } - - require.GreaterOrEqual(t, testcase.UpkeepCount+1, len(keepersPerformedHigherFreq), "At least %d different keepers should have been performing upkeeps after BCPT change", testcase.UpkeepCount+1) - - var countFreq = func(keepers []string, freqMap map[string]int) { - for _, keeper := range keepers { - freqMap[keeper]++ - } - } - - for i := range upkeepIDs { - lowFreqMap := make(map[string]int) - highFreqMap := make(map[string]int) - - countFreq(keepersPerformedLowFreq[upkeepIDs[i]], lowFreqMap) - countFreq(keepersPerformedHigherFreq[upkeepIDs[i]], highFreqMap) - - require.Greater(t, len(highFreqMap), len(lowFreqMap), "High frequency map should have more keepers than low frequency map") - - l.Info().Interface("Low BCPT", lowFreqMap).Interface("High BCPT", highFreqMap).Str("UpkeepID", upkeepIDs[i].String()).Msg("Keeper frequency map") - - for lowKeeper, lowFreq := range lowFreqMap { - highFreq, ok := highFreqMap[lowKeeper] - // it might happen due to fluke that a keeper is not found in high frequency map - if !ok { - continue - } - // require.True(t, ok, "Keeper %s not found in high frequency map. This should not happen", lowKeeper) - require.GreaterOrEqual(t, lowFreq, highFreq, "Keeper %s should have performed less times with high BCPT than with low BCPT", lowKeeper) - } - } - }) - } -} - -func TestKeeperSimulation(t *testing.T) { - testcases := []testcase{ - { - Name: "registry_1_1", - RegistryVersion: contracts.RegistryVersion_1_1, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - ExpectedUpkeepExecutions: defaultExpectedUpkeepExecutions, - UpkeepExecutionTimeout: "1m", - }, - { - Name: "registry_1_2", - RegistryVersion: contracts.RegistryVersion_1_2, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - UpkeepExecutionTimeout: "1m", - }, - { - Name: "registry_1_3", - RegistryVersion: contracts.RegistryVersion_1_3, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - UpkeepExecutionTimeout: "1m", - }, - } - - for _, testcase := range testcases { - t.Run(testcase.Name, func(t *testing.T) { - l := framework.L - t.Cleanup(func() { - cleanupErr := products.CleanupContainerLogs(products.DefaultSettings()) - require.NoError(t, cleanupErr, "failed to process cleanup container logs") - }) - - outputFile := "../../env-out.toml" - in, err := de.LoadOutput[de.Cfg](outputFile) - require.NoError(t, err) - pdConfig, err := products.LoadOutput[keepers.Configurator](outputFile) - require.NoError(t, err) - - var config *keepers.Keepers - for _, candidate := range pdConfig.Config { - if candidate.MustGetRegistryVersion() == testcase.RegistryVersion { - config = candidate - } - } - require.NotNil(t, config, "failed to find matching config with registry version %v", testcase.RegistryVersion.String()) - - pks := []string{products.NetworkPrivateKey()} - - require.Equal(t, "1337", in.Blockchains[0].ChainID, "automation smoke tests can only be run on simulated network. If do want to run on a live network, please read the code, understand the implications (e.g. potential fund loss) and adjust the test accordingly") - - // on simulated network create new ephemeral addresses if insufficient private keys were provided - // we ignore key at index 0, because it is the root key, which is not used during the test - // for contract deployment and interaction - // we create new addresses only on the simulated network to protect against fund loss - if in.Blockchains[0].ChainID == "1337" && len(pks)-1 != testcase.UpkeepCount { - bcNode := in.Blockchains[0].Out.Nodes[0] - c, _, _, err := products.ETHClient( - t.Context(), - bcNode.ExternalWSUrl, - config.GasSettings.FeeCapMultiplier, - config.GasSettings.TipCapMultiplier, - ) - require.NoError(t, err, "Failed to create ETH client") - - newPks, err := products.FundNewAddresses(t.Context(), testcase.UpkeepCount, c, testcase.TestKeyFundingEth) - require.NoError(t, err, "Failed to fund new addresses") - pks = append(pks, newPks...) - } - require.GreaterOrEqual(t, len(pks), testcase.UpkeepCount+1, "you must provide at least %d private keys", testcase.UpkeepCount+1) - chainID, err := strconv.ParseUint(in.Blockchains[0].ChainID, 10, 64) - require.NoError(t, err, "Failed to parse chain ID") - - chainClient, err := products.InitSeth(in.Blockchains[0].Out.Nodes[0].ExternalWSUrl, pks, &chainID) - require.NoError(t, err, "Failed to create chain client") - - test, err := NewTest(l, chainClient, config) - require.NoError(t, err, "Failed to create test") - - // Fund the registry with 1 LINK * amount of KeeperConsumerPerformance contracts - err = test.LinkToken.Transfer(test.Registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(testcase.UpkeepCount)))) - require.NoError(t, err, "Funding keeper registry contract shouldn't fail") - - sb, err := chainClient.Client.BlockNumber(t.Context()) - require.NoError(t, err, "Failed to get start block") - - t.Cleanup(func() { - automation_tests.GetStalenessReportCleanupFn(t, l, chainClient, sb, test.Registry, testcase.RegistryVersion)() - }) - - err = automation.DeployMultiCallAndFundDeploymentAddresses(chainClient, test.LinkToken, testcase.UpkeepCount, big.NewInt(0).Mul(big.NewInt(testcase.UpkeepFundingLink), big.NewInt(1e18))) - require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") - - consumersPerformance := keepers.DeployKeeperConsumersPerformance( - t, - chainClient, - testcase.UpkeepCount, - 10000, // How many blocks this upkeep will be eligible from first upkeep block - 5, // Interval of blocks that upkeeps are expected to be performed - 100000, // How much gas should be burned on checkUpkeep() calls - 4000000, // How much gas should be burned on performUpkeep() calls. Initially set higher than defaultUpkeepGasLimit - ) - - var upkeepsAddresses []string - for _, upkeep := range consumersPerformance { - upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) - } - - upkeepIDs := automation.RegisterUpkeepContracts(t, chainClient, test.LinkToken, big.NewInt(0).Mul(big.NewInt(testcase.UpkeepFundingLink), big.NewInt(1e18)), defaultUpkeepGasLimit, test.Registry, test.Registrar, testcase.UpkeepCount, upkeepsAddresses, false, false, false, nil) - - consumerPerformance := consumersPerformance[0] - upkeepID := upkeepIDs[0] - - gom := gomega.NewGomegaWithT(t) - // Initially performGas is set high, so performUpkeep reverts and no upkeep should be performed - gom.Consistently(func(g gomega.Gomega) { - // Consumer count should remain at 0 - cnt, err := consumerPerformance.GetUpkeepCount(t.Context()) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's Counter shouldn't fail") - g.Expect(cnt.Int64()).Should( - gomega.Equal(int64(0)), - "Expected consumer counter to remain constant at %d, but got %d", 0, cnt.Int64(), - ) - - // Not even reverted upkeeps should be performed. Last keeper for the upkeep should be 0 address - upkeepInfo, err := test.Registry.GetUpkeepInfo(t.Context(), upkeepID) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Registry's getUpkeep shouldn't fail") - g.Expect(upkeepInfo.LastKeeper).Should(gomega.Equal(zeroAddress.String()), "Last keeper should be zero address") - }, testcase.UpkeepExecutionTimeout, "1s").Should(gomega.Succeed()) - - // Set performGas on consumer to be low, so that performUpkeep starts becoming successful - err = consumerPerformance.SetPerformGasToBurn(t.Context(), big.NewInt(100000)) - require.NoError(t, err, "Error setting PerformGasToBurn") - - // Upkeep should now start performing - gom.Eventually(func(g gomega.Gomega) error { - cnt, err := consumerPerformance.GetUpkeepCount(t.Context()) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's Counter shouldn't fail") - g.Expect(cnt.Int64()).Should(gomega.BeNumerically(">", int64(0)), - "Expected consumer counter to be greater than 0, but got %d", cnt.Int64(), - ) - return nil - }, testcase.UpkeepExecutionTimeout, "1s").Should(gomega.Succeed()) - }) - } -} - -func TestKeeperCheckPerformGasLimit(t *testing.T) { - testcases := []testcase{ - { - Name: "registry_1_2", - RegistryVersion: contracts.RegistryVersion_1_2, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - ExpectedUpkeepExecutions: defaultExpectedUpkeepExecutions, - UpkeepExecutionTimeout: "3m", - }, - { - Name: "registry_1_3", - RegistryVersion: contracts.RegistryVersion_1_3, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - ExpectedUpkeepExecutions: defaultExpectedUpkeepExecutions, - UpkeepExecutionTimeout: "3m", - }, - } - - for _, testcase := range testcases { - t.Run(testcase.Name, func(t *testing.T) { - l := framework.L - t.Cleanup(func() { - cleanupErr := products.CleanupContainerLogs(products.DefaultSettings()) - require.NoError(t, cleanupErr, "failed to process cleanup container logs") - }) - - outputFile := "../../env-out.toml" - in, err := de.LoadOutput[de.Cfg](outputFile) - require.NoError(t, err) - pdConfig, err := products.LoadOutput[keepers.Configurator](outputFile) - require.NoError(t, err) - - var config *keepers.Keepers - for _, candidate := range pdConfig.Config { - if candidate.MustGetRegistryVersion() == testcase.RegistryVersion { - config = candidate - } - } - require.NotNil(t, config, "failed to find matching config with registry version %v", testcase.RegistryVersion.String()) - - pks := []string{products.NetworkPrivateKey()} - - require.Equal(t, "1337", in.Blockchains[0].ChainID, "automation smoke tests can only be run on simulated network. If do want to run on a live network, please read the code, understand the implications (e.g. potential fund loss) and adjust the test accordingly") - - // on simulated network create new ephemeral addresses if insufficient private keys were provided - // we ignore key at index 0, because it is the root key, which is not used during the test - // for contract deployment and interaction - // we create new addresses only on the simulated network to protect against fund loss - if in.Blockchains[0].ChainID == "1337" && len(pks)-1 != testcase.UpkeepCount { - bcNode := in.Blockchains[0].Out.Nodes[0] - c, _, _, err := products.ETHClient( - t.Context(), - bcNode.ExternalWSUrl, - config.GasSettings.FeeCapMultiplier, - config.GasSettings.TipCapMultiplier, - ) - require.NoError(t, err, "Failed to create ETH client") - - newPks, err := products.FundNewAddresses(t.Context(), testcase.UpkeepCount, c, testcase.TestKeyFundingEth) - require.NoError(t, err, "Failed to fund new addresses") - pks = append(pks, newPks...) - } - require.GreaterOrEqual(t, len(pks), testcase.UpkeepCount+1, "you must provide at least %d private keys", testcase.UpkeepCount+1) - chainID, err := strconv.ParseUint(in.Blockchains[0].ChainID, 10, 64) - require.NoError(t, err, "Failed to parse chain ID") - - chainClient, err := products.InitSeth(in.Blockchains[0].Out.Nodes[0].ExternalWSUrl, pks, &chainID) - require.NoError(t, err, "Failed to create chain client") - - test, err := NewTest(l, chainClient, config) - require.NoError(t, err, "Failed to create test") - - // Fund the registry with 1 LINK * amount of KeeperConsumerPerformance contracts - err = test.LinkToken.Transfer(test.Registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(testcase.UpkeepCount)))) - require.NoError(t, err, "Funding keeper registry contract shouldn't fail") - - sb, err := chainClient.Client.BlockNumber(t.Context()) - require.NoError(t, err, "Failed to get start block") - - t.Cleanup(func() { - automation_tests.GetStalenessReportCleanupFn(t, l, chainClient, sb, test.Registry, testcase.RegistryVersion)() - }) - - err = automation.DeployMultiCallAndFundDeploymentAddresses(chainClient, test.LinkToken, testcase.UpkeepCount, big.NewInt(0).Mul(big.NewInt(testcase.UpkeepFundingLink), big.NewInt(1e18))) - require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") - - consumersPerformance := keepers.DeployKeeperConsumersPerformance( - t, - chainClient, - testcase.UpkeepCount, - 10000, // How many blocks this upkeep will be eligible from first upkeep block - 5, // Interval of blocks that upkeeps are expected to be performed - 100000, // How much gas should be burned on checkUpkeep() calls - 4000000, // How much gas should be burned on performUpkeep() calls. Initially set higher than defaultUpkeepGasLimit - ) - - var upkeepsAddresses []string - for _, upkeep := range consumersPerformance { - upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) - } - - upkeepIDs := automation.RegisterUpkeepContracts(t, chainClient, test.LinkToken, big.NewInt(0).Mul(big.NewInt(testcase.UpkeepFundingLink), big.NewInt(1e18)), defaultUpkeepGasLimit, test.Registry, test.Registrar, testcase.UpkeepCount, upkeepsAddresses, false, false, false, nil) - - gom := gomega.NewGomegaWithT(t) - // Initially performGas is set higher than defaultUpkeepGasLimit, so no upkeep should be performed - l.Info().Msg("Waiting for 1m for upkeeps to be performed") - gom.Consistently(func(g gomega.Gomega) { - for i := range upkeepIDs { - cnt, err := consumersPerformance[i].GetUpkeepCount(t.Context()) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail") - g.Expect(cnt.Int64()).Should( - gomega.Equal(int64(0)), - "Expected consumer counter to remain constant at %d, but got %d", 0, cnt.Int64(), - ) - } - }, testcase.UpkeepExecutionTimeout, "1s").Should(gomega.Succeed()) - - // Increase gas limit for the upkeep, higher than the performGasBurn - l.Info().Msg("Setting upkeep gas limit higher than performGasBurn") - for i := range upkeepIDs { - err = test.Registry.SetUpkeepGasLimit(upkeepIDs[i], uint32(4500000)) - require.NoError(t, err, "Error setting Upkeep gas limit") - } - - // Upkeep should now start performing - l.Info().Msg("Waiting for 1m for upkeeps to be performed") - gom.Eventually(func(g gomega.Gomega) { - for i := range upkeepIDs { - cnt, err := consumersPerformance[i].GetUpkeepCount(t.Context()) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail") - g.Expect(cnt.Int64()).Should(gomega.BeNumerically(">", int64(0)), - "Expected consumer counter to be greater than 0, but got %d", cnt.Int64(), - ) - } - }, testcase.UpkeepExecutionTimeout, "1s").Should(gomega.Succeed()) - - // Now increase the checkGasBurn on consumer, upkeep should stop performing - l.Info().Msg("Setting checkGasBurn higher than performGasBurn") - for i := range upkeepIDs { - err = consumersPerformance[i].SetCheckGasToBurn(t.Context(), big.NewInt(3000000)) - require.NoError(t, err, "Error setting CheckGasToBurn") - } - - // Get existing performed count - existingCnts := make(map[*big.Int]*big.Int) - for i := range upkeepIDs { - existingCnt, err := consumersPerformance[i].GetUpkeepCount(t.Context()) - existingCnts[upkeepIDs[i]] = existingCnt - require.NoError(t, err, "Error calling consumer's counter") - l.Info().Int64("Upkeep counter", existingCnt.Int64()).Msg("Check Gas Increased") - } - - // In most cases count should remain constant, but there might be a straggling perform tx which - // gets committed later. Since every keeper node cannot have more than 1 straggling tx, it - // is sufficient to check that the upkeep count does not increase by more than 6. - l.Info().Msg("Waiting for 3m to make sure no more than 6 upkeeps are performed") - gom.Consistently(func(g gomega.Gomega) { - for i := range upkeepIDs { - cnt, err := consumersPerformance[i].GetUpkeepCount(t.Context()) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail") - existingCnt := existingCnts[upkeepIDs[i]] - g.Expect(cnt.Int64()).Should( - gomega.BeNumerically("<=", existingCnt.Int64()+numUpkeepsAllowedForStragglingTxs), - "Expected consumer counter to remain constant at %d, but got %d", existingCnt.Int64(), cnt.Int64(), - ) - } - }, testcase.UpkeepExecutionTimeout, "1s").Should(gomega.Succeed()) - - for i := range upkeepIDs { - existingCnt, err := consumersPerformance[i].GetUpkeepCount(t.Context()) - existingCnts[upkeepIDs[i]] = existingCnt - require.NoError(t, err, "Error calling consumer's counter") - l.Info().Int64("Upkeep counter", existingCnt.Int64()).Msg("Upkeep counter when consistently block finished") - } - - // Now increase checkGasLimit on registry - highCheckGasLimit := keeperDefaultRegistryConfig - highCheckGasLimit.CheckGasLimit = uint32(5000000) - err = test.Registry.SetConfig(highCheckGasLimit, contracts.OCRv2Config{}) - require.NoError(t, err, "Error setting registry config") - - t.Cleanup(func() { - err = test.Registry.SetConfig(keeperDefaultRegistryConfig, contracts.OCRv2Config{}) - require.NoError(t, err, "Error setting registry config") - }) - - // Upkeep should start performing again, and it should get regularly performed - l.Info().Msg("Waiting for 1m for upkeeps to be performed") - gom.Eventually(func(g gomega.Gomega) { - for i := range upkeepIDs { - cnt, err := consumersPerformance[i].GetUpkeepCount(t.Context()) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's Counter shouldn't fail") - existingCnt := existingCnts[upkeepIDs[i]] - g.Expect(cnt.Int64()).Should(gomega.BeNumerically(">", existingCnt.Int64()), - "Expected consumer counter to be greater than %d, but got %d", existingCnt.Int64(), cnt.Int64(), - ) - } - }, testcase.UpkeepExecutionTimeout, "1s").Should(gomega.Succeed()) - }) - } -} - -func TestKeeperRegisterUpkeep(t *testing.T) { - testcases := []testcase{ - { - Name: "registry_1_1", - RegistryVersion: contracts.RegistryVersion_1_1, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - UpkeepExecutionTimeout: "1m", - }, - { - Name: "registry_1_2", - RegistryVersion: contracts.RegistryVersion_1_2, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - UpkeepExecutionTimeout: "1m", - }, - { - Name: "registry_1_3", - RegistryVersion: contracts.RegistryVersion_1_3, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - UpkeepExecutionTimeout: "1m", - }, - } - - for _, testcase := range testcases { - t.Run(testcase.Name, func(t *testing.T) { - l := framework.L - t.Cleanup(func() { - cleanupErr := products.CleanupContainerLogs(products.DefaultSettings()) - require.NoError(t, cleanupErr, "failed to process cleanup container logs") - }) - - outputFile := "../../env-out.toml" - in, err := de.LoadOutput[de.Cfg](outputFile) - require.NoError(t, err) - pdConfig, err := products.LoadOutput[keepers.Configurator](outputFile) - require.NoError(t, err) - - var config *keepers.Keepers - for _, candidate := range pdConfig.Config { - if candidate.MustGetRegistryVersion() == testcase.RegistryVersion { - config = candidate - } - } - require.NotNil(t, config, "failed to find matching config with registry version %v", testcase.RegistryVersion.String()) - - pks := []string{products.NetworkPrivateKey()} - - require.Equal(t, "1337", in.Blockchains[0].ChainID, "automation smoke tests can only be run on simulated network. If do want to run on a live network, please read the code, understand the implications (e.g. potential fund loss) and adjust the test accordingly") - - // on simulated network create new ephemeral addresses if insufficient private keys were provided - // we ignore key at index 0, because it is the root key, which is not used during the test - // for contract deployment and interaction - // we create new addresses only on the simulated network to protect against fund loss - if in.Blockchains[0].ChainID == "1337" && len(pks)-1 != testcase.UpkeepCount { - bcNode := in.Blockchains[0].Out.Nodes[0] - c, _, _, err := products.ETHClient( - t.Context(), - bcNode.ExternalWSUrl, - config.GasSettings.FeeCapMultiplier, - config.GasSettings.TipCapMultiplier, - ) - require.NoError(t, err, "Failed to create ETH client") - - newPks, err := products.FundNewAddresses(t.Context(), testcase.UpkeepCount, c, testcase.TestKeyFundingEth) - require.NoError(t, err, "Failed to fund new addresses") - pks = append(pks, newPks...) - } - require.GreaterOrEqual(t, len(pks), testcase.UpkeepCount+1, "you must provide at least %d private keys", testcase.UpkeepCount+1) - chainID, err := strconv.ParseUint(in.Blockchains[0].ChainID, 10, 64) - require.NoError(t, err, "Failed to parse chain ID") - - chainClient, err := products.InitSeth(in.Blockchains[0].Out.Nodes[0].ExternalWSUrl, pks, &chainID) - require.NoError(t, err, "Failed to create chain client") - - test, err := NewTest(l, chainClient, config) - require.NoError(t, err, "Failed to create test") - - // Fund the registry with 1 LINK * amount of KeeperConsumerPerformance contracts - err = test.LinkToken.Transfer(test.Registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(testcase.UpkeepCount)))) - require.NoError(t, err, "Funding keeper registry contract shouldn't fail") - - sb, err := chainClient.Client.BlockNumber(t.Context()) - require.NoError(t, err, "Failed to get start block") - - consumers, upkeepIDs := automation.DeployLegacyConsumers(t, chainClient, test.Registry, test.Registrar, test.LinkToken, testcase.UpkeepCount, big.NewInt(0).Mul(big.NewInt(testcase.UpkeepFundingLink), big.NewInt(1e18)), defaultUpkeepGasLimit, false, false, false, nil) - - t.Cleanup(func() { - automation_tests.GetStalenessReportCleanupFn(t, l, chainClient, sb, test.Registry, testcase.RegistryVersion)() - }) - - var initialCounters = make([]*big.Int, len(upkeepIDs)) - - gom := gomega.NewGomegaWithT(t) - // Observe that the upkeeps which are initially registered are performing and - // store the value of their initial counters in order to compare later on that the value increased. - gom.Eventually(func(g gomega.Gomega) error { - for i := range upkeepIDs { - counter, err := consumers[i].Counter(t.Context()) - initialCounters[i] = counter - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter"+ - " for upkeep at index "+strconv.Itoa(i)) - g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(0)), - "Expected consumer counter to be greater than 0, but got %d", counter.Int64()) - l.Info(). - Int64("Upkeep counter", counter.Int64()). - Int("Upkeep ID", i). - Msg("Number of upkeeps performed") - } - return nil - }, "1m", "1s").Should(gomega.Succeed()) - - newConsumers, _ := automation.RegisterNewUpkeeps(t, chainClient, test.LinkToken, test.Registry, test.Registrar, defaultUpkeepGasLimit, 1) - - // We know that newConsumers has size 1, so we can just use the newly registered upkeep. - newUpkeep := newConsumers[0] - - // Test that the newly registered upkeep is also performing. - gom.Eventually(func(g gomega.Gomega) error { - counter, err := newUpkeep.Counter(t.Context()) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling newly deployed upkeep's counter shouldn't fail") - g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(0)), - "Expected newly registered upkeep's counter to be greater than 0, but got %d", counter.Int64()) - l.Info().Msg("Newly registered upkeeps performed " + strconv.Itoa(int(counter.Int64())) + " times") - return nil - }, testcase.UpkeepExecutionTimeout, "1s").Should(gomega.Succeed()) - - gom.Eventually(func(g gomega.Gomega) error { - for i := range upkeepIDs { - currentCounter, err := consumers[i].Counter(t.Context()) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail") - - l.Info(). - Int("Upkeep ID", i). - Int64("Upkeep counter", currentCounter.Int64()). - Int64("initial counter", initialCounters[i].Int64()). - Msg("Number of upkeeps performed") - - g.Expect(currentCounter.Int64()).Should(gomega.BeNumerically(">", initialCounters[i].Int64()), - "Expected counter to have increased from initial value of %s, but got %s", - initialCounters[i], currentCounter) - } - return nil - }, testcase.UpkeepExecutionTimeout, "1s").Should(gomega.Succeed()) - }) - } -} - -func TestKeeperAddFunds(t *testing.T) { - testcases := []testcase{ - { - Name: "registry_1_1", - RegistryVersion: contracts.RegistryVersion_1_1, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - UpkeepExecutionTimeout: "1m", - }, - { - Name: "registry_1_2", - RegistryVersion: contracts.RegistryVersion_1_2, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - UpkeepExecutionTimeout: "1m", - }, - { - Name: "registry_1_3", - RegistryVersion: contracts.RegistryVersion_1_3, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - UpkeepExecutionTimeout: "1m", - }, - } - - for _, testcase := range testcases { - t.Run(testcase.Name, func(t *testing.T) { - l := framework.L - t.Cleanup(func() { - cleanupErr := products.CleanupContainerLogs(products.DefaultSettings()) - require.NoError(t, cleanupErr, "failed to process cleanup container logs") - }) - - outputFile := "../../env-out.toml" - in, err := de.LoadOutput[de.Cfg](outputFile) - require.NoError(t, err) - pdConfig, err := products.LoadOutput[keepers.Configurator](outputFile) - require.NoError(t, err) - - var config *keepers.Keepers - for _, candidate := range pdConfig.Config { - if candidate.MustGetRegistryVersion() == testcase.RegistryVersion { - config = candidate - } - } - require.NotNil(t, config, "failed to find matching config with registry version %v", testcase.RegistryVersion.String()) - - pks := []string{products.NetworkPrivateKey()} - - require.Equal(t, "1337", in.Blockchains[0].ChainID, "automation smoke tests can only be run on simulated network. If do want to run on a live network, please read the code, understand the implications (e.g. potential fund loss) and adjust the test accordingly") - - // on simulated network create new ephemeral addresses if insufficient private keys were provided - // we ignore key at index 0, because it is the root key, which is not used during the test - // for contract deployment and interaction - // we create new addresses only on the simulated network to protect against fund loss - if in.Blockchains[0].ChainID == "1337" && len(pks)-1 != testcase.UpkeepCount { - bcNode := in.Blockchains[0].Out.Nodes[0] - c, _, _, err := products.ETHClient( - t.Context(), - bcNode.ExternalWSUrl, - config.GasSettings.FeeCapMultiplier, - config.GasSettings.TipCapMultiplier, - ) - require.NoError(t, err, "Failed to create ETH client") - - newPks, err := products.FundNewAddresses(t.Context(), testcase.UpkeepCount, c, testcase.TestKeyFundingEth) - require.NoError(t, err, "Failed to fund new addresses") - pks = append(pks, newPks...) - } - require.GreaterOrEqual(t, len(pks), testcase.UpkeepCount+1, "you must provide at least %d private keys", testcase.UpkeepCount+1) - chainID, err := strconv.ParseUint(in.Blockchains[0].ChainID, 10, 64) - require.NoError(t, err, "Failed to parse chain ID") - - chainClient, err := products.InitSeth(in.Blockchains[0].Out.Nodes[0].ExternalWSUrl, pks, &chainID) - require.NoError(t, err, "Failed to create chain client") - - test, err := NewTest(l, chainClient, config) - require.NoError(t, err, "Failed to create test") - - // Fund the registry with 1 LINK * amount of KeeperConsumerPerformance contracts - err = test.LinkToken.Transfer(test.Registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(testcase.UpkeepCount)))) - require.NoError(t, err, "Funding keeper registry contract shouldn't fail") - - sb, err := chainClient.Client.BlockNumber(t.Context()) - require.NoError(t, err, "Failed to get start block") - - // don't fund the upkeeps with LINK, we will add funds later - consumers, upkeepIDs := automation.DeployLegacyConsumers(t, chainClient, test.Registry, test.Registrar, test.LinkToken, testcase.UpkeepCount, big.NewInt(1), defaultUpkeepGasLimit, false, false, false, nil) - - t.Cleanup(func() { - automation_tests.GetStalenessReportCleanupFn(t, l, chainClient, sb, test.Registry, testcase.RegistryVersion)() - }) - // Since the upkeep is currently underfunded, check that it doesn't get executed - gom := gomega.NewGomegaWithT(t) - l.Info().Msg("Waiting for 1m to make sure no upkeeps are performed") - gom.Consistently(func(g gomega.Gomega) { - for i := range upkeepIDs { - counter, err := consumers[i].Counter(t.Context()) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail") - g.Expect(counter.Int64()).Should(gomega.Equal(int64(0)), - "Expected consumer counter to remain zero, but got %d", counter.Int64()) - } - }, testcase.UpkeepExecutionTimeout, "1s").Should(gomega.Succeed()) - - // Grant permission to the registry to fund the upkeep - err = test.LinkToken.Approve(test.Registry.Address(), big.NewInt(0).Mul(big.NewInt(9e18), big.NewInt(int64(len(upkeepIDs))))) - require.NoError(t, err, "Error approving permissions for registry") - - // Add funds to the upkeep whose ID we know from above - l.Info().Msg("Adding funds to upkeeps") - for i := range upkeepIDs { - err = test.Registry.AddUpkeepFunds(upkeepIDs[i], big.NewInt(9e18)) - require.NoError(t, err, "Error funding upkeep") - } - - // Now the new upkeep should be performing because we added enough funds - gom.Eventually(func(g gomega.Gomega) { - for i := range upkeepIDs { - counter, err := consumers[i].Counter(t.Context()) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail") - g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(0)), - "Expected newly registered upkeep's counter to be greater than 0, but got %d", counter.Int64()) - } - }, testcase.UpkeepExecutionTimeout, "1s").Should(gomega.Succeed()) - }) - } -} - -func TestKeeperRemove(t *testing.T) { - testcases := []testcase{ - { - Name: "registry_1_1", - RegistryVersion: contracts.RegistryVersion_1_1, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - UpkeepExecutionTimeout: "1m", - }, - { - Name: "registry_1_2", - RegistryVersion: contracts.RegistryVersion_1_2, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - UpkeepExecutionTimeout: "1m", - }, - { - Name: "registry_1_3", - RegistryVersion: contracts.RegistryVersion_1_3, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - UpkeepExecutionTimeout: "1m", - }, - } - - for _, testcase := range testcases { - t.Run(testcase.Name, func(t *testing.T) { - l := framework.L - t.Cleanup(func() { - cleanupErr := products.CleanupContainerLogs(products.DefaultSettings()) - require.NoError(t, cleanupErr, "failed to process cleanup container logs") - }) - - outputFile := "../../env-out.toml" - in, err := de.LoadOutput[de.Cfg](outputFile) - require.NoError(t, err) - pdConfig, err := products.LoadOutput[keepers.Configurator](outputFile) - require.NoError(t, err) - - var config *keepers.Keepers - for _, candidate := range pdConfig.Config { - if candidate.MustGetRegistryVersion() == testcase.RegistryVersion { - config = candidate - } - } - require.NotNil(t, config, "failed to find matching config with registry version %v", testcase.RegistryVersion.String()) - - pks := []string{products.NetworkPrivateKey()} - - require.Equal(t, "1337", in.Blockchains[0].ChainID, "automation smoke tests can only be run on simulated network. If do want to run on a live network, please read the code, understand the implications (e.g. potential fund loss) and adjust the test accordingly") - - // on simulated network create new ephemeral addresses if insufficient private keys were provided - // we ignore key at index 0, because it is the root key, which is not used during the test - // for contract deployment and interaction - // we create new addresses only on the simulated network to protect against fund loss - if in.Blockchains[0].ChainID == "1337" && len(pks)-1 != testcase.UpkeepCount { - bcNode := in.Blockchains[0].Out.Nodes[0] - c, _, _, err := products.ETHClient( - t.Context(), - bcNode.ExternalWSUrl, - config.GasSettings.FeeCapMultiplier, - config.GasSettings.TipCapMultiplier, - ) - require.NoError(t, err, "Failed to create ETH client") - - newPks, err := products.FundNewAddresses(t.Context(), testcase.UpkeepCount, c, testcase.TestKeyFundingEth) - require.NoError(t, err, "Failed to fund new addresses") - pks = append(pks, newPks...) - } - require.GreaterOrEqual(t, len(pks), testcase.UpkeepCount+1, "you must provide at least %d private keys", testcase.UpkeepCount+1) - chainID, err := strconv.ParseUint(in.Blockchains[0].ChainID, 10, 64) - require.NoError(t, err, "Failed to parse chain ID") - - chainClient, err := products.InitSeth(in.Blockchains[0].Out.Nodes[0].ExternalWSUrl, pks, &chainID) - require.NoError(t, err, "Failed to create chain client") - - test, err := NewTest(l, chainClient, config) - require.NoError(t, err, "Failed to create test") - - // Fund the registry with 1 LINK * amount of KeeperConsumerPerformance contracts - err = test.LinkToken.Transfer(test.Registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(testcase.UpkeepCount)))) - require.NoError(t, err, "Funding keeper registry contract shouldn't fail") - - sb, err := chainClient.Client.BlockNumber(t.Context()) - require.NoError(t, err, "Failed to get start block") - - consumers, upkeepIDs := automation.DeployLegacyConsumers(t, chainClient, test.Registry, test.Registrar, test.LinkToken, testcase.UpkeepCount, big.NewInt(0).Mul(big.NewInt(testcase.UpkeepFundingLink), big.NewInt(1e18)), defaultUpkeepGasLimit, false, false, false, nil) - - t.Cleanup(func() { - automation_tests.GetStalenessReportCleanupFn(t, l, chainClient, sb, test.Registry, testcase.RegistryVersion)() - }) - var initialCounters = make([]*big.Int, len(upkeepIDs)) - - gom := gomega.NewGomegaWithT(t) - // Make sure the upkeeps are running before we remove a keeper - gom.Eventually(func(g gomega.Gomega) error { - for upkeepID := range upkeepIDs { - counter, err := consumers[upkeepID].Counter(t.Context()) - initialCounters[upkeepID] = counter - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter"+ - " for upkeep with ID "+strconv.Itoa(upkeepID)) - g.Expect(counter.Cmp(big.NewInt(0))).To(gomega.Equal(1), "Expected consumer counter to be greater than 0, but got %s", counter) - } - return nil - }, testcase.UpkeepExecutionTimeout, "1s").Should(gomega.Succeed()) - - keepers, err := test.Registry.GetKeeperList(t.Context()) - require.NoError(t, err, "Error getting list of Keepers") - - // Remove the first keeper from the list - require.GreaterOrEqual(t, len(keepers), 2, "Expected there to be at least 2 keepers") - newKeeperList := keepers[1:] - - cl, err := clclient.New(in.NodeSets[0].Out.CLNodes) - require.NoError(t, err, "Failed to create chainlink client") - - // Construct the addresses of the payees required by the SetKeepers function - payees := make([]string, len(keepers)-1) - for i := range payees { - payees[i], err = cl[0].PrimaryEthAddress() - require.NoError(t, err, "Error building payee list") - } - - err = test.Registry.SetKeepers(newKeeperList, payees, contracts.OCRv2Config{}) - require.NoError(t, err, "Error setting new list of Keepers") - l.Info().Msg("Successfully removed keeper at address " + keepers[0] + " from the list of Keepers") - - // The upkeeps should still perform and their counters should have increased compared to the first check - gom.Eventually(func(g gomega.Gomega) error { - for i := range upkeepIDs { - counter, err := consumers[i].Counter(t.Context()) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i) - g.Expect(counter.Cmp(initialCounters[i])).To(gomega.Equal(1), "Expected consumer counter to be greater "+ - "than initial counter which was %s, but got %s", initialCounters[i], counter) - } - return nil - }, testcase.UpkeepExecutionTimeout, "1s").Should(gomega.Succeed()) - }) - } -} - -func TestKeeperPauseRegistry(t *testing.T) { - testcases := []testcase{ - { - Name: "registry_1_1", - RegistryVersion: contracts.RegistryVersion_1_1, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - UpkeepExecutionTimeout: "1m", - }, - { - Name: "registry_1_2", - RegistryVersion: contracts.RegistryVersion_1_2, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - UpkeepExecutionTimeout: "1m", - }, - { - Name: "registry_1_3", - RegistryVersion: contracts.RegistryVersion_1_3, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - UpkeepExecutionTimeout: "1m", - }, - } - - for _, testcase := range testcases { - t.Run(testcase.Name, func(t *testing.T) { - l := framework.L - t.Cleanup(func() { - cleanupErr := products.CleanupContainerLogs(products.DefaultSettings()) - require.NoError(t, cleanupErr, "failed to process cleanup container logs") - }) - - outputFile := "../../env-out.toml" - in, err := de.LoadOutput[de.Cfg](outputFile) - require.NoError(t, err) - pdConfig, err := products.LoadOutput[keepers.Configurator](outputFile) - require.NoError(t, err) - - var config *keepers.Keepers - for _, candidate := range pdConfig.Config { - if candidate.MustGetRegistryVersion() == testcase.RegistryVersion { - config = candidate - } - } - require.NotNil(t, config, "failed to find matching config with registry version %v", testcase.RegistryVersion.String()) - - pks := []string{products.NetworkPrivateKey()} - - require.Equal(t, "1337", in.Blockchains[0].ChainID, "automation smoke tests can only be run on simulated network. If do want to run on a live network, please read the code, understand the implications (e.g. potential fund loss) and adjust the test accordingly") - - // on simulated network create new ephemeral addresses if insufficient private keys were provided - // we ignore key at index 0, because it is the root key, which is not used during the test - // for contract deployment and interaction - // we create new addresses only on the simulated network to protect against fund loss - if in.Blockchains[0].ChainID == "1337" && len(pks)-1 != testcase.UpkeepCount { - bcNode := in.Blockchains[0].Out.Nodes[0] - c, _, _, err := products.ETHClient( - t.Context(), - bcNode.ExternalWSUrl, - config.GasSettings.FeeCapMultiplier, - config.GasSettings.TipCapMultiplier, - ) - require.NoError(t, err, "Failed to create ETH client") - - newPks, err := products.FundNewAddresses(t.Context(), testcase.UpkeepCount, c, testcase.TestKeyFundingEth) - require.NoError(t, err, "Failed to fund new addresses") - pks = append(pks, newPks...) - } - require.GreaterOrEqual(t, len(pks), testcase.UpkeepCount+1, "you must provide at least %d private keys", testcase.UpkeepCount+1) - chainID, err := strconv.ParseUint(in.Blockchains[0].ChainID, 10, 64) - require.NoError(t, err, "Failed to parse chain ID") - - chainClient, err := products.InitSeth(in.Blockchains[0].Out.Nodes[0].ExternalWSUrl, pks, &chainID) - require.NoError(t, err, "Failed to create chain client") - - test, err := NewTest(l, chainClient, config) - require.NoError(t, err, "Failed to create test") - - // Fund the registry with 1 LINK * amount of KeeperConsumerPerformance contracts - err = test.LinkToken.Transfer(test.Registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(testcase.UpkeepCount)))) - require.NoError(t, err, "Funding keeper registry contract shouldn't fail") - - sb, err := chainClient.Client.BlockNumber(t.Context()) - require.NoError(t, err, "Failed to get start block") - - consumers, upkeepIDs := automation.DeployLegacyConsumers(t, chainClient, test.Registry, test.Registrar, test.LinkToken, testcase.UpkeepCount, big.NewInt(0).Mul(big.NewInt(testcase.UpkeepFundingLink), big.NewInt(1e18)), defaultUpkeepGasLimit, false, false, false, nil) - - t.Cleanup(func() { - automation_tests.GetStalenessReportCleanupFn(t, l, chainClient, sb, test.Registry, testcase.RegistryVersion)() - }) - - gom := gomega.NewGomegaWithT(t) - // Observe that the upkeeps which are initially registered are performing - gom.Eventually(func(g gomega.Gomega) error { - for i := range upkeepIDs { - counter, err := consumers[i].Counter(t.Context()) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i) - g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(0)), - "Expected consumer counter to be greater than 0, but got %d") - } - return nil - }, testcase.UpkeepExecutionTimeout, "1s").Should(gomega.Succeed()) - - // Pause the registry - err = test.Registry.Pause() - require.NoError(t, err, "Error pausing the registry") - - t.Cleanup(func() { - err = test.Registry.Unpause() - require.NoError(t, err, "Error unpausing the registry") - }) - - // Store how many times each upkeep performed once the registry was successfully paused - var countersAfterPause = make([]*big.Int, len(upkeepIDs)) - for i := range upkeepIDs { - countersAfterPause[i], err = consumers[i].Counter(t.Context()) - require.NoError(t, err, "Error retrieving consumer at index %d", i) - } - - // After we paused the registry, the counters of all the upkeeps should stay constant - // because they are no longer getting serviced - gom.Consistently(func(g gomega.Gomega) { - for i := range upkeepIDs { - latestCounter, err := consumers[i].Counter(t.Context()) - require.NoError(t, err, "Error retrieving consumer contract at index %d", i) - g.Expect(latestCounter.Int64()).Should(gomega.Equal(countersAfterPause[i].Int64()), - "Expected consumer counter to remain constant at %d, but got %d", - countersAfterPause[i].Int64(), latestCounter.Int64()) - } - }, testcase.UpkeepExecutionTimeout, "1s").Should(gomega.Succeed()) - }) - } -} - -func TestKeeperMigrateRegistry(t *testing.T) { - testcases := []testcase{ - { - Name: "registry_1_2", - RegistryVersion: contracts.RegistryVersion_1_2, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - UpkeepExecutionTimeout: "1m", - }, - } - - for _, testcase := range testcases { - t.Run(testcase.Name, func(t *testing.T) { - l := framework.L - t.Cleanup(func() { - cleanupErr := products.CleanupContainerLogs(products.DefaultSettings()) - require.NoError(t, cleanupErr, "failed to process cleanup container logs") - }) - - outputFile := "../../env-out.toml" - in, err := de.LoadOutput[de.Cfg](outputFile) - require.NoError(t, err) - pdConfig, err := products.LoadOutput[keepers.Configurator](outputFile) - require.NoError(t, err) - - var config *keepers.Keepers - for _, candidate := range pdConfig.Config { - if candidate.MustGetRegistryVersion() == testcase.RegistryVersion { - config = candidate - } - } - require.NotNil(t, config, "failed to find matching config with registry version %v", testcase.RegistryVersion.String()) - - pks := []string{products.NetworkPrivateKey()} - - require.Equal(t, "1337", in.Blockchains[0].ChainID, "automation smoke tests can only be run on simulated network. If do want to run on a live network, please read the code, understand the implications (e.g. potential fund loss) and adjust the test accordingly") - - // on simulated network create new ephemeral addresses if insufficient private keys were provided - // we ignore key at index 0, because it is the root key, which is not used during the test - // for contract deployment and interaction - // we create new addresses only on the simulated network to protect against fund loss - if in.Blockchains[0].ChainID == "1337" && len(pks)-1 != testcase.UpkeepCount { - bcNode := in.Blockchains[0].Out.Nodes[0] - c, _, _, err := products.ETHClient( - t.Context(), - bcNode.ExternalWSUrl, - config.GasSettings.FeeCapMultiplier, - config.GasSettings.TipCapMultiplier, - ) - require.NoError(t, err, "Failed to create ETH client") - - newPks, err := products.FundNewAddresses(t.Context(), testcase.UpkeepCount, c, testcase.TestKeyFundingEth) - require.NoError(t, err, "Failed to fund new addresses") - pks = append(pks, newPks...) - } - require.GreaterOrEqual(t, len(pks), testcase.UpkeepCount+1, "you must provide at least %d private keys", testcase.UpkeepCount+1) - chainID, err := strconv.ParseUint(in.Blockchains[0].ChainID, 10, 64) - require.NoError(t, err, "Failed to parse chain ID") - - chainClient, err := products.InitSeth(in.Blockchains[0].Out.Nodes[0].ExternalWSUrl, pks, &chainID) - require.NoError(t, err, "Failed to create chain client") - - test, err := NewTest(l, chainClient, config) - require.NoError(t, err, "Failed to create test") - - // Fund the registry with 1 LINK * amount of KeeperConsumerPerformance contracts - err = test.LinkToken.Transfer(test.Registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(testcase.UpkeepCount)))) - require.NoError(t, err, "Funding keeper registry contract shouldn't fail") - - sb, err := chainClient.Client.BlockNumber(t.Context()) - require.NoError(t, err, "Failed to get start block") - - consumers, upkeepIDs := automation.DeployLegacyConsumers(t, chainClient, test.Registry, test.Registrar, test.LinkToken, testcase.UpkeepCount, big.NewInt(0).Mul(big.NewInt(testcase.UpkeepFundingLink), big.NewInt(1e18)), defaultUpkeepGasLimit, false, false, false, nil) - - t.Cleanup(func() { - automation_tests.GetStalenessReportCleanupFn(t, l, chainClient, sb, test.Registry, testcase.RegistryVersion)() - }) - - // Deploy the second registry, second registrar, and the same number of upkeeps as the first one - secondEthLinkFeed, err := contracts.DeployMockLINKETHFeed(chainClient, big.NewInt(2e18)) - require.NoError(t, err, "Failed to deploy mock ETH-LINK feed") - - secondGasFeed, err := contracts.DeployMockGASFeed(chainClient, big.NewInt(2e11)) - require.NoError(t, err, "Failed to deploy mock gas feed") - - secondTranscoder, err := contracts.DeployUpkeepTranscoder(chainClient) - require.NoError(t, err, "Failed to deploy upkeep transcoder") - - secondRegistry, err := contracts.DeployKeeperRegistry(chainClient, &contracts.KeeperRegistryOpts{ - RegistryVersion: config.MustGetRegistryVersion(), - LinkAddr: test.LinkToken.Address(), - ETHFeedAddr: secondEthLinkFeed.Address(), - GasFeedAddr: secondGasFeed.Address(), - TranscoderAddr: secondTranscoder.Address(), - RegistrarAddr: zeroAddress.Hex(), - Settings: config.GetRegistryConfig(), - }) - require.NoError(t, err, "Failed to deploy keeper registry") - - registrarSettings := contracts.KeeperRegistrarSettings{ - AutoApproveConfigType: 2, - AutoApproveMaxAllowed: math.MaxUint16, - RegistryAddr: secondRegistry.Address(), - MinLinkJuels: big.NewInt(0), - } - - secondRegistrar, err := keepers.DeployKeeperRegistrar(chainClient, config.MustGetRegistryVersion(), test.LinkToken, registrarSettings, secondRegistry) - require.NoError(t, err, "Failed to deploy keeper registrar") - - err = secondRegistry.SetRegistrar(secondRegistrar.Address()) - require.NoError(t, err, "Failed to set registrar") - - // Fund the registry with 1 LINK * amount of KeeperConsumerPerformance contracts - err = test.LinkToken.Transfer(secondRegistry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(testcase.UpkeepCount)))) - require.NoError(t, err, "Funding keeper registry contract shouldn't fail") - - chainlinkNodes, err := clclient.New(in.NodeSets[0].Out.CLNodes) - require.NoError(t, err, "Failed to create chainlink client") - - // create jobs for the second registry - for _, chainlinkNode := range chainlinkNodes { - chainlinkNodeAddress, err := chainlinkNode.PrimaryEthAddress() - require.NoError(t, err, "Failed to retrieve chainlink node address") - _, err = chainlinkNode.MustCreateJob(&keepers.KeeperJobSpec{ - Name: "keeper-test-" + secondRegistry.Address(), - ContractAddress: secondRegistry.Address(), - FromAddress: chainlinkNodeAddress, - EVMChainID: strconv.FormatInt(chainClient.ChainID, 10), - MinIncomingConfirmations: 1, - }) - require.NoError(t, err, "Failed to create keeper job") - } - - primaryNode := chainlinkNodes[0] - primaryNodeAddress, err := primaryNode.PrimaryEthAddress() - require.NoError(t, err, "Failed to retrieve chainlink node address") - - nodeAddresses := make([]string, 0) - for _, clNode := range chainlinkNodes { - clNodeAddress, err := clNode.PrimaryEthAddress() - require.NoError(t, err, "Failed to retrieve chainlink node address") - nodeAddresses = append(nodeAddresses, clNodeAddress) - } - - nodeAddressesStr, payees := make([]string, 0), make([]string, 0) - for _, cla := range nodeAddresses { - nodeAddressesStr = append(nodeAddressesStr, cla) - payees = append(payees, primaryNodeAddress) - } - - err = secondRegistry.SetKeepers(nodeAddressesStr, payees, contracts.OCRv2Config{}) - require.NoError(t, err, "Failed to set keepers in the registry") - - _, _ = automation.DeployLegacyConsumers(t, chainClient, secondRegistry, secondRegistrar, test.LinkToken, testcase.UpkeepCount, big.NewInt(0).Mul(big.NewInt(testcase.UpkeepFundingLink), big.NewInt(1e18)), defaultUpkeepGasLimit, false, false, false, nil) - - err = secondRegistry.SetMigrationPermissions(common.HexToAddress(test.Registry.Address()), 3) - require.NoError(t, err, "Error setting bidirectional permissions for first registry") - err = test.Registry.SetMigrationPermissions(common.HexToAddress(secondRegistry.Address()), 3) - require.NoError(t, err, "Error setting bidirectional permissions for second registry") - - gom := gomega.NewGomegaWithT(t) - - // Check that the first upkeep from the first registry is performing (before being migrated) - l.Info().Msg("Waiting for 1m for upkeeps to be performed before migration") - gom.Eventually(func(g gomega.Gomega) { - for i := range upkeepIDs { - counterBeforeMigration, err := consumers[i].Counter(t.Context()) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail") - g.Expect(counterBeforeMigration.Int64()).Should(gomega.BeNumerically(">", int64(0)), - "Expected consumer counter to be greater than 0, but got %s", counterBeforeMigration) - } - }, testcase.UpkeepExecutionTimeout, "1s").Should(gomega.Succeed()) - - // Migrate the upkeeps from the first to the second registry - for i := range upkeepIDs { - err = test.Registry.Migrate([]*big.Int{upkeepIDs[i]}, common.HexToAddress(secondRegistry.Address())) - require.NoError(t, err, "Error migrating first upkeep") - } - - // Pause the first registry, in that way we make sure that the upkeep is being performed by the second one - err = test.Registry.Pause() - require.NoError(t, err, "Error pausing registry") - - t.Cleanup(func() { - err = test.Registry.Unpause() - require.NoError(t, err, "Error unpausing the registry") - }) - - counterAfterMigrationPerUpkeep := make(map[*big.Int]*big.Int) - - for i := range upkeepIDs { - counterAfterMigration, err := consumers[i].Counter(t.Context()) - require.NoError(t, err, "Error calling consumer's counter") - counterAfterMigrationPerUpkeep[upkeepIDs[i]] = counterAfterMigration - } - - // Check that once we migrated the upkeep, the counter has increased - l.Info().Msg("Waiting for 1m for upkeeps to be performed after migration") - gom.Eventually(func(g gomega.Gomega) { - for i := range upkeepIDs { - currentCounter, err := consumers[i].Counter(t.Context()) - counterAfterMigration := counterAfterMigrationPerUpkeep[upkeepIDs[i]] - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Calling consumer's counter shouldn't fail") - g.Expect(currentCounter.Int64()).Should(gomega.BeNumerically(">", counterAfterMigration.Int64()), - "Expected counter to have increased, but stayed constant at %s", counterAfterMigration) - } - }, testcase.UpkeepExecutionTimeout, "1s").Should(gomega.Succeed()) - }) - } -} - -func TestKeeperJobReplacement(t *testing.T) { - testcases := []testcase{ - { - Name: "registry_1_3", - RegistryVersion: contracts.RegistryVersion_1_3, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - ExpectedUpkeepExecutions: defaultExpectedUpkeepExecutions, - UpkeepExecutionTimeout: "5m", - }, - } - - for _, testcase := range testcases { - t.Run(testcase.Name, func(t *testing.T) { - l := framework.L - t.Cleanup(func() { - cleanupErr := products.CleanupContainerLogs(products.DefaultSettings()) - require.NoError(t, cleanupErr, "failed to process cleanup container logs") - }) - - outputFile := "../../env-out.toml" - in, err := de.LoadOutput[de.Cfg](outputFile) - require.NoError(t, err) - pdConfig, err := products.LoadOutput[keepers.Configurator](outputFile) - require.NoError(t, err) - - var config *keepers.Keepers - for _, candidate := range pdConfig.Config { - if candidate.MustGetRegistryVersion() == testcase.RegistryVersion { - config = candidate - } - } - require.NotNil(t, config, "failed to find matching config with registry version %v", testcase.RegistryVersion.String()) - - pks := []string{products.NetworkPrivateKey()} - - require.Equal(t, "1337", in.Blockchains[0].ChainID, "automation smoke tests can only be run on simulated network. If do want to run on a live network, please read the code, understand the implications (e.g. potential fund loss) and adjust the test accordingly") - - // on simulated network create new ephemeral addresses if insufficient private keys were provided - // we ignore key at index 0, because it is the root key, which is not used during the test - // for contract deployment and interaction - // we create new addresses only on the simulated network to protect against fund loss - if in.Blockchains[0].ChainID == "1337" && len(pks)-1 != testcase.UpkeepCount { - bcNode := in.Blockchains[0].Out.Nodes[0] - c, _, _, err := products.ETHClient( - t.Context(), - bcNode.ExternalWSUrl, - config.GasSettings.FeeCapMultiplier, - config.GasSettings.TipCapMultiplier, - ) - require.NoError(t, err, "Failed to create ETH client") - - newPks, err := products.FundNewAddresses(t.Context(), testcase.UpkeepCount, c, testcase.TestKeyFundingEth) - require.NoError(t, err, "Failed to fund new addresses") - pks = append(pks, newPks...) - } - require.GreaterOrEqual(t, len(pks), testcase.UpkeepCount+1, "you must provide at least %d private keys", testcase.UpkeepCount+1) - chainID, err := strconv.ParseUint(in.Blockchains[0].ChainID, 10, 64) - require.NoError(t, err, "Failed to parse chain ID") - - chainClient, err := products.InitSeth(in.Blockchains[0].Out.Nodes[0].ExternalWSUrl, pks, &chainID) - require.NoError(t, err, "Failed to create chain client") - - test, err := NewTest(l, chainClient, config) - require.NoError(t, err, "Failed to create test") - - // Fund the registry with 1 LINK * amount of KeeperConsumerPerformance contracts - err = test.LinkToken.Transfer(test.Registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(testcase.UpkeepCount)))) - require.NoError(t, err, "Funding keeper registry contract shouldn't fail") - - sb, err := chainClient.Client.BlockNumber(t.Context()) - require.NoError(t, err, "Failed to get start block") - - consumers, upkeepIDs := automation.DeployLegacyConsumers(t, chainClient, test.Registry, test.Registrar, test.LinkToken, testcase.UpkeepCount, big.NewInt(0).Mul(big.NewInt(testcase.UpkeepFundingLink), big.NewInt(1e18)), defaultUpkeepGasLimit, false, false, false, nil) - - t.Cleanup(func() { - automation_tests.GetStalenessReportCleanupFn(t, l, chainClient, sb, test.Registry, testcase.RegistryVersion)() - }) - - gom := gomega.NewGomegaWithT(t) - gom.Eventually(func(g gomega.Gomega) error { - // Check if the upkeeps are performing multiple times by analyzing their counters and checking they are greater than 10 - for i := range upkeepIDs { - counter, err := consumers[i].Counter(t.Context()) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i) - g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(testcase.ExpectedUpkeepExecutions)), - "Expected consumer counter to be greater than %d, but got %d", testcase.ExpectedUpkeepExecutions, counter.Int64()) - l.Info().Int64("Upkeep counter", counter.Int64()).Msg("Number of upkeeps performed") - } - return nil - }, testcase.UpkeepExecutionTimeout, "1s").Should(gomega.Succeed()) - - chainlinkNodes, err := clclient.New(in.NodeSets[0].Out.CLNodes) - require.NoError(t, err, "Failed to create chainlink client") - - for i, node := range chainlinkNodes { - jobs, _, err := node.ReadJobs() - require.NoError(t, err, "Failed to read jobs") - var jobID string - for _, job := range jobs.Data { - require.IsType(t, map[string]interface{}{}, job, "job data should be a map[string]interface{}") - if attr, ok := job["attributes"].(map[string]interface{}); ok { - if name, ok := attr["name"].(string); ok && name == "keeper-test-"+test.Registry.Address() { - jobID = job["id"].(string) - break - } - } - } - require.NotEmpty(t, jobID, "Failed to find keeper job") - err = node.MustDeleteJob(jobID) - require.NoError(t, err, "Error deleting job from node %d", i) - } - - // create jobs for the second registry - for _, chainlinkNode := range chainlinkNodes { - chainlinkNodeAddress, err := chainlinkNode.PrimaryEthAddress() - require.NoError(t, err, "Failed to retrieve chainlink node address") - _, err = chainlinkNode.MustCreateJob(&keepers.KeeperJobSpec{ - Name: "keeper-test-" + test.Registry.Address(), - ContractAddress: test.Registry.Address(), - FromAddress: chainlinkNodeAddress, - EVMChainID: strconv.FormatInt(chainClient.ChainID, 10), - MinIncomingConfirmations: 1, - }) - require.NoError(t, err, "Failed to create keeper job") - } - - gom.Eventually(func(g gomega.Gomega) error { - // Check if the upkeeps are performing multiple times by analyzing their counters and checking they are greater than 10 - for i := range upkeepIDs { - counter, err := consumers[i].Counter(t.Context()) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i) - g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(testcase.ExpectedUpkeepExecutions)), - "Expected consumer counter to be greater than %d, but got %d", testcase.ExpectedUpkeepExecutions, counter.Int64()) - l.Info().Int64("Upkeep counter", counter.Int64()).Msg("Number of upkeeps performed") - } - return nil - }, testcase.UpkeepExecutionTimeout, "1s").Should(gomega.Succeed()) - }) - } -} - -func TestKeeperNodeDown(t *testing.T) { - testcases := []testcase{ - { - Name: "registry_1_1", - RegistryVersion: contracts.RegistryVersion_1_1, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - UpkeepExecutionTimeout: "3m", - }, - { - Name: "registry_1_2", - RegistryVersion: contracts.RegistryVersion_1_2, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - UpkeepExecutionTimeout: "3m", - }, - { - Name: "registry_1_3", - RegistryVersion: contracts.RegistryVersion_1_3, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - UpkeepExecutionTimeout: "3m", - }, - } - - for _, testcase := range testcases { - t.Run(testcase.Name, func(t *testing.T) { - l := framework.L - t.Cleanup(func() { - cleanupErr := products.CleanupContainerLogs(products.DefaultSettings()) - require.NoError(t, cleanupErr, "failed to process cleanup container logs") - }) - - outputFile := "../../env-out.toml" - in, err := de.LoadOutput[de.Cfg](outputFile) - require.NoError(t, err) - pdConfig, err := products.LoadOutput[keepers.Configurator](outputFile) - require.NoError(t, err) - - var config *keepers.Keepers - for _, candidate := range pdConfig.Config { - if candidate.MustGetRegistryVersion() == testcase.RegistryVersion { - config = candidate - } - } - require.NotNil(t, config, "failed to find matching config with registry version %v", testcase.RegistryVersion.String()) - - pks := []string{products.NetworkPrivateKey()} - - require.Equal(t, "1337", in.Blockchains[0].ChainID, "automation smoke tests can only be run on simulated network. If do want to run on a live network, please read the code, understand the implications (e.g. potential fund loss) and adjust the test accordingly") - - // on simulated network create new ephemeral addresses if insufficient private keys were provided - // we ignore key at index 0, because it is the root key, which is not used during the test - // for contract deployment and interaction - // we create new addresses only on the simulated network to protect against fund loss - if in.Blockchains[0].ChainID == "1337" && len(pks)-1 != testcase.UpkeepCount { - bcNode := in.Blockchains[0].Out.Nodes[0] - c, _, _, err := products.ETHClient( - t.Context(), - bcNode.ExternalWSUrl, - config.GasSettings.FeeCapMultiplier, - config.GasSettings.TipCapMultiplier, - ) - require.NoError(t, err, "Failed to create ETH client") - - newPks, err := products.FundNewAddresses(t.Context(), testcase.UpkeepCount, c, testcase.TestKeyFundingEth) - require.NoError(t, err, "Failed to fund new addresses") - pks = append(pks, newPks...) - } - require.GreaterOrEqual(t, len(pks), testcase.UpkeepCount+1, "you must provide at least %d private keys", testcase.UpkeepCount+1) - chainID, err := strconv.ParseUint(in.Blockchains[0].ChainID, 10, 64) - require.NoError(t, err, "Failed to parse chain ID") - - chainClient, err := products.InitSeth(in.Blockchains[0].Out.Nodes[0].ExternalWSUrl, pks, &chainID) - require.NoError(t, err, "Failed to create chain client") - - test, err := NewTest(l, chainClient, config) - require.NoError(t, err, "Failed to create test") - - // Fund the registry with 1 LINK * amount of KeeperConsumerPerformance contracts - err = test.LinkToken.Transfer(test.Registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(testcase.UpkeepCount)))) - require.NoError(t, err, "Funding keeper registry contract shouldn't fail") - - sb, err := chainClient.Client.BlockNumber(t.Context()) - require.NoError(t, err, "Failed to get start block") - - consumers, upkeepIDs := automation.DeployLegacyConsumers(t, chainClient, test.Registry, test.Registrar, test.LinkToken, testcase.UpkeepCount, big.NewInt(0).Mul(big.NewInt(testcase.UpkeepFundingLink), big.NewInt(1e18)), defaultUpkeepGasLimit, false, false, false, nil) - - t.Cleanup(func() { - automation_tests.GetStalenessReportCleanupFn(t, l, chainClient, sb, test.Registry, testcase.RegistryVersion)() - }) - - var initialCounters = make([]*big.Int, len(upkeepIDs)) - - gom := gomega.NewGomegaWithT(t) - // Watch upkeeps being performed and store their counters in order to compare them later in the test - gom.Eventually(func(g gomega.Gomega) error { - for i := range upkeepIDs { - counter, err := consumers[i].Counter(t.Context()) - initialCounters[i] = counter - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i) - g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(0)), - "Expected consumer counter to be greater than 0, but got %d", counter.Int64()) - } - return nil - }, testcase.UpkeepExecutionTimeout, "1s").Should(gomega.Succeed()) - - chainlinkNodes, err := clclient.New(in.NodeSets[0].Out.CLNodes) - require.NoError(t, err, "Failed to create chainlink client") - - // Take down half of the Keeper nodes by deleting the Keeper job registered above (after registry deployment) - cutIndex := len(chainlinkNodes)/2 + 1 - firstHalfToTakeDown := chainlinkNodes[:cutIndex] - for i, nodeToTakeDown := range firstHalfToTakeDown { - jobs, _, err := nodeToTakeDown.ReadJobs() - require.NoError(t, err, "Failed to read jobs") - var jobID string - for _, job := range jobs.Data { - require.IsType(t, map[string]interface{}{}, job, "job data should be a map[string]interface{}") - if attr, ok := job["attributes"].(map[string]interface{}); ok { - if name, ok := attr["name"].(string); ok && name == "keeper-test-"+test.Registry.Address() { - jobID = job["id"].(string) - break - } - } - } - require.NotEmpty(t, jobID, "Failed to find keeper job") - err = nodeToTakeDown.MustDeleteJob(jobID) - require.NoError(t, err, "Error deleting job from node %d", i) - } - l.Info().Msg("Successfully managed to take down the first half of the nodes") - - // Assert that upkeeps are still performed and their counters have increased - gom.Eventually(func(g gomega.Gomega) error { - for i := range upkeepIDs { - currentCounter, err := consumers[i].Counter(t.Context()) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i) - g.Expect(currentCounter.Int64()).Should(gomega.BeNumerically(">", initialCounters[i].Int64()), - "Expected counter to have increased from initial value of %s, but got %s", - initialCounters[i], currentCounter) - } - return nil - }, testcase.UpkeepExecutionTimeout, "1s").Should(gomega.Succeed()) - - // Take down the other half of the Keeper nodes - secondHalfToTakeDown := chainlinkNodes[cutIndex:] - for i, nodeToTakeDown := range secondHalfToTakeDown { - jobs, _, err := nodeToTakeDown.ReadJobs() - require.NoError(t, err, "Failed to read jobs") - var jobID string - for _, job := range jobs.Data { - require.IsType(t, map[string]interface{}{}, job, "job data should be a map[string]interface{}") - if attr, ok := job["attributes"].(map[string]interface{}); ok { - if name, ok := attr["name"].(string); ok && name == "keeper-test-"+test.Registry.Address() { - jobID = job["id"].(string) - break - } - } - } - require.NotEmpty(t, jobID, "Failed to find keeper job") - err = nodeToTakeDown.MustDeleteJob(jobID) - require.NoError(t, err, "Error deleting job from node %d", i) - } - l.Info().Msg("Successfully managed to take down the second half of the nodes") - - // See how many times each upkeep was executed - var countersAfterNoMoreNodes = make([]*big.Int, len(upkeepIDs)) - for i := range upkeepIDs { - countersAfterNoMoreNodes[i], err = consumers[i].Counter(t.Context()) - require.NoError(t, err, "Error retrieving consumer counter %d", i) - l.Info(). - Int("Index", i). - Int64("Upkeeps", countersAfterNoMoreNodes[i].Int64()). - Msg("Upkeeps Performed") - } - - // Once all the nodes are taken down, there might be some straggling transactions which went through before - // all the nodes were taken down. Every keeper node can have at most 1 straggling transaction per upkeep, - // so a +6 on the upper limit side should be sufficient. - gom.Consistently(func(g gomega.Gomega) { - for i := range upkeepIDs { - latestCounter, err := consumers[i].Counter(t.Context()) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i) - g.Expect(latestCounter.Int64()).Should(gomega.BeNumerically("<=", - countersAfterNoMoreNodes[i].Int64()+numUpkeepsAllowedForStragglingTxs, - ), - "Expected consumer counter to not have increased more than %d, but got %d", - countersAfterNoMoreNodes[i].Int64()+numUpkeepsAllowedForStragglingTxs, latestCounter.Int64()) - } - }, testcase.UpkeepExecutionTimeout, "1s").Should(gomega.Succeed()) - }) - } -} - -func TestKeeperPauseUnPauseUpkeep(t *testing.T) { - testcases := []testcase{ - { - Name: "registry_1_3", - RegistryVersion: contracts.RegistryVersion_1_3, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - ExpectedUpkeepExecutions: 5, - UpkeepExecutionTimeout: "3m", - }, - } - - for _, testcase := range testcases { - t.Run(testcase.Name, func(t *testing.T) { - l := framework.L - t.Cleanup(func() { - cleanupErr := products.CleanupContainerLogs(products.DefaultSettings()) - require.NoError(t, cleanupErr, "failed to process cleanup container logs") - }) - - outputFile := "../../env-out.toml" - in, err := de.LoadOutput[de.Cfg](outputFile) - require.NoError(t, err) - pdConfig, err := products.LoadOutput[keepers.Configurator](outputFile) - require.NoError(t, err) - - var config *keepers.Keepers - for _, candidate := range pdConfig.Config { - if candidate.MustGetRegistryVersion() == testcase.RegistryVersion { - config = candidate - } - } - require.NotNil(t, config, "failed to find matching config with registry version %v", testcase.RegistryVersion.String()) - - pks := []string{products.NetworkPrivateKey()} - - require.Equal(t, "1337", in.Blockchains[0].ChainID, "automation smoke tests can only be run on simulated network. If do want to run on a live network, please read the code, understand the implications (e.g. potential fund loss) and adjust the test accordingly") - - // on simulated network create new ephemeral addresses if insufficient private keys were provided - // we ignore key at index 0, because it is the root key, which is not used during the test - // for contract deployment and interaction - // we create new addresses only on the simulated network to protect against fund loss - if in.Blockchains[0].ChainID == "1337" && len(pks)-1 != testcase.UpkeepCount { - bcNode := in.Blockchains[0].Out.Nodes[0] - c, _, _, err := products.ETHClient( - t.Context(), - bcNode.ExternalWSUrl, - config.GasSettings.FeeCapMultiplier, - config.GasSettings.TipCapMultiplier, - ) - require.NoError(t, err, "Failed to create ETH client") - - newPks, err := products.FundNewAddresses(t.Context(), testcase.UpkeepCount, c, testcase.TestKeyFundingEth) - require.NoError(t, err, "Failed to fund new addresses") - pks = append(pks, newPks...) - } - require.GreaterOrEqual(t, len(pks), testcase.UpkeepCount+1, "you must provide at least %d private keys", testcase.UpkeepCount+1) - chainID, err := strconv.ParseUint(in.Blockchains[0].ChainID, 10, 64) - require.NoError(t, err, "Failed to parse chain ID") - - chainClient, err := products.InitSeth(in.Blockchains[0].Out.Nodes[0].ExternalWSUrl, pks, &chainID) - require.NoError(t, err, "Failed to create chain client") - - test, err := NewTest(l, chainClient, config) - require.NoError(t, err, "Failed to create test") - - // Fund the registry with 1 LINK * amount of KeeperConsumerPerformance contracts - err = test.LinkToken.Transfer(test.Registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(testcase.UpkeepCount)))) - require.NoError(t, err, "Funding keeper registry contract shouldn't fail") - - sb, err := chainClient.Client.BlockNumber(t.Context()) - require.NoError(t, err, "Failed to get start block") - - consumers, upkeepIDs := automation.DeployLegacyConsumers(t, chainClient, test.Registry, test.Registrar, test.LinkToken, testcase.UpkeepCount, big.NewInt(0).Mul(big.NewInt(testcase.UpkeepFundingLink), big.NewInt(1e18)), defaultUpkeepGasLimit, false, false, false, nil) - - t.Cleanup(func() { - automation_tests.GetStalenessReportCleanupFn(t, l, chainClient, sb, test.Registry, testcase.RegistryVersion)() - }) - - gom := gomega.NewGomegaWithT(t) - 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 5 - for i := range upkeepIDs { - counter, err := consumers[i].Counter(t.Context()) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter for upkeep at index %d", i) - g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(testcase.ExpectedUpkeepExecutions)), - "Expected consumer counter to be greater than %d, but got %d", testcase.ExpectedUpkeepExecutions, counter.Int64()) - l.Info().Int64("Upkeep counter", counter.Int64()).Msg("Number of upkeeps performed") - } - return nil - }, testcase.UpkeepExecutionTimeout, "1s").Should(gomega.Succeed()) - - // pause all the registered upkeeps via the registry - for i := range upkeepIDs { - err := test.Registry.PauseUpkeep(upkeepIDs[i]) - require.NoError(t, err, "Error pausing upkeep at index %d", i) - } - - var countersAfterPause = make([]*big.Int, len(upkeepIDs)) - for i := range upkeepIDs { - // Obtain the amount of times the upkeep has been executed so far - countersAfterPause[i], err = consumers[i].Counter(t.Context()) - require.NoError(t, err, "Error retrieving upkeep count at index %d", i) - l.Info(). - Int("Index", i). - Int64("Upkeeps", countersAfterPause[i].Int64()). - Msg("Paused Upkeep") - } - - gom.Consistently(func(g gomega.Gomega) { - for i := range upkeepIDs { - // In most cases counters should remain constant, but there might be a straggling perform tx which - // gets committed later. Since every keeper node cannot have more than 1 straggling tx, it - // is sufficient to check that the upkeep count does not increase by more than 6. - latestCounter, err := consumers[i].Counter(t.Context()) - require.NoError(t, err, "Error retrieving counter at index %d", i) - g.Expect(latestCounter.Int64()).Should(gomega.BeNumerically("<=", countersAfterPause[i].Int64()+numUpkeepsAllowedForStragglingTxs), - "Expected consumer counter not have increased more than %d, but got %d", - countersAfterPause[i].Int64()+numUpkeepsAllowedForStragglingTxs, latestCounter.Int64()) - } - }, "1m", "1s").Should(gomega.Succeed()) - - // unpause all the registered upkeeps via the registry - for i := range upkeepIDs { - err := test.Registry.UnpauseUpkeep(upkeepIDs[i]) - require.NoError(t, err, "Error un-pausing upkeep at index %d", i) - } - - 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 5 + numbers of performing before pause - for i := range upkeepIDs { - counter, err := consumers[i].Counter(t.Context()) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve consumer counter"+ - " for upkeep at index %d", i) - g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(testcase.ExpectedUpkeepExecutions)+countersAfterPause[i].Int64()), - "Expected consumer counter to be greater than %d, but got %d", int64(testcase.ExpectedUpkeepExecutions)+countersAfterPause[i].Int64(), counter.Int64()) - l.Info().Int64("Upkeeps", counter.Int64()).Msg("Upkeeps Performed") - } - return nil - }, testcase.UpkeepExecutionTimeout, "1s").Should(gomega.Succeed()) - }) - } -} - -// use env from TestKeeperPauseUnPauseUpkeep -func TestKeeperUpdateCheckData(t *testing.T) { - testcases := []testcase{ - { - Name: "registry_1_3", - RegistryVersion: contracts.RegistryVersion_1_3, - UpkeepCount: defaultAmountOfUpkeeps, - UpkeepFundingLink: defaultLinkFunds, - TestKeyFundingEth: defaultEthFunds, - ExpectedUpkeepExecutions: 5, - UpkeepExecutionTimeout: "3m", - }, - } - - for _, testcase := range testcases { - t.Run(testcase.Name, func(t *testing.T) { - l := framework.L - t.Cleanup(func() { - cleanupErr := products.CleanupContainerLogs(products.DefaultSettings()) - require.NoError(t, cleanupErr, "failed to process cleanup container logs") - }) - - outputFile := "../../env-out.toml" - in, err := de.LoadOutput[de.Cfg](outputFile) - require.NoError(t, err) - pdConfig, err := products.LoadOutput[keepers.Configurator](outputFile) - require.NoError(t, err) - - var config *keepers.Keepers - for _, candidate := range pdConfig.Config { - if candidate.MustGetRegistryVersion() == testcase.RegistryVersion { - config = candidate - } - } - require.NotNil(t, config, "failed to find matching config with registry version %v", testcase.RegistryVersion.String()) - - pks := []string{products.NetworkPrivateKey()} - - require.Equal(t, "1337", in.Blockchains[0].ChainID, "automation smoke tests can only be run on simulated network. If do want to run on a live network, please read the code, understand the implications (e.g. potential fund loss) and adjust the test accordingly") - - // on simulated network create new ephemeral addresses if insufficient private keys were provided - // we ignore key at index 0, because it is the root key, which is not used during the test - // for contract deployment and interaction - // we create new addresses only on the simulated network to protect against fund loss - if in.Blockchains[0].ChainID == "1337" && len(pks)-1 != testcase.UpkeepCount { - bcNode := in.Blockchains[0].Out.Nodes[0] - c, _, _, err := products.ETHClient( - t.Context(), - bcNode.ExternalWSUrl, - config.GasSettings.FeeCapMultiplier, - config.GasSettings.TipCapMultiplier, - ) - require.NoError(t, err, "Failed to create ETH client") - - newPks, err := products.FundNewAddresses(t.Context(), testcase.UpkeepCount, c, testcase.TestKeyFundingEth) - require.NoError(t, err, "Failed to fund new addresses") - pks = append(pks, newPks...) - } - require.GreaterOrEqual(t, len(pks), testcase.UpkeepCount+1, "you must provide at least %d private keys", testcase.UpkeepCount+1) - chainID, err := strconv.ParseUint(in.Blockchains[0].ChainID, 10, 64) - require.NoError(t, err, "Failed to parse chain ID") - - chainClient, err := products.InitSeth(in.Blockchains[0].Out.Nodes[0].ExternalWSUrl, pks, &chainID) - require.NoError(t, err, "Failed to create chain client") - - test, err := NewTest(l, chainClient, config) - require.NoError(t, err, "Failed to create test") - - // Fund the registry with 1 LINK * amount of KeeperConsumerPerformance contracts - err = test.LinkToken.Transfer(test.Registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(testcase.UpkeepCount)))) - require.NoError(t, err, "Funding keeper registry contract shouldn't fail") - - sb, err := chainClient.Client.BlockNumber(t.Context()) - require.NoError(t, err, "Failed to get start block") - - performDataChecker := keepers.DeployPerformDataChecker(t, chainClient, testcase.UpkeepCount, []byte(expectedData)) - - err = automation.DeployMultiCallAndFundDeploymentAddresses(chainClient, test.LinkToken, testcase.UpkeepCount, big.NewInt(0).Mul(big.NewInt(testcase.UpkeepFundingLink), big.NewInt(1e18))) - require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") - - var upkeepsAddresses []string - for _, upkeep := range performDataChecker { - upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) - } - - upkeepIDs := automation.RegisterUpkeepContracts(t, chainClient, test.LinkToken, big.NewInt(0).Mul(big.NewInt(testcase.UpkeepFundingLink), big.NewInt(1e18)), defaultUpkeepGasLimit, test.Registry, test.Registrar, testcase.UpkeepCount, upkeepsAddresses, false, false, false, nil) - - t.Cleanup(func() { - automation_tests.GetStalenessReportCleanupFn(t, l, chainClient, sb, test.Registry, testcase.RegistryVersion)() - }) - - gom := gomega.NewGomegaWithT(t) - gom.Consistently(func(g gomega.Gomega) { - // expect the counter to remain 0 because perform data does not match - for i := range upkeepIDs { - counter, err := performDataChecker[i].Counter(t.Context()) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve perform data checker for upkeep at index %d", i) - g.Expect(counter.Int64()).Should(gomega.Equal(int64(0)), - "Expected perform data checker counter to be 0, but got %d", counter.Int64()) - l.Info().Int64("Upkeep perform data checker", counter.Int64()).Msg("Number of upkeeps performed") - } - }, "2m", "1s").Should(gomega.Succeed()) - - for i := range upkeepIDs { - err = test.Registry.UpdateCheckData(upkeepIDs[i], []byte(expectedData)) - require.NoError(t, err, "Error updating check data at index %d", i) - } - - // retrieve new check data for all upkeeps - for i := range upkeepIDs { - upkeep, err := test.Registry.GetUpkeepInfo(t.Context(), upkeepIDs[i]) - require.NoError(t, err, "Error getting upkeep info from index %d", i) - require.Equal(t, []byte(expectedData), upkeep.CheckData, "Check data not as expected") - } - - 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 testcase.ExpectedUpkeepExecutions - for i := range upkeepIDs { - counter, err := performDataChecker[i].Counter(t.Context()) - g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Failed to retrieve perform data checker counter for upkeep at index %d", i) - g.Expect(counter.Int64()).Should(gomega.BeNumerically(">", int64(testcase.ExpectedUpkeepExecutions)), - "Expected perform data checker counter to be greater than %d, but got %d", testcase.ExpectedUpkeepExecutions, counter.Int64()) - l.Info().Int64("Upkeep perform data checker", counter.Int64()).Msg("Number of upkeeps performed") - } - return nil - }, testcase.UpkeepExecutionTimeout, "1s").Should(gomega.Succeed()) - }) - } -} diff --git a/devenv/tests/keepers/smoke_test_helpers.go b/devenv/tests/keepers/smoke_test_helpers.go deleted file mode 100644 index 1bbdb7ecba4..00000000000 --- a/devenv/tests/keepers/smoke_test_helpers.go +++ /dev/null @@ -1,178 +0,0 @@ -package keepers - -import ( - "errors" - "fmt" - - "github.com/ethereum/go-ethereum/common" - "github.com/rs/zerolog" - - "github.com/smartcontractkit/chainlink-testing-framework/seth" - - "github.com/smartcontractkit/chainlink/devenv/contracts" - "github.com/smartcontractkit/chainlink/devenv/products/keepers" -) - -type Test struct { - ChainClient *seth.Client - - Config *keepers.Keepers - - LinkToken contracts.LinkToken - Transcoder contracts.UpkeepTranscoder - LINKETHFeed contracts.MockLINKETHFeed - ETHUSDFeed contracts.MockETHUSDFeed - LINKUSDFeed contracts.MockETHUSDFeed - WETHToken contracts.WETHToken - GasFeed contracts.MockGasFeed - Registry contracts.KeeperRegistry - Registrar contracts.KeeperRegistrar - - RegistrySettings contracts.KeeperRegistrySettings - - Logger zerolog.Logger -} - -func NewTest( - l zerolog.Logger, - chainClient *seth.Client, - config *keepers.Keepers, -) (*Test, error) { - t := &Test{ - ChainClient: chainClient, - Config: config, - RegistrySettings: config.GetRegistryConfig(), - Logger: l, - } - - if err := t.LoadContracts(); err != nil { - return nil, err - } - - return t, nil -} - -func (a *Test) LoadContracts() error { - if err := a.LoadLINK(a.Config.DeployedContracts.LinkToken); err != nil { - return fmt.Errorf("error loading link token contract: %w", err) - } - - if err := a.LoadLinkEthFeed(a.Config.DeployedContracts.LinkEthFeed); err != nil { - return fmt.Errorf("error loading link eth feed contract: %w", err) - } - - if err := a.LoadEthGasFeed(a.Config.DeployedContracts.EthGasFeed); err != nil { - return fmt.Errorf("error loading gas feed contract: %w", err) - } - - if err := a.LoadTranscoder(a.Config.DeployedContracts.Transcoder); err != nil { - return fmt.Errorf("error loading transcoder contract: %w", err) - } - - if err := a.LoadRegistry(a.Config.DeployedContracts.Registry); err != nil { - return fmt.Errorf("error loading registry contract: %w", err) - } - - if a.Registry.RegistryOwnerAddress().String() != a.ChainClient.MustGetRootKeyAddress().String() { - return errors.New("registry owner address is not the root key address") - } - - if err := a.LoadRegistrar(a.Config.DeployedContracts.Registrar); err != nil { - return fmt.Errorf("error loading registrar contract: %w", err) - } - - return nil -} - -func (a *Test) LoadLINK(address string) error { - linkToken, err := contracts.LoadLinkTokenContract(a.Logger, a.ChainClient, common.HexToAddress(address)) - if err != nil { - return err - } - a.LinkToken = linkToken - a.Logger.Info().Str("LINK Token Address", a.LinkToken.Address()).Msg("Successfully loaded LINK Token") - return nil -} - -func (a *Test) LoadTranscoder(address string) error { - transcoder, err := contracts.LoadUpkeepTranscoder(a.ChainClient, common.HexToAddress(address)) - if err != nil { - return err - } - a.Transcoder = transcoder - a.Logger.Info().Str("Transcoder Address", a.Transcoder.Address()).Msg("Successfully loaded Transcoder") - return nil -} - -func (a *Test) LoadLinkEthFeed(address string) error { - ethLinkFeed, err := contracts.LoadMockLINKETHFeed(a.ChainClient, common.HexToAddress(address)) - if err != nil { - return err - } - a.LINKETHFeed = ethLinkFeed - a.Logger.Info().Str("LINK/ETH Feed Address", a.LINKETHFeed.Address()).Msg("Successfully loaded LINK/ETH Feed") - return nil -} - -func (a *Test) LoadEthUSDFeed(address string) error { - ethUSDFeed, err := contracts.LoadMockETHUSDFeed(a.ChainClient, common.HexToAddress(address)) - if err != nil { - return err - } - a.ETHUSDFeed = ethUSDFeed - a.Logger.Info().Str("ETH/USD Feed Address", a.ETHUSDFeed.Address()).Msg("Successfully loaded ETH/USD Feed") - return nil -} - -func (a *Test) LoadLinkUSDFeed(address string) error { - linkUSDFeed, err := contracts.LoadMockETHUSDFeed(a.ChainClient, common.HexToAddress(address)) - if err != nil { - return err - } - a.LINKUSDFeed = linkUSDFeed - a.Logger.Info().Str("LINK/USD Feed Address", a.LINKUSDFeed.Address()).Msg("Successfully loaded LINK/USD Feed") - return nil -} - -func (a *Test) LoadWETH(address string) error { - wethToken, err := contracts.LoadWETHTokenContract(a.Logger, a.ChainClient, common.HexToAddress(address)) - if err != nil { - return err - } - a.WETHToken = wethToken - a.Logger.Info().Str("WETH Token Address", a.WETHToken.Address()).Msg("Successfully loaded WETH Token") - return nil -} - -func (a *Test) LoadEthGasFeed(address string) error { - gasFeed, err := contracts.LoadMockGASFeed(a.ChainClient, common.HexToAddress(address)) - if err != nil { - return err - } - a.GasFeed = gasFeed - a.Logger.Info().Str("Gas Feed Address", a.GasFeed.Address()).Msg("Successfully loaded Gas Feed") - return nil -} - -func (a *Test) LoadRegistry(registryAddress string) error { - registry, err := contracts.LoadKeeperRegistry(a.Logger, a.ChainClient, common.HexToAddress(registryAddress), a.RegistrySettings.RegistryVersion, common.Address{}) - if err != nil { - return err - } - a.Registry = registry - a.Logger.Info().Str("Registry Address", a.Registry.Address()).Msg("Successfully loaded Registry") - return nil -} - -func (a *Test) LoadRegistrar(address string) error { - if a.Registry == nil { - return errors.New("registry must be deployed or loaded before registrar") - } - registrar, err := contracts.LoadKeeperRegistrar(a.ChainClient, common.HexToAddress(address), a.RegistrySettings.RegistryVersion) - if err != nil { - return err - } - a.Logger.Info().Str("Registrar Address", registrar.Address()).Msg("Successfully loaded Registrar") - a.Registrar = registrar - return nil -} diff --git a/docs/CONFIG.md b/docs/CONFIG.md index 16170aa2a71..d478556a668 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -1924,105 +1924,6 @@ Capability-specific configuration as key-value pairs. proxyMode = 'gateway' # Example allowedPorts = '443,8443' # Example -## Keeper -```toml -[Keeper] -DefaultTransactionQueueDepth = 1 # Default -GasPriceBufferPercent = 20 # Default -GasTipCapBufferPercent = 20 # Default -BaseFeeBufferPercent = 20 # Default -MaxGracePeriod = 100 # Default -TurnLookBack = 1_000 # Default -``` - - -### DefaultTransactionQueueDepth -:warning: **_ADVANCED_**: _Do not change this setting unless you know what you are doing._ -```toml -DefaultTransactionQueueDepth = 1 # Default -``` -DefaultTransactionQueueDepth controls the queue size for `DropOldestStrategy` in Keeper. Set to 0 to use `SendEvery` strategy instead. - -### GasPriceBufferPercent -:warning: **_ADVANCED_**: _Do not change this setting unless you know what you are doing._ -```toml -GasPriceBufferPercent = 20 # Default -``` -GasPriceBufferPercent specifies the percentage to add to the gas price used for checking whether to perform an upkeep. Only applies in legacy mode (EIP-1559 off). - -### GasTipCapBufferPercent -:warning: **_ADVANCED_**: _Do not change this setting unless you know what you are doing._ -```toml -GasTipCapBufferPercent = 20 # Default -``` -GasTipCapBufferPercent specifies the percentage to add to the gas price used for checking whether to perform an upkeep. Only applies in EIP-1559 mode. - -### BaseFeeBufferPercent -:warning: **_ADVANCED_**: _Do not change this setting unless you know what you are doing._ -```toml -BaseFeeBufferPercent = 20 # Default -``` -BaseFeeBufferPercent specifies the percentage to add to the base fee used for checking whether to perform an upkeep. Applies only in EIP-1559 mode. - -### MaxGracePeriod -:warning: **_ADVANCED_**: _Do not change this setting unless you know what you are doing._ -```toml -MaxGracePeriod = 100 # Default -``` -MaxGracePeriod is the maximum number of blocks that a keeper will wait after performing an upkeep before it resumes checking that upkeep - -### TurnLookBack -```toml -TurnLookBack = 1_000 # Default -``` -TurnLookBack is the number of blocks in the past to look back when getting a block for a turn. - -## Keeper.Registry -```toml -[Keeper.Registry] -CheckGasOverhead = 200_000 # Default -PerformGasOverhead = 300_000 # Default -SyncInterval = '30m' # Default -MaxPerformDataSize = 5_000 # Default -SyncUpkeepQueueSize = 10 # Default -``` - - -### CheckGasOverhead -:warning: **_ADVANCED_**: _Do not change this setting unless you know what you are doing._ -```toml -CheckGasOverhead = 200_000 # Default -``` -CheckGasOverhead is the amount of extra gas to provide checkUpkeep() calls to account for the gas consumed by the keeper registry. - -### PerformGasOverhead -:warning: **_ADVANCED_**: _Do not change this setting unless you know what you are doing._ -```toml -PerformGasOverhead = 300_000 # Default -``` -PerformGasOverhead is the amount of extra gas to provide performUpkeep() calls to account for the gas consumed by the keeper registry - -### SyncInterval -:warning: **_ADVANCED_**: _Do not change this setting unless you know what you are doing._ -```toml -SyncInterval = '30m' # Default -``` -SyncInterval is the interval in which the RegistrySynchronizer performs a full sync of the keeper registry contract it is tracking. - -### MaxPerformDataSize -:warning: **_ADVANCED_**: _Do not change this setting unless you know what you are doing._ -```toml -MaxPerformDataSize = 5_000 # Default -``` -MaxPerformDataSize is the max size of perform data. - -### SyncUpkeepQueueSize -:warning: **_ADVANCED_**: _Do not change this setting unless you know what you are doing._ -```toml -SyncUpkeepQueueSize = 10 # Default -``` -SyncUpkeepQueueSize represents the maximum number of upkeeps that can be synced in parallel. - ## AutoPprof ```toml [AutoPprof] @@ -8465,6 +8366,7 @@ AcceptanceTimeout = '30s' AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false +ChainType = 'pharos' FinalityDepth = 50 SafeDepth = 0 FinalityTagEnabled = false diff --git a/go.md b/go.md index 3dcf2dc1606..f84ee6c0005 100644 --- a/go.md +++ b/go.md @@ -319,6 +319,7 @@ flowchart LR click chainlink-ccip/ccv/chains/evm href "https://github.com/smartcontractkit/chainlink-ccip" chainlink-ccip/chains/evm --> ccip-contract-examples/chains/evm chainlink-ccip/chains/evm --> chainlink-ccip/deployment + chainlink-ccip/chains/evm --> chainlink-evm click chainlink-ccip/chains/evm href "https://github.com/smartcontractkit/chainlink-ccip" chainlink-ccip/chains/solana --> chainlink-ccip/chains/solana/gobindings chainlink-ccip/chains/solana --> chainlink-common @@ -326,7 +327,6 @@ flowchart LR chainlink-ccip/chains/solana/gobindings click chainlink-ccip/chains/solana/gobindings href "https://github.com/smartcontractkit/chainlink-ccip" chainlink-ccip/deployment --> chainlink-deployments-framework - chainlink-ccip/deployment --> chainlink-evm click chainlink-ccip/deployment href "https://github.com/smartcontractkit/chainlink-ccip" chainlink-ccv --> chainlink-ccip/ccv/chains/evm chainlink-ccv --> chainlink-evm diff --git a/go.mod b/go.mod index 3a36d990f37..c00c248812c 100644 --- a/go.mod +++ b/go.mod @@ -79,8 +79,8 @@ require ( github.com/smartcontractkit/chain-selectors v1.0.98 github.com/smartcontractkit/chainlink-aptos v0.0.0-20260424112027-f932111b88ac github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260423164805-f44aeafa2aaa - github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260415165642-49f23e4d76cc + github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260428205619-2db1389501a1 + github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260428205619-2db1389501a1 github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260415165642-49f23e4d76cc github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260415165642-49f23e4d76cc github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260428133800-3b1484e8b1fd @@ -88,7 +88,7 @@ require ( github.com/smartcontractkit/chainlink-common/keystore v1.1.0 github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10 github.com/smartcontractkit/chainlink-data-streams v0.1.13 - github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260428180431-40447a80e681 + github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429123911-44d13c62c6e1 github.com/smartcontractkit/chainlink-evm/contracts/cre/gobindings v0.0.0-20260403151002-2c91155b5501 github.com/smartcontractkit/chainlink-evm/gethwrappers v0.0.0-20260119171452-39c98c3b33cd github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 @@ -103,7 +103,7 @@ require ( github.com/smartcontractkit/chainlink-protos/ring/go v0.0.0-20260331131315-f08a616d8dcd github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0 github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997 - github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428015924-9456bb6d8932 + github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428170719-7ad4e58aaacf github.com/smartcontractkit/chainlink-sui v0.0.0-20260427132612-76b9f754a556 github.com/smartcontractkit/chainlink-ton v0.0.0-20260423161209-5ce1dba9785e github.com/smartcontractkit/cre-sdk-go v1.5.0 @@ -367,7 +367,7 @@ require ( github.com/smartcontractkit/chainlink-protos/chainlink-ccv/message-discovery v0.0.0-20251211142334-5c3421fe2c8d // indirect github.com/smartcontractkit/chainlink-protos/chainlink-ccv/verifier v0.0.0-20251211142334-5c3421fe2c8d // indirect github.com/smartcontractkit/chainlink-protos/rmn/v1.6/go v0.0.0-20250131130834-15e0d4cde2a6 // indirect - github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3 // indirect + github.com/smartcontractkit/chainlink-protos/svr v1.2.0 // indirect github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20260408092456-3c6369888d4a // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect github.com/spf13/pflag v1.0.10 // indirect diff --git a/go.sum b/go.sum index c3085cd47bb..b160618b45f 100644 --- a/go.sum +++ b/go.sum @@ -1232,12 +1232,12 @@ github.com/smartcontractkit/chainlink-aptos v0.0.0-20260424112027-f932111b88ac h github.com/smartcontractkit/chainlink-aptos v0.0.0-20260424112027-f932111b88ac/go.mod h1:ZU57FhGIb+m20yysn2fw+vLh3qB5hcgd06RXEUEDBck= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260423164805-f44aeafa2aaa h1:GE4B480m+/OMgkmZ9mEI1Abh927N7oW+Ruq9uuKIFQw= -github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260423164805-f44aeafa2aaa/go.mod h1:1XxxpkgCmG/z6y30yRuVrcxre6zixIVX3xzi706Db/8= +github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260428205619-2db1389501a1 h1:p0nFrTYrOQzDhWYm6suaM5CoWiXV5NV7llHnp6/Kn/8= +github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260428205619-2db1389501a1/go.mod h1:1XxxpkgCmG/z6y30yRuVrcxre6zixIVX3xzi706Db/8= github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm v0.0.0-20260408145530-22e2d05695cd h1:Jtw6p5iisjXZyFOcBvWh6PDQKtvryrRU2JMmezdutjo= github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm v0.0.0-20260408145530-22e2d05695cd/go.mod h1:zLqdD2kBX7NsntBneclb2yrHhjFaJdoyA8dK5eimlrE= -github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260415165642-49f23e4d76cc h1:dP1ERzdTbiJbHVXfHYdBAi1+8NjgkyQuY2oFNWWWDsQ= -github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:7XR5wfgT8hjSsiV+t0EAWvna+rYQeMPaoZf/0g+dios= +github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260428205619-2db1389501a1 h1:wfiut4oWMcpJmTEl/1ShwMBxwTQEv0wV4/YTma9Otxk= +github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260428205619-2db1389501a1/go.mod h1:hrNuLHgDa2f47WVO6+KgSxM1/SI1M8npQnaiv4kw3xo= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260415165642-49f23e4d76cc h1:mvobZx5JV5PhG/9IXPReV+8mAGnupl0HIWQZ43zxzd4= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:gzCVLUlNov/zFXSC7G6zcGkZU1IfNOHaakbAPDe5Woc= github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260415165642-49f23e4d76cc h1:War93neyFmv7pzuElZeZC3qc/OfGtLvEXvqL3qeBfM0= @@ -1254,8 +1254,8 @@ github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-2025121515250 github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-20251215152504-b1e41f508340/go.mod h1:P/0OSXUlFaxxD4B/P6HWbxYtIRmmWGDJAvanq19879c= github.com/smartcontractkit/chainlink-data-streams v0.1.13 h1:YOmt545DW6U0SyaqBf+NTGDLm1yMurVI7yOvxP5hlJk= github.com/smartcontractkit/chainlink-data-streams v0.1.13/go.mod h1:00aL7OK0BJdF9gn/4t4f/pctUu2VLwwfA8G/tl9rCrM= -github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260428180431-40447a80e681 h1:ehv4ucho8t5/E/Xg3u7qomdC4gB6IkSHlZx2ZrySaH8= -github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260428180431-40447a80e681/go.mod h1:eOx+FhknhG1+K/pKN77IR/UKmU3WDVaGci64VCGlCUc= +github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429123911-44d13c62c6e1 h1:7H7hiN8Q/bHvsprmA8OqiELGkJmMHYc+MTTOCDKIzm8= +github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429123911-44d13c62c6e1/go.mod h1:lhxIJe+Qy8duvf20q4D8ewfJzwHfvxK/s4s0exG1zEQ= github.com/smartcontractkit/chainlink-evm/contracts/cre/gobindings v0.0.0-20260403151002-2c91155b5501 h1:QJiXTG9CmaQAuMRn5JGi+Jhji7fSkehVnKpjc8oNJJY= github.com/smartcontractkit/chainlink-evm/contracts/cre/gobindings v0.0.0-20260403151002-2c91155b5501/go.mod h1:4cT1BeNF8DAn6In9zr3LayVCv1KzFeuxT7zcuNkfIb0= github.com/smartcontractkit/chainlink-evm/gethwrappers v0.0.0-20260119171452-39c98c3b33cd h1:sK+pK4epQp20yQ7XztwrVgkTkRAr4FY+TvEegW8RuQk= @@ -1294,12 +1294,12 @@ github.com/smartcontractkit/chainlink-protos/rmn/v1.6/go v0.0.0-20250131130834-1 github.com/smartcontractkit/chainlink-protos/rmn/v1.6/go v0.0.0-20250131130834-15e0d4cde2a6/go.mod h1:FRwzI3hGj4CJclNS733gfcffmqQ62ONCkbGi49s658w= github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0 h1:B7itmjy+CMJ26elVw/cAJqqhBQ3Xa/mBYWK0/rQ5MuI= github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0/go.mod h1:h6kqaGajbNRrezm56zhx03p0mVmmA2xxj7E/M4ytLUA= -github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3 h1:X8Pekpv+cy0eW1laZTwATuYLTLZ6gRTxz1ZWOMtU74o= -github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= +github.com/smartcontractkit/chainlink-protos/svr v1.2.0 h1:7jjgqRgORQS/ikL3z0ZgJy95pzjhR9LuU1TVWg4BZ78= +github.com/smartcontractkit/chainlink-protos/svr v1.2.0/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997 h1:W0HKHO8eE8BckTRnhSdqjHKbJcnk068nEWYnWRu6tJY= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997/go.mod h1:GTpDgyK0OObf7jpch6p8N281KxN92wbB8serZhU9yRc= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428015924-9456bb6d8932 h1:aD5KjYqbHiL6OJl3f8tsopVkkAG68UsRJCKjDIACO6w= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428015924-9456bb6d8932/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428170719-7ad4e58aaacf h1:GyBD65Cc4HuwRKZ6k4UCtFaG7njGTnZyR+z3VPm3Vyo= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428170719-7ad4e58aaacf/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-sui v0.0.0-20260427132612-76b9f754a556 h1:Nz70a+A7aNnWRYdLpGdUf8NeauMvZFOBEPfZTm8vxwI= github.com/smartcontractkit/chainlink-sui v0.0.0-20260427132612-76b9f754a556/go.mod h1:xJ1UT4DKu1znbsm4ehkrfr92rgn8Hxgcp3Z9rgfXRjM= github.com/smartcontractkit/chainlink-ton v0.0.0-20260423161209-5ce1dba9785e h1:hoHL/UDtmasVzu78vwCkfLhDktqjPEhRK7DN58fnn1U= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 0829698f0af..1b38ae9cb57 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -25,14 +25,14 @@ require ( github.com/segmentio/ksuid v1.0.4 github.com/smartcontractkit/chain-selectors v1.0.98 github.com/smartcontractkit/chainlink-aptos v0.0.0-20260424112027-f932111b88ac - github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260423164805-f44aeafa2aaa - github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260415165642-49f23e4d76cc + github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260428205619-2db1389501a1 + github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260428205619-2db1389501a1 github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260415165642-49f23e4d76cc github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260415165642-49f23e4d76cc github.com/smartcontractkit/chainlink-common v0.11.2-0.20260428192532-b1f4aebef94a github.com/smartcontractkit/chainlink-common/keystore v1.1.0 github.com/smartcontractkit/chainlink-deployments-framework v0.98.0 - github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260428180431-40447a80e681 + github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429123911-44d13c62c6e1 github.com/smartcontractkit/chainlink-evm/gethwrappers v0.0.0-20260421142741-9c7fbaf7c828 github.com/smartcontractkit/chainlink-protos/job-distributor v0.18.0 github.com/smartcontractkit/chainlink-sui v0.0.0-20260427132612-76b9f754a556 @@ -404,7 +404,7 @@ require ( github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm v0.0.0-20260408145530-22e2d05695cd // indirect - github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260415165642-49f23e4d76cc // indirect + github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260428205619-2db1389501a1 // indirect github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260428133800-3b1484e8b1fd // indirect github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.13 // indirect @@ -427,9 +427,9 @@ require ( github.com/smartcontractkit/chainlink-protos/ring/go v0.0.0-20260331131315-f08a616d8dcd // indirect github.com/smartcontractkit/chainlink-protos/rmn/v1.6/go v0.0.0-20250131130834-15e0d4cde2a6 // indirect github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0 // indirect - github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3 // indirect + github.com/smartcontractkit/chainlink-protos/svr v1.2.0 // indirect github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428015924-9456bb6d8932 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428170719-7ad4e58aaacf // indirect github.com/smartcontractkit/chainlink-testing-framework/framework v0.15.18 // indirect github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20260408092456-3c6369888d4a // indirect github.com/smartcontractkit/freeport v0.1.3-0.20250828155247-add56fa28aad // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 9277a89079a..02884cdd786 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1368,18 +1368,18 @@ github.com/smartcontractkit/chainlink-aptos v0.0.0-20260424112027-f932111b88ac h github.com/smartcontractkit/chainlink-aptos v0.0.0-20260424112027-f932111b88ac/go.mod h1:ZU57FhGIb+m20yysn2fw+vLh3qB5hcgd06RXEUEDBck= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260423164805-f44aeafa2aaa h1:GE4B480m+/OMgkmZ9mEI1Abh927N7oW+Ruq9uuKIFQw= -github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260423164805-f44aeafa2aaa/go.mod h1:1XxxpkgCmG/z6y30yRuVrcxre6zixIVX3xzi706Db/8= +github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260428205619-2db1389501a1 h1:p0nFrTYrOQzDhWYm6suaM5CoWiXV5NV7llHnp6/Kn/8= +github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260428205619-2db1389501a1/go.mod h1:1XxxpkgCmG/z6y30yRuVrcxre6zixIVX3xzi706Db/8= github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm v0.0.0-20260408145530-22e2d05695cd h1:Jtw6p5iisjXZyFOcBvWh6PDQKtvryrRU2JMmezdutjo= github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm v0.0.0-20260408145530-22e2d05695cd/go.mod h1:zLqdD2kBX7NsntBneclb2yrHhjFaJdoyA8dK5eimlrE= -github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260415165642-49f23e4d76cc h1:dP1ERzdTbiJbHVXfHYdBAi1+8NjgkyQuY2oFNWWWDsQ= -github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:7XR5wfgT8hjSsiV+t0EAWvna+rYQeMPaoZf/0g+dios= +github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260428205619-2db1389501a1 h1:wfiut4oWMcpJmTEl/1ShwMBxwTQEv0wV4/YTma9Otxk= +github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260428205619-2db1389501a1/go.mod h1:hrNuLHgDa2f47WVO6+KgSxM1/SI1M8npQnaiv4kw3xo= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260415165642-49f23e4d76cc h1:mvobZx5JV5PhG/9IXPReV+8mAGnupl0HIWQZ43zxzd4= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:gzCVLUlNov/zFXSC7G6zcGkZU1IfNOHaakbAPDe5Woc= github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260415165642-49f23e4d76cc h1:War93neyFmv7pzuElZeZC3qc/OfGtLvEXvqL3qeBfM0= github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:67YbnoglYD61Pz/jTVCgav9wFq7S35OU8UyQSvPllRw= -github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260415165642-49f23e4d76cc h1:entc0pB4VQEkhJf/ymOfnUh6zcu1sj1OU4YW3iPEW4s= -github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:Ex2OUp35VJuCcRAjuBKwP+cevEPOSjy1pZXm3ncV4kQ= +github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260428205619-2db1389501a1 h1:TEdRdqbGFizjLKI16HiETpzUwyxSYhsJGX+NPk9Tv+o= +github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260428205619-2db1389501a1/go.mod h1:1rndR7UVFakZ6kMWZm1Vs6fFtrroJ4tny66U90fH6FE= github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260428133800-3b1484e8b1fd h1:IMopuENFVS63AerRELdfWo6o60UNUidcldJOxJLmk24= github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260428133800-3b1484e8b1fd/go.mod h1:SBN8Urnh5sQvrQRbSo1Nr8coWatHg8LZoPw3R/42sho= github.com/smartcontractkit/chainlink-common v0.11.2-0.20260428192532-b1f4aebef94a h1:uuJRUD/MHY2hX/f8k8MteJo9jA1+/8KLOCeJOCRSblg= @@ -1394,8 +1394,8 @@ github.com/smartcontractkit/chainlink-data-streams v0.1.13 h1:YOmt545DW6U0SyaqBf github.com/smartcontractkit/chainlink-data-streams v0.1.13/go.mod h1:00aL7OK0BJdF9gn/4t4f/pctUu2VLwwfA8G/tl9rCrM= github.com/smartcontractkit/chainlink-deployments-framework v0.98.0 h1:Ov/KOEtubOHXX8oa9UtARhHmkQNCOIjWNt+Zi0AuzHM= github.com/smartcontractkit/chainlink-deployments-framework v0.98.0/go.mod h1:24dwRW1PYolrlxSth///ddG3auGqR+50xaJiXfUHhkg= -github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260428180431-40447a80e681 h1:ehv4ucho8t5/E/Xg3u7qomdC4gB6IkSHlZx2ZrySaH8= -github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260428180431-40447a80e681/go.mod h1:eOx+FhknhG1+K/pKN77IR/UKmU3WDVaGci64VCGlCUc= +github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429123911-44d13c62c6e1 h1:7H7hiN8Q/bHvsprmA8OqiELGkJmMHYc+MTTOCDKIzm8= +github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429123911-44d13c62c6e1/go.mod h1:lhxIJe+Qy8duvf20q4D8ewfJzwHfvxK/s4s0exG1zEQ= github.com/smartcontractkit/chainlink-evm/contracts/cre/gobindings v0.0.0-20260403151002-2c91155b5501 h1:QJiXTG9CmaQAuMRn5JGi+Jhji7fSkehVnKpjc8oNJJY= github.com/smartcontractkit/chainlink-evm/contracts/cre/gobindings v0.0.0-20260403151002-2c91155b5501/go.mod h1:4cT1BeNF8DAn6In9zr3LayVCv1KzFeuxT7zcuNkfIb0= github.com/smartcontractkit/chainlink-evm/gethwrappers v0.0.0-20260421142741-9c7fbaf7c828 h1:BmsFk/TSHL6dPPR86GTqgSrUXLSINNFC6cfpFRrQX+4= @@ -1438,12 +1438,12 @@ github.com/smartcontractkit/chainlink-protos/rmn/v1.6/go v0.0.0-20250131130834-1 github.com/smartcontractkit/chainlink-protos/rmn/v1.6/go v0.0.0-20250131130834-15e0d4cde2a6/go.mod h1:FRwzI3hGj4CJclNS733gfcffmqQ62ONCkbGi49s658w= github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0 h1:B7itmjy+CMJ26elVw/cAJqqhBQ3Xa/mBYWK0/rQ5MuI= github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0/go.mod h1:h6kqaGajbNRrezm56zhx03p0mVmmA2xxj7E/M4ytLUA= -github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3 h1:X8Pekpv+cy0eW1laZTwATuYLTLZ6gRTxz1ZWOMtU74o= -github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= +github.com/smartcontractkit/chainlink-protos/svr v1.2.0 h1:7jjgqRgORQS/ikL3z0ZgJy95pzjhR9LuU1TVWg4BZ78= +github.com/smartcontractkit/chainlink-protos/svr v1.2.0/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997 h1:W0HKHO8eE8BckTRnhSdqjHKbJcnk068nEWYnWRu6tJY= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997/go.mod h1:GTpDgyK0OObf7jpch6p8N281KxN92wbB8serZhU9yRc= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428015924-9456bb6d8932 h1:aD5KjYqbHiL6OJl3f8tsopVkkAG68UsRJCKjDIACO6w= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428015924-9456bb6d8932/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428170719-7ad4e58aaacf h1:GyBD65Cc4HuwRKZ6k4UCtFaG7njGTnZyR+z3VPm3Vyo= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428170719-7ad4e58aaacf/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-sui v0.0.0-20260427132612-76b9f754a556 h1:Nz70a+A7aNnWRYdLpGdUf8NeauMvZFOBEPfZTm8vxwI= github.com/smartcontractkit/chainlink-sui v0.0.0-20260427132612-76b9f754a556/go.mod h1:xJ1UT4DKu1znbsm4ehkrfr92rgn8Hxgcp3Z9rgfXRjM= github.com/smartcontractkit/chainlink-sui/deployment v0.0.0-20260427132612-76b9f754a556 h1:6ocsoNPu3T0LsBiZ1tGZrjhKu8pGC1opUFz5KgHALSU= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index c8de95311e9..a99814555ed 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -16,13 +16,13 @@ require ( github.com/rs/zerolog v1.34.0 github.com/smartcontractkit/chain-selectors v1.0.98 github.com/smartcontractkit/chainlink-aptos v0.0.0-20260424112027-f932111b88ac - github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260423164805-f44aeafa2aaa - github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260415165642-49f23e4d76cc + github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260428205619-2db1389501a1 + github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260428205619-2db1389501a1 github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260415165642-49f23e4d76cc github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260415165642-49f23e4d76cc github.com/smartcontractkit/chainlink-common v0.11.2-0.20260428192532-b1f4aebef94a github.com/smartcontractkit/chainlink-deployments-framework v0.98.0 - github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260428180431-40447a80e681 + github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429123911-44d13c62c6e1 github.com/smartcontractkit/chainlink-testing-framework/framework v0.15.18 github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.5 github.com/smartcontractkit/chainlink-testing-framework/seth v1.51.5 @@ -479,7 +479,7 @@ require ( github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm v0.0.0-20260408145530-22e2d05695cd // indirect - github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260415165642-49f23e4d76cc // indirect + github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260428205619-2db1389501a1 // indirect github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260428133800-3b1484e8b1fd // indirect github.com/smartcontractkit/chainlink-common/keystore v1.1.0 // indirect github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10 // indirect @@ -505,9 +505,9 @@ require ( github.com/smartcontractkit/chainlink-protos/ring/go v0.0.0-20260331131315-f08a616d8dcd // indirect github.com/smartcontractkit/chainlink-protos/rmn/v1.6/go v0.0.0-20250131130834-15e0d4cde2a6 // indirect github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0 // indirect - github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3 // indirect + github.com/smartcontractkit/chainlink-protos/svr v1.2.0 // indirect github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428015924-9456bb6d8932 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428170719-7ad4e58aaacf // indirect github.com/smartcontractkit/chainlink-sui v0.0.0-20260427132612-76b9f754a556 // indirect github.com/smartcontractkit/chainlink-sui/deployment v0.0.0-20260427132612-76b9f754a556 // indirect github.com/smartcontractkit/chainlink-testing-framework/lib v1.54.7 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index d20967e511c..659f1b569aa 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1636,18 +1636,18 @@ github.com/smartcontractkit/chainlink-aptos v0.0.0-20260424112027-f932111b88ac h github.com/smartcontractkit/chainlink-aptos v0.0.0-20260424112027-f932111b88ac/go.mod h1:ZU57FhGIb+m20yysn2fw+vLh3qB5hcgd06RXEUEDBck= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260423164805-f44aeafa2aaa h1:GE4B480m+/OMgkmZ9mEI1Abh927N7oW+Ruq9uuKIFQw= -github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260423164805-f44aeafa2aaa/go.mod h1:1XxxpkgCmG/z6y30yRuVrcxre6zixIVX3xzi706Db/8= +github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260428205619-2db1389501a1 h1:p0nFrTYrOQzDhWYm6suaM5CoWiXV5NV7llHnp6/Kn/8= +github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260428205619-2db1389501a1/go.mod h1:1XxxpkgCmG/z6y30yRuVrcxre6zixIVX3xzi706Db/8= github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm v0.0.0-20260408145530-22e2d05695cd h1:Jtw6p5iisjXZyFOcBvWh6PDQKtvryrRU2JMmezdutjo= github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm v0.0.0-20260408145530-22e2d05695cd/go.mod h1:zLqdD2kBX7NsntBneclb2yrHhjFaJdoyA8dK5eimlrE= -github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260415165642-49f23e4d76cc h1:dP1ERzdTbiJbHVXfHYdBAi1+8NjgkyQuY2oFNWWWDsQ= -github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:7XR5wfgT8hjSsiV+t0EAWvna+rYQeMPaoZf/0g+dios= +github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260428205619-2db1389501a1 h1:wfiut4oWMcpJmTEl/1ShwMBxwTQEv0wV4/YTma9Otxk= +github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260428205619-2db1389501a1/go.mod h1:hrNuLHgDa2f47WVO6+KgSxM1/SI1M8npQnaiv4kw3xo= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260415165642-49f23e4d76cc h1:mvobZx5JV5PhG/9IXPReV+8mAGnupl0HIWQZ43zxzd4= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:gzCVLUlNov/zFXSC7G6zcGkZU1IfNOHaakbAPDe5Woc= github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260415165642-49f23e4d76cc h1:War93neyFmv7pzuElZeZC3qc/OfGtLvEXvqL3qeBfM0= github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:67YbnoglYD61Pz/jTVCgav9wFq7S35OU8UyQSvPllRw= -github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260415165642-49f23e4d76cc h1:entc0pB4VQEkhJf/ymOfnUh6zcu1sj1OU4YW3iPEW4s= -github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:Ex2OUp35VJuCcRAjuBKwP+cevEPOSjy1pZXm3ncV4kQ= +github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260428205619-2db1389501a1 h1:TEdRdqbGFizjLKI16HiETpzUwyxSYhsJGX+NPk9Tv+o= +github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260428205619-2db1389501a1/go.mod h1:1rndR7UVFakZ6kMWZm1Vs6fFtrroJ4tny66U90fH6FE= github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260428133800-3b1484e8b1fd h1:IMopuENFVS63AerRELdfWo6o60UNUidcldJOxJLmk24= github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260428133800-3b1484e8b1fd/go.mod h1:SBN8Urnh5sQvrQRbSo1Nr8coWatHg8LZoPw3R/42sho= github.com/smartcontractkit/chainlink-common v0.11.2-0.20260428192532-b1f4aebef94a h1:uuJRUD/MHY2hX/f8k8MteJo9jA1+/8KLOCeJOCRSblg= @@ -1662,8 +1662,8 @@ github.com/smartcontractkit/chainlink-data-streams v0.1.13 h1:YOmt545DW6U0SyaqBf github.com/smartcontractkit/chainlink-data-streams v0.1.13/go.mod h1:00aL7OK0BJdF9gn/4t4f/pctUu2VLwwfA8G/tl9rCrM= github.com/smartcontractkit/chainlink-deployments-framework v0.98.0 h1:Ov/KOEtubOHXX8oa9UtARhHmkQNCOIjWNt+Zi0AuzHM= github.com/smartcontractkit/chainlink-deployments-framework v0.98.0/go.mod h1:24dwRW1PYolrlxSth///ddG3auGqR+50xaJiXfUHhkg= -github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260428180431-40447a80e681 h1:ehv4ucho8t5/E/Xg3u7qomdC4gB6IkSHlZx2ZrySaH8= -github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260428180431-40447a80e681/go.mod h1:eOx+FhknhG1+K/pKN77IR/UKmU3WDVaGci64VCGlCUc= +github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429123911-44d13c62c6e1 h1:7H7hiN8Q/bHvsprmA8OqiELGkJmMHYc+MTTOCDKIzm8= +github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429123911-44d13c62c6e1/go.mod h1:lhxIJe+Qy8duvf20q4D8ewfJzwHfvxK/s4s0exG1zEQ= github.com/smartcontractkit/chainlink-evm/contracts/cre/gobindings v0.0.0-20260403151002-2c91155b5501 h1:QJiXTG9CmaQAuMRn5JGi+Jhji7fSkehVnKpjc8oNJJY= github.com/smartcontractkit/chainlink-evm/contracts/cre/gobindings v0.0.0-20260403151002-2c91155b5501/go.mod h1:4cT1BeNF8DAn6In9zr3LayVCv1KzFeuxT7zcuNkfIb0= github.com/smartcontractkit/chainlink-evm/gethwrappers v0.0.0-20260421142741-9c7fbaf7c828 h1:BmsFk/TSHL6dPPR86GTqgSrUXLSINNFC6cfpFRrQX+4= @@ -1706,12 +1706,12 @@ github.com/smartcontractkit/chainlink-protos/rmn/v1.6/go v0.0.0-20250131130834-1 github.com/smartcontractkit/chainlink-protos/rmn/v1.6/go v0.0.0-20250131130834-15e0d4cde2a6/go.mod h1:FRwzI3hGj4CJclNS733gfcffmqQ62ONCkbGi49s658w= github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0 h1:B7itmjy+CMJ26elVw/cAJqqhBQ3Xa/mBYWK0/rQ5MuI= github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0/go.mod h1:h6kqaGajbNRrezm56zhx03p0mVmmA2xxj7E/M4ytLUA= -github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3 h1:X8Pekpv+cy0eW1laZTwATuYLTLZ6gRTxz1ZWOMtU74o= -github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= +github.com/smartcontractkit/chainlink-protos/svr v1.2.0 h1:7jjgqRgORQS/ikL3z0ZgJy95pzjhR9LuU1TVWg4BZ78= +github.com/smartcontractkit/chainlink-protos/svr v1.2.0/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997 h1:W0HKHO8eE8BckTRnhSdqjHKbJcnk068nEWYnWRu6tJY= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997/go.mod h1:GTpDgyK0OObf7jpch6p8N281KxN92wbB8serZhU9yRc= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428015924-9456bb6d8932 h1:aD5KjYqbHiL6OJl3f8tsopVkkAG68UsRJCKjDIACO6w= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428015924-9456bb6d8932/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428170719-7ad4e58aaacf h1:GyBD65Cc4HuwRKZ6k4UCtFaG7njGTnZyR+z3VPm3Vyo= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428170719-7ad4e58aaacf/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-sui v0.0.0-20260427132612-76b9f754a556 h1:Nz70a+A7aNnWRYdLpGdUf8NeauMvZFOBEPfZTm8vxwI= github.com/smartcontractkit/chainlink-sui v0.0.0-20260427132612-76b9f754a556/go.mod h1:xJ1UT4DKu1znbsm4ehkrfr92rgn8Hxgcp3Z9rgfXRjM= github.com/smartcontractkit/chainlink-sui/deployment v0.0.0-20260427132612-76b9f754a556 h1:6ocsoNPu3T0LsBiZ1tGZrjhKu8pGC1opUFz5KgHALSU= diff --git a/plugins/plugins.private.yaml b/plugins/plugins.private.yaml index e6b14861e7d..e4a44a874f5 100644 --- a/plugins/plugins.private.yaml +++ b/plugins/plugins.private.yaml @@ -35,7 +35,7 @@ plugins: installPath: "." evm: - moduleURI: "github.com/smartcontractkit/capabilities/chain_capabilities/evm" - gitRef: "f7a5bfd742e34fe99ed6c0768994a0901264e641" + gitRef: "863d867937896a4869106e35995e897d4cf454e4" installPath: "." solana: - moduleURI: "github.com/smartcontractkit/capabilities/chain_capabilities/solana" diff --git a/plugins/plugins.public.yaml b/plugins/plugins.public.yaml index 700209c18e1..31e4eca3b57 100644 --- a/plugins/plugins.public.yaml +++ b/plugins/plugins.public.yaml @@ -35,7 +35,7 @@ plugins: solana: - moduleURI: "github.com/smartcontractkit/chainlink-solana" - gitRef: "v1.1.2-0.20260428015924-9456bb6d8932" + gitRef: "v1.1.2-0.20260428170719-7ad4e58aaacf" installPath: "./pkg/solana/cmd/chainlink-solana" starknet: diff --git a/system-tests/lib/cre/don/config/config.go b/system-tests/lib/cre/don/config/config.go index a3c6dd33b7d..019872cc730 100644 --- a/system-tests/lib/cre/don/config/config.go +++ b/system-tests/lib/cre/don/config/config.go @@ -22,7 +22,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-evm/pkg/config/chaintype" evmconfigtoml "github.com/smartcontractkit/chainlink-evm/pkg/config/toml" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" "github.com/smartcontractkit/chainlink-testing-framework/framework" chipingressset "github.com/smartcontractkit/chainlink-testing-framework/framework/components/dockercompose/chip_ingress_set" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" @@ -854,20 +853,20 @@ func appendEVMChain(existingConfig *evmconfigtoml.EVMConfigs, evmChain *evmChain *existingConfig = append(*existingConfig, &cfg) } -func appendSolanaChain(existingConfig *solcfg.TOMLConfigs, solChain *solanaChain) { +func appendSolanaChain(existingConfig *corechainlink.RawConfigs, solChain *solanaChain) { for _, existingSol := range *existingConfig { - if existingSol.ChainID != nil && *existingSol.ChainID == solChain.ChainID { + if existingSol.ChainID() == solChain.ChainID { return } } - *existingConfig = append(*existingConfig, &solcfg.TOMLConfig{ - Enabled: ptr.Ptr(true), - ChainID: ptr.Ptr(solChain.ChainID), - Nodes: []*solcfg.Node{ + *existingConfig = append(*existingConfig, corechainlink.RawConfig{ + "Enabled": true, + "ChainID": solChain.ChainID, + "Nodes": []map[string]any{ { - Name: &solChain.Name, - URL: commonconfig.MustParseURL(solChain.NodeURL), + "Name": solChain.Name, + "URL": solChain.NodeURL, }, }, }) diff --git a/system-tests/lib/cre/features/solana/v2/solana.go b/system-tests/lib/cre/features/solana/v2/solana.go index 64af56ef840..c7c8bd7e10f 100644 --- a/system-tests/lib/cre/features/solana/v2/solana.go +++ b/system-tests/lib/cre/features/solana/v2/solana.go @@ -22,7 +22,6 @@ import ( "github.com/smartcontractkit/chainlink-deployments-framework/datastore" "github.com/smartcontractkit/chainlink-deployments-framework/operations" kcr "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/cre/forwarder" @@ -445,12 +444,10 @@ func updateNodeConfig(workerNode *cre.NodeMetadata, chainID string, data input, return nil, fmt.Errorf("only 1 Solana chain is supported, but found %d for node at index %d", len(typedConfig.Solana), workerNode.Index) } - if typedConfig.Solana[0].ChainID == nil { - return nil, fmt.Errorf("solana chainID is nil for node at index %d", workerNode.Index) + if typedConfig.Solana[0].ChainID() == "" { + return nil, fmt.Errorf("solana chainID is empty for node at index %d", workerNode.Index) } - var solCfg solcfg.WorkflowConfig - // Execute template with chain's workflow configuration tmpl, err := template.New("solanaWorkflowConfig").Parse(solWorkflowConfigTemplate) if err != nil { @@ -467,12 +464,13 @@ func updateNodeConfig(workerNode *cre.NodeMetadata, chainID string, data input, return nil, fmt.Errorf("%s template validation failed: %w\nRendered template: %s", flag, err, configStr) } - unmarshallErr = toml.Unmarshal([]byte(configStr), &solCfg) + var solWorkflow map[string]any + unmarshallErr = toml.Unmarshal([]byte(configStr), &solWorkflow) if unmarshallErr != nil { return nil, errors.Wrap(unmarshallErr, "failed to unmarshal Solana.Workflow config") } - typedConfig.Solana[0].Workflow = solCfg + typedConfig.Solana[0]["Workflow"] = solWorkflow stringifiedConfig, mErr := toml.Marshal(typedConfig) if mErr != nil { diff --git a/system-tests/lib/go.mod b/system-tests/lib/go.mod index 0b390e38057..75a9f23b646 100644 --- a/system-tests/lib/go.mod +++ b/system-tests/lib/go.mod @@ -36,13 +36,12 @@ require ( github.com/smartcontractkit/chainlink-common v0.11.2-0.20260428192532-b1f4aebef94a github.com/smartcontractkit/chainlink-common/keystore v1.1.0 github.com/smartcontractkit/chainlink-deployments-framework v0.98.0 - github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260428180431-40447a80e681 + github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429123911-44d13c62c6e1 github.com/smartcontractkit/chainlink-evm/gethwrappers v0.0.0-20260421142741-9c7fbaf7c828 github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260420204255-a3f3bdd56877 github.com/smartcontractkit/chainlink-protos/job-distributor v0.18.0 github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997 - github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428015924-9456bb6d8932 github.com/smartcontractkit/chainlink-testing-framework/framework v0.15.18 github.com/smartcontractkit/chainlink-testing-framework/framework/components/chiprouter v1.0.2 github.com/smartcontractkit/chainlink-testing-framework/framework/components/dockercompose v0.1.15 @@ -454,11 +453,11 @@ require ( github.com/smartcontractkit/ccip-contract-examples/chains/evm v0.0.0-20260129135848-c86808ba5cb9 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect - github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260423164805-f44aeafa2aaa // indirect + github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260428205619-2db1389501a1 // indirect github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm v0.0.0-20260408145530-22e2d05695cd // indirect - github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260415165642-49f23e4d76cc // indirect + github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260428205619-2db1389501a1 // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260415165642-49f23e4d76cc // indirect - github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260415165642-49f23e4d76cc // indirect + github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260428205619-2db1389501a1 // indirect github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260428133800-3b1484e8b1fd // indirect github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20251211140724-319861e514c4 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.13 // indirect @@ -478,7 +477,8 @@ require ( github.com/smartcontractkit/chainlink-protos/ring/go v0.0.0-20260331131315-f08a616d8dcd // indirect github.com/smartcontractkit/chainlink-protos/rmn/v1.6/go v0.0.0-20250131130834-15e0d4cde2a6 // indirect github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0 // indirect - github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3 // indirect + github.com/smartcontractkit/chainlink-protos/svr v1.2.0 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428170719-7ad4e58aaacf // indirect github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c // indirect github.com/smartcontractkit/chainlink-sui v0.0.0-20260427132612-76b9f754a556 // indirect github.com/smartcontractkit/chainlink-sui/deployment v0.0.0-20260427132612-76b9f754a556 // indirect diff --git a/system-tests/lib/go.sum b/system-tests/lib/go.sum index 65e648021fc..577df946423 100644 --- a/system-tests/lib/go.sum +++ b/system-tests/lib/go.sum @@ -1604,18 +1604,18 @@ github.com/smartcontractkit/chainlink-aptos v0.0.0-20260424112027-f932111b88ac h github.com/smartcontractkit/chainlink-aptos v0.0.0-20260424112027-f932111b88ac/go.mod h1:ZU57FhGIb+m20yysn2fw+vLh3qB5hcgd06RXEUEDBck= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260423164805-f44aeafa2aaa h1:GE4B480m+/OMgkmZ9mEI1Abh927N7oW+Ruq9uuKIFQw= -github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260423164805-f44aeafa2aaa/go.mod h1:1XxxpkgCmG/z6y30yRuVrcxre6zixIVX3xzi706Db/8= +github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260428205619-2db1389501a1 h1:p0nFrTYrOQzDhWYm6suaM5CoWiXV5NV7llHnp6/Kn/8= +github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260428205619-2db1389501a1/go.mod h1:1XxxpkgCmG/z6y30yRuVrcxre6zixIVX3xzi706Db/8= github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm v0.0.0-20260408145530-22e2d05695cd h1:Jtw6p5iisjXZyFOcBvWh6PDQKtvryrRU2JMmezdutjo= github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm v0.0.0-20260408145530-22e2d05695cd/go.mod h1:zLqdD2kBX7NsntBneclb2yrHhjFaJdoyA8dK5eimlrE= -github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260415165642-49f23e4d76cc h1:dP1ERzdTbiJbHVXfHYdBAi1+8NjgkyQuY2oFNWWWDsQ= -github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:7XR5wfgT8hjSsiV+t0EAWvna+rYQeMPaoZf/0g+dios= +github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260428205619-2db1389501a1 h1:wfiut4oWMcpJmTEl/1ShwMBxwTQEv0wV4/YTma9Otxk= +github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260428205619-2db1389501a1/go.mod h1:hrNuLHgDa2f47WVO6+KgSxM1/SI1M8npQnaiv4kw3xo= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260415165642-49f23e4d76cc h1:mvobZx5JV5PhG/9IXPReV+8mAGnupl0HIWQZ43zxzd4= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:gzCVLUlNov/zFXSC7G6zcGkZU1IfNOHaakbAPDe5Woc= github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260415165642-49f23e4d76cc h1:War93neyFmv7pzuElZeZC3qc/OfGtLvEXvqL3qeBfM0= github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:67YbnoglYD61Pz/jTVCgav9wFq7S35OU8UyQSvPllRw= -github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260415165642-49f23e4d76cc h1:entc0pB4VQEkhJf/ymOfnUh6zcu1sj1OU4YW3iPEW4s= -github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:Ex2OUp35VJuCcRAjuBKwP+cevEPOSjy1pZXm3ncV4kQ= +github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260428205619-2db1389501a1 h1:TEdRdqbGFizjLKI16HiETpzUwyxSYhsJGX+NPk9Tv+o= +github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260428205619-2db1389501a1/go.mod h1:1rndR7UVFakZ6kMWZm1Vs6fFtrroJ4tny66U90fH6FE= github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260428133800-3b1484e8b1fd h1:IMopuENFVS63AerRELdfWo6o60UNUidcldJOxJLmk24= github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260428133800-3b1484e8b1fd/go.mod h1:SBN8Urnh5sQvrQRbSo1Nr8coWatHg8LZoPw3R/42sho= github.com/smartcontractkit/chainlink-common v0.11.2-0.20260428192532-b1f4aebef94a h1:uuJRUD/MHY2hX/f8k8MteJo9jA1+/8KLOCeJOCRSblg= @@ -1630,8 +1630,8 @@ github.com/smartcontractkit/chainlink-data-streams v0.1.13 h1:YOmt545DW6U0SyaqBf github.com/smartcontractkit/chainlink-data-streams v0.1.13/go.mod h1:00aL7OK0BJdF9gn/4t4f/pctUu2VLwwfA8G/tl9rCrM= github.com/smartcontractkit/chainlink-deployments-framework v0.98.0 h1:Ov/KOEtubOHXX8oa9UtARhHmkQNCOIjWNt+Zi0AuzHM= github.com/smartcontractkit/chainlink-deployments-framework v0.98.0/go.mod h1:24dwRW1PYolrlxSth///ddG3auGqR+50xaJiXfUHhkg= -github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260428180431-40447a80e681 h1:ehv4ucho8t5/E/Xg3u7qomdC4gB6IkSHlZx2ZrySaH8= -github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260428180431-40447a80e681/go.mod h1:eOx+FhknhG1+K/pKN77IR/UKmU3WDVaGci64VCGlCUc= +github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429123911-44d13c62c6e1 h1:7H7hiN8Q/bHvsprmA8OqiELGkJmMHYc+MTTOCDKIzm8= +github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429123911-44d13c62c6e1/go.mod h1:lhxIJe+Qy8duvf20q4D8ewfJzwHfvxK/s4s0exG1zEQ= github.com/smartcontractkit/chainlink-evm/contracts/cre/gobindings v0.0.0-20260403151002-2c91155b5501 h1:QJiXTG9CmaQAuMRn5JGi+Jhji7fSkehVnKpjc8oNJJY= github.com/smartcontractkit/chainlink-evm/contracts/cre/gobindings v0.0.0-20260403151002-2c91155b5501/go.mod h1:4cT1BeNF8DAn6In9zr3LayVCv1KzFeuxT7zcuNkfIb0= github.com/smartcontractkit/chainlink-evm/gethwrappers v0.0.0-20260421142741-9c7fbaf7c828 h1:BmsFk/TSHL6dPPR86GTqgSrUXLSINNFC6cfpFRrQX+4= @@ -1674,12 +1674,12 @@ github.com/smartcontractkit/chainlink-protos/rmn/v1.6/go v0.0.0-20250131130834-1 github.com/smartcontractkit/chainlink-protos/rmn/v1.6/go v0.0.0-20250131130834-15e0d4cde2a6/go.mod h1:FRwzI3hGj4CJclNS733gfcffmqQ62ONCkbGi49s658w= github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0 h1:B7itmjy+CMJ26elVw/cAJqqhBQ3Xa/mBYWK0/rQ5MuI= github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0/go.mod h1:h6kqaGajbNRrezm56zhx03p0mVmmA2xxj7E/M4ytLUA= -github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3 h1:X8Pekpv+cy0eW1laZTwATuYLTLZ6gRTxz1ZWOMtU74o= -github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= +github.com/smartcontractkit/chainlink-protos/svr v1.2.0 h1:7jjgqRgORQS/ikL3z0ZgJy95pzjhR9LuU1TVWg4BZ78= +github.com/smartcontractkit/chainlink-protos/svr v1.2.0/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997 h1:W0HKHO8eE8BckTRnhSdqjHKbJcnk068nEWYnWRu6tJY= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997/go.mod h1:GTpDgyK0OObf7jpch6p8N281KxN92wbB8serZhU9yRc= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428015924-9456bb6d8932 h1:aD5KjYqbHiL6OJl3f8tsopVkkAG68UsRJCKjDIACO6w= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428015924-9456bb6d8932/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428170719-7ad4e58aaacf h1:GyBD65Cc4HuwRKZ6k4UCtFaG7njGTnZyR+z3VPm3Vyo= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428170719-7ad4e58aaacf/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c h1:Hn/80PyYFrQhRlNSaq9HY4cjc/7AuP9zyWLle22t34A= github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c/go.mod h1:C5pZsbYX3qkhZTYWr1aYJi9QMfonFAun+Jl1npQ7UJA= github.com/smartcontractkit/chainlink-sui v0.0.0-20260427132612-76b9f754a556 h1:Nz70a+A7aNnWRYdLpGdUf8NeauMvZFOBEPfZTm8vxwI= diff --git a/system-tests/tests/go.mod b/system-tests/tests/go.mod index b4eed26c708..c3dfe04a5dc 100644 --- a/system-tests/tests/go.mod +++ b/system-tests/tests/go.mod @@ -147,17 +147,17 @@ require ( github.com/sigstore/sigstore v1.10.4 // indirect github.com/sigstore/sigstore-go v1.1.4 // indirect github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm v0.0.0-20260408145530-22e2d05695cd // indirect - github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260415165642-49f23e4d76cc // indirect + github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260428205619-2db1389501a1 // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260415165642-49f23e4d76cc // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260415165642-49f23e4d76cc // indirect - github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260415165642-49f23e4d76cc // indirect + github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260428205619-2db1389501a1 // indirect github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260428133800-3b1484e8b1fd // indirect github.com/smartcontractkit/chainlink-protos/chainlink-ccv/committee-verifier v0.0.0-20251211142334-5c3421fe2c8d // indirect github.com/smartcontractkit/chainlink-protos/chainlink-ccv/heartbeat v0.0.0-20260115142640-f6b99095c12e // indirect github.com/smartcontractkit/chainlink-protos/chainlink-ccv/message-discovery v0.0.0-20251211142334-5c3421fe2c8d // indirect github.com/smartcontractkit/chainlink-protos/chainlink-ccv/verifier v0.0.0-20251211142334-5c3421fe2c8d // indirect github.com/smartcontractkit/chainlink-protos/node-platform v0.0.0-20260319180422-b5808c964785 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428015924-9456bb6d8932 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428170719-7ad4e58aaacf // indirect github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c // indirect github.com/smartcontractkit/chainlink-sui/deployment v0.0.0-20260427132612-76b9f754a556 // indirect github.com/smartcontractkit/cld-changesets v0.0.0-20260427210718-b873c54e8d22 // indirect @@ -603,9 +603,9 @@ require ( github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect github.com/smartcontractkit/chainlink-aptos v0.0.0-20260424112027-f932111b88ac github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect - github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260423164805-f44aeafa2aaa // indirect + github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260428205619-2db1389501a1 // indirect github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20251211140724-319861e514c4 - github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260428180431-40447a80e681 // indirect + github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429123911-44d13c62c6e1 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20260423135514-5b1a7565a99c // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20260423135514-5b1a7565a99c // indirect @@ -616,7 +616,7 @@ require ( github.com/smartcontractkit/chainlink-protos/orchestrator v0.10.0 // indirect github.com/smartcontractkit/chainlink-protos/rmn/v1.6/go v0.0.0-20250131130834-15e0d4cde2a6 // indirect github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0 // indirect - github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3 // indirect + github.com/smartcontractkit/chainlink-protos/svr v1.2.0 // indirect github.com/smartcontractkit/chainlink-sui v0.0.0-20260427132612-76b9f754a556 // indirect github.com/smartcontractkit/chainlink-testing-framework/framework/components/dockercompose v0.1.18 // indirect github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 // indirect diff --git a/system-tests/tests/go.sum b/system-tests/tests/go.sum index f7b45cf13a4..0dad6a91db0 100644 --- a/system-tests/tests/go.sum +++ b/system-tests/tests/go.sum @@ -1819,18 +1819,18 @@ github.com/smartcontractkit/chainlink-aptos v0.0.0-20260424112027-f932111b88ac h github.com/smartcontractkit/chainlink-aptos v0.0.0-20260424112027-f932111b88ac/go.mod h1:ZU57FhGIb+m20yysn2fw+vLh3qB5hcgd06RXEUEDBck= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260423164805-f44aeafa2aaa h1:GE4B480m+/OMgkmZ9mEI1Abh927N7oW+Ruq9uuKIFQw= -github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260423164805-f44aeafa2aaa/go.mod h1:1XxxpkgCmG/z6y30yRuVrcxre6zixIVX3xzi706Db/8= +github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260428205619-2db1389501a1 h1:p0nFrTYrOQzDhWYm6suaM5CoWiXV5NV7llHnp6/Kn/8= +github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260428205619-2db1389501a1/go.mod h1:1XxxpkgCmG/z6y30yRuVrcxre6zixIVX3xzi706Db/8= github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm v0.0.0-20260408145530-22e2d05695cd h1:Jtw6p5iisjXZyFOcBvWh6PDQKtvryrRU2JMmezdutjo= github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm v0.0.0-20260408145530-22e2d05695cd/go.mod h1:zLqdD2kBX7NsntBneclb2yrHhjFaJdoyA8dK5eimlrE= -github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260415165642-49f23e4d76cc h1:dP1ERzdTbiJbHVXfHYdBAi1+8NjgkyQuY2oFNWWWDsQ= -github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:7XR5wfgT8hjSsiV+t0EAWvna+rYQeMPaoZf/0g+dios= +github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260428205619-2db1389501a1 h1:wfiut4oWMcpJmTEl/1ShwMBxwTQEv0wV4/YTma9Otxk= +github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260428205619-2db1389501a1/go.mod h1:hrNuLHgDa2f47WVO6+KgSxM1/SI1M8npQnaiv4kw3xo= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260415165642-49f23e4d76cc h1:mvobZx5JV5PhG/9IXPReV+8mAGnupl0HIWQZ43zxzd4= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:gzCVLUlNov/zFXSC7G6zcGkZU1IfNOHaakbAPDe5Woc= github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260415165642-49f23e4d76cc h1:War93neyFmv7pzuElZeZC3qc/OfGtLvEXvqL3qeBfM0= github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:67YbnoglYD61Pz/jTVCgav9wFq7S35OU8UyQSvPllRw= -github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260415165642-49f23e4d76cc h1:entc0pB4VQEkhJf/ymOfnUh6zcu1sj1OU4YW3iPEW4s= -github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:Ex2OUp35VJuCcRAjuBKwP+cevEPOSjy1pZXm3ncV4kQ= +github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260428205619-2db1389501a1 h1:TEdRdqbGFizjLKI16HiETpzUwyxSYhsJGX+NPk9Tv+o= +github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260428205619-2db1389501a1/go.mod h1:1rndR7UVFakZ6kMWZm1Vs6fFtrroJ4tny66U90fH6FE= github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260428133800-3b1484e8b1fd h1:IMopuENFVS63AerRELdfWo6o60UNUidcldJOxJLmk24= github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260428133800-3b1484e8b1fd/go.mod h1:SBN8Urnh5sQvrQRbSo1Nr8coWatHg8LZoPw3R/42sho= github.com/smartcontractkit/chainlink-common v0.11.2-0.20260428192532-b1f4aebef94a h1:uuJRUD/MHY2hX/f8k8MteJo9jA1+/8KLOCeJOCRSblg= @@ -1845,8 +1845,8 @@ github.com/smartcontractkit/chainlink-data-streams v0.1.13 h1:YOmt545DW6U0SyaqBf github.com/smartcontractkit/chainlink-data-streams v0.1.13/go.mod h1:00aL7OK0BJdF9gn/4t4f/pctUu2VLwwfA8G/tl9rCrM= github.com/smartcontractkit/chainlink-deployments-framework v0.98.0 h1:Ov/KOEtubOHXX8oa9UtARhHmkQNCOIjWNt+Zi0AuzHM= github.com/smartcontractkit/chainlink-deployments-framework v0.98.0/go.mod h1:24dwRW1PYolrlxSth///ddG3auGqR+50xaJiXfUHhkg= -github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260428180431-40447a80e681 h1:ehv4ucho8t5/E/Xg3u7qomdC4gB6IkSHlZx2ZrySaH8= -github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260428180431-40447a80e681/go.mod h1:eOx+FhknhG1+K/pKN77IR/UKmU3WDVaGci64VCGlCUc= +github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429123911-44d13c62c6e1 h1:7H7hiN8Q/bHvsprmA8OqiELGkJmMHYc+MTTOCDKIzm8= +github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260429123911-44d13c62c6e1/go.mod h1:lhxIJe+Qy8duvf20q4D8ewfJzwHfvxK/s4s0exG1zEQ= github.com/smartcontractkit/chainlink-evm/contracts/cre/gobindings v0.0.0-20260403151002-2c91155b5501 h1:QJiXTG9CmaQAuMRn5JGi+Jhji7fSkehVnKpjc8oNJJY= github.com/smartcontractkit/chainlink-evm/contracts/cre/gobindings v0.0.0-20260403151002-2c91155b5501/go.mod h1:4cT1BeNF8DAn6In9zr3LayVCv1KzFeuxT7zcuNkfIb0= github.com/smartcontractkit/chainlink-evm/gethwrappers v0.0.0-20260421142741-9c7fbaf7c828 h1:BmsFk/TSHL6dPPR86GTqgSrUXLSINNFC6cfpFRrQX+4= @@ -1889,12 +1889,12 @@ github.com/smartcontractkit/chainlink-protos/rmn/v1.6/go v0.0.0-20250131130834-1 github.com/smartcontractkit/chainlink-protos/rmn/v1.6/go v0.0.0-20250131130834-15e0d4cde2a6/go.mod h1:FRwzI3hGj4CJclNS733gfcffmqQ62ONCkbGi49s658w= github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0 h1:B7itmjy+CMJ26elVw/cAJqqhBQ3Xa/mBYWK0/rQ5MuI= github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0/go.mod h1:h6kqaGajbNRrezm56zhx03p0mVmmA2xxj7E/M4ytLUA= -github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3 h1:X8Pekpv+cy0eW1laZTwATuYLTLZ6gRTxz1ZWOMtU74o= -github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= +github.com/smartcontractkit/chainlink-protos/svr v1.2.0 h1:7jjgqRgORQS/ikL3z0ZgJy95pzjhR9LuU1TVWg4BZ78= +github.com/smartcontractkit/chainlink-protos/svr v1.2.0/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997 h1:W0HKHO8eE8BckTRnhSdqjHKbJcnk068nEWYnWRu6tJY= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997/go.mod h1:GTpDgyK0OObf7jpch6p8N281KxN92wbB8serZhU9yRc= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428015924-9456bb6d8932 h1:aD5KjYqbHiL6OJl3f8tsopVkkAG68UsRJCKjDIACO6w= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428015924-9456bb6d8932/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428170719-7ad4e58aaacf h1:GyBD65Cc4HuwRKZ6k4UCtFaG7njGTnZyR+z3VPm3Vyo= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260428170719-7ad4e58aaacf/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c h1:Hn/80PyYFrQhRlNSaq9HY4cjc/7AuP9zyWLle22t34A= github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c/go.mod h1:C5pZsbYX3qkhZTYWr1aYJi9QMfonFAun+Jl1npQ7UJA= github.com/smartcontractkit/chainlink-sui v0.0.0-20260427132612-76b9f754a556 h1:Nz70a+A7aNnWRYdLpGdUf8NeauMvZFOBEPfZTm8vxwI= diff --git a/testdata/scripts/config/merge_raw_configs.txtar b/testdata/scripts/config/merge_raw_configs.txtar index f61352bb1f0..375ee9b1a9c 100644 --- a/testdata/scripts/config/merge_raw_configs.txtar +++ b/testdata/scripts/config/merge_raw_configs.txtar @@ -340,21 +340,6 @@ DeltaDial = '5s' DeltaReconcile = '5s' ListenAddresses = ['0.0.0.0:6691'] -[Keeper] -DefaultTransactionQueueDepth = 1 -GasPriceBufferPercent = 20 -GasTipCapBufferPercent = 20 -BaseFeeBufferPercent = 20 -MaxGracePeriod = 100 -TurnLookBack = 1000 - -[Keeper.Registry] -CheckGasOverhead = 200000 -PerformGasOverhead = 300000 -MaxPerformDataSize = 5000 -SyncInterval = '30m0s' -SyncUpkeepQueueSize = 10 - [AutoPprof] Enabled = false ProfileRoot = '' diff --git a/testdata/scripts/health/multi-chain.txtar b/testdata/scripts/health/multi-chain.txtar index ad456fc2db8..ec3e64b65b4 100644 --- a/testdata/scripts/health/multi-chain.txtar +++ b/testdata/scripts/health/multi-chain.txtar @@ -46,13 +46,6 @@ Name = 'fake' WSURL = 'wss://foo.bar/ws' HTTPURL = 'https://foo.bar' -[[Solana]] -ChainID = 'Bar' - -[[Solana.Nodes]] -Name = 'primary' -URL = 'http://solana.web' - -- out.txt -- ok BridgeStatusReporter ok CRE @@ -83,10 +76,6 @@ ok PipelineORM ok PipelineRunner ok PipelineRunner.BridgeCache ok RetirementReportCache -ok Solana.Bar.Chain -ok Solana.Bar.Chain.BalanceMonitor -ok Solana.Bar.Chain.Txm -ok Solana.Bar.Relayer ok TelemetryManager ok WorkflowStore @@ -349,42 +338,6 @@ ok WorkflowStore "output": "" } }, - { - "type": "checks", - "id": "Solana.Bar.Chain", - "attributes": { - "name": "Solana.Bar.Chain", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "Solana.Bar.Chain.BalanceMonitor", - "attributes": { - "name": "Solana.Bar.Chain.BalanceMonitor", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "Solana.Bar.Chain.Txm", - "attributes": { - "name": "Solana.Bar.Chain.Txm", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "Solana.Bar.Relayer", - "attributes": { - "name": "Solana.Bar.Relayer", - "status": "passing", - "output": "" - } - }, { "type": "checks", "id": "TelemetryManager", diff --git a/testdata/scripts/node/validate/default.txtar b/testdata/scripts/node/validate/default.txtar index 8c68e3e8080..f3d2d8bd42d 100644 --- a/testdata/scripts/node/validate/default.txtar +++ b/testdata/scripts/node/validate/default.txtar @@ -205,21 +205,6 @@ DeltaDial = '15s' DeltaReconcile = '1m0s' ListenAddresses = [] -[Keeper] -DefaultTransactionQueueDepth = 1 -GasPriceBufferPercent = 20 -GasTipCapBufferPercent = 20 -BaseFeeBufferPercent = 20 -MaxGracePeriod = 100 -TurnLookBack = 1000 - -[Keeper.Registry] -CheckGasOverhead = 200000 -PerformGasOverhead = 300000 -MaxPerformDataSize = 5000 -SyncInterval = '30m0s' -SyncUpkeepQueueSize = 10 - [AutoPprof] Enabled = false ProfileRoot = '' diff --git a/testdata/scripts/node/validate/defaults-override.txtar b/testdata/scripts/node/validate/defaults-override.txtar index 2ac17e1d98a..1c1095d4f6e 100644 --- a/testdata/scripts/node/validate/defaults-override.txtar +++ b/testdata/scripts/node/validate/defaults-override.txtar @@ -266,21 +266,6 @@ DeltaDial = '15s' DeltaReconcile = '1m0s' ListenAddresses = [] -[Keeper] -DefaultTransactionQueueDepth = 1 -GasPriceBufferPercent = 20 -GasTipCapBufferPercent = 20 -BaseFeeBufferPercent = 20 -MaxGracePeriod = 100 -TurnLookBack = 1000 - -[Keeper.Registry] -CheckGasOverhead = 200000 -PerformGasOverhead = 300000 -MaxPerformDataSize = 5000 -SyncInterval = '30m0s' -SyncUpkeepQueueSize = 10 - [AutoPprof] Enabled = false ProfileRoot = '' diff --git a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar index a6faa67cf2b..4f38567ac4d 100644 --- a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar @@ -249,21 +249,6 @@ DeltaDial = '15s' DeltaReconcile = '1m0s' ListenAddresses = [] -[Keeper] -DefaultTransactionQueueDepth = 1 -GasPriceBufferPercent = 20 -GasTipCapBufferPercent = 20 -BaseFeeBufferPercent = 20 -MaxGracePeriod = 100 -TurnLookBack = 1000 - -[Keeper.Registry] -CheckGasOverhead = 200000 -PerformGasOverhead = 300000 -MaxPerformDataSize = 5000 -SyncInterval = '30m0s' -SyncUpkeepQueueSize = 10 - [AutoPprof] Enabled = false ProfileRoot = '' diff --git a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar index 70d7d128c18..8ebd43333a2 100644 --- a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar @@ -249,21 +249,6 @@ DeltaDial = '15s' DeltaReconcile = '1m0s' ListenAddresses = [] -[Keeper] -DefaultTransactionQueueDepth = 1 -GasPriceBufferPercent = 20 -GasTipCapBufferPercent = 20 -BaseFeeBufferPercent = 20 -MaxGracePeriod = 100 -TurnLookBack = 1000 - -[Keeper.Registry] -CheckGasOverhead = 200000 -PerformGasOverhead = 300000 -MaxPerformDataSize = 5000 -SyncInterval = '30m0s' -SyncUpkeepQueueSize = 10 - [AutoPprof] Enabled = false ProfileRoot = '' diff --git a/testdata/scripts/node/validate/disk-based-logging.txtar b/testdata/scripts/node/validate/disk-based-logging.txtar index 85d2fe99370..4f9631aff06 100644 --- a/testdata/scripts/node/validate/disk-based-logging.txtar +++ b/testdata/scripts/node/validate/disk-based-logging.txtar @@ -249,21 +249,6 @@ DeltaDial = '15s' DeltaReconcile = '1m0s' ListenAddresses = [] -[Keeper] -DefaultTransactionQueueDepth = 1 -GasPriceBufferPercent = 20 -GasTipCapBufferPercent = 20 -BaseFeeBufferPercent = 20 -MaxGracePeriod = 100 -TurnLookBack = 1000 - -[Keeper.Registry] -CheckGasOverhead = 200000 -PerformGasOverhead = 300000 -MaxPerformDataSize = 5000 -SyncInterval = '30m0s' -SyncUpkeepQueueSize = 10 - [AutoPprof] Enabled = false ProfileRoot = '' diff --git a/testdata/scripts/node/validate/fallback-override.txtar b/testdata/scripts/node/validate/fallback-override.txtar index ae2ecc22a0e..df43ea5f0b4 100644 --- a/testdata/scripts/node/validate/fallback-override.txtar +++ b/testdata/scripts/node/validate/fallback-override.txtar @@ -349,21 +349,6 @@ DeltaDial = '15s' DeltaReconcile = '1m0s' ListenAddresses = [] -[Keeper] -DefaultTransactionQueueDepth = 1 -GasPriceBufferPercent = 20 -GasTipCapBufferPercent = 20 -BaseFeeBufferPercent = 20 -MaxGracePeriod = 100 -TurnLookBack = 1000 - -[Keeper.Registry] -CheckGasOverhead = 200000 -PerformGasOverhead = 300000 -MaxPerformDataSize = 5000 -SyncInterval = '30m0s' -SyncUpkeepQueueSize = 10 - [AutoPprof] Enabled = false ProfileRoot = '' diff --git a/testdata/scripts/node/validate/invalid-duplicates.txtar b/testdata/scripts/node/validate/invalid-duplicates.txtar index 7cb1bbe6b6b..c45237d410d 100644 --- a/testdata/scripts/node/validate/invalid-duplicates.txtar +++ b/testdata/scripts/node/validate/invalid-duplicates.txtar @@ -96,10 +96,9 @@ Error running app: invalid configuration: 5 errors: - Cosmos: 2 errors: - 1.ChainID: invalid value (Malaga-420): duplicate - must be unique - 1.Nodes.1.Name: invalid value (primary): duplicate - must be unique - - Solana: 3 errors: + - Solana: 2 errors: - 1.ChainID: invalid value (mainnet): duplicate - must be unique - 1.Nodes.1.Name: invalid value (primary): duplicate - must be unique - - 1.Nodes.1.URL: invalid value (http://solana.web): duplicate - must be unique - Starknet: 2 errors: - 1.ChainID: invalid value (foobar): duplicate - must be unique - 1.Nodes.1.Name: invalid value (primary): duplicate - must be unique diff --git a/testdata/scripts/node/validate/invalid-ocr-p2p.txtar b/testdata/scripts/node/validate/invalid-ocr-p2p.txtar index 8b92ebfd791..714b54d7e75 100644 --- a/testdata/scripts/node/validate/invalid-ocr-p2p.txtar +++ b/testdata/scripts/node/validate/invalid-ocr-p2p.txtar @@ -234,21 +234,6 @@ DeltaDial = '15s' DeltaReconcile = '1m0s' ListenAddresses = [] -[Keeper] -DefaultTransactionQueueDepth = 1 -GasPriceBufferPercent = 20 -GasTipCapBufferPercent = 20 -BaseFeeBufferPercent = 20 -MaxGracePeriod = 100 -TurnLookBack = 1000 - -[Keeper.Registry] -CheckGasOverhead = 200000 -PerformGasOverhead = 300000 -MaxPerformDataSize = 5000 -SyncInterval = '30m0s' -SyncUpkeepQueueSize = 10 - [AutoPprof] Enabled = false ProfileRoot = '' diff --git a/testdata/scripts/node/validate/invalid.txtar b/testdata/scripts/node/validate/invalid.txtar index a3e7559ee4c..28a2b2ff3e3 100644 --- a/testdata/scripts/node/validate/invalid.txtar +++ b/testdata/scripts/node/validate/invalid.txtar @@ -245,21 +245,6 @@ DeltaDial = '15s' DeltaReconcile = '1m0s' ListenAddresses = [] -[Keeper] -DefaultTransactionQueueDepth = 1 -GasPriceBufferPercent = 20 -GasTipCapBufferPercent = 20 -BaseFeeBufferPercent = 20 -MaxGracePeriod = 100 -TurnLookBack = 1000 - -[Keeper.Registry] -CheckGasOverhead = 200000 -PerformGasOverhead = 300000 -MaxPerformDataSize = 5000 -SyncInterval = '30m0s' -SyncUpkeepQueueSize = 10 - [AutoPprof] Enabled = false ProfileRoot = '' diff --git a/testdata/scripts/node/validate/valid.txtar b/testdata/scripts/node/validate/valid.txtar index dbddd11dac7..bf73f4924cf 100644 --- a/testdata/scripts/node/validate/valid.txtar +++ b/testdata/scripts/node/validate/valid.txtar @@ -246,21 +246,6 @@ DeltaDial = '15s' DeltaReconcile = '1m0s' ListenAddresses = [] -[Keeper] -DefaultTransactionQueueDepth = 1 -GasPriceBufferPercent = 20 -GasTipCapBufferPercent = 20 -BaseFeeBufferPercent = 20 -MaxGracePeriod = 100 -TurnLookBack = 1000 - -[Keeper.Registry] -CheckGasOverhead = 200000 -PerformGasOverhead = 300000 -MaxPerformDataSize = 5000 -SyncInterval = '30m0s' -SyncUpkeepQueueSize = 10 - [AutoPprof] Enabled = false ProfileRoot = '' diff --git a/testdata/scripts/node/validate/warnings.txtar b/testdata/scripts/node/validate/warnings.txtar index 3ab643dd95b..973da76176b 100644 --- a/testdata/scripts/node/validate/warnings.txtar +++ b/testdata/scripts/node/validate/warnings.txtar @@ -228,21 +228,6 @@ DeltaDial = '15s' DeltaReconcile = '1m0s' ListenAddresses = [] -[Keeper] -DefaultTransactionQueueDepth = 1 -GasPriceBufferPercent = 20 -GasTipCapBufferPercent = 20 -BaseFeeBufferPercent = 20 -MaxGracePeriod = 100 -TurnLookBack = 1000 - -[Keeper.Registry] -CheckGasOverhead = 200000 -PerformGasOverhead = 300000 -MaxPerformDataSize = 5000 -SyncInterval = '30m0s' -SyncUpkeepQueueSize = 10 - [AutoPprof] Enabled = false ProfileRoot = '' diff --git a/testdata/scripts/nodes/solana/list/list.txtar b/testdata/scripts/nodes/solana/list/list.txtar index dc65e06103f..81f5ec851f8 100644 --- a/testdata/scripts/nodes/solana/list/list.txtar +++ b/testdata/scripts/nodes/solana/list/list.txtar @@ -10,6 +10,7 @@ exec chainlink --remote-node-url $NODEURL admin login -file creds --bypass-versi exec chainlink --remote-node-url $NODEURL nodes solana list cmp stdout out.txt +-- go:build.integration -- -- testdb.txt -- CL_DATABASE_URL -- testport.txt --