Skip to content

Commit

Permalink
Added ChainWriter to ChainComponents interface tests
Browse files Browse the repository at this point in the history
  • Loading branch information
silaslenihan committed Sep 5, 2024
1 parent 2f4f446 commit 1467436
Show file tree
Hide file tree
Showing 14 changed files with 360 additions and 204 deletions.
5 changes: 5 additions & 0 deletions .changeset/loud-months-act.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink": minor
---

#internal Added ChainWriter to ChainReader tests
2 changes: 1 addition & 1 deletion core/scripts/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ require (
github.com/prometheus/client_golang v1.17.0
github.com/shopspring/decimal v1.4.0
github.com/smartcontractkit/chainlink-automation v1.0.4
github.com/smartcontractkit/chainlink-common v0.2.2-0.20240903184200-6488292a85e3
github.com/smartcontractkit/chainlink-common v0.2.2-0.20240905145927-2ff0f9628f4d
github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000
github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7
github.com/spf13/cobra v1.8.0
Expand Down
4 changes: 2 additions & 2 deletions core/scripts/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1190,8 +1190,8 @@ github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8um
github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM=
github.com/smartcontractkit/chainlink-ccip v0.0.0-20240905130411-ebd9328c9870 h1:/NYLKZOQhOAPFszrq86gPBD47Rt6TF69GnZ8Vf7qdVQ=
github.com/smartcontractkit/chainlink-ccip v0.0.0-20240905130411-ebd9328c9870/go.mod h1:Z9lQ5t20kRk28pzRLnqAJZUVOw8E6/siA3P3MLyKqoM=
github.com/smartcontractkit/chainlink-common v0.2.2-0.20240903184200-6488292a85e3 h1:fkfOoAPviqO2rN8ngvejsDa7WKcw4paGEFA4/Znu0L0=
github.com/smartcontractkit/chainlink-common v0.2.2-0.20240903184200-6488292a85e3/go.mod h1:D/qaCoq0SxXzg5NRN5FtBRv98VBf+D2NOC++RbvvuOc=
github.com/smartcontractkit/chainlink-common v0.2.2-0.20240905145927-2ff0f9628f4d h1:VVtgseTBEJN0/NcewMcka1qwslKhY1HPXs4EEpZa7ek=
github.com/smartcontractkit/chainlink-common v0.2.2-0.20240905145927-2ff0f9628f4d/go.mod h1:D/qaCoq0SxXzg5NRN5FtBRv98VBf+D2NOC++RbvvuOc=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45/go.mod h1:LV0h7QBQUpoC2UUi6TcUvcIFm1xjP/DtEcqV8+qeLUs=
github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240904093355-e40169857652 h1:0aZ3HiEz2bMM5ywHAyKlFMN95qTzpNDn7uvnHLrFX6s=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package evm_test

import (
"context"
"crypto/ecdsa"
"fmt"
"math"
"math/big"
Expand All @@ -18,26 +19,33 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config"
clcommontypes "github.com/smartcontractkit/chainlink-common/pkg/types"
. "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint common practice to import test mods with .
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"

"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm"
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types"

commontestutils "github.com/smartcontractkit/chainlink-common/pkg/loop/testutils"

"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
evmtxmgr "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
keytypes "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey"
. "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/evmtesting" //nolint common practice to import test mods with .
)

const commonGasLimitOnEvms = uint64(4712388)

func TestChainReaderEventsInitValidation(t *testing.T) {
func TestContractReaderEventsInitValidation(t *testing.T) {
tests := []struct {
name string
chainContractReaders map[string]types.ChainContractReader
Expand Down Expand Up @@ -143,43 +151,77 @@ func TestChainReaderEventsInitValidation(t *testing.T) {
}
}

func TestChainReader(t *testing.T) {
func TestChainComponents(t *testing.T) {
t.Parallel()
it := &EVMChainReaderInterfaceTester[*testing.T]{Helper: &helper{}}
it := &EVMChainComponentsInterfaceTester[*testing.T]{Helper: &helper{}}

it.Helper.Init(t)

// add new subtests here so that it can be run on real chains too
RunChainReaderEvmTests(t, it)
RunChainReaderInterfaceTests[*testing.T](t, commontestutils.WrapChainReaderTesterForLoop(it))
RunChainComponentsEvmTests(t, it)
RunContractReaderInterfaceTests[*testing.T](t, commontestutils.WrapContractReaderTesterForLoop(it), false)
}

type helper struct {
sim *backends.SimulatedBackend
auth *bind.TransactOpts
sim *backends.SimulatedBackend
accounts []*bind.TransactOpts
deployerKey *ecdsa.PrivateKey
senderKey *ecdsa.PrivateKey
txm evmtxmgr.TxManager
client client.Client
db *sqlx.DB
}

func (h *helper) MustGenerateRandomKey(t *testing.T) ethkey.KeyV2 {
return cltest.MustGenerateRandomKey(t)
func (h *helper) Init(t *testing.T) {
h.SetupKeys(t)

h.accounts = h.Accounts(t)

h.db = pgtest.NewSqlxDB(t)

h.Backend()
h.client = h.Client(t)

h.txm = h.TXM(t, h.client)
h.Commit()
}

func (h *helper) GasPriceBufferPercent() int64 {
return 0
func (h *helper) SetupKeys(t *testing.T) {
deployerPkey, err := crypto.GenerateKey()
require.NoError(t, err)
h.deployerKey = deployerPkey

senderPkey, err := crypto.GenerateKey()
require.NoError(t, err)
h.senderKey = senderPkey
}

func (h *helper) SetupAuth(t *testing.T) *bind.TransactOpts {
privateKey, err := crypto.GenerateKey()
func (h *helper) Accounts(t *testing.T) []*bind.TransactOpts {
if h.accounts != nil {
return h.accounts
}
deployer, err := bind.NewKeyedTransactorWithChainID(h.deployerKey, big.NewInt(1337))
require.NoError(t, err)

h.auth, err = bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(1337))
sender, err := bind.NewKeyedTransactorWithChainID(h.senderKey, big.NewInt(1337))
require.NoError(t, err)

h.Backend()
h.Commit()
return h.auth
return []*bind.TransactOpts{deployer, sender}
}

func (h *helper) MustGenerateRandomKey(t *testing.T) ethkey.KeyV2 {
return cltest.MustGenerateRandomKey(t)
}

func (h *helper) GasPriceBufferPercent() int64 {
return 0
}

func (h *helper) Backend() bind.ContractBackend {
if h.sim == nil {
h.sim = backends.NewSimulatedBackend(
core.GenesisAlloc{h.auth.From: {Balance: big.NewInt(math.MaxInt64)}}, commonGasLimitOnEvms*5000)
core.GenesisAlloc{h.accounts[0].From: {Balance: big.NewInt(math.MaxInt64)}, h.accounts[1].From: {Balance: big.NewInt(math.MaxInt64)}}, commonGasLimitOnEvms*5000)
cltest.Mine(h.sim, 1*time.Second)
}

return h.sim
Expand All @@ -190,6 +232,9 @@ func (h *helper) Commit() {
}

func (h *helper) Client(t *testing.T) client.Client {
if h.client != nil {
return h.client
}
return client.NewSimulatedBackendClient(t, h.sim, big.NewInt(1337))
}

Expand All @@ -205,6 +250,18 @@ func (h *helper) Context(t *testing.T) context.Context {
return testutils.Context(t)
}

func (h *helper) ChainReaderEVMClient(ctx context.Context, t *testing.T, ht logpoller.HeadTracker, conf types.ChainReaderConfig) client.Client {
// wrap the client so that we can mock historical contract state
cwh := &evm.ClientWithContractHistory{Client: h.Client(t), HT: ht}
require.NoError(t, cwh.Init(ctx, conf))
return cwh
}

func (h *helper) WrappedChainWriter(cw clcommontypes.ChainWriter, client client.Client) clcommontypes.ChainWriter {
cwhw := evm.NewChainWriterHistoricalWrapper(cw, client.(*evm.ClientWithContractHistory))
return cwhw
}

func (h *helper) MaxWaitTimeForEvents() time.Duration {
// From trial and error, when running on CI, sometimes the boxes get slow
maxWaitTime := time.Second * 30
Expand All @@ -216,6 +273,41 @@ func (h *helper) MaxWaitTimeForEvents() time.Duration {
}
maxWaitTime = time.Second * time.Duration(waitS)
}

return maxWaitTime
}

func (h *helper) TXM(t *testing.T, client client.Client) evmtxmgr.TxManager {
if h.txm != nil {
return h.txm
}
db := h.db

clconfig := configtest.NewGeneralConfigSimulated(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.Database.Listener.FallbackPollInterval = commonconfig.MustNewDuration(100 * time.Millisecond)
c.EVM[0].GasEstimator.EIP1559DynamicFees = ptr(true)
})

clconfig.EVMConfigs()[0].GasEstimator.PriceMax = assets.GWei(100)

app := cltest.NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain(t, clconfig, h.sim, db, client)
err := app.Start(h.Context(t))
require.NoError(t, err)

keyStore := app.KeyStore.Eth()

keyStore.XXXTestingOnlyAdd(h.Context(t), keytypes.FromPrivateKey(h.deployerKey))
require.NoError(t, keyStore.Add(h.Context(t), h.accounts[0].From, h.ChainID()))
require.NoError(t, keyStore.Enable(h.Context(t), h.accounts[0].From, h.ChainID()))

keyStore.XXXTestingOnlyAdd(h.Context(t), keytypes.FromPrivateKey(h.senderKey))
require.NoError(t, keyStore.Add(h.Context(t), h.accounts[1].From, h.ChainID()))
require.NoError(t, keyStore.Enable(h.Context(t), h.accounts[1].From, h.ChainID()))

chain, err := app.GetRelayers().LegacyEVMChains().Get((h.ChainID()).String())
require.NoError(t, err)

h.txm = chain.TxManager()
return h.txm
}

func ptr[T any](v T) *T { return &v }
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package evmtesting
package evm

import (
"context"
Expand All @@ -14,9 +14,9 @@ import (

clcommontypes "github.com/smartcontractkit/chainlink-common/pkg/types"
. "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint common practice to import test mods with .

"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm"
"github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types"
)

Expand All @@ -30,7 +30,7 @@ type ClientWithContractHistory struct {

func (cwh *ClientWithContractHistory) Init(_ context.Context, config types.ChainReaderConfig) error {
cwh.valsWithCall = make(map[int64]valWithCall)
parsedTypes := evm.ParsedTypes{
parsedTypes := ParsedTypes{
EncoderDefs: make(map[string]types.CodecEntry),
DecoderDefs: make(map[string]types.CodecEntry),
}
Expand All @@ -47,12 +47,12 @@ func (cwh *ClientWithContractHistory) Init(_ context.Context, config types.Chain
continue
}

inputMod, err := readDef.InputModifications.ToModifier(evm.DecoderHooks...)
inputMod, err := readDef.InputModifications.ToModifier(DecoderHooks...)
if err != nil {
return err
}

outputMod, err := readDef.OutputModifications.ToModifier(evm.DecoderHooks...)
outputMod, err := readDef.OutputModifications.ToModifier(DecoderHooks...)
if err != nil {
return err
}
Expand All @@ -67,8 +67,8 @@ func (cwh *ClientWithContractHistory) Init(_ context.Context, config types.Chain
return err
}

parsedTypes.EncoderDefs[evm.WrapItemType(contractName, genericName, true)] = input
parsedTypes.DecoderDefs[evm.WrapItemType(contractName, genericName, false)] = output
parsedTypes.EncoderDefs[WrapItemType(contractName, genericName, true)] = input
parsedTypes.DecoderDefs[WrapItemType(contractName, genericName, false)] = output
}
}

Expand All @@ -90,7 +90,6 @@ func (cwh *ClientWithContractHistory) SetUintLatestValue(ctx context.Context, va
ExpectedGetLatestValueArgs: forCall,
val: val,
}

return nil
}

Expand Down Expand Up @@ -123,7 +122,7 @@ func (cwh *ClientWithContractHistory) CallContract(ctx context.Context, msg ethe
}

// encode the expected call to compare with the actual call
dataToCmp, err := cwh.codec.Encode(ctx, valAndCall.Params, evm.WrapItemType(valAndCall.ContractName, valAndCall.ReadName, true))
dataToCmp, err := cwh.codec.Encode(ctx, valAndCall.Params, WrapItemType(valAndCall.ContractName, valAndCall.ReadName, true))
if err != nil {
return nil, err
}
Expand Down
39 changes: 39 additions & 0 deletions core/services/relay/evm/chain_writer_historical_wrapper_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package evm

import (
"context"
"math/big"

commontypes "github.com/smartcontractkit/chainlink-common/pkg/types"
interfacetesttypes "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests"
primitives "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives"
)

// This wrapper is required to enable the ChainReader to access historical data
// Since the geth simulated backend doesn't support historical data, we use this
// thin wrapper.
type ChainWriterHistoricalWrapper struct {
commontypes.ChainWriter
cwh *ClientWithContractHistory
}

func NewChainWriterHistoricalWrapper(cw commontypes.ChainWriter, cwh *ClientWithContractHistory) *ChainWriterHistoricalWrapper {
return &ChainWriterHistoricalWrapper{ChainWriter: cw, cwh: cwh}
}

func (cwhw *ChainWriterHistoricalWrapper) SubmitTransaction(ctx context.Context, contractName, method string, args any, transactionID string, toAddress string, meta *commontypes.TxMeta, value *big.Int) error {
if primArgs, ok := args.(interfacetesttypes.PrimitiveArgs); ok {
callArgs := interfacetesttypes.ExpectedGetLatestValueArgs{
ContractName: contractName,
ReadName: "GetAlterablePrimitiveValue",
ConfidenceLevel: primitives.Unconfirmed,
Params: nil,
ReturnVal: nil,
}
err := cwhw.cwh.SetUintLatestValue(ctx, primArgs.Value, callArgs)
if err != nil {
return err
}
}
return cwhw.ChainWriter.SubmitTransaction(ctx, contractName, method, args, transactionID, toAddress, meta, value)
}
Loading

0 comments on commit 1467436

Please sign in to comment.