From 1ea5e2f8cdc4cbf7a3b71b3cfb4c604766574317 Mon Sep 17 00:00:00 2001 From: 0xAustinWang Date: Fri, 10 Jan 2025 23:00:30 +0800 Subject: [PATCH] test changes --- ccip/config/evm/fallback.toml | 95 ------------------- deployment/ccip/changeset/cs_ccip_home.go | 6 +- deployment/environment/crib/ccip_deployer.go | 45 ++++----- deployment/environment/devenv/chain.go | 11 ++- integration-tests/load/ccip/ccip_test.go | 47 +++++++-- .../load/ccip/destination_gun.go | 91 +++++++++++++++--- integration-tests/load/ccip/helpers.go | 1 + integration-tests/testconfig/ccip/ccip.toml | 9 +- integration-tests/testconfig/ccip/load.go | 8 +- 9 files changed, 169 insertions(+), 144 deletions(-) delete mode 100644 ccip/config/evm/fallback.toml diff --git a/ccip/config/evm/fallback.toml b/ccip/config/evm/fallback.toml deleted file mode 100644 index c1f963a33ff..00000000000 --- a/ccip/config/evm/fallback.toml +++ /dev/null @@ -1,95 +0,0 @@ -AutoCreateKey = true -BlockBackfillDepth = 10 -BlockBackfillSkip = false -FinalityDepth = 50 -FinalityTagEnabled = false -LogBackfillBatchSize = 1000 -LogPollInterval = '15s' -LogKeepBlocksDepth = 100000 -# CCIP uses paging when removing logs to avoid pushing too much pressure on the database -LogPrunePageSize = 10000 -BackupLogPollerBlockDelay = 100 -MinContractPayment = '.00001 link' -MinIncomingConfirmations = 3 -NonceAutoSync = true -NoNewHeadsThreshold = '3m' -RPCDefaultBatchSize = 250 -RPCBlockQueryDelay = 1 -FinalizedBlockOffset = 0 -NoNewFinalizedHeadsThreshold = '0' -LogBroadcasterEnabled = true - -[Transactions] -ForwardersEnabled = false -MaxInFlight = 16 -MaxQueued = 250 -ReaperInterval = '1h' -ReaperThreshold = '168h' -ResendAfterThreshold = '1m' - -[Transactions.AutoPurge] -Enabled = false - -[BalanceMonitor] -Enabled = true - -[GasEstimator] -Mode = 'BlockHistory' -PriceDefault = '20 gwei' -PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' -PriceMin = '1 gwei' -LimitDefault = 8_000_000 -LimitMax = 8_000_000 -LimitMultiplier = '1' -LimitTransfer = 21_000 -BumpMin = '5 gwei' -BumpPercent = 20 -BumpThreshold = 3 -EIP1559DynamicFees = false -FeeCapDefault = '100 gwei' -TipCapDefault = '1' -TipCapMin = '1' -EstimateLimit = false - -[GasEstimator.BlockHistory] -BatchSize = 25 -BlockHistorySize = 8 -CheckInclusionBlocks = 12 -CheckInclusionPercentile = 90 -TransactionPercentile = 60 - -[GasEstimator.FeeHistory] -CacheTimeout = '10s' - -[HeadTracker] -HistoryDepth = 100 -MaxBufferSize = 3 -SamplingInterval = '1s' -FinalityTagBypass = true -MaxAllowedFinalityDepth = 10000 - -[NodePool] -PollFailureThreshold = 5 -PollInterval = '10s' -SelectionMode = 'HighestHead' -SyncThreshold = 5 -LeaseDuration = '0s' -NodeIsSyncingEnabled = false -FinalizedBlockPollInterval = '5s' -EnforceRepeatableRead = false -DeathDeclarationDelay = '10s' -NewHeadsPollInterval = '0s' - -[OCR] -ContractConfirmations = 4 -ContractTransmitterTransmitTimeout = '10s' -DatabaseTimeout = '10s' -DeltaCOverride = '168h' -DeltaCJitterOverride = '1h' -ObservationGracePeriod = '1s' - -[OCR2.Automation] -GasLimit = 5400000 - -[Workflow] -GasLimitDefault = 400_000 diff --git a/deployment/ccip/changeset/cs_ccip_home.go b/deployment/ccip/changeset/cs_ccip_home.go index 7d3327a31f2..a7ac1a63df2 100644 --- a/deployment/ccip/changeset/cs_ccip_home.go +++ b/deployment/ccip/changeset/cs_ccip_home.go @@ -1024,8 +1024,10 @@ func (c UpdateChainConfigConfig) Validate(e deployment.Environment) error { if !exists { return fmt.Errorf("home chain %d does not exist", c.HomeChainSelector) } - if err := commoncs.ValidateOwnership(e.GetContext(), c.MCMS != nil, e.Chains[c.HomeChainSelector].DeployerKey.From, homeChainState.Timelock.Address(), homeChainState.CCIPHome); err != nil { - return err + if c.MCMS != nil { + if err := commoncs.ValidateOwnership(e.GetContext(), c.MCMS != nil, e.Chains[c.HomeChainSelector].DeployerKey.From, homeChainState.Timelock.Address(), homeChainState.CCIPHome); err != nil { + return err + } } for _, remove := range c.RemoteChainRemoves { if err := deployment.IsValidChainSelector(remove); err != nil { diff --git a/deployment/environment/crib/ccip_deployer.go b/deployment/environment/crib/ccip_deployer.go index 5c6863f801c..10799e67f60 100644 --- a/deployment/environment/crib/ccip_deployer.go +++ b/deployment/environment/crib/ccip_deployer.go @@ -152,19 +152,18 @@ func DeployCCIPAndAddLanes(ctx context.Context, lggr logger.Logger, envConfig de return DeployCCIPOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } // Add all lanes - for from := range e.Chains { - for to := range e.Chains { - if from != to { - stateChain1 := state.Chains[from] + for src := range e.Chains { + for dst := range e.Chains { + if src != dst { + stateChain1 := state.Chains[src] newEnv, err := commonchangeset.ApplyChangesets(nil, *e, nil, []commonchangeset.ChangesetApplication{ { Changeset: commonchangeset.WrapChangeSet(changeset.UpdateOnRampsDests), Config: changeset.UpdateOnRampDestsConfig{ UpdatesByChain: map[uint64]map[uint64]changeset.OnRampDestinationUpdate{ - from: { - to: { + src: { + dst: { IsEnabled: true, - TestRouter: false, AllowListEnabled: false, }, }, @@ -175,13 +174,13 @@ func DeployCCIPAndAddLanes(ctx context.Context, lggr logger.Logger, envConfig de Changeset: commonchangeset.WrapChangeSet(changeset.UpdateFeeQuoterPricesCS), Config: changeset.UpdateFeeQuoterPricesConfig{ PricesByChain: map[uint64]changeset.FeeQuoterPriceUpdatePerSource{ - from: { + src: { TokenPrices: map[common.Address]*big.Int{ stateChain1.LinkToken.Address(): changeset.DefaultLinkPrice, stateChain1.Weth9.Address(): changeset.DefaultWethPrice, }, GasPrices: map[uint64]*big.Int{ - to: changeset.DefaultGasPrice, + dst: changeset.DefaultGasPrice, }, }, }, @@ -191,8 +190,8 @@ func DeployCCIPAndAddLanes(ctx context.Context, lggr logger.Logger, envConfig de Changeset: commonchangeset.WrapChangeSet(changeset.UpdateFeeQuoterDests), Config: changeset.UpdateFeeQuoterDestsConfig{ UpdatesByChain: map[uint64]map[uint64]fee_quoter.FeeQuoterDestChainConfig{ - from: { - to: changeset.DefaultFeeQuoterDestChainConfig(), + src: { + dst: changeset.DefaultFeeQuoterDestChainConfig(), }, }, }, @@ -201,10 +200,9 @@ func DeployCCIPAndAddLanes(ctx context.Context, lggr logger.Logger, envConfig de Changeset: commonchangeset.WrapChangeSet(changeset.UpdateOffRampSources), Config: changeset.UpdateOffRampSourcesConfig{ UpdatesByChain: map[uint64]map[uint64]changeset.OffRampSourceUpdate{ - to: { - from: { - IsEnabled: true, - TestRouter: false, + dst: { + src: { + IsEnabled: true, }, }, }, @@ -213,18 +211,21 @@ func DeployCCIPAndAddLanes(ctx context.Context, lggr logger.Logger, envConfig de { Changeset: commonchangeset.WrapChangeSet(changeset.UpdateRouterRamps), Config: changeset.UpdateRouterRampsConfig{ - TestRouter: false, UpdatesByChain: map[uint64]changeset.RouterUpdates{ - // onRamp update on source chain - from: { + src: { + OffRampUpdates: map[uint64]bool{ + dst: true, + }, OnRampUpdates: map[uint64]bool{ - to: true, + dst: true, }, }, - // off - from: { + dst: { OffRampUpdates: map[uint64]bool{ - to: true, + src: true, + }, + OnRampUpdates: map[uint64]bool{ + src: true, }, }, }, diff --git a/deployment/environment/devenv/chain.go b/deployment/environment/devenv/chain.go index 19d58882e03..c53cb82a7ed 100644 --- a/deployment/environment/devenv/chain.go +++ b/deployment/environment/devenv/chain.go @@ -22,13 +22,18 @@ const ( EVMChainType = "EVM" ) +type CribRPCs struct { + Internal string + External string +} + // ChainConfig holds the configuration for a with a deployer key which can be used to send transactions to the chain. type ChainConfig struct { ChainID uint64 // chain id as per EIP-155, mainly applicable for EVM chains ChainName string // name of the chain populated from chainselector repo ChainType string // should denote the chain family. Acceptable values are EVM, COSMOS, SOLANA, STARKNET, APTOS etc - WSRPCs []string // websocket rpcs to connect to the chain - HTTPRPCs []string // http rpcs to connect to the chain + WSRPCs []CribRPCs // websocket rpcs to connect to the chain + HTTPRPCs []CribRPCs // http rpcs to connect to the chain DeployerKey *bind.TransactOpts // key to deploy and configure contracts on the chain Users []*bind.TransactOpts // map of addresses to their transact opts to interact with the chain as users } @@ -97,7 +102,7 @@ func NewChains(logger logger.Logger, configs []ChainConfig) (map[uint64]deployme // TODO : better client handling var ec *ethclient.Client for _, rpc := range chainCfg.WSRPCs { - ec, err = ethclient.Dial(rpc) + ec, err = ethclient.Dial(rpc.External) if err != nil { logger.Warnf("failed to dial ws rpc %s", rpc) continue diff --git a/integration-tests/load/ccip/ccip_test.go b/integration-tests/load/ccip/ccip_test.go index 1ee1049b502..8148df444b0 100644 --- a/integration-tests/load/ccip/ccip_test.go +++ b/integration-tests/load/ccip/ccip_test.go @@ -46,6 +46,17 @@ func TestCCIPLoad_RPS(t *testing.T) { config, err := tc.GetConfig([]string{"Load"}, tc.CCIP) require.NoError(t, err) lggr.Infof("loaded ccip test config: %+v", config.CCIP.Load) + userOverrides := config.CCIP.Load + + timeout, err := time.ParseDuration(*userOverrides.TestTimeout) + if err != nil { + require.NoError(t, err) + } + t.Cleanup(func() { + time.AfterFunc(timeout, func() { + t.Fatalf("Test passed timeout after %v", timeout) + }) + }) cribEnv := crib.NewDevspaceEnvFromStateDir(CRIB_DIRECTORY) @@ -61,7 +72,7 @@ func TestCCIPLoad_RPS(t *testing.T) { require.NoError(t, err) // Parse all events from the simulated chains, send to Loki - loki, err := wasp.NewLokiClient(wasp.NewLokiConfig(config.CCIP.Load.LokiEndpoint, nil, nil, nil)) + loki, err := wasp.NewLokiClient(wasp.NewLokiConfig(userOverrides.LokiEndpoint, nil, nil, nil)) require.NoError(t, err) defer loki.StopNow() @@ -75,8 +86,16 @@ func TestCCIPLoad_RPS(t *testing.T) { block := latesthdr.Number.Uint64() startBlocks[selector] = &block - gunMap[selector] = NewDestinationGun(env.Logger, selector, *env, state.Chains[selector].Receiver.Address(), loki) - + // Only create a destination gun if we have decided to send traffic to this chain + for _, cs := range *userOverrides.EnabledDestionationChains { + if cs == selector { + gunMap[selector], err = NewDestinationGun(env.Logger, selector, *env, state.Chains[selector].Receiver.Address(), userOverrides, loki) + if err != nil { + lggr.Errorw("Failed to initialize DestinationGun for", "chainSelector", chain, "error", err) + t.Fatal(err) + } + } + } } for _, gun := range gunMap { @@ -85,7 +104,7 @@ func TestCCIPLoad_RPS(t *testing.T) { GenName: "ccipLoad", LoadType: wasp.RPS, CallTimeout: 5 * time.Second, - Schedule: wasp.Plain(1, 5*time.Second), + Schedule: wasp.Plain(1, time.Duration(*userOverrides.SecondsPerRequestPerDestination)*time.Second), // will need to be divided by number of chains // this schedule is per generator // in this example, it would be 1 request per 10seconds per generator (dest chain) @@ -97,20 +116,34 @@ func TestCCIPLoad_RPS(t *testing.T) { })) } - _, err = p.Run(true) + // find get fee revert csPair := ChainSelectorPair{ src: 12922642891491394802, dst: 3379446385462418246, } + res, err := state.Chains[csPair.src].Router.IsChainSupported(nil, csPair.dst) + lggr.Infow("IsChainSupported", "res", res, "err", err) + + destChainConfig, err := state.Chains[csPair.src].FeeQuoter.GetDestChainConfig(nil, csPair.dst) + lggr.Infow("GetDestChainConfig", "destChainConfig", destChainConfig, "err", err) + + // find the getFee revert + _, err = p.Run(true) + //csPair := ChainSelectorPair{ + // src: 12922642891491394802, + // dst: 3379446385462418246, + //} src, dst := env.Chains[csPair.src], env.Chains[csPair.dst] startblk := uint64(11654) seqNum := gunMap[csPair.dst].seqNums[csPair].End.Load() _, err = ccipchangeset.ConfirmCommitWithExpectedSeqNumRange(t, src, dst, state.Chains[3379446385462418246].OffRamp, &startblk, cciptypes.SeqNumRange{ - cciptypes.SeqNum(seqNum), - cciptypes.SeqNum(seqNum), + cciptypes.SeqNum(seqNum - 1), + cciptypes.SeqNum(seqNum - 1), }, false) + // todo: create channels that watch for these events beforehand using WatchExecutionStateChanged and WatchCommitReportAccepted + // rather than waiting for the generator to finish lokiLabels := map[string]string{} for chainSelector, startBlock := range startBlocks { wg.Add(1) diff --git a/integration-tests/load/ccip/destination_gun.go b/integration-tests/load/ccip/destination_gun.go index 4f94ef2b071..06b91a4d727 100644 --- a/integration-tests/load/ccip/destination_gun.go +++ b/integration-tests/load/ccip/destination_gun.go @@ -9,9 +9,12 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/wasp" "github.com/smartcontractkit/chainlink/deployment" ccipchangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/integration-tests/testconfig/ccip" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "go.uber.org/atomic" + "math/big" + "math/rand" "time" ) @@ -32,10 +35,11 @@ type DestinationGun struct { roundNum *atomic.Int32 chainSelector uint64 receiver common.Address + testConfig *ccip.LoadConfig loki *wasp.LokiClient } -func NewDestinationGun(l logger.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, overrides *ccip.LoadConfig, loki *wasp.LokiClient) (*DestinationGun, error) { seqNums := make(map[ChainSelectorPair]SeqNumRange) for _, cs := range env.AllChainSelectorsExcluding([]uint64{chainSelector}) { @@ -48,15 +52,38 @@ func NewDestinationGun(l logger.Logger, chainSelector uint64, env deployment.Env End: atomic.NewUint64(0), } } - return &DestinationGun{ + dg := DestinationGun{ l: l, env: env, seqNums: seqNums, roundNum: &atomic.Int32{}, chainSelector: chainSelector, receiver: receiver, + testConfig: overrides, loki: loki, } + + err := dg.Validate() + if err != nil { + return nil, err + } + + return &dg, nil +} + +func (m *DestinationGun) Validate() error { + if len(*m.testConfig.MessageTypeWeights) != 3 { + return fmt.Errorf( + "message type must have 3 weights corresponding to message only, token only, token with message") + } + sum := 0 + for _, weight := range *m.testConfig.MessageTypeWeights { + sum += weight + } + if sum != 100 { + return fmt.Errorf("message type weights must sum to 100") + } + return nil } func (m *DestinationGun) Call(_ *wasp.Generator) *wasp.Response { @@ -84,7 +111,11 @@ func (m *DestinationGun) Call(_ *wasp.Generator) *wasp.Response { src: src, dst: m.chainSelector, } - m.l.Infow("Starting transmit with ", "RoundNum", requestedRound, "Destination ChainSelector", m.chainSelector, "Source ChainSelector", src, "SequenceNumber", m.seqNums[csPair].End.Load()) + m.l.Infow("Starting transmit with ", + "RoundNum", requestedRound, + "Source ChainSelector", src, + "Destination ChainSelector", m.chainSelector, + "SequenceNumber", m.seqNums[csPair].End.Load()) r := state.Chains[src].Router @@ -96,7 +127,7 @@ func (m *DestinationGun) Call(_ *wasp.Generator) *wasp.Response { fee, err := r.GetFee( &bind.CallOpts{Context: context.Background()}, m.chainSelector, msg) if err != nil { - m.l.Errorw("could not get fee ", "dstChainSelector", m.chainSelector, "msg", msg, "fee", fee) + m.l.Errorw("could not get fee ", "dstChainSelector", m.chainSelector, "msg", msg, "fee", fee, "err", err) return &wasp.Response{Error: err.Error(), Group: waspGroup, Failed: true} } m.l.Debugw("setting fee for ", "srcChain", src, "dstChain", m.chainSelector, "fee", fee, "msg", msg) @@ -152,6 +183,7 @@ func (m *DestinationGun) Call(_ *wasp.Generator) *wasp.Response { func (m *DestinationGun) MustSourceChain() (uint64, error) { // TODO: make this smarter by checking if this chain has sent a message recently, if so, switch to the next chain + // Currently performing a round robin otherCS := m.env.AllChainSelectorsExcluding([]uint64{m.chainSelector}) if len(otherCS) == 0 { return 0, fmt.Errorf("no other chains to send from") @@ -161,7 +193,6 @@ func (m *DestinationGun) MustSourceChain() (uint64, error) { } // GetMessage will return the message to be sent while considering expected load of different messages -// TODO: implement randomness and different types of messages func (m *DestinationGun) GetMessage() (router.ClientEVM2AnyMessage, error) { rcv, err := utils.ABIEncode(`[{"type":"address"}]`, m.receiver) if err != nil { @@ -169,13 +200,49 @@ func (m *DestinationGun) GetMessage() (router.ClientEVM2AnyMessage, error) { return router.ClientEVM2AnyMessage{}, err } - return router.ClientEVM2AnyMessage{ - Receiver: rcv, - Data: common.Hex2Bytes("hello world"), - TokenAmounts: nil, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, - }, nil + messages := []router.ClientEVM2AnyMessage{ + { + Receiver: rcv, + Data: common.Hex2Bytes("message"), + TokenAmounts: nil, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + }, + { + Receiver: rcv, + TokenAmounts: []router.ClientEVMTokenAmount{ + { + Token: common.HexToAddress("0x0"), + Amount: big.NewInt(100), + }, + }, + Data: common.Hex2Bytes("hello world"), + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + }, + { + Receiver: rcv, + Data: common.Hex2Bytes("message with token"), + TokenAmounts: []router.ClientEVMTokenAmount{ + { + Token: common.HexToAddress("0x0"), + Amount: big.NewInt(100), + }, + }, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + }, + } + // Select a random message + randomValue := rand.Intn(100) + switch { + case randomValue < (*m.testConfig.MessageTypeWeights)[0]: + return messages[0], nil + case randomValue < (*m.testConfig.MessageTypeWeights)[0]+(*m.testConfig.MessageTypeWeights)[1]: + return messages[1], nil + default: + return messages[2], nil + } } func (m *DestinationGun) GetSequenceNumberRange(csPair ChainSelectorPair) (uint64, uint64, error) { diff --git a/integration-tests/load/ccip/helpers.go b/integration-tests/load/ccip/helpers.go index faeede61e7a..8634f49edbf 100644 --- a/integration-tests/load/ccip/helpers.go +++ b/integration-tests/load/ccip/helpers.go @@ -106,6 +106,7 @@ func CreateEnvironmentFromCribOutput(t *testing.T, lggr logger.Logger) (*deploym lggr, ab, chains, + nil, nodeIds, nil, func() context.Context { return context.Background() }, diff --git a/integration-tests/testconfig/ccip/ccip.toml b/integration-tests/testconfig/ccip/ccip.toml index 1e0afee34de..d9eaeced856 100644 --- a/integration-tests/testconfig/ccip/ccip.toml +++ b/integration-tests/testconfig/ccip/ccip.toml @@ -241,7 +241,14 @@ addresses_to_fund = [ # Seth specific configuration, no need for generating ephemeral addresses for ccip-tests. ephemeral_addresses_number = 0 - [Load.CCIP.Load] +# replace this with the loki endpoint of the crib stack LokiEndpoint = "http://loki.localhost/loki/api/v1/push" NoOfNodes = 4 +TestTimeout = "1m" +# corresponds to [data only, token only, message with data] +MessageTypeWeights = [100,0,0] +# each destination chain will have 1 request per 5 seconds +SecondsPerRequestPerDestination = 5 +# destination chain selectors to send messages to +EnabledDestionationChains = [3379446385462418246] \ No newline at end of file diff --git a/integration-tests/testconfig/ccip/load.go b/integration-tests/testconfig/ccip/load.go index 5b226d6e7eb..57bbc5e37e9 100644 --- a/integration-tests/testconfig/ccip/load.go +++ b/integration-tests/testconfig/ccip/load.go @@ -1,6 +1,10 @@ package ccip type LoadConfig struct { - NoOfNodes *int - LokiEndpoint *string + TestTimeout *string + NoOfNodes *int + LokiEndpoint *string + MessageTypeWeights *[]int + SecondsPerRequestPerDestination *int + EnabledDestionationChains *[]uint64 }