diff --git a/core/chains/evm/chain.go b/core/chains/evm/chain.go index 39c92252c7f..6a948a4cdd0 100644 --- a/core/chains/evm/chain.go +++ b/core/chains/evm/chain.go @@ -74,8 +74,6 @@ type LegacyChains struct { // //go:generate mockery --quiet --name LegacyChainContainer --output ./mocks/ --case=underscore type LegacyChainContainer interface { - SetDefault(Chain) - Default() (Chain, error) Get(id string) (Chain, error) Len() int List(ids ...string) ([]Chain, error) @@ -100,27 +98,14 @@ func (c *LegacyChains) ChainNodeConfigs() evmtypes.Configs { return c.cfgs } -// TODO BCR-2510 this may not be needed if EVM is not enabled by default -func (c *LegacyChains) SetDefault(dflt Chain) { - c.dflt = dflt -} - -func (c *LegacyChains) Default() (Chain, error) { - if c.dflt == nil { - return nil, fmt.Errorf("no default chain specified") - } - return c.dflt, nil -} - // backward compatibility. // eth keys are represented as multiple types in the code base; -// *big.Int, string, and int64. this lead to special 'default' handling -// of nil big.Int and empty string. +// *big.Int, string, and int64. // // TODO BCF-2507 unify the type system func (c *LegacyChains) Get(id string) (Chain, error) { if id == nilBigInt.String() || id == emptyString { - return c.Default() + return nil, fmt.Errorf("invalid chain id requested: %q", id) } return c.ChainsKV.Get(id) } diff --git a/core/chains/evm/config/mocks/chain_scoped_config.go b/core/chains/evm/config/mocks/chain_scoped_config.go index f1e09cc54ab..b8347f6e4bb 100644 --- a/core/chains/evm/config/mocks/chain_scoped_config.go +++ b/core/chains/evm/config/mocks/chain_scoped_config.go @@ -3,8 +3,6 @@ package mocks import ( - big "math/big" - config "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" coreconfig "github.com/smartcontractkit/chainlink/v2/core/config" @@ -100,22 +98,6 @@ func (_m *ChainScopedConfig) Database() coreconfig.Database { return r0 } -// DefaultChainID provides a mock function with given fields: -func (_m *ChainScopedConfig) DefaultChainID() *big.Int { - ret := _m.Called() - - var r0 *big.Int - if rf, ok := ret.Get(0).(func() *big.Int); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*big.Int) - } - } - - return r0 -} - // EVM provides a mock function with given fields: func (_m *ChainScopedConfig) EVM() config.EVM { ret := _m.Called() diff --git a/core/chains/evm/headtracker/head_tracker_test.go b/core/chains/evm/headtracker/head_tracker_test.go index 12fcb195310..330142b9dc0 100644 --- a/core/chains/evm/headtracker/head_tracker_test.go +++ b/core/chains/evm/headtracker/head_tracker_test.go @@ -428,7 +428,7 @@ func TestHeadTracker_SwitchesToLongestChainWithHeadSamplingEnabled(t *testing.T) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) checker := commonmocks.NewHeadTrackable[*evmtypes.Head, gethCommon.Hash](t) - orm := headtracker.NewORM(db, logger, config.Database(), *config.DefaultChainID()) + orm := headtracker.NewORM(db, logger, config.Database(), *evmtest.MustGetDefaultChainID(t, config.EVMConfigs())) csCfg := evmtest.NewChainScopedConfig(t, config) ht := createHeadTrackerWithChecker(t, ethClient, csCfg.EVM(), csCfg.EVM().HeadTracker(), orm, checker) @@ -779,7 +779,7 @@ func TestHeadTracker_Backfill(t *testing.T) { } ethClient := evmtest.NewEthClientMock(t) - ethClient.On("ConfiguredChainID", mock.Anything).Return(cfg.DefaultChainID(), nil) + ethClient.On("ConfiguredChainID", mock.Anything).Return(evmtest.MustGetDefaultChainID(t, cfg.EVMConfigs()), nil) ht := createHeadTrackerWithNeverSleeper(t, ethClient, cfg, orm) err := ht.Backfill(ctx, &h12, 2) @@ -796,7 +796,7 @@ func TestHeadTracker_Backfill(t *testing.T) { } ethClient := evmtest.NewEthClientMock(t) - ethClient.On("ConfiguredChainID", mock.Anything).Return(cfg.DefaultChainID(), nil) + ethClient.On("ConfiguredChainID", mock.Anything).Return(evmtest.MustGetDefaultChainID(t, cfg.EVMConfigs()), nil) ethClient.On("HeadByHash", mock.Anything, head10.Hash). Return(&head10, nil) @@ -832,7 +832,7 @@ func TestHeadTracker_Backfill(t *testing.T) { } ethClient := evmtest.NewEthClientMock(t) - ethClient.On("ConfiguredChainID", mock.Anything).Return(cfg.DefaultChainID(), nil) + ethClient.On("ConfiguredChainID", mock.Anything).Return(evmtest.MustGetDefaultChainID(t, cfg.EVMConfigs()), nil) ht := createHeadTrackerWithNeverSleeper(t, ethClient, cfg, orm) @@ -865,7 +865,7 @@ func TestHeadTracker_Backfill(t *testing.T) { } ethClient := evmtest.NewEthClientMock(t) - ethClient.On("ConfiguredChainID", mock.Anything).Return(cfg.DefaultChainID(), nil) + ethClient.On("ConfiguredChainID", mock.Anything).Return(evmtest.MustGetDefaultChainID(t, cfg.EVMConfigs()), nil) ht := createHeadTrackerWithNeverSleeper(t, ethClient, cfg, orm) @@ -883,7 +883,7 @@ func TestHeadTracker_Backfill(t *testing.T) { orm := headtracker.NewORM(db, logger, cfg.Database(), cltest.FixtureChainID) ethClient := evmtest.NewEthClientMock(t) - ethClient.On("ConfiguredChainID", mock.Anything).Return(cfg.DefaultChainID(), nil) + ethClient.On("ConfiguredChainID", mock.Anything).Return(evmtest.MustGetDefaultChainID(t, cfg.EVMConfigs()), nil) ethClient.On("HeadByHash", mock.Anything, head0.Hash). Return(&head0, nil) @@ -911,7 +911,7 @@ func TestHeadTracker_Backfill(t *testing.T) { } ethClient := evmtest.NewEthClientMock(t) - ethClient.On("ConfiguredChainID", mock.Anything).Return(cfg.DefaultChainID(), nil) + ethClient.On("ConfiguredChainID", mock.Anything).Return(evmtest.MustGetDefaultChainID(t, cfg.EVMConfigs()), nil) ethClient.On("HeadByHash", mock.Anything, head10.Hash). Return(&head10, nil). Once() @@ -942,7 +942,7 @@ func TestHeadTracker_Backfill(t *testing.T) { } ethClient := evmtest.NewEthClientMock(t) - ethClient.On("ConfiguredChainID", mock.Anything).Return(cfg.DefaultChainID(), nil) + ethClient.On("ConfiguredChainID", mock.Anything).Return(evmtest.MustGetDefaultChainID(t, cfg.EVMConfigs()), nil) ethClient.On("HeadByHash", mock.Anything, head10.Hash). Return(&head10, nil) ethClient.On("HeadByHash", mock.Anything, head8.Hash). @@ -967,7 +967,7 @@ func TestHeadTracker_Backfill(t *testing.T) { logger := logger.TestLogger(t) orm := headtracker.NewORM(db, logger, cfg.Database(), cltest.FixtureChainID) ethClient := evmtest.NewEthClientMock(t) - ethClient.On("ConfiguredChainID", mock.Anything).Return(cfg.DefaultChainID(), nil) + ethClient.On("ConfiguredChainID", mock.Anything).Return(evmtest.MustGetDefaultChainID(t, cfg.EVMConfigs()), nil) ethClient.On("HeadByHash", mock.Anything, h14.Hash).Return(&h14, nil).Once() ethClient.On("HeadByHash", mock.Anything, h13.Hash).Return(&h13, nil).Once() ethClient.On("HeadByHash", mock.Anything, h12.Hash).Return(nil, errors.New("not found")).Once() diff --git a/core/chains/evm/mocks/legacy_chain_container.go b/core/chains/evm/mocks/legacy_chain_container.go index fe906234f16..d8dfa209a08 100644 --- a/core/chains/evm/mocks/legacy_chain_container.go +++ b/core/chains/evm/mocks/legacy_chain_container.go @@ -30,32 +30,6 @@ func (_m *LegacyChainContainer) ChainNodeConfigs() types.Configs { return r0 } -// Default provides a mock function with given fields: -func (_m *LegacyChainContainer) Default() (evm.Chain, error) { - ret := _m.Called() - - var r0 evm.Chain - var r1 error - if rf, ok := ret.Get(0).(func() (evm.Chain, error)); ok { - return rf() - } - if rf, ok := ret.Get(0).(func() evm.Chain); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(evm.Chain) - } - } - - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - // Get provides a mock function with given fields: id func (_m *LegacyChainContainer) Get(id string) (evm.Chain, error) { ret := _m.Called(id) @@ -128,11 +102,6 @@ func (_m *LegacyChainContainer) List(ids ...string) ([]evm.Chain, error) { return r0, r1 } -// SetDefault provides a mock function with given fields: _a0 -func (_m *LegacyChainContainer) SetDefault(_a0 evm.Chain) { - _m.Called(_a0) -} - // Slice provides a mock function with given fields: func (_m *LegacyChainContainer) Slice() []evm.Chain { ret := _m.Called() diff --git a/core/chains/evm/txmgr/evm_tx_store_test.go b/core/chains/evm/txmgr/evm_tx_store_test.go index 0cf2fd83cfd..c4837f81e87 100644 --- a/core/chains/evm/txmgr/evm_tx_store_test.go +++ b/core/chains/evm/txmgr/evm_tx_store_test.go @@ -417,7 +417,7 @@ func TestORM_SetBroadcastBeforeBlockNum(t *testing.T) { t.Run("only updates evm.tx_attempts for the current chain", func(t *testing.T) { require.NoError(t, ethKeyStore.Add(fromAddress, testutils.SimulatedChainID)) require.NoError(t, ethKeyStore.Enable(fromAddress, testutils.SimulatedChainID)) - etxThisChain := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress, cfg.DefaultChainID()) + etxThisChain := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress, cfg.EVM().ChainID()) etxOtherChain := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress, testutils.SimulatedChainID) require.NoError(t, txStore.SetBroadcastBeforeBlockNum(headNum, chainID)) diff --git a/core/cmd/eth_keys_commands_test.go b/core/cmd/eth_keys_commands_test.go index da0a9ce5a66..30e115e9482 100644 --- a/core/cmd/eth_keys_commands_test.go +++ b/core/cmd/eth_keys_commands_test.go @@ -15,6 +15,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/assets" "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/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" @@ -182,28 +183,21 @@ func TestShell_CreateETHKey(t *testing.T) { require.NoError(t, err) require.Equal(t, 1, len(keys)) - // create a key on the default chain - set := flag.NewFlagSet("test", 0) - cltest.FlagSetApplyFromAction(client.CreateETHKey, set, "") - c := cli.NewContext(nil, set, nil) - assert.NoError(t, client.CreateETHKey(c)) - - // create the key on a specific chainID id := big.NewInt(0) - set = flag.NewFlagSet("test", 0) + set := flag.NewFlagSet("test", 0) cltest.FlagSetApplyFromAction(client.CreateETHKey, set, "") - require.NoError(t, set.Set("evmChainID", "")) + require.NoError(t, set.Set("evm-chain-id", testutils.FixtureChainID.String())) - c = cli.NewContext(nil, set, nil) - require.NoError(t, set.Parse([]string{"-evmChainID", id.String()})) + c := cli.NewContext(nil, set, nil) + require.NoError(t, set.Parse([]string{"-evm-chain-id", id.String()})) assert.NoError(t, client.CreateETHKey(c)) - cltest.AssertCount(t, db, "evm.key_states", 3) + cltest.AssertCount(t, db, "evm.key_states", 2) keys, err = app.KeyStore.Eth().GetAll() require.NoError(t, err) - require.Equal(t, 3, len(keys)) + require.Equal(t, 2, len(keys)) } func TestShell_DeleteETHKey(t *testing.T) { @@ -308,9 +302,12 @@ func TestShell_ImportExportETHKey_NoChains(t *testing.T) { // Import the key set = flag.NewFlagSet("test", 0) - set.String("old-password", "../internal/fixtures/incorrect_password.txt", "") - err = set.Parse([]string{keyfilepath}) - require.NoError(t, err) + cltest.FlagSetApplyFromAction(client.ImportETHKey, set, "") + + require.NoError(t, set.Set("evmChainID", testutils.FixtureChainID.String())) + require.NoError(t, set.Set("old-password", "../internal/fixtures/incorrect_password.txt")) + require.NoError(t, set.Parse([]string{keyfilepath})) + c = cli.NewContext(nil, set, nil) err = client.ImportETHKey(c) require.NoError(t, err) @@ -412,6 +409,8 @@ func TestShell_ImportExportETHKey_WithChains(t *testing.T) { set = flag.NewFlagSet("test", 0) cltest.FlagSetApplyFromAction(client.ImportETHKey, set, "") + require.NoError(t, set.Set("evmChainID", testutils.FixtureChainID.String())) + require.NoError(t, set.Set("evmChainID", testutils.FixtureChainID.String())) require.NoError(t, set.Set("old-password", "../internal/fixtures/incorrect_password.txt")) require.NoError(t, set.Parse([]string{keyfilepath})) diff --git a/core/cmd/evm_transaction_commands_test.go b/core/cmd/evm_transaction_commands_test.go index 67e4da03752..f213aefb154 100644 --- a/core/cmd/evm_transaction_commands_test.go +++ b/core/cmd/evm_transaction_commands_test.go @@ -17,6 +17,8 @@ import ( evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "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/evmtest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/store/models" ) @@ -160,6 +162,7 @@ func TestShell_SendEther_From_Txm(t *testing.T) { amount := "100.5" to := "0x342156c8d3bA54Abc67920d35ba1d1e67201aC9C" require.NoError(t, set.Parse([]string{amount, fromAddress.Hex(), to})) + require.NoError(t, set.Set("id", evmtest.MustGetDefaultChainID(t, app.Config.EVMConfigs()).String())) cliapp := cli.NewApp() c := cli.NewContext(cliapp, set, nil) @@ -215,6 +218,7 @@ func TestShell_SendEther_From_Txm_WEI(t *testing.T) { set := flag.NewFlagSet("sendether", 0) cltest.FlagSetApplyFromAction(client.SendEther, set, "") + require.NoError(t, set.Set("id", testutils.FixtureChainID.String())) require.NoError(t, set.Set("wei", "false")) amount := "1000000000000000000" diff --git a/core/cmd/forwarders_commands_test.go b/core/cmd/forwarders_commands_test.go index 7d519917d5a..4381b5ca683 100644 --- a/core/cmd/forwarders_commands_test.go +++ b/core/cmd/forwarders_commands_test.go @@ -77,7 +77,7 @@ func TestShell_TrackEVMForwarder(t *testing.T) { cltest.FlagSetApplyFromAction(client.TrackForwarder, set, "") require.NoError(t, set.Set("address", "0x5431F5F973781809D18643b87B44921b11355d81")) - require.NoError(t, set.Set("evmChainID", id.String())) + require.NoError(t, set.Set("evm-chain-id", id.String())) err := client.TrackForwarder(cli.NewContext(nil, set, nil)) require.NoError(t, err) @@ -122,7 +122,7 @@ func TestShell_TrackEVMForwarder_BadAddress(t *testing.T) { cltest.FlagSetApplyFromAction(client.TrackForwarder, set, "") require.NoError(t, set.Set("address", "0xWrongFormatAddress")) - require.NoError(t, set.Set("evmChainID", id.String())) + require.NoError(t, set.Set("evm-chain-id", id.String())) err := client.TrackForwarder(cli.NewContext(nil, set, nil)) require.Contains(t, err.Error(), "could not decode address: invalid hex string") diff --git a/core/cmd/shell_local.go b/core/cmd/shell_local.go index cd4f170523b..db4d0476fb3 100644 --- a/core/cmd/shell_local.go +++ b/core/cmd/shell_local.go @@ -375,18 +375,6 @@ func (s *Shell) runNode(c *cli.Context) error { legacyEVMChains := app.GetRelayers().LegacyEVMChains() - // By passing in a function we can be lazy trying to look up a default - // chain - if there are no existing keys, there is no need to check for - // a chain ID - DefaultEVMChainIDFunc := func() (*big.Int, error) { - def, err2 := legacyEVMChains.Default() - if err2 != nil { - return nil, errors.Wrap(err2, "cannot get default EVM chain ID; no default EVM chain available") - } - return def.ID(), nil - } - err = keyStore.Migrate(s.Config.Password().VRF(), DefaultEVMChainIDFunc) - if s.Config.EVMEnabled() { if err != nil { return errors.Wrap(err, "error migrating keystore") diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go index 88e323ad5cf..8d2b5f1fabf 100644 --- a/core/cmd/shell_local_test.go +++ b/core/cmd/shell_local_test.go @@ -323,6 +323,7 @@ func TestShell_RebroadcastTransactions_Txm(t *testing.T) { set := flag.NewFlagSet("test", 0) cltest.FlagSetApplyFromAction(client.RebroadcastTransactions, set, "") + require.NoError(t, set.Set("evmChainID", testutils.FixtureChainID.String())) require.NoError(t, set.Set("beginningNonce", strconv.FormatUint(beginningNonce, 10))) require.NoError(t, set.Set("endingNonce", strconv.FormatUint(endingNonce, 10))) require.NoError(t, set.Set("gasPriceWei", "100000000000")) @@ -402,6 +403,7 @@ func TestShell_RebroadcastTransactions_OutsideRange_Txm(t *testing.T) { set := flag.NewFlagSet("test", 0) cltest.FlagSetApplyFromAction(client.RebroadcastTransactions, set, "") + require.NoError(t, set.Set("evmChainID", testutils.FixtureChainID.String())) require.NoError(t, set.Set("beginningNonce", strconv.FormatUint(uint64(beginningNonce), 10))) require.NoError(t, set.Set("endingNonce", strconv.FormatUint(uint64(endingNonce), 10))) require.NoError(t, set.Set("gasPriceWei", gasPrice.String())) @@ -482,6 +484,7 @@ func TestShell_RebroadcastTransactions_AddressCheck(t *testing.T) { set := flag.NewFlagSet("test", 0) cltest.FlagSetApplyFromAction(client.RebroadcastTransactions, set, "") + require.NoError(t, set.Set("evmChainID", testutils.FixtureChainID.String())) require.NoError(t, set.Set("address", fromAddress.Hex())) require.NoError(t, set.Set("password", "../internal/fixtures/correct_password.txt")) c := cli.NewContext(nil, set, nil) diff --git a/core/cmd/shell_remote_test.go b/core/cmd/shell_remote_test.go index 07b0119130f..83686443faa 100644 --- a/core/cmd/shell_remote_test.go +++ b/core/cmd/shell_remote_test.go @@ -125,12 +125,8 @@ func TestShell_ReplayBlocks(t *testing.T) { cltest.FlagSetApplyFromAction(client.ReplayFromBlock, set, "") require.NoError(t, set.Set("block-number", "42")) - - c := cli.NewContext(nil, set, nil) - assert.NoError(t, client.ReplayFromBlock(c)) - require.NoError(t, set.Set("evm-chain-id", "12345678")) - c = cli.NewContext(nil, set, nil) + c := cli.NewContext(nil, set, nil) assert.ErrorContains(t, client.ReplayFromBlock(c), "chain id does not match any local chains") require.NoError(t, set.Set("evm-chain-id", "0")) diff --git a/core/config/app_config.go b/core/config/app_config.go index 1e60644dd0c..20e877e6ec1 100644 --- a/core/config/app_config.go +++ b/core/config/app_config.go @@ -1,7 +1,6 @@ package config import ( - "math/big" "time" "github.com/google/uuid" @@ -21,7 +20,6 @@ type AppConfig interface { RootDir() string ShutdownGracePeriod() time.Duration InsecureFastScrypt() bool - DefaultChainID() *big.Int EVMEnabled() bool EVMRPCEnabled() bool CosmosEnabled() bool diff --git a/core/config/ethereum_config.go b/core/config/ethereum_config.go deleted file mode 100644 index de3ccf28047..00000000000 --- a/core/config/ethereum_config.go +++ /dev/null @@ -1,9 +0,0 @@ -package config - -import ( - "math/big" -) - -type Ethereum interface { - DefaultChainID() *big.Int -} diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index 01228954640..8799ff42776 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -378,9 +378,6 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn } } - if ethClient == nil { - ethClient = evmclient.NewNullClient(cfg.DefaultChainID(), lggr) - } keyStore := keystore.New(db, utils.FastScryptParams, lggr, cfg.Database()) @@ -395,22 +392,28 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn GRPCOpts: loop.GRPCOpts{}, } - chainId := ethClient.ConfiguredChainID() evmOpts := chainlink.EVMFactoryConfig{ RelayerConfig: &evm.RelayerConfig{ AppConfig: cfg, EventBroadcaster: eventBroadcaster, MailMon: mailMon, - GenEthClient: func(_ *big.Int) evmclient.Client { - if chainId.Cmp(cfg.DefaultChainID()) != 0 { - t.Fatalf("expected eth client ChainID %d to match configured DefaultChainID %d", chainId, cfg.DefaultChainID()) - } - return ethClient - }, }, CSAETHKeystore: keyStore, } + if cfg.EVMEnabled() { + if ethClient == nil { + ethClient = evmclient.NewNullClient(evmtest.MustGetDefaultChainID(t, cfg.EVMConfigs()), lggr) + } + chainId := ethClient.ConfiguredChainID() + evmOpts.GenEthClient = func(_ *big.Int) evmclient.Client { + if chainId.Cmp(evmtest.MustGetDefaultChainID(t, cfg.EVMConfigs())) != 0 { + t.Fatalf("expected eth client ChainID %d to match evm config chain id %d", chainId, evmtest.MustGetDefaultChainID(t, cfg.EVMConfigs())) + } + return ethClient + } + } + testCtx := testutils.Context(t) // evm alway enabled for backward compatibility initOps := []chainlink.CoreRelayerChainInitFunc{chainlink.InitEVM(testCtx, relayerFactory, evmOpts)} @@ -1290,7 +1293,7 @@ func MockApplicationEthCalls(t *testing.T, app *TestApplication, ethClient *evmc // Start ethClient.On("Dial", mock.Anything).Return(nil) ethClient.On("SubscribeNewHead", mock.Anything, mock.Anything).Return(sub, nil).Maybe() - ethClient.On("ConfiguredChainID", mock.Anything).Return(app.GetConfig().DefaultChainID(), nil) + ethClient.On("ConfiguredChainID", mock.Anything).Return(evmtest.MustGetDefaultChainID(t, app.GetConfig().EVMConfigs()), nil) ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil).Maybe() ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(nil, nil).Maybe() ethClient.On("Close").Return().Maybe() diff --git a/core/internal/cltest/factories.go b/core/internal/cltest/factories.go index f4b154218a6..36a89971ca6 100644 --- a/core/internal/cltest/factories.go +++ b/core/internal/cltest/factories.go @@ -481,6 +481,14 @@ func MustAddRandomKeyToKeystore(t testing.TB, ethKeyStore keystore.Eth) (ethkey. return k, k.Address } +func MustAddRandomKeyToKeystoreWithChainID(t testing.TB, chainID *big.Int, ethKeyStore keystore.Eth) (ethkey.KeyV2, common.Address) { + t.Helper() + k := MustGenerateRandomKey(t) + MustAddKeyToKeystore(t, k, chainID, ethKeyStore) + + return k, k.Address +} + func MustAddKeyToKeystore(t testing.TB, key ethkey.KeyV2, chainID *big.Int, ethKeyStore keystore.Eth) { t.Helper() ethKeyStore.XXXTestingOnlyAdd(key) @@ -624,7 +632,7 @@ NOW(),NOW(),$1,'{}',false,$2,$3,0,0,0,0,0,0,0,0 func MakeDirectRequestJobSpec(t *testing.T) *job.Job { t.Helper() - drs := &job.DirectRequestSpec{} + drs := &job.DirectRequestSpec{EVMChainID: (*utils.Big)(testutils.FixtureChainID)} spec := &job.Job{ Type: job.DirectRequest, SchemaVersion: 1, @@ -640,7 +648,7 @@ func MustInsertKeeperJob(t *testing.T, db *sqlx.DB, korm keeper.ORM, from ethkey t.Helper() var keeperSpec job.KeeperSpec - err := korm.Q().Get(&keeperSpec, `INSERT INTO keeper_specs (contract_address, from_address, created_at, updated_at) VALUES ($1, $2, NOW(), NOW()) RETURNING *`, contract, from) + err := korm.Q().Get(&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 @@ -668,7 +676,7 @@ func MustInsertKeeperJob(t *testing.T, db *sqlx.DB, korm keeper.ORM, from ethkey } func MustInsertKeeperRegistry(t *testing.T, db *sqlx.DB, korm keeper.ORM, ethKeyStore keystore.Eth, keeperIndex, numKeepers, blockCountPerTurn int32) (keeper.Registry, job.Job) { - key, _ := MustAddRandomKeyToKeystore(t, ethKeyStore) + key, _ := MustAddRandomKeyToKeystoreWithChainID(t, testutils.SimulatedChainID, ethKeyStore) from := key.EIP55Address t.Helper() contractAddress := NewEIP55Address() diff --git a/core/internal/cltest/job_factories.go b/core/internal/cltest/job_factories.go index ef59a9d312c..910ffe79e38 100644 --- a/core/internal/cltest/job_factories.go +++ b/core/internal/cltest/job_factories.go @@ -24,6 +24,7 @@ const ( type = "offchainreporting" schemaVersion = 1 contractAddress = "%s" + evmChainID = "0" p2pPeerID = "%s" p2pBootstrapPeers = ["/dns4/chain.link/tcp/1234/p2p/16Uiu2HAm58SP7UL8zsnpeuwHfytLocaqgnyaYKP8wu7qRdrixLju"] isBootstrapPeer = false diff --git a/core/internal/cltest/mocks.go b/core/internal/cltest/mocks.go index 423791f716c..439ca2b721d 100644 --- a/core/internal/cltest/mocks.go +++ b/core/internal/cltest/mocks.go @@ -429,7 +429,5 @@ func NewLegacyChainsWithMockChain(t testing.TB, ethClient evmclient.Client, cfg func NewLegacyChainsWithChain(ch evm.Chain, cfg evm.AppConfig) evm.LegacyChainContainer { m := map[string]evm.Chain{ch.ID().String(): ch} - legacyChains := evm.NewLegacyChains(m, cfg.EVMConfigs()) - legacyChains.SetDefault(ch) - return legacyChains + return evm.NewLegacyChains(m, cfg.EVMConfigs()) } diff --git a/core/internal/cltest/simulated_backend.go b/core/internal/cltest/simulated_backend.go index 9a3dcfd5184..010478837da 100644 --- a/core/internal/cltest/simulated_backend.go +++ b/core/internal/cltest/simulated_backend.go @@ -12,6 +12,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/pg" @@ -36,8 +37,8 @@ func NewApplicationWithConfigV2OnSimulatedBlockchain( if bid := backend.Blockchain().Config().ChainID; bid.Cmp(testutils.SimulatedChainID) != 0 { t.Fatalf("expected backend chain ID to be %s but it was %s", testutils.SimulatedChainID.String(), bid.String()) } - defID := cfg.DefaultChainID() - require.Zero(t, defID.Cmp(testutils.SimulatedChainID)) + + require.Zero(t, evmtest.MustGetDefaultChainID(t, cfg.EVMConfigs()).Cmp(testutils.SimulatedChainID)) chainID := utils.NewBig(testutils.SimulatedChainID) client := client.NewSimulatedBackendClient(t, backend, testutils.SimulatedChainID) eventBroadcaster := pg.NewEventBroadcaster(cfg.Database().URL(), 0, 0, logger.TestLogger(t), uuid.New()) @@ -61,8 +62,8 @@ func NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain( if bid := backend.Blockchain().Config().ChainID; bid.Cmp(testutils.SimulatedChainID) != 0 { t.Fatalf("expected backend chain ID to be %s but it was %s", testutils.SimulatedChainID.String(), bid.String()) } - defID := cfg.DefaultChainID() - require.Zero(t, defID.Cmp(testutils.SimulatedChainID)) + + require.Zero(t, evmtest.MustGetDefaultChainID(t, cfg.EVMConfigs()).Cmp(testutils.SimulatedChainID)) chainID := utils.NewBig(testutils.SimulatedChainID) client := client.NewSimulatedBackendClient(t, backend, testutils.SimulatedChainID) eventBroadcaster := pg.NewEventBroadcaster(cfg.Database().URL(), 0, 0, logger.TestLogger(t), uuid.New()) diff --git a/core/internal/features/features_test.go b/core/internal/features/features_test.go index 2e2d29c248d..39eee3f7b43 100644 --- a/core/internal/features/features_test.go +++ b/core/internal/features/features_test.go @@ -505,13 +505,14 @@ observationSource = """ data="%s" minConfirmations="2" failOnRevert=false + evmChainID="%s" from="[\\"%s\\"]" ] """ ` // This succeeds for whatever reason revertingData := "0xdeadbeef" - tomlSpec = fmt.Sprintf(tomlSpec, operatorContracts.linkTokenAddress.String(), revertingData, sendingAddr) + tomlSpec = fmt.Sprintf(tomlSpec, operatorContracts.linkTokenAddress.String(), revertingData, testutils.SimulatedChainID.String(), sendingAddr) j := cltest.CreateJobViaWeb(t, app, []byte(cltest.MustJSONMarshal(t, web.CreateJobRequest{TOML: tomlSpec}))) cltest.AwaitJobActive(t, app.JobSpawner(), j.ID, testutils.WaitTimeout(t)) @@ -550,13 +551,14 @@ observationSource = """ data="%s" minConfirmations="2" failOnRevert=true + evmChainID="%s" from="[\\"%s\\"]" ] """ ` // This data is a call to link token's `transfer` function and will revert due to insufficient LINK on the sender address revertingData := "0xa9059cbb000000000000000000000000526485b5abdd8ae9c6a63548e0215a83e7135e6100000000000000000000000000000000000000000000000db069932ea4fe1400" - tomlSpec = fmt.Sprintf(tomlSpec, operatorContracts.linkTokenAddress.String(), revertingData, sendingAddr) + tomlSpec = fmt.Sprintf(tomlSpec, operatorContracts.linkTokenAddress.String(), revertingData, testutils.SimulatedChainID.String(), sendingAddr) j := cltest.CreateJobViaWeb(t, app, []byte(cltest.MustJSONMarshal(t, web.CreateJobRequest{TOML: tomlSpec}))) cltest.AwaitJobActive(t, app.JobSpawner(), j.ID, testutils.WaitTimeout(t)) @@ -587,13 +589,14 @@ observationSource = """ data="%s" minConfirmations="2" failOnRevert=false + evmChainID="%s" from="[\\"%s\\"]" ] """ ` // This data is a call to link token's `transfer` function and will revert due to insufficient LINK on the sender address revertingData := "0xa9059cbb000000000000000000000000526485b5abdd8ae9c6a63548e0215a83e7135e6100000000000000000000000000000000000000000000000db069932ea4fe1400" - tomlSpec = fmt.Sprintf(tomlSpec, operatorContracts.linkTokenAddress.String(), revertingData, sendingAddr) + tomlSpec = fmt.Sprintf(tomlSpec, operatorContracts.linkTokenAddress.String(), revertingData, testutils.SimulatedChainID.String(), sendingAddr) j := cltest.CreateJobViaWeb(t, app, []byte(cltest.MustJSONMarshal(t, web.CreateJobRequest{TOML: tomlSpec}))) cltest.AwaitJobActive(t, app.JobSpawner(), j.ID, testutils.WaitTimeout(t)) @@ -929,8 +932,9 @@ type = "offchainreporting" schemaVersion = 1 name = "boot" contractAddress = "%s" +evmChainID = "%s" isBootstrapPeer = true -`, ocrContractAddress)) +`, ocrContractAddress, testutils.SimulatedChainID.String())) require.NoError(t, err) jb.Name = null.NewString("boot", true) err = appBootstrap.AddJobV2(testutils.Context(t), &jb) @@ -997,6 +1001,7 @@ type = "offchainreporting" schemaVersion = 1 name = "web oracle spec" contractAddress = "%s" +evmChainID = "%s" isBootstrapPeer = false p2pBootstrapPeers = [ "/ip4/127.0.0.1/tcp/%d/p2p/%s" @@ -1022,7 +1027,7 @@ observationSource = """ answer1 [type=median index=0]; """ -`, ocrContractAddress, bootstrapNodePortV1, bootstrapPeerID, keys[i].ID(), transmitters[i], fmt.Sprintf("bridge%d", i), i, slowServers[i].URL, i)) +`, ocrContractAddress, testutils.SimulatedChainID.String(), bootstrapNodePortV1, bootstrapPeerID, keys[i].ID(), transmitters[i], fmt.Sprintf("bridge%d", i), i, slowServers[i].URL, i)) require.NoError(t, err) jb.Name = null.NewString("testocr", true) err = apps[i].AddJobV2(testutils.Context(t), &jb) @@ -1157,9 +1162,10 @@ type = "offchainreporting" schemaVersion = 1 name = "boot" contractAddress = "%s" +evmChainID = "%s" forwardingAllowed = true isBootstrapPeer = true -`, ocrContractAddress)) +`, ocrContractAddress, testutils.SimulatedChainID.String())) require.NoError(t, err) jb.Name = null.NewString("boot", true) err = appBootstrap.AddJobV2(testutils.Context(t), &jb) @@ -1227,6 +1233,7 @@ type = "offchainreporting" schemaVersion = 1 name = "web oracle spec" contractAddress = "%s" +evmChainID = "%s" forwardingAllowed = true isBootstrapPeer = false p2pBootstrapPeers = [ @@ -1253,7 +1260,7 @@ observationSource = """ answer1 [type=median index=0]; """ -`, ocrContractAddress, bootstrapNodePortV1, bootstrapPeerID, keys[i].ID(), transmitters[i], fmt.Sprintf("bridge%d", i), i, slowServers[i].URL, i)) +`, ocrContractAddress, testutils.SimulatedChainID.String(), bootstrapNodePortV1, bootstrapPeerID, keys[i].ID(), transmitters[i], fmt.Sprintf("bridge%d", i), i, slowServers[i].URL, i)) require.NoError(t, err) jb.Name = null.NewString("testocr", true) err = apps[i].AddJobV2(testutils.Context(t), &jb) @@ -1342,7 +1349,7 @@ func TestIntegration_BlockHistoryEstimator(t *testing.T) { Transactions: cltest.LegacyTransactionsFromGasPrices(48_000_000_000, 49_000_000_000, 31_000_000_000), } - evmChainID := utils.NewBig(cfg.DefaultChainID()) + evmChainID := utils.NewBig(evmtest.MustGetDefaultChainID(t, cfg.EVMConfigs())) h40 := evmtypes.Head{Hash: utils.NewHash(), Number: 40, EVMChainID: evmChainID} h41 := evmtypes.Head{Hash: b41.Hash, ParentHash: h40.Hash, Number: 41, EVMChainID: evmChainID} h42 := evmtypes.Head{Hash: b42.Hash, ParentHash: h41.Hash, Number: 42, EVMChainID: evmChainID} @@ -1373,7 +1380,7 @@ func TestIntegration_BlockHistoryEstimator(t *testing.T) { }) ethClient.On("Dial", mock.Anything).Return(nil) - ethClient.On("ConfiguredChainID", mock.Anything).Return(cfg.DefaultChainID(), nil) + ethClient.On("ConfiguredChainID", mock.Anything).Return(*evmtest.MustGetDefaultChainID(t, cfg.EVMConfigs()), nil) ethClient.On("BalanceAt", mock.Anything, mock.Anything, mock.Anything).Maybe().Return(oneETH.ToInt(), nil) // HeadTracker backfill ethClient.On("HeadByHash", mock.Anything, h40.Hash).Return(&h40, nil).Maybe() diff --git a/core/internal/testutils/evmtest/evmtest.go b/core/internal/testutils/evmtest/evmtest.go index 4532e79ac07..62696f75d96 100644 --- a/core/internal/testutils/evmtest/evmtest.go +++ b/core/internal/testutils/evmtest/evmtest.go @@ -45,7 +45,7 @@ func NewChainScopedConfig(t testing.TB, cfg evm.AppConfig) evmconfig.ChainScoped if len(cfg.EVMConfigs()) > 0 { evmCfg = cfg.EVMConfigs()[0] } else { - chainID := utils.NewBigI(0) + var chainID = (*utils.Big)(testutils.FixtureChainID) evmCfg = &evmtoml.EVMConfig{ ChainID: chainID, Chain: evmtoml.Defaults(chainID), @@ -95,7 +95,7 @@ func NewChainRelayExtOpts(t testing.TB, testopts TestChainOpts) evm.ChainRelayEx if testopts.Client != nil { return testopts.Client } - return evmclient.NewNullClient(testopts.GeneralConfig.DefaultChainID(), logger.TestLogger(t)) + return evmclient.NewNullClient(MustGetDefaultChainID(t, testopts.GeneralConfig.EVMConfigs()), logger.TestLogger(t)) } if testopts.LogBroadcaster != nil { opts.GenLogBroadcaster = func(*big.Int) log.Broadcaster { @@ -129,10 +129,21 @@ func NewChainRelayExtOpts(t testing.TB, testopts TestChainOpts) evm.ChainRelayEx return opts } +// Deprecated, this is a replacement function for tests for now removed default evmChainID logic +func MustGetDefaultChainID(t testing.TB, evmCfgs evmtoml.EVMConfigs) *big.Int { + if len(evmCfgs) == 0 { + t.Fatalf("at least one evm chain config must be defined") + } + return evmCfgs[0].ChainID.ToInt() +} + +// Deprecated, this is a replacement function for tests for now removed default chain logic func MustGetDefaultChain(t testing.TB, cc evm.LegacyChainContainer) evm.Chain { - chain, err := cc.Default() - require.NoError(t, err) - return chain + if len(cc.Slice()) == 0 { + t.Fatalf("at least one evm chain container must be defined") + } + + return cc.Slice()[0] } type TestConfigs struct { diff --git a/core/services/blockhashstore/delegate_test.go b/core/services/blockhashstore/delegate_test.go index 78242d519d7..3060f617876 100644 --- a/core/services/blockhashstore/delegate_test.go +++ b/core/services/blockhashstore/delegate_test.go @@ -89,7 +89,7 @@ func TestDelegate_ServicesForSpec(t *testing.T) { defaultWaitBlocks := (int32)(testData.legacyChains.Slice()[0].Config().EVM().FinalityDepth()) t.Run("happy", func(t *testing.T) { - spec := job.Job{BlockhashStoreSpec: &job.BlockhashStoreSpec{WaitBlocks: defaultWaitBlocks}} + spec := job.Job{BlockhashStoreSpec: &job.BlockhashStoreSpec{WaitBlocks: defaultWaitBlocks, EVMChainID: (*utils.Big)(testutils.FixtureChainID)}} services, err := delegate.ServicesForSpec(spec) require.NoError(t, err) @@ -106,6 +106,7 @@ func TestDelegate_ServicesForSpec(t *testing.T) { CoordinatorV1Address: &coordinatorV1, CoordinatorV2Address: &coordinatorV2, CoordinatorV2PlusAddress: &coordinatorV2Plus, + EVMChainID: (*utils.Big)(testutils.FixtureChainID), }} services, err := delegate.ServicesForSpec(spec) @@ -150,6 +151,7 @@ func TestDelegate_StartStop(t *testing.T) { WaitBlocks: defaultWaitBlocks, PollPeriod: time.Second, RunTimeout: testutils.WaitTimeout(t), + EVMChainID: (*utils.Big)(testutils.FixtureChainID), }} services, err := delegate.ServicesForSpec(spec) diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index 498d355d7f7..9d741130502 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -737,6 +737,7 @@ func (app *ChainlinkApplication) RunJobV2( "externalJobID": jb.ExternalJobID, "name": jb.Name.ValueOrZero(), "publicKey": jb.VRFSpec.PublicKey[:], + "evmChainID": jb.VRFSpec.EVMChainID.String(), }, "jobRun": map[string]interface{}{ "meta": meta, diff --git a/core/services/chainlink/config_general.go b/core/services/chainlink/config_general.go index 057b7e554e7..688215c6978 100644 --- a/core/services/chainlink/config_general.go +++ b/core/services/chainlink/config_general.go @@ -3,7 +3,6 @@ package chainlink import ( _ "embed" "fmt" - "math/big" "net/url" "os" "path/filepath" @@ -313,15 +312,6 @@ func (g *generalConfig) EVMRPCEnabled() bool { return false } -func (g *generalConfig) DefaultChainID() *big.Int { - for _, c := range g.c.EVM { - if c.IsEnabled() { - return (*big.Int)(c.ChainID) - } - } - return nil -} - func (g *generalConfig) SolanaEnabled() bool { for _, c := range g.c.Solana { if c.IsEnabled() { diff --git a/core/services/chainlink/config_general_test.go b/core/services/chainlink/config_general_test.go index 8a0f58ecd48..8e95e389ffc 100644 --- a/core/services/chainlink/config_general_test.go +++ b/core/services/chainlink/config_general_test.go @@ -24,7 +24,6 @@ func TestTOMLGeneralConfig_Defaults(t *testing.T) { config, err := GeneralConfigOpts{}.New() require.NoError(t, err) assert.Equal(t, (*url.URL)(nil), config.WebServer().BridgeResponseURL()) - assert.Nil(t, config.DefaultChainID()) assert.False(t, config.EVMRPCEnabled()) assert.False(t, config.EVMEnabled()) assert.False(t, config.CosmosEnabled()) diff --git a/core/services/chainlink/mocks/general_config.go b/core/services/chainlink/mocks/general_config.go index d91901fce6f..416fbd33756 100644 --- a/core/services/chainlink/mocks/general_config.go +++ b/core/services/chainlink/mocks/general_config.go @@ -3,11 +3,8 @@ package mocks import ( - big "math/big" - - config "github.com/smartcontractkit/chainlink/v2/core/config" - cosmos "github.com/smartcontractkit/chainlink/v2/core/chains/cosmos" + config "github.com/smartcontractkit/chainlink/v2/core/config" mock "github.com/stretchr/testify/mock" @@ -147,22 +144,6 @@ func (_m *GeneralConfig) Database() config.Database { return r0 } -// DefaultChainID provides a mock function with given fields: -func (_m *GeneralConfig) DefaultChainID() *big.Int { - ret := _m.Called() - - var r0 *big.Int - if rf, ok := ret.Get(0).(func() *big.Int); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*big.Int) - } - } - - return r0 -} - // EVMConfigs provides a mock function with given fields: func (_m *GeneralConfig) EVMConfigs() toml.EVMConfigs { ret := _m.Called() diff --git a/core/services/chainlink/relayer_chain_interoperators.go b/core/services/chainlink/relayer_chain_interoperators.go index 823d3f88c98..1a0dbadd266 100644 --- a/core/services/chainlink/relayer_chain_interoperators.go +++ b/core/services/chainlink/relayer_chain_interoperators.go @@ -110,23 +110,13 @@ func InitEVM(ctx context.Context, factory RelayerFactory, config EVMFactoryConfi } legacyMap := make(map[string]evm.Chain) - var defaultChain evm.Chain - for id, a := range adapters { // adapter is a service op.srvs = append(op.srvs, a) op.loopRelayers[id] = a legacyMap[id.ChainID] = a.Chain() - if a.Default() { - defaultChain = a.Chain() - } - } op.legacyChains.EVMChains = evm.NewLegacyChains(legacyMap, config.AppConfig.EVMConfigs()) - // TODO BCF-2510 this may not be necessary if EVM is not enabled by default - if defaultChain != nil { - op.legacyChains.EVMChains.SetDefault(defaultChain) - } return nil } } diff --git a/core/services/directrequest/delegate.go b/core/services/directrequest/delegate.go index 4e2ca1e1899..56020f77566 100644 --- a/core/services/directrequest/delegate.go +++ b/core/services/directrequest/delegate.go @@ -339,6 +339,7 @@ func (l *listener) handleOracleRequest(request *operator_wrapper.OperatorOracleR ctx, cancel := runCloserChannel.NewCtx() defer cancel() + evmChainID := lb.EVMChainID() vars := pipeline.NewVarsFrom(map[string]interface{}{ "jobSpec": map[string]interface{}{ "databaseID": l.job.ID, @@ -347,6 +348,7 @@ func (l *listener) handleOracleRequest(request *operator_wrapper.OperatorOracleR "pipelineSpec": &pipeline.Spec{ ForwardingAllowed: l.job.ForwardingAllowed, }, + "evmChainID": evmChainID.String(), }, "jobRun": map[string]interface{}{ "meta": meta, diff --git a/core/services/directrequest/delegate_test.go b/core/services/directrequest/delegate_test.go index 0a4334e8693..ffd78443cc2 100644 --- a/core/services/directrequest/delegate_test.go +++ b/core/services/directrequest/delegate_test.go @@ -57,7 +57,7 @@ func TestDelegate_ServicesForSpec(t *testing.T) { }) t.Run("Spec with DirectRequestSpec", func(t *testing.T) { - spec := job.Job{DirectRequestSpec: &job.DirectRequestSpec{}, PipelineSpec: &pipeline.Spec{}} + spec := job.Job{DirectRequestSpec: &job.DirectRequestSpec{EVMChainID: (*utils.Big)(testutils.FixtureChainID)}, PipelineSpec: &pipeline.Spec{}} services, err := delegate.ServicesForSpec(spec) require.NoError(t, err) assert.Len(t, services, 1) @@ -143,6 +143,7 @@ func TestDelegate_ServicesListenerHandleLog(t *testing.T) { log.On("ReceiptsRoot").Return(common.Hash{}) log.On("TransactionsRoot").Return(common.Hash{}) log.On("StateRoot").Return(common.Hash{}) + log.On("EVMChainID").Return(*big.NewInt(0)) uni.logBroadcaster.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) logOracleRequest := operator_wrapper.OperatorOracleRequest{ @@ -203,6 +204,7 @@ func TestDelegate_ServicesListenerHandleLog(t *testing.T) { }).Maybe() log.On("DecodedLog").Return(&logOracleRequest).Maybe() log.On("String").Return("") + log.On("EVMChainID").Return(*big.NewInt(0)) uni.logBroadcaster.On("MarkConsumed", mock.Anything, mock.Anything).Return(nil).Maybe() err := uni.service.Start(testutils.Context(t)) @@ -295,6 +297,7 @@ func TestDelegate_ServicesListenerHandleLog(t *testing.T) { runLog.On("ReceiptsRoot").Return(common.Hash{}) runLog.On("TransactionsRoot").Return(common.Hash{}) runLog.On("StateRoot").Return(common.Hash{}) + runLog.On("EVMChainID").Return(*big.NewInt(0)) uni.logBroadcaster.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) logOracleRequest := operator_wrapper.OperatorOracleRequest{ @@ -364,6 +367,7 @@ func TestDelegate_ServicesListenerHandleLog(t *testing.T) { log.On("ReceiptsRoot").Return(common.Hash{}) log.On("TransactionsRoot").Return(common.Hash{}) log.On("StateRoot").Return(common.Hash{}) + log.On("EVMChainID").Return(*big.NewInt(0)) uni.logBroadcaster.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) logOracleRequest := operator_wrapper.OperatorOracleRequest{ @@ -456,6 +460,7 @@ func TestDelegate_ServicesListenerHandleLog(t *testing.T) { log.On("ReceiptsRoot").Return(common.Hash{}) log.On("TransactionsRoot").Return(common.Hash{}) log.On("StateRoot").Return(common.Hash{}) + log.On("EVMChainID").Return(*big.NewInt(0)) uni.logBroadcaster.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) logOracleRequest := operator_wrapper.OperatorOracleRequest{ diff --git a/core/services/feeds/service_test.go b/core/services/feeds/service_test.go index c864b8c1922..db6497d11f6 100644 --- a/core/services/feeds/service_test.go +++ b/core/services/feeds/service_test.go @@ -73,6 +73,7 @@ type = "offchainreporting" schemaVersion = 1 name = "example OCR1 spec" externalJobID = "0EEC7E1D-D0D2-476C-A1A8-72DFB6633F46" +evmChainID = 0 contractAddress = "0x613a38AC1659769640aaE063C651F48E0250454C" p2pBootstrapPeers = [ "/dns4/chain.link/tcp/1234/p2p/16Uiu2HAm58SP7UL8zsnpeuwHfytLocaqgnyaYKP8wu7qRdrixLju", diff --git a/core/services/fluxmonitorv2/flux_monitor.go b/core/services/fluxmonitorv2/flux_monitor.go index ad34c84b1d8..34ca121e9a9 100644 --- a/core/services/fluxmonitorv2/flux_monitor.go +++ b/core/services/fluxmonitorv2/flux_monitor.go @@ -735,6 +735,7 @@ func (fm *FluxMonitor) respondToNewRoundLog(log flux_aggregator_wrapper.FluxAggr "databaseID": fm.jobSpec.ID, "externalJobID": fm.jobSpec.ExternalJobID, "name": fm.jobSpec.Name.ValueOrZero(), + "evmChainID": fm.chainID.String(), }, "jobRun": map[string]interface{}{ "meta": metaDataForBridge, @@ -938,6 +939,7 @@ func (fm *FluxMonitor) pollIfEligible(pollReq PollRequestType, deviationChecker "databaseID": fm.jobSpec.ID, "externalJobID": fm.jobSpec.ExternalJobID, "name": fm.jobSpec.Name.ValueOrZero(), + "evmChainID": fm.chainID.String(), }, "jobRun": map[string]interface{}{ "meta": metaDataForBridge, diff --git a/core/services/fluxmonitorv2/flux_monitor_test.go b/core/services/fluxmonitorv2/flux_monitor_test.go index 923658fef09..5a67c2fa1da 100644 --- a/core/services/fluxmonitorv2/flux_monitor_test.go +++ b/core/services/fluxmonitorv2/flux_monitor_test.go @@ -445,6 +445,7 @@ func TestFluxMonitor_PollIfEligible(t *testing.T) { "databaseID": int32(0), "externalJobID": uuid.UUID{}, "name": "", + "evmChainID": testutils.FixtureChainID.String(), }, }, ), mock.Anything). @@ -1882,6 +1883,7 @@ func TestFluxMonitor_DrumbeatTicker(t *testing.T) { "databaseID": int32(0), "externalJobID": uuid.UUID{}, "name": "", + "evmChainID": testutils.FixtureChainID.String(), }, }, ), mock.Anything). diff --git a/core/services/fluxmonitorv2/integrations_test.go b/core/services/fluxmonitorv2/integrations_test.go index e76d859e81b..5b6a94cac58 100644 --- a/core/services/fluxmonitorv2/integrations_test.go +++ b/core/services/fluxmonitorv2/integrations_test.go @@ -644,6 +644,7 @@ type = "fluxmonitor" schemaVersion = 1 name = "example flux monitor spec" contractAddress = "%s" +evmChainID = "%s" threshold = 0.5 absoluteThreshold = 0.0 @@ -661,7 +662,7 @@ ds1 -> ds1_parse """ ` - s = fmt.Sprintf(s, fa.aggregatorContractAddress, pollTimerPeriod, mockServer.URL) + s = fmt.Sprintf(s, fa.aggregatorContractAddress, testutils.SimulatedChainID.String(), pollTimerPeriod, mockServer.URL) // raise flags to disable polling _, err = fa.flagsContract.RaiseFlag(fa.sergey, utils.ZeroAddress) // global kill switch @@ -752,6 +753,7 @@ type = "fluxmonitor" schemaVersion = 1 name = "example flux monitor spec" contractAddress = "%s" +evmChainID = "%s" threshold = 0.5 absoluteThreshold = 0.0 @@ -769,7 +771,7 @@ ds1 -> ds1_parse """ ` - s = fmt.Sprintf(s, fa.aggregatorContractAddress, "1000ms", mockServer.URL) + s = fmt.Sprintf(s, fa.aggregatorContractAddress, testutils.SimulatedChainID.String(), "1000ms", mockServer.URL) // raise flags _, err = fa.flagsContract.RaiseFlag(fa.sergey, utils.ZeroAddress) // global kill switch @@ -862,6 +864,7 @@ type = "fluxmonitor" schemaVersion = 1 name = "example flux monitor spec" contractAddress = "%s" +evmChainID = "%s" threshold = 0.5 absoluteThreshold = 0.01 @@ -879,7 +882,7 @@ ds1 -> ds1_parse """ ` - s := fmt.Sprintf(toml, fa.aggregatorContractAddress, "100ms", mockServer.URL) + s := fmt.Sprintf(toml, fa.aggregatorContractAddress, testutils.SimulatedChainID.String(), "100ms", mockServer.URL) // raise flags _, err = fa.flagsContract.RaiseFlag(fa.sergey, utils.ZeroAddress) // global kill switch @@ -963,6 +966,7 @@ type = "fluxmonitor" schemaVersion = 1 name = "example flux monitor spec" contractAddress = "%s" +evmChainID = "%s" threshold = 0.5 absoluteThreshold = 0.0 @@ -981,7 +985,7 @@ ds1 -> ds1_parse -> ds1_multiply """ ` - s = fmt.Sprintf(s, fa.aggregatorContractAddress, "200ms", mockServer.URL) + s = fmt.Sprintf(s, fa.aggregatorContractAddress, testutils.SimulatedChainID.String(), "200ms", mockServer.URL) requestBody, err := json.Marshal(web.CreateJobRequest{ TOML: string(s), }) diff --git a/core/services/fluxmonitorv2/orm_test.go b/core/services/fluxmonitorv2/orm_test.go index caaea838517..1377737c49b 100644 --- a/core/services/fluxmonitorv2/orm_test.go +++ b/core/services/fluxmonitorv2/orm_test.go @@ -23,6 +23,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" + "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestORM_MostRecentFluxMonitorRoundID(t *testing.T) { @@ -161,6 +162,7 @@ func makeJob(t *testing.T) *job.Job { IdleTimerDisabled: false, CreatedAt: time.Now(), UpdatedAt: time.Now(), + EVMChainID: (*utils.Big)(testutils.FixtureChainID), }, } } diff --git a/core/services/job/helpers_test.go b/core/services/job/helpers_test.go index 21f3a8daa99..167ed5297cc 100644 --- a/core/services/job/helpers_test.go +++ b/core/services/job/helpers_test.go @@ -35,6 +35,7 @@ const ( type = "offchainreporting" schemaVersion = 1 contractAddress = "%s" +evmChainID = "0" p2pBootstrapPeers = [ "/dns4/chain.link/tcp/1234/p2p/16Uiu2HAm58SP7UL8zsnpeuwHfytLocaqgnyaYKP8wu7qRdrixLju", ] @@ -112,6 +113,7 @@ ds1 -> ds1_parse -> ds1_multiply; transmitterAddress = "%s" keyBundleID = "%s" observationTimeout = "10s" + evmChainID = "0" observationSource = """ ds1 [type=http method=GET url="%s" allowunrestrictednetworkaccess="true" %s]; ds1_parse [type=jsonparse path="USD" lax=true]; @@ -122,6 +124,7 @@ ds1 -> ds1_parse; type = "offchainreporting" schemaVersion = 1 contractAddress = "%s" + evmChainID = "0" p2pBootstrapPeers = [] isBootstrapPeer = true ` @@ -129,6 +132,7 @@ ds1 -> ds1_parse; type = "offchainreporting" schemaVersion = 1 contractAddress = "%s" +evmChainID = "0" p2pPeerID = "%s" p2pBootstrapPeers = [ "/dns4/chain.link/tcp/1234/p2p/16Uiu2HAm58SP7UL8zsnpeuwHfytLocaqgnyaYKP8wu7qRdrixLju", diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go index 4fb8b767903..fb34f92a060 100644 --- a/core/services/job/job_orm_test.go +++ b/core/services/job/job_orm_test.go @@ -16,6 +16,7 @@ import ( "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink-relay/pkg/types" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/assets" @@ -604,6 +605,92 @@ func TestORM_CreateJob_OCRBootstrap(t *testing.T) { cltest.AssertCount(t, db, "jobs", 0) } +func TestORM_CreateJob_EVMChainID_Validation(t *testing.T) { + config := configtest.NewGeneralConfig(t, nil) + db := pgtest.NewSqlxDB(t) + keyStore := cltest.NewKeyStore(t, db, config.Database()) + + lggr := logger.TestLogger(t) + pipelineORM := pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns()) + bridgesORM := bridges.NewORM(db, lggr, config.Database()) + + relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) + legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + jobORM := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database()) + + t.Run("evm chain id validation for ocr works", func(t *testing.T) { + jb := job.Job{ + Type: job.OffchainReporting, + OCROracleSpec: &job.OCROracleSpec{}, + } + assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(&jb).Error()) + }) + + t.Run("evm chain id validation for direct request works", func(t *testing.T) { + jb := job.Job{ + Type: job.DirectRequest, + DirectRequestSpec: &job.DirectRequestSpec{}, + } + assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(&jb).Error()) + }) + + t.Run("evm chain id validation for flux monitor works", func(t *testing.T) { + jb := job.Job{ + Type: job.FluxMonitor, + FluxMonitorSpec: &job.FluxMonitorSpec{}, + } + assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(&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(&jb).Error()) + }) + + t.Run("evm chain id validation for vrf works", func(t *testing.T) { + jb := job.Job{ + Type: job.VRF, + VRFSpec: &job.VRFSpec{}, + } + assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(&jb).Error()) + }) + + t.Run("evm chain id validation for block hash store works", func(t *testing.T) { + jb := job.Job{ + Type: job.BlockhashStore, + BlockhashStoreSpec: &job.BlockhashStoreSpec{}, + } + assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(&jb).Error()) + }) + + t.Run("evm chain id validation for block header feeder works", func(t *testing.T) { + jb := job.Job{ + Type: job.BlockHeaderFeeder, + BlockHeaderFeederSpec: &job.BlockHeaderFeederSpec{}, + } + assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(&jb).Error()) + }) + + t.Run("evm chain id validation for legacy gas station server spec works", func(t *testing.T) { + jb := job.Job{ + Type: job.LegacyGasStationServer, + LegacyGasStationServerSpec: &job.LegacyGasStationServerSpec{}, + } + assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(&jb).Error()) + }) + + t.Run("evm chain id validation for legacy gas station sidecar spec works", func(t *testing.T) { + jb := job.Job{ + Type: job.LegacyGasStationSidecar, + LegacyGasStationSidecarSpec: &job.LegacyGasStationSidecarSpec{}, + } + assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(&jb).Error()) + }) +} + func TestORM_CreateJob_OCR_DuplicatedContractAddress(t *testing.T) { customChainID := utils.NewBig(testutils.NewRandomEVMChainID()) @@ -628,16 +715,15 @@ func TestORM_CreateJob_OCR_DuplicatedContractAddress(t *testing.T) { legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) jobORM := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database()) - defaultChainID := config.DefaultChainID() - + // defaultChainID is deprecated + defaultChainID := customChainID _, address := cltest.MustInsertRandomKey(t, keyStore.Eth()) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}, config.Database()) _, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}, config.Database()) - // EVMChainID will default to 0, but we want to override that - // with nil later to represent a job spec with no chain id spec := testspecs.GenerateOCRSpec(testspecs.OCRSpecParams{ Name: "job1", + EVMChainID: testutils.FixtureChainID.String(), DS1BridgeName: bridge.Name.String(), DS2BridgeName: bridge2.Name.String(), TransmitterAddress: address.Hex(), @@ -646,40 +732,30 @@ func TestORM_CreateJob_OCR_DuplicatedContractAddress(t *testing.T) { jb, err := ocr.ValidatedOracleSpecToml(legacyChains, spec.Toml()) require.NoError(t, err) - // 2nd job with no Chain ID - spec2 := testspecs.GenerateOCRSpec(testspecs.OCRSpecParams{ - Name: "job2", - DS1BridgeName: bridge.Name.String(), - DS2BridgeName: bridge2.Name.String(), - TransmitterAddress: address.Hex(), - }) - jb2, err := ocr.ValidatedOracleSpecToml(legacyChains, spec2.Toml()) - require.NoError(t, err) - // Default Chain Job externalJobID := uuid.NullUUID{UUID: uuid.New(), Valid: true} - spec3 := testspecs.GenerateOCRSpec(testspecs.OCRSpecParams{ - Name: "job3", + spec2 := testspecs.GenerateOCRSpec(testspecs.OCRSpecParams{ + Name: "job2", EVMChainID: defaultChainID.String(), DS1BridgeName: bridge.Name.String(), DS2BridgeName: bridge2.Name.String(), TransmitterAddress: address.Hex(), JobID: externalJobID.UUID.String(), }) - jb3, err := ocr.ValidatedOracleSpecToml(legacyChains, spec3.Toml()) + jb2, err := ocr.ValidatedOracleSpecToml(legacyChains, spec2.Toml()) require.NoError(t, err) // Custom Chain Job externalJobID = uuid.NullUUID{UUID: uuid.New(), Valid: true} - spec4 := testspecs.GenerateOCRSpec(testspecs.OCRSpecParams{ - Name: "job4", + spec3 := testspecs.GenerateOCRSpec(testspecs.OCRSpecParams{ + Name: "job3", EVMChainID: customChainID.String(), DS1BridgeName: bridge.Name.String(), DS2BridgeName: bridge2.Name.String(), TransmitterAddress: address.Hex(), JobID: externalJobID.UUID.String(), }) - jb4, err := ocr.ValidatedOracleSpecToml(legacyChains, spec4.Toml()) + jb3, err := ocr.ValidatedOracleSpecToml(legacyChains, spec3.Toml()) require.NoError(t, err) t.Run("with legacy NULL chain id", func(t *testing.T) { @@ -692,33 +768,24 @@ func TestORM_CreateJob_OCR_DuplicatedContractAddress(t *testing.T) { cltest.AssertCount(t, db, "ocr_oracle_specs", 1) cltest.AssertCount(t, db, "jobs", 1) - jb2.OCROracleSpec.EVMChainID = nil - err = jobORM.CreateJob(&jb2) // try adding job for same contract with no chain id in spec + err = jobORM.CreateJob(&jb2) // try adding job for same contract with default chain id require.Error(t, err) - assert.Equal(t, fmt.Sprintf("CreateJobFailed: a job with contract address %s already exists for chain ID %s", jb2.OCROracleSpec.ContractAddress, defaultChainID.String()), err.Error()) + assert.Equal(t, fmt.Sprintf("CreateJobFailed: a job with contract address %s already exists for chain ID %d", jb2.OCROracleSpec.ContractAddress, jb2.OCROracleSpec.EVMChainID.ToInt()), err.Error()) - err = jobORM.CreateJob(&jb3) // try adding job for same contract with default chain id + err = jobORM.CreateJob(&jb3) // Try adding job with custom chain id require.Error(t, err) assert.Equal(t, fmt.Sprintf("CreateJobFailed: a job with contract address %s already exists for chain ID %d", jb3.OCROracleSpec.ContractAddress, jb3.OCROracleSpec.EVMChainID.ToInt()), err.Error()) - - err = jobORM.CreateJob(&jb4) // Try adding job with custom chain id - require.Error(t, err) - assert.Equal(t, fmt.Sprintf("CreateJobFailed: a job with contract address %s already exists for chain ID %d", jb4.OCROracleSpec.ContractAddress, jb4.OCROracleSpec.EVMChainID.ToInt()), err.Error()) }) require.NoError(t, jobORM.DeleteJob(jb.ID)) t.Run("with a set chain id", func(t *testing.T) { - err = jobORM.CreateJob(&jb4) // Add job with custom chain id + err = jobORM.CreateJob(&jb3) // Add job with custom chain id require.NoError(t, err) cltest.AssertCount(t, db, "ocr_oracle_specs", 1) cltest.AssertCount(t, db, "jobs", 1) - jb.OCROracleSpec.EVMChainID = nil - err = jobORM.CreateJob(&jb) - require.NoError(t, err) // should be able to add same contract address on default chain by omitting chain id - externalJobID = uuid.NullUUID{UUID: uuid.New(), Valid: true} spec3.JobID = externalJobID.UUID.String() jb3a, err := ocr.ValidatedOracleSpecToml(legacyChains, spec3.Toml()) @@ -728,11 +795,11 @@ func TestORM_CreateJob_OCR_DuplicatedContractAddress(t *testing.T) { assert.Equal(t, fmt.Sprintf("CreateJobFailed: a job with contract address %s already exists for chain ID %s", jb3.OCROracleSpec.ContractAddress, defaultChainID.String()), err.Error()) externalJobID = uuid.NullUUID{UUID: uuid.New(), Valid: true} - spec4.JobID = externalJobID.UUID.String() - jb5, err := ocr.ValidatedOracleSpecToml(legacyChains, spec4.Toml()) + spec3.JobID = externalJobID.UUID.String() + jb4, err := ocr.ValidatedOracleSpecToml(legacyChains, spec3.Toml()) require.NoError(t, err) - err = jobORM.CreateJob(&jb5) // Try to add duplicate job with custom id + err = jobORM.CreateJob(&jb4) // Try to add duplicate job with custom id require.Error(t, err) assert.Equal(t, fmt.Sprintf("CreateJobFailed: a job with contract address %s already exists for chain ID %s", jb4.OCROracleSpec.ContractAddress, customChainID), err.Error()) }) diff --git a/core/services/job/orm.go b/core/services/job/orm.go index d53452fa3bc..190df2f4966 100644 --- a/core/services/job/orm.go +++ b/core/services/job/orm.go @@ -167,6 +167,9 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { switch jb.Type { case DirectRequest: + if jb.DirectRequestSpec.EVMChainID == nil { + return errors.New("evm chain id must be defined") + } var specID int32 sql := `INSERT INTO direct_request_specs (contract_address, min_incoming_confirmations, requesters, min_contract_payment, evm_chain_id, created_at, updated_at) VALUES (:contract_address, :min_incoming_confirmations, :requesters, :min_contract_payment, :evm_chain_id, now(), now()) @@ -176,6 +179,9 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { } jb.DirectRequestSpecID = &specID case FluxMonitor: + if jb.FluxMonitorSpec.EVMChainID == nil { + return errors.New("evm chain id must be defined") + } var specID int32 sql := `INSERT INTO flux_monitor_specs (contract_address, threshold, absolute_threshold, poll_timer_period, poll_timer_disabled, idle_timer_period, idle_timer_disabled, drumbeat_schedule, drumbeat_random_delay, drumbeat_enabled, min_payment, evm_chain_id, created_at, updated_at) @@ -187,6 +193,10 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { } jb.FluxMonitorSpecID = &specID case OffchainReporting: + if jb.OCROracleSpec.EVMChainID == nil { + return errors.New("evm chain id must be defined") + } + var specID int32 if jb.OCROracleSpec.EncryptedOCRKeyBundleID != nil { _, err := o.keyStore.OCR().Get(jb.OCROracleSpec.EncryptedOCRKeyBundleID.String()) @@ -201,16 +211,7 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { } } - if jb.OCROracleSpec.EVMChainID == nil { - // If unspecified, assume we're creating a job intended to run on default chain id - newChain, err := o.legacyChains.Default() - if err != nil { - return err - } - jb.OCROracleSpec.EVMChainID = utils.NewBig(newChain.ID()) - } newChainID := jb.OCROracleSpec.EVMChainID - existingSpec := new(OCROracleSpec) err := tx.Get(existingSpec, `SELECT * FROM ocr_oracle_specs WHERE contract_address = $1 and (evm_chain_id = $2 or evm_chain_id IS NULL) LIMIT 1;`, jb.OCROracleSpec.ContractAddress, newChainID, @@ -308,6 +309,9 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { } jb.OCR2OracleSpecID = &specID case Keeper: + if jb.KeeperSpec.EVMChainID == nil { + return errors.New("evm chain id must be defined") + } var specID int32 sql := `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()) @@ -326,6 +330,9 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { } jb.CronSpecID = &specID case VRF: + if jb.VRFSpec.EVMChainID == nil { + return errors.New("evm chain id must be defined") + } var specID int32 sql := `INSERT INTO vrf_specs ( coordinator_address, public_key, min_incoming_confirmations, @@ -377,6 +384,9 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { } } case BlockhashStore: + if jb.BlockhashStoreSpec.EVMChainID == nil { + return errors.New("evm chain id must be defined") + } var specID int32 sql := `INSERT INTO blockhash_store_specs (coordinator_v1_address, coordinator_v2_address, coordinator_v2_plus_address, trusted_blockhash_store_address, trusted_blockhash_store_batch_size, wait_blocks, lookback_blocks, blockhash_store_address, poll_period, run_timeout, evm_chain_id, from_addresses, created_at, updated_at) VALUES (:coordinator_v1_address, :coordinator_v2_address, :coordinator_v2_plus_address, :trusted_blockhash_store_address, :trusted_blockhash_store_batch_size, :wait_blocks, :lookback_blocks, :blockhash_store_address, :poll_period, :run_timeout, :evm_chain_id, :from_addresses, NOW(), NOW()) @@ -386,6 +396,9 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { } jb.BlockhashStoreSpecID = &specID case BlockHeaderFeeder: + if jb.BlockHeaderFeederSpec.EVMChainID == nil { + return errors.New("evm chain id must be defined") + } var specID int32 sql := `INSERT INTO block_header_feeder_specs (coordinator_v1_address, coordinator_v2_address, coordinator_v2_plus_address, wait_blocks, lookback_blocks, blockhash_store_address, batch_blockhash_store_address, poll_period, run_timeout, evm_chain_id, from_addresses, get_blockhashes_batch_size, store_blockhashes_batch_size, created_at, updated_at) VALUES (:coordinator_v1_address, :coordinator_v2_address, :coordinator_v2_plus_address, :wait_blocks, :lookback_blocks, :blockhash_store_address, :batch_blockhash_store_address, :poll_period, :run_timeout, :evm_chain_id, :from_addresses, :get_blockhashes_batch_size, :store_blockhashes_batch_size, NOW(), NOW()) @@ -395,6 +408,9 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { } jb.BlockHeaderFeederSpecID = &specID case LegacyGasStationServer: + if jb.LegacyGasStationServerSpec.EVMChainID == nil { + return errors.New("evm chain id must be defined") + } var specID int32 sql := `INSERT INTO legacy_gas_station_server_specs (forwarder_address, evm_chain_id, ccip_chain_selector, from_addresses, created_at, updated_at) VALUES (:forwarder_address, :evm_chain_id, :ccip_chain_selector, :from_addresses, NOW(), NOW()) @@ -404,6 +420,9 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { } jb.LegacyGasStationServerSpecID = &specID case LegacyGasStationSidecar: + if jb.LegacyGasStationSidecarSpec.EVMChainID == nil { + return errors.New("evm chain id must be defined") + } var specID int32 sql := `INSERT INTO legacy_gas_station_sidecar_specs (forwarder_address, off_ramp_address, lookback_blocks, poll_period, run_timeout, evm_chain_id, ccip_chain_selector, created_at, updated_at) VALUES (:forwarder_address, :off_ramp_address, :lookback_blocks, :poll_period, :run_timeout, :evm_chain_id, :ccip_chain_selector, NOW(), NOW()) diff --git a/core/services/job/runner_integration_test.go b/core/services/job/runner_integration_test.go index 72a20a476e3..da670f99a79 100644 --- a/core/services/job/runner_integration_test.go +++ b/core/services/job/runner_integration_test.go @@ -169,6 +169,7 @@ func TestRunner(t *testing.T) { jb := makeOCRJobSpecFromToml(t, fmt.Sprintf(` type = "offchainreporting" schemaVersion = 1 + evmChainID = "0" observationSource = """ ds1 [type=bridge name="%s"]; """ @@ -434,6 +435,7 @@ answer1 [type=median index=0]; schemaVersion = 1 contractAddress = "%s" isBootstrapPeer = false + evmChainID = "0" observationSource = """ ds1 [type=http method=GET url="%s" allowunrestrictednetworkaccess="true" %s]; ds1_parse [type=jsonparse path="USD" lax=true]; @@ -471,6 +473,7 @@ ds1 -> ds1_parse; schemaVersion = 1 contractAddress = "%s" isBootstrapPeer = true + evmChainID = "0" ` s = fmt.Sprintf(s, cltest.NewEIP55Address()) jb, err := ocr.ValidatedOracleSpecToml(legacyChains, s) @@ -509,6 +512,7 @@ ds1 -> ds1_parse; contractAddress = "%s" isBootstrapPeer = false observationTimeout = "15s" + evmChainID = "0" observationSource = """ ds1 [type=http method=GET url="%s" allowunrestrictednetworkaccess="true" %s]; ds1_parse [type=jsonparse path="USD" lax=true]; diff --git a/core/services/keeper/integration_test.go b/core/services/keeper/integration_test.go index cf36628f6a1..39431063bcd 100644 --- a/core/services/keeper/integration_test.go +++ b/core/services/keeper/integration_test.go @@ -405,6 +405,7 @@ func TestKeeperForwarderEthIntegration(t *testing.T) { 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 = (*utils.Big)(testutils.SimulatedChainID) }) scopedConfig := evmtest.NewChainScopedConfig(t, config) korm := keeper.NewORM(db, logger.TestLogger(t), scopedConfig.Database()) @@ -430,6 +431,7 @@ func TestKeeperForwarderEthIntegration(t *testing.T) { KeeperSpec: &job.KeeperSpec{ FromAddress: nodeAddressEIP55, ContractAddress: regAddrEIP55, + EVMChainID: (*utils.Big)(testutils.SimulatedChainID), }, SchemaVersion: 1, ForwardingAllowed: true, diff --git a/core/services/keeper/upkeep_executer_test.go b/core/services/keeper/upkeep_executer_test.go index 70982d7b7ce..702633e1d08 100644 --- a/core/services/keeper/upkeep_executer_test.go +++ b/core/services/keeper/upkeep_executer_test.go @@ -72,7 +72,9 @@ func setup(t *testing.T, estimator gas.EvmFeeEstimator, overrideFn func(c *chain }) db := pgtest.NewSqlxDB(t) keyStore := cltest.NewKeyStore(t, db, cfg.Database()) - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient := evmtest.NewEthClientMock(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) relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{TxManager: txm, DB: db, Client: ethClient, KeyStore: keyStore.Eth(), GeneralConfig: cfg, GasEstimator: estimator}) @@ -81,6 +83,7 @@ func setup(t *testing.T, estimator gas.EvmFeeEstimator, overrideFn func(c *chain ch := evmtest.MustGetDefaultChain(t, legacyChains) orm := keeper.NewORM(db, logger.TestLogger(t), ch.Config().Database()) registry, job := cltest.MustInsertKeeperRegistry(t, db, orm, keyStore.Eth(), 0, 1, 20) + lggr := logger.TestLogger(t) executer := keeper.NewUpkeepExecuter(job, orm, jpv2.Pr, ethClient, ch.HeadBroadcaster(), ch.GasEstimator(), lggr, ch.Config().Keeper(), job.KeeperSpec.FromAddress.Address()) upkeep := cltest.MustInsertUpkeepForRegistry(t, db, ch.Config().Database(), registry) @@ -122,7 +125,10 @@ func Test_UpkeepExecuter_PerformsUpkeep_Happy(t *testing.T) { 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, mockEstimator(t), nil) + db, config, ethMock, executer, registry, upkeep, job, jpv2, txm, _, _, _ := setup(t, mockEstimator(t), + func(c *chainlink.Config, s *chainlink.Secrets) { + c.EVM[0].ChainID = (*utils.Big)(testutils.SimulatedChainID) + }) gasLimit := 5_000_000 + config.Keeper().Registry().PerformGasOverhead() @@ -165,6 +171,7 @@ func Test_UpkeepExecuter_PerformsUpkeep_Happy(t *testing.T) { runTest := func(t *testing.T, eip1559 bool) { db, config, ethMock, executer, registry, upkeep, job, jpv2, txm, _, _, _ := setup(t, mockEstimator(t), func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].GasEstimator.EIP1559DynamicFees = &eip1559 + c.EVM[0].ChainID = (*utils.Big)(testutils.SimulatedChainID) }) gasLimit := 5_000_000 + config.Keeper().Registry().PerformGasOverhead() @@ -215,10 +222,12 @@ func Test_UpkeepExecuter_PerformsUpkeep_Happy(t *testing.T) { }) t.Run("errors if submission key not found", func(t *testing.T) { - _, _, ethMock, executer, registry, _, job, jpv2, _, keyStore, _, _ := setup(t, mockEstimator(t), nil) + _, _, ethMock, executer, registry, _, job, jpv2, _, keyStore, _, _ := setup(t, mockEstimator(t), func(c *chainlink.Config, s *chainlink.Secrets) { + c.EVM[0].ChainID = (*utils.Big)(testutils.SimulatedChainID) + }) // replace expected key with random one - _, err := keyStore.Eth().Create(&cltest.FixtureChainID) + _, err := keyStore.Eth().Create(testutils.SimulatedChainID) require.NoError(t, err) _, err = keyStore.Eth().Delete(job.KeeperSpec.FromAddress.Hex()) require.NoError(t, err) @@ -265,7 +274,9 @@ func Test_UpkeepExecuter_PerformsUpkeep_Happy(t *testing.T) { }) 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, mockEstimator(t), nil) + db, config, ethMock, executer, registry, upkeep, job, jpv2, txm, _, _, _ := setup(t, mockEstimator(t), func(c *chainlink.Config, s *chainlink.Secrets) { + c.EVM[0].ChainID = (*utils.Big)(testutils.SimulatedChainID) + }) etxs := []cltest.Awaiter{ cltest.NewAwaiter(), @@ -304,7 +315,10 @@ func Test_UpkeepExecuter_PerformsUpkeep_Error(t *testing.T) { g := gomega.NewWithT(t) - db, _, ethMock, executer, registry, _, _, _, _, _, _, _ := setup(t, mockEstimator(t), nil) + db, _, ethMock, executer, registry, _, _, _, _, _, _, _ := setup(t, mockEstimator(t), + func(c *chainlink.Config, s *chainlink.Secrets) { + c.EVM[0].ChainID = (*utils.Big)(testutils.SimulatedChainID) + }) var wasCalled atomic.Bool registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_1ABI, registry.ContractAddress.Address()) diff --git a/core/services/keystore/master.go b/core/services/keystore/master.go index 4a8333d8448..ab4c3256c5c 100644 --- a/core/services/keystore/master.go +++ b/core/services/keystore/master.go @@ -51,7 +51,6 @@ type Master interface { StarkNet() StarkNet VRF() VRF Unlock(password string) error - Migrate(vrfPassword string, f DefaultEVMChainIDFunc) error IsEmpty() (bool, error) } @@ -151,93 +150,6 @@ func (ks *master) IsEmpty() (bool, error) { return count == 0, nil } -func (ks *master) Migrate(vrfPssword string, f DefaultEVMChainIDFunc) error { - ks.lock.Lock() - defer ks.lock.Unlock() - if ks.isLocked() { - return ErrLocked - } - csaKeys, err := ks.csa.GetV1KeysAsV2() - if err != nil { - return err - } - for _, csaKey := range csaKeys { - if _, exists := ks.keyRing.CSA[csaKey.ID()]; exists { - continue - } - ks.logger.Debugf("Migrating CSA key %s", csaKey.ID()) - ks.keyRing.CSA[csaKey.ID()] = csaKey - } - ocrKeys, err := ks.ocr.GetV1KeysAsV2() - if err != nil { - return err - } - for _, ocrKey := range ocrKeys { - if _, exists := ks.keyRing.OCR[ocrKey.ID()]; exists { - continue - } - ks.logger.Debugf("Migrating OCR key %s", ocrKey.ID()) - ks.keyRing.OCR[ocrKey.ID()] = ocrKey - } - p2pKeys, err := ks.p2p.GetV1KeysAsV2() - if err != nil { - return err - } - for _, p2pKey := range p2pKeys { - if _, exists := ks.keyRing.P2P[p2pKey.ID()]; exists { - continue - } - ks.logger.Debugf("Migrating P2P key %s", p2pKey.ID()) - ks.keyRing.P2P[p2pKey.ID()] = p2pKey - } - vrfKeys, err := ks.vrf.GetV1KeysAsV2(vrfPssword) - if err != nil { - return err - } - for _, vrfKey := range vrfKeys { - if _, exists := ks.keyRing.VRF[vrfKey.ID()]; exists { - continue - } - ks.logger.Debugf("Migrating VRF key %s", vrfKey.ID()) - ks.keyRing.VRF[vrfKey.ID()] = vrfKey - } - if err = ks.keyManager.save(); err != nil { - return err - } - ethKeys, nonces, fundings, err := ks.eth.getV1KeysAsV2() - if err != nil { - return err - } - if len(ethKeys) > 0 { - chainID, err := f() - if err != nil { - return errors.Wrapf(err, `%d legacy eth keys detected, but no default EVM chain ID was specified - -PLEASE READ THIS ADDITIONAL INFO - -If you are running Chainlink with EVM.Enabled=false and don't care about EVM keys at all, you can run the following SQL to remove any lingering eth keys that may have been autogenerated by an older version of Chainlink, and boot the node again: - -pqsl> TRUNCATE keys; - -WARNING: This will PERMANENTLY AND IRRECOVERABLY delete any legacy eth keys, so please be absolutely sure this is what you want before you run this. Consider taking a database backup first`, len(ethKeys)) - } - for i, ethKey := range ethKeys { - if _, exists := ks.keyRing.Eth[ethKey.ID()]; exists { - continue - } - ks.logger.Debugf("Migrating Eth key %s (and pegging to chain ID %s)", ethKey.ID(), chainID.String()) - // Note that V1 keys that were "funding" will be migrated as "disabled" - if err = ks.eth.addWithNonce(ethKey, chainID, nonces[i], fundings[i]); err != nil { - return err - } - if err = ks.keyManager.save(); err != nil { - return err - } - } - } - return nil -} - type keyManager struct { orm ksORM scryptParams utils.ScryptParams diff --git a/core/services/keystore/mocks/master.go b/core/services/keystore/mocks/master.go index ec55dc21089..e8b4775d662 100644 --- a/core/services/keystore/mocks/master.go +++ b/core/services/keystore/mocks/master.go @@ -116,20 +116,6 @@ func (_m *Master) IsEmpty() (bool, error) { return r0, r1 } -// Migrate provides a mock function with given fields: vrfPassword, f -func (_m *Master) Migrate(vrfPassword string, f keystore.DefaultEVMChainIDFunc) error { - ret := _m.Called(vrfPassword, f) - - var r0 error - if rf, ok := ret.Get(0).(func(string, keystore.DefaultEVMChainIDFunc) error); ok { - r0 = rf(vrfPassword, f) - } else { - r0 = ret.Error(0) - } - - return r0 -} - // OCR provides a mock function with given fields: func (_m *Master) OCR() keystore.OCR { ret := _m.Called() diff --git a/core/services/pipeline/task.estimategas.go b/core/services/pipeline/task.estimategas.go index 967fb7ca034..88c6f6facc3 100644 --- a/core/services/pipeline/task.estimategas.go +++ b/core/services/pipeline/task.estimategas.go @@ -47,12 +47,20 @@ func (t *EstimateGasLimitTask) Type() TaskType { return TaskTypeEstimateGasLimit } +func (t *EstimateGasLimitTask) getEvmChainID() string { + if t.EVMChainID == "" { + t.EVMChainID = "$(jobSpec.evmChainID)" + } + return t.EVMChainID +} + func (t *EstimateGasLimitTask) Run(ctx context.Context, lggr logger.Logger, vars Vars, inputs []Result) (result Result, runInfo RunInfo) { var ( fromAddr AddressParam toAddr AddressParam data BytesParam multiplier DecimalParam + chainID StringParam ) err := multierr.Combine( errors.Wrap(ResolveParam(&fromAddr, From(VarExpr(t.From, vars), utils.ZeroAddress)), "from"), @@ -60,14 +68,15 @@ func (t *EstimateGasLimitTask) Run(ctx context.Context, lggr logger.Logger, vars errors.Wrap(ResolveParam(&data, From(VarExpr(t.Data, vars), NonemptyString(t.Data))), "data"), // Default to 1, i.e. exactly what estimateGas suggests errors.Wrap(ResolveParam(&multiplier, From(VarExpr(t.Multiplier, vars), NonemptyString(t.Multiplier), decimal.New(1, 0))), "multiplier"), + errors.Wrap(ResolveParam(&chainID, From(VarExpr(t.getEvmChainID(), vars), NonemptyString(t.getEvmChainID()), "")), "evmChainID"), ) if err != nil { return Result{Error: err}, runInfo } - chain, err := t.legacyChains.Get(t.EVMChainID) + chain, err := t.legacyChains.Get(string(chainID)) if err != nil { - err = fmt.Errorf("%w: %s: %w", ErrInvalidEVMChainID, t.EVMChainID, err) + err = fmt.Errorf("%w: %s: %w", ErrInvalidEVMChainID, chainID, err) return Result{Error: err}, runInfo } diff --git a/core/services/pipeline/task.eth_call.go b/core/services/pipeline/task.eth_call.go index f3c76d404d4..e877e1e90f4 100644 --- a/core/services/pipeline/task.eth_call.go +++ b/core/services/pipeline/task.eth_call.go @@ -55,6 +55,13 @@ func (t *ETHCallTask) Type() TaskType { return TaskTypeETHCall } +func (t *ETHCallTask) getEvmChainID() string { + if t.EVMChainID == "" { + t.EVMChainID = "$(jobSpec.evmChainID)" + } + return t.EVMChainID +} + func (t *ETHCallTask) Run(ctx context.Context, lggr logger.Logger, vars Vars, inputs []Result) (result Result, runInfo RunInfo) { _, err := CheckInputs(inputs, -1, -1, 0) if err != nil { @@ -80,7 +87,7 @@ func (t *ETHCallTask) Run(ctx context.Context, lggr logger.Logger, vars Vars, in errors.Wrap(ResolveParam(&gasPrice, From(VarExpr(t.GasPrice, vars), t.GasPrice)), "gasPrice"), errors.Wrap(ResolveParam(&gasTipCap, From(VarExpr(t.GasTipCap, vars), t.GasTipCap)), "gasTipCap"), errors.Wrap(ResolveParam(&gasFeeCap, From(VarExpr(t.GasFeeCap, vars), t.GasFeeCap)), "gasFeeCap"), - errors.Wrap(ResolveParam(&chainID, From(VarExpr(t.EVMChainID, vars), NonemptyString(t.EVMChainID), "")), "evmChainID"), + errors.Wrap(ResolveParam(&chainID, From(VarExpr(t.getEvmChainID(), vars), NonemptyString(t.getEvmChainID()), "")), "evmChainID"), errors.Wrap(ResolveParam(&gasUnlimited, From(VarExpr(t.GasUnlimited, vars), NonemptyString(t.GasUnlimited), false)), "gasUnlimited"), ) if err != nil { diff --git a/core/services/pipeline/task.eth_call_test.go b/core/services/pipeline/task.eth_call_test.go index b8896488e2d..77a10681fb4 100644 --- a/core/services/pipeline/task.eth_call_test.go +++ b/core/services/pipeline/task.eth_call_test.go @@ -56,7 +56,7 @@ func TestETHCallTask(t *testing.T) { "0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF", "", "$(foo)", - "", + "0", "", nil, pipeline.NewVarsFrom(map[string]interface{}{ @@ -76,7 +76,7 @@ func TestETHCallTask(t *testing.T) { "0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF", "", "$(foo)", - "", + "0", "$(gasLimit)", nil, pipeline.NewVarsFrom(map[string]interface{}{ @@ -97,7 +97,7 @@ func TestETHCallTask(t *testing.T) { "0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF", "", "$(foo)", - "", + "0", "", &specGasLimit, pipeline.NewVarsFrom(map[string]interface{}{ @@ -117,7 +117,7 @@ func TestETHCallTask(t *testing.T) { "0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF", "0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF", "$(foo)", - "", + "0", "", nil, pipeline.NewVarsFrom(map[string]interface{}{ @@ -138,7 +138,7 @@ func TestETHCallTask(t *testing.T) { "0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF", "0xThisAintGonnaWork", "$(foo)", - "", + "0", "", nil, pipeline.NewVarsFrom(map[string]interface{}{ @@ -153,7 +153,7 @@ func TestETHCallTask(t *testing.T) { "0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbee", "", "$(foo)", - "", + "0", "", nil, pipeline.NewVarsFrom(map[string]interface{}{ @@ -168,7 +168,7 @@ func TestETHCallTask(t *testing.T) { "0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF", "", "$(foo)", - "", + "0", "", nil, pipeline.NewVarsFrom(map[string]interface{}{ @@ -183,7 +183,7 @@ func TestETHCallTask(t *testing.T) { "0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF", "", "$(foo)", - "", + "0", "", nil, pipeline.NewVarsFrom(map[string]interface{}{ @@ -198,7 +198,7 @@ func TestETHCallTask(t *testing.T) { "0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF", "", "$(foo)", - "", + "0", "", nil, pipeline.NewVarsFrom(map[string]interface{}{ diff --git a/core/services/pipeline/task.eth_tx.go b/core/services/pipeline/task.eth_tx.go index 8761732e4f0..d5d29240652 100644 --- a/core/services/pipeline/task.eth_tx.go +++ b/core/services/pipeline/task.eth_tx.go @@ -56,9 +56,16 @@ func (t *ETHTxTask) Type() TaskType { return TaskTypeETHTx } +func (t *ETHTxTask) getEvmChainID() string { + if t.EVMChainID == "" { + t.EVMChainID = "$(jobSpec.evmChainID)" + } + return t.EVMChainID +} + func (t *ETHTxTask) Run(_ context.Context, lggr logger.Logger, vars Vars, inputs []Result) (result Result, runInfo RunInfo) { var chainID StringParam - err := errors.Wrap(ResolveParam(&chainID, From(VarExpr(t.EVMChainID, vars), NonemptyString(t.EVMChainID), "")), "evmChainID") + err := errors.Wrap(ResolveParam(&chainID, From(VarExpr(t.getEvmChainID(), vars), NonemptyString(t.getEvmChainID()), "")), "evmChainID") if err != nil { return Result{Error: err}, runInfo } diff --git a/core/services/pipeline/task.eth_tx_test.go b/core/services/pipeline/task.eth_tx_test.go index d465c16f8fd..a280e6f2720 100644 --- a/core/services/pipeline/task.eth_tx_test.go +++ b/core/services/pipeline/task.eth_tx_test.go @@ -65,7 +65,7 @@ func TestETHTxTask(t *testing.T) { "12345", `{ "jobID": 321, "requestID": "0x5198616554d738d9485d1a7cf53b2f33e09c3bbc8fe9ac0020bd672cd2bc15d2", "requestTxHash": "0xc524fafafcaec40652b1f84fca09c231185437d008d195fccf2f51e64b7062f8" }`, `0`, - "", + "0", `{"CheckerType": "vrf_v2", "VRFCoordinatorAddress": "0x2E396ecbc8223Ebc16EC45136228AE5EDB649943"}`, nil, false, @@ -107,7 +107,7 @@ func TestETHTxTask(t *testing.T) { "$(gasLimit)", `{ "jobID": $(jobID), "requestID": $(requestID), "requestTxHash": $(requestTxHash) }`, `0`, - "", + "0", "", nil, false, @@ -150,7 +150,7 @@ func TestETHTxTask(t *testing.T) { "$(gasLimit)", `{ "jobID": $(jobID), "requestID": $(requestID), "requestTxHash": $(requestTxHash) }`, "$(minConfirmations)", - "", + "0", "", nil, false, @@ -182,7 +182,7 @@ func TestETHTxTask(t *testing.T) { "$(gasLimit)", `$(requestData)`, `0`, - "", + "0", "", nil, false, @@ -227,7 +227,7 @@ func TestETHTxTask(t *testing.T) { "$(gasLimit)", `$(requestData)`, `0`, - "", + "0", "", nil, false, @@ -272,7 +272,7 @@ func TestETHTxTask(t *testing.T) { "12345", `{}`, `0`, - "", + "0", "", nil, false, @@ -302,7 +302,7 @@ func TestETHTxTask(t *testing.T) { "", `{ "jobID": 321, "requestID": "0x5198616554d738d9485d1a7cf53b2f33e09c3bbc8fe9ac0020bd672cd2bc15d2", "requestTxHash": "0xc524fafafcaec40652b1f84fca09c231185437d008d195fccf2f51e64b7062f8" }`, `0`, - "", + "0", "", nil, // spec does not override gas limit false, @@ -336,7 +336,7 @@ func TestETHTxTask(t *testing.T) { "", `{ "jobID": 321, "requestID": "0x5198616554d738d9485d1a7cf53b2f33e09c3bbc8fe9ac0020bd672cd2bc15d2", "requestTxHash": "0xc524fafafcaec40652b1f84fca09c231185437d008d195fccf2f51e64b7062f8" }`, `0`, - "", + "0", "", &specGasLimit, false, @@ -370,7 +370,7 @@ func TestETHTxTask(t *testing.T) { "$(gasLimit)", `$(requestData)`, `0`, - "", + "0", "", nil, false, @@ -400,7 +400,7 @@ func TestETHTxTask(t *testing.T) { "12345", `{ "jobID": 321, "requestID": "0x5198616554d738d9485d1a7cf53b2f33e09c3bbc8fe9ac0020bd672cd2bc15d2", "requestTxHash": "0xc524fafafcaec40652b1f84fca09c231185437d008d195fccf2f51e64b7062f8" }`, `0`, - "", + "0", "", nil, false, @@ -435,7 +435,7 @@ func TestETHTxTask(t *testing.T) { "12345", `{ "jobID": 321, "requestID": "0x5198616554d738d9485d1a7cf53b2f33e09c3bbc8fe9ac0020bd672cd2bc15d2", "requestTxHash": "0xc524fafafcaec40652b1f84fca09c231185437d008d195fccf2f51e64b7062f8", "foo": "bar" }`, `0`, - "", + "0", "", nil, false, @@ -452,7 +452,7 @@ func TestETHTxTask(t *testing.T) { "12345", `{ "jobID": "asdf", "requestID": 123, "requestTxHash": true }`, `0`, - "", + "0", "", nil, false, @@ -469,7 +469,7 @@ func TestETHTxTask(t *testing.T) { "12345", `{ "jobID": 321, "requestID": "0x5198616554d738d9485d1a7cf53b2f33e09c3bbc8fe9ac0020bd672cd2bc15d2", "requestTxHash": "0xc524fafafcaec40652b1f84fca09c231185437d008d195fccf2f51e64b7062f8" }`, `0`, - "", + "0", "", nil, false, @@ -486,7 +486,7 @@ func TestETHTxTask(t *testing.T) { "12345", `{ "jobID": 321, "requestID": "0x5198616554d738d9485d1a7cf53b2f33e09c3bbc8fe9ac0020bd672cd2bc15d2", "requestTxHash": "0xc524fafafcaec40652b1f84fca09c231185437d008d195fccf2f51e64b7062f8" }`, `0`, - "", + "0", "", nil, false, @@ -503,7 +503,7 @@ func TestETHTxTask(t *testing.T) { "12345", `{ "jobID": 321, "requestID": "0x5198616554d738d9485d1a7cf53b2f33e09c3bbc8fe9ac0020bd672cd2bc15d2", "requestTxHash": "0xc524fafafcaec40652b1f84fca09c231185437d008d195fccf2f51e64b7062f8" }`, `3`, - "", + "0", "", nil, false, diff --git a/core/services/relay/evm/loop_impl.go b/core/services/relay/evm/loop_impl.go index 87f7aed1a55..8142721ed16 100644 --- a/core/services/relay/evm/loop_impl.go +++ b/core/services/relay/evm/loop_impl.go @@ -2,6 +2,7 @@ package evm import ( "github.com/smartcontractkit/chainlink-relay/pkg/loop" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm" "github.com/smartcontractkit/chainlink/v2/core/services/relay" ) @@ -10,7 +11,6 @@ import ( type LoopRelayAdapter interface { loop.Relayer Chain() evm.Chain - Default() bool } type LoopRelayer struct { loop.Relayer @@ -30,7 +30,3 @@ func NewLoopRelayServerAdapter(r *Relayer, cs EVMChainRelayerExtender) *LoopRela func (la *LoopRelayer) Chain() evm.Chain { return la.ext.Chain() } - -func (la *LoopRelayer) Default() bool { - return la.ext.Default() -} diff --git a/core/services/relay/evm/mocks/loop_relay_adapter.go b/core/services/relay/evm/mocks/loop_relay_adapter.go index 02064c2ea9f..11150874b9e 100644 --- a/core/services/relay/evm/mocks/loop_relay_adapter.go +++ b/core/services/relay/evm/mocks/loop_relay_adapter.go @@ -47,20 +47,6 @@ func (_m *LoopRelayAdapter) Close() error { return r0 } -// Default provides a mock function with given fields: -func (_m *LoopRelayAdapter) Default() bool { - ret := _m.Called() - - var r0 bool - if rf, ok := ret.Get(0).(func() bool); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(bool) - } - - return r0 -} - // GetChainStatus provides a mock function with given fields: ctx func (_m *LoopRelayAdapter) GetChainStatus(ctx context.Context) (types.ChainStatus, error) { ret := _m.Called(ctx) diff --git a/core/services/relay/evm/relayer_extender.go b/core/services/relay/evm/relayer_extender.go index 9f19ef13143..592c9bacee2 100644 --- a/core/services/relay/evm/relayer_extender.go +++ b/core/services/relay/evm/relayer_extender.go @@ -22,7 +22,6 @@ var ErrNoChains = errors.New("no EVM chains loaded") type EVMChainRelayerExtender interface { relay.RelayerExt Chain() evmchain.Chain - Default() bool } type EVMChainRelayerExtenderSlicer interface { @@ -40,18 +39,10 @@ var _ EVMChainRelayerExtenderSlicer = &ChainRelayerExtenders{} func NewLegacyChainsFromRelayerExtenders(exts EVMChainRelayerExtenderSlicer) *evmchain.LegacyChains { m := make(map[string]evmchain.Chain) - var dflt evmchain.Chain for _, r := range exts.Slice() { m[r.Chain().ID().String()] = r.Chain() - if r.Default() { - dflt = r.Chain() - } - } - l := evmchain.NewLegacyChains(m, exts.AppConfig().EVMConfigs()) - if dflt != nil { - l.SetDefault(dflt) } - return l + return evmchain.NewLegacyChains(m, exts.AppConfig().EVMConfigs()) } func newChainRelayerExtsFromSlice(exts []*ChainRelayerExt, appConfig evm.AppConfig) *ChainRelayerExtenders { @@ -79,8 +70,7 @@ func (c *ChainRelayerExtenders) Len() int { // implements OneChain type ChainRelayerExt struct { - chain evmchain.Chain - isDefault bool + chain evmchain.Chain } var _ EVMChainRelayerExtender = &ChainRelayerExt{} @@ -105,10 +95,6 @@ func (s *ChainRelayerExt) Chain() evmchain.Chain { return s.chain } -func (s *ChainRelayerExt) Default() bool { - return s.isDefault -} - var ErrCorruptEVMChain = errors.New("corrupt evm chain") func (s *ChainRelayerExt) Start(ctx context.Context) error { @@ -151,14 +137,6 @@ func NewChainRelayerExtenders(ctx context.Context, opts evmchain.ChainRelayExten } } - defaultChainID := opts.AppConfig.DefaultChainID() - if defaultChainID == nil && len(enabled) >= 1 { - defaultChainID = enabled[0].ChainID.ToInt() - if len(enabled) > 1 { - opts.Logger.Debugf("Multiple chains present, default chain: %s", defaultChainID.String()) - } - } - var result []*ChainRelayerExt var err error for i := range enabled { @@ -179,8 +157,7 @@ func NewChainRelayerExtenders(ctx context.Context, opts evmchain.ChainRelayExten } s := &ChainRelayerExt{ - chain: chain, - isDefault: (cid == defaultChainID.String()), + chain: chain, } result = append(result, s) } diff --git a/core/services/vrf/delegate_test.go b/core/services/vrf/delegate_test.go index 1541c80a400..ae0accc329e 100644 --- a/core/services/vrf/delegate_test.go +++ b/core/services/vrf/delegate_test.go @@ -155,7 +155,7 @@ func setup(t *testing.T) (vrfUniverse, *v1.Listener, job.Job) { logger.TestLogger(t), cfg.Database(), mailMon) - vs := testspecs.GenerateVRFSpec(testspecs.VRFSpecParams{PublicKey: vuni.vrfkey.PublicKey.String()}) + vs := testspecs.GenerateVRFSpec(testspecs.VRFSpecParams{PublicKey: vuni.vrfkey.PublicKey.String(), EVMChainID: testutils.FixtureChainID.String()}) jb, err := vrfcommon.ValidatedVRFSpec(vs.Toml()) require.NoError(t, err) err = vuni.jrm.CreateJob(&jb) diff --git a/core/services/vrf/v1/integration_test.go b/core/services/vrf/v1/integration_test.go index 42b709e298c..0a57c72ef17 100644 --- a/core/services/vrf/v1/integration_test.go +++ b/core/services/vrf/v1/integration_test.go @@ -30,6 +30,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrftesthelpers" "github.com/smartcontractkit/chainlink/v2/core/store/models" "github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs" + "github.com/smartcontractkit/chainlink/v2/core/utils" ) func TestIntegration_VRF_JPV2(t *testing.T) { @@ -47,6 +48,7 @@ func TestIntegration_VRF_JPV2(t *testing.T) { t.Run(test.name, func(t *testing.T) { config, _ := heavyweight.FullTestDBV2(t, fmt.Sprintf("vrf_jpv2_%v", test.eip1559), func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].GasEstimator.EIP1559DynamicFees = &test.eip1559 + c.EVM[0].ChainID = (*utils.Big)(testutils.SimulatedChainID) }) key1 := cltest.MustGenerateRandomKey(t) key2 := cltest.MustGenerateRandomKey(t) @@ -133,6 +135,7 @@ func TestIntegration_VRF_WithBHS(t *testing.T) { c.Feature.LogPoller = ptr(true) c.EVM[0].FinalityDepth = ptr[uint32](2) c.EVM[0].LogPollInterval = models.MustNewDuration(time.Second) + c.EVM[0].ChainID = (*utils.Big)(testutils.SimulatedChainID) }) key := cltest.MustGenerateRandomKey(t) cu := vrftesthelpers.NewVRFCoordinatorUniverse(t, key) @@ -241,7 +244,9 @@ func createVRFJobRegisterKey(t *testing.T, u vrftesthelpers.CoordinatorUniverse, Name: "vrf-primary", CoordinatorAddress: u.RootContractAddress.String(), MinIncomingConfirmations: incomingConfs, - PublicKey: vrfKey.PublicKey.String()}).Toml() + PublicKey: vrfKey.PublicKey.String(), + EVMChainID: testutils.SimulatedChainID.String(), + }).Toml() jb, err := vrfcommon.ValidatedVRFSpec(s) require.NoError(t, err) assert.Equal(t, expectedOnChainJobID, jb.ExternalIDEncodeStringToTopic().Bytes()) diff --git a/core/services/vrf/v1/listener_v1.go b/core/services/vrf/v1/listener_v1.go index 0fce2ebedde..39aec367b4a 100644 --- a/core/services/vrf/v1/listener_v1.go +++ b/core/services/vrf/v1/listener_v1.go @@ -416,6 +416,7 @@ func (lsn *Listener) ProcessRequest(ctx context.Context, req request) bool { "name": lsn.Job.Name.ValueOrZero(), "publicKey": lsn.Job.VRFSpec.PublicKey[:], "from": lsn.fromAddresses(), + "evmChainID": lsn.Job.VRFSpec.EVMChainID.String(), }, "jobRun": map[string]interface{}{ "logBlockHash": req.req.Raw.BlockHash[:], diff --git a/core/services/vrf/v2/integration_helpers_test.go b/core/services/vrf/v2/integration_helpers_test.go index 43ca198334d..74d7175e08b 100644 --- a/core/services/vrf/v2/integration_helpers_test.go +++ b/core/services/vrf/v2/integration_helpers_test.go @@ -28,6 +28,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" "github.com/smartcontractkit/chainlink/v2/core/services/signatures/secp256k1" @@ -533,6 +534,7 @@ func testSingleConsumerHappyPathBatchFulfillment( })(c, s) c.EVM[0].GasEstimator.LimitDefault = ptr[uint32](5_000_000) c.EVM[0].MinIncomingConfirmations = ptr[uint32](2) + c.EVM[0].ChainID = (*utils.Big)(testutils.SimulatedChainID) }) app := cltest.NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain(t, config, uni.backend, ownerKey, key1) @@ -1616,6 +1618,7 @@ func testMaliciousConsumer( c.EVM[0].GasEstimator.PriceMax = assets.GWei(1) c.EVM[0].GasEstimator.PriceDefault = assets.GWei(1) c.EVM[0].GasEstimator.FeeCapDefault = assets.GWei(1) + c.EVM[0].ChainID = (*utils.Big)(testutils.SimulatedChainID) }) carol := uni.vrfConsumers[0] @@ -1640,6 +1643,7 @@ func testMaliciousConsumer( GasLanePrice: assets.GWei(1), PublicKey: vrfkey.PublicKey.String(), V2: true, + EVMChainID: testutils.SimulatedChainID.String(), }).Toml() jb, err := vrfcommon.ValidatedVRFSpec(s) require.NoError(t, err) @@ -1681,7 +1685,7 @@ func testMaliciousConsumer( }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue()) // The fulfillment tx should succeed - ch, err := app.GetRelayers().LegacyEVMChains().Default() + ch, err := app.GetRelayers().LegacyEVMChains().Get(evmtest.MustGetDefaultChainID(t, config.EVMConfigs()).String()) require.NoError(t, err) r, err := ch.Client().TransactionReceipt(testutils.Context(t), attempts[0].Hash) require.NoError(t, err) diff --git a/core/services/vrf/v2/integration_v2_test.go b/core/services/vrf/v2/integration_v2_test.go index 40622b84594..f4054333808 100644 --- a/core/services/vrf/v2/integration_v2_test.go +++ b/core/services/vrf/v2/integration_v2_test.go @@ -554,6 +554,7 @@ func createVRFJobs( V2: true, GasLanePrice: gasLanePrices[i], VRFOwnerAddress: vrfOwnerString, + EVMChainID: testutils.SimulatedChainID.String(), }).Toml() jb, err := vrfcommon.ValidatedVRFSpec(spec) diff --git a/core/services/vrf/v2/listener_v2.go b/core/services/vrf/v2/listener_v2.go index 461840c6f3c..2eb10f64c89 100644 --- a/core/services/vrf/v2/listener_v2.go +++ b/core/services/vrf/v2/listener_v2.go @@ -1415,6 +1415,7 @@ func (lsn *listenerV2) simulateFulfillment( "name": lsn.job.Name.ValueOrZero(), "publicKey": lsn.job.VRFSpec.PublicKey[:], "maxGasPrice": maxGasPriceWei.ToInt().String(), + "evmChainID": lsn.job.VRFSpec.EVMChainID.String(), }, "jobRun": map[string]interface{}{ "logBlockHash": req.req.Raw().BlockHash.Bytes(), diff --git a/core/testdata/testspecs/v2_specs.go b/core/testdata/testspecs/v2_specs.go index 4c44f3b9c5e..f2669a6fe9d 100644 --- a/core/testdata/testspecs/v2_specs.go +++ b/core/testdata/testspecs/v2_specs.go @@ -44,6 +44,7 @@ type = "directrequest" schemaVersion = 1 name = "%s" contractAddress = "0x613a38AC1659769640aaE063C651F48E0250454C" +evmChainID = "0" observationSource = """ ds1 [type=http method=GET url="http://example.com" allowunrestrictednetworkaccess="true"]; ds1_parse [type=jsonparse path="USD"]; @@ -57,6 +58,7 @@ schemaVersion = 1 name = "example eth request event spec" contractAddress = "0x613a38AC1659769640aaE063C651F48E0250454C" externalJobID = "123e4567-e89b-12d3-a456-426655440004" +evmChainID = "0" observationSource = """ ds1 [type=http method=GET url="http://example.com" allowunrestrictednetworkaccess="true"]; ds1_parse [type=jsonparse path="USD"]; @@ -72,6 +74,7 @@ minContractPaymentLinkJuels = "1000000000000000000000" name = "example eth request event spec with requesters and min contract payment" contractAddress = "0x613a38AC1659769640aaE063C651F48E0250454C" externalJobID = "123e4567-e89b-12d3-a456-426655440014" +evmChainID = 0 observationSource = """ ds1 [type=http method=GET url="http://example.com" allowunrestrictednetworkaccess="true"]; ds1_parse [type=jsonparse path="USD"]; @@ -85,6 +88,7 @@ schemaVersion = 1 name = "example flux monitor spec" contractAddress = "0x3cCad4715152693fE3BC4460591e3D3Fbd071b42" externalJobID = "123e4567-e89b-12d3-a456-426655440005" +evmChainID = 0 threshold = 0.5 absoluteThreshold = 0.0 # optional @@ -251,6 +255,7 @@ type VRFSpecParams struct { FromAddresses []string PublicKey string ObservationSource string + EVMChainID string RequestedConfsDelay int RequestTimeout time.Duration V2 bool @@ -353,14 +358,16 @@ vrf [type=vrfv2 estimate_gas [type=estimategaslimit to="%s" multiplier="1.1" - data="$(vrf.output)"] + data="$(vrf.output)" +] simulate [type=ethcall to="%s" gas="$(estimate_gas)" gasPrice="$(jobSpec.maxGasPrice)" extractRevertReason=true contract="%s" - data="$(vrf.output)"] + data="$(vrf.output)" +] decode_log->vrf->estimate_gas->simulate `, coordinatorAddress, coordinatorAddress, coordinatorAddress) } @@ -378,26 +385,32 @@ generate_proof [type=vrfv2plus estimate_gas [type=estimategaslimit to="%s" multiplier="1.1" - data="$(generate_proof.output)"] + data="$(generate_proof.output)" +] simulate_fulfillment [type=ethcall to="%s" gas="$(estimate_gas)" gasPrice="$(jobSpec.maxGasPrice)" extractRevertReason=true contract="%s" - data="$(generate_proof.output)"] + data="$(generate_proof.output)" +] decode_log->generate_proof->estimate_gas->simulate_fulfillment `, coordinatorAddress, coordinatorAddress, coordinatorAddress) } if params.ObservationSource != "" { observationSource = params.ObservationSource } + if params.EVMChainID == "" { + params.EVMChainID = "0" + } template := ` externalJobID = "%s" type = "vrf" schemaVersion = 1 name = "%s" coordinatorAddress = "%s" +evmChainID = "%s" batchCoordinatorAddress = "%s" batchFulfillmentEnabled = %v batchFulfillmentGasMultiplier = %s @@ -414,7 +427,7 @@ observationSource = """ """ ` toml := fmt.Sprintf(template, - jobID, name, coordinatorAddress, batchCoordinatorAddress, + jobID, name, coordinatorAddress, params.EVMChainID, batchCoordinatorAddress, params.BatchFulfillmentEnabled, strconv.FormatFloat(batchFulfillmentGasMultiplier, 'f', 2, 64), confirmations, params.RequestedConfsDelay, requestTimeout.String(), publicKey, chunkSize, params.BackoffInitialDelay.String(), params.BackoffMaxDelay.String(), gasLanePrice.String(), observationSource) @@ -438,6 +451,7 @@ observationSource = """ MinIncomingConfirmations: confirmations, PublicKey: publicKey, ObservationSource: observationSource, + EVMChainID: params.EVMChainID, RequestedConfsDelay: params.RequestedConfsDelay, RequestTimeout: requestTimeout, ChunkSize: chunkSize, @@ -492,7 +506,7 @@ func GenerateOCRSpec(params OCRSpecParams) OCRSpec { if params.DS2BridgeName != "" { ds2BridgeName = params.DS2BridgeName } - // set to empty so it defaults to the default evm chain id + evmChainID := "0" if params.EVMChainID != "" { evmChainID = params.EVMChainID diff --git a/core/testdata/tomlspecs/direct-request-spec-cbor.toml b/core/testdata/tomlspecs/direct-request-spec-cbor.toml index 2a51cefef7b..500c4973d88 100644 --- a/core/testdata/tomlspecs/direct-request-spec-cbor.toml +++ b/core/testdata/tomlspecs/direct-request-spec-cbor.toml @@ -3,6 +3,7 @@ schemaVersion = 1 name = "example eth request event spec" contractAddress = "0x613a38AC1659769640aaE063C651F48E0250454C" externalJobID = "0EEC7E1D-D0D2-476C-A1A8-72DFB6633F90" +evmChainID = 1337 observationSource = """ decode_log [type=ethabidecodelog abi="OracleRequest(bytes32 indexed specId, address requester, bytes32 requestId, uint256 payment, address callbackAddr, bytes4 callbackFunctionId, uint256 cancelExpiration, uint256 dataVersion, bytes data)" diff --git a/core/testdata/tomlspecs/direct-request-spec.toml b/core/testdata/tomlspecs/direct-request-spec.toml index d3c866102bc..35c0cc9274e 100644 --- a/core/testdata/tomlspecs/direct-request-spec.toml +++ b/core/testdata/tomlspecs/direct-request-spec.toml @@ -1,5 +1,6 @@ type = "directrequest" schemaVersion = 1 +evmChainID = "0" name = "example eth request event spec" contractAddress = "0x613a38AC1659769640aaE063C651F48E0250454C" externalJobID = "0EEC7E1D-D0D2-476C-A1A8-72DFB6633F47" diff --git a/core/testdata/tomlspecs/multiword-response-spec.toml b/core/testdata/tomlspecs/multiword-response-spec.toml index 825f96946b1..31da76b797c 100644 --- a/core/testdata/tomlspecs/multiword-response-spec.toml +++ b/core/testdata/tomlspecs/multiword-response-spec.toml @@ -2,6 +2,7 @@ type = "directrequest" schemaVersion = 1 name = "example eth request event spec" contractAddress = "0x613a38AC1659769640aaE063C651F48E0250454C" +evmChainID = "1337" externalJobID = "0EEC7E1D-D0D2-476C-A1A8-72DFB6633F47" observationSource = """ decode_log [type=ethabidecodelog diff --git a/core/testdata/tomlspecs/ocr-bootstrap-spec.toml b/core/testdata/tomlspecs/ocr-bootstrap-spec.toml index ce12800f634..9df0a861960 100644 --- a/core/testdata/tomlspecs/ocr-bootstrap-spec.toml +++ b/core/testdata/tomlspecs/ocr-bootstrap-spec.toml @@ -2,6 +2,7 @@ type = "offchainreporting" schemaVersion = 1 contractAddress = "0x27548a32b9aD5D64c5945EaE9Da5337bc3169D15" externalJobID = "0EEC7E1D-D0D2-476C-A1A8-72DFB6633F50" +evmChainID = "0" p2pBootstrapPeers = [ "/dns4/chain.link/tcp/1234/p2p/16Uiu2HAm58SP7UL8zsnpeuwHfytLocaqgnyaYKP8wu7qRdrixLju", ] diff --git a/core/web/common.go b/core/web/common.go index 9586fa798e0..ae2158d153b 100644 --- a/core/web/common.go +++ b/core/web/common.go @@ -10,6 +10,7 @@ import ( var ( ErrMissingChainID = errors.New("chain id does not match any local chains") + ErrEmptyChainID = errors.New("chainID is empty") ErrInvalidChainID = errors.New("invalid chain id") ErrMultipleChains = errors.New("more than one chain available, you must specify chain id parameter") ) @@ -33,9 +34,5 @@ func getChain(legacyChains evm.LegacyChainContainer, chainIDstr string) (chain e return nil, ErrMultipleChains } - chain, err = legacyChains.Default() - if err != nil { - return nil, err - } - return chain, nil + return nil, ErrEmptyChainID } diff --git a/core/web/eth_keys_controller_test.go b/core/web/eth_keys_controller_test.go index d656d94e6a8..104e487b207 100644 --- a/core/web/eth_keys_controller_test.go +++ b/core/web/eth_keys_controller_test.go @@ -228,7 +228,12 @@ func TestETHKeysController_CreateSuccess(t *testing.T) { require.NoError(t, app.Start(testutils.Context(t))) - resp, cleanup := client.Post("/v2/keys/evm", nil) + chainURL := url.URL{Path: "/v2/keys/evm"} + query := chainURL.Query() + query.Set("evmChainID", cltest.FixtureChainID.String()) + chainURL.RawQuery = query.Encode() + + resp, cleanup := client.Post(chainURL.String(), nil) defer cleanup() cltest.AssertServerResponse(t, resp, http.StatusOK) diff --git a/core/web/evm_transfer_controller_test.go b/core/web/evm_transfer_controller_test.go index 8ca3102d7a8..70d4c7d5e0b 100644 --- a/core/web/evm_transfer_controller_test.go +++ b/core/web/evm_transfer_controller_test.go @@ -16,8 +16,10 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest2 "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/store/models" + "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" @@ -53,6 +55,7 @@ func TestTransfersController_CreateSuccess_From(t *testing.T) { FromAddress: key.Address, Amount: amount, SkipWaitTxAttempt: true, + EVMChainID: utils.NewBig(evmtest.MustGetDefaultChainID(t, app.Config.EVMConfigs())), } body, err := json.Marshal(&request) @@ -93,6 +96,7 @@ func TestTransfersController_CreateSuccess_From_WEI(t *testing.T) { FromAddress: key.Address, Amount: amount, SkipWaitTxAttempt: true, + EVMChainID: utils.NewBig(evmtest.MustGetDefaultChainID(t, app.Config.EVMConfigs())), } body, err := json.Marshal(&request) @@ -138,6 +142,7 @@ func TestTransfersController_CreateSuccess_From_BalanceMonitorDisabled(t *testin FromAddress: key.Address, Amount: amount, SkipWaitTxAttempt: true, + EVMChainID: utils.NewBig(evmtest.MustGetDefaultChainID(t, app.Config.EVMConfigs())), } body, err := json.Marshal(&request) @@ -167,6 +172,7 @@ func TestTransfersController_TransferZeroAddressError(t *testing.T) { DestinationAddress: common.HexToAddress("0xFA01FA015C8A5332987319823728982379128371"), FromAddress: common.HexToAddress("0x0000000000000000000000000000000000000000"), Amount: amount, + EVMChainID: utils.NewBig(evmtest.MustGetDefaultChainID(t, app.Config.EVMConfigs())), } body, err := json.Marshal(&request) @@ -201,6 +207,7 @@ func TestTransfersController_TransferBalanceToLowError(t *testing.T) { DestinationAddress: common.HexToAddress("0xFA01FA015C8A5332987319823728982379128371"), Amount: amount, AllowHigherAmounts: false, + EVMChainID: utils.NewBig(evmtest.MustGetDefaultChainID(t, app.Config.EVMConfigs())), } body, err := json.Marshal(&request) @@ -238,6 +245,7 @@ func TestTransfersController_TransferBalanceToLowError_ZeroBalance(t *testing.T) DestinationAddress: common.HexToAddress("0xFA01FA015C8A5332987319823728982379128371"), Amount: amount, AllowHigherAmounts: false, + EVMChainID: utils.NewBig(evmtest.MustGetDefaultChainID(t, app.Config.EVMConfigs())), } body, err := json.Marshal(&request) @@ -280,7 +288,7 @@ func TestTransfersController_CreateSuccess_eip1559(t *testing.T) { config := configtest2.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].GasEstimator.EIP1559DynamicFees = ptr(true) c.EVM[0].GasEstimator.Mode = ptr("FixedPrice") - + c.EVM[0].ChainID = (*utils.Big)(testutils.FixtureChainID) // NOTE: FallbackPollInterval is used in this test to quickly create TxAttempts // Testing triggers requires committing transactions and does not work with transactional tests c.Database.Listener.FallbackPollInterval = models.MustNewDuration(time.Second) @@ -300,6 +308,7 @@ func TestTransfersController_CreateSuccess_eip1559(t *testing.T) { FromAddress: key.Address, Amount: amount, WaitAttemptTimeout: &timeout, + EVMChainID: utils.NewBig(evmtest.MustGetDefaultChainID(t, config.EVMConfigs())), } body, err := json.Marshal(&request) diff --git a/core/web/jobs_controller_test.go b/core/web/jobs_controller_test.go index b8b68e402d5..d6d3f459a8a 100644 --- a/core/web/jobs_controller_test.go +++ b/core/web/jobs_controller_test.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "net/http" + "net/url" "strconv" "sync" "testing" @@ -186,7 +187,7 @@ func TestJobController_Create_HappyPath(t *testing.T) { name = "example keeper spec" contractAddress = "0x9E40733cC9df84636505f4e6Db28DCa0dC5D1bba" fromAddress = "0xa8037A20989AFcBC51798de9762b351D63ff462e" - evmChainId = 4 + evmChainID = 0 minIncomingConfigurations = 1 externalJobID = "123e4567-e89b-12d3-a456-426655440002" `, @@ -398,7 +399,12 @@ func TestJobsController_FailToCreate_EmptyJsonAttribute(t *testing.T) { func TestJobsController_Index_HappyPath(t *testing.T) { _, client, ocrJobSpecFromFile, _, ereJobSpecFromFile, _ := setupJobSpecsControllerTestsWithJobs(t) - response, cleanup := client.Get("/v2/jobs") + url := url.URL{Path: "/v2/jobs"} + query := url.Query() + query.Set("evmChainID", cltest.FixtureChainID.String()) + url.RawQuery = query.Encode() + + response, cleanup := client.Get(url.String()) t.Cleanup(cleanup) cltest.AssertServerResponse(t, response, http.StatusOK) @@ -653,7 +659,7 @@ func setupJobSpecsControllerTestsWithJobs(t *testing.T) (*cltest.TestApplication client := app.NewHTTPClient(cltest.APIEmailAdmin) var jb job.Job - ocrspec := testspecs.GenerateOCRSpec(testspecs.OCRSpecParams{DS1BridgeName: bridge.Name.String(), DS2BridgeName: bridge2.Name.String()}) + ocrspec := testspecs.GenerateOCRSpec(testspecs.OCRSpecParams{DS1BridgeName: bridge.Name.String(), DS2BridgeName: bridge2.Name.String(), EVMChainID: testutils.FixtureChainID.String()}) err := toml.Unmarshal([]byte(ocrspec.Toml()), &jb) require.NoError(t, err) var ocrSpec job.OCROracleSpec diff --git a/core/web/pipeline_runs_controller_test.go b/core/web/pipeline_runs_controller_test.go index 4af7a761827..4637b1836bf 100644 --- a/core/web/pipeline_runs_controller_test.go +++ b/core/web/pipeline_runs_controller_test.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "net/http" + "net/url" "strconv" "strings" "testing" @@ -149,7 +150,12 @@ func TestPipelineRunsController_CreateNoBody_HappyPath(t *testing.T) { func TestPipelineRunsController_Index_GlobalHappyPath(t *testing.T) { client, jobID, runIDs := setupPipelineRunsControllerTests(t) - response, cleanup := client.Get("/v2/pipeline/runs") + url := url.URL{Path: "/v2/pipeline/runs"} + query := url.Query() + query.Set("evmChainID", cltest.FixtureChainID.String()) + url.RawQuery = query.Encode() + + response, cleanup := client.Get(url.String()) defer cleanup() cltest.AssertServerResponse(t, response, http.StatusOK) @@ -266,6 +272,7 @@ func setupPipelineRunsControllerTests(t *testing.T) (cltest.HTTPClientCleaner, i schemaVersion = 1 externalJobID = "0EEC7E1D-D0D2-476C-A1A8-72DFB6633F46" contractAddress = "%s" + evmChainID = "0" p2pBootstrapPeers = [ "/dns4/chain.link/tcp/1234/p2p/16Uiu2HAm58SP7UL8zsnpeuwHfytLocaqgnyaYKP8wu7qRdrixLju", ] diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 9b648d92687..aa98a138c86 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Removed - Removed support for sending telemetry to the deprecated Explorer service. All nodes will have to remove `Explorer` related keys from TOML configuration and env vars. +- Removed default evmChainID logic where evmChainID was implicitly injected into the jobspecs based on node EVM chainID toml configuration. All newly created jobs(that have evmChainID field) will have to explicitly define evmChainID in the jobspec. +- Removed keyset migration that migrated v1 keys to v2 keys. All keys should've been migrated by now, and we don't permit creation of new v1 keys anymore All nodes will have to remove the following secret configurations: * `Explorer.AccessKey` diff --git a/integration-tests/actions/keeper_helpers.go b/integration-tests/actions/keeper_helpers.go index 98c9a51e1c8..dfe2acbbed3 100644 --- a/integration-tests/actions/keeper_helpers.go +++ b/integration-tests/actions/keeper_helpers.go @@ -27,6 +27,7 @@ func CreateKeeperJobs( chainlinkNodes []*client.ChainlinkK8sClient, keeperRegistry contracts.KeeperRegistry, ocrConfig contracts.OCRv2Config, + evmChainID string, ) { // Send keeper jobs to registry and chainlink nodes primaryNode := chainlinkNodes[0] @@ -49,6 +50,7 @@ func CreateKeeperJobs( Name: fmt.Sprintf("keeper-test-%s", keeperRegistry.Address()), ContractAddress: keeperRegistry.Address(), FromAddress: chainlinkNodeAddress, + EVMChainID: evmChainID, MinIncomingConfirmations: 1, }) require.NoError(t, err, "Creating KeeperV2 Job shouldn't fail") @@ -61,6 +63,7 @@ func CreateKeeperJobsWithKeyIndex( keeperRegistry contracts.KeeperRegistry, keyIndex int, ocrConfig contracts.OCRv2Config, + evmChainID string, ) { // Send keeper jobs to registry and chainlink nodes primaryNode := chainlinkNodes[0] @@ -83,6 +86,7 @@ func CreateKeeperJobsWithKeyIndex( Name: fmt.Sprintf("keeper-test-%s", keeperRegistry.Address()), ContractAddress: keeperRegistry.Address(), FromAddress: chainlinkNodeAddress[keyIndex], + EVMChainID: evmChainID, MinIncomingConfirmations: 1, }) require.NoError(t, err, "Creating KeeperV2 Job shouldn't fail") diff --git a/integration-tests/actions/keeper_helpers_local.go b/integration-tests/actions/keeper_helpers_local.go index 6fc7ef43dbe..ade1ab7f1a3 100644 --- a/integration-tests/actions/keeper_helpers_local.go +++ b/integration-tests/actions/keeper_helpers_local.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/rs/zerolog/log" + "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" ) @@ -12,6 +13,7 @@ func CreateKeeperJobsLocal( chainlinkNodes []*client.ChainlinkClient, keeperRegistry contracts.KeeperRegistry, ocrConfig contracts.OCRv2Config, + evmChainID string, ) ([]*client.Job, error) { // Send keeper jobs to registry and chainlink nodes primaryNode := chainlinkNodes[0] @@ -46,6 +48,7 @@ func CreateKeeperJobsLocal( Name: fmt.Sprintf("keeper-test-%s", keeperRegistry.Address()), ContractAddress: keeperRegistry.Address(), FromAddress: chainlinkNodeAddress, + EVMChainID: evmChainID, MinIncomingConfirmations: 1, }) if err != nil { diff --git a/integration-tests/actions/ocr_helpers.go b/integration-tests/actions/ocr_helpers.go index bff96c73042..edef393027a 100644 --- a/integration-tests/actions/ocr_helpers.go +++ b/integration-tests/actions/ocr_helpers.go @@ -186,6 +186,7 @@ func CreateOCRJobs( workerNodes []*client.ChainlinkK8sClient, mockValue int, mockserver *ctfClient.MockserverClient, + evmChainID string, ) error { for _, ocrInstance := range ocrInstances { bootstrapP2PIds, err := bootstrapNode.MustReadP2PKeys() @@ -196,6 +197,7 @@ func CreateOCRJobs( bootstrapSpec := &client.OCRBootstrapJobSpec{ Name: fmt.Sprintf("bootstrap-%s", uuid.New().String()), ContractAddress: ocrInstance.Address(), + EVMChainID: evmChainID, P2PPeerID: bootstrapP2PId, IsBootstrapPeer: true, } @@ -240,6 +242,7 @@ func CreateOCRJobs( bootstrapPeers := []*client.ChainlinkClient{bootstrapNode.ChainlinkClient} ocrSpec := &client.OCRTaskJobSpec{ ContractAddress: ocrInstance.Address(), + EVMChainID: evmChainID, P2PPeerID: nodeP2PId, P2PBootstrapPeers: bootstrapPeers, KeyBundleID: nodeOCRKeyId, @@ -264,6 +267,7 @@ func CreateOCRJobsWithForwarder( workerNodes []*client.ChainlinkK8sClient, mockValue int, mockserver *ctfClient.MockserverClient, + evmChainID string, ) { for _, ocrInstance := range ocrInstances { bootstrapP2PIds, err := bootstrapNode.MustReadP2PKeys() @@ -272,6 +276,7 @@ func CreateOCRJobsWithForwarder( bootstrapSpec := &client.OCRBootstrapJobSpec{ Name: fmt.Sprintf("bootstrap-%s", uuid.New().String()), ContractAddress: ocrInstance.Address(), + EVMChainID: evmChainID, P2PPeerID: bootstrapP2PId, IsBootstrapPeer: true, } @@ -302,6 +307,7 @@ func CreateOCRJobsWithForwarder( bootstrapPeers := []*client.ChainlinkClient{bootstrapNode.ChainlinkClient} ocrSpec := &client.OCRTaskJobSpec{ ContractAddress: ocrInstance.Address(), + EVMChainID: evmChainID, P2PPeerID: nodeP2PId, P2PBootstrapPeers: bootstrapPeers, KeyBundleID: nodeOCRKeyId, diff --git a/integration-tests/actions/ocr_helpers_local.go b/integration-tests/actions/ocr_helpers_local.go index 13fc01dcea6..33d6498b9e5 100644 --- a/integration-tests/actions/ocr_helpers_local.go +++ b/integration-tests/actions/ocr_helpers_local.go @@ -2,6 +2,9 @@ package actions import ( "fmt" + "math/big" + "strings" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" @@ -9,11 +12,10 @@ import ( "github.com/rs/zerolog/log" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" + "golang.org/x/sync/errgroup" + "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" - "golang.org/x/sync/errgroup" - "math/big" - "strings" ) /* @@ -140,6 +142,7 @@ func CreateOCRJobsLocal( workerNodes []*client.ChainlinkClient, mockValue int, mockserver *ctfClient.MockserverClient, + evmChainID string, ) error { for _, ocrInstance := range ocrInstances { bootstrapP2PIds, err := bootstrapNode.MustReadP2PKeys() @@ -150,6 +153,7 @@ func CreateOCRJobsLocal( bootstrapSpec := &client.OCRBootstrapJobSpec{ Name: fmt.Sprintf("bootstrap-%s", uuid.New().String()), ContractAddress: ocrInstance.Address(), + EVMChainID: evmChainID, P2PPeerID: bootstrapP2PId, IsBootstrapPeer: true, } @@ -194,6 +198,7 @@ func CreateOCRJobsLocal( bootstrapPeers := []*client.ChainlinkClient{bootstrapNode} ocrSpec := &client.OCRTaskJobSpec{ ContractAddress: ocrInstance.Address(), + EVMChainID: evmChainID, P2PPeerID: nodeP2PId, P2PBootstrapPeers: bootstrapPeers, KeyBundleID: nodeOCRKeyId, @@ -353,6 +358,7 @@ func CreateOCRJobsWithForwarderLocal( workerNodes []*client.ChainlinkClient, mockValue int, mockserver *ctfClient.MockserverClient, + evmChainID string, ) error { for _, ocrInstance := range ocrInstances { bootstrapP2PIds, err := bootstrapNode.MustReadP2PKeys() @@ -363,6 +369,7 @@ func CreateOCRJobsWithForwarderLocal( bootstrapSpec := &client.OCRBootstrapJobSpec{ Name: fmt.Sprintf("bootstrap-%s", uuid.New().String()), ContractAddress: ocrInstance.Address(), + EVMChainID: evmChainID, P2PPeerID: bootstrapP2PId, IsBootstrapPeer: true, } @@ -407,6 +414,7 @@ func CreateOCRJobsWithForwarderLocal( bootstrapPeers := []*client.ChainlinkClient{bootstrapNode} ocrSpec := &client.OCRTaskJobSpec{ ContractAddress: ocrInstance.Address(), + EVMChainID: evmChainID, P2PPeerID: nodeP2PId, P2PBootstrapPeers: bootstrapPeers, KeyBundleID: nodeOCRKeyId, diff --git a/integration-tests/chaos/ocr_chaos_test.go b/integration-tests/chaos/ocr_chaos_test.go index 1e5b8451454..d765cafb9e6 100644 --- a/integration-tests/chaos/ocr_chaos_test.go +++ b/integration-tests/chaos/ocr_chaos_test.go @@ -185,7 +185,7 @@ func TestOCRChaos(t *testing.T) { require.NoError(t, err) err = chainClient.WaitForEvents() require.NoError(t, err) - err = actions.CreateOCRJobs(ocrInstances, bootstrapNode, workerNodes, 5, ms) + err = actions.CreateOCRJobs(ocrInstances, bootstrapNode, workerNodes, 5, ms, chainClient.GetChainID().String()) require.NoError(t, err) chaosApplied := false diff --git a/integration-tests/client/chainlink_models.go b/integration-tests/client/chainlink_models.go index d1b2f8eae9d..6013e13e0fa 100644 --- a/integration-tests/client/chainlink_models.go +++ b/integration-tests/client/chainlink_models.go @@ -762,6 +762,7 @@ func (d *DirectRequestTxPipelineSpec) String() (string, error) { type DirectRequestJobSpec struct { Name string `toml:"name"` ContractAddress string `toml:"contractAddress"` + EVMChainID string `toml:"evmChainID"` ExternalJobID string `toml:"externalJobID"` MinIncomingConfirmations string `toml:"minIncomingConfirmations"` ObservationSource string `toml:"observationSource"` // List of commands for the Chainlink node @@ -777,6 +778,7 @@ schemaVersion = 1 name = "{{.Name}}" maxTaskDuration = "99999s" contractAddress = "{{.ContractAddress}}" +evmChainID = "{{.EVMChainID}}" externalJobID = "{{.ExternalJobID}}" minIncomingConfirmations = {{.MinIncomingConfirmations}} observationSource = """ @@ -789,6 +791,7 @@ observationSource = """ type FluxMonitorJobSpec struct { Name string `toml:"name"` ContractAddress string `toml:"contractAddress"` // Address of the Flux Monitor script + EVMChainID string `toml:"evmChainID"` // Not optional Precision int `toml:"precision"` // Optional Threshold float32 `toml:"threshold"` // Optional AbsoluteThreshold float32 `toml:"absoluteThreshold"` // Optional @@ -809,6 +812,7 @@ func (f *FluxMonitorJobSpec) String() (string, error) { schemaVersion = 1 name = "{{.Name}}" contractAddress = "{{.ContractAddress}}" +evmChainID = "{{.EVMChainID}}" precision ={{if not .Precision}} 0 {{else}} {{.Precision}} {{end}} threshold ={{if not .Threshold}} 0.5 {{else}} {{.Threshold}} {{end}} absoluteThreshold ={{if not .AbsoluteThreshold}} 0.1 {{else}} {{.AbsoluteThreshold}} {{end}} @@ -832,6 +836,7 @@ 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"` } @@ -846,6 +851,7 @@ schemaVersion = 1 name = "{{.Name}}" contractAddress = "{{.ContractAddress}}" fromAddress = "{{.FromAddress}}" +evmChainID = "{{.EVMChainID}}" minIncomingConfirmations = {{.MinIncomingConfirmations}} ` return MarshallTemplate(k, "Keeper Job", keeperTemplateString) @@ -860,8 +866,9 @@ type OCRBootstrapJobSpec struct { TrackerPollInterval time.Duration `toml:"contractConfigTrackerPollInterval"` // Optional TrackerSubscribeInterval time.Duration `toml:"contractConfigTrackerSubscribeInterval"` // Optional ContractAddress string `toml:"contractAddress"` // Address of the OCR contract - IsBootstrapPeer bool `toml:"isBootstrapPeer"` // Typically true - P2PPeerID string `toml:"p2pPeerID"` // This node's P2P ID + EVMChainID string `toml:"evmChainID"` + IsBootstrapPeer bool `toml:"isBootstrapPeer"` // Typically true + P2PPeerID string `toml:"p2pPeerID"` // This node's P2P ID } // Type returns the type of the job @@ -876,6 +883,7 @@ contractConfigConfirmations ={{if not .ContractConfirmations}} 3 {{el contractConfigTrackerPollInterval ={{if not .TrackerPollInterval}} "1m" {{else}} {{.TrackerPollInterval}} {{end}} contractConfigTrackerSubscribeInterval ={{if not .TrackerSubscribeInterval}} "2m" {{else}} {{.TrackerSubscribeInterval}} {{end}} contractAddress = "{{.ContractAddress}}" +evmChainID = "{{.EVMChainID}}" p2pBootstrapPeers = [] isBootstrapPeer = {{.IsBootstrapPeer}} p2pPeerID = "{{.P2PPeerID}}"` @@ -892,13 +900,14 @@ type OCRTaskJobSpec struct { TrackerSubscribeInterval time.Duration `toml:"contractConfigTrackerSubscribeInterval"` // Optional ForwardingAllowed bool `toml:"forwardingAllowed"` // Optional, by default false ContractAddress string `toml:"contractAddress"` // Address of the OCR contract - P2PBootstrapPeers []*ChainlinkClient `toml:"p2pBootstrapPeers"` // P2P ID of the bootstrap node - IsBootstrapPeer bool `toml:"isBootstrapPeer"` // Typically false - P2PPeerID string `toml:"p2pPeerID"` // This node's P2P ID - KeyBundleID string `toml:"keyBundleID"` // ID of this node's OCR key bundle - MonitoringEndpoint string `toml:"monitoringEndpoint"` // Typically "chain.link:4321" - TransmitterAddress string `toml:"transmitterAddress"` // ETH address this node will use to transmit its answer - ObservationSource string `toml:"observationSource"` // List of commands for the Chainlink node + EVMChainID string `toml:"evmChainID"` + P2PBootstrapPeers []*ChainlinkClient `toml:"p2pBootstrapPeers"` // P2P ID of the bootstrap node + IsBootstrapPeer bool `toml:"isBootstrapPeer"` // Typically false + P2PPeerID string `toml:"p2pPeerID"` // This node's P2P ID + KeyBundleID string `toml:"keyBundleID"` // ID of this node's OCR key bundle + MonitoringEndpoint string `toml:"monitoringEndpoint"` // Typically "chain.link:4321" + TransmitterAddress string `toml:"transmitterAddress"` // ETH address this node will use to transmit its answer + ObservationSource string `toml:"observationSource"` // List of commands for the Chainlink node } // P2PData holds the remote ip and the peer id and port @@ -939,6 +948,7 @@ func (o *OCRTaskJobSpec) String() (string, error) { TrackerPollInterval time.Duration TrackerSubscribeInterval time.Duration ContractAddress string + EVMChainID string P2PBootstrapPeers []P2PData IsBootstrapPeer bool P2PPeerID string @@ -954,6 +964,7 @@ func (o *OCRTaskJobSpec) String() (string, error) { TrackerPollInterval: o.TrackerPollInterval, TrackerSubscribeInterval: o.TrackerSubscribeInterval, ContractAddress: o.ContractAddress, + EVMChainID: o.EVMChainID, P2PBootstrapPeers: peers, IsBootstrapPeer: o.IsBootstrapPeer, P2PPeerID: o.P2PPeerID, @@ -971,6 +982,7 @@ contractConfigConfirmations ={{if not .ContractConfirmations}} 3 {{el contractConfigTrackerPollInterval ={{if not .TrackerPollInterval}} "1m" {{else}} {{.TrackerPollInterval}} {{end}} contractConfigTrackerSubscribeInterval ={{if not .TrackerSubscribeInterval}} "2m" {{else}} {{.TrackerSubscribeInterval}} {{end}} contractAddress = "{{.ContractAddress}}" +evmChainID = "{{.EVMChainID}}" {{if .P2PBootstrapPeers}} p2pBootstrapPeers = [ {{range $peer := .P2PBootstrapPeers}} @@ -1186,6 +1198,7 @@ type VRFJobSpec struct { Name string `toml:"name"` CoordinatorAddress string `toml:"coordinatorAddress"` // Address of the VRF CoordinatorV2 contract PublicKey string `toml:"publicKey"` // Public key of the proving key + EVMChainID string `toml:"evmChainID"` ExternalJobID string `toml:"externalJobID"` ObservationSource string `toml:"observationSource"` // List of commands for the Chainlink node MinIncomingConfirmations int `toml:"minIncomingConfirmations"` @@ -1203,6 +1216,7 @@ name = "{{.Name}}" coordinatorAddress = "{{.CoordinatorAddress}}" minIncomingConfirmations = {{.MinIncomingConfirmations}} publicKey = "{{.PublicKey}}" +evmChainID = "{{.EVMChainID}}" externalJobID = "{{.ExternalJobID}}" observationSource = """ {{.ObservationSource}} diff --git a/integration-tests/performance/directrequest_test.go b/integration-tests/performance/directrequest_test.go index dca84ab09c3..a24493a6781 100644 --- a/integration-tests/performance/directrequest_test.go +++ b/integration-tests/performance/directrequest_test.go @@ -83,6 +83,7 @@ func TestDirectRequestPerformance(t *testing.T) { Name: "direct_request", MinIncomingConfirmations: "1", ContractAddress: oracle.Address(), + EVMChainID: chainClient.GetChainID().String(), ExternalJobID: jobUUID.String(), ObservationSource: ost, }) diff --git a/integration-tests/performance/flux_test.go b/integration-tests/performance/flux_test.go index bc914c329b9..47b2b22e1ad 100644 --- a/integration-tests/performance/flux_test.go +++ b/integration-tests/performance/flux_test.go @@ -100,6 +100,7 @@ func TestFluxPerformance(t *testing.T) { fluxSpec := &client.FluxMonitorJobSpec{ Name: fmt.Sprintf("flux-monitor-%s", adapterUUID), ContractAddress: fluxInstance.Address(), + EVMChainID: chainClient.GetChainID().String(), Threshold: 0, AbsoluteThreshold: 0, PollTimerPeriod: 15 * time.Second, // min 15s diff --git a/integration-tests/performance/keeper_test.go b/integration-tests/performance/keeper_test.go index 384729dfab3..5688a05aa6d 100644 --- a/integration-tests/performance/keeper_test.go +++ b/integration-tests/performance/keeper_test.go @@ -68,7 +68,7 @@ func TestKeeperPerformance(t *testing.T) { // Not the last node, hence not all nodes started profiling yet. return } - actions.CreateKeeperJobs(t, chainlinkNodes, registry, contracts.OCRv2Config{}) + actions.CreateKeeperJobs(t, chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) err := chainClient.WaitForEvents() require.NoError(t, err, "Error creating keeper jobs") diff --git a/integration-tests/performance/ocr_test.go b/integration-tests/performance/ocr_test.go index d056d58e30b..a1f588c4411 100644 --- a/integration-tests/performance/ocr_test.go +++ b/integration-tests/performance/ocr_test.go @@ -58,7 +58,7 @@ func TestOCRBasic(t *testing.T) { require.NoError(t, err, "Error waiting for events") profileFunction := func(chainlinkNode *client.ChainlinkClient) { - err = actions.CreateOCRJobs(ocrInstances, bootstrapNode, workerNodes, 5, mockServer) + err = actions.CreateOCRJobs(ocrInstances, bootstrapNode, workerNodes, 5, mockServer, chainClient.GetChainID().String()) require.NoError(t, err) err = actions.StartNewRound(1, ocrInstances, chainClient) require.NoError(t, err) diff --git a/integration-tests/reorg/reorg_test.go b/integration-tests/reorg/reorg_test.go index c944b7a7539..03d179ce268 100644 --- a/integration-tests/reorg/reorg_test.go +++ b/integration-tests/reorg/reorg_test.go @@ -181,6 +181,7 @@ func TestDirectRequestReorg(t *testing.T) { Name: "direct_request", MinIncomingConfirmations: minIncomingConfirmations, ContractAddress: oracle.Address(), + EVMChainID: chainClient.GetChainID().String(), ExternalJobID: jobUUID.String(), ObservationSource: ost, }) diff --git a/integration-tests/smoke/flux_test.go b/integration-tests/smoke/flux_test.go index c4cd02b857d..385ed90034f 100644 --- a/integration-tests/smoke/flux_test.go +++ b/integration-tests/smoke/flux_test.go @@ -93,6 +93,7 @@ func TestFluxBasic(t *testing.T) { fluxSpec := &client.FluxMonitorJobSpec{ Name: fmt.Sprintf("flux-monitor-%s", adapterUUID), ContractAddress: fluxInstance.Address(), + EVMChainID: env.EVMClient.GetChainID().String(), Threshold: 0, AbsoluteThreshold: 0, PollTimerPeriod: 15 * time.Second, // min 15s diff --git a/integration-tests/smoke/forwarder_ocr_test.go b/integration-tests/smoke/forwarder_ocr_test.go index e4cf5cb0527..2e83a4fe688 100644 --- a/integration-tests/smoke/forwarder_ocr_test.go +++ b/integration-tests/smoke/forwarder_ocr_test.go @@ -68,7 +68,7 @@ func TestForwarderOCRBasic(t *testing.T) { ) require.NoError(t, err, "Error deploying OCR contracts") - err = actions.CreateOCRJobsWithForwarderLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockServer.Client) + err = actions.CreateOCRJobsWithForwarderLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockServer.Client, env.EVMClient.GetChainID().String()) require.NoError(t, err, "failed to setup forwarder jobs") err = actions.StartNewRound(1, ocrInstances, env.EVMClient) require.NoError(t, err) diff --git a/integration-tests/smoke/keeper_test.go b/integration-tests/smoke/keeper_test.go index 35bb632c113..e51631d1583 100644 --- a/integration-tests/smoke/keeper_test.go +++ b/integration-tests/smoke/keeper_test.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink-testing-framework/utils" + "github.com/smartcontractkit/chainlink/v2/core/store/models" "github.com/smartcontractkit/chainlink/integration-tests/actions" @@ -100,7 +101,7 @@ func TestKeeperBasicSmoke(t *testing.T) { ) gom := gomega.NewGomegaWithT(t) - _, err := actions.CreateKeeperJobsLocal(chainlinkNodes, registry, contracts.OCRv2Config{}) + _, err := actions.CreateKeeperJobsLocal(chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) require.NoError(t, err, "Error creating keeper jobs") err = chainClient.WaitForEvents() require.NoError(t, err, "Error creating keeper jobs") @@ -176,7 +177,7 @@ func TestKeeperBlockCountPerTurn(t *testing.T) { ) gom := gomega.NewGomegaWithT(t) - _, err := actions.CreateKeeperJobsLocal(chainlinkNodes, registry, contracts.OCRv2Config{}) + _, err := actions.CreateKeeperJobsLocal(chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) require.NoError(t, err, "Error creating keeper jobs") err = chainClient.WaitForEvents() require.NoError(t, err, "Error creating keeper jobs") @@ -283,7 +284,7 @@ func TestKeeperSimulation(t *testing.T) { ) gom := gomega.NewGomegaWithT(t) - _, err := actions.CreateKeeperJobsLocal(chainlinkNodes, registry, contracts.OCRv2Config{}) + _, err := actions.CreateKeeperJobsLocal(chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) require.NoError(t, err, "Error creating keeper jobs") err = chainClient.WaitForEvents() require.NoError(t, err, "Error creating keeper jobs") @@ -356,7 +357,7 @@ func TestKeeperCheckPerformGasLimit(t *testing.T) { ) gom := gomega.NewGomegaWithT(t) - _, err := actions.CreateKeeperJobsLocal(chainlinkNodes, registry, contracts.OCRv2Config{}) + _, err := actions.CreateKeeperJobsLocal(chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) require.NoError(t, err, "Error creating keeper jobs") err = chainClient.WaitForEvents() require.NoError(t, err, "Error creating keeper jobs") @@ -465,7 +466,7 @@ func TestKeeperRegisterUpkeep(t *testing.T) { ) gom := gomega.NewGomegaWithT(t) - _, err := actions.CreateKeeperJobsLocal(chainlinkNodes, registry, contracts.OCRv2Config{}) + _, err := actions.CreateKeeperJobsLocal(chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) require.NoError(t, err, "Error creating keeper jobs") err = chainClient.WaitForEvents() require.NoError(t, err, "Error creating keeper jobs") @@ -553,7 +554,7 @@ func TestKeeperAddFunds(t *testing.T) { ) gom := gomega.NewGomegaWithT(t) - _, err := actions.CreateKeeperJobsLocal(chainlinkNodes, registry, contracts.OCRv2Config{}) + _, err := actions.CreateKeeperJobsLocal(chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) require.NoError(t, err, "Error creating keeper jobs") err = chainClient.WaitForEvents() require.NoError(t, err, "Error creating keeper jobs") @@ -616,7 +617,7 @@ func TestKeeperRemove(t *testing.T) { ) gom := gomega.NewGomegaWithT(t) - _, err := actions.CreateKeeperJobsLocal(chainlinkNodes, registry, contracts.OCRv2Config{}) + _, err := actions.CreateKeeperJobsLocal(chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) require.NoError(t, err, "Error creating keeper jobs") err = chainClient.WaitForEvents() require.NoError(t, err, "Error creating keeper jobs") @@ -693,7 +694,7 @@ func TestKeeperPauseRegistry(t *testing.T) { ) gom := gomega.NewGomegaWithT(t) - _, err := actions.CreateKeeperJobsLocal(chainlinkNodes, registry, contracts.OCRv2Config{}) + _, err := actions.CreateKeeperJobsLocal(chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) require.NoError(t, err, "Error creating keeper jobs") err = chainClient.WaitForEvents() require.NoError(t, err, "Error creating keeper jobs") @@ -753,7 +754,7 @@ func TestKeeperMigrateRegistry(t *testing.T) { ) gom := gomega.NewGomegaWithT(t) - _, err := actions.CreateKeeperJobsLocal(chainlinkNodes, registry, contracts.OCRv2Config{}) + _, err := actions.CreateKeeperJobsLocal(chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) require.NoError(t, err, "Error creating keeper jobs") err = chainClient.WaitForEvents() require.NoError(t, err, "Error creating keeper jobs") @@ -772,7 +773,7 @@ func TestKeeperMigrateRegistry(t *testing.T) { ) // Set the jobs for the second registry - _, err = actions.CreateKeeperJobsLocal(chainlinkNodes, secondRegistry, contracts.OCRv2Config{}) + _, err = actions.CreateKeeperJobsLocal(chainlinkNodes, secondRegistry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) require.NoError(t, err, "Error creating keeper jobs") err = chainClient.WaitForEvents() require.NoError(t, err, "Error creating keeper jobs") @@ -845,7 +846,7 @@ func TestKeeperNodeDown(t *testing.T) { ) gom := gomega.NewGomegaWithT(t) - jobs, err := actions.CreateKeeperJobsLocal(chainlinkNodes, registry, contracts.OCRv2Config{}) + jobs, err := actions.CreateKeeperJobsLocal(chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) require.NoError(t, err, "Error creating keeper jobs") err = chainClient.WaitForEvents() require.NoError(t, err, "Error creating keeper jobs") @@ -951,7 +952,7 @@ func TestKeeperPauseUnPauseUpkeep(t *testing.T) { ) gom := gomega.NewGomegaWithT(t) - _, err := actions.CreateKeeperJobsLocal(chainlinkNodes, registry, contracts.OCRv2Config{}) + _, err := actions.CreateKeeperJobsLocal(chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) require.NoError(t, err, "Error creating keeper jobs") err = chainClient.WaitForEvents() require.NoError(t, err, "Error creating keeper jobs") @@ -1042,7 +1043,7 @@ func TestKeeperUpdateCheckData(t *testing.T) { ) gom := gomega.NewGomegaWithT(t) - _, err := actions.CreateKeeperJobsLocal(chainlinkNodes, registry, contracts.OCRv2Config{}) + _, err := actions.CreateKeeperJobsLocal(chainlinkNodes, registry, contracts.OCRv2Config{}, chainClient.GetChainID().String()) require.NoError(t, err, "Error creating keeper jobs") err = chainClient.WaitForEvents() require.NoError(t, err, "Error creating keeper jobs") diff --git a/integration-tests/smoke/ocr_test.go b/integration-tests/smoke/ocr_test.go index 50d6abe662b..47426b895de 100644 --- a/integration-tests/smoke/ocr_test.go +++ b/integration-tests/smoke/ocr_test.go @@ -43,7 +43,7 @@ func TestOCRBasic(t *testing.T) { err = env.EVMClient.WaitForEvents() require.NoError(t, err, "Error waiting for events") - err = actions.CreateOCRJobsLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockServer.Client) + err = actions.CreateOCRJobsLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockServer.Client, env.EVMClient.GetChainID().String()) require.NoError(t, err) err = actions.StartNewRound(1, ocrInstances, env.EVMClient) diff --git a/integration-tests/smoke/runlog_test.go b/integration-tests/smoke/runlog_test.go index cd2a099b142..83160449e59 100644 --- a/integration-tests/smoke/runlog_test.go +++ b/integration-tests/smoke/runlog_test.go @@ -68,6 +68,7 @@ func TestRunLogBasic(t *testing.T) { Name: fmt.Sprintf("direct-request-%s", uuid.NewString()), MinIncomingConfirmations: "1", ContractAddress: oracle.Address(), + EVMChainID: env.EVMClient.GetChainID().String(), ExternalJobID: jobUUID.String(), ObservationSource: ost, }) diff --git a/integration-tests/smoke/vrf_test.go b/integration-tests/smoke/vrf_test.go index 0e12b185a6a..465b1322261 100644 --- a/integration-tests/smoke/vrf_test.go +++ b/integration-tests/smoke/vrf_test.go @@ -66,6 +66,7 @@ func TestVRFBasic(t *testing.T) { MinIncomingConfirmations: 1, PublicKey: pubKeyCompressed, ExternalJobID: jobUUID.String(), + EVMChainID: env.EVMClient.GetChainID().String(), ObservationSource: ost, }) require.NoError(t, err, "Creating VRF Job shouldn't fail") diff --git a/integration-tests/testsetups/keeper_benchmark.go b/integration-tests/testsetups/keeper_benchmark.go index 7e862467266..bdba3a67665 100644 --- a/integration-tests/testsetups/keeper_benchmark.go +++ b/integration-tests/testsetups/keeper_benchmark.go @@ -246,7 +246,7 @@ func (k *KeeperBenchmarkTest) Run(t *testing.T) { // Give time for OCR nodes to bootstrap time.Sleep(1 * time.Minute) } else { - actions.CreateKeeperJobsWithKeyIndex(t, k.chainlinkNodes, k.keeperRegistries[rIndex], txKeyId, ocrConfig) + actions.CreateKeeperJobsWithKeyIndex(t, k.chainlinkNodes, k.keeperRegistries[rIndex], txKeyId, ocrConfig, k.chainClient.GetChainID().String()) } err = k.chainClient.WaitForEvents() require.NoError(t, err, "Error waiting for registry setConfig") diff --git a/integration-tests/testsetups/ocr.go b/integration-tests/testsetups/ocr.go index 07aa3b2c4e8..c0e84525822 100644 --- a/integration-tests/testsetups/ocr.go +++ b/integration-tests/testsetups/ocr.go @@ -263,9 +263,9 @@ func (o *OCRSoakTest) Run() { startingValue := 5 if o.OperatorForwarderFlow { - actions.CreateOCRJobsWithForwarder(o.t, o.ocrInstances, o.bootstrapNode, o.workerNodes, startingValue, o.mockServer) + actions.CreateOCRJobsWithForwarder(o.t, o.ocrInstances, o.bootstrapNode, o.workerNodes, startingValue, o.mockServer, o.chainClient.GetChainID().String()) } else { - err := actions.CreateOCRJobs(o.ocrInstances, o.bootstrapNode, o.workerNodes, startingValue, o.mockServer) + err := actions.CreateOCRJobs(o.ocrInstances, o.bootstrapNode, o.workerNodes, startingValue, o.mockServer, o.chainClient.GetChainID().String()) require.NoError(o.t, err, "Error creating OCR jobs") }