Skip to content

Commit

Permalink
CCIP-4420 Merging integration tests and scripts (#15902)
Browse files Browse the repository at this point in the history
* Merging integration tests and scripts

* Fixing build, adding missing e2e tests

* Fixing linter

* Bump

* Bump

* Update integration-tests/ccip-tests/testconfig/README.md

Co-authored-by: Balamurali Gopalswami <[email protected]>

---------

Co-authored-by: Balamurali Gopalswami <[email protected]>
  • Loading branch information
mateusz-sekara and b-gopalswami authored Jan 14, 2025
1 parent 9fab511 commit 6505cb2
Show file tree
Hide file tree
Showing 62 changed files with 5,536 additions and 2,485 deletions.
28 changes: 28 additions & 0 deletions .github/e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1124,6 +1124,34 @@ runner-test-matrix:
CHAINLINK_USER_TEAM: CCIP
test_config_override_path: integration-tests/ccip-tests/testconfig/tomls/usdc_mock_deployment.toml

- id: ccip-smoke-lbtc-32bytes-destination-pool-data
path: integration-tests/ccip-tests/smoke/ccip_test.go
test_env_type: docker
runs_on: ubuntu-latest
triggers:
- PR E2E CCIP Tests
- Merge Queue E2E CCIP Tests
- Nightly E2E Tests
test_cmd: cd integration-tests/ccip-tests/smoke && go test ccip_test.go -test.run ^TestSmokeCCIPForBidirectionalLane$ -timeout 30m -count=1 -test.parallel=1 -json
test_env_vars:
E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2
CHAINLINK_USER_TEAM: CCIP
test_config_override_path: integration-tests/ccip-tests/testconfig/tomls/lbtc_mock_deployment_with_32bytes_data.toml

- id: ccip-smoke-lbtc-non32bytes-destination-pool-data
path: integration-tests/ccip-tests/smoke/ccip_test.go
test_env_type: docker
runs_on: ubuntu-latest
triggers:
- PR E2E CCIP Tests
- Merge Queue E2E CCIP Tests
- Nightly E2E Tests
test_cmd: cd integration-tests/ccip-tests/smoke && go test ccip_test.go -test.run ^TestSmokeCCIPForBidirectionalLane$ -timeout 30m -count=1 -test.parallel=1 -json
test_env_vars:
E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2
CHAINLINK_USER_TEAM: CCIP
test_config_override_path: integration-tests/ccip-tests/testconfig/tomls/lbtc_mock_deployment_with_non32bytes_data.toml

- id: ccip-smoke-db-compatibility
path: integration-tests/ccip-tests/smoke/ccip_test.go
test_env_type: docker
Expand Down
9 changes: 9 additions & 0 deletions core/scripts/ccip/.example.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
## DO NOT EDIT THIS FILE. PLEASE COPY TO .env AND EDIT THAT FILE INSTEAD
OWNER_KEY=DEF

RPC_5=wss://rpc.com
RPC_43113=wss://rpc.com
RPC_420=wss://rpc.com
RPC_11155111=wss://rpc.com
RPC_421613=wss://rpc.com
RPC_80001=wss://rpc.com
71 changes: 71 additions & 0 deletions core/scripts/ccip/ccip-revert-reason/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package main

import (
"flag"
"fmt"

"github.com/ethereum/go-ethereum/ethclient"

"github.com/smartcontractkit/chainlink/core/scripts/ccip/revert-reason/handler"
"github.com/smartcontractkit/chainlink/core/scripts/ccip/secrets"
)

var (
errorCodeString = flag.String("errorCode", "", "Error code string (e.g. 0x08c379a0)")

chainID = flag.Uint64("chainId", 0, "Chain ID for the transaction (e.g. 420)")
txHash = flag.String("txHash", "", "Transaction hash (e.g. 0x97be8559164442595aba46b5f849c23257905b78e72ee43d9b998b28eee78b84)")
txRequester = flag.String("txRequester", "", "Transaction requester address (e.g. 0xe88ff73814fb891bb0e149f5578796fa41f20242)")
rpcURL = flag.String("rpcURL", "", "RPC URL for the chain (can also be set in env var RPC_<chain_id>)")
)

func main() {
flag.Usage = func() {
fmt.Println("Usage: go run . [flags]")
fmt.Println("You must provide either an error code string or the transaction details and an RPC URL to decode the error")
flag.PrintDefaults()
}

flag.Parse()

if *errorCodeString == "" && (*chainID == 0 || *txHash == "" || *txRequester == "") {
flag.Usage()
return
}

errorString, err := getErrorString()
if err != nil {
fmt.Printf("Error getting error string: %v\n", err)
return
}
decodedError, err := handler.DecodeErrorStringFromABI(errorString)
if err != nil {
fmt.Printf("Error decoding error string: %v\n", err)
return
}

fmt.Println(decodedError)
}

func getErrorString() (string, error) {
if *errorCodeString != "" {
return *errorCodeString, nil
}

if *rpcURL == "" {
fmt.Printf("RPC URL not provided, looking for RPC_%d env var\n", *chainID)
envRPC := secrets.GetRPC(*chainID)
rpcURL = &envRPC
}

ec, err := ethclient.Dial(*rpcURL)
if err != nil {
return "", err
}
errString, err := handler.GetErrorForTx(ec, *txHash, *txRequester)
if err != nil {
return "", err
}

return errString, nil
}
20 changes: 20 additions & 0 deletions core/scripts/ccip/ccip-revert-reason/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package main

import (
"fmt"
"testing"

"github.com/smartcontractkit/chainlink/core/scripts/ccip/revert-reason/handler"
)

func TestRevertReason(t *testing.T) {
errorCodeString := "e1cd55090000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000008408c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002645524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"

decodedError, err := handler.DecodeErrorStringFromABI(errorCodeString)
if err != nil {
fmt.Printf("Error decoding error string: %v\n", err)
return
}

fmt.Println(decodedError)
}
120 changes: 120 additions & 0 deletions core/scripts/ccip/debugreceiver/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package main

import (
"bytes"
"context"
"fmt"
"math/big"
"strings"

"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/ethclient"
)

type ccipAny struct {
SourceChainID *big.Int
Sender []byte
Data []byte
Tokens []common.Address
Amounts []*big.Int
}

func panicErr(err error) {
if err != nil {
panic(err)
}
}

// ABIEncode is the equivalent of abi.encode.
// See a full set of examples https://github.com/ethereum/go-ethereum/blob/420b78659bef661a83c5c442121b13f13288c09f/accounts/abi/packing_test.go#L31
func ABIEncode(abiStr string, values ...interface{}) ([]byte, error) {
// Create a dummy method with arguments
inDef := fmt.Sprintf(`[{ "name" : "method", "type": "function", "inputs": %s}]`, abiStr)
inAbi, err := abi.JSON(strings.NewReader(inDef))
if err != nil {
return nil, err
}
res, err := inAbi.Pack("method", values...)
if err != nil {
return nil, err
}
return res[4:], nil
}

// ABIDecode is the equivalent of abi.decode.
// See a full set of examples https://github.com/ethereum/go-ethereum/blob/420b78659bef661a83c5c442121b13f13288c09f/accounts/abi/packing_test.go#L31
func ABIDecode(abiStr string, data []byte) ([]interface{}, error) {
inDef := fmt.Sprintf(`[{ "name" : "method", "type": "function", "outputs": %s}]`, abiStr)
inAbi, err := abi.JSON(strings.NewReader(inDef))
if err != nil {
return nil, err
}
return inAbi.Unpack("method", data)
}

func main() {
// User inputs
source, err := ethclient.Dial("TODO goerli URL")
panicErr(err)
dest, err := ethclient.Dial("TODO optimism URL")
panicErr(err)
var (
requestBlock = int64(7916078)
receiveBlock = int64(2518035)
ccipReceiver = common.HexToAddress("0x9fE056F44510F970d724adA16903ba5D75CC4742")
)

log, err := source.FilterLogs(context.Background(), ethereum.FilterQuery{
FromBlock: big.NewInt(requestBlock),
ToBlock: big.NewInt(requestBlock),
Topics: [][]common.Hash{{common.HexToHash("0x73dfb9df8214728e699dbaaf6ba97aa125afaaba83a5d0de7903062e7c5b3139")}}, // CCIPSendRequested
})
panicErr(err)
encodedMsg, err := ABIDecode(`[{"components":[
{"internalType":"uint256","name":"sourceChainId","type":"uint256"},
{"internalType":"uint64","name":"sequenceNumber","type":"uint64"},
{"internalType":"address","name":"sender","type":"address"},
{"internalType":"address","name":"receiver","type":"address"},
{"internalType":"uint64","name":"nonce","type":"uint64"},
{"internalType":"bytes","name":"data","type":"bytes"},
{"internalType":"address[]","name":"tokens","type":"address[]"},
{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},
{"internalType":"uint256","name":"gasLimit","type":"uint256"}],
"internalType":"structCCIP.EVM2EVMSubscriptionMessage","name":"message","type":"tuple"}]`,
log[0].Data)
panicErr(err)
send := encodedMsg[0].(struct {
SourceChainID *big.Int `json:"sourceChainId"`
SequenceNumber uint64 `json:"sequenceNumber"`
Sender common.Address `json:"sender"`
Receiver common.Address `json:"receiver"`
Nonce uint64 `json:"nonce"`
Data []uint8 `json:"data"`
Tokens []common.Address `json:"tokens"`
Amounts []*big.Int `json:"amounts"`
GasLimit *big.Int `json:"gasLimit"`
})
sender, err := ABIEncode(`[{"type":"bytes", "name":"sender"}]`, send.Sender.Bytes())
panicErr(err)
any2evm, err := ABIEncode(`[{"components":[
{"internalType":"uint256","name":"sourceChainId","type":"uint256"},
{"internalType":"bytes","name":"sender","type":"bytes"},
{"internalType":"bytes","name":"data","type":"bytes"},
{"internalType":"address[]","name":"tokens","type":"address[]"},
{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],
"internalType":"structCCIP.Any2EVMMessage","name":"message","type":"tuple"}]`,
ccipAny{send.SourceChainID, sender, send.Data, send.Tokens, send.Amounts})
panicErr(err)
a, err := dest.CallContract(context.Background(), ethereum.CallMsg{
From: common.HexToAddress("0x2b7ab40413da5077e168546ea376920591aee8e7"), // offramp router
To: &ccipReceiver,
Gas: send.GasLimit.Uint64(),
GasPrice: big.NewInt(0),
Data: bytes.Join([][]byte{hexutil.MustDecode("0xa0c6df15"), any2evm}, []byte{}), // ccipReceive selector
AccessList: nil,
}, big.NewInt(receiveBlock))
fmt.Println(a, err)
}
22 changes: 22 additions & 0 deletions core/scripts/ccip/manual-execution/batch_runner/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# batchrun.py

This script will run the manual-execution script repeatedly using a CSV file to
supply message IDs and txn hashes.

## Usage

Build main.go and copy 'manual-execution' into the same directory as this script.

Export messages to a file named 'msgs.csv' in the same directory as this script.
CSV file will ignore the first line (header) and each line should have two values separated by a comma.

The first value is the message ID and the second value is the CCIP send transaction hash.

Example csv file:
```
"message_id","transaction_hash"
0x1e221l7db3f193d19353d42e1bcece771e7edar57149a7f30afd31r8aa783e9a,0x03c88qfd30ar54f36a353262a67362838r52029a47h2a31141a0430bda937ba2
0x1e221l7db3f193d19353d42e1bcece771e7edar57149a7f30afd31r8aa783e9a,0x03c88qfd30ar54f36a353262a67362838r52029a47h2a31141a0430bda937ba2
0x1e221l7db3f193d19353d42e1bcece771e7edar57149a7f30afd31r8aa783e9a,0x03c88qfd30ar54f36a353262a67362838r52029a47h2a31141a0430bda937ba2
0x1e221l7db3f193d19353d42e1bcece771e7edar57149a7f30afd31r8aa783e9a,0x03c88qfd30ar54f36a353262a67362838r52029a47h2a31141a0430bda937ba2
```
55 changes: 55 additions & 0 deletions core/scripts/ccip/manual-execution/batch_runner/batchrun.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/bin/env python3

import subprocess
import os
import tempfile
import json

binary_name = "./manual-execution"
input_msgs = "msgs.csv"

# global config
src_rpc = "<rpc for source chain here>"
dest_rpc = "<rpc for destination chain here>"
dest_owner_key = "<private key for destination chain here>"
commit_store = "<commit store address here>"
off_ramp = "<off ramp address here>"
on_ramp = "<on ramp address here>"
dest_start_block = 11063581 # set to block where the messages commit report was written.
gas_limit_override = 2000000 # you can change this or leave it as is.

lines = open(input_msgs, "r").read().split("\n")[1:]

for i, pairs in enumerate(lines):
# per msg config
parts = pairs.split(",")
if len(parts) != 2:
if pairs != "":
print("skipping CSV line with unexpected format: %s" % pairs)
continue

msg_id = parts[0]
ccip_send_tx = parts[1]

print("[%d/%d] >>> %s %s" % (i, len(lines), ccip_send_tx, msg_id))

config = {
"source_chain_tx": ccip_send_tx,
"ccip_msg_id": msg_id,
"src_rpc": src_rpc,
"dest_rpc": dest_rpc,
"dest_owner_key": dest_owner_key,
"commit_store": commit_store,
"off_ramp": off_ramp,
"dest_start_block": dest_start_block,
"gas_limit_override": gas_limit_override
}
json_config = json.dumps(config)

with open("config.json", 'w') as f:
f.write(json_config)

try:
subprocess.run([binary_name])
except subprocess.CalledProcessError as e:
print("called process error: ", e)
12 changes: 12 additions & 0 deletions core/scripts/ccip/manual-execution/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"src_rpc": "<src_rpc_url>",
"dest_rpc": "<dest_rpc_url>",
"dest_owner_key": "<owner's private key for destination chain>",
"commit_store": "0xd2Aa03c8C6E6a8E227223E72f314d4398ABe6eD0",
"off_ramp": "0x60475789dF0d8739cda56aF1D914749A5b48B3f7",
"on_ramp": "0xBb0e1066888F9Ef72824f63fd2067ff469378f6F",
"dest_start_block": 0,
"source_chain_tx": "0x517f6d4742568d531bc9b980bc7f82460a5012fce5dd7c57ec703444f88f5d92",
"ccip_msg_id": "0xba2312c236dd9f83ccd22ff6636fca5af739abb0cdc9824b8f59ec9824a5daf1",
"dest_deployed_at": 3043616
}
33 changes: 33 additions & 0 deletions core/scripts/ccip/manual-execution/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module manual-execution

go 1.20

require (
github.com/ethereum/go-ethereum v1.11.3
github.com/pkg/errors v0.9.1
github.com/smartcontractkit/chain-selectors v1.0.35
go.uber.org/multierr v1.1.0
golang.org/x/crypto v0.1.0
)

require (
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
github.com/deckarep/golang-set/v2 v2.1.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-ole/go-ole v1.2.1 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
github.com/tklauser/go-sysconf v0.3.5 // indirect
github.com/tklauser/numcpus v0.2.2 // indirect
go.uber.org/atomic v1.3.2 // indirect
golang.org/x/sys v0.5.0 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

exclude github.com/sourcegraph/sourcegraph/lib v0.0.0-20221216004406-749998a2ac74
Loading

0 comments on commit 6505cb2

Please sign in to comment.