From 61608c0a3c4eadbdf0ddad053acc8ea7be90ebeb Mon Sep 17 00:00:00 2001 From: krehermann Date: Thu, 21 Sep 2023 15:35:58 -0600 Subject: [PATCH 1/7] hacking at unique DB for evm relayer --- core/chains/evm/chain.go | 22 ++- core/cmd/shell.go | 7 +- core/cmd/shell_local_test.go | 11 +- core/cmd/shell_test.go | 8 +- core/internal/cltest/cltest.go | 6 +- core/internal/testutils/evmtest/evmtest.go | 2 +- core/internal/testutils/pgtest/pgtest.go | 33 +++- core/internal/testutils/pgtest/txdb.go | 59 ++++-- .../relayer_chain_interoperators_test.go | 182 +++++++++--------- core/services/chainlink/relayer_factory.go | 25 ++- core/services/pg/connection.go | 16 +- core/services/pg/locked_db.go | 28 ++- core/services/relay/evm/relayer_extender.go | 4 +- .../relay/evm/relayer_extender_test.go | 2 +- 14 files changed, 265 insertions(+), 140 deletions(-) diff --git a/core/chains/evm/chain.go b/core/chains/evm/chain.go index 6a948a4cdd0..43e47c0035d 100644 --- a/core/chains/evm/chain.go +++ b/core/chains/evm/chain.go @@ -142,7 +142,6 @@ type AppConfig interface { type ChainRelayExtenderConfig struct { Logger logger.Logger - DB *sqlx.DB KeyStore keystore.Eth *RelayerConfig } @@ -158,6 +157,8 @@ type RelayerConfig struct { MailMon *utils.MailboxMonitor GasEstimator gas.EvmFeeEstimator + DB *sqlx.DB + // TODO BCF-2513 remove test code from the API // Gen-functions are useful for dependency injection by tests GenEthClient func(*big.Int) client.Client @@ -168,6 +169,24 @@ type RelayerConfig struct { GenGasEstimator func(*big.Int) gas.EvmFeeEstimator } +func (r RelayerConfig) validate() error { + var err error + if r.AppConfig == nil { + err = errors.Join(err, fmt.Errorf("nil AppConfig")) + } + if r.EventBroadcaster == nil { + err = errors.Join(err, fmt.Errorf("nil EventBroadcaster")) + } + + if r.MailMon == nil { + err = errors.Join(err, fmt.Errorf("nil MailMon")) + } + + if r.DB == nil { + err = errors.Join(err, fmt.Errorf("nil DB")) + } + return err +} func NewTOMLChain(ctx context.Context, chain *toml.EVMConfig, opts ChainRelayExtenderConfig) (Chain, error) { chainID := chain.ChainID l := opts.Logger.With("evmChainID", chainID.String()) @@ -180,6 +199,7 @@ func NewTOMLChain(ctx context.Context, chain *toml.EVMConfig, opts ChainRelayExt } func newChain(ctx context.Context, cfg *evmconfig.ChainScoped, nodes []*toml.Node, opts ChainRelayExtenderConfig) (*chain, error) { + chainID, chainType := cfg.EVM().ChainID(), cfg.EVM().ChainType() l := opts.Logger var client evmclient.Client diff --git a/core/cmd/shell.go b/core/cmd/shell.go index b9c031fd8b7..ed766d07571 100644 --- a/core/cmd/shell.go +++ b/core/cmd/shell.go @@ -154,15 +154,18 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G // create the relayer-chain interoperators from application configuration relayerFactory := chainlink.RelayerFactory{ Logger: appLggr, - DB: db, QConfig: cfg.Database(), LoopRegistry: loopRegistry, GRPCOpts: grpcOpts, } + evmScopedDB, err := pg.OpenUnlockedDB(cfg.AppID(), cfg.Database(), pg.WithSchema("evm")) //pg.NewLockedDB(cfg.AppID(), cfg.Database(), cfg.Database().Lock(), lggr) + if err != nil { + return nil, err + } evmFactoryCfg := chainlink.EVMFactoryConfig{ CSAETHKeystore: keyStore, - RelayerConfig: &evm.RelayerConfig{AppConfig: cfg, EventBroadcaster: eventBroadcaster, MailMon: mailMon}, + RelayerConfig: &evm.RelayerConfig{AppConfig: cfg, EventBroadcaster: eventBroadcaster, MailMon: mailMon, DB: evmScopedDB}, } // evm always enabled for backward compatibility // TODO BCF-2510 this needs to change in order to clear the path for EVM extraction diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go index 8d2b5f1fabf..73c158cbcc0 100644 --- a/core/cmd/shell_local_test.go +++ b/core/cmd/shell_local_test.go @@ -41,8 +41,8 @@ import ( func genTestEVMRelayers(t *testing.T, opts evm.ChainRelayExtenderConfig, ks evmrelayer.CSAETHKeystore) *chainlink.CoreRelayerChainInteroperators { f := chainlink.RelayerFactory{ - Logger: opts.Logger, - DB: opts.DB, + Logger: opts.Logger, + //DB: opts.DB, QConfig: opts.AppConfig.Database(), LoopRegistry: plugins.NewLoopRegistry(opts.Logger), } @@ -86,13 +86,14 @@ func TestShell_RunNodeWithPasswords(t *testing.T) { lggr := logger.TestLogger(t) opts := evm.ChainRelayExtenderConfig{ - Logger: lggr, - DB: db, + Logger: lggr, + KeyStore: keyStore.Eth(), RelayerConfig: &evm.RelayerConfig{ AppConfig: cfg, EventBroadcaster: pg.NewNullEventBroadcaster(), MailMon: &utils.MailboxMonitor{}, + DB: pgtest.NewEVMScopedDB(t), }, } testRelayers := genTestEVMRelayers(t, opts, keyStore) @@ -191,13 +192,13 @@ func TestShell_RunNodeWithAPICredentialsFile(t *testing.T) { lggr := logger.TestLogger(t) opts := evm.ChainRelayExtenderConfig{ Logger: lggr, - DB: db, KeyStore: keyStore.Eth(), RelayerConfig: &evm.RelayerConfig{ AppConfig: cfg, EventBroadcaster: pg.NewNullEventBroadcaster(), MailMon: &utils.MailboxMonitor{}, + DB: pgtest.NewEVMScopedDB(t), }, } testRelayers := genTestEVMRelayers(t, opts, keyStore) diff --git a/core/cmd/shell_test.go b/core/cmd/shell_test.go index 45192392f6d..c9e96c1df74 100644 --- a/core/cmd/shell_test.go +++ b/core/cmd/shell_test.go @@ -369,8 +369,8 @@ func TestSetupSolanaRelayer(t *testing.T) { }) rf := chainlink.RelayerFactory{ - Logger: lggr, - DB: pgtest.NewSqlxDB(t), + Logger: lggr, + // DB: pgtest.NewSqlxDB(t), QConfig: tConfig.Database(), LoopRegistry: reg, } @@ -456,8 +456,8 @@ func TestSetupStarkNetRelayer(t *testing.T) { } }) rf := chainlink.RelayerFactory{ - Logger: lggr, - DB: pgtest.NewSqlxDB(t), + Logger: lggr, + //DB: pgtest.NewSqlxDB(t), QConfig: tConfig.Database(), LoopRegistry: reg, } diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index 1c5d1ed5bbb..fb9880ca7ad 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -64,6 +64,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" clhttptest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/httptest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/keystest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/logger/audit" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -385,8 +386,8 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn loopRegistry := plugins.NewLoopRegistry(lggr) relayerFactory := chainlink.RelayerFactory{ - Logger: lggr, - DB: db, + Logger: lggr, + // DB: db, QConfig: cfg.Database(), LoopRegistry: loopRegistry, GRPCOpts: loop.GRPCOpts{}, @@ -397,6 +398,7 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn AppConfig: cfg, EventBroadcaster: eventBroadcaster, MailMon: mailMon, + DB: pgtest.NewEVMScopedDB(t), }, CSAETHKeystore: keyStore, } diff --git a/core/internal/testutils/evmtest/evmtest.go b/core/internal/testutils/evmtest/evmtest.go index 62696f75d96..773220a199a 100644 --- a/core/internal/testutils/evmtest/evmtest.go +++ b/core/internal/testutils/evmtest/evmtest.go @@ -82,13 +82,13 @@ func NewChainRelayExtOpts(t testing.TB, testopts TestChainOpts) evm.ChainRelayEx require.NotNil(t, testopts.KeyStore) opts := evm.ChainRelayExtenderConfig{ Logger: logger.TestLogger(t), - DB: testopts.DB, KeyStore: testopts.KeyStore, RelayerConfig: &evm.RelayerConfig{ AppConfig: testopts.GeneralConfig, EventBroadcaster: pg.NewNullEventBroadcaster(), MailMon: testopts.MailMon, GasEstimator: testopts.GasEstimator, + DB: testopts.DB, }, } opts.GenEthClient = func(*big.Int) evmclient.Client { diff --git a/core/internal/testutils/pgtest/pgtest.go b/core/internal/testutils/pgtest/pgtest.go index 283326de85f..164244b532a 100644 --- a/core/internal/testutils/pgtest/pgtest.go +++ b/core/internal/testutils/pgtest/pgtest.go @@ -2,6 +2,8 @@ package pgtest import ( "database/sql" + "encoding/json" + "fmt" "testing" "github.com/google/uuid" @@ -29,9 +31,28 @@ func NewSqlDB(t *testing.T) *sql.DB { return db } -func NewSqlxDB(t testing.TB) *sqlx.DB { +func NewEVMScopedDB(t testing.TB) *sqlx.DB { + // hack to scope to evm schema + url := withSchema(defaultDBURL, "evm") + return NewSqlxDB(t, WithURL(url)) +} + +func withSchema(conn, schema string) string { + return fmt.Sprintf("%s&options=-csearch_path=%s", conn, schema) +} + +func NewSqlxDB(t testing.TB, opts ...ConnectionOpt) *sqlx.DB { testutils.SkipShortDB(t) - db, err := sqlx.Open(string(dialects.TransactionWrappedPostgres), uuid.New().String()) + conn := &pg.ConnectionScope{ + UUID: uuid.New().String(), + URL: defaultDBURL, + } + for _, opt := range opts { + opt(conn) + } + enc, err := json.Marshal(conn) + require.NoError(t, err) + db, err := sqlx.Open(string(dialects.TransactionWrappedPostgres), string(enc)) require.NoError(t, err) t.Cleanup(func() { assert.NoError(t, db.Close()) }) @@ -40,6 +61,14 @@ func NewSqlxDB(t testing.TB) *sqlx.DB { return db } +type ConnectionOpt func(conn *pg.ConnectionScope) + +func WithURL(url string) ConnectionOpt { + return func(conn *pg.ConnectionScope) { + conn.URL = url + } +} + func MustExec(t *testing.T, db *sqlx.DB, stmt string, args ...interface{}) { require.NoError(t, utils.JustError(db.Exec(stmt, args...))) } diff --git a/core/internal/testutils/pgtest/txdb.go b/core/internal/testutils/pgtest/txdb.go index 1e65b1797b7..31587fda23d 100644 --- a/core/internal/testutils/pgtest/txdb.go +++ b/core/internal/testutils/pgtest/txdb.go @@ -4,6 +4,7 @@ import ( "context" "database/sql" "database/sql/driver" + "encoding/json" "flag" "fmt" "io" @@ -16,6 +17,7 @@ import ( "go.uber.org/multierr" "github.com/smartcontractkit/chainlink/v2/core/config/env" + "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/store/dialects" ) @@ -35,6 +37,7 @@ import ( // store to use the raw DialectPostgres dialect and setup a one-use database. // See heavyweight.FullTestDB() as a convenience function to help you do this, // but please use sparingly because as it's name implies, it is expensive. +var defaultDBURL string // global used to create a [NewSqlxDB] func init() { testing.Init() if !flag.Parsed() { @@ -44,12 +47,12 @@ func init() { // -short tests don't need a DB return } - dbURL := string(env.DatabaseURL.Get()) - if dbURL == "" { + defaultDBURL = string(env.DatabaseURL.Get()) + if defaultDBURL == "" { panic("you must provide a CL_DATABASE_URL environment variable") } - parsed, err := url.Parse(dbURL) + parsed, err := url.Parse(defaultDBURL) if err != nil { panic(err) } @@ -63,8 +66,8 @@ func init() { } name := string(dialects.TransactionWrappedPostgres) sql.Register(name, &txDriver{ - dbURL: dbURL, - conns: make(map[string]*conn), + dbURL: defaultDBURL, + conns: make(map[string]map[string]*conn), }) sqlx.BindDriver(name, sqlx.DOLLAR) } @@ -75,34 +78,47 @@ var _ driver.Conn = &conn{} // when the Close is called, transaction is rolled back type txDriver struct { sync.Mutex - db *sql.DB - conns map[string]*conn + db map[string]*sql.DB // url -> db + conns map[string]map[string]*conn // url -> (uuid -> db) so we can close per url dbURL string } -func (d *txDriver) Open(dsn string) (driver.Conn, error) { +// jsonConnectionScope must be a json-encoded [ConnectionScope]. The Open interface requires +// a string +func (d *txDriver) Open(jsonConnectionScope string) (driver.Conn, error) { d.Lock() defer d.Unlock() - // Open real db connection if its the first call + var scope pg.ConnectionScope + err := json.Unmarshal([]byte(jsonConnectionScope), &scope) + if err != nil { + return nil, fmt.Errorf("pgtest tx driver failed to parse connection string %s: must be json encoded scope: %w", jsonConnectionScope, err) + } + // initialize dbs if the first call if d.db == nil { - db, err := sql.Open("pgx", d.dbURL) + d.db = make(map[string]*sql.DB) + } + db, exists := d.db[scope.URL] + if !exists { + db, err = sql.Open("pgx", scope.URL) if err != nil { return nil, err } - d.db = db + d.db[scope.URL] = db + d.conns[scope.URL] = make(map[string]*conn) } - c, exists := d.conns[dsn] + + c, exists := d.conns[scope.URL][scope.UUID] if !exists || !c.tryOpen() { - tx, err := d.db.Begin() + tx, err := db.Begin() if err != nil { return nil, err } - c = &conn{tx: tx, opened: 1} + c = &conn{tx: tx, opened: 1, scope: scope} c.removeSelf = func() error { return d.deleteConn(c) } - d.conns[dsn] = c + d.conns[scope.URL][scope.UUID] = c } return c, nil } @@ -114,22 +130,23 @@ func (d *txDriver) deleteConn(c *conn) error { d.Lock() defer d.Unlock() - if d.conns[c.dsn] != c { + if d.conns[c.scope.URL][c.scope.UUID] != c { return nil // already been replaced } - delete(d.conns, c.dsn) - if len(d.conns) == 0 && d.db != nil { - if err := d.db.Close(); err != nil { + delete(d.conns[c.scope.URL], c.scope.UUID) + if len(d.conns[c.scope.URL]) == 0 && d.db[c.scope.URL] != nil { + if err := d.db[c.scope.URL].Close(); err != nil { return err } - d.db = nil + delete(d.db, c.scope.URL) } return nil } type conn struct { sync.Mutex - dsn string + //dsn string + scope pg.ConnectionScope tx *sql.Tx // tx may be shared by many conns, definitive one lives in the map keyed by DSN on the txDriver. Do not modify from conn closed bool opened int diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go index 9cfe354fe91..786e9c55780 100644 --- a/core/services/chainlink/relayer_chain_interoperators_test.go +++ b/core/services/chainlink/relayer_chain_interoperators_test.go @@ -173,8 +173,8 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { lggr := logger.TestLogger(t) factory := chainlink.RelayerFactory{ - Logger: lggr, - DB: db, + Logger: lggr, + //DB: db, QConfig: cfg.Database(), LoopRegistry: plugins.NewLoopRegistry(lggr), GRPCOpts: loop.GRPCOpts{}, @@ -211,6 +211,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { AppConfig: cfg, EventBroadcaster: pg.NewNullEventBroadcaster(), MailMon: &utils.MailboxMonitor{}, + DB: pgtest.NewEVMScopedDB(t), }, CSAETHKeystore: keyStore, }), @@ -223,108 +224,109 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { }, expectedRelayerNetworks: map[relay.Network]struct{}{relay.EVM: {}}, }, + /* + {name: "2 solana chain with 2 node", - {name: "2 solana chain with 2 node", - - initFuncs: []chainlink.CoreRelayerChainInitFunc{ - chainlink.InitSolana(testctx, factory, chainlink.SolanaFactoryConfig{ - Keystore: keyStore.Solana(), - SolanaConfigs: cfg.SolanaConfigs()}), - }, - expectedSolanaChainCnt: 2, - expectedSolanaNodeCnt: 2, - expectedSolanaRelayerIds: []relay.ID{ - {Network: relay.Solana, ChainID: relay.ChainID(solanaChainID1)}, - {Network: relay.Solana, ChainID: relay.ChainID(solanaChainID2)}, + initFuncs: []chainlink.CoreRelayerChainInitFunc{ + chainlink.InitSolana(testctx, factory, chainlink.SolanaFactoryConfig{ + Keystore: keyStore.Solana(), + SolanaConfigs: cfg.SolanaConfigs()}), + }, + expectedSolanaChainCnt: 2, + expectedSolanaNodeCnt: 2, + expectedSolanaRelayerIds: []relay.ID{ + {Network: relay.Solana, ChainID: relay.ChainID(solanaChainID1)}, + {Network: relay.Solana, ChainID: relay.ChainID(solanaChainID2)}, + }, + expectedRelayerNetworks: map[relay.Network]struct{}{relay.Solana: {}}, }, - expectedRelayerNetworks: map[relay.Network]struct{}{relay.Solana: {}}, - }, - {name: "2 starknet chain with 4 nodes", + {name: "2 starknet chain with 4 nodes", - initFuncs: []chainlink.CoreRelayerChainInitFunc{ - chainlink.InitStarknet(testctx, factory, chainlink.StarkNetFactoryConfig{ - Keystore: keyStore.StarkNet(), - StarknetConfigs: cfg.StarknetConfigs()}), - }, - expectedStarknetChainCnt: 2, - expectedStarknetNodeCnt: 4, - expectedStarknetRelayerIds: []relay.ID{ - {Network: relay.StarkNet, ChainID: relay.ChainID(starknetChainID1)}, - {Network: relay.StarkNet, ChainID: relay.ChainID(starknetChainID2)}, + initFuncs: []chainlink.CoreRelayerChainInitFunc{ + chainlink.InitStarknet(testctx, factory, chainlink.StarkNetFactoryConfig{ + Keystore: keyStore.StarkNet(), + StarknetConfigs: cfg.StarknetConfigs()}), + }, + expectedStarknetChainCnt: 2, + expectedStarknetNodeCnt: 4, + expectedStarknetRelayerIds: []relay.ID{ + {Network: relay.StarkNet, ChainID: relay.ChainID(starknetChainID1)}, + {Network: relay.StarkNet, ChainID: relay.ChainID(starknetChainID2)}, + }, + expectedRelayerNetworks: map[relay.Network]struct{}{relay.StarkNet: {}}, }, - expectedRelayerNetworks: map[relay.Network]struct{}{relay.StarkNet: {}}, - }, - { - name: "2 cosmos chains with 2 nodes", - initFuncs: []chainlink.CoreRelayerChainInitFunc{ - chainlink.InitCosmos(testctx, factory, chainlink.CosmosFactoryConfig{ - Keystore: keyStore.Cosmos(), - CosmosConfigs: cfg.CosmosConfigs(), - EventBroadcaster: pg.NewNullEventBroadcaster()}), - }, - expectedCosmosChainCnt: 2, - expectedCosmosNodeCnt: 2, - expectedCosmosRelayerIds: []relay.ID{ - {Network: relay.Cosmos, ChainID: relay.ChainID(cosmosChainID1)}, - {Network: relay.Cosmos, ChainID: relay.ChainID(cosmosChainID2)}, + { + name: "2 cosmos chains with 2 nodes", + initFuncs: []chainlink.CoreRelayerChainInitFunc{ + chainlink.InitCosmos(testctx, factory, chainlink.CosmosFactoryConfig{ + Keystore: keyStore.Cosmos(), + CosmosConfigs: cfg.CosmosConfigs(), + EventBroadcaster: pg.NewNullEventBroadcaster()}), + }, + expectedCosmosChainCnt: 2, + expectedCosmosNodeCnt: 2, + expectedCosmosRelayerIds: []relay.ID{ + {Network: relay.Cosmos, ChainID: relay.ChainID(cosmosChainID1)}, + {Network: relay.Cosmos, ChainID: relay.ChainID(cosmosChainID2)}, + }, + expectedRelayerNetworks: map[relay.Network]struct{}{relay.Cosmos: {}}, }, - expectedRelayerNetworks: map[relay.Network]struct{}{relay.Cosmos: {}}, - }, - {name: "all chains", + {name: "all chains", - initFuncs: []chainlink.CoreRelayerChainInitFunc{chainlink.InitSolana(testctx, factory, chainlink.SolanaFactoryConfig{ - Keystore: keyStore.Solana(), - SolanaConfigs: cfg.SolanaConfigs()}), - chainlink.InitEVM(testctx, factory, chainlink.EVMFactoryConfig{ - RelayerConfig: &evm.RelayerConfig{ - AppConfig: cfg, + initFuncs: []chainlink.CoreRelayerChainInitFunc{chainlink.InitSolana(testctx, factory, chainlink.SolanaFactoryConfig{ + Keystore: keyStore.Solana(), + SolanaConfigs: cfg.SolanaConfigs()}), + chainlink.InitEVM(testctx, factory, chainlink.EVMFactoryConfig{ + RelayerConfig: &evm.RelayerConfig{ + AppConfig: cfg, + EventBroadcaster: pg.NewNullEventBroadcaster(), + MailMon: &utils.MailboxMonitor{}, + }, + CSAETHKeystore: keyStore, + }), + chainlink.InitStarknet(testctx, factory, chainlink.StarkNetFactoryConfig{ + Keystore: keyStore.StarkNet(), + StarknetConfigs: cfg.StarknetConfigs()}), + chainlink.InitCosmos(testctx, factory, chainlink.CosmosFactoryConfig{ + Keystore: keyStore.Cosmos(), + CosmosConfigs: cfg.CosmosConfigs(), EventBroadcaster: pg.NewNullEventBroadcaster(), - MailMon: &utils.MailboxMonitor{}, - }, - CSAETHKeystore: keyStore, - }), - chainlink.InitStarknet(testctx, factory, chainlink.StarkNetFactoryConfig{ - Keystore: keyStore.StarkNet(), - StarknetConfigs: cfg.StarknetConfigs()}), - chainlink.InitCosmos(testctx, factory, chainlink.CosmosFactoryConfig{ - Keystore: keyStore.Cosmos(), - CosmosConfigs: cfg.CosmosConfigs(), - EventBroadcaster: pg.NewNullEventBroadcaster(), - }), - }, - expectedEVMChainCnt: 2, - expectedEVMNodeCnt: 3, - expectedEVMRelayerIds: []relay.ID{ - {Network: relay.EVM, ChainID: relay.ChainID(evmChainID1.String())}, - {Network: relay.EVM, ChainID: relay.ChainID(evmChainID2.String())}, - }, + }), + }, + expectedEVMChainCnt: 2, + expectedEVMNodeCnt: 3, + expectedEVMRelayerIds: []relay.ID{ + {Network: relay.EVM, ChainID: relay.ChainID(evmChainID1.String())}, + {Network: relay.EVM, ChainID: relay.ChainID(evmChainID2.String())}, + }, - expectedSolanaChainCnt: 2, - expectedSolanaNodeCnt: 2, - expectedSolanaRelayerIds: []relay.ID{ - {Network: relay.Solana, ChainID: relay.ChainID(solanaChainID1)}, - {Network: relay.Solana, ChainID: relay.ChainID(solanaChainID2)}, - }, + expectedSolanaChainCnt: 2, + expectedSolanaNodeCnt: 2, + expectedSolanaRelayerIds: []relay.ID{ + {Network: relay.Solana, ChainID: relay.ChainID(solanaChainID1)}, + {Network: relay.Solana, ChainID: relay.ChainID(solanaChainID2)}, + }, - expectedStarknetChainCnt: 2, - expectedStarknetNodeCnt: 4, - expectedStarknetRelayerIds: []relay.ID{ - {Network: relay.StarkNet, ChainID: relay.ChainID(starknetChainID1)}, - {Network: relay.StarkNet, ChainID: relay.ChainID(starknetChainID2)}, - }, + expectedStarknetChainCnt: 2, + expectedStarknetNodeCnt: 4, + expectedStarknetRelayerIds: []relay.ID{ + {Network: relay.StarkNet, ChainID: relay.ChainID(starknetChainID1)}, + {Network: relay.StarkNet, ChainID: relay.ChainID(starknetChainID2)}, + }, - expectedCosmosChainCnt: 2, - expectedCosmosNodeCnt: 2, - expectedCosmosRelayerIds: []relay.ID{ - {Network: relay.Cosmos, ChainID: relay.ChainID(cosmosChainID1)}, - {Network: relay.Cosmos, ChainID: relay.ChainID(cosmosChainID2)}, - }, + expectedCosmosChainCnt: 2, + expectedCosmosNodeCnt: 2, + expectedCosmosRelayerIds: []relay.ID{ + {Network: relay.Cosmos, ChainID: relay.ChainID(cosmosChainID1)}, + {Network: relay.Cosmos, ChainID: relay.ChainID(cosmosChainID2)}, + }, - expectedRelayerNetworks: map[relay.Network]struct{}{relay.EVM: {}, relay.Cosmos: {}, relay.Solana: {}, relay.StarkNet: {}}, - }, + expectedRelayerNetworks: map[relay.Network]struct{}{relay.EVM: {}, relay.Cosmos: {}, relay.Solana: {}, relay.StarkNet: {}}, + }, + */ } for _, tt := range tests { tt := tt diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go index 0a0d653f5fc..17c2f07ffac 100644 --- a/core/services/chainlink/relayer_factory.go +++ b/core/services/chainlink/relayer_factory.go @@ -27,7 +27,6 @@ import ( type RelayerFactory struct { logger.Logger - *sqlx.DB pg.QConfig *plugins.LoopRegistry loop.GRPCOpts @@ -40,13 +39,21 @@ type EVMFactoryConfig struct { func (r *RelayerFactory) NewEVM(ctx context.Context, config EVMFactoryConfig) (map[relay.ID]evmrelay.LoopRelayAdapter, error) { // TODO impl EVM loop. For now always 'fallback' to an adapter and embedded chain - + /* + if config.DBConn == "" { + u := config.AppConfig.Database().URL() + config.DBConn = withSchema((&u).String(), "evm") + } + db, err := sqlx.Open(string(dialects.Postgres), config.DBConn) + if err != nil { + return nil, err + } + */ relayers := make(map[relay.ID]evmrelay.LoopRelayAdapter) // override some common opts with the factory values. this seems weird... maybe other signatures should change, or this should take a different type... ccOpts := evm.ChainRelayExtenderConfig{ Logger: r.Logger.Named("EVM"), - DB: r.DB, KeyStore: config.CSAETHKeystore.Eth(), RelayerConfig: config.RelayerConfig, } @@ -209,9 +216,16 @@ type CosmosFactoryConfig struct { Keystore keystore.Cosmos cosmos.CosmosConfigs EventBroadcaster pg.EventBroadcaster + DB *sqlx.DB } func (r *RelayerFactory) NewCosmos(ctx context.Context, config CosmosFactoryConfig) (map[relay.ID]cosmos.LoopRelayerChainer, error) { + /* + db, err := sqlx.Open(string(dialects.Postgres), config.DBConn) + if err != nil { + return nil, err + } + */ relayers := make(map[relay.ID]cosmos.LoopRelayerChainer) var ( @@ -226,7 +240,6 @@ func (r *RelayerFactory) NewCosmos(ctx context.Context, config CosmosFactoryConf opts := cosmos.ChainOpts{ QueryConfig: r.QConfig, Logger: lggr.Named(relayId.ChainID), - DB: r.DB, KeyStore: loopKs, EventBroadcaster: config.EventBroadcaster, } @@ -242,3 +255,7 @@ func (r *RelayerFactory) NewCosmos(ctx context.Context, config CosmosFactoryConf return relayers, nil } + +func withSchema(conn, schema string) string { + return fmt.Sprintf("%s&options=-csearch_path=%s", conn, schema) +} diff --git a/core/services/pg/connection.go b/core/services/pg/connection.go index 19c48a118b9..80e3266690a 100644 --- a/core/services/pg/connection.go +++ b/core/services/pg/connection.go @@ -1,6 +1,7 @@ package pg import ( + "encoding/json" "fmt" "time" @@ -19,6 +20,11 @@ type ConnectionConfig interface { MaxIdleConns() int } +type ConnectionScope struct { + URL string + UUID string +} + func NewConnection(uri string, dialect dialects.DialectName, config ConnectionConfig) (db *sqlx.DB, err error) { if dialect == dialects.TransactionWrappedPostgres { // Dbtx uses the uri as a unique identifier for each transaction. Each ORM @@ -28,7 +34,15 @@ func NewConnection(uri string, dialect dialects.DialectName, config ConnectionCo // We can happily throw away the original uri here because if we are using // txdb it should have already been set at the point where we called // txdb.Register - uri = uuid.New().String() + s := ConnectionScope{ + URL: uri, + UUID: uuid.New().String(), + } + b, err := json.Marshal(&s) + if err != nil { + return nil, err + } + uri = string(b) } // Initialize sql/sqlx diff --git a/core/services/pg/locked_db.go b/core/services/pg/locked_db.go index af4481285ce..627ce0f82cd 100644 --- a/core/services/pg/locked_db.go +++ b/core/services/pg/locked_db.go @@ -2,6 +2,7 @@ package pg import ( "context" + "fmt" "net/url" "time" @@ -18,7 +19,7 @@ import ( // LockedDB bounds DB connection and DB locks. type LockedDB interface { - Open(ctx context.Context) error + Open(ctx context.Context, opts ...ConnectionOpt) error Close() error DB() *sqlx.DB } @@ -53,7 +54,7 @@ func NewLockedDB(appID uuid.UUID, cfg LockedDBConfig, lockCfg config.Lock, lggr // OpenUnlockedDB just opens DB connection, without any DB locks. // This should be used carefully, when we know we don't need any locks. // Currently this is used by RebroadcastTransactions command only. -func OpenUnlockedDB(appID uuid.UUID, cfg LockedDBConfig) (db *sqlx.DB, err error) { +func OpenUnlockedDB(appID uuid.UUID, cfg LockedDBConfig, opts ...ConnectionOpt) (db *sqlx.DB, err error) { return openDB(appID, cfg) } @@ -61,7 +62,7 @@ func OpenUnlockedDB(appID uuid.UUID, cfg LockedDBConfig) (db *sqlx.DB, err error // If any of the steps fails or ctx is cancelled, it reverts everything. // This is a blocking function and it may execute long due to DB locks acquisition. // NOT THREAD SAFE -func (l *lockedDb) Open(ctx context.Context) (err error) { +func (l *lockedDb) Open(ctx context.Context, opts ...ConnectionOpt) (err error) { // If Open succeeded previously, db will not be nil if l.db != nil { l.lggr.Panic("calling Open() twice") @@ -139,10 +140,27 @@ func (l lockedDb) DB() *sqlx.DB { return l.db } -func openDB(appID uuid.UUID, cfg LockedDBConfig) (db *sqlx.DB, err error) { +func openDB(appID uuid.UUID, cfg LockedDBConfig, opts ...ConnectionOpt) (db *sqlx.DB, err error) { uri := cfg.URL() static.SetConsumerName(&uri, "App", &appID) dialect := cfg.Dialect() - db, err = NewConnection(uri.String(), dialect, cfg) + connStr := uri.String() + for _, opt := range opts { + opt(&connStr) + } + db, err = NewConnection(connStr, dialect, cfg) return } + +type ConnectionOpt func(*string) + +func WithSchema(schema string) ConnectionOpt { + return func(url *string) { + u := withSchema(*url, schema) + url = &u + } +} + +func withSchema(conn, schema string) string { + return fmt.Sprintf("%s&options=-csearch_path=%s", conn, schema) +} diff --git a/core/services/relay/evm/relayer_extender.go b/core/services/relay/evm/relayer_extender.go index 592c9bacee2..5e5f9cadbc4 100644 --- a/core/services/relay/evm/relayer_extender.go +++ b/core/services/relay/evm/relayer_extender.go @@ -145,7 +145,6 @@ func NewChainRelayerExtenders(ctx context.Context, opts evmchain.ChainRelayExten privOpts := evmchain.ChainRelayExtenderConfig{ Logger: opts.Logger.Named(cid), RelayerConfig: opts.RelayerConfig, - DB: opts.DB, KeyStore: opts.KeyStore, } @@ -161,5 +160,8 @@ func NewChainRelayerExtenders(ctx context.Context, opts evmchain.ChainRelayExten } result = append(result, s) } + if err != nil { + return nil, err + } return newChainRelayerExtsFromSlice(result, opts.AppConfig), nil } diff --git a/core/services/relay/evm/relayer_extender_test.go b/core/services/relay/evm/relayer_extender_test.go index 361a7468f30..5c237ce2cbd 100644 --- a/core/services/relay/evm/relayer_extender_test.go +++ b/core/services/relay/evm/relayer_extender_test.go @@ -34,7 +34,7 @@ func TestChainRelayExtenders(t *testing.T) { kst := cltest.NewKeyStore(t, db, cfg.Database()) require.NoError(t, kst.Unlock(cltest.Password)) - opts := evmtest.NewChainRelayExtOpts(t, evmtest.TestChainOpts{DB: db, KeyStore: kst.Eth(), GeneralConfig: cfg}) + opts := evmtest.NewChainRelayExtOpts(t, evmtest.TestChainOpts{DB: pgtest.NewEVMScopedDB(t), KeyStore: kst.Eth(), GeneralConfig: cfg}) opts.GenEthClient = func(*big.Int) evmclient.Client { return cltest.NewEthMocksWithStartupAssertions(t) } From a01e0a8501abb990c416703b8b5570315f27728e Mon Sep 17 00:00:00 2001 From: krehermann Date: Thu, 21 Sep 2023 16:05:12 -0600 Subject: [PATCH 2/7] proof implicit schema can work with single head tracker test --- core/chains/evm/headtracker/head_tracker_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/chains/evm/headtracker/head_tracker_test.go b/core/chains/evm/headtracker/head_tracker_test.go index 330142b9dc0..7de2c0bc4bc 100644 --- a/core/chains/evm/headtracker/head_tracker_test.go +++ b/core/chains/evm/headtracker/head_tracker_test.go @@ -38,7 +38,7 @@ import ( ) func firstHead(t *testing.T, db *sqlx.DB) (h evmtypes.Head) { - if err := db.Get(&h, `SELECT * FROM evm.heads ORDER BY number ASC LIMIT 1`); err != nil { + if err := db.Get(&h, `SELECT * FROM heads ORDER BY number ASC LIMIT 1`); err != nil { t.Fatal(err) } return h @@ -47,7 +47,7 @@ func firstHead(t *testing.T, db *sqlx.DB) (h evmtypes.Head) { func TestHeadTracker_New(t *testing.T) { t.Parallel() - db := pgtest.NewSqlxDB(t) + db := pgtest.NewEVMScopedDB(t) logger := logger.TestLogger(t) config := configtest.NewGeneralConfig(t, nil) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) @@ -71,7 +71,7 @@ func TestHeadTracker_New(t *testing.T) { func TestHeadTracker_Save_InsertsAndTrimsTable(t *testing.T) { t.Parallel() - db := pgtest.NewSqlxDB(t) + db := pgtest.NewEVMScopedDB(t) logger := logger.TestLogger(t) config := cltest.NewTestChainScopedConfig(t) From 1526b8141548da4af0c97f8f67329a4e49cc7adc Mon Sep 17 00:00:00 2001 From: krehermann Date: Thu, 21 Sep 2023 16:30:45 -0600 Subject: [PATCH 3/7] cleanup for initial feedback review --- core/chains/evm/chain.go | 2 +- core/cmd/shell_local_test.go | 3 +- core/cmd/shell_test.go | 6 +- core/internal/cltest/cltest.go | 3 +- core/internal/testutils/pgtest/pgtest.go | 9 +- .../relayer_chain_interoperators_test.go | 181 +++++++++--------- core/services/chainlink/relayer_factory.go | 43 +++-- core/services/pg/locked_db.go | 27 ++- 8 files changed, 143 insertions(+), 131 deletions(-) diff --git a/core/chains/evm/chain.go b/core/chains/evm/chain.go index 43e47c0035d..c1fd99d9e42 100644 --- a/core/chains/evm/chain.go +++ b/core/chains/evm/chain.go @@ -169,7 +169,7 @@ type RelayerConfig struct { GenGasEstimator func(*big.Int) gas.EvmFeeEstimator } -func (r RelayerConfig) validate() error { +func (r RelayerConfig) Validate() error { var err error if r.AppConfig == nil { err = errors.Join(err, fmt.Errorf("nil AppConfig")) diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go index 73c158cbcc0..aad17f6f9e5 100644 --- a/core/cmd/shell_local_test.go +++ b/core/cmd/shell_local_test.go @@ -41,8 +41,7 @@ import ( func genTestEVMRelayers(t *testing.T, opts evm.ChainRelayExtenderConfig, ks evmrelayer.CSAETHKeystore) *chainlink.CoreRelayerChainInteroperators { f := chainlink.RelayerFactory{ - Logger: opts.Logger, - //DB: opts.DB, + Logger: opts.Logger, QConfig: opts.AppConfig.Database(), LoopRegistry: plugins.NewLoopRegistry(opts.Logger), } diff --git a/core/cmd/shell_test.go b/core/cmd/shell_test.go index c9e96c1df74..2b8cbf14124 100644 --- a/core/cmd/shell_test.go +++ b/core/cmd/shell_test.go @@ -369,8 +369,7 @@ func TestSetupSolanaRelayer(t *testing.T) { }) rf := chainlink.RelayerFactory{ - Logger: lggr, - // DB: pgtest.NewSqlxDB(t), + Logger: lggr, QConfig: tConfig.Database(), LoopRegistry: reg, } @@ -456,8 +455,7 @@ func TestSetupStarkNetRelayer(t *testing.T) { } }) rf := chainlink.RelayerFactory{ - Logger: lggr, - //DB: pgtest.NewSqlxDB(t), + Logger: lggr, QConfig: tConfig.Database(), LoopRegistry: reg, } diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index fb9880ca7ad..1cbfc2137ad 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -386,8 +386,7 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn loopRegistry := plugins.NewLoopRegistry(lggr) relayerFactory := chainlink.RelayerFactory{ - Logger: lggr, - // DB: db, + Logger: lggr, QConfig: cfg.Database(), LoopRegistry: loopRegistry, GRPCOpts: loop.GRPCOpts{}, diff --git a/core/internal/testutils/pgtest/pgtest.go b/core/internal/testutils/pgtest/pgtest.go index 164244b532a..6f8159a5a40 100644 --- a/core/internal/testutils/pgtest/pgtest.go +++ b/core/internal/testutils/pgtest/pgtest.go @@ -3,7 +3,6 @@ package pgtest import ( "database/sql" "encoding/json" - "fmt" "testing" "github.com/google/uuid" @@ -32,15 +31,11 @@ func NewSqlDB(t *testing.T) *sql.DB { } func NewEVMScopedDB(t testing.TB) *sqlx.DB { - // hack to scope to evm schema - url := withSchema(defaultDBURL, "evm") + // hack to scope to evm schema. the value "evm" will need to be dynamic to support multiple relayers + url := pg.SchemaScopedConnection(defaultDBURL, "evm") return NewSqlxDB(t, WithURL(url)) } -func withSchema(conn, schema string) string { - return fmt.Sprintf("%s&options=-csearch_path=%s", conn, schema) -} - func NewSqlxDB(t testing.TB, opts ...ConnectionOpt) *sqlx.DB { testutils.SkipShortDB(t) conn := &pg.ConnectionScope{ diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go index 786e9c55780..e56f99698fd 100644 --- a/core/services/chainlink/relayer_chain_interoperators_test.go +++ b/core/services/chainlink/relayer_chain_interoperators_test.go @@ -173,8 +173,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { lggr := logger.TestLogger(t) factory := chainlink.RelayerFactory{ - Logger: lggr, - //DB: db, + Logger: lggr, QConfig: cfg.Database(), LoopRegistry: plugins.NewLoopRegistry(lggr), GRPCOpts: loop.GRPCOpts{}, @@ -224,109 +223,109 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { }, expectedRelayerNetworks: map[relay.Network]struct{}{relay.EVM: {}}, }, - /* - {name: "2 solana chain with 2 node", - initFuncs: []chainlink.CoreRelayerChainInitFunc{ - chainlink.InitSolana(testctx, factory, chainlink.SolanaFactoryConfig{ - Keystore: keyStore.Solana(), - SolanaConfigs: cfg.SolanaConfigs()}), - }, - expectedSolanaChainCnt: 2, - expectedSolanaNodeCnt: 2, - expectedSolanaRelayerIds: []relay.ID{ - {Network: relay.Solana, ChainID: relay.ChainID(solanaChainID1)}, - {Network: relay.Solana, ChainID: relay.ChainID(solanaChainID2)}, - }, - expectedRelayerNetworks: map[relay.Network]struct{}{relay.Solana: {}}, + {name: "2 solana chain with 2 node", + + initFuncs: []chainlink.CoreRelayerChainInitFunc{ + chainlink.InitSolana(testctx, factory, chainlink.SolanaFactoryConfig{ + Keystore: keyStore.Solana(), + SolanaConfigs: cfg.SolanaConfigs()}), }, + expectedSolanaChainCnt: 2, + expectedSolanaNodeCnt: 2, + expectedSolanaRelayerIds: []relay.ID{ + {Network: relay.Solana, ChainID: relay.ChainID(solanaChainID1)}, + {Network: relay.Solana, ChainID: relay.ChainID(solanaChainID2)}, + }, + expectedRelayerNetworks: map[relay.Network]struct{}{relay.Solana: {}}, + }, - {name: "2 starknet chain with 4 nodes", + {name: "2 starknet chain with 4 nodes", - initFuncs: []chainlink.CoreRelayerChainInitFunc{ - chainlink.InitStarknet(testctx, factory, chainlink.StarkNetFactoryConfig{ - Keystore: keyStore.StarkNet(), - StarknetConfigs: cfg.StarknetConfigs()}), - }, - expectedStarknetChainCnt: 2, - expectedStarknetNodeCnt: 4, - expectedStarknetRelayerIds: []relay.ID{ - {Network: relay.StarkNet, ChainID: relay.ChainID(starknetChainID1)}, - {Network: relay.StarkNet, ChainID: relay.ChainID(starknetChainID2)}, - }, - expectedRelayerNetworks: map[relay.Network]struct{}{relay.StarkNet: {}}, + initFuncs: []chainlink.CoreRelayerChainInitFunc{ + chainlink.InitStarknet(testctx, factory, chainlink.StarkNetFactoryConfig{ + Keystore: keyStore.StarkNet(), + StarknetConfigs: cfg.StarknetConfigs()}), + }, + expectedStarknetChainCnt: 2, + expectedStarknetNodeCnt: 4, + expectedStarknetRelayerIds: []relay.ID{ + {Network: relay.StarkNet, ChainID: relay.ChainID(starknetChainID1)}, + {Network: relay.StarkNet, ChainID: relay.ChainID(starknetChainID2)}, }, + expectedRelayerNetworks: map[relay.Network]struct{}{relay.StarkNet: {}}, + }, - { - name: "2 cosmos chains with 2 nodes", - initFuncs: []chainlink.CoreRelayerChainInitFunc{ - chainlink.InitCosmos(testctx, factory, chainlink.CosmosFactoryConfig{ - Keystore: keyStore.Cosmos(), - CosmosConfigs: cfg.CosmosConfigs(), - EventBroadcaster: pg.NewNullEventBroadcaster()}), - }, - expectedCosmosChainCnt: 2, - expectedCosmosNodeCnt: 2, - expectedCosmosRelayerIds: []relay.ID{ - {Network: relay.Cosmos, ChainID: relay.ChainID(cosmosChainID1)}, - {Network: relay.Cosmos, ChainID: relay.ChainID(cosmosChainID2)}, - }, - expectedRelayerNetworks: map[relay.Network]struct{}{relay.Cosmos: {}}, + { + name: "2 cosmos chains with 2 nodes", + initFuncs: []chainlink.CoreRelayerChainInitFunc{ + chainlink.InitCosmos(testctx, factory, chainlink.CosmosFactoryConfig{ + Keystore: keyStore.Cosmos(), + CosmosConfigs: cfg.CosmosConfigs(), + EventBroadcaster: pg.NewNullEventBroadcaster()}), + }, + expectedCosmosChainCnt: 2, + expectedCosmosNodeCnt: 2, + expectedCosmosRelayerIds: []relay.ID{ + {Network: relay.Cosmos, ChainID: relay.ChainID(cosmosChainID1)}, + {Network: relay.Cosmos, ChainID: relay.ChainID(cosmosChainID2)}, }, + expectedRelayerNetworks: map[relay.Network]struct{}{relay.Cosmos: {}}, + }, - {name: "all chains", + {name: "all chains", - initFuncs: []chainlink.CoreRelayerChainInitFunc{chainlink.InitSolana(testctx, factory, chainlink.SolanaFactoryConfig{ - Keystore: keyStore.Solana(), - SolanaConfigs: cfg.SolanaConfigs()}), - chainlink.InitEVM(testctx, factory, chainlink.EVMFactoryConfig{ - RelayerConfig: &evm.RelayerConfig{ - AppConfig: cfg, - EventBroadcaster: pg.NewNullEventBroadcaster(), - MailMon: &utils.MailboxMonitor{}, - }, - CSAETHKeystore: keyStore, - }), - chainlink.InitStarknet(testctx, factory, chainlink.StarkNetFactoryConfig{ - Keystore: keyStore.StarkNet(), - StarknetConfigs: cfg.StarknetConfigs()}), - chainlink.InitCosmos(testctx, factory, chainlink.CosmosFactoryConfig{ - Keystore: keyStore.Cosmos(), - CosmosConfigs: cfg.CosmosConfigs(), + initFuncs: []chainlink.CoreRelayerChainInitFunc{chainlink.InitSolana(testctx, factory, chainlink.SolanaFactoryConfig{ + Keystore: keyStore.Solana(), + SolanaConfigs: cfg.SolanaConfigs()}), + chainlink.InitEVM(testctx, factory, chainlink.EVMFactoryConfig{ + RelayerConfig: &evm.RelayerConfig{ + AppConfig: cfg, EventBroadcaster: pg.NewNullEventBroadcaster(), - }), - }, - expectedEVMChainCnt: 2, - expectedEVMNodeCnt: 3, - expectedEVMRelayerIds: []relay.ID{ - {Network: relay.EVM, ChainID: relay.ChainID(evmChainID1.String())}, - {Network: relay.EVM, ChainID: relay.ChainID(evmChainID2.String())}, - }, - - expectedSolanaChainCnt: 2, - expectedSolanaNodeCnt: 2, - expectedSolanaRelayerIds: []relay.ID{ - {Network: relay.Solana, ChainID: relay.ChainID(solanaChainID1)}, - {Network: relay.Solana, ChainID: relay.ChainID(solanaChainID2)}, - }, + MailMon: &utils.MailboxMonitor{}, + DB: pgtest.NewEVMScopedDB(t), + }, + CSAETHKeystore: keyStore, + }), + chainlink.InitStarknet(testctx, factory, chainlink.StarkNetFactoryConfig{ + Keystore: keyStore.StarkNet(), + StarknetConfigs: cfg.StarknetConfigs()}), + chainlink.InitCosmos(testctx, factory, chainlink.CosmosFactoryConfig{ + Keystore: keyStore.Cosmos(), + CosmosConfigs: cfg.CosmosConfigs(), + EventBroadcaster: pg.NewNullEventBroadcaster(), + }), + }, + expectedEVMChainCnt: 2, + expectedEVMNodeCnt: 3, + expectedEVMRelayerIds: []relay.ID{ + {Network: relay.EVM, ChainID: relay.ChainID(evmChainID1.String())}, + {Network: relay.EVM, ChainID: relay.ChainID(evmChainID2.String())}, + }, - expectedStarknetChainCnt: 2, - expectedStarknetNodeCnt: 4, - expectedStarknetRelayerIds: []relay.ID{ - {Network: relay.StarkNet, ChainID: relay.ChainID(starknetChainID1)}, - {Network: relay.StarkNet, ChainID: relay.ChainID(starknetChainID2)}, - }, + expectedSolanaChainCnt: 2, + expectedSolanaNodeCnt: 2, + expectedSolanaRelayerIds: []relay.ID{ + {Network: relay.Solana, ChainID: relay.ChainID(solanaChainID1)}, + {Network: relay.Solana, ChainID: relay.ChainID(solanaChainID2)}, + }, - expectedCosmosChainCnt: 2, - expectedCosmosNodeCnt: 2, - expectedCosmosRelayerIds: []relay.ID{ - {Network: relay.Cosmos, ChainID: relay.ChainID(cosmosChainID1)}, - {Network: relay.Cosmos, ChainID: relay.ChainID(cosmosChainID2)}, - }, + expectedStarknetChainCnt: 2, + expectedStarknetNodeCnt: 4, + expectedStarknetRelayerIds: []relay.ID{ + {Network: relay.StarkNet, ChainID: relay.ChainID(starknetChainID1)}, + {Network: relay.StarkNet, ChainID: relay.ChainID(starknetChainID2)}, + }, - expectedRelayerNetworks: map[relay.Network]struct{}{relay.EVM: {}, relay.Cosmos: {}, relay.Solana: {}, relay.StarkNet: {}}, + expectedCosmosChainCnt: 2, + expectedCosmosNodeCnt: 2, + expectedCosmosRelayerIds: []relay.ID{ + {Network: relay.Cosmos, ChainID: relay.ChainID(cosmosChainID1)}, + {Network: relay.Cosmos, ChainID: relay.ChainID(cosmosChainID2)}, }, - */ + + expectedRelayerNetworks: map[relay.Network]struct{}{relay.EVM: {}, relay.Cosmos: {}, relay.Solana: {}, relay.StarkNet: {}}, + }, } for _, tt := range tests { tt := tt diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go index 17c2f07ffac..a06c4d029e5 100644 --- a/core/services/chainlink/relayer_factory.go +++ b/core/services/chainlink/relayer_factory.go @@ -2,6 +2,7 @@ package chainlink import ( "context" + "errors" "fmt" "github.com/pelletier/go-toml/v2" @@ -37,18 +38,30 @@ type EVMFactoryConfig struct { evmrelay.CSAETHKeystore } +// TODO plumb the generic validator here maybe +func (c EVMFactoryConfig) Validate() error { + var err error + if c.RelayerConfig == nil { + err = errors.Join(err, fmt.Errorf("nil RelayerConfig")) + } else { + err = errors.Join(err, c.RelayerConfig.Validate()) + } + if c.CSAETHKeystore == nil { + err = errors.Join(err, fmt.Errorf("nil CSAETH Keystore")) + } + if err != nil { + err = fmt.Errorf("invalid EVMFactoryConfig: %w", err) + } + return err +} + func (r *RelayerFactory) NewEVM(ctx context.Context, config EVMFactoryConfig) (map[relay.ID]evmrelay.LoopRelayAdapter, error) { // TODO impl EVM loop. For now always 'fallback' to an adapter and embedded chain - /* - if config.DBConn == "" { - u := config.AppConfig.Database().URL() - config.DBConn = withSchema((&u).String(), "evm") - } - db, err := sqlx.Open(string(dialects.Postgres), config.DBConn) - if err != nil { - return nil, err - } - */ + + err := config.Validate() + if err != nil { + return nil, err + } relayers := make(map[relay.ID]evmrelay.LoopRelayAdapter) // override some common opts with the factory values. this seems weird... maybe other signatures should change, or this should take a different type... @@ -220,12 +233,6 @@ type CosmosFactoryConfig struct { } func (r *RelayerFactory) NewCosmos(ctx context.Context, config CosmosFactoryConfig) (map[relay.ID]cosmos.LoopRelayerChainer, error) { - /* - db, err := sqlx.Open(string(dialects.Postgres), config.DBConn) - if err != nil { - return nil, err - } - */ relayers := make(map[relay.ID]cosmos.LoopRelayerChainer) var ( @@ -255,7 +262,3 @@ func (r *RelayerFactory) NewCosmos(ctx context.Context, config CosmosFactoryConf return relayers, nil } - -func withSchema(conn, schema string) string { - return fmt.Sprintf("%s&options=-csearch_path=%s", conn, schema) -} diff --git a/core/services/pg/locked_db.go b/core/services/pg/locked_db.go index 627ce0f82cd..c213d590eb4 100644 --- a/core/services/pg/locked_db.go +++ b/core/services/pg/locked_db.go @@ -2,8 +2,8 @@ package pg import ( "context" - "fmt" "net/url" + "strings" "time" "github.com/google/uuid" @@ -154,13 +154,32 @@ func openDB(appID uuid.UUID, cfg LockedDBConfig, opts ...ConnectionOpt) (db *sql type ConnectionOpt func(*string) +// WithSchema scopes the current url connection string to the given schema func WithSchema(schema string) ConnectionOpt { return func(url *string) { - u := withSchema(*url, schema) + u := SchemaScopedConnection(*url, schema) url = &u } } -func withSchema(conn, schema string) string { - return fmt.Sprintf("%s&options=-csearch_path=%s", conn, schema) +// WithURL sets the url connection string +func WithURL(override string) ConnectionOpt { + return func(url *string) { + url = &override + } +} + +func SchemaScopedConnection(conn, schema string) string { + // documentation on this options is limited; find by searching the official postgres docs + // https://www.postgresql.org/docs/16/app-psql.html + + //TODO real parsing for connection query string + opt := "options=-csearch_path=" + schema + // assume the conn has a query string that we can append to + seperator := "&" + if !strings.Contains(conn, "?") { + // no query string, so make one + seperator = "?" + } + return conn + seperator + opt } From cfb1c1b949116667aa6e5450e8ddf17b67df3709 Mon Sep 17 00:00:00 2001 From: krehermann Date: Tue, 26 Sep 2023 10:39:16 -0600 Subject: [PATCH 4/7] refactor txdb and opts to use URLs --- .../evm/headtracker/head_tracker_test.go | 8 +- core/cmd/shell_local_test.go | 4 +- core/internal/cltest/cltest.go | 3 +- core/internal/testutils/evmtest/evmtest.go | 10 +++ core/internal/testutils/pgtest/pgtest.go | 33 ++++---- core/internal/testutils/pgtest/txdb.go | 75 +++++++++++-------- .../relayer_chain_interoperators_test.go | 5 +- core/services/pg/connection.go | 20 ++--- core/services/pg/locked_db.go | 38 +++++----- .../relay/evm/relayer_extender_test.go | 2 +- 10 files changed, 109 insertions(+), 89 deletions(-) diff --git a/core/chains/evm/headtracker/head_tracker_test.go b/core/chains/evm/headtracker/head_tracker_test.go index 7de2c0bc4bc..ad582f4fb93 100644 --- a/core/chains/evm/headtracker/head_tracker_test.go +++ b/core/chains/evm/headtracker/head_tracker_test.go @@ -47,9 +47,9 @@ func firstHead(t *testing.T, db *sqlx.DB) (h evmtypes.Head) { func TestHeadTracker_New(t *testing.T) { t.Parallel() - db := pgtest.NewEVMScopedDB(t) + config := cltest.NewTestChainScopedConfig(t) + db := evmtest.NewScopedDB(t, config.Database()) logger := logger.TestLogger(t) - config := configtest.NewGeneralConfig(t, nil) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(cltest.Head(0), nil) @@ -71,9 +71,9 @@ func TestHeadTracker_New(t *testing.T) { func TestHeadTracker_Save_InsertsAndTrimsTable(t *testing.T) { t.Parallel() - db := pgtest.NewEVMScopedDB(t) - logger := logger.TestLogger(t) config := cltest.NewTestChainScopedConfig(t) + db := evmtest.NewScopedDB(t, config.Database()) + logger := logger.TestLogger(t) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) orm := headtracker.NewORM(db, logger, config.Database(), cltest.FixtureChainID) diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go index ac166111b59..f54cf7d6e9a 100644 --- a/core/cmd/shell_local_test.go +++ b/core/cmd/shell_local_test.go @@ -90,7 +90,7 @@ func TestShell_RunNodeWithPasswords(t *testing.T) { AppConfig: cfg, EventBroadcaster: pg.NewNullEventBroadcaster(), MailMon: &utils.MailboxMonitor{}, - DB: pgtest.NewEVMScopedDB(t), + DB: evmtest.NewScopedDB(t, cfg.Database()), }, } testRelayers := genTestEVMRelayers(t, opts, keyStore) @@ -195,7 +195,7 @@ func TestShell_RunNodeWithAPICredentialsFile(t *testing.T) { EventBroadcaster: pg.NewNullEventBroadcaster(), MailMon: &utils.MailboxMonitor{}, - DB: pgtest.NewEVMScopedDB(t), + DB: evmtest.NewScopedDB(t, cfg.Database()), }, } testRelayers := genTestEVMRelayers(t, opts, keyStore) diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index e28982a7819..662ee7de452 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -64,7 +64,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" clhttptest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/httptest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/keystest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/logger/audit" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -396,7 +395,7 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn AppConfig: cfg, EventBroadcaster: eventBroadcaster, MailMon: mailMon, - DB: pgtest.NewEVMScopedDB(t), + DB: evmtest.NewScopedDB(t, cfg.Database()), }, CSAETHKeystore: keyStore, } diff --git a/core/internal/testutils/evmtest/evmtest.go b/core/internal/testutils/evmtest/evmtest.go index 2a86101d0d8..2332de24dc3 100644 --- a/core/internal/testutils/evmtest/evmtest.go +++ b/core/internal/testutils/evmtest/evmtest.go @@ -12,6 +12,7 @@ import ( "github.com/smartcontractkit/sqlx" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "github.com/test-go/testify/assert" "golang.org/x/exp/slices" "gopkg.in/guregu/null.v4" @@ -30,7 +31,9 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/pg" @@ -368,3 +371,10 @@ func (r *RawSub[T]) TrySend(t T) { case r.ch <- t: } } + +func NewScopedDB(t testing.TB, cfg config.Database) *sqlx.DB { + // hack to scope to evm schema. the value "evm" will need to be dynamic to support multiple relayers + url, err := pg.SchemaScopedConnection(cfg.URL(), "evm") + assert.NoError(t, err, "failed to create evm scoped db") + return pgtest.NewSqlxDB(t, pgtest.WithURL(*url)) +} diff --git a/core/internal/testutils/pgtest/pgtest.go b/core/internal/testutils/pgtest/pgtest.go index 6f8159a5a40..f47a1853599 100644 --- a/core/internal/testutils/pgtest/pgtest.go +++ b/core/internal/testutils/pgtest/pgtest.go @@ -2,7 +2,7 @@ package pgtest import ( "database/sql" - "encoding/json" + "net/url" "testing" "github.com/google/uuid" @@ -30,24 +30,23 @@ func NewSqlDB(t *testing.T) *sql.DB { return db } -func NewEVMScopedDB(t testing.TB) *sqlx.DB { - // hack to scope to evm schema. the value "evm" will need to be dynamic to support multiple relayers - url := pg.SchemaScopedConnection(defaultDBURL, "evm") - return NewSqlxDB(t, WithURL(url)) +func uniqueConnection(t testing.TB) *url.URL { + url := testutils.MustParseURL(t, defaultDBURL.String()) + // inject uuid by default because the transaction wrapped driver requires it + q := url.Query() + q.Add("uuid", uuid.New().String()) + url.RawQuery = q.Encode() + return url } func NewSqlxDB(t testing.TB, opts ...ConnectionOpt) *sqlx.DB { testutils.SkipShortDB(t) - conn := &pg.ConnectionScope{ - UUID: uuid.New().String(), - URL: defaultDBURL, - } + + url := uniqueConnection(t) for _, opt := range opts { - opt(conn) + opt(url) } - enc, err := json.Marshal(conn) - require.NoError(t, err) - db, err := sqlx.Open(string(dialects.TransactionWrappedPostgres), string(enc)) + db, err := sqlx.Open(string(dialects.TransactionWrappedPostgres), url.String()) require.NoError(t, err) t.Cleanup(func() { assert.NoError(t, db.Close()) }) @@ -56,11 +55,11 @@ func NewSqlxDB(t testing.TB, opts ...ConnectionOpt) *sqlx.DB { return db } -type ConnectionOpt func(conn *pg.ConnectionScope) +type ConnectionOpt func(*url.URL) -func WithURL(url string) ConnectionOpt { - return func(conn *pg.ConnectionScope) { - conn.URL = url +func WithURL(override url.URL) ConnectionOpt { + return func(u *url.URL) { + u = &override } } diff --git a/core/internal/testutils/pgtest/txdb.go b/core/internal/testutils/pgtest/txdb.go index 31587fda23d..4f1273121d2 100644 --- a/core/internal/testutils/pgtest/txdb.go +++ b/core/internal/testutils/pgtest/txdb.go @@ -4,7 +4,6 @@ import ( "context" "database/sql" "database/sql/driver" - "encoding/json" "flag" "fmt" "io" @@ -37,7 +36,7 @@ import ( // store to use the raw DialectPostgres dialect and setup a one-use database. // See heavyweight.FullTestDB() as a convenience function to help you do this, // but please use sparingly because as it's name implies, it is expensive. -var defaultDBURL string // global used to create a [NewSqlxDB] +var defaultDBURL *url.URL // global used to create a [NewSqlxDB] func init() { testing.Init() if !flag.Parsed() { @@ -47,26 +46,25 @@ func init() { // -short tests don't need a DB return } - defaultDBURL = string(env.DatabaseURL.Get()) - if defaultDBURL == "" { + envDBURL := string(env.DatabaseURL.Get()) + if envDBURL == "" { panic("you must provide a CL_DATABASE_URL environment variable") } - - parsed, err := url.Parse(defaultDBURL) + var err error + defaultDBURL, err = url.Parse(envDBURL) if err != nil { panic(err) } - if parsed.Path == "" { - msg := fmt.Sprintf("invalid %[1]s: `%[2]s`. You must set %[1]s env var to point to your test database. Note that the test database MUST end in `_test` to differentiate from a possible production DB. HINT: Try %[1]s=postgresql://postgres@localhost:5432/chainlink_test?sslmode=disable", env.DatabaseURL, parsed.String()) + if defaultDBURL.Path == "" { + msg := fmt.Sprintf("invalid %[1]s: `%[2]s`. You must set %[1]s env var to point to your test database. Note that the test database MUST end in `_test` to differentiate from a possible production DB. HINT: Try %[1]s=postgresql://postgres@localhost:5432/chainlink_test?sslmode=disable", env.DatabaseURL, defaultDBURL.String()) panic(msg) } - if !strings.HasSuffix(parsed.Path, "_test") { - msg := fmt.Sprintf("cannot run tests against database named `%s`. Note that the test database MUST end in `_test` to differentiate from a possible production DB. HINT: Try %s=postgresql://postgres@localhost:5432/chainlink_test?sslmode=disable", parsed.Path[1:], env.DatabaseURL) + if !strings.HasSuffix(defaultDBURL.Path, "_test") { + msg := fmt.Sprintf("cannot run tests against database named `%s`. Note that the test database MUST end in `_test` to differentiate from a possible production DB. HINT: Try %s=postgresql://postgres@localhost:5432/chainlink_test?sslmode=disable", defaultDBURL.Path[1:], env.DatabaseURL) panic(msg) } name := string(dialects.TransactionWrappedPostgres) sql.Register(name, &txDriver{ - dbURL: defaultDBURL, conns: make(map[string]map[string]*conn), }) sqlx.BindDriver(name, sqlx.DOLLAR) @@ -80,45 +78,60 @@ type txDriver struct { sync.Mutex db map[string]*sql.DB // url -> db conns map[string]map[string]*conn // url -> (uuid -> db) so we can close per url - - dbURL string } -// jsonConnectionScope must be a json-encoded [ConnectionScope]. The Open interface requires -// a string -func (d *txDriver) Open(jsonConnectionScope string) (driver.Conn, error) { +func cleanseURL(u *url.URL) { + q := u.Query() + q.Del("uuid") + u.RawQuery = q.Encode() + +} +func (d *txDriver) Open(connection string) (driver.Conn, error) { d.Lock() defer d.Unlock() - var scope pg.ConnectionScope - err := json.Unmarshal([]byte(jsonConnectionScope), &scope) + + dbURL, err := url.Parse(connection) if err != nil { - return nil, fmt.Errorf("pgtest tx driver failed to parse connection string %s: must be json encoded scope: %w", jsonConnectionScope, err) + return nil, fmt.Errorf("pgtest tx driver failed to parse connection string %s: %w", connection, err) + } + + // tx db requires client connection to self-identify a uuid for connection routing + // extract in and track the resulting url for scoping connections + queryVals := dbURL.Query() + uuid := queryVals.Get("uuid") + if uuid == "" { + return nil, fmt.Errorf("txdb can open connection: missing `uuid` query parameter in connection string %s", connection) } + queryVals.Del("uuid") + dbURL.RawQuery = queryVals.Encode() // encode is sorted + + endpt := dbURL.String() + // initialize dbs if the first call if d.db == nil { d.db = make(map[string]*sql.DB) } - db, exists := d.db[scope.URL] + db, exists := d.db[endpt] if !exists { - db, err = sql.Open("pgx", scope.URL) + db, err = sql.Open("pgx", endpt) if err != nil { return nil, err } - d.db[scope.URL] = db - d.conns[scope.URL] = make(map[string]*conn) + d.db[endpt] = db + d.conns[endpt] = make(map[string]*conn) } - c, exists := d.conns[scope.URL][scope.UUID] + c, exists := d.conns[endpt][uuid] if !exists || !c.tryOpen() { tx, err := db.Begin() if err != nil { return nil, err } - c = &conn{tx: tx, opened: 1, scope: scope} + c = &conn{tx: tx, opened: 1, scope: pg.ConnectionScope{Endpoint: endpt, UUID: uuid}} c.removeSelf = func() error { return d.deleteConn(c) } - d.conns[scope.URL][scope.UUID] = c + d.conns[endpt][uuid] = c } return c, nil } @@ -130,15 +143,15 @@ func (d *txDriver) deleteConn(c *conn) error { d.Lock() defer d.Unlock() - if d.conns[c.scope.URL][c.scope.UUID] != c { + if d.conns[c.scope.Endpoint][c.scope.UUID] != c { return nil // already been replaced } - delete(d.conns[c.scope.URL], c.scope.UUID) - if len(d.conns[c.scope.URL]) == 0 && d.db[c.scope.URL] != nil { - if err := d.db[c.scope.URL].Close(); err != nil { + delete(d.conns[c.scope.Endpoint], c.scope.UUID) + if len(d.conns[c.scope.Endpoint]) == 0 && d.db[c.scope.Endpoint] != nil { + if err := d.db[c.scope.Endpoint].Close(); err != nil { return err } - delete(d.db, c.scope.URL) + delete(d.db, c.scope.Endpoint) } return nil } diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go index ef949c5f6da..409f828d098 100644 --- a/core/services/chainlink/relayer_chain_interoperators_test.go +++ b/core/services/chainlink/relayer_chain_interoperators_test.go @@ -21,6 +21,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/starknet" "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/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -209,7 +210,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { AppConfig: cfg, EventBroadcaster: pg.NewNullEventBroadcaster(), MailMon: &utils.MailboxMonitor{}, - DB: pgtest.NewEVMScopedDB(t), + DB: evmtest.NewScopedDB(t, cfg.Database()), }, CSAETHKeystore: keyStore, }), @@ -284,7 +285,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { AppConfig: cfg, EventBroadcaster: pg.NewNullEventBroadcaster(), MailMon: &utils.MailboxMonitor{}, - DB: pgtest.NewEVMScopedDB(t), + DB: evmtest.NewScopedDB(t, cfg.Database()), }, CSAETHKeystore: keyStore, }), diff --git a/core/services/pg/connection.go b/core/services/pg/connection.go index 80e3266690a..be48f40654e 100644 --- a/core/services/pg/connection.go +++ b/core/services/pg/connection.go @@ -1,8 +1,8 @@ package pg import ( - "encoding/json" "fmt" + "net/url" "time" "github.com/google/uuid" @@ -21,8 +21,8 @@ type ConnectionConfig interface { } type ConnectionScope struct { - URL string - UUID string + Endpoint string + UUID string } func NewConnection(uri string, dialect dialects.DialectName, config ConnectionConfig) (db *sqlx.DB, err error) { @@ -31,18 +31,14 @@ func NewConnection(uri string, dialect dialects.DialectName, config ConnectionCo // should be encapsulated in it's own transaction, and thus needs its own // unique id. // - // We can happily throw away the original uri here because if we are using - // txdb it should have already been set at the point where we called - // txdb.Register - s := ConnectionScope{ - URL: uri, - UUID: uuid.New().String(), - } - b, err := json.Marshal(&s) + u, err := url.Parse(uri) if err != nil { return nil, err } - uri = string(b) + q := u.Query() + q.Add("uuid", uuid.New().String()) + u.RawQuery = q.Encode() + uri = u.String() } // Initialize sql/sqlx diff --git a/core/services/pg/locked_db.go b/core/services/pg/locked_db.go index c213d590eb4..fae5bfa88e5 100644 --- a/core/services/pg/locked_db.go +++ b/core/services/pg/locked_db.go @@ -3,7 +3,6 @@ package pg import ( "context" "net/url" - "strings" "time" "github.com/google/uuid" @@ -142,44 +141,47 @@ func (l lockedDb) DB() *sqlx.DB { func openDB(appID uuid.UUID, cfg LockedDBConfig, opts ...ConnectionOpt) (db *sqlx.DB, err error) { uri := cfg.URL() + static.SetConsumerName(&uri, "App", &appID) dialect := cfg.Dialect() - connStr := uri.String() for _, opt := range opts { - opt(&connStr) + opt(&uri) } - db, err = NewConnection(connStr, dialect, cfg) + db, err = NewConnection(uri.String(), dialect, cfg) return } -type ConnectionOpt func(*string) +type ConnectionOpt func(*url.URL) error // WithSchema scopes the current url connection string to the given schema func WithSchema(schema string) ConnectionOpt { - return func(url *string) { - u := SchemaScopedConnection(*url, schema) - url = &u + return func(url *url.URL) (err error) { + url, err = SchemaScopedConnection(*url, schema) + return } } // WithURL sets the url connection string func WithURL(override string) ConnectionOpt { - return func(url *string) { - url = &override + return func(url *url.URL) (err error) { + url, err = url.Parse(override) + return } } -func SchemaScopedConnection(conn, schema string) string { +func SchemaScopedConnection(conn url.URL, schema string) (*url.URL, error) { // documentation on this options is limited; find by searching the official postgres docs // https://www.postgresql.org/docs/16/app-psql.html //TODO real parsing for connection query string - opt := "options=-csearch_path=" + schema - // assume the conn has a query string that we can append to - seperator := "&" - if !strings.Contains(conn, "?") { - // no query string, so make one - seperator = "?" + opt := "options=-csearch_path=" + u, err := url.Parse(conn.String()) + if err != nil { + return nil, err } - return conn + seperator + opt + queryVals := u.Query() + queryVals.Add(opt, schema) + + u.RawQuery = queryVals.Encode() + return u, nil } diff --git a/core/services/relay/evm/relayer_extender_test.go b/core/services/relay/evm/relayer_extender_test.go index 5c237ce2cbd..dc8433d4f0f 100644 --- a/core/services/relay/evm/relayer_extender_test.go +++ b/core/services/relay/evm/relayer_extender_test.go @@ -34,7 +34,7 @@ func TestChainRelayExtenders(t *testing.T) { kst := cltest.NewKeyStore(t, db, cfg.Database()) require.NoError(t, kst.Unlock(cltest.Password)) - opts := evmtest.NewChainRelayExtOpts(t, evmtest.TestChainOpts{DB: pgtest.NewEVMScopedDB(t), KeyStore: kst.Eth(), GeneralConfig: cfg}) + opts := evmtest.NewChainRelayExtOpts(t, evmtest.TestChainOpts{DB: evmtest.NewScopedDB(t, cfg.Database()), KeyStore: kst.Eth(), GeneralConfig: cfg}) opts.GenEthClient = func(*big.Int) evmclient.Client { return cltest.NewEthMocksWithStartupAssertions(t) } From 832e137b4bb11af393aa50c4f10955092ff5d57f Mon Sep 17 00:00:00 2001 From: krehermann Date: Tue, 26 Sep 2023 11:57:54 -0600 Subject: [PATCH 5/7] move test code --- core/internal/testutils/evmtest/evmtest.go | 7 ++---- core/internal/testutils/pgtest/pgtest.go | 12 ++--------- core/internal/testutils/pgtest/txdb.go | 6 ------ core/services/pg/locked_db.go | 25 ++++++++++------------ core/services/pg/locked_db_test.go | 14 ++++++++++++ 5 files changed, 29 insertions(+), 35 deletions(-) diff --git a/core/internal/testutils/evmtest/evmtest.go b/core/internal/testutils/evmtest/evmtest.go index 2332de24dc3..fa7023ee2cb 100644 --- a/core/internal/testutils/evmtest/evmtest.go +++ b/core/internal/testutils/evmtest/evmtest.go @@ -12,7 +12,6 @@ import ( "github.com/smartcontractkit/sqlx" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - "github.com/test-go/testify/assert" "golang.org/x/exp/slices" "gopkg.in/guregu/null.v4" @@ -373,8 +372,6 @@ func (r *RawSub[T]) TrySend(t T) { } func NewScopedDB(t testing.TB, cfg config.Database) *sqlx.DB { - // hack to scope to evm schema. the value "evm" will need to be dynamic to support multiple relayers - url, err := pg.SchemaScopedConnection(cfg.URL(), "evm") - assert.NoError(t, err, "failed to create evm scoped db") - return pgtest.NewSqlxDB(t, pgtest.WithURL(*url)) + u := pg.SchemaScopedConnection(cfg.URL(), "evm") + return pgtest.NewSqlxDB(t, pg.WithURL(u)) } diff --git a/core/internal/testutils/pgtest/pgtest.go b/core/internal/testutils/pgtest/pgtest.go index f47a1853599..a9adbe12da5 100644 --- a/core/internal/testutils/pgtest/pgtest.go +++ b/core/internal/testutils/pgtest/pgtest.go @@ -39,12 +39,12 @@ func uniqueConnection(t testing.TB) *url.URL { return url } -func NewSqlxDB(t testing.TB, opts ...ConnectionOpt) *sqlx.DB { +func NewSqlxDB(t testing.TB, opts ...pg.ConnectionOpt) *sqlx.DB { testutils.SkipShortDB(t) url := uniqueConnection(t) for _, opt := range opts { - opt(url) + assert.NoError(t, opt(url)) } db, err := sqlx.Open(string(dialects.TransactionWrappedPostgres), url.String()) require.NoError(t, err) @@ -55,14 +55,6 @@ func NewSqlxDB(t testing.TB, opts ...ConnectionOpt) *sqlx.DB { return db } -type ConnectionOpt func(*url.URL) - -func WithURL(override url.URL) ConnectionOpt { - return func(u *url.URL) { - u = &override - } -} - func MustExec(t *testing.T, db *sqlx.DB, stmt string, args ...interface{}) { require.NoError(t, utils.JustError(db.Exec(stmt, args...))) } diff --git a/core/internal/testutils/pgtest/txdb.go b/core/internal/testutils/pgtest/txdb.go index 4f1273121d2..7f008247229 100644 --- a/core/internal/testutils/pgtest/txdb.go +++ b/core/internal/testutils/pgtest/txdb.go @@ -80,12 +80,6 @@ type txDriver struct { conns map[string]map[string]*conn // url -> (uuid -> db) so we can close per url } -func cleanseURL(u *url.URL) { - q := u.Query() - q.Del("uuid") - u.RawQuery = q.Encode() - -} func (d *txDriver) Open(connection string) (driver.Conn, error) { d.Lock() defer d.Unlock() diff --git a/core/services/pg/locked_db.go b/core/services/pg/locked_db.go index fae5bfa88e5..f4f8bfa3b36 100644 --- a/core/services/pg/locked_db.go +++ b/core/services/pg/locked_db.go @@ -2,11 +2,12 @@ package pg import ( "context" + "errors" + "fmt" "net/url" "time" "github.com/google/uuid" - "github.com/pkg/errors" "github.com/smartcontractkit/sqlx" @@ -71,7 +72,7 @@ func (l *lockedDb) Open(ctx context.Context, opts ...ConnectionOpt) (err error) l.db, err = openDB(l.appID, l.cfg) if err != nil { // l.db will be nil in case of error - return errors.Wrap(err, "failed to open db") + return fmt.Errorf("failed to open db: %w", err) } revert := func() { // Let Open() return the actual error, while l.Close() error is just logged. @@ -99,7 +100,7 @@ func (l *lockedDb) Open(ctx context.Context, opts ...ConnectionOpt) (err error) l.leaseLock = NewLeaseLock(l.db, l.appID, l.lggr, cfg) if err = l.leaseLock.TakeAndHold(ctx); err != nil { defer revert() - return errors.Wrap(err, "failed to take initial lease on database") + return fmt.Errorf("failed to take initial lease on database: %w", err) } } @@ -145,7 +146,7 @@ func openDB(appID uuid.UUID, cfg LockedDBConfig, opts ...ConnectionOpt) (db *sql static.SetConsumerName(&uri, "App", &appID) dialect := cfg.Dialect() for _, opt := range opts { - opt(&uri) + err = errors.Join(err, opt(&uri)) } db, err = NewConnection(uri.String(), dialect, cfg) return @@ -156,32 +157,28 @@ type ConnectionOpt func(*url.URL) error // WithSchema scopes the current url connection string to the given schema func WithSchema(schema string) ConnectionOpt { return func(url *url.URL) (err error) { - url, err = SchemaScopedConnection(*url, schema) + *url = SchemaScopedConnection(*url, schema) return } } // WithURL sets the url connection string -func WithURL(override string) ConnectionOpt { +func WithURL(override url.URL) ConnectionOpt { return func(url *url.URL) (err error) { - url, err = url.Parse(override) + (*url) = override return } } -func SchemaScopedConnection(conn url.URL, schema string) (*url.URL, error) { +func SchemaScopedConnection(conn url.URL, schema string) url.URL { // documentation on this options is limited; find by searching the official postgres docs // https://www.postgresql.org/docs/16/app-psql.html - //TODO real parsing for connection query string + u := conn opt := "options=-csearch_path=" - u, err := url.Parse(conn.String()) - if err != nil { - return nil, err - } queryVals := u.Query() queryVals.Add(opt, schema) u.RawQuery = queryVals.Encode() - return u, nil + return u } diff --git a/core/services/pg/locked_db_test.go b/core/services/pg/locked_db_test.go index aaf7ebf32c4..6f1007378f0 100644 --- a/core/services/pg/locked_db_test.go +++ b/core/services/pg/locked_db_test.go @@ -2,9 +2,12 @@ package pg_test import ( "context" + "net/url" "testing" "time" + "github.com/test-go/testify/assert" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -102,3 +105,14 @@ func TestOpenUnlockedDB(t *testing.T) { require.NoError(t, db1.Close()) require.NoError(t, db2.Close()) } + +func TestConnectionOpt(t *testing.T) { + t.Parallel() + + url := new(url.URL) + override, err := url.Parse("postgres://postgres:password@localhost:5432/chainlink_dev_test?sslmode=disable") + require.NoError(t, err) + pg.WithURL(*override)(url) + + assert.EqualValues(t, override, url) +} From a86f233e75e45e601e0680df156afdb4b2d02e53 Mon Sep 17 00:00:00 2001 From: krehermann Date: Tue, 26 Sep 2023 19:08:46 -0600 Subject: [PATCH 6/7] WIP: add evm-scoped db type to ensure that services are not violating db boundaries. hint: they are and it's painful --- core/chains/evm/chain.go | 6 +- core/chains/evm/db/db.go | 39 +++++ core/chains/evm/evm_txm.go | 5 +- .../evm/forwarders/forwarder_manager.go | 4 +- .../evm/forwarders/forwarder_manager_test.go | 5 +- core/chains/evm/forwarders/orm.go | 5 +- core/chains/evm/forwarders/orm_test.go | 17 ++- .../evm/headtracker/head_broadcaster_test.go | 6 +- .../chains/evm/headtracker/head_saver_test.go | 7 +- .../evm/headtracker/head_tracker_test.go | 80 +++++----- core/chains/evm/headtracker/orm.go | 19 ++- core/chains/evm/headtracker/orm_test.go | 34 ++--- core/chains/evm/legacy_container.go | 37 +++++ core/chains/evm/log/orm.go | 7 +- .../evm/logpoller/observability_test.go | 6 +- core/chains/evm/logpoller/orm.go | 143 +++++++++--------- core/chains/evm/txmgr/builder.go | 5 +- core/chains/evm/txmgr/evm_tx_store.go | 5 +- core/cmd/ocr2vrf_configure_commands.go | 7 +- core/cmd/shell.go | 3 +- core/cmd/shell_local.go | 8 +- core/cmd/shell_local_test.go | 5 +- core/internal/cltest/cltest.go | 8 +- core/internal/cltest/factories.go | 3 +- core/internal/cltest/heavyweight/orm.go | 9 +- core/internal/cltest/job_factories.go | 4 +- core/internal/features/features_test.go | 10 +- .../features/ocr2/features_ocr2_test.go | 2 +- core/internal/testutils/evmtest/db/dbtest.go | 15 ++ core/internal/testutils/evmtest/evmtest.go | 12 +- core/internal/testutils/pgtest/pgtest.go | 22 +-- core/services/blockhashstore/bhs_test.go | 10 +- core/services/blockhashstore/delegate_test.go | 8 +- core/services/chainlink/application.go | 24 ++- .../chainlink/relayer_chain_interoperators.go | 13 +- .../relayer_chain_interoperators_test.go | 6 +- core/services/cron/cron_test.go | 15 +- core/services/directrequest/delegate_test.go | 20 ++- core/services/feeds/orm_test.go | 4 +- core/services/feeds/service_test.go | 10 +- .../fluxmonitorv2/integrations_test.go | 7 +- core/services/fluxmonitorv2/orm_test.go | 17 ++- core/services/functions/listener_test.go | 9 +- core/services/job/helpers_test.go | 4 +- core/services/job/job_orm_test.go | 73 ++++----- .../job/job_pipeline_orm_integration_test.go | 5 +- core/services/job/runner_integration_test.go | 8 +- core/services/job/spawner_test.go | 9 +- core/services/keeper/integration_test.go | 9 +- .../keeper/registry1_1_synchronizer_test.go | 22 +-- .../keeper/registry1_2_synchronizer_test.go | 24 +-- .../keeper/registry1_3_synchronizer_test.go | 33 ++-- .../registry_synchronizer_helper_test.go | 4 +- core/services/keeper/upkeep_executer_test.go | 4 +- core/services/keystore/eth_test.go | 4 +- core/services/ocr2/delegate_test.go | 4 +- .../evm21/logprovider/integration_test.go | 13 +- .../plugins/ocr2keeper/integration_test.go | 2 +- .../internal/ocr2vrf_integration_test.go | 2 +- core/services/pg/locked_db.go | 3 +- core/services/pipeline/orm_test.go | 15 +- core/services/pipeline/runner_test.go | 9 +- core/services/pipeline/task.eth_call_test.go | 8 +- core/services/pipeline/task.eth_tx_test.go | 6 +- .../promreporter/prom_reporter_test.go | 12 +- core/services/relay/evm/config_poller_test.go | 36 ++--- core/services/relay/evm/evm.go | 14 +- core/services/relay/evm/evm_test.go | 4 +- .../relay/evm/functions/config_poller_test.go | 9 +- .../relay/evm/mercury/helpers_test.go | 6 +- core/services/relay/evm/mercury/orm.go | 1 + .../relay/evm/relayer_extender_test.go | 3 +- core/services/vrf/delegate_test.go | 14 +- core/services/vrf/v1/integration_test.go | 4 +- core/web/evm_forwarders_controller.go | 6 +- core/web/evm_transactions_controller_test.go | 6 +- core/web/evm_tx_attempts_controller_test.go | 2 +- 77 files changed, 600 insertions(+), 459 deletions(-) create mode 100644 core/chains/evm/db/db.go create mode 100644 core/chains/evm/legacy_container.go create mode 100644 core/internal/testutils/evmtest/db/dbtest.go diff --git a/core/chains/evm/chain.go b/core/chains/evm/chain.go index 9a2fd608031..ec551274eec 100644 --- a/core/chains/evm/chain.go +++ b/core/chains/evm/chain.go @@ -11,8 +11,6 @@ import ( "go.uber.org/multierr" "golang.org/x/exp/maps" - "github.com/smartcontractkit/sqlx" - gotoml "github.com/pelletier/go-toml/v2" "github.com/smartcontractkit/chainlink-relay/pkg/types" @@ -22,6 +20,7 @@ import ( evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types" @@ -162,13 +161,14 @@ func (c ChainRelayExtenderConfig) Validate() error { } type ChainOpts struct { + // TODO BCF-2509 does this need the entire app config? AppConfig AppConfig EventBroadcaster pg.EventBroadcaster MailMon *utils.MailboxMonitor GasEstimator gas.EvmFeeEstimator - *sqlx.DB + DB *evmdb.ScopedDB // TODO BCF-2513 remove test code from the API // Gen-functions are useful for dependency injection by tests diff --git a/core/chains/evm/db/db.go b/core/chains/evm/db/db.go new file mode 100644 index 00000000000..c167fa1c958 --- /dev/null +++ b/core/chains/evm/db/db.go @@ -0,0 +1,39 @@ +package db + +import ( + "net/url" + + "github.com/google/uuid" + "github.com/smartcontractkit/sqlx" + + "github.com/smartcontractkit/chainlink/v2/core/config" + "github.com/smartcontractkit/chainlink/v2/core/services/pg" +) + +type ScopedDB struct { + *sqlx.DB +} + +var schema = "evm" + +func NewScopedDB(uuid uuid.UUID, cfg config.Database) (*ScopedDB, error) { + db, err := pg.OpenUnlockedDB(uuid, cfg, pg.WithSchema(schema)) + if err != nil { + return nil, err + } + return &ScopedDB{DB: db}, nil +} + +func (s *ScopedDB) SqlxDB() *sqlx.DB { + return s.DB +} + +func ScopedConnection(dbURL url.URL) (evmScopedConnection url.URL) { + return pg.SchemaScopedConnection(dbURL, schema) +} + +func UseEVMSchema() pg.ConnectionOpt { + return func(u *url.URL) error { + return pg.WithSchema(schema)(u) + } +} diff --git a/core/chains/evm/evm_txm.go b/core/chains/evm/evm_txm.go index d2f4178c7d9..3c2e9eb048c 100644 --- a/core/chains/evm/evm_txm.go +++ b/core/chains/evm/evm_txm.go @@ -3,10 +3,9 @@ package evm import ( "fmt" - "github.com/smartcontractkit/sqlx" - evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" @@ -14,7 +13,7 @@ import ( ) func newEvmTxm( - db *sqlx.DB, + db *evmdb.ScopedDB, cfg evmconfig.EVM, evmRPCEnabled bool, databaseConfig txmgr.DatabaseConfig, diff --git a/core/chains/evm/forwarders/forwarder_manager.go b/core/chains/evm/forwarders/forwarder_manager.go index 80b8b3d8b94..c2fae684614 100644 --- a/core/chains/evm/forwarders/forwarder_manager.go +++ b/core/chains/evm/forwarders/forwarder_manager.go @@ -9,9 +9,9 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/pkg/errors" - "github.com/smartcontractkit/sqlx" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" evmlogpoller "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" @@ -52,7 +52,7 @@ type FwdMgr struct { wg sync.WaitGroup } -func NewFwdMgr(db *sqlx.DB, client evmclient.Client, logpoller evmlogpoller.LogPoller, l logger.Logger, cfg Config, dbConfig pg.QConfig) *FwdMgr { +func NewFwdMgr(db *evmdb.ScopedDB, client evmclient.Client, logpoller evmlogpoller.LogPoller, l logger.Logger, cfg Config, dbConfig pg.QConfig) *FwdMgr { lggr := logger.Sugared(l.Named("EVMForwarderManager")) fwdMgr := FwdMgr{ logger: lggr, diff --git a/core/chains/evm/forwarders/forwarder_manager_test.go b/core/chains/evm/forwarders/forwarder_manager_test.go index bcbe43ef9b6..b281d85b810 100644 --- a/core/chains/evm/forwarders/forwarder_manager_test.go +++ b/core/chains/evm/forwarders/forwarder_manager_test.go @@ -21,6 +21,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/pg" @@ -33,8 +34,8 @@ var SimpleOracleCallABI = evmtypes.MustGetABI(operator_wrapper.OperatorABI).Meth func TestFwdMgr_MaybeForwardTransaction(t *testing.T) { lggr := logger.TestLogger(t) - db := pgtest.NewSqlxDB(t) cfg := configtest.NewTestGeneralConfig(t) + db := evmtestdb.NewScopedDB(t, cfg.Database()) evmcfg := evmtest.NewChainScopedConfig(t, cfg) owner := testutils.MustNewSimTransactor(t) @@ -92,8 +93,8 @@ func TestFwdMgr_MaybeForwardTransaction(t *testing.T) { func TestFwdMgr_AccountUnauthorizedToForward_SkipsForwarding(t *testing.T) { lggr := logger.TestLogger(t) - db := pgtest.NewSqlxDB(t) cfg := configtest.NewTestGeneralConfig(t) + db := evmtestdb.NewScopedDB(t, cfg.Database()) evmcfg := evmtest.NewChainScopedConfig(t, cfg) owner := testutils.MustNewSimTransactor(t) ec := backends.NewSimulatedBackend(map[common.Address]core.GenesisAccount{ diff --git a/core/chains/evm/forwarders/orm.go b/core/chains/evm/forwarders/orm.go index 287698d22f6..db21134bbc6 100644 --- a/core/chains/evm/forwarders/orm.go +++ b/core/chains/evm/forwarders/orm.go @@ -7,6 +7,7 @@ import ( "github.com/pkg/errors" "github.com/smartcontractkit/sqlx" + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/utils" @@ -28,8 +29,8 @@ type orm struct { var _ ORM = (*orm)(nil) -func NewORM(db *sqlx.DB, lggr logger.Logger, cfg pg.QConfig) *orm { - return &orm{pg.NewQ(db, lggr, cfg)} +func NewORM(db *evmdb.ScopedDB, lggr logger.Logger, cfg pg.QConfig) *orm { + return &orm{pg.NewQ(db.SqlxDB(), lggr, cfg)} } // CreateForwarder creates the Forwarder address associated with the current EVM chain id. diff --git a/core/chains/evm/forwarders/orm_test.go b/core/chains/evm/forwarders/orm_test.go index a3d5c2831fe..008609969c2 100644 --- a/core/chains/evm/forwarders/orm_test.go +++ b/core/chains/evm/forwarders/orm_test.go @@ -1,4 +1,4 @@ -package forwarders +package forwarders_test import ( "database/sql" @@ -9,27 +9,30 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/utils" - - "github.com/smartcontractkit/sqlx" ) type TestORM struct { - ORM - db *sqlx.DB + forwarders.ORM + db *evmdb.ScopedDB } func setupORM(t *testing.T) *TestORM { t.Helper() var ( - db = pgtest.NewSqlxDB(t) + cfg = configtest.NewTestGeneralConfig(t) + db = evmtestdb.NewScopedDB(t, cfg.Database()) lggr = logger.TestLogger(t) - orm = NewORM(db, lggr, pgtest.NewQConfig(true)) + orm = forwarders.NewORM(db, lggr, pgtest.NewQConfig(true)) ) return &TestORM{ORM: orm, db: db} diff --git a/core/chains/evm/headtracker/head_broadcaster_test.go b/core/chains/evm/headtracker/head_broadcaster_test.go index c478920e00e..7dc383aaf09 100644 --- a/core/chains/evm/headtracker/head_broadcaster_test.go +++ b/core/chains/evm/headtracker/head_broadcaster_test.go @@ -19,7 +19,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "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/internal/testutils/pgtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -47,7 +47,7 @@ func TestHeadBroadcaster_Subscribe(t *testing.T) { c.EVM[0].HeadTracker.SamplingInterval = &models.Duration{} }) evmCfg := evmtest.NewChainScopedConfig(t, cfg) - db := pgtest.NewSqlxDB(t) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) logger := logger.TestLogger(t) sub := commonmocks.NewSubscription(t) @@ -69,7 +69,7 @@ func TestHeadBroadcaster_Subscribe(t *testing.T) { checker2 := &cltest.MockHeadTrackable{} hb := headtracker.NewHeadBroadcaster(logger) - orm := headtracker.NewORM(db, logger, cfg.Database(), *ethClient.ConfiguredChainID()) + orm := headtracker.NewORM(evmdb, logger, cfg.Database(), *ethClient.ConfiguredChainID()) hs := headtracker.NewHeadSaver(logger, orm, evmCfg.EVM(), evmCfg.EVM().HeadTracker()) mailMon := utils.NewMailboxMonitor(t.Name()) ht := headtracker.NewHeadTracker(logger, ethClient, evmCfg.EVM(), evmCfg.EVM().HeadTracker(), hb, hs, mailMon) diff --git a/core/chains/evm/headtracker/head_saver_test.go b/core/chains/evm/headtracker/head_saver_test.go index 5ab43679f4b..889f4edbde6 100644 --- a/core/chains/evm/headtracker/head_saver_test.go +++ b/core/chains/evm/headtracker/head_saver_test.go @@ -11,7 +11,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -42,11 +42,12 @@ func (c *config) BlockEmissionIdleWarningThreshold() time.Duration { } func configureSaver(t *testing.T) (httypes.HeadSaver, headtracker.ORM) { - db := pgtest.NewSqlxDB(t) lggr := logger.TestLogger(t) cfg := configtest.NewGeneralConfig(t, nil) + + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) htCfg := &config{finalityDepth: uint32(1)} - orm := headtracker.NewORM(db, lggr, cfg.Database(), cltest.FixtureChainID) + orm := headtracker.NewORM(evmdb, lggr, cfg.Database(), cltest.FixtureChainID) saver := headtracker.NewHeadSaver(lggr, orm, htCfg, &headTrackerConfig{historyDepth: 6}) return saver, orm } diff --git a/core/chains/evm/headtracker/head_tracker_test.go b/core/chains/evm/headtracker/head_tracker_test.go index ad582f4fb93..f466eb210c5 100644 --- a/core/chains/evm/headtracker/head_tracker_test.go +++ b/core/chains/evm/headtracker/head_tracker_test.go @@ -20,24 +20,24 @@ import ( gethCommon "github.com/ethereum/go-ethereum/common" gethTypes "github.com/ethereum/go-ethereum/core/types" "github.com/onsi/gomega" - "github.com/smartcontractkit/sqlx" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" commonmocks "github.com/smartcontractkit/chainlink/v2/common/types/mocks" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/utils" ) -func firstHead(t *testing.T, db *sqlx.DB) (h evmtypes.Head) { +func firstHead(t *testing.T, db *evmdb.ScopedDB) (h evmtypes.Head) { if err := db.Get(&h, `SELECT * FROM heads ORDER BY number ASC LIMIT 1`); err != nil { t.Fatal(err) } @@ -48,12 +48,12 @@ func TestHeadTracker_New(t *testing.T) { t.Parallel() config := cltest.NewTestChainScopedConfig(t) - db := evmtest.NewScopedDB(t, config.Database()) + evmdb := evmtestdb.NewScopedDB(t, config.Database()) logger := logger.TestLogger(t) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(cltest.Head(0), nil) - orm := headtracker.NewORM(db, logger, config.Database(), cltest.FixtureChainID) + orm := headtracker.NewORM(evmdb, logger, config.Database(), cltest.FixtureChainID) assert.Nil(t, orm.IdempotentInsertHead(testutils.Context(t), cltest.Head(1))) last := cltest.Head(16) assert.Nil(t, orm.IdempotentInsertHead(testutils.Context(t), last)) @@ -72,7 +72,7 @@ func TestHeadTracker_Save_InsertsAndTrimsTable(t *testing.T) { t.Parallel() config := cltest.NewTestChainScopedConfig(t) - db := evmtest.NewScopedDB(t, config.Database()) + db := evmtestdb.NewScopedDB(t, config.Database()) logger := logger.TestLogger(t) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) @@ -116,10 +116,10 @@ func TestHeadTracker_Get(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - db := pgtest.NewSqlxDB(t) logger := logger.TestLogger(t) config := cltest.NewTestChainScopedConfig(t) - orm := headtracker.NewORM(db, logger, config.Database(), cltest.FixtureChainID) + evmdb := evmtestdb.NewScopedDB(t, config.Database()) + orm := headtracker.NewORM(evmdb, logger, config.Database(), cltest.FixtureChainID) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) chStarted := make(chan struct{}) @@ -163,10 +163,10 @@ func TestHeadTracker_Get(t *testing.T) { func TestHeadTracker_Start_NewHeads(t *testing.T) { t.Parallel() - db := pgtest.NewSqlxDB(t) logger := logger.TestLogger(t) config := cltest.NewTestChainScopedConfig(t) - orm := headtracker.NewORM(db, logger, config.Database(), cltest.FixtureChainID) + evmdb := evmtestdb.NewScopedDB(t, config.Database()) + orm := headtracker.NewORM(evmdb, logger, config.Database(), cltest.FixtureChainID) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) chStarted := make(chan struct{}) @@ -188,10 +188,10 @@ func TestHeadTracker_Start_NewHeads(t *testing.T) { func TestHeadTracker_Start_CancelContext(t *testing.T) { t.Parallel() - db := pgtest.NewSqlxDB(t) logger := logger.TestLogger(t) config := cltest.NewTestChainScopedConfig(t) - orm := headtracker.NewORM(db, logger, config.Database(), cltest.FixtureChainID) + evmdb := evmtestdb.NewScopedDB(t, config.Database()) + orm := headtracker.NewORM(evmdb, logger, config.Database(), cltest.FixtureChainID) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) chStarted := make(chan struct{}) ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Run(func(args mock.Arguments) { @@ -228,10 +228,10 @@ func TestHeadTracker_CallsHeadTrackableCallbacks(t *testing.T) { t.Parallel() g := gomega.NewWithT(t) - db := pgtest.NewSqlxDB(t) logger := logger.TestLogger(t) config := cltest.NewTestChainScopedConfig(t) - orm := headtracker.NewORM(db, logger, config.Database(), cltest.FixtureChainID) + evmdb := evmtestdb.NewScopedDB(t, config.Database()) + orm := headtracker.NewORM(evmdb, logger, config.Database(), cltest.FixtureChainID) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) @@ -267,10 +267,10 @@ func TestHeadTracker_ReconnectOnError(t *testing.T) { t.Parallel() g := gomega.NewWithT(t) - db := pgtest.NewSqlxDB(t) logger := logger.TestLogger(t) config := cltest.NewTestChainScopedConfig(t) - orm := headtracker.NewORM(db, logger, config.Database(), cltest.FixtureChainID) + evmdb := evmtestdb.NewScopedDB(t, config.Database()) + orm := headtracker.NewORM(evmdb, logger, config.Database(), cltest.FixtureChainID) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) mockEth := &evmtest.MockEth{EthClient: ethClient} @@ -303,10 +303,10 @@ func TestHeadTracker_ResubscribeOnSubscriptionError(t *testing.T) { t.Parallel() g := gomega.NewWithT(t) - db := pgtest.NewSqlxDB(t) logger := logger.TestLogger(t) config := cltest.NewTestChainScopedConfig(t) - orm := headtracker.NewORM(db, logger, config.Database(), cltest.FixtureChainID) + evmdb := evmtestdb.NewScopedDB(t, config.Database()) + orm := headtracker.NewORM(evmdb, logger, config.Database(), cltest.FixtureChainID) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) @@ -350,9 +350,9 @@ func TestHeadTracker_ResubscribeOnSubscriptionError(t *testing.T) { func TestHeadTracker_Start_LoadsLatestChain(t *testing.T) { t.Parallel() - db := pgtest.NewSqlxDB(t) logger := logger.TestLogger(t) config := cltest.NewTestChainScopedConfig(t) + evmdb := evmtestdb.NewScopedDB(t, config.Database()) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) heads := []*evmtypes.Head{ @@ -385,7 +385,7 @@ func TestHeadTracker_Start_LoadsLatestChain(t *testing.T) { func(ctx context.Context, ch chan<- *evmtypes.Head) error { return nil }, ) - orm := headtracker.NewORM(db, logger, config.Database(), cltest.FixtureChainID) + orm := headtracker.NewORM(evmdb, logger, config.Database(), cltest.FixtureChainID) trackable := &cltest.MockHeadTrackable{} ht := createHeadTrackerWithChecker(t, ethClient, config.EVM(), config.EVM().HeadTracker(), orm, trackable) @@ -415,7 +415,6 @@ func TestHeadTracker_Start_LoadsLatestChain(t *testing.T) { func TestHeadTracker_SwitchesToLongestChainWithHeadSamplingEnabled(t *testing.T) { t.Parallel() - db := pgtest.NewSqlxDB(t) logger := logger.TestLogger(t) config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { @@ -425,10 +424,11 @@ func TestHeadTracker_SwitchesToLongestChainWithHeadSamplingEnabled(t *testing.T) c.EVM[0].HeadTracker.SamplingInterval = models.MustNewDuration(2500 * time.Millisecond) }) + evmdb := evmtestdb.NewScopedDB(t, config.Database()) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) checker := commonmocks.NewHeadTrackable[*evmtypes.Head, gethCommon.Hash](t) - orm := headtracker.NewORM(db, logger, config.Database(), *evmtest.MustGetDefaultChainID(t, config.EVMConfigs())) + orm := headtracker.NewORM(evmdb, logger, config.Database(), *evmtest.MustGetDefaultChainID(t, config.EVMConfigs())) csCfg := evmtest.NewChainScopedConfig(t, config) ht := createHeadTrackerWithChecker(t, ethClient, csCfg.EVM(), csCfg.EVM().HeadTracker(), orm, checker) @@ -543,7 +543,6 @@ func TestHeadTracker_SwitchesToLongestChainWithHeadSamplingEnabled(t *testing.T) func TestHeadTracker_SwitchesToLongestChainWithHeadSamplingDisabled(t *testing.T) { t.Parallel() - db := pgtest.NewSqlxDB(t) logger := logger.TestLogger(t) config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { @@ -555,8 +554,9 @@ func TestHeadTracker_SwitchesToLongestChainWithHeadSamplingDisabled(t *testing.T ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + evmdb := evmtestdb.NewScopedDB(t, config.Database()) checker := commonmocks.NewHeadTrackable[*evmtypes.Head, gethCommon.Hash](t) - orm := headtracker.NewORM(db, logger, config.Database(), cltest.FixtureChainID) + orm := headtracker.NewORM(evmdb, logger, config.Database(), cltest.FixtureChainID) evmcfg := evmtest.NewChainScopedConfig(t, config) ht := createHeadTrackerWithChecker(t, ethClient, evmcfg.EVM(), evmcfg.EVM().HeadTracker(), orm, checker) @@ -770,10 +770,10 @@ func TestHeadTracker_Backfill(t *testing.T) { ctx := testutils.Context(t) t.Run("does nothing if all the heads are in database", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) logger := logger.TestLogger(t) - orm := headtracker.NewORM(db, logger, cfg.Database(), cltest.FixtureChainID) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + orm := headtracker.NewORM(evmdb, logger, cfg.Database(), cltest.FixtureChainID) for i := range heads { require.NoError(t, orm.IdempotentInsertHead(testutils.Context(t), &heads[i])) } @@ -787,10 +787,10 @@ func TestHeadTracker_Backfill(t *testing.T) { }) t.Run("fetches a missing head", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) logger := logger.TestLogger(t) - orm := headtracker.NewORM(db, logger, cfg.Database(), cltest.FixtureChainID) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + orm := headtracker.NewORM(evmdb, logger, cfg.Database(), cltest.FixtureChainID) for i := range heads { require.NoError(t, orm.IdempotentInsertHead(testutils.Context(t), &heads[i])) } @@ -823,10 +823,10 @@ func TestHeadTracker_Backfill(t *testing.T) { }) t.Run("fetches only heads that are missing", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) logger := logger.TestLogger(t) - orm := headtracker.NewORM(db, logger, cfg.Database(), cltest.FixtureChainID) + orm := headtracker.NewORM(evmdb, logger, cfg.Database(), cltest.FixtureChainID) for i := range heads { require.NoError(t, orm.IdempotentInsertHead(testutils.Context(t), &heads[i])) } @@ -856,10 +856,10 @@ func TestHeadTracker_Backfill(t *testing.T) { }) t.Run("does not backfill if chain length is already greater than or equal to depth", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) logger := logger.TestLogger(t) - orm := headtracker.NewORM(db, logger, cfg.Database(), cltest.FixtureChainID) + orm := headtracker.NewORM(evmdb, logger, cfg.Database(), cltest.FixtureChainID) for i := range heads { require.NoError(t, orm.IdempotentInsertHead(testutils.Context(t), &heads[i])) } @@ -877,10 +877,10 @@ func TestHeadTracker_Backfill(t *testing.T) { }) t.Run("only backfills to height 0 if chain length would otherwise cause it to try and fetch a negative head", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) logger := logger.TestLogger(t) - orm := headtracker.NewORM(db, logger, cfg.Database(), cltest.FixtureChainID) + orm := headtracker.NewORM(evmdb, logger, cfg.Database(), cltest.FixtureChainID) ethClient := evmtest.NewEthClientMock(t) ethClient.On("ConfiguredChainID", mock.Anything).Return(evmtest.MustGetDefaultChainID(t, cfg.EVMConfigs()), nil) @@ -902,10 +902,10 @@ func TestHeadTracker_Backfill(t *testing.T) { }) t.Run("abandons backfill and returns error if the eth node returns not found", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) logger := logger.TestLogger(t) - orm := headtracker.NewORM(db, logger, cfg.Database(), cltest.FixtureChainID) + orm := headtracker.NewORM(evmdb, logger, cfg.Database(), cltest.FixtureChainID) for i := range heads { require.NoError(t, orm.IdempotentInsertHead(testutils.Context(t), &heads[i])) } @@ -933,10 +933,10 @@ func TestHeadTracker_Backfill(t *testing.T) { }) t.Run("abandons backfill and returns error if the context time budget is exceeded", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) logger := logger.TestLogger(t) - orm := headtracker.NewORM(db, logger, cfg.Database(), cltest.FixtureChainID) + orm := headtracker.NewORM(evmdb, logger, cfg.Database(), cltest.FixtureChainID) for i := range heads { require.NoError(t, orm.IdempotentInsertHead(testutils.Context(t), &heads[i])) } @@ -962,10 +962,10 @@ func TestHeadTracker_Backfill(t *testing.T) { }) t.Run("abandons backfill and returns error when fetching a block by hash fails, indicating a reorg", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) logger := logger.TestLogger(t) - orm := headtracker.NewORM(db, logger, cfg.Database(), cltest.FixtureChainID) + orm := headtracker.NewORM(evmdb, logger, cfg.Database(), cltest.FixtureChainID) ethClient := evmtest.NewEthClientMock(t) ethClient.On("ConfiguredChainID", mock.Anything).Return(evmtest.MustGetDefaultChainID(t, cfg.EVMConfigs()), nil) ethClient.On("HeadByHash", mock.Anything, h14.Hash).Return(&h14, nil).Once() diff --git a/core/chains/evm/headtracker/orm.go b/core/chains/evm/headtracker/orm.go index 426df68b301..9c9d938d885 100644 --- a/core/chains/evm/headtracker/orm.go +++ b/core/chains/evm/headtracker/orm.go @@ -8,8 +8,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" - "github.com/smartcontractkit/sqlx" - + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/pg" @@ -35,15 +34,15 @@ type orm struct { chainID utils.Big } -func NewORM(db *sqlx.DB, lggr logger.Logger, cfg pg.QConfig, chainID big.Int) ORM { - return &orm{pg.NewQ(db, lggr.Named("HeadTrackerORM"), cfg), utils.Big(chainID)} +func NewORM(db *evmdb.ScopedDB, lggr logger.Logger, cfg pg.QConfig, chainID big.Int) ORM { + return &orm{pg.NewQ(db.SqlxDB(), lggr.Named("HeadTrackerORM"), cfg), utils.Big(chainID)} } func (orm *orm) IdempotentInsertHead(ctx context.Context, head *evmtypes.Head) error { // listener guarantees head.EVMChainID to be equal to orm.chainID q := orm.q.WithOpts(pg.WithParentCtx(ctx)) query := ` - INSERT INTO evm.heads (hash, number, parent_hash, created_at, timestamp, l1_block_number, evm_chain_id, base_fee_per_gas) VALUES ( + INSERT INTO heads (hash, number, parent_hash, created_at, timestamp, l1_block_number, evm_chain_id, base_fee_per_gas) VALUES ( :hash, :number, :parent_hash, :created_at, :timestamp, :l1_block_number, :evm_chain_id, :base_fee_per_gas) ON CONFLICT (evm_chain_id, hash) DO NOTHING` err := q.ExecQNamed(query, head) @@ -53,11 +52,11 @@ func (orm *orm) IdempotentInsertHead(ctx context.Context, head *evmtypes.Head) e func (orm *orm) TrimOldHeads(ctx context.Context, n uint) (err error) { q := orm.q.WithOpts(pg.WithParentCtx(ctx)) return q.ExecQ(` - DELETE FROM evm.heads + DELETE FROM heads WHERE evm_chain_id = $1 AND number < ( SELECT min(number) FROM ( SELECT number - FROM evm.heads + FROM heads WHERE evm_chain_id = $1 ORDER BY number DESC LIMIT $2 @@ -68,7 +67,7 @@ func (orm *orm) TrimOldHeads(ctx context.Context, n uint) (err error) { func (orm *orm) LatestHead(ctx context.Context) (head *evmtypes.Head, err error) { head = new(evmtypes.Head) q := orm.q.WithOpts(pg.WithParentCtx(ctx)) - err = q.Get(head, `SELECT * FROM evm.heads WHERE evm_chain_id = $1 ORDER BY number DESC, created_at DESC, id DESC LIMIT 1`, orm.chainID) + err = q.Get(head, `SELECT * FROM heads WHERE evm_chain_id = $1 ORDER BY number DESC, created_at DESC, id DESC LIMIT 1`, orm.chainID) if errors.Is(err, sql.ErrNoRows) { return nil, nil } @@ -78,7 +77,7 @@ func (orm *orm) LatestHead(ctx context.Context) (head *evmtypes.Head, err error) func (orm *orm) LatestHeads(ctx context.Context, limit uint) (heads []*evmtypes.Head, err error) { q := orm.q.WithOpts(pg.WithParentCtx(ctx)) - err = q.Select(&heads, `SELECT * FROM evm.heads WHERE evm_chain_id = $1 ORDER BY number DESC, created_at DESC, id DESC LIMIT $2`, orm.chainID, limit) + err = q.Select(&heads, `SELECT * FROM heads WHERE evm_chain_id = $1 ORDER BY number DESC, created_at DESC, id DESC LIMIT $2`, orm.chainID, limit) err = errors.Wrap(err, "LatestHeads failed") return } @@ -86,7 +85,7 @@ func (orm *orm) LatestHeads(ctx context.Context, limit uint) (heads []*evmtypes. func (orm *orm) HeadByHash(ctx context.Context, hash common.Hash) (head *evmtypes.Head, err error) { q := orm.q.WithOpts(pg.WithParentCtx(ctx)) head = new(evmtypes.Head) - err = q.Get(head, `SELECT * FROM evm.heads WHERE evm_chain_id = $1 AND hash = $2`, orm.chainID, hash) + err = q.Get(head, `SELECT * FROM heads WHERE evm_chain_id = $1 AND hash = $2`, orm.chainID, hash) if errors.Is(err, sql.ErrNoRows) { return nil, nil } diff --git a/core/chains/evm/headtracker/orm_test.go b/core/chains/evm/headtracker/orm_test.go index 5b106ac1018..40d90b6c94f 100644 --- a/core/chains/evm/headtracker/orm_test.go +++ b/core/chains/evm/headtracker/orm_test.go @@ -13,17 +13,20 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/logger" ) +func setupORM(t *testing.T) headtracker.ORM { + logger := logger.TestLogger(t) + cfg := configtest.NewGeneralConfig(t, nil) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + return headtracker.NewORM(evmdb, logger, cfg.Database(), cltest.FixtureChainID) +} func TestORM_IdempotentInsertHead(t *testing.T) { t.Parallel() - db := pgtest.NewSqlxDB(t) - logger := logger.TestLogger(t) - cfg := configtest.NewGeneralConfig(t, nil) - orm := headtracker.NewORM(db, logger, cfg.Database(), cltest.FixtureChainID) + orm := setupORM(t) // Returns nil when inserting first head head := cltest.Head(0) @@ -46,10 +49,7 @@ func TestORM_IdempotentInsertHead(t *testing.T) { func TestORM_TrimOldHeads(t *testing.T) { t.Parallel() - db := pgtest.NewSqlxDB(t) - logger := logger.TestLogger(t) - cfg := configtest.NewGeneralConfig(t, nil) - orm := headtracker.NewORM(db, logger, cfg.Database(), cltest.FixtureChainID) + orm := setupORM(t) for i := 0; i < 10; i++ { head := cltest.Head(i) @@ -71,10 +71,7 @@ func TestORM_TrimOldHeads(t *testing.T) { func TestORM_HeadByHash(t *testing.T) { t.Parallel() - db := pgtest.NewSqlxDB(t) - logger := logger.TestLogger(t) - cfg := configtest.NewGeneralConfig(t, nil) - orm := headtracker.NewORM(db, logger, cfg.Database(), cltest.FixtureChainID) + orm := setupORM(t) var hash common.Hash for i := 0; i < 10; i++ { @@ -94,10 +91,7 @@ func TestORM_HeadByHash(t *testing.T) { func TestORM_HeadByHash_NotFound(t *testing.T) { t.Parallel() - db := pgtest.NewSqlxDB(t) - logger := logger.TestLogger(t) - cfg := configtest.NewGeneralConfig(t, nil) - orm := headtracker.NewORM(db, logger, cfg.Database(), cltest.FixtureChainID) + orm := setupORM(t) hash := cltest.Head(123).Hash head, err := orm.HeadByHash(testutils.Context(t), hash) @@ -109,11 +103,7 @@ func TestORM_HeadByHash_NotFound(t *testing.T) { func TestORM_LatestHeads_NoRows(t *testing.T) { t.Parallel() - db := pgtest.NewSqlxDB(t) - logger := logger.TestLogger(t) - cfg := configtest.NewGeneralConfig(t, nil) - orm := headtracker.NewORM(db, logger, cfg.Database(), cltest.FixtureChainID) - + orm := setupORM(t) heads, err := orm.LatestHeads(testutils.Context(t), 100) require.Zero(t, len(heads)) diff --git a/core/chains/evm/legacy_container.go b/core/chains/evm/legacy_container.go new file mode 100644 index 00000000000..9e177f500a5 --- /dev/null +++ b/core/chains/evm/legacy_container.go @@ -0,0 +1,37 @@ +package evm + +import ( + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" +) + +type LegacyContainer interface { + DB() *evmdb.ScopedDB + TxmORM() txmgr.EvmTxStore + Chains() LegacyChainContainer +} + +type LegacyContainerImpl struct { + chains *LegacyChains + db *evmdb.ScopedDB + txmorm txmgr.EvmTxStore +} + +func (l *LegacyContainerImpl) DB() *evmdb.ScopedDB { + return l.db +} + +func (l *LegacyContainerImpl) TxmORM() txmgr.EvmTxStore { + return l.txmorm +} + +func (l *LegacyContainerImpl) Chains() LegacyChainContainer { + return l.chains +} +func NewLegacyContainerImpl(db *evmdb.ScopedDB, txm txmgr.EvmTxStore, chains *LegacyChains) *LegacyContainerImpl { + return &LegacyContainerImpl{ + db: db, + txmorm: txm, + chains: chains, + } +} diff --git a/core/chains/evm/log/orm.go b/core/chains/evm/log/orm.go index 4e51940f344..19a280e0a6c 100644 --- a/core/chains/evm/log/orm.go +++ b/core/chains/evm/log/orm.go @@ -9,8 +9,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/pkg/errors" - "github.com/smartcontractkit/sqlx" - + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/utils" @@ -53,8 +52,8 @@ type orm struct { var _ ORM = (*orm)(nil) -func NewORM(db *sqlx.DB, lggr logger.Logger, cfg pg.QConfig, evmChainID big.Int) *orm { - return &orm{pg.NewQ(db, lggr, cfg), *utils.NewBig(&evmChainID)} +func NewORM(db *evmdb.ScopedDB, lggr logger.Logger, cfg pg.QConfig, evmChainID big.Int) *orm { + return &orm{pg.NewQ(db.SqlxDB(), lggr, cfg), *utils.NewBig(&evmChainID)} } func (o *orm) WasBroadcastConsumed(blockHash common.Hash, logIndex uint, jobID int32, qopts ...pg.QOpt) (consumed bool, err error) { diff --git a/core/chains/evm/logpoller/observability_test.go b/core/chains/evm/logpoller/observability_test.go index 5bd0a772d96..0485fa423f8 100644 --- a/core/chains/evm/logpoller/observability_test.go +++ b/core/chains/evm/logpoller/observability_test.go @@ -15,6 +15,8 @@ import ( "github.com/prometheus/client_golang/prometheus/testutil" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/pg" @@ -98,7 +100,7 @@ func TestMetricsAreProperlyPopulatedWithLabels(t *testing.T) { func TestNotPublishingDatasetSizeInCaseOfError(t *testing.T) { lp := createObservedPollLogger(t, 420) - _, err := withObservedQueryAndResults(lp, "errorQuery", func() ([]string, error) { return nil, fmt.Errorf("error") }) + _, err := WithObservedQueryAndResults(lp, "errorQuery", func() ([]string, error) { return nil, fmt.Errorf("error") }) require.Error(t, err) require.Equal(t, 1, counterFromHistogramByLabels(t, lp.queryDuration, "420", "errorQuery")) @@ -107,7 +109,7 @@ func TestNotPublishingDatasetSizeInCaseOfError(t *testing.T) { func createObservedPollLogger(t *testing.T, chainId int64) *ObservedLogPoller { lggr, _ := logger.TestLoggerObserved(t, zapcore.ErrorLevel) - db := pgtest.NewSqlxDB(t) + db := evmtestdb.NewScopedDB(t, configtest.NewTestGeneralConfig(t).Database()) orm := NewORM(big.NewInt(chainId), db, lggr, pgtest.NewQConfig(true)) return NewObservedLogPoller( orm, nil, lggr, 1, 1, 1, 1, 1000, diff --git a/core/chains/evm/logpoller/orm.go b/core/chains/evm/logpoller/orm.go index c062ef3e080..398f0737f63 100644 --- a/core/chains/evm/logpoller/orm.go +++ b/core/chains/evm/logpoller/orm.go @@ -11,6 +11,7 @@ import ( "github.com/pkg/errors" "github.com/smartcontractkit/sqlx" + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/utils" @@ -22,9 +23,9 @@ type ORM struct { } // NewORM creates an ORM scoped to chainID. -func NewORM(chainID *big.Int, db *sqlx.DB, lggr logger.Logger, cfg pg.QConfig) *ORM { +func NewORM(chainID *big.Int, db *evmdb.ScopedDB, lggr logger.Logger, cfg pg.QConfig) *ORM { namedLogger := lggr.Named("Configs") - q := pg.NewQ(db, namedLogger, cfg) + q := pg.NewQ(db.SqlxDB(), namedLogger, cfg) return &ORM{ chainID: chainID, q: q, @@ -34,7 +35,7 @@ func NewORM(chainID *big.Int, db *sqlx.DB, lggr logger.Logger, cfg pg.QConfig) * // InsertBlock is idempotent to support replays. func (o *ORM) InsertBlock(h common.Hash, n int64, t time.Time, qopts ...pg.QOpt) error { q := o.q.WithOpts(qopts...) - err := q.ExecQ(`INSERT INTO evm.log_poller_blocks (evm_chain_id, block_hash, block_number, block_timestamp, created_at) + err := q.ExecQ(`INSERT INTO log_poller_blocks (evm_chain_id, block_hash, block_number, block_timestamp, created_at) VALUES ($1, $2, $3, $4, NOW()) ON CONFLICT DO NOTHING`, utils.NewBig(o.chainID), h[:], n, t) return err } @@ -54,7 +55,7 @@ func (o *ORM) InsertFilter(filter Filter, qopts ...pg.QOpt) (err error) { for _, ev := range filter.EventSigs { events = append(events, ev.Bytes()) } - return q.ExecQ(`INSERT INTO evm.log_poller_filters + return q.ExecQ(`INSERT INTO log_poller_filters (name, evm_chain_id, retention, created_at, address, event) SELECT * FROM (SELECT $1, $2::NUMERIC, $3::BIGINT, NOW()) x, @@ -67,7 +68,7 @@ func (o *ORM) InsertFilter(filter Filter, qopts ...pg.QOpt) (err error) { // DeleteFilter removes all events,address pairs associated with the Filter func (o *ORM) DeleteFilter(name string, qopts ...pg.QOpt) error { q := o.q.WithOpts(qopts...) - return q.ExecQ(`DELETE FROM evm.log_poller_filters WHERE name = $1 AND evm_chain_id = $2`, name, utils.NewBig(o.chainID)) + return q.ExecQ(`DELETE FROM log_poller_filters WHERE name = $1 AND evm_chain_id = $2`, name, utils.NewBig(o.chainID)) } // LoadFiltersForChain returns all filters for this chain @@ -78,7 +79,7 @@ func (o *ORM) LoadFilters(qopts ...pg.QOpt) (map[string]Filter, error) { ARRAY_AGG(DISTINCT address)::BYTEA[] AS addresses, ARRAY_AGG(DISTINCT event)::BYTEA[] AS event_sigs, MAX(retention) AS retention - FROM evm.log_poller_filters WHERE evm_chain_id = $1 + FROM log_poller_filters WHERE evm_chain_id = $1 GROUP BY name`, utils.NewBig(o.chainID)) filters := make(map[string]Filter) for _, filter := range rows { @@ -91,7 +92,7 @@ func (o *ORM) LoadFilters(qopts ...pg.QOpt) (map[string]Filter, error) { func (o *ORM) SelectBlockByHash(h common.Hash, qopts ...pg.QOpt) (*LogPollerBlock, error) { q := o.q.WithOpts(qopts...) var b LogPollerBlock - if err := q.Get(&b, `SELECT * FROM evm.log_poller_blocks WHERE block_hash = $1 AND evm_chain_id = $2`, h, utils.NewBig(o.chainID)); err != nil { + if err := q.Get(&b, `SELECT * FROM log_poller_blocks WHERE block_hash = $1 AND evm_chain_id = $2`, h, utils.NewBig(o.chainID)); err != nil { return nil, err } return &b, nil @@ -100,7 +101,7 @@ func (o *ORM) SelectBlockByHash(h common.Hash, qopts ...pg.QOpt) (*LogPollerBloc func (o *ORM) SelectBlockByNumber(n int64, qopts ...pg.QOpt) (*LogPollerBlock, error) { q := o.q.WithOpts(qopts...) var b LogPollerBlock - if err := q.Get(&b, `SELECT * FROM evm.log_poller_blocks WHERE block_number = $1 AND evm_chain_id = $2`, n, utils.NewBig(o.chainID)); err != nil { + if err := q.Get(&b, `SELECT * FROM log_poller_blocks WHERE block_number = $1 AND evm_chain_id = $2`, n, utils.NewBig(o.chainID)); err != nil { return nil, err } return &b, nil @@ -109,7 +110,7 @@ func (o *ORM) SelectBlockByNumber(n int64, qopts ...pg.QOpt) (*LogPollerBlock, e func (o *ORM) SelectLatestBlock(qopts ...pg.QOpt) (*LogPollerBlock, error) { q := o.q.WithOpts(qopts...) var b LogPollerBlock - if err := q.Get(&b, `SELECT * FROM evm.log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1`, utils.NewBig(o.chainID)); err != nil { + if err := q.Get(&b, `SELECT * FROM log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1`, utils.NewBig(o.chainID)); err != nil { return nil, err } return &b, nil @@ -118,11 +119,11 @@ func (o *ORM) SelectLatestBlock(qopts ...pg.QOpt) (*LogPollerBlock, error) { func (o *ORM) SelectLatestLogEventSigWithConfs(eventSig common.Hash, address common.Address, confs int, qopts ...pg.QOpt) (*Log, error) { q := o.q.WithOpts(qopts...) var l Log - if err := q.Get(&l, `SELECT * FROM evm.logs + if err := q.Get(&l, `SELECT * FROM logs WHERE evm_chain_id = $1 AND event_sig = $2 AND address = $3 - AND (block_number + $4) <= (SELECT COALESCE(block_number, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1) + AND (block_number + $4) <= (SELECT COALESCE(block_number, 0) FROM log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1) ORDER BY (block_number, log_index) DESC LIMIT 1`, utils.NewBig(o.chainID), eventSig, address, confs); err != nil { return nil, err } @@ -132,19 +133,19 @@ func (o *ORM) SelectLatestLogEventSigWithConfs(eventSig common.Hash, address com // DeleteBlocksAfter delete all blocks after and including start. func (o *ORM) DeleteBlocksAfter(start int64, qopts ...pg.QOpt) error { q := o.q.WithOpts(qopts...) - return q.ExecQ(`DELETE FROM evm.log_poller_blocks WHERE block_number >= $1 AND evm_chain_id = $2`, start, utils.NewBig(o.chainID)) + return q.ExecQ(`DELETE FROM log_poller_blocks WHERE block_number >= $1 AND evm_chain_id = $2`, start, utils.NewBig(o.chainID)) } // DeleteBlocksBefore delete all blocks before and including end. func (o *ORM) DeleteBlocksBefore(end int64, qopts ...pg.QOpt) error { q := o.q.WithOpts(qopts...) - _, err := q.Exec(`DELETE FROM evm.log_poller_blocks WHERE block_number <= $1 AND evm_chain_id = $2`, end, utils.NewBig(o.chainID)) + _, err := q.Exec(`DELETE FROM log_poller_blocks WHERE block_number <= $1 AND evm_chain_id = $2`, end, utils.NewBig(o.chainID)) return err } func (o *ORM) DeleteLogsAfter(start int64, qopts ...pg.QOpt) error { q := o.q.WithOpts(qopts...) - return q.ExecQ(`DELETE FROM evm.logs WHERE block_number >= $1 AND evm_chain_id = $2`, start, utils.NewBig(o.chainID)) + return q.ExecQ(`DELETE FROM logs WHERE block_number >= $1 AND evm_chain_id = $2`, start, utils.NewBig(o.chainID)) } type Exp struct { @@ -161,9 +162,9 @@ func (o *ORM) DeleteExpiredLogs(qopts ...pg.QOpt) error { return q.ExecQ(`WITH r AS ( SELECT address, event, MAX(retention) AS retention - FROM evm.log_poller_filters WHERE evm_chain_id=$1 + FROM log_poller_filters WHERE evm_chain_id=$1 GROUP BY evm_chain_id,address, event HAVING NOT 0 = ANY(ARRAY_AGG(retention)) - ) DELETE FROM evm.logs l USING r + ) DELETE FROM logs l USING r WHERE l.evm_chain_id = $1 AND l.address=r.address AND l.event_sig=r.event AND l.created_at <= STATEMENT_TIMESTAMP() - (r.retention / 10^9 * interval '1 second')`, // retention is in nanoseconds (time.Duration aka BIGINT) utils.NewBig(o.chainID)) @@ -185,7 +186,7 @@ func (o *ORM) InsertLogs(logs []Log, qopts ...pg.QOpt) error { end = len(logs) } - err := q.ExecQNamed(`INSERT INTO evm.logs + err := q.ExecQNamed(`INSERT INTO logs (evm_chain_id, log_index, block_hash, block_number, block_timestamp, address, event_sig, topics, tx_hash, data, created_at) VALUES (:evm_chain_id, :log_index, :block_hash, :block_number, :block_timestamp, :address, :event_sig, :topics, :tx_hash, :data, NOW()) ON CONFLICT DO NOTHING`, logs[start:end]) @@ -206,7 +207,7 @@ func (o *ORM) InsertLogs(logs []Log, qopts ...pg.QOpt) error { func (o *ORM) SelectLogsByBlockRange(start, end int64) ([]Log, error) { var logs []Log err := o.q.Select(&logs, ` - SELECT * FROM evm.logs + SELECT * FROM logs WHERE block_number >= $1 AND block_number <= $2 AND evm_chain_id = $3 ORDER BY (block_number, log_index, created_at)`, start, end, utils.NewBig(o.chainID)) if err != nil { @@ -220,10 +221,10 @@ func (o *ORM) SelectLogsByBlockRangeFilter(start, end int64, address common.Addr var logs []Log q := o.q.WithOpts(qopts...) err := q.Select(&logs, ` - SELECT * FROM evm.logs - WHERE evm.logs.block_number >= $1 AND evm.logs.block_number <= $2 AND evm.logs.evm_chain_id = $3 + SELECT * FROM logs + WHERE logs.block_number >= $1 AND logs.block_number <= $2 AND logs.evm_chain_id = $3 AND address = $4 AND event_sig = $5 - ORDER BY (evm.logs.block_number, evm.logs.log_index)`, start, end, utils.NewBig(o.chainID), address, eventSig.Bytes()) + ORDER BY (logs.block_number, logs.log_index)`, start, end, utils.NewBig(o.chainID), address, eventSig.Bytes()) if err != nil { return nil, err } @@ -235,12 +236,12 @@ func (o *ORM) SelectLogsCreatedAfter(eventSig []byte, address common.Address, af var logs []Log q := o.q.WithOpts(qopts...) err := q.Select(&logs, ` - SELECT * FROM evm.logs + SELECT * FROM logs WHERE evm_chain_id = $1 AND address = $2 AND event_sig = $3 AND created_at > $4 - AND (block_number + $5) <= (SELECT COALESCE(block_number, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1) + AND (block_number + $5) <= (SELECT COALESCE(block_number, 0) FROM log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1) ORDER BY created_at ASC`, utils.NewBig(o.chainID), address, eventSig, after, confs) if err != nil { return nil, err @@ -267,12 +268,12 @@ func (o *ORM) SelectLogsWithSigsByBlockRangeFilter(start, end int64, address com ` SELECT * -FROM evm.logs -WHERE evm.logs.block_number BETWEEN :start AND :end - AND evm.logs.evm_chain_id = :chainid - AND evm.logs.address = :address - AND evm.logs.event_sig IN (:EventSigs) -ORDER BY (evm.logs.block_number, evm.logs.log_index)`, a) +FROM logs +WHERE logs.block_number BETWEEN :start AND :end + AND logs.evm_chain_id = :chainid + AND logs.address = :address + AND logs.event_sig IN (:EventSigs) +ORDER BY (logs.block_number, logs.log_index)`, a) if err != nil { return nil, errors.Wrap(err, "sqlx Named") } @@ -292,7 +293,7 @@ func (o *ORM) GetBlocksRange(start uint64, end uint64, qopts ...pg.QOpt) ([]LogP var blocks []LogPollerBlock q := o.q.WithOpts(qopts...) err := q.Select(&blocks, ` - SELECT * FROM evm.log_poller_blocks + SELECT * FROM log_poller_blocks WHERE block_number >= $1 AND block_number <= $2 AND evm_chain_id = $3 ORDER BY block_number ASC`, start, end, utils.NewBig(o.chainID)) if err != nil { @@ -309,13 +310,13 @@ func (o *ORM) SelectLatestLogEventSigsAddrsWithConfs(fromBlock int64, addresses q := o.q.WithOpts(qopts...) err := q.Select(&logs, ` - SELECT * FROM evm.logs WHERE (block_number, address, event_sig) IN ( - SELECT MAX(block_number), address, event_sig FROM evm.logs + SELECT * FROM logs WHERE (block_number, address, event_sig) IN ( + SELECT MAX(block_number), address, event_sig FROM logs WHERE evm_chain_id = $1 AND event_sig = ANY($2) AND address = ANY($3) AND block_number > $4 AND - block_number <= (SELECT COALESCE(block_number, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1) - $5 + block_number <= (SELECT COALESCE(block_number, 0) FROM log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1) - $5 GROUP BY event_sig, address ) ORDER BY block_number ASC @@ -334,12 +335,12 @@ func (o *ORM) SelectLatestBlockNumberEventSigsAddrsWithConfs(fromBlock int64, ev q := o.q.WithOpts(qopts...) err := q.Get(&blockNumber, ` - SELECT COALESCE(MAX(block_number), 0) FROM evm.logs + SELECT COALESCE(MAX(block_number), 0) FROM logs WHERE evm_chain_id = $1 AND event_sig = ANY($2) AND address = ANY($3) AND block_number > $4 AND - block_number <= (SELECT COALESCE(block_number, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1) - $5`, + block_number <= (SELECT COALESCE(block_number, 0) FROM log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1) - $5`, o.chainID.Int64(), sigs, addrs, fromBlock, confs) if err != nil { return 0, err @@ -351,13 +352,13 @@ func (o *ORM) SelectDataWordRange(address common.Address, eventSig common.Hash, var logs []Log q := o.q.WithOpts(qopts...) err := q.Select(&logs, - `SELECT * FROM evm.logs - WHERE evm.logs.evm_chain_id = $1 + `SELECT * FROM logs + WHERE logs.evm_chain_id = $1 AND address = $2 AND event_sig = $3 AND substring(data from 32*$4+1 for 32) >= $5 AND substring(data from 32*$4+1 for 32) <= $6 - AND block_number <= (SELECT COALESCE(block_number, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1) - $7 - ORDER BY (evm.logs.block_number, evm.logs.log_index)`, utils.NewBig(o.chainID), address, eventSig.Bytes(), wordIndex, wordValueMin.Bytes(), wordValueMax.Bytes(), confs) + AND block_number <= (SELECT COALESCE(block_number, 0) FROM log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1) - $7 + ORDER BY (logs.block_number, logs.log_index)`, utils.NewBig(o.chainID), address, eventSig.Bytes(), wordIndex, wordValueMin.Bytes(), wordValueMax.Bytes(), confs) if err != nil { return nil, err } @@ -368,12 +369,12 @@ func (o *ORM) SelectDataWordGreaterThan(address common.Address, eventSig common. var logs []Log q := o.q.WithOpts(qopts...) err := q.Select(&logs, - `SELECT * FROM evm.logs - WHERE evm.logs.evm_chain_id = $1 + `SELECT * FROM logs + WHERE logs.evm_chain_id = $1 AND address = $2 AND event_sig = $3 AND substring(data from 32*$4+1 for 32) >= $5 - AND block_number <= (SELECT COALESCE(block_number, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1) - $6 - ORDER BY (evm.logs.block_number, evm.logs.log_index)`, utils.NewBig(o.chainID), address, eventSig.Bytes(), wordIndex, wordValueMin.Bytes(), confs) + AND block_number <= (SELECT COALESCE(block_number, 0) FROM log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1) - $6 + ORDER BY (logs.block_number, logs.log_index)`, utils.NewBig(o.chainID), address, eventSig.Bytes(), wordIndex, wordValueMin.Bytes(), confs) if err != nil { return nil, err } @@ -388,12 +389,12 @@ func (o *ORM) SelectIndexLogsTopicGreaterThan(address common.Address, eventSig c var logs []Log q := o.q.WithOpts(qopts...) err := q.Select(&logs, - `SELECT * FROM evm.logs - WHERE evm.logs.evm_chain_id = $1 + `SELECT * FROM logs + WHERE logs.evm_chain_id = $1 AND address = $2 AND event_sig = $3 AND topics[$4] >= $5 - AND block_number <= (SELECT COALESCE(block_number, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1) - $6 - ORDER BY (evm.logs.block_number, evm.logs.log_index)`, utils.NewBig(o.chainID), address, eventSig.Bytes(), topicIndex+1, topicValueMin.Bytes(), confs) + AND block_number <= (SELECT COALESCE(block_number, 0) FROM log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1) - $6 + ORDER BY (logs.block_number, logs.log_index)`, utils.NewBig(o.chainID), address, eventSig.Bytes(), topicIndex+1, topicValueMin.Bytes(), confs) if err != nil { return nil, err } @@ -407,12 +408,12 @@ func (o *ORM) SelectUntilBlockHashDataWordGreaterThan(address common.Address, ev // We want to mimic the behaviour of the ETH RPC which errors if blockhash not found. var block LogPollerBlock if err := tx.Get(&block, - `SELECT * FROM evm.log_poller_blocks + `SELECT * FROM log_poller_blocks WHERE evm_chain_id = $1 AND block_hash = $2`, utils.NewBig(o.chainID), untilBlockHash); err != nil { return err } return q.Select(&logs, - `SELECT * FROM evm.logs + `SELECT * FROM logs WHERE evm_chain_id = $1 AND address = $2 AND event_sig = $3 AND substring(data from 32*$4+1 for 32) >= $5 @@ -433,13 +434,13 @@ func (o *ORM) SelectIndexLogsTopicRange(address common.Address, eventSig common. var logs []Log q := o.q.WithOpts(qopts...) err := q.Select(&logs, - `SELECT * FROM evm.logs - WHERE evm.logs.evm_chain_id = $1 + `SELECT * FROM logs + WHERE logs.evm_chain_id = $1 AND address = $2 AND event_sig = $3 AND topics[$4] >= $5 AND topics[$4] <= $6 - AND block_number <= (SELECT COALESCE(block_number, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1) - $7 - ORDER BY (evm.logs.block_number, evm.logs.log_index)`, utils.NewBig(o.chainID), address, eventSig.Bytes(), topicIndex+1, topicValueMin.Bytes(), topicValueMax.Bytes(), confs) + AND block_number <= (SELECT COALESCE(block_number, 0) FROM log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1) - $7 + ORDER BY (logs.block_number, logs.log_index)`, utils.NewBig(o.chainID), address, eventSig.Bytes(), topicIndex+1, topicValueMin.Bytes(), topicValueMax.Bytes(), confs) if err != nil { return nil, err } @@ -456,12 +457,12 @@ func (o *ORM) SelectIndexedLogs(address common.Address, eventSig common.Hash, to topicValuesBytes := concatBytes(topicValues) // Add 1 since postgresql arrays are 1-indexed. err := q.Select(&logs, ` - SELECT * FROM evm.logs - WHERE evm.logs.evm_chain_id = $1 + SELECT * FROM logs + WHERE logs.evm_chain_id = $1 AND address = $2 AND event_sig = $3 AND topics[$4] = ANY($5) - AND block_number <= (SELECT COALESCE(block_number, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1) - $6 - ORDER BY (evm.logs.block_number, evm.logs.log_index)`, utils.NewBig(o.chainID), address, eventSig.Bytes(), topicIndex+1, topicValuesBytes, confs) + AND block_number <= (SELECT COALESCE(block_number, 0) FROM log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1) - $6 + ORDER BY (logs.block_number, logs.log_index)`, utils.NewBig(o.chainID), address, eventSig.Bytes(), topicIndex+1, topicValuesBytes, confs) if err != nil { return nil, err } @@ -478,11 +479,11 @@ func (o *ORM) SelectIndexedLogsByBlockRangeFilter(start, end int64, address comm topicValuesBytes := concatBytes(topicValues) q := o.q.WithOpts(qopts...) err := q.Select(&logs, ` - SELECT * FROM evm.logs - WHERE evm.logs.block_number >= $1 AND evm.logs.block_number <= $2 AND evm.logs.evm_chain_id = $3 + SELECT * FROM logs + WHERE logs.block_number >= $1 AND logs.block_number <= $2 AND logs.evm_chain_id = $3 AND address = $4 AND event_sig = $5 AND topics[$6] = ANY($7) - ORDER BY (evm.logs.block_number, evm.logs.log_index)`, start, end, utils.NewBig(o.chainID), address, eventSig.Bytes(), topicIndex+1, topicValuesBytes) + ORDER BY (logs.block_number, logs.log_index)`, start, end, utils.NewBig(o.chainID), address, eventSig.Bytes(), topicIndex+1, topicValuesBytes) if err != nil { return nil, err } @@ -503,12 +504,12 @@ func (o *ORM) SelectIndexedLogsCreatedAfter(address common.Address, eventSig com topicValuesBytes := concatBytes(topicValues) // Add 1 since postgresql arrays are 1-indexed. err := q.Select(&logs, ` - SELECT * FROM evm.logs - WHERE evm.logs.evm_chain_id = $1 + SELECT * FROM logs + WHERE logs.evm_chain_id = $1 AND address = $2 AND event_sig = $3 AND topics[$4] = ANY($5) AND created_at > $6 - AND block_number <= (SELECT COALESCE(block_number, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1) - $7 + AND block_number <= (SELECT COALESCE(block_number, 0) FROM log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1) - $7 ORDER BY created_at ASC`, utils.NewBig(o.chainID), address, eventSig.Bytes(), topicIndex+1, topicValuesBytes, after, confs) if err != nil { return nil, err @@ -520,11 +521,11 @@ func (o *ORM) SelectIndexedLogsByTxHash(eventSig common.Hash, txHash common.Hash q := o.q.WithOpts(qopts...) var logs []Log err := q.Select(&logs, ` - SELECT * FROM evm.logs - WHERE evm.logs.evm_chain_id = $1 + SELECT * FROM logs + WHERE logs.evm_chain_id = $1 AND tx_hash = $2 AND event_sig = $3 - ORDER BY (evm.logs.block_number, evm.logs.log_index)`, + ORDER BY (logs.block_number, logs.log_index)`, utils.NewBig(o.chainID), txHash.Bytes(), eventSig.Bytes()) if err != nil { return nil, err @@ -543,25 +544,25 @@ func (o *ORM) SelectIndexedLogsWithSigsExcluding(sigA, sigB common.Hash, topicIn err := q.Select(&logs, ` SELECT * - FROM evm.logs + FROM logs WHERE evm_chain_id = $1 AND address = $2 AND event_sig = $3 AND block_number BETWEEN $6 AND $7 - AND block_number <= (SELECT COALESCE(block_number, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1) - $8 + AND block_number <= (SELECT COALESCE(block_number, 0) FROM log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1) - $8 EXCEPT SELECT a.* - FROM evm.logs AS a - INNER JOIN evm.logs B + FROM logs AS a + INNER JOIN logs B ON a.evm_chain_id = b.evm_chain_id AND a.address = b.address AND a.topics[$5] = b.topics[$5] AND a.event_sig = $3 AND b.event_sig = $4 AND b.block_number BETWEEN $6 AND $7 - AND b.block_number <= (SELECT COALESCE(block_number, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1) - $8 + AND b.block_number <= (SELECT COALESCE(block_number, 0) FROM log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1) - $8 ORDER BY block_number,log_index ASC `, utils.NewBig(o.chainID), address, sigA.Bytes(), sigB.Bytes(), topicIndex+1, startBlock, endBlock, confs) diff --git a/core/chains/evm/txmgr/builder.go b/core/chains/evm/txmgr/builder.go index 464cf6f9c59..ee1120f5a08 100644 --- a/core/chains/evm/txmgr/builder.go +++ b/core/chains/evm/txmgr/builder.go @@ -4,12 +4,11 @@ import ( "math/big" "time" - "github.com/smartcontractkit/sqlx" - "github.com/smartcontractkit/chainlink/v2/common/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" @@ -21,7 +20,7 @@ import ( // NewTxm constructs the necessary dependencies for the EvmTxm (broadcaster, confirmer, etc) and returns a new EvmTxManager func NewTxm( - db *sqlx.DB, + db *evmdb.ScopedDB, chainConfig ChainConfig, fCfg FeeConfig, txConfig config.Transactions, diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index 52cd50cba32..9aa34fec7e1 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -21,6 +21,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/common/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/core/assets" + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/label" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -320,13 +321,13 @@ func dbEthTxAttemptsToEthTxAttempts(dbEthTxAttempt []DbEthTxAttempt) []TxAttempt } func NewTxStore( - db *sqlx.DB, + db *evmdb.ScopedDB, lggr logger.Logger, cfg pg.QConfig, ) *evmTxStore { namedLogger := lggr.Named("TxmStore") ctx, cancel := context.WithCancel(context.Background()) - q := pg.NewQ(db, namedLogger, cfg, pg.WithParentCtx(ctx)) + q := pg.NewQ(db.SqlxDB(), namedLogger, cfg, pg.WithParentCtx(ctx)) return &evmTxStore{ q: q, logger: namedLogger, diff --git a/core/cmd/ocr2vrf_configure_commands.go b/core/cmd/ocr2vrf_configure_commands.go index 01bfd89c32b..b56636b09e8 100644 --- a/core/cmd/ocr2vrf_configure_commands.go +++ b/core/cmd/ocr2vrf_configure_commands.go @@ -14,6 +14,7 @@ import ( "github.com/pkg/errors" "github.com/urfave/cli" + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -240,8 +241,12 @@ func (s *Shell) ConfigureOCR2VRFNode(c *cli.Context, owner *bind.TransactOpts, e return nil, err } + evmDB, err := evmdb.NewScopedDB(s.Config.AppID(), s.Config.Database()) + if err != nil { + return nil, err + } // Create forwarder for management in forwarder_manager.go. - orm := forwarders.NewORM(ldb.DB(), lggr, s.Config.Database()) + orm := forwarders.NewORM(evmDB, lggr, s.Config.Database()) _, err = orm.CreateForwarder(common.HexToAddress(forwarderAddress), *utils.NewBigI(chainID)) if err != nil { return nil, err diff --git a/core/cmd/shell.go b/core/cmd/shell.go index 78e02d6ff71..1cc0e9a434b 100644 --- a/core/cmd/shell.go +++ b/core/cmd/shell.go @@ -35,6 +35,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/build" "github.com/smartcontractkit/chainlink/v2/core/chains/evm" + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/logger/audit" @@ -152,7 +153,7 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G GRPCOpts: grpcOpts, } - evmScopedDB, err := pg.OpenUnlockedDB(cfg.AppID(), cfg.Database(), pg.WithSchema("evm")) //pg.NewLockedDB(cfg.AppID(), cfg.Database(), cfg.Database().Lock(), lggr) + evmScopedDB, err := evmdb.NewScopedDB(cfg.AppID(), cfg.Database()) if err != nil { return nil, err } diff --git a/core/cmd/shell_local.go b/core/cmd/shell_local.go index 372aad01384..823913937db 100644 --- a/core/cmd/shell_local.go +++ b/core/cmd/shell_local.go @@ -33,6 +33,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/assets" "github.com/smartcontractkit/chainlink/v2/core/build" + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -633,7 +634,12 @@ func (s *Shell) RebroadcastTransactions(c *cli.Context) (err error) { s.Logger.Infof("Rebroadcasting transactions from %v to %v", beginningNonce, endingNonce) - orm := txmgr.NewTxStore(app.GetSqlxDB(), lggr, s.Config.Database()) + evmDB, err := evmdb.NewScopedDB(s.Config.AppID(), s.Config.Database()) + if err != nil { + return s.errorOut(fmt.Errorf("could not open evm db: %w", err)) + } + + orm := txmgr.NewTxStore(evmDB, lggr, s.Config.Database()) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), chain.Config().EVM().GasEstimator(), keyStore.Eth(), nil) cfg := txmgr.NewEvmTxmConfig(chain.Config().EVM()) feeCfg := txmgr.NewEvmTxmFeeConfig(chain.Config().EVM().GasEstimator()) diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go index f54cf7d6e9a..8a7e680b4f7 100644 --- a/core/cmd/shell_local_test.go +++ b/core/cmd/shell_local_test.go @@ -18,6 +18,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/logger/audit" @@ -90,7 +91,7 @@ func TestShell_RunNodeWithPasswords(t *testing.T) { AppConfig: cfg, EventBroadcaster: pg.NewNullEventBroadcaster(), MailMon: &utils.MailboxMonitor{}, - DB: evmtest.NewScopedDB(t, cfg.Database()), + DB: evmtestdb.NewScopedDB(t, cfg.Database()), }, } testRelayers := genTestEVMRelayers(t, opts, keyStore) @@ -195,7 +196,7 @@ func TestShell_RunNodeWithAPICredentialsFile(t *testing.T) { EventBroadcaster: pg.NewNullEventBroadcaster(), MailMon: &utils.MailboxMonitor{}, - DB: evmtest.NewScopedDB(t, cfg.Database()), + DB: evmtestdb.NewScopedDB(t, cfg.Database()), }, } testRelayers := genTestEVMRelayers(t, opts, keyStore) diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index 662ee7de452..ebe7f67e8ac 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -53,6 +53,7 @@ import ( evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" @@ -62,6 +63,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" configtest2 "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" clhttptest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/httptest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/keystest" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -395,7 +397,7 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn AppConfig: cfg, EventBroadcaster: eventBroadcaster, MailMon: mailMon, - DB: evmtest.NewScopedDB(t, cfg.Database()), + DB: evmtestdb.NewScopedDB(t, cfg.Database()), }, CSAETHKeystore: keyStore, } @@ -1627,11 +1629,11 @@ func MustGetStateForKey(t testing.TB, kst keystore.Eth, key ethkey.KeyV2) ethkey return state } -func NewTxStore(t *testing.T, db *sqlx.DB, cfg pg.QConfig) txmgr.EvmTxStore { +func NewTxStore(t *testing.T, db *evmdb.ScopedDB, cfg pg.QConfig) txmgr.EvmTxStore { return txmgr.NewTxStore(db, logger.TestLogger(t), cfg) } -func NewTestTxStore(t *testing.T, db *sqlx.DB, cfg pg.QConfig) txmgr.TestEvmTxStore { +func NewTestTxStore(t *testing.T, db *evmdb.ScopedDB, cfg pg.QConfig) txmgr.TestEvmTxStore { return txmgr.NewTxStore(db, logger.TestLogger(t), cfg) } diff --git a/core/internal/cltest/factories.go b/core/internal/cltest/factories.go index cb0b51743e4..7c6b02c232f 100644 --- a/core/internal/cltest/factories.go +++ b/core/internal/cltest/factories.go @@ -28,6 +28,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/assets" "github.com/smartcontractkit/chainlink/v2/core/auth" "github.com/smartcontractkit/chainlink/v2/core/bridges" + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" @@ -583,7 +584,7 @@ func MustGenerateRandomKeyState(t testing.TB) ethkey.State { return ethkey.State{Address: NewEIP55Address()} } -func MustInsertHead(t *testing.T, db *sqlx.DB, cfg pg.QConfig, number int64) evmtypes.Head { +func MustInsertHead(t *testing.T, db *evmdb.ScopedDB, cfg pg.QConfig, number int64) evmtypes.Head { h := evmtypes.NewHead(big.NewInt(number), utils.NewHash(), utils.NewHash(), 0, utils.NewBig(&FixtureChainID)) horm := headtracker.NewORM(db, logger.TestLogger(t), cfg, FixtureChainID) diff --git a/core/internal/cltest/heavyweight/orm.go b/core/internal/cltest/heavyweight/orm.go index 3690a986e2e..efa5f2acd87 100644 --- a/core/internal/cltest/heavyweight/orm.go +++ b/core/internal/cltest/heavyweight/orm.go @@ -18,7 +18,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" "github.com/smartcontractkit/chainlink/v2/core/cmd" + "github.com/smartcontractkit/chainlink/v2/core/config" "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/services/chainlink" @@ -42,7 +44,12 @@ func FullTestDBNoFixturesV2(t *testing.T, name string, overrideFn func(c *chainl func FullTestDBEmptyV2(t *testing.T, name string, overrideFn func(c *chainlink.Config, s *chainlink.Secrets)) (chainlink.GeneralConfig, *sqlx.DB) { return prepareFullTestDBV2(t, name, true, false, overrideFn) } - +func EVMDB(t *testing.T, cfg config.Database) *evmdb.ScopedDB { + evmConn := evmdb.ScopedConnection(cfg.URL()) + edb, err := pg.NewConnection(evmConn.String(), dialects.Postgres, cfg) + require.NoError(t, err) + return &evmdb.ScopedDB{edb} +} func prepareFullTestDBV2(t *testing.T, name string, empty bool, loadFixtures bool, overrideFn func(c *chainlink.Config, s *chainlink.Secrets)) (chainlink.GeneralConfig, *sqlx.DB) { testutils.SkipShort(t, "FullTestDB") diff --git a/core/internal/cltest/job_factories.go b/core/internal/cltest/job_factories.go index 910ffe79e38..ada20b47aff 100644 --- a/core/internal/cltest/job_factories.go +++ b/core/internal/cltest/job_factories.go @@ -11,6 +11,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/bridges" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" @@ -61,11 +62,12 @@ func MustInsertWebhookSpec(t *testing.T, db *sqlx.DB) (job.Job, job.WebhookSpec) func getORMs(t *testing.T, db *sqlx.DB) (jobORM job.ORM, pipelineORM pipeline.ORM) { config := configtest.NewTestGeneralConfig(t) + evmdb := evmtestdb.NewScopedDB(t, config.Database()) keyStore := NewKeyStore(t, db, config.Database()) lggr := logger.TestLogger(t) pipelineORM = pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns()) bridgeORM := bridges.NewORM(db, lggr, config.Database()) - cc := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) + cc := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: evmdb, GeneralConfig: config, KeyStore: keyStore.Eth()}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(cc) jobORM = job.NewORM(db, legacyChains, pipelineORM, bridgeORM, keyStore, lggr, config.Database()) t.Cleanup(func() { jobORM.Close() }) diff --git a/core/internal/features/features_test.go b/core/internal/features/features_test.go index 39eee3f7b43..5a443afaf37 100644 --- a/core/internal/features/features_test.go +++ b/core/internal/features/features_test.go @@ -56,6 +56,7 @@ import ( "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" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -828,7 +829,7 @@ func setupForwarderEnabledNode( b.Commit() // add forwarder address to be tracked in db - forwarderORM := forwarders.NewORM(app.GetSqlxDB(), logger.TestLogger(t), config.Database()) + forwarderORM := forwarders.NewORM(app.GetRelayers().LegacyEVM().DB(), logger.TestLogger(t), config.Database()) chainID := utils.Big(*b.Blockchain().Config().ChainID) _, err = forwarderORM.CreateForwarder(forwarder, chainID) require.NoError(t, err) @@ -1327,11 +1328,12 @@ func TestIntegration_BlockHistoryEstimator(t *testing.T) { ethClient.On("ConfiguredChainID").Return(big.NewInt(client.NullClientChainID)).Maybe() chchNewHeads := make(chan evmtest.RawSub[*evmtypes.Head], 1) - db := pgtest.NewSqlxDB(t) - kst := cltest.NewKeyStore(t, db, cfg.Database()) + coredb := pgtest.NewSqlxDB(t) + kst := cltest.NewKeyStore(t, coredb, cfg.Database()) require.NoError(t, kst.Unlock(cltest.Password)) - cc := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, KeyStore: kst.Eth(), Client: ethClient, GeneralConfig: cfg}) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + cc := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: evmdb, KeyStore: kst.Eth(), Client: ethClient, GeneralConfig: cfg}) b41 := evmtypes.Block{ Number: 41, diff --git a/core/internal/features/ocr2/features_ocr2_test.go b/core/internal/features/ocr2/features_ocr2_test.go index 3883e0319ed..eed892550af 100644 --- a/core/internal/features/ocr2/features_ocr2_test.go +++ b/core/internal/features/ocr2/features_ocr2_test.go @@ -170,7 +170,7 @@ func setupNodeOCR2( b.Commit() // add forwarder address to be tracked in db - forwarderORM := forwarders.NewORM(app.GetSqlxDB(), logger.TestLogger(t), config.Database()) + forwarderORM := forwarders.NewORM(app.GetRelayers().LegacyEVM().DB(), logger.TestLogger(t), config.Database()) chainID := utils.Big(*b.Blockchain().Config().ChainID) _, err = forwarderORM.CreateForwarder(faddr, chainID) require.NoError(t, err) diff --git a/core/internal/testutils/evmtest/db/dbtest.go b/core/internal/testutils/evmtest/db/dbtest.go new file mode 100644 index 00000000000..3292d2b73be --- /dev/null +++ b/core/internal/testutils/evmtest/db/dbtest.go @@ -0,0 +1,15 @@ +package db + +import ( + "testing" + + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" + "github.com/smartcontractkit/chainlink/v2/core/config" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" + "github.com/smartcontractkit/chainlink/v2/core/services/pg" +) + +func NewScopedDB(t testing.TB, cfg config.Database) *evmdb.ScopedDB { + evmURL := evmdb.ScopedConnection(cfg.URL()) + return &evmdb.ScopedDB{pgtest.NewSqlxDB(t, pg.WithURL(evmURL))} +} diff --git a/core/internal/testutils/evmtest/evmtest.go b/core/internal/testutils/evmtest/evmtest.go index fa7023ee2cb..0527c5b852e 100644 --- a/core/internal/testutils/evmtest/evmtest.go +++ b/core/internal/testutils/evmtest/evmtest.go @@ -9,7 +9,6 @@ import ( "github.com/ethereum/go-ethereum" "github.com/pelletier/go-toml/v2" - "github.com/smartcontractkit/sqlx" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "golang.org/x/exp/slices" @@ -24,15 +23,15 @@ import ( evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" evmtoml "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/pg" @@ -64,7 +63,7 @@ type TestChainOpts struct { LogPoller logpoller.LogPoller GeneralConfig evm.AppConfig HeadTracker httypes.HeadTracker - DB *sqlx.DB + DB *evmdb.ScopedDB TxManager txmgr.TxManager KeyStore keystore.Eth MailMon *utils.MailboxMonitor @@ -370,8 +369,3 @@ func (r *RawSub[T]) TrySend(t T) { case r.ch <- t: } } - -func NewScopedDB(t testing.TB, cfg config.Database) *sqlx.DB { - u := pg.SchemaScopedConnection(cfg.URL(), "evm") - return pgtest.NewSqlxDB(t, pg.WithURL(u)) -} diff --git a/core/internal/testutils/pgtest/pgtest.go b/core/internal/testutils/pgtest/pgtest.go index a9adbe12da5..dfa66856c43 100644 --- a/core/internal/testutils/pgtest/pgtest.go +++ b/core/internal/testutils/pgtest/pgtest.go @@ -30,24 +30,26 @@ func NewSqlDB(t *testing.T) *sql.DB { return db } -func uniqueConnection(t testing.TB) *url.URL { - url := testutils.MustParseURL(t, defaultDBURL.String()) - // inject uuid by default because the transaction wrapped driver requires it - q := url.Query() - q.Add("uuid", uuid.New().String()) - url.RawQuery = q.Encode() - return url +func withUUID() pg.ConnectionOpt { + return func(u *url.URL) error { + q := u.Query() + q.Add("uuid", uuid.New().String()) + u.RawQuery = q.Encode() + return nil + } } func NewSqlxDB(t testing.TB, opts ...pg.ConnectionOpt) *sqlx.DB { testutils.SkipShortDB(t) - url := uniqueConnection(t) + url := testutils.MustParseURL(t, defaultDBURL.String()) + // tx wrapped db driver requires a uuid + opts = append(opts, withUUID()) for _, opt := range opts { assert.NoError(t, opt(url)) } - db, err := sqlx.Open(string(dialects.TransactionWrappedPostgres), url.String()) - require.NoError(t, err) + db := sqlx.MustConnect(string(dialects.TransactionWrappedPostgres), url.String()) + t.Cleanup(func() { assert.NoError(t, db.Close()) }) db.MapperFunc(reflectx.CamelToSnakeASCII) diff --git a/core/services/blockhashstore/bhs_test.go b/core/services/blockhashstore/bhs_test.go index 79494ea41f6..c049af84fa3 100644 --- a/core/services/blockhashstore/bhs_test.go +++ b/core/services/blockhashstore/bhs_test.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/blockhashstore" @@ -24,17 +25,18 @@ import ( ) func TestStoreRotatesFromAddresses(t *testing.T) { - db := pgtest.NewSqlxDB(t) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) cfg := configtest.NewTestGeneralConfig(t) - kst := cltest.NewKeyStore(t, db, cfg.Database()) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + coredb := pgtest.NewSqlxDB(t) + kst := cltest.NewKeyStore(t, coredb, cfg.Database()) require.NoError(t, kst.Unlock(cltest.Password)) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, KeyStore: kst.Eth(), GeneralConfig: cfg, Client: ethClient}) + relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: evmdb, KeyStore: kst.Eth(), GeneralConfig: cfg, Client: ethClient}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) chain, err := legacyChains.Get(cltest.FixtureChainID.String()) require.NoError(t, err) lggr := logger.TestLogger(t) - ks := keystore.New(db, utils.FastScryptParams, lggr, cfg.Database()) + ks := keystore.New(coredb, utils.FastScryptParams, lggr, cfg.Database()) require.NoError(t, ks.Unlock("blah")) k1, err := ks.Eth().Create(&cltest.FixtureChainID) require.NoError(t, err) diff --git a/core/services/blockhashstore/delegate_test.go b/core/services/blockhashstore/delegate_test.go index 3060f617876..0278baa2ec2 100644 --- a/core/services/blockhashstore/delegate_test.go +++ b/core/services/blockhashstore/delegate_test.go @@ -17,6 +17,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/blockhashstore" @@ -53,8 +54,9 @@ func createTestDelegate(t *testing.T) (*blockhashstore.Delegate, *testData) { cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.Feature.LogPoller = func(b bool) *bool { return &b }(true) }) - db := pgtest.NewSqlxDB(t) - kst := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + coredb := pgtest.NewSqlxDB(t) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + kst := cltest.NewKeyStore(t, coredb, cfg.Database()).Eth() sendingKey, _ := cltest.MustAddRandomKeyToKeystore(t, kst) lp := &mocklp.LogPoller{} lp.On("RegisterFilter", mock.Anything).Return(nil) @@ -63,7 +65,7 @@ func createTestDelegate(t *testing.T) (*blockhashstore.Delegate, *testData) { relayExtenders := evmtest.NewChainRelayExtenders( t, evmtest.TestChainOpts{ - DB: db, + DB: evmdb, KeyStore: kst, GeneralConfig: cfg, Client: ethClient, diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index 814c8a1c10b..3067f06ec0b 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -109,15 +109,15 @@ type Application interface { // and Store. The JobSubscriber and Scheduler are also available // in the services package, but the Store has its own package. type ChainlinkApplication struct { - relayers *CoreRelayerChainInteroperators - EventBroadcaster pg.EventBroadcaster - jobORM job.ORM - jobSpawner job.Spawner - pipelineORM pipeline.ORM - pipelineRunner pipeline.Runner - bridgeORM bridges.ORM - sessionORM sessions.ORM - txmStorageService txmgr.EvmTxStore + relayers *CoreRelayerChainInteroperators + EventBroadcaster pg.EventBroadcaster + jobORM job.ORM + jobSpawner job.Spawner + pipelineORM pipeline.ORM + pipelineRunner pipeline.Runner + bridgeORM bridges.ORM + sessionORM sessions.ORM + //txmStorageService txmgr.EvmTxStore FeedsService feeds.Service webhookJobRunner webhook.JobRunner Config GeneralConfig @@ -269,7 +269,6 @@ func NewApplication(opts ApplicationOpts) (Application, error) { mercuryORM = mercury.NewORM(db, globalLogger, cfg.Database()) pipelineRunner = pipeline.NewRunner(pipelineORM, bridgeORM, cfg.JobPipeline(), cfg.WebServer(), legacyEVMChains, keyStore.Eth(), keyStore.VRF(), globalLogger, restrictedHTTPClient, unrestrictedHTTPClient) jobORM = job.NewORM(db, legacyEVMChains, pipelineORM, bridgeORM, keyStore, globalLogger, cfg.Database()) - txmORM = txmgr.NewTxStore(db, globalLogger, cfg.Database()) ) for _, chain := range legacyEVMChains.Slice() { @@ -458,7 +457,6 @@ func NewApplication(opts ApplicationOpts) (Application, error) { pipelineORM: pipelineORM, bridgeORM: bridgeORM, sessionORM: sessionORM, - txmStorageService: txmORM, FeedsService: feedsService, Config: cfg, webhookJobRunner: webhookJobRunner, @@ -635,7 +633,7 @@ func (app *ChainlinkApplication) SessionORM() sessions.ORM { // TODO BCF-2516 remove this all together remove EVM specifics func (app *ChainlinkApplication) EVMORM() evmtypes.Configs { - return app.GetRelayers().LegacyEVMChains().ChainNodeConfigs() + return app.GetRelayers().LegacyEVM().Chains().ChainNodeConfigs() } func (app *ChainlinkApplication) PipelineORM() pipeline.ORM { @@ -643,7 +641,7 @@ func (app *ChainlinkApplication) PipelineORM() pipeline.ORM { } func (app *ChainlinkApplication) TxmStorageService() txmgr.EvmTxStore { - return app.txmStorageService + return app.GetRelayers().LegacyEVM().TxmORM() } func (app *ChainlinkApplication) GetExternalInitiatorManager() webhook.ExternalInitiatorManager { diff --git a/core/services/chainlink/relayer_chain_interoperators.go b/core/services/chainlink/relayer_chain_interoperators.go index 6513184d9ec..d858f2d87a3 100644 --- a/core/services/chainlink/relayer_chain_interoperators.go +++ b/core/services/chainlink/relayer_chain_interoperators.go @@ -13,6 +13,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains" "github.com/smartcontractkit/chainlink/v2/core/chains/cosmos" "github.com/smartcontractkit/chainlink/v2/core/chains/evm" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" "github.com/smartcontractkit/chainlink/v2/core/services" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2" "github.com/smartcontractkit/chainlink/v2/core/services/relay" @@ -35,6 +36,7 @@ type RelayerChainInteroperators interface { LoopRelayerStorer LegacyChainer + LegacyEVM() evm.LegacyContainer ChainsNodesStatuser } @@ -79,6 +81,7 @@ type CoreRelayerChainInteroperators struct { loopRelayers map[relay.ID]loop.Relayer legacyChains legacyChains + legacyEVM evm.LegacyContainer // we keep an explicit list of services because the legacy implementations have more than // just the relayer service srvs []services.ServiceCtx @@ -116,7 +119,11 @@ func InitEVM(ctx context.Context, factory RelayerFactory, config EVMFactoryConfi op.loopRelayers[id] = a legacyMap[id.ChainID] = a.Chain() } - op.legacyChains.EVMChains = evm.NewLegacyChains(legacyMap, config.AppConfig.EVMConfigs()) + + chains := evm.NewLegacyChains(legacyMap, config.AppConfig.EVMConfigs()) + op.legacyChains.EVMChains = chains + txmORM := txmgr.NewTxStore(config.DB, factory.Logger, config.AppConfig.Database()) + op.legacyEVM = evm.NewLegacyContainerImpl(config.DB, txmORM, chains) return nil } } @@ -338,6 +345,10 @@ func (rs *CoreRelayerChainInteroperators) List(filter FilterFn) RelayerChainInte } } +func (rs *CoreRelayerChainInteroperators) LegacyEVM() evm.LegacyContainer { + return rs.legacyEVM +} + // Returns a slice of [loop.Relayer]. A typically usage pattern to is // use [List(criteria)].Slice() for range based operations func (rs *CoreRelayerChainInteroperators) Slice() []loop.Relayer { diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go index 409f828d098..2fb1ec6a891 100644 --- a/core/services/chainlink/relayer_chain_interoperators_test.go +++ b/core/services/chainlink/relayer_chain_interoperators_test.go @@ -21,7 +21,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/starknet" "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" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -210,7 +210,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { AppConfig: cfg, EventBroadcaster: pg.NewNullEventBroadcaster(), MailMon: &utils.MailboxMonitor{}, - DB: evmtest.NewScopedDB(t, cfg.Database()), + DB: evmtestdb.NewScopedDB(t, cfg.Database()), }, CSAETHKeystore: keyStore, }), @@ -285,7 +285,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { AppConfig: cfg, EventBroadcaster: pg.NewNullEventBroadcaster(), MailMon: &utils.MailboxMonitor{}, - DB: evmtest.NewScopedDB(t, cfg.Database()), + DB: evmtestdb.NewScopedDB(t, cfg.Database()), }, CSAETHKeystore: keyStore, }), diff --git a/core/services/cron/cron_test.go b/core/services/cron/cron_test.go index 174f80586ae..771893b1b0d 100644 --- a/core/services/cron/cron_test.go +++ b/core/services/cron/cron_test.go @@ -13,6 +13,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/cron" @@ -25,15 +26,15 @@ import ( func TestCronV2Pipeline(t *testing.T) { runner := pipelinemocks.NewRunner(t) cfg := configtest.NewTestGeneralConfig(t) - db := pgtest.NewSqlxDB(t) - - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) - relayerExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, Client: evmtest.NewEthClientMockWithDefaultChain(t), KeyStore: keyStore.Eth()}) + coredb := pgtest.NewSqlxDB(t) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + keyStore := cltest.NewKeyStore(t, coredb, cfg.Database()) + relayerExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: evmdb, GeneralConfig: cfg, Client: evmtest.NewEthClientMockWithDefaultChain(t), KeyStore: keyStore.Eth()}) lggr := logger.TestLogger(t) - orm := pipeline.NewORM(db, lggr, cfg.Database(), cfg.JobPipeline().MaxSuccessfulRuns()) - btORM := bridges.NewORM(db, lggr, cfg.Database()) + orm := pipeline.NewORM(coredb, lggr, cfg.Database(), cfg.JobPipeline().MaxSuccessfulRuns()) + btORM := bridges.NewORM(coredb, lggr, cfg.Database()) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayerExtenders) - jobORM := job.NewORM(db, legacyChains, orm, btORM, keyStore, lggr, cfg.Database()) + jobORM := job.NewORM(coredb, legacyChains, orm, btORM, keyStore, lggr, cfg.Database()) jb := &job.Job{ Type: job.Cron, diff --git a/core/services/directrequest/delegate_test.go b/core/services/directrequest/delegate_test.go index ffd78443cc2..84be0a3b1da 100644 --- a/core/services/directrequest/delegate_test.go +++ b/core/services/directrequest/delegate_test.go @@ -22,6 +22,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -44,7 +45,9 @@ func TestDelegate_ServicesForSpec(t *testing.T) { }) keyStore := cltest.NewKeyStore(t, db, cfg.Database()) mailMon := srvctest.Start(t, utils.NewMailboxMonitor(t.Name())) - relayerExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, Client: ethClient, MailMon: mailMon, KeyStore: keyStore.Eth()}) + + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + relayerExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: evmdb, GeneralConfig: cfg, Client: ethClient, MailMon: mailMon, KeyStore: keyStore.Eth()}) lggr := logger.TestLogger(t) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayerExtenders) @@ -82,14 +85,17 @@ func NewDirectRequestUniverseWithConfig(t *testing.T, cfg chainlink.GeneralConfi mailMon := srvctest.Start(t, utils.NewMailboxMonitor(t.Name())) - db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, Client: ethClient, LogBroadcaster: broadcaster, MailMon: mailMon, KeyStore: keyStore.Eth()}) + coredb := pgtest.NewSqlxDB(t) + keyStore := cltest.NewKeyStore(t, coredb, cfg.Database()) + + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: evmdb, GeneralConfig: cfg, Client: ethClient, LogBroadcaster: broadcaster, MailMon: mailMon, KeyStore: keyStore.Eth()}) + lggr := logger.TestLogger(t) - orm := pipeline.NewORM(db, lggr, cfg.Database(), cfg.JobPipeline().MaxSuccessfulRuns()) - btORM := bridges.NewORM(db, lggr, cfg.Database()) + orm := pipeline.NewORM(coredb, lggr, cfg.Database(), cfg.JobPipeline().MaxSuccessfulRuns()) + btORM := bridges.NewORM(coredb, lggr, cfg.Database()) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) - jobORM := job.NewORM(db, legacyChains, orm, btORM, keyStore, lggr, cfg.Database()) + jobORM := job.NewORM(coredb, legacyChains, orm, btORM, keyStore, lggr, cfg.Database()) delegate := directrequest.NewDelegate(lggr, runner, orm, legacyChains, mailMon) jb := cltest.MakeDirectRequestJobSpec(t) diff --git a/core/services/feeds/orm_test.go b/core/services/feeds/orm_test.go index f2dacc4f02f..61b2fe7d904 100644 --- a/core/services/feeds/orm_test.go +++ b/core/services/feeds/orm_test.go @@ -16,6 +16,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/feeds" @@ -1477,7 +1478,8 @@ func createJob(t *testing.T, db *sqlx.DB, externalJobID uuid.UUID) *job.Job { lggr = logger.TestLogger(t) pipelineORM = pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns()) bridgeORM = bridges.NewORM(db, lggr, config.Database()) - relayExtenders = evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) + evmdb = evmtestdb.NewScopedDB(t, config.Database()) + relayExtenders = evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: evmdb, GeneralConfig: config, KeyStore: keyStore.Eth()}) ) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) orm := job.NewORM(db, legacyChains, pipelineORM, bridgeORM, keyStore, lggr, config.Database()) diff --git a/core/services/feeds/service_test.go b/core/services/feeds/service_test.go index 85f14e407f8..14c7b2123ce 100644 --- a/core/services/feeds/service_test.go +++ b/core/services/feeds/service_test.go @@ -17,6 +17,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -175,12 +176,13 @@ func setupTestServiceCfg(t *testing.T, overrideCfg func(c *chainlink.Config, s * lggr := logger.TestLogger(t) - db := pgtest.NewSqlxDB(t) gcfg := configtest.NewGeneralConfig(t, overrideCfg) + coredb := pgtest.NewSqlxDB(t) + evmdb := evmtestdb.NewScopedDB(t, gcfg.Database()) keyStore := new(ksmocks.Master) scopedConfig := evmtest.NewChainScopedConfig(t, gcfg) - ethKeyStore := cltest.NewKeyStore(t, db, gcfg.Database()).Eth() - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: gcfg, + ethKeyStore := cltest.NewKeyStore(t, coredb, gcfg.Database()).Eth() + relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: evmdb, GeneralConfig: gcfg, HeadTracker: headtracker.NullTracker, KeyStore: ethKeyStore}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) keyStore.On("Eth").Return(ethKeyStore) @@ -188,7 +190,7 @@ func setupTestServiceCfg(t *testing.T, overrideCfg func(c *chainlink.Config, s * keyStore.On("P2P").Return(p2pKeystore) keyStore.On("OCR").Return(ocr1Keystore) keyStore.On("OCR2").Return(ocr2Keystore) - svc := feeds.NewService(orm, jobORM, db, spawner, keyStore, scopedConfig.Insecure(), scopedConfig.JobPipeline(), scopedConfig.OCR(), scopedConfig.OCR2(), scopedConfig.Database(), legacyChains, lggr, "1.0.0") + svc := feeds.NewService(orm, jobORM, coredb, spawner, keyStore, scopedConfig.Insecure(), scopedConfig.JobPipeline(), scopedConfig.OCR(), scopedConfig.OCR2(), scopedConfig.Database(), legacyChains, lggr, "1.0.0") svc.SetConnectionsManager(connMgr) return &TestService{ diff --git a/core/services/fluxmonitorv2/integrations_test.go b/core/services/fluxmonitorv2/integrations_test.go index 5b6a94cac58..d14387ab1ca 100644 --- a/core/services/fluxmonitorv2/integrations_test.go +++ b/core/services/fluxmonitorv2/integrations_test.go @@ -27,6 +27,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/assets" "github.com/smartcontractkit/chainlink/v2/core/bridges" + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flags_wrapper" faw "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flux_aggregator_wrapper" @@ -404,7 +405,7 @@ func assertPipelineRunCreated(t *testing.T, db *sqlx.DB, roundID int64, result i return run } -func checkLogWasConsumed(t *testing.T, fa fluxAggregatorUniverse, db *sqlx.DB, pipelineSpecID int32, blockNumber uint64, cfg pg.QConfig) { +func checkLogWasConsumed(t *testing.T, fa fluxAggregatorUniverse, db *evmdb.ScopedDB, pipelineSpecID int32, blockNumber uint64, cfg pg.QConfig) { t.Helper() lggr := logger.TestLogger(t) lggr.Infof("Waiting for log on block: %v, job id: %v", blockNumber, pipelineSpecID) @@ -559,7 +560,7 @@ func TestFluxMonitor_Deviation(t *testing.T) { // Need to wait until NewRound log is consumed - otherwise there is a chance // it will arrive after the next answer is submitted, and cause // DeleteFluxMonitorRoundsBackThrough to delete previous stats - checkLogWasConsumed(t, fa, app.GetSqlxDB(), int32(jobId), receiptBlock, app.GetConfig().Database()) + checkLogWasConsumed(t, fa, app.GetRelayers().LegacyEVM().DB(), int32(jobId), receiptBlock, app.GetConfig().Database()) lggr.Info("Updating price to 103") // Change reported price to a value outside the deviation @@ -588,7 +589,7 @@ func TestFluxMonitor_Deviation(t *testing.T) { // Need to wait until NewRound log is consumed - otherwise there is a chance // it will arrive after the next answer is submitted, and cause // DeleteFluxMonitorRoundsBackThrough to delete previous stats - checkLogWasConsumed(t, fa, app.GetSqlxDB(), int32(jobId), receiptBlock, app.GetConfig().Database()) + checkLogWasConsumed(t, fa, app.GetRelayers().LegacyEVM().DB(), int32(jobId), receiptBlock, app.GetConfig().Database()) // Should not received a submission as it is inside the deviation reportPrice.Store(104) diff --git a/core/services/fluxmonitorv2/orm_test.go b/core/services/fluxmonitorv2/orm_test.go index a24f516c7f0..139244341dd 100644 --- a/core/services/fluxmonitorv2/orm_test.go +++ b/core/services/fluxmonitorv2/orm_test.go @@ -17,6 +17,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/fluxmonitorv2" @@ -85,22 +86,24 @@ func TestORM_UpdateFluxMonitorRoundStats(t *testing.T) { t.Parallel() cfg := configtest.NewGeneralConfig(t, nil) - db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) + coredb := pgtest.NewSqlxDB(t) + keyStore := cltest.NewKeyStore(t, coredb, cfg.Database()) + + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) lggr := logger.TestLogger(t) // Instantiate a real pipeline ORM because we need to create a pipeline run // for the foreign key constraint of the stats record - pipelineORM := pipeline.NewORM(db, lggr, cfg.Database(), cfg.JobPipeline().MaxSuccessfulRuns()) - bridgeORM := bridges.NewORM(db, lggr, cfg.Database()) + pipelineORM := pipeline.NewORM(coredb, lggr, cfg.Database(), cfg.JobPipeline().MaxSuccessfulRuns()) + bridgeORM := bridges.NewORM(coredb, lggr, cfg.Database()) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{GeneralConfig: cfg, DB: db, KeyStore: keyStore.Eth()}) + relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{GeneralConfig: cfg, DB: evmdb, KeyStore: keyStore.Eth()}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) // Instantiate a real job ORM because we need to create a job to satisfy // a check in pipeline.CreateRun - jobORM := job.NewORM(db, legacyChains, pipelineORM, bridgeORM, keyStore, lggr, cfg.Database()) - orm := newORM(t, db, cfg.Database(), nil) + jobORM := job.NewORM(coredb, legacyChains, pipelineORM, bridgeORM, keyStore, lggr, cfg.Database()) + orm := newORM(t, coredb, cfg.Database(), nil) address := testutils.NewAddress() var roundID uint32 = 1 diff --git a/core/services/functions/listener_test.go b/core/services/functions/listener_test.go index a06fcf3e3b2..b7e5f6baa0f 100644 --- a/core/services/functions/listener_test.go +++ b/core/services/functions/listener_test.go @@ -26,6 +26,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -87,9 +88,11 @@ func NewFunctionsListenerUniverse(t *testing.T, timeoutSec int, pruneFrequencySe broadcaster.On("AddDependents", 1) mailMon := srvctest.Start(t, utils.NewMailboxMonitor(t.Name())) - db := pgtest.NewSqlxDB(t) - kst := cltest.NewKeyStore(t, db, cfg.Database()) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, Client: ethClient, KeyStore: kst.Eth(), LogBroadcaster: broadcaster, MailMon: mailMon}) + coredb := pgtest.NewSqlxDB(t) + kst := cltest.NewKeyStore(t, coredb, cfg.Database()) + + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: evmdb, GeneralConfig: cfg, Client: ethClient, KeyStore: kst.Eth(), LogBroadcaster: broadcaster, MailMon: mailMon}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) chain := legacyChains.Slice()[0] diff --git a/core/services/job/helpers_test.go b/core/services/job/helpers_test.go index 167ed5297cc..92ede524d70 100644 --- a/core/services/job/helpers_test.go +++ b/core/services/job/helpers_test.go @@ -20,6 +20,7 @@ import ( "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" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/job" @@ -223,7 +224,8 @@ func makeMinimalHTTPOracleSpec(t *testing.T, db *sqlx.DB, cfg chainlink.GeneralC } s := fmt.Sprintf(minimalNonBootstrapTemplate, contractAddress, transmitterAddress, keyBundle, fetchUrl, timeout) keyStore := cltest.NewKeyStore(t, db, pgtest.NewQConfig(true)) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, Client: evmtest.NewEthClientMockWithDefaultChain(t), GeneralConfig: cfg, KeyStore: keyStore.Eth()}) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: evmdb, Client: evmtest.NewEthClientMockWithDefaultChain(t), GeneralConfig: cfg, KeyStore: keyStore.Eth()}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) _, err := ocr.ValidatedOracleSpecToml(legacyChains, s) require.NoError(t, err) diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go index bf81064e6a6..b826952eedf 100644 --- a/core/services/job/job_orm_test.go +++ b/core/services/job/job_orm_test.go @@ -17,15 +17,18 @@ import ( "github.com/smartcontractkit/chainlink-relay/pkg/types" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/assets" "github.com/smartcontractkit/chainlink/v2/core/bridges" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm" evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/blockhashstore" @@ -84,8 +87,7 @@ func TestORM(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.Database(), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db, logger.TestLogger(t), config.Database()) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: ethKeyStore}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := setupLegacyEVMChains(t, config, ethKeyStore) orm := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database()) borm := bridges.NewORM(db, logger.TestLogger(t), config.Database()) @@ -318,8 +320,8 @@ func TestORM_DeleteJob_DeletesAssociatedRecords(t *testing.T) { 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) + + legacyChains := setupLegacyEVMChains(t, config, keyStore.Eth()) jobORM := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database()) scopedConfig := evmtest.NewChainScopedConfig(t, config) korm := keeper.NewORM(db, logger.TestLogger(t), scopedConfig.Database()) @@ -418,8 +420,7 @@ func TestORM_CreateJob_VRFV2(t *testing.T) { 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) + legacyChains := setupLegacyEVMChains(t, config, keyStore.Eth()) jobORM := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database()) @@ -501,8 +502,7 @@ func TestORM_CreateJob_VRFV2Plus(t *testing.T) { lggr := logger.TestLogger(t) pipelineORM := pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db, lggr, config.Database()) - cc := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(cc) + legacyChains := setupLegacyEVMChains(t, config, keyStore.Eth()) jobORM := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database()) fromAddresses := []string{cltest.NewEIP55Address().String(), cltest.NewEIP55Address().String()} @@ -586,8 +586,7 @@ func TestORM_CreateJob_OCRBootstrap(t *testing.T) { 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) + legacyChains := setupLegacyEVMChains(t, config, keyStore.Eth()) jobORM := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database()) jb, err := ocrbootstrap.ValidatedBootstrapSpecToml(testspecs.OCRBootstrapSpec) @@ -615,8 +614,7 @@ func TestORM_CreateJob_EVMChainID_Validation(t *testing.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) + legacyChains := setupLegacyEVMChains(t, config, keyStore.Eth()) jobORM := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database()) t.Run("evm chain id validation for ocr works", func(t *testing.T) { @@ -712,8 +710,7 @@ func TestORM_CreateJob_OCR_DuplicatedContractAddress(t *testing.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) + legacyChains := setupLegacyEVMChains(t, config, keyStore.Eth()) jobORM := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database()) // defaultChainID is deprecated @@ -781,8 +778,7 @@ func TestORM_CreateJob_OCR2_DuplicatedContractAddress(t *testing.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) + legacyChains := setupLegacyEVMChains(t, config, keyStore.Eth()) jobORM := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database()) _, address := cltest.MustInsertRandomKey(t, keyStore.Eth()) @@ -844,9 +840,7 @@ func TestORM_CreateJob_OCR2_Sending_Keys_Transmitter_Keys_Validations(t *testing 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()}) - require.True(t, relayExtenders.Len() > 0) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := setupLegacyEVMChains(t, config, keyStore.Eth()) jobORM := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database()) jb, err := ocr2validate.ValidatedOracleSpecToml(config.OCR2(), config.Insecure(), testspecs.OCR2EVMSpecMinimal) @@ -957,8 +951,7 @@ func Test_FindJobs(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.Database(), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db, logger.TestLogger(t), config.Database()) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := setupLegacyEVMChains(t, config, keyStore.Eth()) orm := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database()) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}, config.Database()) @@ -1037,8 +1030,7 @@ func Test_FindJob(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.Database(), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db, logger.TestLogger(t), config.Database()) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := setupLegacyEVMChains(t, config, keyStore.Eth()) orm := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database()) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}, config.Database()) @@ -1215,8 +1207,7 @@ func Test_FindJobsByPipelineSpecIDs(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.Database(), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db, logger.TestLogger(t), config.Database()) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := setupLegacyEVMChains(t, config, keyStore.Eth()) orm := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database()) jb, err := directrequest.ValidatedDirectRequestSpec(testspecs.DirectRequestSpec) @@ -1256,7 +1247,7 @@ func Test_FindJobsByPipelineSpecIDs(t *testing.T) { Enabled: ptr(true), }) }) - relayExtenders2 := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: newCfg, KeyStore: keyStore.Eth()}) + relayExtenders2 := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: evmtestdb.NewScopedDB(t, newCfg.Database()), GeneralConfig: newCfg, KeyStore: keyStore.Eth()}) legacyChains2 := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders2) orm2 := NewTestORM(t, db, legacyChains2, pipelineORM, bridgesORM, keyStore, config.Database()) @@ -1278,8 +1269,7 @@ func Test_FindPipelineRuns(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.Database(), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db, logger.TestLogger(t), config.Database()) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := setupLegacyEVMChains(t, config, keyStore.Eth()) orm := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database()) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}, config.Database()) @@ -1339,8 +1329,7 @@ func Test_PipelineRunsByJobID(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.Database(), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db, logger.TestLogger(t), config.Database()) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := setupLegacyEVMChains(t, config, keyStore.Eth()) orm := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database()) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}, config.Database()) @@ -1400,8 +1389,7 @@ func Test_FindPipelineRunIDsByJobID(t *testing.T) { lggr := logger.TestLogger(t) pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), 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) + legacyChains := setupLegacyEVMChains(t, config, keyStore.Eth()) orm := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database()) _, address := cltest.MustInsertRandomKey(t, keyStore.Eth()) @@ -1508,8 +1496,7 @@ func Test_FindPipelineRunsByIDs(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.Database(), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db, logger.TestLogger(t), config.Database()) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := setupLegacyEVMChains(t, config, keyStore.Eth()) orm := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database()) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}, config.Database()) @@ -1566,8 +1553,7 @@ func Test_FindPipelineRunByID(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.Database(), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db, logger.TestLogger(t), config.Database()) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := setupLegacyEVMChains(t, config, keyStore.Eth()) orm := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database()) jb, err := directrequest.ValidatedDirectRequestSpec(testspecs.DirectRequestSpec) @@ -1611,8 +1597,7 @@ func Test_FindJobWithoutSpecErrors(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.Database(), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db, logger.TestLogger(t), config.Database()) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := setupLegacyEVMChains(t, config, keyStore.Eth()) orm := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database()) jb, err := directrequest.ValidatedDirectRequestSpec(testspecs.DirectRequestSpec) @@ -1650,8 +1635,7 @@ func Test_FindSpecErrorsByJobIDs(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.Database(), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db, logger.TestLogger(t), config.Database()) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := setupLegacyEVMChains(t, config, keyStore.Eth()) orm := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database()) jb, err := directrequest.ValidatedDirectRequestSpec(testspecs.DirectRequestSpec) @@ -1686,8 +1670,7 @@ func Test_CountPipelineRunsByJobID(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.Database(), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db, logger.TestLogger(t), config.Database()) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := setupLegacyEVMChains(t, config, keyStore.Eth()) orm := NewTestORM(t, db, legacyChains, pipelineORM, bridgesORM, keyStore, config.Database()) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}, config.Database()) @@ -1738,3 +1721,9 @@ func mustInsertPipelineRun(t *testing.T, orm pipeline.ORM, j job.Job) pipeline.R require.NoError(t, err) return run } + +func setupLegacyEVMChains(t *testing.T, cfg evm.AppConfig, ks keystore.Eth) *evm.LegacyChains { + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: evmdb, GeneralConfig: cfg, KeyStore: ks}) + return evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) +} diff --git a/core/services/job/job_pipeline_orm_integration_test.go b/core/services/job/job_pipeline_orm_integration_test.go index a5d3ee984da..e1ce4fa54b9 100644 --- a/core/services/job/job_pipeline_orm_integration_test.go +++ b/core/services/job/job_pipeline_orm_integration_test.go @@ -12,12 +12,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/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/store/models" ) @@ -151,8 +149,7 @@ func TestPipelineORM_Integration(t *testing.T) { clearJobsDb(t, db) orm := pipeline.NewORM(db, logger.TestLogger(t), cfg.Database(), cfg.JobPipeline().MaxSuccessfulRuns()) btORM := bridges.NewORM(db, logger.TestLogger(t), cfg.Database()) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{Client: evmtest.NewEthClientMockWithDefaultChain(t), DB: db, GeneralConfig: config, KeyStore: ethKeyStore}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := setupLegacyEVMChains(t, config, keyStore.Eth()) runner := pipeline.NewRunner(orm, btORM, config.JobPipeline(), cfg.WebServer(), legacyChains, nil, nil, lggr, nil, nil) jobORM := NewTestORM(t, db, legacyChains, orm, btORM, keyStore, cfg.Database()) diff --git a/core/services/job/runner_integration_test.go b/core/services/job/runner_integration_test.go index a886c52f283..6294499d35c 100644 --- a/core/services/job/runner_integration_test.go +++ b/core/services/job/runner_integration_test.go @@ -81,8 +81,7 @@ func TestRunner(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.Database(), config.JobPipeline().MaxSuccessfulRuns()) btORM := bridges.NewORM(db, logger.TestLogger(t), config.Database()) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, Client: ethClient, GeneralConfig: config, KeyStore: ethKeyStore}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := setupLegacyEVMChains(t, config, keyStore.Eth()) c := clhttptest.NewTestLocalOnlyHTTPClient() runner := pipeline.NewRunner(pipelineORM, btORM, config.JobPipeline(), config.WebServer(), legacyChains, nil, nil, logger.TestLogger(t), c, c) @@ -767,8 +766,7 @@ func TestRunner_Success_Callback_AsyncJob(t *testing.T) { app := cltest.NewApplicationWithConfig(t, cfg, ethClient, cltest.UseRealExternalInitiatorManager) keyStore := cltest.NewKeyStore(t, app.GetSqlxDB(), pgtest.NewQConfig(true)) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: app.GetSqlxDB(), Client: ethClient, GeneralConfig: cfg, KeyStore: keyStore.Eth()}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := setupLegacyEVMChains(t, cfg, keyStore.Eth()) require.NoError(t, app.Start(testutils.Context(t))) var ( @@ -949,7 +947,7 @@ func TestRunner_Error_Callback_AsyncJob(t *testing.T) { app := cltest.NewApplicationWithConfig(t, cfg, ethClient, cltest.UseRealExternalInitiatorManager) keyStore := cltest.NewKeyStore(t, app.GetSqlxDB(), pgtest.NewQConfig(true)) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: app.GetSqlxDB(), Client: ethClient, GeneralConfig: cfg, KeyStore: keyStore.Eth()}) + relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: app.GetRelayers().LegacyEVM().DB(), Client: ethClient, GeneralConfig: cfg, KeyStore: keyStore.Eth()}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) require.NoError(t, app.Start(testutils.Context(t))) diff --git a/core/services/job/spawner_test.go b/core/services/job/spawner_test.go index 7dbf811f783..e7dc1064d0c 100644 --- a/core/services/job/spawner_test.go +++ b/core/services/job/spawner_test.go @@ -22,6 +22,7 @@ import ( "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" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -95,8 +96,7 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { }). Return(nil).Maybe() - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, Client: ethClient, GeneralConfig: config, KeyStore: ethKeyStore}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := setupLegacyEVMChains(t, config, keyStore.Eth()) t.Run("should respect its dependents", func(t *testing.T) { lggr := logger.TestLogger(t) orm := NewTestORM(t, db, legacyChains, pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db, lggr, config.Database()), keyStore, config.Database()) @@ -270,8 +270,9 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { c.Feature.LogPoller = func(b bool) *bool { return &b }(true) }) lp := &mocklp.LogPoller{} + evmdb := evmtestdb.NewScopedDB(t, config.Database()) testopts := evmtest.TestChainOpts{ - DB: db, + DB: evmdb, Client: ethClient, GeneralConfig: config, LogPoller: lp, @@ -285,7 +286,7 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { chain := evmtest.MustGetDefaultChain(t, legacyChains) evmRelayer, err := evmrelayer.NewRelayer(lggr, chain, evmrelayer.RelayerOpts{ - DB: db, + DB: evmdb, QConfig: testopts.GeneralConfig.Database(), CSAETHKeystore: keyStore, EventBroadcaster: pg.NewNullEventBroadcaster(), diff --git a/core/services/keeper/integration_test.go b/core/services/keeper/integration_test.go index 39431063bcd..be1e6a81ff7 100644 --- a/core/services/keeper/integration_test.go +++ b/core/services/keeper/integration_test.go @@ -13,6 +13,7 @@ import ( "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/onsi/gomega" "github.com/pkg/errors" + "github.com/smartcontractkit/libocr/gethwrappers/link_token_interface" "github.com/stretchr/testify/require" @@ -247,6 +248,7 @@ func TestKeeperEthIntegration(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 }) + scopedConfig := evmtest.NewChainScopedConfig(t, config) korm := keeper.NewORM(db, logger.TestLogger(t), scopedConfig.Database()) @@ -407,13 +409,16 @@ func TestKeeperForwarderEthIntegration(t *testing.T) { c.EVM[0].Transactions.ForwardersEnabled = ptr(true) // Enable Operator Forwarder flow c.EVM[0].ChainID = (*utils.Big)(testutils.SimulatedChainID) }) + + require.NoError(t, err) + scopedConfig := evmtest.NewChainScopedConfig(t, config) korm := keeper.NewORM(db, logger.TestLogger(t), scopedConfig.Database()) app := cltest.NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain(t, config, backend.Backend(), nodeKey) require.NoError(t, app.Start(testutils.Context(t))) - - forwarderORM := forwarders.NewORM(db, logger.TestLogger(t), config.Database()) + evmdb := heavyweight.EVMDB(t, config.Database()) + forwarderORM := forwarders.NewORM(evmdb, logger.TestLogger(t), config.Database()) chainID := utils.Big(*backend.ConfiguredChainID()) _, err = forwarderORM.CreateForwarder(fwdrAddress, chainID) require.NoError(t, err) diff --git a/core/services/keeper/registry1_1_synchronizer_test.go b/core/services/keeper/registry1_1_synchronizer_test.go index 8444aa50dd4..02ba1ef10e9 100644 --- a/core/services/keeper/registry1_1_synchronizer_test.go +++ b/core/services/keeper/registry1_1_synchronizer_test.go @@ -20,6 +20,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keeper" @@ -229,8 +230,7 @@ func Test_RegistrySynchronizer1_1_ConfigSetLog(t *testing.T) { registryMock.MockResponse("getKeeperList", []common.Address{fromAddress}).Once() registryMock.MockResponse("getConfig", newConfig).Once() - cfg := configtest.NewGeneralConfig(t, nil) - head := cltest.MustInsertHead(t, db, cfg.Database(), 1) + head := getTestHead(t, 1) rawLog := types.Log{BlockHash: head.Hash} log := registry1_1.KeeperRegistryConfigSet{} logBroadcast := logmocks.NewBroadcast(t) @@ -277,8 +277,7 @@ func Test_RegistrySynchronizer1_1_KeepersUpdatedLog(t *testing.T) { registryMock.MockResponse("getConfig", registryConfig1_1).Once() registryMock.MockResponse("getKeeperList", addresses).Once() - cfg := configtest.NewGeneralConfig(t, nil) - head := cltest.MustInsertHead(t, db, cfg.Database(), 1) + head := getTestHead(t, 1) rawLog := types.Log{BlockHash: head.Hash} log := registry1_1.KeeperRegistryKeepersUpdated{} logBroadcast := logmocks.NewBroadcast(t) @@ -318,8 +317,7 @@ func Test_RegistrySynchronizer1_1_UpkeepCanceledLog(t *testing.T) { cltest.WaitForCount(t, db, "keeper_registries", 1) cltest.WaitForCount(t, db, "upkeep_registrations", 3) - cfg := configtest.NewGeneralConfig(t, nil) - head := cltest.MustInsertHead(t, db, cfg.Database(), 1) + head := getTestHead(t, 1) rawLog := types.Log{BlockHash: head.Hash} log := registry1_1.KeeperRegistryUpkeepCanceled{Id: big.NewInt(1)} logBroadcast := logmocks.NewBroadcast(t) @@ -360,8 +358,7 @@ func Test_RegistrySynchronizer1_1_UpkeepRegisteredLog(t *testing.T) { registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_1ABI, contractAddress) registryMock.MockResponse("getUpkeep", upkeepConfig1_1).Once() - cfg := configtest.NewGeneralConfig(t, nil) - head := cltest.MustInsertHead(t, db, cfg.Database(), 1) + head := getTestHead(t, 1) rawLog := types.Log{BlockHash: head.Hash} log := registry1_1.KeeperRegistryUpkeepRegistered{Id: big.NewInt(1)} logBroadcast := logmocks.NewBroadcast(t) @@ -403,8 +400,7 @@ func Test_RegistrySynchronizer1_1_UpkeepPerformedLog(t *testing.T) { pgtest.MustExec(t, db, `UPDATE upkeep_registrations SET last_run_block_height = 100`) - cfg := configtest.NewGeneralConfig(t, nil) - head := cltest.MustInsertHead(t, db, cfg.Database(), 1) + head := getTestHead(t, 1) rawLog := types.Log{BlockHash: head.Hash, BlockNumber: 200} log := registry1_1.KeeperRegistryUpkeepPerformed{Id: big.NewInt(0), From: fromAddress} logBroadcast := logmocks.NewBroadcast(t) @@ -431,3 +427,9 @@ func Test_RegistrySynchronizer1_1_UpkeepPerformedLog(t *testing.T) { return upkeep.LastKeeperIndex.Int64 }, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal(int64(0))) } + +func getTestHead(t *testing.T, number int64) evmtypes.Head { + cfg := configtest.NewGeneralConfig(t, nil) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + return cltest.MustInsertHead(t, evmdb, cfg.Database(), number) +} diff --git a/core/services/keeper/registry1_2_synchronizer_test.go b/core/services/keeper/registry1_2_synchronizer_test.go index f593a638f99..c48764a74ef 100644 --- a/core/services/keeper/registry1_2_synchronizer_test.go +++ b/core/services/keeper/registry1_2_synchronizer_test.go @@ -252,8 +252,7 @@ func Test_RegistrySynchronizer1_2_ConfigSetLog(t *testing.T) { Keepers: []common.Address{fromAddress}, }).Once() - cfg := configtest.NewGeneralConfig(t, nil) - head := cltest.MustInsertHead(t, db, cfg.Database(), 1) + head := getTestHead(t, 1) rawLog := types.Log{BlockHash: head.Hash} log := registry1_2.KeeperRegistryConfigSet{} logBroadcast := logmocks.NewBroadcast(t) @@ -304,8 +303,7 @@ func Test_RegistrySynchronizer1_2_KeepersUpdatedLog(t *testing.T) { Keepers: addresses, }).Once() - cfg := configtest.NewGeneralConfig(t, nil) - head := cltest.MustInsertHead(t, db, cfg.Database(), 1) + head := getTestHead(t, 1) rawLog := types.Log{BlockHash: head.Hash} log := registry1_2.KeeperRegistryKeepersUpdated{} logBroadcast := logmocks.NewBroadcast(t) @@ -347,8 +345,7 @@ func Test_RegistrySynchronizer1_2_UpkeepCanceledLog(t *testing.T) { cltest.WaitForCount(t, db, "keeper_registries", 1) cltest.WaitForCount(t, db, "upkeep_registrations", 3) - cfg := configtest.NewGeneralConfig(t, nil) - head := cltest.MustInsertHead(t, db, cfg.Database(), 1) + head := getTestHead(t, 1) rawLog := types.Log{BlockHash: head.Hash} log := registry1_2.KeeperRegistryUpkeepCanceled{Id: big.NewInt(3)} logBroadcast := logmocks.NewBroadcast(t) @@ -390,8 +387,7 @@ func Test_RegistrySynchronizer1_2_UpkeepRegisteredLog(t *testing.T) { registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_2ABI, contractAddress) registryMock.MockResponse("getUpkeep", upkeepConfig1_2).Once() - cfg := configtest.NewGeneralConfig(t, nil) - head := cltest.MustInsertHead(t, db, cfg.Database(), 1) + head := getTestHead(t, 1) rawLog := types.Log{BlockHash: head.Hash} log := registry1_2.KeeperRegistryUpkeepRegistered{Id: big.NewInt(420)} logBroadcast := logmocks.NewBroadcast(t) @@ -434,8 +430,7 @@ func Test_RegistrySynchronizer1_2_UpkeepPerformedLog(t *testing.T) { pgtest.MustExec(t, db, `UPDATE upkeep_registrations SET last_run_block_height = 100`) - cfg := configtest.NewGeneralConfig(t, nil) - head := cltest.MustInsertHead(t, db, cfg.Database(), 1) + head := getTestHead(t, 1) rawLog := types.Log{BlockHash: head.Hash, BlockNumber: 200} log := registry1_2.KeeperRegistryUpkeepPerformed{Id: big.NewInt(3), From: fromAddress} logBroadcast := logmocks.NewBroadcast(t) @@ -500,8 +495,7 @@ func Test_RegistrySynchronizer1_2_UpkeepGasLimitSetLog(t *testing.T) { newConfig.ExecuteGas = 4_000_000 // change from default registryMock.MockResponse("getUpkeep", newConfig).Once() - cfg := configtest.NewGeneralConfig(t, nil) - head := cltest.MustInsertHead(t, db, cfg.Database(), 1) + head := getTestHead(t, 1) rawLog := types.Log{BlockHash: head.Hash} log := registry1_2.KeeperRegistryUpkeepGasLimitSet{Id: big.NewInt(3), GasLimit: big.NewInt(4_000_000)} logBroadcast := logmocks.NewBroadcast(t) @@ -543,8 +537,7 @@ func Test_RegistrySynchronizer1_2_UpkeepReceivedLog(t *testing.T) { registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_2ABI, contractAddress) registryMock.MockResponse("getUpkeep", upkeepConfig1_2).Once() - cfg := configtest.NewGeneralConfig(t, nil) - head := cltest.MustInsertHead(t, db, cfg.Database(), 1) + head := getTestHead(t, 1) rawLog := types.Log{BlockHash: head.Hash} log := registry1_2.KeeperRegistryUpkeepReceived{Id: big.NewInt(420)} logBroadcast := logmocks.NewBroadcast(t) @@ -583,8 +576,7 @@ func Test_RegistrySynchronizer1_2_UpkeepMigratedLog(t *testing.T) { cltest.WaitForCount(t, db, "keeper_registries", 1) cltest.WaitForCount(t, db, "upkeep_registrations", 3) - cfg := configtest.NewGeneralConfig(t, nil) - head := cltest.MustInsertHead(t, db, cfg.Database(), 1) + head := getTestHead(t, 1) rawLog := types.Log{BlockHash: head.Hash} log := registry1_2.KeeperRegistryUpkeepMigrated{Id: big.NewInt(3)} logBroadcast := logmocks.NewBroadcast(t) diff --git a/core/services/keeper/registry1_3_synchronizer_test.go b/core/services/keeper/registry1_3_synchronizer_test.go index 53b5cbf983f..42141898a8a 100644 --- a/core/services/keeper/registry1_3_synchronizer_test.go +++ b/core/services/keeper/registry1_3_synchronizer_test.go @@ -257,8 +257,7 @@ func Test_RegistrySynchronizer1_3_ConfigSetLog(t *testing.T) { Keepers: []common.Address{fromAddress}, }).Once() - cfg := configtest.NewGeneralConfig(t, nil) - head := cltest.MustInsertHead(t, db, cfg.Database(), 1) + head := getTestHead(t, 1) rawLog := types.Log{BlockHash: head.Hash} log := registry1_3.KeeperRegistryConfigSet{} logBroadcast := logmocks.NewBroadcast(t) @@ -309,8 +308,7 @@ func Test_RegistrySynchronizer1_3_KeepersUpdatedLog(t *testing.T) { Keepers: addresses, }).Once() - cfg := configtest.NewGeneralConfig(t, nil) - head := cltest.MustInsertHead(t, db, cfg.Database(), 1) + head := getTestHead(t, 1) rawLog := types.Log{BlockHash: head.Hash} log := registry1_3.KeeperRegistryKeepersUpdated{} logBroadcast := logmocks.NewBroadcast(t) @@ -352,8 +350,7 @@ func Test_RegistrySynchronizer1_3_UpkeepCanceledLog(t *testing.T) { cltest.WaitForCount(t, db, "keeper_registries", 1) cltest.WaitForCount(t, db, "upkeep_registrations", 3) - cfg := configtest.NewGeneralConfig(t, nil) - head := cltest.MustInsertHead(t, db, cfg.Database(), 1) + head := getTestHead(t, 1) rawLog := types.Log{BlockHash: head.Hash} log := registry1_3.KeeperRegistryUpkeepCanceled{Id: big.NewInt(3)} logBroadcast := logmocks.NewBroadcast(t) @@ -395,8 +392,7 @@ func Test_RegistrySynchronizer1_3_UpkeepRegisteredLog(t *testing.T) { registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_3ABI, contractAddress) registryMock.MockResponse("getUpkeep", upkeepConfig1_3).Once() - cfg := configtest.NewGeneralConfig(t, nil) - head := cltest.MustInsertHead(t, db, cfg.Database(), 1) + head := getTestHead(t, 1) rawLog := types.Log{BlockHash: head.Hash} log := registry1_3.KeeperRegistryUpkeepRegistered{Id: big.NewInt(420)} logBroadcast := logmocks.NewBroadcast(t) @@ -439,8 +435,7 @@ func Test_RegistrySynchronizer1_3_UpkeepPerformedLog(t *testing.T) { pgtest.MustExec(t, db, `UPDATE upkeep_registrations SET last_run_block_height = 100`) - cfg := configtest.NewGeneralConfig(t, nil) - head := cltest.MustInsertHead(t, db, cfg.Database(), 1) + head := getTestHead(t, 1) rawLog := types.Log{BlockHash: head.Hash, BlockNumber: 200} log := registry1_3.KeeperRegistryUpkeepPerformed{Id: big.NewInt(3), From: fromAddress} logBroadcast := logmocks.NewBroadcast(t) @@ -505,8 +500,7 @@ func Test_RegistrySynchronizer1_3_UpkeepGasLimitSetLog(t *testing.T) { newConfig.ExecuteGas = 4_000_000 // change from default registryMock.MockResponse("getUpkeep", newConfig).Once() - cfg := configtest.NewGeneralConfig(t, nil) - head := cltest.MustInsertHead(t, db, cfg.Database(), 1) + head := getTestHead(t, 1) rawLog := types.Log{BlockHash: head.Hash} log := registry1_3.KeeperRegistryUpkeepGasLimitSet{Id: big.NewInt(3), GasLimit: big.NewInt(4_000_000)} logBroadcast := logmocks.NewBroadcast(t) @@ -548,8 +542,7 @@ func Test_RegistrySynchronizer1_3_UpkeepReceivedLog(t *testing.T) { registryMock := cltest.NewContractMockReceiver(t, ethMock, keeper.Registry1_3ABI, contractAddress) registryMock.MockResponse("getUpkeep", upkeepConfig1_3).Once() - cfg := configtest.NewGeneralConfig(t, nil) - head := cltest.MustInsertHead(t, db, cfg.Database(), 1) + head := getTestHead(t, 1) rawLog := types.Log{BlockHash: head.Hash} log := registry1_3.KeeperRegistryUpkeepReceived{Id: big.NewInt(420)} logBroadcast := logmocks.NewBroadcast(t) @@ -588,8 +581,7 @@ func Test_RegistrySynchronizer1_3_UpkeepMigratedLog(t *testing.T) { cltest.WaitForCount(t, db, "keeper_registries", 1) cltest.WaitForCount(t, db, "upkeep_registrations", 3) - cfg := configtest.NewGeneralConfig(t, nil) - head := cltest.MustInsertHead(t, db, cfg.Database(), 1) + head := getTestHead(t, 1) rawLog := types.Log{BlockHash: head.Hash} log := registry1_3.KeeperRegistryUpkeepMigrated{Id: big.NewInt(3)} logBroadcast := logmocks.NewBroadcast(t) @@ -630,8 +622,7 @@ func Test_RegistrySynchronizer1_3_UpkeepPausedLog_UpkeepUnpausedLog(t *testing.T cltest.WaitForCount(t, db, "keeper_registries", 1) cltest.WaitForCount(t, db, "upkeep_registrations", 3) - cfg := configtest.NewGeneralConfig(t, nil) - head := cltest.MustInsertHead(t, db, cfg.Database(), 1) + head := getTestHead(t, 1) rawLog := types.Log{BlockHash: head.Hash} log := registry1_3.KeeperRegistryUpkeepPaused{Id: upkeepId} logBroadcast := logmocks.NewBroadcast(t) @@ -646,8 +637,7 @@ func Test_RegistrySynchronizer1_3_UpkeepPausedLog_UpkeepUnpausedLog(t *testing.T cltest.WaitForCount(t, db, "upkeep_registrations", 2) - cfg = configtest.NewGeneralConfig(t, nil) - head = cltest.MustInsertHead(t, db, cfg.Database(), 2) + head = getTestHead(t, 2) rawLog = types.Log{BlockHash: head.Hash} unpausedlog := registry1_3.KeeperRegistryUpkeepUnpaused{Id: upkeepId} logBroadcast = logmocks.NewBroadcast(t) @@ -700,8 +690,7 @@ func Test_RegistrySynchronizer1_3_UpkeepCheckDataUpdatedLog(t *testing.T) { cltest.WaitForCount(t, db, "keeper_registries", 1) cltest.WaitForCount(t, db, "upkeep_registrations", 1) - cfg := configtest.NewGeneralConfig(t, nil) - head := cltest.MustInsertHead(t, db, cfg.Database(), 1) + head := getTestHead(t, 1) rawLog := types.Log{BlockHash: head.Hash} _ = logmocks.NewBroadcast(t) newCheckData := []byte("Chainlink") diff --git a/core/services/keeper/registry_synchronizer_helper_test.go b/core/services/keeper/registry_synchronizer_helper_test.go index 6b9bb815a89..ab22963bfbe 100644 --- a/core/services/keeper/registry_synchronizer_helper_test.go +++ b/core/services/keeper/registry_synchronizer_helper_test.go @@ -15,6 +15,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" @@ -43,7 +44,8 @@ func setupRegistrySync(t *testing.T, version keeper.RegistryVersion) ( lbMock := logmocks.NewBroadcaster(t) lbMock.On("AddDependents", 1).Maybe() j := cltest.MustInsertKeeperJob(t, db, korm, cltest.NewEIP55Address(), cltest.NewEIP55Address()) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, Client: ethClient, LogBroadcaster: lbMock, GeneralConfig: cfg, KeyStore: keyStore.Eth()}) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: evmdb, Client: ethClient, LogBroadcaster: lbMock, GeneralConfig: cfg, KeyStore: keyStore.Eth()}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) ch := evmtest.MustGetDefaultChain(t, legacyChains) jpv2 := cltest.NewJobPipelineV2(t, cfg.WebServer(), cfg.JobPipeline(), cfg.Database(), legacyChains, db, keyStore, nil, nil) diff --git a/core/services/keeper/upkeep_executer_test.go b/core/services/keeper/upkeep_executer_test.go index 702633e1d08..3d22180e3fb 100644 --- a/core/services/keeper/upkeep_executer_test.go +++ b/core/services/keeper/upkeep_executer_test.go @@ -26,6 +26,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -77,7 +78,8 @@ func setup(t *testing.T, estimator gas.EvmFeeEstimator, overrideFn func(c *chain 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}) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{TxManager: txm, DB: evmdb, Client: ethClient, KeyStore: keyStore.Eth(), GeneralConfig: cfg, GasEstimator: estimator}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) jpv2 := cltest.NewJobPipelineV2(t, cfg.WebServer(), cfg.JobPipeline(), cfg.Database(), legacyChains, db, keyStore, nil, nil) ch := evmtest.MustGetDefaultChain(t, legacyChains) diff --git a/core/services/keystore/eth_test.go b/core/services/keystore/eth_test.go index 78131bec133..ff97f6e5e8c 100644 --- a/core/services/keystore/eth_test.go +++ b/core/services/keystore/eth_test.go @@ -19,6 +19,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" @@ -32,6 +33,7 @@ func Test_EthKeyStore(t *testing.T) { cfg := configtest.NewTestGeneralConfig(t) keyStore := keystore.ExposedNewMaster(t, db, cfg.Database()) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) err := keyStore.Unlock(cltest.Password) require.NoError(t, err) ethKeyStore := keyStore.Eth() @@ -112,7 +114,7 @@ func Test_EthKeyStore(t *testing.T) { cltest.AssertCount(t, db, statesTableName, 1) // add one eth_tx - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + txStore := cltest.NewTestTxStore(t, evmdb, cfg.Database()) cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 42, key.Address) _, err = ethKeyStore.Delete(key.ID()) diff --git a/core/services/ocr2/delegate_test.go b/core/services/ocr2/delegate_test.go index 97c9faa44d4..36c1258259e 100644 --- a/core/services/ocr2/delegate_test.go +++ b/core/services/ocr2/delegate_test.go @@ -15,6 +15,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -43,8 +44,9 @@ func TestGetEVMEffectiveTransmitterID(t *testing.T) { require.NoError(t, keyStore.OCR2().Add(cltest.DefaultOCR2Key)) lggr := logger.TestLogger(t) + evmdb := evmtestdb.NewScopedDB(t, config.Database()) txManager := txmmocks.NewMockEvmTxManager(t) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth(), TxManager: txManager}) + relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: evmdb, GeneralConfig: config, KeyStore: keyStore.Eth(), TxManager: txManager}) require.True(t, relayExtenders.Len() > 0) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) diff --git a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go index b5f229f6015..ad1e2aebe5b 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evm21/logprovider/integration_test.go @@ -20,13 +20,13 @@ import ( "go.uber.org/zap/zapcore" "golang.org/x/time/rate" - "github.com/smartcontractkit/sqlx" - ocr2keepers "github.com/smartcontractkit/ocr2keepers/pkg/v3/types" "github.com/smartcontractkit/chainlink/v2/core/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_utils_2_1" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_upkeep_counter_wrapper" @@ -662,7 +662,7 @@ func newPlainLogTriggerConfig(upkeepAddr common.Address) logprovider.LogTriggerC } } -func setupDependencies(t *testing.T, db *sqlx.DB, backend *backends.SimulatedBackend) (logpoller.LogPollerTest, *evmclient.SimulatedBackendClient, abi.ABI) { +func setupDependencies(t *testing.T, db *evmdb.ScopedDB, backend *backends.SimulatedBackend) (logpoller.LogPollerTest, *evmclient.SimulatedBackendClient, abi.ABI) { ethClient := evmclient.NewSimulatedBackendClient(t, backend, big.NewInt(1337)) pollerLggr := logger.TestLogger(t) pollerLggr.SetLogLevel(zapcore.WarnLevel) @@ -703,8 +703,8 @@ func setupBackend(t *testing.T) (*backends.SimulatedBackend, func(), []*bind.Tra func ptr[T any](v T) *T { return &v } -func setupDB(t *testing.T) *sqlx.DB { - _, db := heavyweight.FullTestDBV2(t, fmt.Sprintf("%s%d", "chainlink_test", 5432), func(c *chainlink.Config, s *chainlink.Secrets) { +func setupDB(t *testing.T) *evmdb.ScopedDB { + cfg, _ := heavyweight.FullTestDBV2(t, fmt.Sprintf("%s%d", "chainlink_test", 5432), func(c *chainlink.Config, s *chainlink.Secrets) { c.Feature.LogPoller = ptr(true) c.OCR.Enabled = ptr(false) @@ -713,7 +713,8 @@ func setupDB(t *testing.T) *sqlx.DB { c.EVM[0].Transactions.ForwardersEnabled = ptr(true) c.EVM[0].GasEstimator.Mode = ptr("FixedPrice") }) - return db + evmdb := heavyweight.EVMDB(t, cfg.Database()) + return evmdb } type mockUpkeepStateStore struct { diff --git a/core/services/ocr2/plugins/ocr2keeper/integration_test.go b/core/services/ocr2/plugins/ocr2keeper/integration_test.go index eea9c1574cf..1a70e14d6fd 100644 --- a/core/services/ocr2/plugins/ocr2keeper/integration_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/integration_test.go @@ -449,7 +449,7 @@ func setupForwarderForNode( backend.Commit() // add forwarder address to be tracked in db - forwarderORM := forwarders.NewORM(app.GetSqlxDB(), logger.TestLogger(t), app.GetConfig().Database()) + forwarderORM := forwarders.NewORM(app.GetRelayers().LegacyEVM().DB(), logger.TestLogger(t), app.GetConfig().Database()) chainID := utils.Big(*backend.Blockchain().Config().ChainID) _, err = forwarderORM.CreateForwarder(faddr, chainID) require.NoError(t, err) diff --git a/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go b/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go index c6a4552683a..cb357962638 100644 --- a/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go +++ b/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go @@ -281,7 +281,7 @@ func setupNodeOCR2( b.Commit() // Add the forwarder to the node's forwarder manager. - forwarderORM := forwarders.NewORM(app.GetSqlxDB(), logger.TestLogger(t), config.Database()) + forwarderORM := forwarders.NewORM(app.GetRelayers().LegacyEVM().DB(), logger.TestLogger(t), config.Database()) chainID := utils.Big(*b.Blockchain().Config().ChainID) _, err = forwarderORM.CreateForwarder(faddr, chainID) require.NoError(t, err) diff --git a/core/services/pg/locked_db.go b/core/services/pg/locked_db.go index f4f8bfa3b36..7d946baee41 100644 --- a/core/services/pg/locked_db.go +++ b/core/services/pg/locked_db.go @@ -175,9 +175,8 @@ func SchemaScopedConnection(conn url.URL, schema string) url.URL { // https://www.postgresql.org/docs/16/app-psql.html u := conn - opt := "options=-csearch_path=" queryVals := u.Query() - queryVals.Add(opt, schema) + queryVals.Add("options", "-csearch_path="+schema) u.RawQuery = queryVals.Encode() return u diff --git a/core/services/pipeline/orm_test.go b/core/services/pipeline/orm_test.go index 4c03ce16ef8..b5ddc7aa742 100644 --- a/core/services/pipeline/orm_test.go +++ b/core/services/pipeline/orm_test.go @@ -12,15 +12,18 @@ import ( "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink/v2/core/bridges" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm" "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" configtest2 "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/job" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" @@ -521,8 +524,7 @@ func Test_GetUnfinishedRuns_Keepers(t *testing.T) { porm := pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns()) bridgeORM := bridges.NewORM(db, lggr, config.Database()) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := setupLegacyEVMChains(t, config, keyStore.Eth()) jorm := job.NewORM(db, legacyChains, porm, bridgeORM, keyStore, lggr, config.Database()) defer func() { assert.NoError(t, jorm.Close()) }() @@ -623,8 +625,7 @@ func Test_GetUnfinishedRuns_DirectRequest(t *testing.T) { porm := pipeline.NewORM(db, lggr, config.Database(), config.JobPipeline().MaxSuccessfulRuns()) bridgeORM := bridges.NewORM(db, lggr, config.Database()) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := setupLegacyEVMChains(t, config, keyStore.Eth()) jorm := job.NewORM(db, legacyChains, porm, bridgeORM, keyStore, lggr, config.Database()) defer func() { assert.NoError(t, jorm.Close()) }() @@ -765,3 +766,9 @@ func Test_Prune(t *testing.T) { cnt = pgtest.MustCount(t, db, "SELECT count(*) FROM pipeline_runs WHERE pipeline_spec_id = $1 AND state = $2", ps2.ID, pipeline.RunStatusSuspended) assert.Equal(t, 3, cnt) } + +func setupLegacyEVMChains(t testing.TB, config evm.AppConfig, ks keystore.Eth) *evm.LegacyChains { + evmdb := evmtestdb.NewScopedDB(t, config.Database()) + relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: evmdb, GeneralConfig: config, KeyStore: ks}) + return evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) +} diff --git a/core/services/pipeline/runner_test.go b/core/services/pipeline/runner_test.go index 22b70829ba5..dfce7a1a361 100644 --- a/core/services/pipeline/runner_test.go +++ b/core/services/pipeline/runner_test.go @@ -20,14 +20,11 @@ import ( "github.com/stretchr/testify/require" "gopkg.in/guregu/null.v4" - evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - "github.com/smartcontractkit/chainlink/v2/core/bridges" bridgesMocks "github.com/smartcontractkit/chainlink/v2/core/bridges/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" clhttptest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/httptest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -43,8 +40,7 @@ import ( func newRunner(t testing.TB, db *sqlx.DB, bridgeORM bridges.ORM, cfg chainlink.GeneralConfig) (pipeline.Runner, *mocks.ORM) { lggr := logger.TestLogger(t) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, KeyStore: ethKeyStore}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := setupLegacyEVMChains(t, cfg, ethKeyStore) orm := mocks.NewORM(t) q := pg.NewQ(db, lggr, cfg.Database()) @@ -480,8 +476,7 @@ func Test_PipelineRunner_HandleFaultsPersistRun(t *testing.T) { Return(nil) cfg := configtest.NewTestGeneralConfig(t) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, KeyStore: ethKeyStore}) - legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) + legacyChains := setupLegacyEVMChains(t, cfg, ethKeyStore) lggr := logger.TestLogger(t) r := pipeline.NewRunner(orm, btORM, cfg.JobPipeline(), cfg.WebServer(), legacyChains, ethKeyStore, nil, lggr, nil, nil) diff --git a/core/services/pipeline/task.eth_call_test.go b/core/services/pipeline/task.eth_call_test.go index 77a10681fb4..1d4e5a33426 100644 --- a/core/services/pipeline/task.eth_call_test.go +++ b/core/services/pipeline/task.eth_call_test.go @@ -19,7 +19,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "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/internal/testutils/pgtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" keystoremocks "github.com/smartcontractkit/chainlink/v2/core/services/keystore/mocks" @@ -254,12 +254,12 @@ func TestETHCallTask(t *testing.T) { lggr := logger.TestLogger(t) keyStore := keystoremocks.NewEth(t) - txManager := txmmocks.NewMockEvmTxManager(t) - db := pgtest.NewSqlxDB(t) var legacyChains evm.LegacyChainContainer if test.expectedErrorCause != nil || test.expectedErrorContains != "" { - exts := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, TxManager: txManager, KeyStore: keyStore}) + txManager := txmmocks.NewMockEvmTxManager(t) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + exts := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: evmdb, GeneralConfig: cfg, TxManager: txManager, KeyStore: keyStore}) legacyChains = evmrelay.NewLegacyChainsFromRelayerExtenders(exts) } else { legacyChains = cltest.NewLegacyChainsWithMockChain(t, ethClient, cfg) diff --git a/core/services/pipeline/task.eth_tx_test.go b/core/services/pipeline/task.eth_tx_test.go index a280e6f2720..57cd35d69fd 100644 --- a/core/services/pipeline/task.eth_tx_test.go +++ b/core/services/pipeline/task.eth_tx_test.go @@ -17,7 +17,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "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/internal/testutils/pgtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/logger" clnull "github.com/smartcontractkit/chainlink/v2/core/null" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -566,14 +566,14 @@ func TestETHTxTask(t *testing.T) { keyStore := keystoremocks.NewEth(t) txManager := txmmocks.NewMockEvmTxManager(t) - db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].GasEstimator.LimitDefault = ptr(defaultGasLimit) c.EVM[0].GasEstimator.LimitJobType.DR = ptr(drJobTypeGasLimit) }) lggr := logger.TestLogger(t) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: evmdb, GeneralConfig: cfg, TxManager: txManager, KeyStore: keyStore}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) diff --git a/core/services/promreporter/prom_reporter_test.go b/core/services/promreporter/prom_reporter_test.go index 9629045cb0b..87c227a4554 100644 --- a/core/services/promreporter/prom_reporter_test.go +++ b/core/services/promreporter/prom_reporter_test.go @@ -9,6 +9,7 @@ import ( evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/services/promreporter" "github.com/stretchr/testify/assert" @@ -55,10 +56,11 @@ func Test_PromReporter_OnNewLongestChain(t *testing.T) { }) t.Run("with unconfirmed evm.txes", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) + coredb := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + txStore := cltest.NewTestTxStore(t, evmdb, cfg.Database()) + ethKeyStore := cltest.NewKeyStore(t, coredb, cfg.Database()).Eth() _, fromAddress := cltest.MustAddRandomKeyToKeystore(t, ethKeyStore) var subscribeCalls atomic.Int32 @@ -75,14 +77,14 @@ func Test_PromReporter_OnNewLongestChain(t *testing.T) { subscribeCalls.Add(1) }). Return() - reporter := promreporter.NewPromReporter(db.DB, logger.TestLogger(t), backend, 10*time.Millisecond) + reporter := promreporter.NewPromReporter(coredb.DB, logger.TestLogger(t), backend, 10*time.Millisecond) require.NoError(t, reporter.Start(testutils.Context(t))) defer func() { assert.NoError(t, reporter.Close()) }() etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress) cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress) cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, fromAddress) - require.NoError(t, utils.JustError(db.Exec(`UPDATE evm.tx_attempts SET broadcast_before_block_num = 7 WHERE eth_tx_id = $1`, etx.ID))) + require.NoError(t, utils.JustError(coredb.Exec(`UPDATE evm.tx_attempts SET broadcast_before_block_num = 7 WHERE eth_tx_id = $1`, etx.ID))) head := newHead() reporter.OnNewLongestChain(testutils.Context(t), &head) diff --git a/core/services/relay/evm/config_poller_test.go b/core/services/relay/evm/config_poller_test.go index 73c16a19596..c032b2253e4 100644 --- a/core/services/relay/evm/config_poller_test.go +++ b/core/services/relay/evm/config_poller_test.go @@ -1,4 +1,4 @@ -package evm +package evm_test import ( "database/sql" @@ -28,6 +28,8 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" ocrtypes2 "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmClientMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" @@ -35,9 +37,10 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/testhelpers" + evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -82,18 +85,18 @@ func TestConfigPoller(t *testing.T) { require.NoError(t, err) b.Commit() - db := pgtest.NewSqlxDB(t) - cfg := pgtest.NewQConfig(false) + cfg := configtest.NewTestGeneralConfig(t) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) ethClient = evmclient.NewSimulatedBackendClient(t, b, testutils.SimulatedChainID) ctx := testutils.Context(t) - lorm := logpoller.NewORM(testutils.SimulatedChainID, db, lggr, cfg) + lorm := logpoller.NewORM(testutils.SimulatedChainID, evmdb, lggr, cfg.Database()) lp = logpoller.NewLogPoller(lorm, ethClient, lggr, 100*time.Millisecond, 1, 2, 2, 1000) require.NoError(t, lp.Start(ctx)) t.Cleanup(func() { lp.Close() }) } t.Run("LatestConfig errors if there is no config in logs and config store is unconfigured", func(t *testing.T) { - cp, err := NewConfigPoller(lggr, ethClient, lp, ocrAddress, nil) + cp, err := evmrelay.NewConfigPoller(lggr, ethClient, lp, ocrAddress, nil) require.NoError(t, err) _, err = cp.LatestConfig(testutils.Context(t), 0) @@ -102,7 +105,7 @@ func TestConfigPoller(t *testing.T) { }) t.Run("happy path (with config store)", func(t *testing.T) { - cp, err := NewConfigPoller(lggr, ethClient, lp, ocrAddress, &configStoreContractAddr) + cp, err := evmrelay.NewConfigPoller(lggr, ethClient, lp, ocrAddress, &configStoreContractAddr) require.NoError(t, err) // Should have no config to begin with. _, configDigest, err := cp.LatestConfigDetails(testutils.Context(t)) @@ -173,7 +176,7 @@ func TestConfigPoller(t *testing.T) { mp.On("LatestLogByEventSigWithConfs", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, sql.ErrNoRows) t.Run("if callLatestConfigDetails succeeds", func(t *testing.T) { - cp, err := newConfigPoller(lggr, ethClient, mp, ocrAddress, &configStoreContractAddr) + cp, err := evmrelay.NewConfigPoller(lggr, ethClient, mp, ocrAddress, &configStoreContractAddr) require.NoError(t, err) t.Run("when config has not been set, returns zero values", func(t *testing.T) { @@ -210,12 +213,9 @@ func TestConfigPoller(t *testing.T) { failingClient := new(evmClientMocks.Client) failingClient.On("ConfiguredChainID").Return(big.NewInt(42)) failingClient.On("CallContract", mock.Anything, mock.Anything, mock.Anything).Return(nil, errors.New("something exploded")) - cp, err := newConfigPoller(lggr, failingClient, mp, ocrAddress, &configStoreContractAddr) + cp, err := evmrelay.NewConfigPoller(lggr, failingClient, mp, ocrAddress, &configStoreContractAddr) require.NoError(t, err) - cp.configStoreContractAddr = &configStoreContractAddr - cp.configStoreContract = configStoreContract - _, _, err = cp.LatestConfigDetails(testutils.Context(t)) assert.EqualError(t, err, "something exploded") @@ -249,7 +249,7 @@ func TestConfigPoller(t *testing.T) { mp.On("LatestLogByEventSigWithConfs", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, sql.ErrNoRows) t.Run("if callReadConfig succeeds", func(t *testing.T) { - cp, err := newConfigPoller(lggr, ethClient, mp, ocrAddress, &configStoreContractAddr) + cp, err := evmrelay.NewConfigPoller(lggr, ethClient, mp, ocrAddress, &configStoreContractAddr) require.NoError(t, err) t.Run("when config has not been set, returns error", func(t *testing.T) { @@ -271,9 +271,9 @@ func TestConfigPoller(t *testing.T) { DeltaC: 10, }, ocrContract, user) - signerAddresses, err := OnchainPublicKeyToAddress(contractConfig.Signers) + signerAddresses, err := evmrelay.OnchainPublicKeyToAddress(contractConfig.Signers) require.NoError(t, err) - transmitterAddresses, err := AccountToAddress(contractConfig.Transmitters) + transmitterAddresses, err := evmrelay.AccountToAddress(contractConfig.Transmitters) require.NoError(t, err) configuration := ocrconfigurationstoreevmsimple.OCRConfigurationStoreEVMSimpleConfigurationEVMSimple{ @@ -311,7 +311,7 @@ func TestConfigPoller(t *testing.T) { // initial call to retrieve config store address from aggregator return *callArgs.To == ocrAddress }), mock.Anything).Return(nil, errors.New("something exploded")).Once() - cp, err := newConfigPoller(lggr, failingClient, mp, ocrAddress, &configStoreContractAddr) + cp, err := evmrelay.NewConfigPoller(lggr, failingClient, mp, ocrAddress, &configStoreContractAddr) require.NoError(t, err) _, err = cp.LatestConfig(testutils.Context(t), 0) @@ -359,9 +359,9 @@ func setConfig(t *testing.T, pluginConfig median.OffchainConfig, ocrContract *oc onchainConfig, ) require.NoError(t, err) - signerAddresses, err := OnchainPublicKeyToAddress(signers) + signerAddresses, err := evmrelay.OnchainPublicKeyToAddress(signers) require.NoError(t, err) - transmitterAddresses, err := AccountToAddress(transmitters) + transmitterAddresses, err := evmrelay.AccountToAddress(transmitters) require.NoError(t, err) _, err = ocrContract.SetConfig(user, signerAddresses, transmitterAddresses, threshold, onchainConfig, offchainConfigVersion, offchainConfig) require.NoError(t, err) diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go index 6ae2052c408..7d60d04a33a 100644 --- a/core/services/relay/evm/evm.go +++ b/core/services/relay/evm/evm.go @@ -16,7 +16,6 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2/reportingplugin/median/evmreportcodec" "github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - "github.com/smartcontractkit/sqlx" "go.uber.org/multierr" "golang.org/x/exp/maps" @@ -24,6 +23,7 @@ import ( txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" "github.com/smartcontractkit/chainlink/v2/core/chains/evm" + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" txm "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services" @@ -48,7 +48,7 @@ import ( var _ relaytypes.Relayer = &Relayer{} type Relayer struct { - db *sqlx.DB + db *evmdb.ScopedDB chain evm.Chain lggr logger.Logger ks CSAETHKeystore @@ -63,7 +63,7 @@ type CSAETHKeystore interface { } type RelayerOpts struct { - *sqlx.DB + DB *evmdb.ScopedDB pg.QConfig CSAETHKeystore pg.EventBroadcaster @@ -187,7 +187,10 @@ func (r *Relayer) NewMercuryProvider(rargs relaytypes.RelayArgs, pargs relaytype default: return nil, fmt.Errorf("invalid feed version %d", feedID.Version()) } - transmitter := mercury.NewTransmitter(r.lggr, configWatcher.ContractConfigTracker(), client, privKey.PublicKey, rargs.JobID, *relayConfig.FeedID, r.db, r.pgCfg, transmitterCodec) + // KRR note to self: this is going to break because the mercury transmitter is using db tables outside the `evm` schema but mercury is using the relayer's db which is scoped to evm. + // this new provider code should be passed a connection string and make it's own DB. might need some sort of DB manager so that multiple providers can share the same DB object. not sure + // how many times NewProvider is called. + transmitter := mercury.NewTransmitter(r.lggr, configWatcher.ContractConfigTracker(), client, privKey.PublicKey, rargs.JobID, *relayConfig.FeedID, r.db.SqlxDB(), r.pgCfg, transmitterCodec) return NewMercuryProvider(configWatcher, transmitter, reportCodecV1, reportCodecV2, reportCodecV3, r.lggr), nil } @@ -512,7 +515,8 @@ func (r *Relayer) NewMedianProvider(rargs relaytypes.RelayArgs, pargs relaytypes return nil, err } - medianContract, err := newMedianContract(configWatcher.ContractConfigTracker(), configWatcher.contractAddress, configWatcher.chain, rargs.JobID, r.db, r.lggr) + // KRR note to self: this is going to break because the queries that use the `db` are not scoped to the `evm` schema + medianContract, err := newMedianContract(configWatcher.ContractConfigTracker(), configWatcher.contractAddress, configWatcher.chain, rargs.JobID, r.db.SqlxDB(), r.lggr) if err != nil { return nil, err } diff --git a/core/services/relay/evm/evm_test.go b/core/services/relay/evm/evm_test.go index df7cd8eb818..3a628c9b919 100644 --- a/core/services/relay/evm/evm_test.go +++ b/core/services/relay/evm/evm_test.go @@ -3,9 +3,9 @@ package evm_test import ( "testing" - "github.com/smartcontractkit/sqlx" "github.com/stretchr/testify/assert" + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" @@ -14,7 +14,7 @@ import ( func TestRelayerOpts_Validate(t *testing.T) { cfg := configtest.NewTestGeneralConfig(t) type fields struct { - DB *sqlx.DB + DB *evmdb.ScopedDB QConfig pg.QConfig CSAETHKeystore evm.CSAETHKeystore EventBroadcaster pg.EventBroadcaster diff --git a/core/services/relay/evm/functions/config_poller_test.go b/core/services/relay/evm/functions/config_poller_test.go index d6573ef3544..ae5e8f89e44 100644 --- a/core/services/relay/evm/functions/config_poller_test.go +++ b/core/services/relay/evm/functions/config_poller_test.go @@ -27,6 +27,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" @@ -72,14 +74,15 @@ func runTest(t *testing.T, pluginType functions.FunctionsPluginType, expectedDig ) require.NoError(t, err) b.Commit() - db := pgtest.NewSqlxDB(t) - defer db.Close() + cfg := pgtest.NewQConfig(false) ethClient := evmclient.NewSimulatedBackendClient(t, b, big.NewInt(1337)) defer ethClient.Close() lggr := logger.TestLogger(t) ctx := testutils.Context(t) - lorm := logpoller.NewORM(big.NewInt(1337), db, lggr, cfg) + evmdb := evmtestdb.NewScopedDB(t, configtest.NewTestGeneralConfig(t).Database()) + defer evmdb.Close() + lorm := logpoller.NewORM(big.NewInt(1337), evmdb, lggr, cfg) lp := logpoller.NewLogPoller(lorm, ethClient, lggr, 100*time.Millisecond, 1, 2, 2, 1000) defer lp.Close() require.NoError(t, lp.Start(ctx)) diff --git a/core/services/relay/evm/mercury/helpers_test.go b/core/services/relay/evm/mercury/helpers_test.go index 4e3587b5de6..8f769318e91 100644 --- a/core/services/relay/evm/mercury/helpers_test.go +++ b/core/services/relay/evm/mercury/helpers_test.go @@ -18,6 +18,7 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier_proxy" @@ -163,12 +164,13 @@ func SetupTH(t *testing.T, feedID common.Hash) TestHarness { require.NoError(t, err) b.Commit() - db := pgtest.NewSqlxDB(t) cfg := pgtest.NewQConfig(false) ethClient := evmclient.NewSimulatedBackendClient(t, b, big.NewInt(1337)) lggr := logger.TestLogger(t) ctx := testutils.Context(t) - lorm := logpoller.NewORM(big.NewInt(1337), db, lggr, cfg) + // explicitly scope the db rather than use evmtestdb.NewScopedDB because that requires a config, which causes an import cycle + evmScopedDB := &evmdb.ScopedDB{pgtest.NewSqlxDB(t, evmdb.UseEVMSchema())} + lorm := logpoller.NewORM(big.NewInt(1337), evmScopedDB, lggr, cfg) lp := logpoller.NewLogPoller(lorm, ethClient, lggr, 100*time.Millisecond, 1, 2, 2, 1000) eventBroadcaster := pgmocks.NewEventBroadcaster(t) subscription := pgmocks.NewSubscription(t) diff --git a/core/services/relay/evm/mercury/orm.go b/core/services/relay/evm/mercury/orm.go index dd7d7b33e74..4df5abfd163 100644 --- a/core/services/relay/evm/mercury/orm.go +++ b/core/services/relay/evm/mercury/orm.go @@ -54,6 +54,7 @@ func (o *orm) InsertTransmitRequest(req *pb.TransmitRequest, jobID int32, report wg.Add(2) var err1, err2 error + // KRR note to self: this is going to break because mercury is inside the evm relayer and the evm relayer is being scoped to the `evm` schema go func() { defer wg.Done() err1 = q.ExecQ(` diff --git a/core/services/relay/evm/relayer_extender_test.go b/core/services/relay/evm/relayer_extender_test.go index dc8433d4f0f..0a9fca52bcd 100644 --- a/core/services/relay/evm/relayer_extender_test.go +++ b/core/services/relay/evm/relayer_extender_test.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" @@ -34,7 +35,7 @@ func TestChainRelayExtenders(t *testing.T) { kst := cltest.NewKeyStore(t, db, cfg.Database()) require.NoError(t, kst.Unlock(cltest.Password)) - opts := evmtest.NewChainRelayExtOpts(t, evmtest.TestChainOpts{DB: evmtest.NewScopedDB(t, cfg.Database()), KeyStore: kst.Eth(), GeneralConfig: cfg}) + opts := evmtest.NewChainRelayExtOpts(t, evmtest.TestChainOpts{DB: evmtestdb.NewScopedDB(t, cfg.Database()), KeyStore: kst.Eth(), GeneralConfig: cfg}) opts.GenEthClient = func(*big.Int) evmclient.Client { return cltest.NewEthMocksWithStartupAssertions(t) } diff --git a/core/services/vrf/delegate_test.go b/core/services/vrf/delegate_test.go index ae0accc329e..dc599fda272 100644 --- a/core/services/vrf/delegate_test.go +++ b/core/services/vrf/delegate_test.go @@ -23,6 +23,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -64,7 +65,7 @@ type vrfUniverse struct { cid big.Int } -func buildVrfUni(t *testing.T, db *sqlx.DB, cfg chainlink.GeneralConfig) vrfUniverse { +func buildVrfUni(t *testing.T, coredb *sqlx.DB, cfg chainlink.GeneralConfig) vrfUniverse { // Mock all chain interactions lb := log_mocks.NewBroadcaster(t) lb.On("AddDependents", 1).Maybe() @@ -74,13 +75,14 @@ func buildVrfUni(t *testing.T, db *sqlx.DB, cfg chainlink.GeneralConfig) vrfUniv hb := headtracker.NewHeadBroadcaster(lggr) // Don't mock db interactions - prm := pipeline.NewORM(db, lggr, cfg.Database(), cfg.JobPipeline().MaxSuccessfulRuns()) - btORM := bridges.NewORM(db, lggr, cfg.Database()) + prm := pipeline.NewORM(coredb, lggr, cfg.Database(), cfg.JobPipeline().MaxSuccessfulRuns()) + btORM := bridges.NewORM(coredb, lggr, cfg.Database()) txm := txmmocks.NewMockEvmTxManager(t) - ks := keystore.New(db, utils.FastScryptParams, lggr, cfg.Database()) - relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{LogBroadcaster: lb, KeyStore: ks.Eth(), Client: ec, DB: db, GeneralConfig: cfg, TxManager: txm}) + ks := keystore.New(coredb, utils.FastScryptParams, lggr, cfg.Database()) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{LogBroadcaster: lb, KeyStore: ks.Eth(), Client: ec, DB: evmdb, GeneralConfig: cfg, TxManager: txm}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) - jrm := job.NewORM(db, legacyChains, prm, btORM, ks, lggr, cfg.Database()) + jrm := job.NewORM(coredb, legacyChains, prm, btORM, ks, lggr, cfg.Database()) t.Cleanup(func() { jrm.Close() }) pr := pipeline.NewRunner(prm, btORM, cfg.JobPipeline(), cfg.WebServer(), legacyChains, ks.Eth(), ks.VRF(), lggr, nil, nil) require.NoError(t, ks.Unlock(testutils.Password)) diff --git a/core/services/vrf/v1/integration_test.go b/core/services/vrf/v1/integration_test.go index 14cbb36c9d6..c97e6c52a2d 100644 --- a/core/services/vrf/v1/integration_test.go +++ b/core/services/vrf/v1/integration_test.go @@ -97,7 +97,7 @@ func TestIntegration_VRF_JPV2(t *testing.T) { // Ensure the eth transaction gets confirmed on chain. gomega.NewWithT(t).Eventually(func() bool { - orm := txmgr.NewTxStore(app.GetSqlxDB(), app.GetLogger(), app.GetConfig().Database()) + orm := txmgr.NewTxStore(app.GetRelayers().LegacyEVM().DB(), app.GetLogger(), app.GetConfig().Database()) uc, err2 := orm.CountUnconfirmedTransactions(key1.Address, testutils.SimulatedChainID) require.NoError(t, err2) return uc == 0 @@ -214,7 +214,7 @@ func TestIntegration_VRF_WithBHS(t *testing.T) { // Ensure the eth transaction gets confirmed on chain. gomega.NewWithT(t).Eventually(func() bool { - orm := txmgr.NewTxStore(app.GetSqlxDB(), app.GetLogger(), app.GetConfig().Database()) + orm := txmgr.NewTxStore(app.GetRelayers().LegacyEVM().DB(), app.GetLogger(), app.GetConfig().Database()) uc, err2 := orm.CountUnconfirmedTransactions(key.Address, testutils.SimulatedChainID) require.NoError(t, err2) return uc == 0 diff --git a/core/web/evm_forwarders_controller.go b/core/web/evm_forwarders_controller.go index 6228723506d..7c7b7c4a14d 100644 --- a/core/web/evm_forwarders_controller.go +++ b/core/web/evm_forwarders_controller.go @@ -25,7 +25,7 @@ type EVMForwardersController struct { // Index lists EVM forwarders. func (cc *EVMForwardersController) Index(c *gin.Context, size, page, offset int) { - orm := forwarders.NewORM(cc.App.GetSqlxDB(), cc.App.GetLogger(), cc.App.GetConfig().Database()) + orm := forwarders.NewORM(cc.App.GetRelayers().LegacyEVM().DB(), cc.App.GetLogger(), cc.App.GetConfig().Database()) fwds, count, err := orm.FindForwarders(0, size) if err != nil { @@ -55,7 +55,7 @@ func (cc *EVMForwardersController) Track(c *gin.Context) { jsonAPIError(c, http.StatusUnprocessableEntity, err) return } - orm := forwarders.NewORM(cc.App.GetSqlxDB(), cc.App.GetLogger(), cc.App.GetConfig().Database()) + orm := forwarders.NewORM(cc.App.GetRelayers().LegacyEVM().DB(), cc.App.GetLogger(), cc.App.GetConfig().Database()) fwd, err := orm.CreateForwarder(request.Address, *request.EVMChainID) if err != nil { @@ -94,7 +94,7 @@ func (cc *EVMForwardersController) Delete(c *gin.Context) { return chain.LogPoller().UnregisterFilter(forwarders.FilterName(addr), pg.WithQueryer(tx)) } - orm := forwarders.NewORM(cc.App.GetSqlxDB(), cc.App.GetLogger(), cc.App.GetConfig().Database()) + orm := forwarders.NewORM(cc.App.GetRelayers().LegacyEVM().DB(), cc.App.GetLogger(), cc.App.GetConfig().Database()) err = orm.DeleteForwarder(id, filterCleanup) if err != nil { diff --git a/core/web/evm_transactions_controller_test.go b/core/web/evm_transactions_controller_test.go index 951d9d99259..0d1a87cf6f7 100644 --- a/core/web/evm_transactions_controller_test.go +++ b/core/web/evm_transactions_controller_test.go @@ -25,7 +25,7 @@ func TestTransactionsController_Index_Success(t *testing.T) { require.NoError(t, app.Start(testutils.Context(t))) db := app.GetSqlxDB() - txStore := cltest.NewTestTxStore(t, app.GetSqlxDB(), app.GetConfig().Database()) + txStore := cltest.NewTestTxStore(t, app.GetRelayers().LegacyEVM().DB(), app.GetConfig().Database()) ethKeyStore := cltest.NewKeyStore(t, db, app.Config.Database()).Eth() client := app.NewHTTPClient(&cltest.User{}) _, from := cltest.MustInsertRandomKey(t, ethKeyStore, 0) @@ -81,7 +81,7 @@ func TestTransactionsController_Show_Success(t *testing.T) { app := cltest.NewApplicationWithKey(t) require.NoError(t, app.Start(testutils.Context(t))) - txStore := cltest.NewTestTxStore(t, app.GetSqlxDB(), app.GetConfig().Database()) + txStore := cltest.NewTestTxStore(t, app.GetRelayers().LegacyEVM().DB(), app.GetConfig().Database()) client := app.NewHTTPClient(&cltest.User{}) _, from := cltest.MustInsertRandomKey(t, app.KeyStore.Eth(), 0) @@ -114,7 +114,7 @@ func TestTransactionsController_Show_NotFound(t *testing.T) { app := cltest.NewApplicationWithKey(t) require.NoError(t, app.Start(testutils.Context(t))) - txStore := cltest.NewTestTxStore(t, app.GetSqlxDB(), app.GetConfig().Database()) + txStore := cltest.NewTestTxStore(t, app.GetRelayers().LegacyEVM().DB(), app.GetConfig().Database()) client := app.NewHTTPClient(&cltest.User{}) _, from := cltest.MustInsertRandomKey(t, app.KeyStore.Eth(), 0) tx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, from) diff --git a/core/web/evm_tx_attempts_controller_test.go b/core/web/evm_tx_attempts_controller_test.go index abf80add213..f918beefa8d 100644 --- a/core/web/evm_tx_attempts_controller_test.go +++ b/core/web/evm_tx_attempts_controller_test.go @@ -20,7 +20,7 @@ func TestTxAttemptsController_Index_Success(t *testing.T) { app := cltest.NewApplicationWithKey(t) require.NoError(t, app.Start(testutils.Context(t))) - txStore := cltest.NewTestTxStore(t, app.GetSqlxDB(), app.GetConfig().Database()) + txStore := cltest.NewTestTxStore(t, app.GetRelayers().LegacyEVM().DB(), app.GetConfig().Database()) client := app.NewHTTPClient(&cltest.User{}) _, from := cltest.MustInsertRandomKey(t, app.KeyStore.Eth(), 0) From 6fad30186e9a099d1facad36210d3efa744e3309 Mon Sep 17 00:00:00 2001 From: krehermann Date: Wed, 11 Oct 2023 16:16:06 -0600 Subject: [PATCH 7/7] wip -- txm fk error --- core/chains/evm/chain_test.go | 11 +- core/chains/evm/db/db.go | 3 +- .../evm/logpoller/log_poller_internal_test.go | 2 +- core/chains/evm/txmgr/broadcaster_test.go | 52 ++++-- core/chains/evm/txmgr/confirmer_test.go | 86 +++++---- core/chains/evm/txmgr/evm_tx_store.go | 168 +++++++++--------- core/chains/evm/txmgr/evm_tx_store_test.go | 128 ++++++++----- core/chains/evm/txmgr/nonce_syncer_test.go | 16 +- core/chains/evm/txmgr/reaper_test.go | 4 +- core/chains/evm/txmgr/resender_test.go | 10 +- core/chains/evm/txmgr/txmgr_test.go | 38 ++-- core/cmd/evm_transaction_commands_test.go | 7 +- core/cmd/shell_local_test.go | 6 +- core/internal/testutils/evmtest/db/dbtest.go | 21 +++ core/services/pg/locked_db.go | 6 +- 15 files changed, 336 insertions(+), 222 deletions(-) diff --git a/core/chains/evm/chain_test.go b/core/chains/evm/chain_test.go index 09395ff4c97..12dff2d1089 100644 --- a/core/chains/evm/chain_test.go +++ b/core/chains/evm/chain_test.go @@ -4,13 +4,13 @@ import ( "math/big" "testing" - "github.com/smartcontractkit/sqlx" "github.com/stretchr/testify/assert" "github.com/smartcontractkit/chainlink/v2/core/chains/evm" + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/mocks" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -35,8 +35,9 @@ func TestChainOpts_Validate(t *testing.T) { AppConfig evm.AppConfig EventBroadcaster pg.EventBroadcaster MailMon *utils.MailboxMonitor - DB *sqlx.DB + DB *evmdb.ScopedDB } + cfg := configtest.NewTestGeneralConfig(t) tests := []struct { name string fields fields @@ -45,10 +46,10 @@ func TestChainOpts_Validate(t *testing.T) { { name: "valid", fields: fields{ - AppConfig: configtest.NewTestGeneralConfig(t), + AppConfig: cfg, EventBroadcaster: pg.NewNullEventBroadcaster(), MailMon: &utils.MailboxMonitor{}, - DB: pgtest.NewSqlxDB(t), + DB: evmtestdb.NewScopedDB(t, cfg.Database()), }, }, { diff --git a/core/chains/evm/db/db.go b/core/chains/evm/db/db.go index c167fa1c958..3fac0add177 100644 --- a/core/chains/evm/db/db.go +++ b/core/chains/evm/db/db.go @@ -29,7 +29,8 @@ func (s *ScopedDB) SqlxDB() *sqlx.DB { } func ScopedConnection(dbURL url.URL) (evmScopedConnection url.URL) { - return pg.SchemaScopedConnection(dbURL, schema) + // hacking, include public schema + return pg.SchemaScopedConnection(dbURL, schema, "public") } func UseEVMSchema() pg.ConnectionOpt { diff --git a/core/chains/evm/logpoller/log_poller_internal_test.go b/core/chains/evm/logpoller/log_poller_internal_test.go index 5f1c21a5b81..71bf5c5d052 100644 --- a/core/chains/evm/logpoller/log_poller_internal_test.go +++ b/core/chains/evm/logpoller/log_poller_internal_test.go @@ -52,7 +52,7 @@ func TestLogPoller_RegisterFilter(t *testing.T) { lggr, observedLogs := logger.TestLoggerObserved(t, zapcore.ErrorLevel) chainID := testutils.NewRandomEVMChainID() - db := pgtest.NewSqlxDB(t) + db := evmtestdb.NewScopedDBWithOpts(t) orm := NewORM(chainID, db, lggr, pgtest.NewQConfig(true)) diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go index e1133e8ef21..620a8b91c9c 100644 --- a/core/chains/evm/txmgr/broadcaster_test.go +++ b/core/chains/evm/txmgr/broadcaster_test.go @@ -38,6 +38,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -85,7 +86,8 @@ func TestEthBroadcaster_Lifecycle(t *testing.T) { err := eventBroadcaster.Start(testutils.Context(t)) require.NoError(t, err) t.Cleanup(func() { assert.NoError(t, eventBroadcaster.Close()) }) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + txStore := cltest.NewTestTxStore(t, evmdb, cfg.Database()) evmcfg := evmtest.NewChainScopedConfig(t, cfg) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() @@ -143,7 +145,8 @@ func TestEthBroadcaster_Lifecycle(t *testing.T) { func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewTestGeneralConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + txStore := cltest.NewTestTxStore(t, evmdb, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -491,7 +494,8 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) { func TestEthBroadcaster_TransmitChecking(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewTestGeneralConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + txStore := cltest.NewTestTxStore(t, evmdb, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -573,7 +577,8 @@ func TestEthBroadcaster_TransmitChecking(t *testing.T) { func TestEthBroadcaster_ProcessUnstartedEthTxs_OptimisticLockingOnEthTx(t *testing.T) { // non-transactional DB needed because we deliberately test for FK violation cfg, db := heavyweight.FullTestDBV2(t, "eth_broadcaster_optimistic_locking", nil) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmdb := heavyweight.EVMDB(t, cfg.Database()) + txStore := cltest.NewTestTxStore(t, evmdb, cfg.Database()) ccfg := evmtest.NewChainScopedConfig(t, cfg) evmcfg := txmgr.NewEvmTxmConfig(ccfg.EVM()) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) @@ -637,7 +642,8 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success_WithMultiplier(t *testing lm := decimal.RequireFromString("1.3") c.EVM[0].GasEstimator.LimitMultiplier = &lm }) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + txStore := cltest.NewTestTxStore(t, evmdb, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -684,7 +690,8 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { t.Run("cannot be more than one transaction per address in an unfinished state", func(t *testing.T) { db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + txStore := cltest.NewTestTxStore(t, evmdb, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, nextNonce) @@ -719,7 +726,8 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { t.Run("previous run assigned nonce but never broadcast", func(t *testing.T) { db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + txStore := cltest.NewTestTxStore(t, evmdb, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, nextNonce) @@ -757,7 +765,8 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { t.Run("previous run assigned nonce and broadcast but it fatally errored before we could save", func(t *testing.T) { db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + txStore := cltest.NewTestTxStore(t, evmdb, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, nextNonce) @@ -795,7 +804,8 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { t.Run("previous run assigned nonce and broadcast and is now in mempool", func(t *testing.T) { db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + txStore := cltest.NewTestTxStore(t, evmdb, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, nextNonce) @@ -832,7 +842,8 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { t.Run("previous run assigned nonce and broadcast and now the transaction has been confirmed", func(t *testing.T) { db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + txStore := cltest.NewTestTxStore(t, evmdb, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, nextNonce) @@ -871,7 +882,8 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { t.Run("previous run assigned nonce and then failed to reach node for some reason and node is still down", func(t *testing.T) { failedToReachNodeError := context.DeadlineExceeded db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + txStore := cltest.NewTestTxStore(t, evmdb, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, nextNonce) @@ -908,7 +920,8 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { t.Run("previous run assigned nonce and broadcast transaction then crashed and rebooted with a different configured gas price", func(t *testing.T) { db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + txStore := cltest.NewTestTxStore(t, evmdb, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, nextNonce) @@ -979,7 +992,8 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewTestGeneralConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + txStore := cltest.NewTestTxStore(t, evmdb, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -1630,7 +1644,8 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_KeystoreErrors(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + txStore := cltest.NewTestTxStore(t, evmdb, cfg.Database()) realKeystore := cltest.NewKeyStore(t, db, cfg.Database()) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, realKeystore.Eth()) @@ -1715,7 +1730,8 @@ func TestEthBroadcaster_Trigger(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + txStore := cltest.NewTestTxStore(t, evmdb, cfg.Database()) evmcfg := evmtest.NewChainScopedConfig(t, cfg) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() eb := NewTestEthBroadcaster(t, txStore, evmtest.NewEthClientMockWithDefaultChain(t), ethKeyStore, evmcfg, &testCheckerFactory{}, false) @@ -1728,7 +1744,8 @@ func TestEthBroadcaster_Trigger(t *testing.T) { func TestEthBroadcaster_EthTxInsertEventCausesTriggerToFire(t *testing.T) { // NOTE: Testing triggers requires committing transactions and does not work with transactional tests cfg, db := heavyweight.FullTestDBV2(t, "eth_tx_triggers", nil) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmdb := heavyweight.EVMDB(t, cfg.Database()) + txStore := cltest.NewTestTxStore(t, evmdb, cfg.Database()) evmcfg := evmtest.NewChainScopedConfig(t, cfg) @@ -1758,7 +1775,8 @@ func TestEthBroadcaster_SyncNonce(t *testing.T) { }) evmcfg := evmtest.NewChainScopedConfig(t, cfg) evmTxmCfg := txmgr.NewEvmTxmConfig(evmcfg.EVM()) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + txStore := cltest.NewTestTxStore(t, evmdb, cfg.Database()) kst := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, kst, true) diff --git a/core/chains/evm/txmgr/confirmer_test.go b/core/chains/evm/txmgr/confirmer_test.go index e0070e35b17..0bdbb498e2d 100644 --- a/core/chains/evm/txmgr/confirmer_test.go +++ b/core/chains/evm/txmgr/confirmer_test.go @@ -35,6 +35,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -111,7 +112,8 @@ func TestEthConfirmer_Lifecycle(t *testing.T) { db := pgtest.NewSqlxDB(t) config := newTestChainScopedConfig(t) - txStore := cltest.NewTxStore(t, db, config.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(config.Database())) + txStore := cltest.NewTxStore(t, evmDB, config.Database()) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) ethKeyStore := cltest.NewKeyStore(t, db, config.Database()).Eth() @@ -180,7 +182,8 @@ func TestEthConfirmer_CheckForReceipts(t *testing.T) { db := pgtest.NewSqlxDB(t) config := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, config.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(config.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, config.Database()) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) ethKeyStore := cltest.NewKeyStore(t, db, config.Database()).Eth() @@ -595,7 +598,8 @@ func TestEthConfirmer_CheckForReceipts_batching(t *testing.T) { cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].RPCDefaultBatchSize = ptr[uint32](2) }) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() @@ -660,8 +664,8 @@ func TestEthConfirmer_CheckForReceipts_HandlesNonFwdTxsWithForwardingEnabled(t * c.EVM[0].RPCDefaultBatchSize = ptr[uint32](1) c.EVM[0].Transactions.ForwardersEnabled = ptr(true) }) - - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) evmcfg := evmtest.NewChainScopedConfig(t, cfg) @@ -711,7 +715,8 @@ func TestEthConfirmer_CheckForReceipts_only_likely_confirmed(t *testing.T) { cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].RPCDefaultBatchSize = ptr[uint32](6) }) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() @@ -769,7 +774,8 @@ func TestEthConfirmer_CheckForReceipts_should_not_check_for_likely_unconfirmed(t db := pgtest.NewSqlxDB(t) config := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, config.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(config.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, config.Database()) ethKeyStore := cltest.NewKeyStore(t, db, config.Database()).Eth() @@ -799,7 +805,8 @@ func TestEthConfirmer_CheckForReceipts_confirmed_missing_receipt_scoped_to_key(t db := pgtest.NewSqlxDB(t) cfg := configtest.NewTestGeneralConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() chainId1, chainId2 := 1, 2 @@ -869,7 +876,8 @@ func TestEthConfirmer_CheckForReceipts_confirmed_missing_receipt(t *testing.T) { cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].FinalityDepth = ptr[uint32](50) }) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() @@ -1127,7 +1135,8 @@ func TestEthConfirmer_CheckConfirmedMissingReceipt(t *testing.T) { cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].FinalityDepth = ptr[uint32](50) }) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() @@ -1207,7 +1216,8 @@ func TestEthConfirmer_CheckConfirmedMissingReceipt_batchSendTransactions_fails(t cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].FinalityDepth = ptr[uint32](50) }) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() @@ -1272,7 +1282,8 @@ func TestEthConfirmer_CheckConfirmedMissingReceipt_smallEvmRPCBatchSize_middleBa c.EVM[0].FinalityDepth = ptr[uint32](50) c.EVM[0].RPCDefaultBatchSize = ptr[uint32](1) }) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() @@ -1340,7 +1351,8 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewTestGeneralConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) @@ -1642,8 +1654,8 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing c.EVM[0].GasEstimator.BlockHistory.CheckInclusionBlocks = ptr[uint16](4) }) ccfg := evmtest.NewChainScopedConfig(t, cfg) - - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) kst := ksmocks.NewEth(t) @@ -1687,8 +1699,8 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing c.EVM[0].GasEstimator.BlockHistory.CheckInclusionBlocks = ptr[uint16](4) }) ccfg := evmtest.NewChainScopedConfig(t, cfg) - - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) kst := ksmocks.NewEth(t) @@ -1733,7 +1745,8 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].GasEstimator.PriceMax = (*assets.Wei)(assets.GWei(500)) }) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() @@ -2386,7 +2399,8 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyUnderpriced_ThenGoesTh cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].GasEstimator.PriceMax = (*assets.Wei)(assets.GWei(500)) }) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() @@ -2501,8 +2515,9 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + cfg := newTestChainScopedConfig(t) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() @@ -2511,11 +2526,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) { _, err := ethKeyStore.EnabledKeysForChain(testutils.FixtureChainID) require.NoError(t, err) - require.NoError(t, err) - // keyStates, err := ethKeyStore.GetStatesForKeys(keys) - // require.NoError(t, err) - config := newTestChainScopedConfig(t) currentHead := int64(30) oldEnough := int64(19) nonce := int64(0) @@ -2531,7 +2542,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) { insufficientEthError := errors.New("insufficient funds for gas * price + value") t.Run("saves attempt with state 'insufficient_eth' if eth node returns this error", func(t *testing.T) { - ec, err := cltest.NewEthConfirmer(t, txStore, ethClient, config, ethKeyStore, nil) + ec, err := cltest.NewEthConfirmer(t, txStore, ethClient, cfg, ethKeyStore, nil) require.NoError(t, err) expectedBumpedGasPrice := big.NewInt(20000000000) @@ -2558,7 +2569,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) { }) t.Run("does not bump gas when previous error was 'out of eth', instead resubmits existing transaction", func(t *testing.T) { - ec, err := cltest.NewEthConfirmer(t, txStore, ethClient, config, ethKeyStore, nil) + ec, err := cltest.NewEthConfirmer(t, txStore, ethClient, cfg, ethKeyStore, nil) require.NoError(t, err) expectedBumpedGasPrice := big.NewInt(20000000000) @@ -2584,7 +2595,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) { }) t.Run("saves the attempt as broadcast after node wallet has been topped up with sufficient balance", func(t *testing.T) { - ec, err := cltest.NewEthConfirmer(t, txStore, ethClient, config, ethKeyStore, nil) + ec, err := cltest.NewEthConfirmer(t, txStore, ethClient, cfg, ethKeyStore, nil) require.NoError(t, err) expectedBumpedGasPrice := big.NewInt(20000000000) @@ -2643,8 +2654,9 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + cfg := newTestChainScopedConfig(t) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() @@ -2652,8 +2664,7 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) - config := newTestChainScopedConfig(t) - ec, err := cltest.NewEthConfirmer(t, txStore, ethClient, config, ethKeyStore, nil) + ec, err := cltest.NewEthConfirmer(t, txStore, ethClient, cfg, ethKeyStore, nil) require.NoError(t, err) head := evmtypes.Head{ @@ -2818,13 +2829,13 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + config := newTestChainScopedConfig(t) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(config.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, config.Database()) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db, config.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) - config := newTestChainScopedConfig(t) cltest.MustCreateUnstartedGeneratedTx(t, txStore, fromAddress, config.EVM().ChainID()) mustInsertInProgressEthTx(t, txStore, 0, fromAddress) etx1 := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress) @@ -2925,7 +2936,8 @@ func TestEthConfirmer_ResumePendingRuns(t *testing.T) { db := pgtest.NewSqlxDB(t) config := configtest.NewTestGeneralConfig(t) - txStore := cltest.NewTestTxStore(t, db, config.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(config.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, config.Database()) ethKeyStore := cltest.NewKeyStore(t, db, config.Database()).Eth() diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index 9aa34fec7e1..8cb6eab856b 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -250,7 +250,7 @@ func dbEthTxsToEvmEthTxPtrs(dbEthTxs []DbEthTx, evmEthTxs []*Tx) { } } -// Directly maps to columns of database table "evm.tx_attempts". +// Directly maps to columns of database table "tx_attempts". // This is exported, as tests and other external code still directly reads DB using this schema. type DbEthTxAttempt struct { ID int64 @@ -337,7 +337,7 @@ func NewTxStore( } const insertIntoEthTxAttemptsQuery = ` -INSERT INTO evm.tx_attempts (eth_tx_id, gas_price, signed_raw_tx, hash, broadcast_before_block_num, state, created_at, chain_specific_gas_limit, tx_type, gas_tip_cap, gas_fee_cap) +INSERT INTO tx_attempts (eth_tx_id, gas_price, signed_raw_tx, hash, broadcast_before_block_num, state, created_at, chain_specific_gas_limit, tx_type, gas_tip_cap, gas_fee_cap) VALUES (:eth_tx_id, :gas_price, :signed_raw_tx, :hash, :broadcast_before_block_num, :state, NOW(), :chain_specific_gas_limit, :tx_type, :gas_tip_cap, :gas_fee_cap) RETURNING *; ` @@ -358,7 +358,7 @@ func (o *evmTxStore) preloadTxAttempts(txs []Tx) error { return nil } var dbAttempts []DbEthTxAttempt - sql := `SELECT * FROM evm.tx_attempts WHERE eth_tx_id IN (?) ORDER BY id desc;` + sql := `SELECT * FROM tx_attempts WHERE eth_tx_id IN (?) ORDER BY id desc;` query, args, err := sqlx.In(sql, ids) if err != nil { return err @@ -410,12 +410,12 @@ func (o *evmTxStore) PreloadTxes(attempts []TxAttempt, qopts ...pg.QOpt) error { // Transactions returns all eth transactions without loaded relations // limited by passed parameters. func (o *evmTxStore) Transactions(offset, limit int) (txs []Tx, count int, err error) { - sql := `SELECT count(*) FROM evm.txes WHERE id IN (SELECT DISTINCT eth_tx_id FROM evm.tx_attempts)` + sql := `SELECT count(*) FROM evm.txes WHERE id IN (SELECT DISTINCT eth_tx_id FROM tx_attempts)` if err = o.q.Get(&count, sql); err != nil { return } - sql = `SELECT * FROM evm.txes WHERE id IN (SELECT DISTINCT eth_tx_id FROM evm.tx_attempts) ORDER BY id desc LIMIT $1 OFFSET $2` + sql = `SELECT * FROM evm.txes WHERE id IN (SELECT DISTINCT eth_tx_id FROM tx_attempts) ORDER BY id desc LIMIT $1 OFFSET $2` var dbEthTxs []DbEthTx if err = o.q.Select(&dbEthTxs, sql, limit, offset); err != nil { return @@ -427,12 +427,12 @@ func (o *evmTxStore) Transactions(offset, limit int) (txs []Tx, count int, err e // TransactionsWithAttempts returns all eth transactions with at least one attempt // limited by passed parameters. Attempts are sorted by id. func (o *evmTxStore) TransactionsWithAttempts(offset, limit int) (txs []Tx, count int, err error) { - sql := `SELECT count(*) FROM evm.txes WHERE id IN (SELECT DISTINCT eth_tx_id FROM evm.tx_attempts)` + sql := `SELECT count(*) FROM evm.txes WHERE id IN (SELECT DISTINCT eth_tx_id FROM tx_attempts)` if err = o.q.Get(&count, sql); err != nil { return } - sql = `SELECT * FROM evm.txes WHERE id IN (SELECT DISTINCT eth_tx_id FROM evm.tx_attempts) ORDER BY id desc LIMIT $1 OFFSET $2` + sql = `SELECT * FROM evm.txes WHERE id IN (SELECT DISTINCT eth_tx_id FROM tx_attempts) ORDER BY id desc LIMIT $1 OFFSET $2` var dbTxs []DbEthTx if err = o.q.Select(&dbTxs, sql, limit, offset); err != nil { return @@ -444,12 +444,12 @@ func (o *evmTxStore) TransactionsWithAttempts(offset, limit int) (txs []Tx, coun // TxAttempts returns the last tx attempts sorted by created_at descending. func (o *evmTxStore) TxAttempts(offset, limit int) (txs []TxAttempt, count int, err error) { - sql := `SELECT count(*) FROM evm.tx_attempts` + sql := `SELECT count(*) FROM tx_attempts` if err = o.q.Get(&count, sql); err != nil { return } - sql = `SELECT * FROM evm.tx_attempts ORDER BY created_at DESC, id DESC LIMIT $1 OFFSET $2` + sql = `SELECT * FROM tx_attempts ORDER BY created_at DESC, id DESC LIMIT $1 OFFSET $2` var dbTxs []DbEthTxAttempt if err = o.q.Select(&dbTxs, sql, limit, offset); err != nil { return @@ -462,7 +462,7 @@ func (o *evmTxStore) TxAttempts(offset, limit int) (txs []TxAttempt, count int, // FindTxAttempt returns an individual TxAttempt func (o *evmTxStore) FindTxAttempt(hash common.Hash) (*TxAttempt, error) { dbTxAttempt := DbEthTxAttempt{} - sql := `SELECT * FROM evm.tx_attempts WHERE hash = $1` + sql := `SELECT * FROM tx_attempts WHERE hash = $1` if err := o.q.Get(&dbTxAttempt, sql, hash); err != nil { return nil, err } @@ -476,7 +476,7 @@ func (o *evmTxStore) FindTxAttempt(hash common.Hash) (*TxAttempt, error) { // FindTxAttemptsByTxIDs returns a list of attempts by ETH Tx IDs func (o *evmTxStore) FindTxAttemptsByTxIDs(ids []int64) ([]TxAttempt, error) { - sql := `SELECT * FROM evm.tx_attempts WHERE eth_tx_id = ANY($1)` + sql := `SELECT * FROM tx_attempts WHERE eth_tx_id = ANY($1)` var dbTxAttempts []DbEthTxAttempt if err := o.q.Select(&dbTxAttempts, sql, ids); err != nil { return nil, err @@ -487,7 +487,7 @@ func (o *evmTxStore) FindTxAttemptsByTxIDs(ids []int64) ([]TxAttempt, error) { func (o *evmTxStore) FindTxByHash(hash common.Hash) (*Tx, error) { var dbEtx DbEthTx err := o.q.Transaction(func(tx pg.Queryer) error { - sql := `SELECT evm.txes.* FROM evm.txes WHERE id IN (SELECT DISTINCT eth_tx_id FROM evm.tx_attempts WHERE hash = $1)` + sql := `SELECT evm.txes.* FROM evm.txes WHERE id IN (SELECT DISTINCT eth_tx_id FROM tx_attempts WHERE hash = $1)` if err := tx.Get(&dbEtx, sql, hash); err != nil { return pkgerrors.Wrapf(err, "failed to find eth_tx with hash %d", hash) } @@ -504,7 +504,7 @@ func (o *evmTxStore) InsertTx(etx *Tx) error { if etx.CreatedAt == (time.Time{}) { etx.CreatedAt = time.Now() } - const insertEthTxSQL = `INSERT INTO evm.txes (nonce, from_address, to_address, encoded_payload, value, gas_limit, error, broadcast_at, initial_broadcast_at, created_at, state, meta, subject, pipeline_task_run_id, min_confirmations, evm_chain_id, transmit_checker) VALUES ( + const insertEthTxSQL = `INSERT INTO txes (nonce, from_address, to_address, encoded_payload, value, gas_limit, error, broadcast_at, initial_broadcast_at, created_at, state, meta, subject, pipeline_task_run_id, min_confirmations, evm_chain_id, transmit_checker) VALUES ( :nonce, :from_address, :to_address, :encoded_payload, :value, :gas_limit, :error, :broadcast_at, :initial_broadcast_at, :created_at, :state, :meta, :subject, :pipeline_task_run_id, :min_confirmations, :evm_chain_id, :transmit_checker ) RETURNING *` var dbTx DbEthTx @@ -528,7 +528,7 @@ func (o *evmTxStore) InsertReceipt(receipt *evmtypes.Receipt) (int64, error) { // convert to database representation r := DbReceiptFromEvmReceipt(receipt) - const insertEthReceiptSQL = `INSERT INTO evm.receipts (tx_hash, block_hash, block_number, transaction_index, receipt, created_at) VALUES ( + const insertEthReceiptSQL = `INSERT INTO receipts (tx_hash, block_hash, block_number, transaction_index, receipt, created_at) VALUES ( :tx_hash, :block_hash, :block_number, :transaction_index, :receipt, NOW() ) RETURNING *` err := o.q.GetNamed(insertEthReceiptSQL, &r, &r) @@ -540,15 +540,15 @@ func (o *evmTxStore) InsertReceipt(receipt *evmtypes.Receipt) (int64, error) { func (o *evmTxStore) FindTxWithAttempts(etxID int64) (etx Tx, err error) { err = o.q.Transaction(func(tx pg.Queryer) error { var dbEtx DbEthTx - if err = tx.Get(&dbEtx, `SELECT * FROM evm.txes WHERE id = $1 ORDER BY created_at ASC, id ASC`, etxID); err != nil { + if err = tx.Get(&dbEtx, `SELECT * FROM txes WHERE id = $1 ORDER BY created_at ASC, id ASC`, etxID); err != nil { return pkgerrors.Wrapf(err, "failed to find eth_tx with id %d", etxID) } dbEtx.ToTx(&etx) if err = o.LoadTxAttempts(&etx, pg.WithQueryer(tx)); err != nil { - return pkgerrors.Wrapf(err, "failed to load evm.tx_attempts for eth_tx with id %d", etxID) + return pkgerrors.Wrapf(err, "failed to load tx_attempts for eth_tx with id %d", etxID) } if err = loadEthTxAttemptsReceipts(tx, &etx); err != nil { - return pkgerrors.Wrapf(err, "failed to load evm.receipts for eth_tx with id %d", etxID) + return pkgerrors.Wrapf(err, "failed to load receipts for eth_tx with id %d", etxID) } return nil }, pg.OptReadOnlyTx()) @@ -560,8 +560,8 @@ func (o *evmTxStore) FindTxAttemptConfirmedByTxIDs(ids []int64) ([]TxAttempt, er err := o.q.Transaction(func(tx pg.Queryer) error { var dbAttempts []DbEthTxAttempt if err := tx.Select(&dbAttempts, `SELECT eta.* - FROM evm.tx_attempts eta - join evm.receipts er on eta.hash = er.tx_hash where eta.eth_tx_id = ANY($1) ORDER BY eta.gas_price DESC, eta.gas_tip_cap DESC`, ids); err != nil { + FROM tx_attempts eta + join receipts er on eta.hash = er.tx_hash where eta.eth_tx_id = ANY($1) ORDER BY eta.gas_price DESC, eta.gas_tip_cap DESC`, ids); err != nil { return err } txAttempts = dbEthTxAttemptsToEthTxAttempts(dbAttempts) @@ -580,8 +580,8 @@ func (o *evmTxStore) LoadTxesAttempts(etxs []*Tx, qopts ...pg.QOpt) error { ethTxesM[etx.ID] = etxs[i] } var dbTxAttempts []DbEthTxAttempt - if err := qq.Select(&dbTxAttempts, `SELECT * FROM evm.tx_attempts WHERE eth_tx_id = ANY($1) ORDER BY evm.tx_attempts.gas_price DESC, evm.tx_attempts.gas_tip_cap DESC`, pq.Array(ethTxIDs)); err != nil { - return pkgerrors.Wrap(err, "loadEthTxesAttempts failed to load evm.tx_attempts") + if err := qq.Select(&dbTxAttempts, `SELECT * FROM tx_attempts WHERE eth_tx_id = ANY($1) ORDER BY tx_attempts.gas_price DESC, tx_attempts.gas_tip_cap DESC`, pq.Array(ethTxIDs)); err != nil { + return pkgerrors.Wrap(err, "loadEthTxesAttempts failed to load tx_attempts") } for _, dbAttempt := range dbTxAttempts { etx := ethTxesM[dbAttempt.EthTxID] @@ -656,16 +656,16 @@ func (o *evmTxStore) FindTxAttemptsRequiringResend(olderThan time.Time, maxInFli // this select distinct works because of unique index on evm.txes // (evm_chain_id, from_address, nonce) err = o.q.Select(&dbAttempts, ` -SELECT DISTINCT ON (evm.txes.nonce) evm.tx_attempts.* -FROM evm.tx_attempts -JOIN evm.txes ON evm.txes.id = evm.tx_attempts.eth_tx_id AND evm.txes.state IN ('unconfirmed', 'confirmed_missing_receipt') -WHERE evm.tx_attempts.state <> 'in_progress' AND evm.txes.broadcast_at <= $1 AND evm_chain_id = $2 AND from_address = $3 -ORDER BY evm.txes.nonce ASC, evm.tx_attempts.gas_price DESC, evm.tx_attempts.gas_tip_cap DESC +SELECT DISTINCT ON (evm.txes.nonce) tx_attempts.* +FROM tx_attempts +JOIN evm.txes ON evm.txes.id = tx_attempts.eth_tx_id AND evm.txes.state IN ('unconfirmed', 'confirmed_missing_receipt') +WHERE tx_attempts.state <> 'in_progress' AND evm.txes.broadcast_at <= $1 AND evm_chain_id = $2 AND from_address = $3 +ORDER BY evm.txes.nonce ASC, tx_attempts.gas_price DESC, tx_attempts.gas_tip_cap DESC LIMIT $4 `, olderThan, chainID.String(), address, limit) attempts = dbEthTxAttemptsToEthTxAttempts(dbAttempts) - return attempts, pkgerrors.Wrap(err, "FindEthTxAttemptsRequiringResend failed to load evm.tx_attempts") + return attempts, pkgerrors.Wrap(err, "FindEthTxAttemptsRequiringResend failed to load tx_attempts") } func (o *evmTxStore) UpdateBroadcastAts(now time.Time, etxIDs []int64) error { @@ -685,11 +685,11 @@ func (o *evmTxStore) UpdateBroadcastAts(now time.Time, etxIDs []int64) error { // the attempt is already broadcast it _must_ have been before this head. func (o *evmTxStore) SetBroadcastBeforeBlockNum(blockNum int64, chainID *big.Int) error { _, err := o.q.Exec( - `UPDATE evm.tx_attempts + `UPDATE tx_attempts SET broadcast_before_block_num = $1 FROM evm.txes -WHERE evm.tx_attempts.broadcast_before_block_num IS NULL AND evm.tx_attempts.state = 'broadcast' -AND evm.txes.id = evm.tx_attempts.eth_tx_id AND evm.txes.evm_chain_id = $2`, +WHERE tx_attempts.broadcast_before_block_num IS NULL AND tx_attempts.state = 'broadcast' +AND evm.txes.id = tx_attempts.eth_tx_id AND evm.txes.evm_chain_id = $2`, blockNum, chainID.String(), ) return pkgerrors.Wrap(err, "SetBroadcastBeforeBlockNum failed") @@ -698,11 +698,11 @@ AND evm.txes.id = evm.tx_attempts.eth_tx_id AND evm.txes.evm_chain_id = $2`, func (o *evmTxStore) FindTxAttemptsConfirmedMissingReceipt(chainID *big.Int) (attempts []TxAttempt, err error) { var dbAttempts []DbEthTxAttempt err = o.q.Select(&dbAttempts, - `SELECT DISTINCT ON (evm.tx_attempts.eth_tx_id) evm.tx_attempts.* - FROM evm.tx_attempts - JOIN evm.txes ON evm.txes.id = evm.tx_attempts.eth_tx_id AND evm.txes.state = 'confirmed_missing_receipt' + `SELECT DISTINCT ON (tx_attempts.eth_tx_id) tx_attempts.* + FROM tx_attempts + JOIN evm.txes ON evm.txes.id = tx_attempts.eth_tx_id AND evm.txes.state = 'confirmed_missing_receipt' WHERE evm_chain_id = $1 - ORDER BY evm.tx_attempts.eth_tx_id ASC, evm.tx_attempts.gas_price DESC, evm.tx_attempts.gas_tip_cap DESC`, + ORDER BY tx_attempts.eth_tx_id ASC, tx_attempts.gas_price DESC, tx_attempts.gas_tip_cap DESC`, chainID.String()) if err != nil { err = pkgerrors.Wrap(err, "FindEtxAttemptsConfirmedMissingReceipt failed to query") @@ -724,13 +724,13 @@ func (o *evmTxStore) FindTxAttemptsRequiringReceiptFetch(chainID *big.Int) (atte err = o.q.Transaction(func(tx pg.Queryer) error { var dbAttempts []DbEthTxAttempt err = tx.Select(&dbAttempts, ` -SELECT evm.tx_attempts.* FROM evm.tx_attempts -JOIN evm.txes ON evm.txes.id = evm.tx_attempts.eth_tx_id AND evm.txes.state IN ('unconfirmed', 'confirmed_missing_receipt') AND evm.txes.evm_chain_id = $1 -WHERE evm.tx_attempts.state != 'insufficient_eth' -ORDER BY evm.txes.nonce ASC, evm.tx_attempts.gas_price DESC, evm.tx_attempts.gas_tip_cap DESC +SELECT tx_attempts.* FROM tx_attempts +JOIN evm.txes ON evm.txes.id = tx_attempts.eth_tx_id AND evm.txes.state IN ('unconfirmed', 'confirmed_missing_receipt') AND evm.txes.evm_chain_id = $1 +WHERE tx_attempts.state != 'insufficient_eth' +ORDER BY evm.txes.nonce ASC, tx_attempts.gas_price DESC, tx_attempts.gas_tip_cap DESC `, chainID.String()) if err != nil { - return pkgerrors.Wrap(err, "FindEthTxAttemptsRequiringReceiptFetch failed to load evm.tx_attempts") + return pkgerrors.Wrap(err, "FindEthTxAttemptsRequiringReceiptFetch failed to load tx_attempts") } attempts = dbEthTxAttemptsToEthTxAttempts(dbAttempts) err = o.PreloadTxes(attempts, pg.WithQueryer(tx)) @@ -797,13 +797,13 @@ func (o *evmTxStore) SaveFetchedReceipts(r []*evmtypes.Receipt, chainID *big.Int RETURNING evm.receipts.tx_hash, evm.receipts.block_number ), updated_eth_tx_attempts AS ( - UPDATE evm.tx_attempts + UPDATE tx_attempts SET state = 'broadcast', - broadcast_before_block_num = COALESCE(evm.tx_attempts.broadcast_before_block_num, inserted_receipts.block_number) + broadcast_before_block_num = COALESCE(tx_attempts.broadcast_before_block_num, inserted_receipts.block_number) FROM inserted_receipts - WHERE inserted_receipts.tx_hash = evm.tx_attempts.hash - RETURNING evm.tx_attempts.eth_tx_id + WHERE inserted_receipts.tx_hash = tx_attempts.hash + RETURNING tx_attempts.eth_tx_id ) UPDATE evm.txes SET state = 'confirmed' @@ -821,7 +821,7 @@ func (o *evmTxStore) SaveFetchedReceipts(r []*evmtypes.Receipt, chainID *big.Int } // MarkAllConfirmedMissingReceipt -// It is possible that we can fail to get a receipt for all evm.tx_attempts +// It is possible that we can fail to get a receipt for all tx_attempts // even though a transaction with this nonce has long since been confirmed (we // know this because transactions with higher nonces HAVE returned a receipt). // @@ -873,12 +873,12 @@ func (o *evmTxStore) GetInProgressTxAttempts(ctx context.Context, address common err = qq.Transaction(func(tx pg.Queryer) error { var dbAttempts []DbEthTxAttempt err = tx.Select(&dbAttempts, ` -SELECT evm.tx_attempts.* FROM evm.tx_attempts -INNER JOIN evm.txes ON evm.txes.id = evm.tx_attempts.eth_tx_id AND evm.txes.state in ('confirmed', 'confirmed_missing_receipt', 'unconfirmed') -WHERE evm.tx_attempts.state = 'in_progress' AND evm.txes.from_address = $1 AND evm.txes.evm_chain_id = $2 +SELECT tx_attempts.* FROM tx_attempts +INNER JOIN evm.txes ON evm.txes.id = tx_attempts.eth_tx_id AND evm.txes.state in ('confirmed', 'confirmed_missing_receipt', 'unconfirmed') +WHERE tx_attempts.state = 'in_progress' AND evm.txes.from_address = $1 AND evm.txes.evm_chain_id = $2 `, address, chainID.String()) if err != nil { - return pkgerrors.Wrap(err, "getInProgressEthTxAttempts failed to load evm.tx_attempts") + return pkgerrors.Wrap(err, "getInProgressEthTxAttempts failed to load tx_attempts") } attempts = dbEthTxAttemptsToEthTxAttempts(dbAttempts) err = o.PreloadTxes(attempts, pg.WithQueryer(tx)) @@ -894,8 +894,8 @@ func (o *evmTxStore) FindReceiptsPendingConfirmation(ctx context.Context, blockN SELECT pipeline_task_runs.id, evm.receipts.receipt, COALESCE((evm.txes.meta->>'FailOnRevert')::boolean, false) "FailOnRevert" FROM pipeline_task_runs INNER JOIN pipeline_runs ON pipeline_runs.id = pipeline_task_runs.pipeline_run_id INNER JOIN evm.txes ON evm.txes.pipeline_task_run_id = pipeline_task_runs.id - INNER JOIN evm.tx_attempts ON evm.txes.id = evm.tx_attempts.eth_tx_id - INNER JOIN evm.receipts ON evm.tx_attempts.hash = evm.receipts.tx_hash + INNER JOIN tx_attempts ON evm.txes.id = tx_attempts.eth_tx_id + INNER JOIN evm.receipts ON tx_attempts.hash = evm.receipts.tx_hash WHERE pipeline_runs.state = 'suspended' AND evm.receipts.block_number <= ($1 - evm.txes.min_confirmations) AND evm.txes.evm_chain_id = $2 `, blockNum, chainID.String()) @@ -931,7 +931,7 @@ SELECT * FROM evm.txes WHERE from_address = $1 AND nonce = $2 AND state IN ('con } dbEtx.ToTx(etx) err = o.LoadTxAttempts(etx, pg.WithQueryer(tx)) - return pkgerrors.Wrap(err, "FindEthTxWithNonce failed to load evm.tx_attempts") + return pkgerrors.Wrap(err, "FindEthTxWithNonce failed to load tx_attempts") }, pg.OptReadOnlyTx()) if errors.Is(err, sql.ErrNoRows) { return nil, nil @@ -943,7 +943,7 @@ func updateEthTxAttemptUnbroadcast(q pg.Queryer, attempt TxAttempt) error { if attempt.State != txmgrtypes.TxAttemptBroadcast { return errors.New("expected eth_tx_attempt to be broadcast") } - _, err := q.Exec(`UPDATE evm.tx_attempts SET broadcast_before_block_num = NULL, state = 'in_progress' WHERE id = $1`, attempt.ID) + _, err := q.Exec(`UPDATE tx_attempts SET broadcast_before_block_num = NULL, state = 'in_progress' WHERE id = $1`, attempt.ID) return pkgerrors.Wrap(err, "updateEthTxAttemptUnbroadcast failed") } @@ -958,9 +958,9 @@ func updateEthTxUnconfirm(q pg.Queryer, etx Tx) error { func deleteEthReceipts(q pg.Queryer, etxID int64) (err error) { _, err = q.Exec(` DELETE FROM evm.receipts -USING evm.tx_attempts -WHERE evm.receipts.tx_hash = evm.tx_attempts.hash -AND evm.tx_attempts.eth_tx_id = $1 +USING tx_attempts +WHERE evm.receipts.tx_hash = tx_attempts.hash +AND tx_attempts.eth_tx_id = $1 `, etxID) return pkgerrors.Wrap(err, "deleteEthReceipts failed") } @@ -982,8 +982,8 @@ func (o *evmTxStore) FindTransactionsConfirmedInBlockRange(highBlockNumber, lowB var dbEtxs []DbEthTx err = tx.Select(&dbEtxs, ` SELECT DISTINCT evm.txes.* FROM evm.txes -INNER JOIN evm.tx_attempts ON evm.txes.id = evm.tx_attempts.eth_tx_id AND evm.tx_attempts.state = 'broadcast' -INNER JOIN evm.receipts ON evm.receipts.tx_hash = evm.tx_attempts.hash +INNER JOIN tx_attempts ON evm.txes.id = tx_attempts.eth_tx_id AND tx_attempts.state = 'broadcast' +INNER JOIN evm.receipts ON evm.receipts.tx_hash = tx_attempts.hash WHERE evm.txes.state IN ('confirmed', 'confirmed_missing_receipt') AND block_number BETWEEN $1 AND $2 AND evm_chain_id = $3 ORDER BY nonce ASC `, lowBlockNumber, highBlockNumber, chainID.String()) @@ -993,7 +993,7 @@ ORDER BY nonce ASC etxs = make([]*Tx, len(dbEtxs)) dbEthTxsToEvmEthTxPtrs(dbEtxs, etxs) if err = o.LoadTxesAttempts(etxs, pg.WithQueryer(tx)); err != nil { - return pkgerrors.Wrap(err, "FindTransactionsConfirmedInBlockRange failed to load evm.tx_attempts") + return pkgerrors.Wrap(err, "FindTransactionsConfirmedInBlockRange failed to load tx_attempts") } err = loadEthTxesAttemptsReceipts(tx, etxs) return pkgerrors.Wrap(err, "FindTransactionsConfirmedInBlockRange failed to load evm.receipts") @@ -1013,8 +1013,8 @@ func saveAttemptWithNewState(q pg.Queryer, timeout time.Duration, logger logger. if _, err := tx.Exec(`UPDATE evm.txes SET broadcast_at = $1 WHERE id = $2 AND broadcast_at < $1`, broadcastAt, dbAttempt.EthTxID); err != nil { return pkgerrors.Wrap(err, "saveAttemptWithNewState failed to update evm.txes") } - _, err := tx.Exec(`UPDATE evm.tx_attempts SET state=$1 WHERE id=$2`, dbAttempt.State, dbAttempt.ID) - return pkgerrors.Wrap(err, "saveAttemptWithNewState failed to update evm.tx_attempts") + _, err := tx.Exec(`UPDATE tx_attempts SET state=$1 WHERE id=$2`, dbAttempt.State, dbAttempt.ID) + return pkgerrors.Wrap(err, "saveAttemptWithNewState failed to update tx_attempts") }) } @@ -1062,7 +1062,7 @@ func (o *evmTxStore) DeleteInProgressAttempt(ctx context.Context, attempt TxAtte if attempt.ID == 0 { return errors.New("DeleteInProgressAttempt: expected attempt to have an id") } - _, err := qq.Exec(`DELETE FROM evm.tx_attempts WHERE id = $1`, attempt.ID) + _, err := qq.Exec(`DELETE FROM tx_attempts WHERE id = $1`, attempt.ID) return pkgerrors.Wrap(err, "DeleteInProgressAttempt failed") } @@ -1081,19 +1081,19 @@ func (o *evmTxStore) SaveInProgressAttempt(attempt *TxAttempt) error { } e = o.q.Get(&dbAttempt, query, args...) dbAttempt.ToTxAttempt(attempt) - return pkgerrors.Wrap(e, "SaveInProgressAttempt failed to insert into evm.tx_attempts") + return pkgerrors.Wrap(e, "SaveInProgressAttempt failed to insert into tx_attempts") } // Update only applies to case of insufficient eth and simply changes the state to in_progress - res, err := o.q.Exec(`UPDATE evm.tx_attempts SET state=$1, broadcast_before_block_num=$2 WHERE id=$3`, dbAttempt.State, dbAttempt.BroadcastBeforeBlockNum, dbAttempt.ID) + res, err := o.q.Exec(`UPDATE tx_attempts SET state=$1, broadcast_before_block_num=$2 WHERE id=$3`, dbAttempt.State, dbAttempt.BroadcastBeforeBlockNum, dbAttempt.ID) if err != nil { - return pkgerrors.Wrap(err, "SaveInProgressAttempt failed to update evm.tx_attempts") + return pkgerrors.Wrap(err, "SaveInProgressAttempt failed to update tx_attempts") } rowsAffected, err := res.RowsAffected() if err != nil { return pkgerrors.Wrap(err, "SaveInProgressAttempt failed to get RowsAffected") } if rowsAffected == 0 { - return pkgerrors.Wrapf(sql.ErrNoRows, "SaveInProgressAttempt tried to update evm.tx_attempts but no rows matched id %d", attempt.ID) + return pkgerrors.Wrapf(sql.ErrNoRows, "SaveInProgressAttempt tried to update tx_attempts but no rows matched id %d", attempt.ID) } return nil } @@ -1102,7 +1102,7 @@ func (o *evmTxStore) SaveInProgressAttempt(attempt *TxAttempt) error { // attempts which are unconfirmed for at least gasBumpThreshold blocks, // limited by limit pending transactions // -// It also returns evm.txes that are unconfirmed with no evm.tx_attempts +// It also returns evm.txes that are unconfirmed with no tx_attempts func (o *evmTxStore) FindTxsRequiringGasBump(ctx context.Context, address common.Address, blockNum, gasBumpThreshold, depth int64, chainID *big.Int) (etxs []*Tx, err error) { if gasBumpThreshold == 0 { return @@ -1111,8 +1111,8 @@ func (o *evmTxStore) FindTxsRequiringGasBump(ctx context.Context, address common err = qq.Transaction(func(tx pg.Queryer) error { stmt := ` SELECT evm.txes.* FROM evm.txes -LEFT JOIN evm.tx_attempts ON evm.txes.id = evm.tx_attempts.eth_tx_id AND (broadcast_before_block_num > $4 OR broadcast_before_block_num IS NULL OR evm.tx_attempts.state != 'broadcast') -WHERE evm.txes.state = 'unconfirmed' AND evm.tx_attempts.id IS NULL AND evm.txes.from_address = $1 AND evm.txes.evm_chain_id = $2 +LEFT JOIN tx_attempts ON evm.txes.id = tx_attempts.eth_tx_id AND (broadcast_before_block_num > $4 OR broadcast_before_block_num IS NULL OR tx_attempts.state != 'broadcast') +WHERE evm.txes.state = 'unconfirmed' AND tx_attempts.id IS NULL AND evm.txes.from_address = $1 AND evm.txes.evm_chain_id = $2 AND (($3 = 0) OR (evm.txes.id IN (SELECT id FROM evm.txes WHERE state = 'unconfirmed' AND from_address = $1 ORDER BY nonce ASC LIMIT $3))) ORDER BY nonce ASC ` @@ -1123,7 +1123,7 @@ ORDER BY nonce ASC etxs = make([]*Tx, len(dbEtxs)) dbEthTxsToEvmEthTxPtrs(dbEtxs, etxs) err = o.LoadTxesAttempts(etxs, pg.WithQueryer(tx)) - return pkgerrors.Wrap(err, "FindEthTxsRequiringGasBump failed to load evm.tx_attempts") + return pkgerrors.Wrap(err, "FindEthTxsRequiringGasBump failed to load tx_attempts") }, pg.OptReadOnlyTx()) return } @@ -1137,7 +1137,7 @@ func (o *evmTxStore) FindTxsRequiringResubmissionDueToInsufficientFunds(address var dbEtxs []DbEthTx err = tx.Select(&dbEtxs, ` SELECT DISTINCT evm.txes.* FROM evm.txes -INNER JOIN evm.tx_attempts ON evm.txes.id = evm.tx_attempts.eth_tx_id AND evm.tx_attempts.state = 'insufficient_eth' +INNER JOIN tx_attempts ON evm.txes.id = tx_attempts.eth_tx_id AND tx_attempts.state = 'insufficient_eth' WHERE evm.txes.from_address = $1 AND evm.txes.state = 'unconfirmed' AND evm.txes.evm_chain_id = $2 ORDER BY nonce ASC `, address, chainID.String()) @@ -1147,7 +1147,7 @@ ORDER BY nonce ASC etxs = make([]*Tx, len(dbEtxs)) dbEthTxsToEvmEthTxPtrs(dbEtxs, etxs) err = o.LoadTxesAttempts(etxs, pg.WithQueryer(tx)) - return pkgerrors.Wrap(err, "FindEthTxsRequiringResubmissionDueToInsufficientEth failed to load evm.tx_attempts") + return pkgerrors.Wrap(err, "FindEthTxsRequiringResubmissionDueToInsufficientEth failed to load tx_attempts") }, pg.OptReadOnlyTx()) return } @@ -1184,11 +1184,11 @@ SET state='fatal_error', nonce=NULL, error=$1, broadcast_at=NULL, initial_broadc FROM ( SELECT e1.id, e1.nonce, e1.from_address FROM evm.txes AS e1 WHERE id IN ( SELECT e2.id FROM evm.txes AS e2 - INNER JOIN evm.tx_attempts ON e2.id = evm.tx_attempts.eth_tx_id + INNER JOIN tx_attempts ON e2.id = tx_attempts.eth_tx_id WHERE e2.state = 'confirmed_missing_receipt' AND e2.evm_chain_id = $3 GROUP BY e2.id - HAVING max(evm.tx_attempts.broadcast_before_block_num) < $2 + HAVING max(tx_attempts.broadcast_before_block_num) < $2 ) FOR UPDATE OF e1 ) e0 @@ -1221,7 +1221,7 @@ RETURNING e0.id, e0.nonce`, ErrCouldNotGetReceipt, cutoff, chainID.String()) err = q.Select(&results, ` SELECT e.id, e.from_address, max(a.broadcast_before_block_num) AS max_broadcast_before_block_num, array_agg(a.hash) AS tx_hashes FROM evm.txes e -INNER JOIN evm.tx_attempts a ON e.id = a.eth_tx_id +INNER JOIN tx_attempts a ON e.id = a.eth_tx_id WHERE e.id = ANY($1) GROUP BY e.id `, etxIDs) @@ -1259,8 +1259,8 @@ func (o *evmTxStore) SaveReplacementInProgressAttempt(oldAttempt TxAttempt, repl return errors.New("expected oldAttempt to have an ID") } return qq.Transaction(func(tx pg.Queryer) error { - if _, err := tx.Exec(`DELETE FROM evm.tx_attempts WHERE id=$1`, oldAttempt.ID); err != nil { - return pkgerrors.Wrap(err, "saveReplacementInProgressAttempt failed to delete from evm.tx_attempts") + if _, err := tx.Exec(`DELETE FROM tx_attempts WHERE id=$1`, oldAttempt.ID); err != nil { + return pkgerrors.Wrap(err, "saveReplacementInProgressAttempt failed to delete from tx_attempts") } var dbAttempt DbEthTxAttempt dbAttempt.FromTxAttempt(replacementAttempt) @@ -1297,7 +1297,7 @@ func (o *evmTxStore) UpdateTxFatalError(etx *Tx, qopts ...pg.QOpt) error { etx.State = txmgr.TxFatalError return qq.Transaction(func(tx pg.Queryer) error { - if _, err := tx.Exec(`DELETE FROM evm.tx_attempts WHERE eth_tx_id = $1`, etx.ID); err != nil { + if _, err := tx.Exec(`DELETE FROM tx_attempts WHERE eth_tx_id = $1`, etx.ID); err != nil { return pkgerrors.Wrapf(err, "saveFatallyErroredTransaction failed to delete eth_tx_attempt with eth_tx.ID %v", etx.ID) } var dbEtx DbEthTx @@ -1343,7 +1343,7 @@ func (o *evmTxStore) UpdateTxAttemptInProgressToBroadcast(etx *Tx, attempt TxAtt dbEtx.ToTx(etx) var dbAttempt DbEthTxAttempt dbAttempt.FromTxAttempt(&attempt) - if err := tx.Get(&dbAttempt, `UPDATE evm.tx_attempts SET state = $1 WHERE id = $2 RETURNING *`, dbAttempt.State, dbAttempt.ID); err != nil { + if err := tx.Get(&dbAttempt, `UPDATE tx_attempts SET state = $1 WHERE id = $2 RETURNING *`, dbAttempt.State, dbAttempt.ID); err != nil { return pkgerrors.Wrap(err, "SaveEthTxAttempt failed to save eth_tx_attempt") } return nil @@ -1365,13 +1365,13 @@ func (o *evmTxStore) UpdateTxUnstartedToInProgress(etx *Tx, attempt *TxAttempt, etx.State = txmgr.TxInProgress return qq.Transaction(func(tx pg.Queryer) error { // If a replay was triggered while unconfirmed transactions were pending, they will be marked as fatal_error => abandoned. - // In this case, we must remove the abandoned attempt from evm.tx_attempts before replacing it with a new one. In any other + // In this case, we must remove the abandoned attempt from tx_attempts before replacing it with a new one. In any other // case, we uphold the constraint, leaving the original tx attempt as-is and returning the constraint violation error. // // Note: the record of the original abandoned transaction will remain in evm.txes, only the attempt is replaced. (Any receipt // associated with the abandoned attempt would also be lost, although this shouldn't happen since only unconfirmed transactions // can be abandoned.) - _, err := tx.Exec(`DELETE FROM evm.tx_attempts a USING evm.txes t + _, err := tx.Exec(`DELETE FROM tx_attempts a USING evm.txes t WHERE t.id = a.eth_tx_id AND a.hash = $1 AND t.state = $2 AND t.error = 'abandoned'`, attempt.Hash, txmgr.TxFatalError, ) @@ -1570,7 +1570,7 @@ id < ( func (o *evmTxStore) ReapTxHistory(minBlockNumberToKeep int64, timeThreshold time.Time, chainID *big.Int) error { // Delete old confirmed evm.txes // NOTE that this relies on foreign key triggers automatically removing - // the evm.tx_attempts and evm.receipts linked to every eth_tx + // the tx_attempts and evm.receipts linked to every eth_tx err := pg.Batch(func(_, limit uint) (count uint, err error) { res, err := o.q.Exec(` WITH old_enough_receipts AS ( @@ -1580,9 +1580,9 @@ WITH old_enough_receipts AS ( LIMIT $2 ) DELETE FROM evm.txes -USING old_enough_receipts, evm.tx_attempts -WHERE evm.tx_attempts.eth_tx_id = evm.txes.id -AND evm.tx_attempts.hash = old_enough_receipts.tx_hash +USING old_enough_receipts, tx_attempts +WHERE tx_attempts.eth_tx_id = evm.txes.id +AND tx_attempts.hash = old_enough_receipts.tx_hash AND evm.txes.created_at < $3 AND evm.txes.state = 'confirmed' AND evm_chain_id = $4`, minBlockNumberToKeep, limit, timeThreshold, chainID.String()) diff --git a/core/chains/evm/txmgr/evm_tx_store_test.go b/core/chains/evm/txmgr/evm_tx_store_test.go index 913652b7c8b..ed601264419 100644 --- a/core/chains/evm/txmgr/evm_tx_store_test.go +++ b/core/chains/evm/txmgr/evm_tx_store_test.go @@ -18,6 +18,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -35,7 +36,8 @@ import ( func TestORM_TransactionsWithAttempts(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, from := cltest.MustInsertRandomKey(t, ethKeyStore, 0) @@ -80,7 +82,8 @@ func TestORM_TransactionsWithAttempts(t *testing.T) { func TestORM_Transactions(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, from := cltest.MustInsertRandomKey(t, ethKeyStore, 0) @@ -119,8 +122,9 @@ func TestORM(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) keyStore := cltest.NewKeyStore(t, db, cfg.Database()) - orm := cltest.NewTestTxStore(t, db, cfg.Database()) + orm := cltest.NewTestTxStore(t, evmDB, cfg.Database()) _, fromAddress := cltest.MustInsertRandomKey(t, keyStore.Eth(), 0) var err error @@ -189,7 +193,8 @@ func TestORM(t *testing.T) { func TestORM_FindTxAttemptConfirmedByTxIDs(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) - orm := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + orm := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, from := cltest.MustInsertRandomKey(t, ethKeyStore, 0) @@ -240,7 +245,8 @@ func TestORM_FindTxAttemptsRequiringResend(t *testing.T) { db := pgtest.NewSqlxDB(t) logCfg := pgtest.NewQConfig(true) - txStore := cltest.NewTestTxStore(t, db, logCfg) + evmDB := evmtestdb.NewScopedDBWithOpts(t) + txStore := cltest.NewTestTxStore(t, evmDB, logCfg) ethKeyStore := cltest.NewKeyStore(t, db, logCfg).Eth() @@ -327,8 +333,9 @@ func TestORM_UpdateBroadcastAts(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) keyStore := cltest.NewKeyStore(t, db, cfg.Database()) - orm := cltest.NewTestTxStore(t, db, cfg.Database()) + orm := cltest.NewTestTxStore(t, evmDB, cfg.Database()) _, fromAddress := cltest.MustInsertRandomKey(t, keyStore.Eth(), 0) t.Run("does not update when broadcast_at is NULL", func(t *testing.T) { @@ -375,7 +382,8 @@ func TestORM_SetBroadcastBeforeBlockNum(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -443,7 +451,8 @@ func TestORM_FindTxAttemptsConfirmedMissingReceipt(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -466,7 +475,8 @@ func TestORM_UpdateTxsUnconfirmed(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -486,7 +496,8 @@ func TestORM_FindTxAttemptsRequiringReceiptFetch(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -507,7 +518,8 @@ func TestORM_SaveFetchedReceipts(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -541,7 +553,8 @@ func TestORM_MarkAllConfirmedMissingReceipt(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) @@ -571,7 +584,8 @@ func TestORM_PreloadTxes(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -605,7 +619,8 @@ func TestORM_GetInProgressTxAttempts(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -626,7 +641,8 @@ func TestORM_FindReceiptsPendingConfirmation(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -670,7 +686,8 @@ func Test_FindTxWithIdempotencyKey(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -700,7 +717,8 @@ func TestORM_FindTxWithSequence(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -725,7 +743,8 @@ func TestORM_UpdateTxForRebroadcast(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -765,7 +784,8 @@ func TestORM_FindTransactionsConfirmedInBlockRange(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -801,7 +821,8 @@ func TestORM_SaveInsufficientEthAttempt(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) defaultDuration, err := time.ParseDuration("5s") @@ -825,7 +846,8 @@ func TestORM_SaveSentAttempt(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) defaultDuration, err := time.ParseDuration("5s") @@ -850,7 +872,8 @@ func TestORM_SaveConfirmedMissingReceiptAttempt(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) defaultDuration, err := time.ParseDuration("5s") @@ -875,7 +898,8 @@ func TestORM_DeleteInProgressAttempt(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -897,7 +921,8 @@ func TestORM_SaveInProgressAttempt(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -938,7 +963,8 @@ func TestORM_FindTxsRequiringGasBump(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -978,7 +1004,8 @@ func TestEthConfirmer_FindTxsRequiringResubmissionDueToInsufficientEth(t *testin db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() @@ -1039,7 +1066,8 @@ func TestORM_MarkOldTxesMissingReceiptAsErrored(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -1080,7 +1108,8 @@ func TestORM_LoadEthTxesAttempts(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -1129,7 +1158,8 @@ func TestORM_SaveReplacementInProgressAttempt(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -1153,7 +1183,8 @@ func TestORM_FindNextUnstartedTransactionFromAddress(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) @@ -1180,7 +1211,8 @@ func TestORM_UpdateTxFatalError(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -1204,7 +1236,8 @@ func TestORM_UpdateTxAttemptInProgressToBroadcast(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -1237,7 +1270,8 @@ func TestORM_UpdateTxUnstartedToInProgress(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) q := pg.NewQ(db, logger.TestLogger(t), cfg.Database()) @@ -1272,7 +1306,7 @@ func TestORM_UpdateTxUnstartedToInProgress(t *testing.T) { db = pgtest.NewSqlxDB(t) cfg = newTestChainScopedConfig(t) - txStore = cltest.NewTestTxStore(t, db, cfg.Database()) + txStore = cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore = cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress = cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) q = pg.NewQ(db, logger.TestLogger(t), cfg.Database()) @@ -1319,7 +1353,7 @@ func TestORM_UpdateTxUnstartedToInProgress(t *testing.T) { // Should fail due to idx_eth_tx_attempt_hash constraint err := txStore.UpdateTxUnstartedToInProgress(&etx, &etx.TxAttempts[0]) assert.ErrorContains(t, err, "idx_eth_tx_attempts_hash") - txStore = cltest.NewTestTxStore(t, db, cfg.Database()) // current txStore is poisened now, next test will need fresh one + txStore = cltest.NewTestTxStore(t, evmDB, cfg.Database()) // current txStore is poisened now, next test will need fresh one }) } @@ -1328,7 +1362,8 @@ func TestORM_GetTxInProgress(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -1352,7 +1387,8 @@ func TestORM_HasInProgressTransaction(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -1377,7 +1413,8 @@ func TestORM_UpdateEthKeyNextNonce(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) ethKeyState, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) @@ -1403,7 +1440,8 @@ func TestORM_CountUnconfirmedTransactions(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore, 0) @@ -1424,7 +1462,8 @@ func TestORM_CountUnstartedTransactions(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore, 0) @@ -1445,7 +1484,8 @@ func TestORM_CheckTxQueueCapacity(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.MustAddRandomKeyToKeystore(t, ethKeyStore) @@ -1541,7 +1581,8 @@ func TestORM_CreateTransaction(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) - txStore := cltest.NewTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTxStore(t, evmDB, cfg.Database()) kst := cltest.NewKeyStore(t, db, cfg.Database()) _, fromAddress := cltest.MustInsertRandomKey(t, kst.Eth(), 0) @@ -1614,7 +1655,8 @@ func TestORM_PruneUnstartedTxQueue(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) - txStore := cltest.NewTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore, 0) diff --git a/core/chains/evm/txmgr/nonce_syncer_test.go b/core/chains/evm/txmgr/nonce_syncer_test.go index 05a6d4c8c7b..9baad0e2f53 100644 --- a/core/chains/evm/txmgr/nonce_syncer_test.go +++ b/core/chains/evm/txmgr/nonce_syncer_test.go @@ -8,6 +8,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -27,7 +28,8 @@ func Test_NonceSyncer_Sync(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) cfg := configtest.NewGeneralConfig(t, nil) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() - txStore := cltest.NewTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTxStore(t, evmDB, cfg.Database()) _, from := cltest.MustAddRandomKeyToKeystore(t, ethKeyStore) @@ -53,7 +55,8 @@ func Test_NonceSyncer_Sync(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) cfg := configtest.NewGeneralConfig(t, nil) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() - txStore := cltest.NewTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTxStore(t, evmDB, cfg.Database()) _, from := cltest.MustAddRandomKeyToKeystore(t, ethKeyStore) @@ -75,7 +78,8 @@ func Test_NonceSyncer_Sync(t *testing.T) { t.Run("does nothing if chain nonce is behind local nonce", func(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) - txStore := cltest.NewTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTxStore(t, evmDB, cfg.Database()) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() @@ -100,7 +104,8 @@ func Test_NonceSyncer_Sync(t *testing.T) { t.Run("fast forwards if chain nonce is ahead of local nonce", func(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) - txStore := cltest.NewTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTxStore(t, evmDB, cfg.Database()) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() @@ -130,7 +135,8 @@ func Test_NonceSyncer_Sync(t *testing.T) { t.Run("counts 'in_progress' eth_tx as bumping the local next nonce by 1", func(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, key1 := cltest.MustInsertRandomKey(t, ethKeyStore, int64(0)) diff --git a/core/chains/evm/txmgr/reaper_test.go b/core/chains/evm/txmgr/reaper_test.go index 11843222999..09c6c69e9ef 100644 --- a/core/chains/evm/txmgr/reaper_test.go +++ b/core/chains/evm/txmgr/reaper_test.go @@ -13,6 +13,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/utils" @@ -44,7 +45,8 @@ func TestReaper_ReapTxes(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, from := cltest.MustAddRandomKeyToKeystore(t, ethKeyStore) diff --git a/core/chains/evm/txmgr/resender_test.go b/core/chains/evm/txmgr/resender_test.go index d17156f4525..4f6e37902f6 100644 --- a/core/chains/evm/txmgr/resender_test.go +++ b/core/chains/evm/txmgr/resender_test.go @@ -19,6 +19,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -41,7 +42,8 @@ func Test_EthResender_resendUnconfirmed(t *testing.T) { _, fromAddress2 := cltest.MustInsertRandomKey(t, ethKeyStore) _, fromAddress3 := cltest.MustInsertRandomKey(t, ethKeyStore) - txStore := cltest.NewTestTxStore(t, db, logCfg) + evmDB := evmtestdb.NewScopedDBWithOpts(t) + txStore := cltest.NewTestTxStore(t, evmDB, logCfg) originalBroadcastAt := time.Unix(1616509100, 0) @@ -118,7 +120,8 @@ func Test_EthResender_alertUnconfirmed(t *testing.T) { _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) - txStore := cltest.NewTestTxStore(t, db, logCfg) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, logCfg) originalBroadcastAt := time.Unix(1616509100, 0) er := txmgr.NewEvmResender(lggr, txStore, txmgr.NewEvmTxmClient(ethClient), ethKeyStore, 100*time.Millisecond, ccfg.EVM(), ccfg.EVM().Transactions()) @@ -148,7 +151,8 @@ func Test_EthResender_Start(t *testing.T) { // Set batch size low to test batching c.EVM[0].RPCDefaultBatchSize = ptr[uint32](1) }) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmDB := evmtestdb.NewScopedDBWithOpts(t, evmtestdb.DBConfig(cfg.Database())) + txStore := cltest.NewTestTxStore(t, evmDB, cfg.Database()) ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() ccfg := evmtest.NewChainScopedConfig(t, cfg) _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) diff --git a/core/chains/evm/txmgr/txmgr_test.go b/core/chains/evm/txmgr/txmgr_test.go index 79fcf101d5f..ee6b1f0be6c 100644 --- a/core/chains/evm/txmgr/txmgr_test.go +++ b/core/chains/evm/txmgr/txmgr_test.go @@ -17,13 +17,12 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/sqlx" - txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" commontxmmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/types/mocks" "github.com/smartcontractkit/chainlink/v2/core/assets" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" + evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" @@ -33,6 +32,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" + evmtestdb "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest/db" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" @@ -43,7 +43,7 @@ import ( ) func makeTestEvmTxm( - t *testing.T, db *sqlx.DB, ethClient evmclient.Client, estimator gas.EvmFeeEstimator, ccfg txmgr.ChainConfig, fcfg txmgr.FeeConfig, txConfig evmconfig.Transactions, dbConfig txmgr.DatabaseConfig, listenerConfig txmgr.ListenerConfig, keyStore keystore.Eth, eventBroadcaster pg.EventBroadcaster) (txmgr.TxManager, error) { + t *testing.T, db *evmdb.ScopedDB, ethClient evmclient.Client, estimator gas.EvmFeeEstimator, ccfg txmgr.ChainConfig, fcfg txmgr.FeeConfig, txConfig evmconfig.Transactions, dbConfig txmgr.DatabaseConfig, listenerConfig txmgr.ListenerConfig, keyStore keystore.Eth, eventBroadcaster pg.EventBroadcaster) (txmgr.TxManager, error) { lggr := logger.TestLogger(t) lp := logpoller.NewLogPoller(logpoller.NewORM(testutils.FixtureChainID, db, lggr, pgtest.NewQConfig(true)), ethClient, lggr, 100*time.Millisecond, 2, 3, 2, 1000) @@ -73,7 +73,7 @@ func makeTestEvmTxm( func TestTxm_SendNativeToken_DoesNotSendToZero(t *testing.T) { t.Parallel() - db := pgtest.NewSqlxDB(t) + coredb := pgtest.NewSqlxDB(t) from := utils.ZeroAddress to := utils.ZeroAddress @@ -81,10 +81,11 @@ func TestTxm_SendNativeToken_DoesNotSendToZero(t *testing.T) { config, dbConfig, evmConfig := makeConfigs(t) - keyStore := cltest.NewKeyStore(t, db, dbConfig).Eth() + keyStore := cltest.NewKeyStore(t, coredb, dbConfig).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) estimator := gas.NewEstimator(logger.TestLogger(t), ethClient, config, evmConfig.GasEstimator()) - txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), keyStore, nil) + evmdb := evmtestdb.NewScopedDB(t, dbConfig) + txm, err := makeTestEvmTxm(t, evmdb, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), keyStore, nil) require.NoError(t, err) _, err = txm.SendNativeToken(big.NewInt(0), from, to, *value, 21000) @@ -97,7 +98,8 @@ func TestTxm_CreateTransaction(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + txStore := cltest.NewTestTxStore(t, evmdb, cfg.Database()) kst := cltest.NewKeyStore(t, db, cfg.Database()) _, fromAddress := cltest.MustInsertRandomKey(t, kst.Eth(), 0) @@ -110,7 +112,7 @@ func TestTxm_CreateTransaction(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) estimator := gas.NewEstimator(logger.TestLogger(t), ethClient, config, evmConfig.GasEstimator()) - txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), kst.Eth(), nil) + txm, err := makeTestEvmTxm(t, evmdb, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), kst.Eth(), nil) require.NoError(t, err) t.Run("with queue under capacity inserts eth_tx", func(t *testing.T) { @@ -293,12 +295,12 @@ func TestTxm_CreateTransaction(t *testing.T) { }) t.Run("forwards tx when a proper forwarder is set up", func(t *testing.T) { - pgtest.MustExec(t, db, `DELETE FROM evm.txes`) - pgtest.MustExec(t, db, `DELETE FROM evm.forwarders`) + pgtest.MustExec(t, evmdb.SqlxDB(), `DELETE FROM txes`) + pgtest.MustExec(t, evmdb.SqlxDB(), `DELETE FROM forwarders`) evmConfig.maxQueued = uint64(1) // Create mock forwarder, mock authorizedsenders call. - form := forwarders.NewORM(db, logger.TestLogger(t), cfg.Database()) + form := forwarders.NewORM(evmdb, logger.TestLogger(t), cfg.Database()) fwdrAddr := testutils.NewAddress() fwdr, err := form.CreateForwarder(fwdrAddr, utils.Big(cltest.FixtureChainID)) require.NoError(t, err) @@ -509,7 +511,8 @@ func makeConfigs(t *testing.T) (*mockConfig, *databaseConfig, *evmConfig) { func TestTxm_CreateTransaction_OutOfEth(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, nil) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + txStore := cltest.NewTestTxStore(t, evmdb, cfg.Database()) etKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() thisKey, _ := cltest.MustInsertRandomKey(t, etKeyStore, 1) @@ -525,7 +528,7 @@ func TestTxm_CreateTransaction_OutOfEth(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) kst := cltest.NewKeyStore(t, db, dbConfig) estimator := gas.NewEstimator(logger.TestLogger(t), ethClient, config, evmConfig.GasEstimator()) - txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), kst.Eth(), nil) + txm, err := makeTestEvmTxm(t, evmdb, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), kst.Eth(), nil) require.NoError(t, err) t.Run("if another key has any transactions with insufficient eth errors, transmits as normal", func(t *testing.T) { @@ -597,7 +600,6 @@ func TestTxm_CreateTransaction_OutOfEth(t *testing.T) { } func TestTxm_Lifecycle(t *testing.T) { - db := pgtest.NewSqlxDB(t) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) kst := ksmocks.NewEth(t) @@ -617,7 +619,8 @@ func TestTxm_Lifecycle(t *testing.T) { unsub := cltest.NewAwaiter() kst.On("SubscribeToKeyChanges").Return(keyChangeCh, unsub.ItHappened) estimator := gas.NewEstimator(logger.TestLogger(t), ethClient, config, evmConfig.GasEstimator()) - txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), kst, eventBroadcaster) + evmdb := evmtestdb.NewScopedDB(t, dbConfig) + txm, err := makeTestEvmTxm(t, evmdb, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), kst, eventBroadcaster) require.NoError(t, err) head := cltest.Head(42) @@ -676,7 +679,8 @@ func TestTxm_Reset(t *testing.T) { _, addr := cltest.MustInsertRandomKey(t, kst.Eth(), 5) _, addr2 := cltest.MustInsertRandomKey(t, kst.Eth(), 3) - txStore := cltest.NewTestTxStore(t, db, cfg.Database()) + evmdb := evmtestdb.NewScopedDB(t, cfg.Database()) + txStore := cltest.NewTestTxStore(t, evmdb, cfg.Database()) // 4 confirmed tx from addr1 for i := int64(0); i < 4; i++ { cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, i, i*42+1, addr) @@ -698,7 +702,7 @@ func TestTxm_Reset(t *testing.T) { eventBroadcaster.On("Subscribe", "evm.insert_on_txes", "").Return(sub, nil) estimator := gas.NewEstimator(logger.TestLogger(t), ethClient, cfg.EVM(), cfg.EVM().GasEstimator()) - txm, err := makeTestEvmTxm(t, db, ethClient, estimator, cfg.EVM(), cfg.EVM().GasEstimator(), cfg.EVM().Transactions(), cfg.Database(), cfg.Database().Listener(), kst.Eth(), eventBroadcaster) + txm, err := makeTestEvmTxm(t, evmdb, ethClient, estimator, cfg.EVM(), cfg.EVM().GasEstimator(), cfg.EVM().Transactions(), cfg.Database(), cfg.Database().Listener(), kst.Eth(), eventBroadcaster) require.NoError(t, err) cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, addr2) diff --git a/core/cmd/evm_transaction_commands_test.go b/core/cmd/evm_transaction_commands_test.go index eb421b03968..0633de94078 100644 --- a/core/cmd/evm_transaction_commands_test.go +++ b/core/cmd/evm_transaction_commands_test.go @@ -31,7 +31,7 @@ func TestShell_IndexTransactions(t *testing.T) { _, from := cltest.MustAddRandomKeyToKeystore(t, app.KeyStore.Eth()) - txStore := cltest.NewTestTxStore(t, app.GetSqlxDB(), app.GetConfig().Database()) + txStore := cltest.NewTestTxStore(t, app.GetRelayers().LegacyEVM().DB(), app.GetConfig().Database()) tx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 1, from) attempt := tx.TxAttempts[0] @@ -69,10 +69,9 @@ func TestShell_ShowTransaction(t *testing.T) { app := startNewApplicationV2(t, nil) client, r := app.NewShellAndRenderer() - db := app.GetSqlxDB() _, from := cltest.MustAddRandomKeyToKeystore(t, app.KeyStore.Eth()) - txStore := cltest.NewTestTxStore(t, db, app.GetConfig().Database()) + txStore := cltest.NewTestTxStore(t, app.GetRelayers().LegacyEVM().DB(), app.GetConfig().Database()) tx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 1, from) attempt := tx.TxAttempts[0] @@ -96,7 +95,7 @@ func TestShell_IndexTxAttempts(t *testing.T) { _, from := cltest.MustAddRandomKeyToKeystore(t, app.KeyStore.Eth()) - txStore := cltest.NewTestTxStore(t, app.GetSqlxDB(), app.GetConfig().Database()) + txStore := cltest.NewTestTxStore(t, app.GetRelayers().LegacyEVM().DB(), app.GetConfig().Database()) tx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 1, from) // page 1 diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go index 8a7e680b4f7..ceb74210afe 100644 --- a/core/cmd/shell_local_test.go +++ b/core/cmd/shell_local_test.go @@ -292,7 +292,8 @@ func TestShell_RebroadcastTransactions_Txm(t *testing.T) { keyStore := cltest.NewKeyStore(t, sqlxDB, config.Database()) _, fromAddress := cltest.MustInsertRandomKey(t, keyStore.Eth()) - txStore := cltest.NewTestTxStore(t, sqlxDB, config.Database()) + evmDB := heavyweight.EVMDB(t, config.Database()) + txStore := cltest.NewTestTxStore(t, evmDB, config.Database()) cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 7, 42, fromAddress) lggr := logger.TestLogger(t) @@ -370,11 +371,12 @@ func TestShell_RebroadcastTransactions_OutsideRange_Txm(t *testing.T) { c.Insecure.OCRDevelopmentMode = nil }) + evmDB := heavyweight.EVMDB(t, config.Database()) keyStore := cltest.NewKeyStore(t, sqlxDB, config.Database()) _, fromAddress := cltest.MustInsertRandomKey(t, keyStore.Eth(), 0) - txStore := cltest.NewTestTxStore(t, sqlxDB, config.Database()) + txStore := cltest.NewTestTxStore(t, evmDB, config.Database()) cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, int64(test.nonce), 42, fromAddress) lggr := logger.TestLogger(t) diff --git a/core/internal/testutils/evmtest/db/dbtest.go b/core/internal/testutils/evmtest/db/dbtest.go index 3292d2b73be..764424e733f 100644 --- a/core/internal/testutils/evmtest/db/dbtest.go +++ b/core/internal/testutils/evmtest/db/dbtest.go @@ -5,6 +5,7 @@ import ( evmdb "github.com/smartcontractkit/chainlink/v2/core/chains/evm/db" "github.com/smartcontractkit/chainlink/v2/core/config" + configtest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest/v2" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) @@ -13,3 +14,23 @@ func NewScopedDB(t testing.TB, cfg config.Database) *evmdb.ScopedDB { evmURL := evmdb.ScopedConnection(cfg.URL()) return &evmdb.ScopedDB{pgtest.NewSqlxDB(t, pg.WithURL(evmURL))} } + +// krr note to self: consolidate with above +func NewScopedDBWithOpts(t testing.TB, opts ...TestDBOpt) *evmdb.ScopedDB { + cfg := configtest.NewTestGeneralConfig(t) + evmURL := evmdb.ScopedConnection(cfg.Database().URL()) + d := &evmdb.ScopedDB{DB: pgtest.NewSqlxDB(t, pg.WithURL(evmURL))} + for _, opt := range opts { + opt(t, d) + } + return d +} + +type TestDBOpt = func(t testing.TB, d *evmdb.ScopedDB) + +func DBConfig(cfg config.Database) TestDBOpt { + return func(t testing.TB, d *evmdb.ScopedDB) { + evmURL := evmdb.ScopedConnection(cfg.URL()) + d.DB = pgtest.NewSqlxDB(t, pg.WithURL(evmURL)) + } +} diff --git a/core/services/pg/locked_db.go b/core/services/pg/locked_db.go index 7d946baee41..322e202e6c7 100644 --- a/core/services/pg/locked_db.go +++ b/core/services/pg/locked_db.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "net/url" + "strings" "time" "github.com/google/uuid" @@ -170,13 +171,14 @@ func WithURL(override url.URL) ConnectionOpt { } } -func SchemaScopedConnection(conn url.URL, schema string) url.URL { +func SchemaScopedConnection(conn url.URL, schema ...string) url.URL { // documentation on this options is limited; find by searching the official postgres docs // https://www.postgresql.org/docs/16/app-psql.html + schemas := strings.Join(schema, ",") u := conn queryVals := u.Query() - queryVals.Add("options", "-csearch_path="+schema) + queryVals.Add("options", "-csearch_path="+schemas) u.RawQuery = queryVals.Encode() return u