diff --git a/deployment/environment.go b/deployment/environment.go index 7b5d1b6c9e3..0823404da2d 100644 --- a/deployment/environment.go +++ b/deployment/environment.go @@ -35,7 +35,6 @@ type OnchainClient interface { bind.DeployBackend BalanceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (*big.Int, error) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) - BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) } // OffchainClient interacts with the job-distributor diff --git a/deployment/environment/memory/sim.go b/deployment/environment/memory/sim.go index 93f77a0d29b..c0fba87e2b3 100644 --- a/deployment/environment/memory/sim.go +++ b/deployment/environment/memory/sim.go @@ -80,10 +80,6 @@ func (b *Backend) NonceAt(ctx context.Context, account common.Address, blockNumb return b.Sim.Client().NonceAt(ctx, account, blockNumber) } -func (b *Backend) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { - return b.Sim.Client().BlockByNumber(ctx, number) -} - func NewBackend(sim *simulated.Backend) *Backend { if sim == nil { panic("simulated backend is nil") diff --git a/integration-tests/load/ccip/ccip_test.go b/integration-tests/load/ccip/ccip_test.go index 79c87106960..6f364252fb9 100644 --- a/integration-tests/load/ccip/ccip_test.go +++ b/integration-tests/load/ccip/ccip_test.go @@ -3,11 +3,10 @@ package ccip import ( "fmt" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" "github.com/smartcontractkit/chainlink-testing-framework/wasp" - "github.com/smartcontractkit/chainlink/deployment" - ccipdeployment "github.com/smartcontractkit/chainlink/deployment/ccip" + ccipchangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" "github.com/stretchr/testify/require" "math/big" @@ -21,9 +20,7 @@ var ( "branch": "ccip_load_crib", "commit": "ccip_load_crib", } - wg sync.WaitGroup - abPath = "/Users/austin.wang/ccip-core/repos/chainlink/integration-tests/load/ccip/testfiles/ccip-v2-scripts-address-book.json" - nodeIdsPath = "/Users/austin.wang/ccip-core/repos/chainlink/integration-tests/load/ccip/testfiles/ccip-v2-scripts-node-details.json" + wg sync.WaitGroup ) // step 1: setup @@ -36,32 +33,24 @@ var ( // Stop the chains, cleanup the environment func TestCCIPLoad_RPS(t *testing.T) { ctx := tests.Context(t) - l := logging.GetTestLogger(t) + lggr := logger.Test(t) config, err := tc.GetConfig([]string{"Load"}, tc.CCIP) - if err != nil { - t.Fatal(err) - } - l.Info().Interface("loadedTestConfig", config).Msg("Loaded Test Config") - - l.Info().Msg("Starting ccip load test") - l.Info(). - Int("Number of Nodes", *(config.CCIP.Load.NoOfNodes)). - Interface("config", config.CCIP.Load). - Msg("Test Config") + require.NoError(t, err) + lggr.Infof("loaded test config: %+v", config) - var env = generateEnvironment() + lggr.Info("starting ccip load test") + lggr.Infof("Number of nodes: %d", *(config.CCIP.Load.NoOfNodes)) + lggr.Infof("config: %+v", config.CCIP.Load) + lggr.Info("Test Config") - var env = deployment.Environment{} - // output, err := actions.SetupCCIPHomeChain(l, sethClient, config.CCIP, workerNodes) - // require.NoError(t, err) - // env, err = crib.DeployPrerequisites(output, config.CCIP) - // merge addressbooks - // env, err := crib.DeployCCIPContracts(output, config.CCIP) + env, err := CreateEnvironmentFromCribOutput(t, lggr) + require.NoError(t, err) + require.NotNil(t, env) // Need to keep track of the block number for each chain so that event subscription can be done from that block. startBlocks := make(map[uint64]*uint64) - state, err := ccipdeployment.LoadOnchainState(env) + state, err := ccipchangeset.LoadOnchainState(*env) require.NoError(t, err) cfgl := config.Logging.Loki @@ -69,7 +58,7 @@ func TestCCIPLoad_RPS(t *testing.T) { // Parse all events from the simulated chains, send to Loki loki, err := wasp.NewLokiClient(wasp.NewLokiConfig(cfgl.Endpoint, cfgl.TenantId, cfgl.BasicAuth, cfgl.BearerToken)) if err != nil { - l.Error().Err(err).Msg("Failed to create Loki client") + env.Logger.Error("failed to create loki client") return } defer loki.StopNow() @@ -92,7 +81,7 @@ func TestCCIPLoad_RPS(t *testing.T) { // this schedule is per generator // in this example, it would be 1 request per 10seconds per generator (dest chain) // so if there are 3 generators, it would be 3 requests per 10 seconds over the network - Gun: NewDestinationGun(l, selector, env, state.Chains[selector].Receiver.Address(), loki), + Gun: NewDestinationGun(env.Logger, selector, env, state.Chains[selector].Receiver.Address(), loki), Labels: CommonTestLabels, LokiConfig: wasp.NewLokiConfig(cfgl.Endpoint, cfgl.TenantId, cfgl.BasicAuth, cfgl.BearerToken), // use the same loki client using `NewLokiClient` with the same config for sending events @@ -122,9 +111,9 @@ func TestCCIPLoad_RPS(t *testing.T) { fmt.Printf("CommitReportAccepted event: %+v\n", event) blockNum := commitIterator.Event.Raw.BlockNumber - block, err := env.Chains[chainSelector].Client.BlockByNumber(ctx, big.NewInt(int64(blockNum))) + header, err := env.Chains[chainSelector].Client.HeaderByNumber(ctx, big.NewInt(int64(blockNum))) require.NoError(t, err) - timestamp := time.Unix(int64(block.Time()), 0) + timestamp := time.Unix(int64(header.Time()), 0) for _, root := range event.MerkleRoots { lokiLabels = setLokiLabels(root.SourceChainSelector, chainSelector) @@ -148,9 +137,9 @@ func TestCCIPLoad_RPS(t *testing.T) { fmt.Printf("ExecutionStateChanged event: %+v\n", event) blockNum := execIterator.Event.Raw.BlockNumber - block, err := env.Chains[chainSelector].Client.BlockByNumber(ctx, big.NewInt(int64(blockNum))) + header, err := env.Chains[chainSelector].Client.HeaderByNumber(ctx, big.NewInt(int64(blockNum))) require.NoError(t, err) - timestamp := time.Unix(int64(block.Time()), 0) + timestamp := time.Unix(int64(header.Time), 0) // todo: push loki calls to channel? lokiLabels = setLokiLabels(execIterator.Event.SourceChainSelector, chainSelector) @@ -172,9 +161,3 @@ func TestCCIPLoad_RPS(t *testing.T) { // crib.StopChains(env) // crib.StopNodes(env) } - -func generateEnvironment() { - ab := readAddressBook(abPath) - nIds := readNodeIds(nodeIdsPath) - -} diff --git a/integration-tests/load/ccip/destination_gun.go b/integration-tests/load/ccip/destination_gun.go index 455f6dcc186..3ba9e2416ad 100644 --- a/integration-tests/load/ccip/destination_gun.go +++ b/integration-tests/load/ccip/destination_gun.go @@ -5,12 +5,13 @@ import ( "fmt" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - "github.com/rs/zerolog" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-testing-framework/wasp" "github.com/smartcontractkit/chainlink/deployment" - ccipdeployment "github.com/smartcontractkit/chainlink/deployment/ccip" + ccipchangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "sync/atomic" "time" ) @@ -21,7 +22,7 @@ type ChainSelectorPair struct { } type DestinationGun struct { - l zerolog.Logger + l logger.Logger env deployment.Environment seqNums map[ChainSelectorPair]*atomic.Uint64 roundNum *atomic.Int32 @@ -30,7 +31,7 @@ type DestinationGun struct { loki *wasp.LokiClient } -func NewDestinationGun(l zerolog.Logger, chainSelector uint64, env deployment.Environment, receiver common.Address, loki *wasp.LokiClient) *DestinationGun { +func NewDestinationGun(l logger.Logger, chainSelector uint64, env deployment.Environment, receiver common.Address, loki *wasp.LokiClient) *DestinationGun { seqNums := make(map[ChainSelectorPair]*atomic.Uint64) for _, cs := range env.AllChainSelectorsExcluding([]uint64{chainSelector}) { @@ -60,7 +61,7 @@ func (m *DestinationGun) Call(_ *wasp.Generator) *wasp.Response { waspGroup := fmt.Sprintf("%d-%s", m.chainSelector, "messageOnly") - state, err := ccipdeployment.LoadOnchainState(m.env) + state, err := ccipchangeset.LoadOnchainState(m.env) if err != nil { return &wasp.Response{Error: err.Error(), Group: waspGroup, Failed: true} } @@ -75,12 +76,7 @@ func (m *DestinationGun) Call(_ *wasp.Generator) *wasp.Response { dst: m.chainSelector, } m.seqNums[csPair].Add(1) - m.l.Info(). - Int32("RoundNum", requestedRound). - Uint64("Destination ChainSelector", m.chainSelector). - Uint64("Source ChainSelector", src). - Uint64("SequenceNumber", m.seqNums[csPair].Load()). - Msg("starting transmit") + m.l.Infow("Starting transmit with ", "RoundNum", requestedRound, "Destination ChainSelector", m.chainSelector, "Source ChainSelector", src, "SequenceNumber", m.seqNums[csPair].Load()) r := state.Chains[src].Router @@ -116,10 +112,10 @@ func (m *DestinationGun) Call(_ *wasp.Generator) *wasp.Response { return &wasp.Response{Failed: false, Group: waspGroup} } -// GetCycledClient will return a valid client from a random source chain +// MustSourceChain will return a chain selector to send a message from func (m *DestinationGun) MustSourceChain() (uint64, error) { - // TODO: check if this chain has sent a message recently, if so, switch to the next chain + // TODO: make this smarter by checking if this chain has sent a message recently, if so, switch to the next chain otherCS := m.env.AllChainSelectorsExcluding([]uint64{m.chainSelector}) if len(otherCS) == 0 { return 0, fmt.Errorf("no other chains to send from") @@ -133,7 +129,8 @@ func (m *DestinationGun) MustSourceChain() (uint64, error) { func (m *DestinationGun) GetMessage() (router.ClientEVM2AnyMessage, error) { rcv, err := utils.ABIEncode(`[{"type":"address"}]`, m.receiver) if err != nil { - m.l.Error().Err(err).Msg("Error encoding receiver address") + m.l.Error("Error encoding receiver address") + return router.ClientEVM2AnyMessage{}, err } return router.ClientEVM2AnyMessage{ diff --git a/integration-tests/load/ccip/helpers.go b/integration-tests/load/ccip/helpers.go index 0ef76126967..0df27431963 100644 --- a/integration-tests/load/ccip/helpers.go +++ b/integration-tests/load/ccip/helpers.go @@ -1,15 +1,17 @@ package ccip import ( + "context" "encoding/json" "fmt" - "github.com/ethereum/go-ethereum/common" - "github.com/rs/zerolog" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-testing-framework/wasp" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/environment/devenv" + "github.com/stretchr/testify/require" "io" "os" + "testing" "time" ) @@ -17,9 +19,12 @@ const ( transmitted = iota committed executed - LokiLoadLabel = "ccip_load_test" - ErrLokiClient = "failed to create Loki client for monitoring" - ErrLokiPush = "failed to push metrics to Loki" + LokiLoadLabel = "ccip_load_test" + ErrLokiClient = "failed to create Loki client for monitoring" + ErrLokiPush = "failed to push metrics to Loki" + abPath = "/Users/austin.wang/ccip-core/repos/chainlink/integration-tests/load/ccip/testfiles/ccip-v2-scripts-address-book.json" + nodeIdsPath = "/Users/austin.wang/ccip-core/repos/chainlink/integration-tests/load/ccip/testfiles/ccip-v2-scripts-node-details.json" + chainConfigPath = "/Users/austin.wang/ccip-core/repos/chainlink/integration-tests/load/ccip/testfiles/ccip-v2-scripts-chains-details.json" ) // todo: Have a different struct for commit/exec? @@ -30,36 +35,23 @@ type LokiMetric struct { SequenceNumber uint64 `json:"sequence_number"` } -func GetAddressFromTypeAndVersion(ab deployment.AddressBook, cs uint64, tv string) (common.Address, error) { - allAddr, err := ab.AddressesForChain(cs) - if err != nil { - return common.Address{}, err - } - for addr, tv := range allAddr { - if tv.Type == tv.Type && tv.Version == tv.Version { - return common.HexToAddress(addr), nil - } - } - - return common.Address{}, fmt.Errorf("address not found for chain selector %d and typeAndVersion %s", cs, tv) -} - -func SendMetricsToLoki(l zerolog.Logger, lc *wasp.LokiClient, updatedLabels map[string]string, metrics *LokiMetric) { +func SendMetricsToLoki(l logger.Logger, lc *wasp.LokiClient, updatedLabels map[string]string, metrics *LokiMetric) { if err := lc.HandleStruct(wasp.LabelsMapToModel(updatedLabels), time.Now(), metrics); err != nil { - l.Error().Err(err).Msg(ErrLokiPush) + l.Error(ErrLokiPush) } } func setLokiLabels(src, dst uint64) map[string]string { return map[string]string{ - "sourceSelector": fmt.Sprintf("%d", src), + "sourceEvmChainId": fmt.Sprintf("%d", src), + "destEvmChainId": fmt.Sprintf("%d", src), "destinationSelector": fmt.Sprintf("%d", dst), "testType": LokiLoadLabel, } } -func readFile(inputDir string, fileName string) []byte { - file, err := os.Open(fmt.Sprintf("%s/%s", inputDir, fileName)) +func readFile(filePath string) []byte { + file, err := os.Open(filePath) if err != nil { fmt.Println("Error opening file:", err) panic(err) @@ -75,42 +67,28 @@ func readFile(inputDir string, fileName string) []byte { return byteValue } -func ReadAddressBook(inputDir string) *deployment.AddressBookMap { - byteValue := readFile(inputDir, AddressBookFileName) - - var result map[uint64]map[string]deployment.TypeAndVersion +func readFromFile[T []string | *deployment.AddressBookMap | []devenv.ChainConfig](t *testing.T, inputDir string) T { + byteValue := readFile(inputDir) + var result T // Unmarshal the JSON into the map err := json.Unmarshal(byteValue, &result) - if err != nil { - fmt.Println("Error unmarshalling JSON:", err) - panic(err) - } + require.NoError(t, err) // Print the deserialized map fmt.Println(result) - return deployment.NewMemoryAddressBookFromMap(result) + return result } -func ReadNodesDetails(inputDir string) NodesDetails { - byteValue := readFile(inputDir, NodesDetailsFileName) +func CreateEnvironmentFromCribOutput(t *testing.T, lggr logger.Logger) (*deployment.Environment, error) { + ab := readFromFile[*deployment.AddressBookMap](t, abPath) + nodeIds := readFromFile[[]string](t, nodeIdsPath) + chainDetails := readFromFile[[]devenv.ChainConfig](t, chainConfigPath) - var result NodesDetails - - // Unmarshal the JSON into the map - err := json.Unmarshal(byteValue, &result) - if err != nil { - fmt.Println("Error unmarshalling JSON:", err) - panic(err) - } - - // Print the deserialized map - fmt.Println(result) - return result -} + // todo: make sure to call chainDetails.SetDeployerKey() for each chain + // where private keys should be stored in env vars or .toml -func NewDeployEnvironmentFromCribOutput(lggr logger.Logger, ab deployment.AddressBook, nodeIDs []string) (*deployment.Environment, error) { - chains, err := devenv.NewChains(lggr, output.Chains) + chains, err := devenv.NewChains(lggr, chainDetails) if err != nil { return nil, err } @@ -119,7 +97,9 @@ func NewDeployEnvironmentFromCribOutput(lggr logger.Logger, ab deployment.Addres lggr, ab, chains, - nodeIDs, - nil, // todo: populate the offchain client using output.DON + nodeIds, + nil, + func() context.Context { return context.Background() }, + deployment.XXXGenerateTestOCRSecrets(), ), nil }