Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CCIP-3428 Enabling ccip smoke test for testnet #14452

Merged
merged 19 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions integration-tests/actions/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/lib/logging"
"github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters"
"github.com/smartcontractkit/chainlink-testing-framework/lib/utils/conversions"

"github.com/smartcontractkit/chainlink/integration-tests/contracts"
ethContracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
"github.com/smartcontractkit/chainlink/integration-tests/wrappers"
Expand Down Expand Up @@ -285,7 +286,7 @@ func fundChainlinkNodesAtAnyKey(
return err
}

fromAddress, err := privateKeyToAddress(privateKey)
fromAddress, err := PrivateKeyToAddress(privateKey)
if err != nil {
return err
}
Expand Down Expand Up @@ -336,7 +337,7 @@ type FundsToSendPayload struct {
// to given address. You can override any or none of the following: gas limit, gas price, gas fee cap, gas tip cap.
// Values that are not set will be estimated or taken from config.
func SendFunds(logger zerolog.Logger, client *seth.Client, payload FundsToSendPayload) (*types.Receipt, error) {
fromAddress, err := privateKeyToAddress(payload.PrivateKey)
fromAddress, err := PrivateKeyToAddress(payload.PrivateKey)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -910,7 +911,7 @@ func deployAnyOCRv1Contracts(
return ocrInstances, nil
}

func privateKeyToAddress(privateKey *ecdsa.PrivateKey) (common.Address, error) {
func PrivateKeyToAddress(privateKey *ecdsa.PrivateKey) (common.Address, error) {
publicKey := privateKey.Public()
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
Expand Down
8 changes: 8 additions & 0 deletions integration-tests/actions/refund.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,14 @@ func (r *OvershotTransferRetrier) Retry(ctx context.Context, logger zerolog.Logg
// of strategies to attempt to return funds, including retrying with less funds if the transaction fails due to
// insufficient funds, and retrying with a higher gas limit if the transaction fails due to gas too low.
func ReturnFundsFromNodes(log zerolog.Logger, client *seth.Client, chainlinkNodes []contracts.ChainlinkNodeWithKeysAndAddress) error {
var keyExporters []contracts.ChainlinkKeyExporter
for _, node := range chainlinkNodes {
keyExporters = append(keyExporters, node)
}
return ReturnFundsFromKeyExporterNodes(log, client, keyExporters)
}

func ReturnFundsFromKeyExporterNodes(log zerolog.Logger, client *seth.Client, chainlinkNodes []contracts.ChainlinkKeyExporter) error {
if client == nil {
return fmt.Errorf("seth client is nil, unable to return funds from chainlink nodes")
}
Expand Down
3 changes: 3 additions & 0 deletions integration-tests/ccip-tests/testsetups/test_env.go
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,9 @@ func DeployLocalCluster(
// a func to start the CL nodes asynchronously
deployCL := func() error {
noOfNodes := pointer.GetInt(testInputs.EnvInput.NewCLCluster.NoOfNodes)
if env.ClCluster == nil {
env.ClCluster = &test_env.ClCluster{}
}
// if individual nodes are specified, then deploy them with specified configs
if len(testInputs.EnvInput.NewCLCluster.Nodes) > 0 {
for _, clNode := range testInputs.EnvInput.NewCLCluster.Nodes {
Expand Down
6 changes: 5 additions & 1 deletion integration-tests/contracts/contract_models.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,13 @@ type OffchainAggregatorData struct {
type ChainlinkNodeWithKeysAndAddress interface {
MustReadOCRKeys() (*client.OCRKeys, error)
MustReadP2PKeys() (*client.P2PKeys, error)
ExportEVMKeysForChain(string) ([]*client.ExportedEVMKey, error)
PrimaryEthAddress() (string, error)
EthAddresses() ([]string, error)
ChainlinkKeyExporter
}

type ChainlinkKeyExporter interface {
ExportEVMKeysForChain(string) ([]*client.ExportedEVMKey, error)
}

type ChainlinkNodeWithForwarder interface {
Expand Down
6 changes: 3 additions & 3 deletions integration-tests/deployment/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ environments like testnet/mainnet.
- In-memory environment for fast integration testing
- EVM only

/deployment/docker
/deployment/devenv
- Coming soon
- package name `docker`
- package name `devenv`
- Docker environment for higher fidelity testing
- Support non-EVMs
- Support non-EVMs (yet to be implemented)

/deployment/ccip
- package name `ccipdeployment`
Expand Down
3 changes: 2 additions & 1 deletion integration-tests/deployment/ccip/add_chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,9 @@ func TestAddChainInbound(t *testing.T) {

// TODO: Send via all inbound lanes and use parallel helper
// Now that the proposal has been executed we expect to be able to send traffic to this new 4th chain.
startBlock, err := e.Env.Chains[newChain].LatestBlockNum(testcontext.Get(t))
latesthdr, err := e.Env.Chains[newChain].Client.HeaderByNumber(testcontext.Get(t), nil)
require.NoError(t, err)
startBlock := latesthdr.Number.Uint64()
seqNr := SendRequest(t, e.Env, state, initialDeploy[0], newChain, true)
require.NoError(t,
ConfirmExecWithSeqNr(t, e.Env.Chains[initialDeploy[0]], e.Env.Chains[newChain], state.Chains[newChain].OffRamp, &startBlock, seqNr))
Expand Down
3 changes: 2 additions & 1 deletion integration-tests/deployment/ccip/add_lane_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@ func TestAddLane(t *testing.T) {
require.Len(t, offRamps, 0)
}
}
startBlock, err := e.Env.Chains[to].LatestBlockNum(testcontext.Get(t))
latesthdr, err := e.Env.Chains[to].Client.HeaderByNumber(testcontext.Get(t), nil)
require.NoError(t, err)
startBlock := latesthdr.Number.Uint64()
seqNum := SendRequest(t, e.Env, state, from, to, false)
require.Equal(t, uint64(1), seqNum)
require.NoError(t, ConfirmExecWithSeqNr(t, e.Env.Chains[from], e.Env.Chains[to], state.Chains[to].OffRamp, &startBlock, seqNum))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,9 @@ func Test0002_InitialDeploy(t *testing.T) {
if src == dest {
continue
}
block, err := destChain.LatestBlockNum(testcontext.Get(t))
latesthdr, err := destChain.Client.HeaderByNumber(testcontext.Get(t), nil)
require.NoError(t, err)
block := latesthdr.Number.Uint64()
startBlocks[dest] = &block
seqNum := ccipdeployment.SendRequest(t, e, state, src, dest, false)
expectedSeqNum[dest] = seqNum
Expand Down
14 changes: 11 additions & 3 deletions integration-tests/deployment/ccip/test_assertions.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,15 @@ func ConfirmCommitWithExpectedSeqNumRange(
}

defer subscription.Unsubscribe()
timer := time.NewTimer(5 * time.Minute)
var duration time.Duration
deadline, ok := t.Deadline()
if ok {
// make this timer end a minute before so that we don't hit the deadline
duration = deadline.Sub(time.Now().Add(-1 * time.Minute))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the downside of hitting the deadline other than failing with a timeout which will happen anyways?
I think seconds should be enough? If the deadline is 5 minutes then 1 minute is 20% of the time. So either make it a percentage of the total deadline 2-5% or just a couple of seconds.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no real downside other than log output after the test times out, the test runtime will print all running goroutines and their stack

} else {
duration = 5 * time.Minute
}
timer := time.NewTimer(duration)
defer timer.Stop()
ticker := time.NewTicker(2 * time.Second)
defer ticker.Stop()
Expand All @@ -91,8 +99,8 @@ func ConfirmCommitWithExpectedSeqNumRange(
case subErr := <-subscription.Err():
return fmt.Errorf("subscription error: %w", subErr)
case <-timer.C:
return fmt.Errorf("timed out waiting for commit report on chain selector %d from source selector %d expected seq nr range %s",
dest.Selector, src.Selector, expectedSeqNumRange.String())
return fmt.Errorf("timed out after waiting %s duration for commit report on chain selector %d from source selector %d expected seq nr range %s",
duration.String(), dest.Selector, src.Selector, expectedSeqNumRange.String())
case report := <-sink:
if len(report.Report.MerkleRoots) > 0 {
// Check the interval of sequence numbers and make sure it matches
Expand Down
25 changes: 13 additions & 12 deletions integration-tests/deployment/ccip/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (

"github.com/ethereum/go-ethereum/accounts/abi/bind"

"github.com/smartcontractkit/chainlink-testing-framework/lib/logging"

"github.com/ethereum/go-ethereum/common"
chainsel "github.com/smartcontractkit/chain-selectors"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -158,7 +160,9 @@ func SendRequest(t *testing.T, e deployment.Environment, state CCIPOnChainState,
}, []uint64{dest})
require.NoError(t, err)
require.True(t, it.Next())
return it.Event.Message.Header.SequenceNumber
seqNum := it.Event.Message.Header.SequenceNumber
t.Logf("CCIP message sent from chain selector %d to chain selector %d tx %s seqNum %d", src, dest, tx.Hash().String(), seqNum)
return seqNum
}

// DeployedLocalDevEnvironment is a helper struct for setting up a local dev environment with docker
Expand All @@ -179,15 +183,13 @@ func NewDeployedLocalDevEnvironment(t *testing.T, lggr logger.Logger) DeployedLo
require.NotEmpty(t, envConfig.JDConfig, "jdUrl should not be empty")
chains, err := devenv.NewChains(lggr, envConfig.Chains)
require.NoError(t, err)
homeChainSel := uint64(0)
homeChainEVM := uint64(0)
// locate the home chain
homeChainSel := envConfig.HomeChainSelector
require.NotEmpty(t, homeChainSel, "homeChainSel should not be empty")
homeChainEVM, err := chainsel.ChainIdFromSelector(homeChainSel)
require.NoError(t, err)
require.NotEmpty(t, homeChainEVM, "homeChainEVM should not be empty")

// Say first chain is home chain.
for chainSel := range chains {
homeChainEVM, _ = chainsel.ChainIdFromSelector(chainSel)
homeChainSel = chainSel
break
}
// deploy the capability registry
ab, capReg, err := DeployCapReg(lggr, chains, homeChainSel)
require.NoError(t, err)
Expand All @@ -205,10 +207,9 @@ func NewDeployedLocalDevEnvironment(t *testing.T, lggr logger.Logger) DeployedLo
require.NoError(t, err)
require.NotNil(t, e)
require.NotNil(t, don)

zeroLogLggr := logging.GetTestLogger(t)
// fund the nodes
require.NoError(t, don.FundNodes(ctx, deployment.E18Mult(10), e.Chains))

devenv.FundNodes(t, zeroLogLggr, testEnv, cfg, don.PluginNodes())
return DeployedLocalDevEnvironment{
Ab: ab,
Env: *e,
Expand Down
22 changes: 21 additions & 1 deletion integration-tests/deployment/devenv/.sample.env
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,24 @@ E2E_JD_IMAGE=<job-distributor-image>
E2E_JD_VERSION=<job-distributor-version>

E2E_TEST_CHAINLINK_IMAGE=public.ecr.aws/w0i8p0z9/chainlink-ccip
E2E_TEST_CHAINLINK_VERSION=2.14.0-ccip1.5.0
E2E_TEST_CHAINLINK_VERSION=2.14.0-ccip1.5.0

# RPC Configuration
E2E_TEST_SEPOLIA_WALLET_KEY=<sepolia-wallet-key>
E2E_TEST_SEPOLIA_RPC_HTTP_URL_1=<sepolia-rpc-http-url>
E2E_TEST_SEPOLIA_RPC_HTTP_URL_2=<sepolia-rpc-http-url>
E2E_TEST_SEPOLIA_RPC_WS_URL_1=<rpc-ws-url>
E2E_TEST_SEPOLIA_RPC_WS_URL_2=<rpc-ws-url>

E2E_TEST_AVALANCHE_FUJI_WALLET_KEY=<avalanche-wallet-key>
E2E_TEST_AVALANCHE_FUJI_RPC_HTTP_URL_1=<avalanche-rpc-http-url>
E2E_TEST_AVALANCHE_FUJI_RPC_HTTP_URL_2=<avalanche-rpc-http-url>
E2E_TEST_AVALANCHE_FUJI_RPC_WS_URL_1=<avalanche-rpc-ws-url>
E2E_TEST_AVALANCHE_FUJI_RPC_WS_URL_2=<avalanche-rpc-ws-url>

E2E_TEST_BSC_TESTNET_WALLET_KEY=<bsc-wallet-key>
E2E_TEST_BSC_TESTNET_RPC_HTTP_URL_1=<bsc-rpc-http-url>
E2E_TEST_BSC_TESTNET_RPC_HTTP_URL_2=<bsc-rpc-http-url>
E2E_TEST_BSC_TESTNET_RPC_WS_URL_1=<bsc-rpc-ws-url>
E2E_TEST_BSC_TESTNET_RPC_WS_URL_2=<bsc-rpc-ws-url>

45 changes: 45 additions & 0 deletions integration-tests/deployment/devenv/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
## Overview

This package is used to create ephemeral environment for local/CI testing.
It sets up an environment with local Docker containers running Chainlink nodes and a job distributor.
It can either create new simulated private Ethereum network containers or connect to existing testnets/mainnets.

### Run Tests with Devenv

The tests created with this environment are run as [end-to-end integration smoke tests](../../smoke).

#### Setting Up Testconfig with Simulated Private Ethereum Network

To run tests (e.g., [ccip-test](../../smoke/ccip_test.go)),
you need to set up the testconfig following the [testconfig setup instructions](../../testconfig/README.md).
The testconfig specifies the details of the different configurations to set up the environment and run the tests.
Generally, tests are run with the [default](../../testconfig/default.toml) config unless overridden by product-specific config.
For example, the [ccip-test](../../smoke/ccip_test.go) uses [ccip.toml](../../testconfig/ccip/ccip.toml) to specify
CCIP-specific test environment details.

There are additional secret configuration parameters required by the `devenv` environment that are not stored in the testconfig.
These are read from environment variables. For example, Chainlink image, Job-Distributor image, etc.
All such environment variables are listed in the [sample.env](./.sample.env) file.
You can create a `.env` file in the same directory of the test and set the required environment variables.

#### Setting Up Testconfig for Running Tests with Existing Testnet/Mainnet

To run tests with existing testnet/mainnet, set up the testconfig with the details of the testnet/mainnet networks.
Following the integration-test [testconfig framework](../../testconfig/README.md#configuration-and-overrides),
create a new `overrides.toml` file with testnet/mainnet network details and place it under any location in the `integration-tests` directory.
By default, tests are run with private Ethereum network containers set up in the same Docker network as
the Chainlink nodes and job distributor. To run tests against existing testnet/mainnet,
set the `selected_network` field in the testconfig with the specific network names.

For example, if running [ccip-smoke](../../smoke/ccip_test.go) tests with Sepolia, Avax, and Binance testnets,
copy the contents of [sepolia_avax_binance.toml](../../testconfig/ccip/overrides/sepolia_avax_binance.toml)
to the `overrides.toml` file.

Before running the test, ensure that RPC and wallet secrets are set as environment variables.
Refer to the environment variables pattern in the [sample.env](./.sample.env) file to
provide necessary secrets applicable to the network you are running the tests against:
- `E2E_TEST_<networkName>_WALLET_KEY_<sequence_number>`
- `E2E_TEST_<networkName>_RPC_HTTP_URL_<sequence_number>`
- `E2E_TEST_<networkName>_RPC_WS_URL_<sequence_number>`

Now you are all set to run the tests with the existing testnet/mainnet.
Loading
Loading