Skip to content

Commit

Permalink
CCIP-2645: Introducing leader lane and setting PriceReportingDisabled…
Browse files Browse the repository at this point in the history
… in Test (#1120)

## Motivation
This [PR](#1071) introduces
leader lane feature. Setting leader lane will avoid duplicate gas price
fetch for the same destination from different source chain. Here in this
PR, the expectation is to add a test where leader lane is setup and
verify every commitstore report transaction hash emitted two
`UsdPerUnitGasUpdated` events.

## Solution
Introduce config variable to enable leader lane setup and based on
network pair, automatically define set of lanes as leader and non-leader
lanes, track the tx hash from the event `UsdPerUnitGasUpdated` and
ensure transaction count matches to the number of sources chain selector
expected.
  • Loading branch information
b-gopalswami authored Aug 5, 2024
1 parent 49cfead commit a9ba0a9
Show file tree
Hide file tree
Showing 12 changed files with 209 additions and 26 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,13 @@ jobs:
os: ubuntu-latest
file: ccip
run: -run ^TestSmokeCCIPOffRampAggRateLimit$
- name: ccip-smoke-leader-lane
nodes: 15
dir: ccip-tests/smoke
os: ubuntu-latest
file: ccip
run: -run ^TestSmokeCCIPForBidirectionalLane$
config_path: ./integration-tests/ccip-tests/testconfig/tomls/leader-lane.toml
- name: runlog
id: runlog
nodes: 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,16 @@ func NewCommitOffchainConfig(
ExecGasPriceDeviationPPB uint32,
TokenPriceHeartBeat config.Duration,
TokenPriceDeviationPPB uint32,
InflightCacheExpiry config.Duration) CommitOffchainConfig {
InflightCacheExpiry config.Duration,
priceReportingDisabled bool) CommitOffchainConfig {
return CommitOffchainConfig{v1_2_0.JSONCommitOffchainConfig{
GasPriceHeartBeat: GasPriceHeartBeat,
DAGasPriceDeviationPPB: DAGasPriceDeviationPPB,
ExecGasPriceDeviationPPB: ExecGasPriceDeviationPPB,
TokenPriceHeartBeat: TokenPriceHeartBeat,
TokenPriceDeviationPPB: TokenPriceDeviationPPB,
InflightCacheExpiry: InflightCacheExpiry,
PriceReportingDisabled: priceReportingDisabled,
}}
}

Expand Down
1 change: 1 addition & 0 deletions core/services/ocr2/plugins/ccip/testhelpers/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func (c *CCIPContracts) createCommitOffchainConfig(t *testing.T, feeUpdateHearBe
*config.MustNewDuration(feeUpdateHearBeat),
1,
*config.MustNewDuration(inflightCacheExpiry),
false,
).Encode()
require.NoError(t, err)
return config
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,16 @@ func NewCommitOffchainConfig(
ExecGasPriceDeviationPPB uint32,
TokenPriceHeartBeat config.Duration,
TokenPriceDeviationPPB uint32,
InflightCacheExpiry config.Duration) CommitOffchainConfig {
InflightCacheExpiry config.Duration,
priceReportingDisabled bool) CommitOffchainConfig {
return CommitOffchainConfig{v1_2_0.JSONCommitOffchainConfig{
GasPriceHeartBeat: GasPriceHeartBeat,
DAGasPriceDeviationPPB: DAGasPriceDeviationPPB,
ExecGasPriceDeviationPPB: ExecGasPriceDeviationPPB,
TokenPriceHeartBeat: TokenPriceHeartBeat,
TokenPriceDeviationPPB: TokenPriceDeviationPPB,
InflightCacheExpiry: InflightCacheExpiry,
PriceReportingDisabled: priceReportingDisabled,
}}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ func (c *CCIPContracts) createCommitOffchainConfig(t *testing.T, feeUpdateHearBe
*config.MustNewDuration(feeUpdateHearBeat),
1,
*config.MustNewDuration(inflightCacheExpiry),
false,
).Encode()
require.NoError(t, err)
return config
Expand Down
61 changes: 38 additions & 23 deletions integration-tests/ccip-tests/actions/ccip_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver"
"github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/reorg"
"github.com/smartcontractkit/chainlink-testing-framework/networks"

"github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/contracts"
"github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/contracts/laneconfig"
"github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testconfig"
Expand Down Expand Up @@ -185,6 +184,7 @@ type CCIPCommon struct {
tokenPriceUpdateWatcher map[common.Address]*big.Int // key - token; value - timestamp of update
gasUpdateWatcherMu *sync.Mutex
gasUpdateWatcher map[uint64]*big.Int // key - destchain id; value - timestamp of update
GasUpdateEvents []contracts.GasUpdateEvent
}

// FreeUpUnusedSpace sets nil to various elements of ccipModule which are only used
Expand Down Expand Up @@ -524,6 +524,9 @@ func (ccipModule *CCIPCommon) WaitForPriceUpdates(
}
}

// WatchForPriceUpdates helps to ensure the price updates are happening in price registry by subscribing to a couple
// of price update events and add the event details to watchers. It subscribes to 'UsdPerUnitGasUpdated'
// and 'UsdPerTokenUpdated' event.
func (ccipModule *CCIPCommon) WatchForPriceUpdates(ctx context.Context, lggr *zerolog.Logger) error {
gasUpdateEventLatest := make(chan *price_registry.PriceRegistryUsdPerUnitGasUpdated)
tokenUpdateEvent := make(chan *price_registry.PriceRegistryUsdPerTokenUpdated)
Expand All @@ -549,20 +552,28 @@ func (ccipModule *CCIPCommon) WatchForPriceUpdates(ctx context.Context, lggr *ze
if tokenUpdateSub == nil {
return fmt.Errorf("no event subscription found")
}
processEvent := func(timestamp *big.Int, destChainSelector uint64) error {
processEvent := func(value, timestamp *big.Int, destChainSelector uint64, raw types.Log) error {
destChain, err := chainselectors.ChainIdFromSelector(destChainSelector)
if err != nil {
return err
}
ccipModule.gasUpdateWatcherMu.Lock()
ccipModule.gasUpdateWatcher[destChain] = timestamp

ccipModule.GasUpdateEvents = append(ccipModule.GasUpdateEvents, contracts.GasUpdateEvent{
Sender: raw.Address.Hex(),
Tx: raw.TxHash.Hex(),
Value: value,
DestChain: destChain,
Source: ccipModule.ChainClient.GetNetworkName(),
})
ccipModule.gasUpdateWatcherMu.Unlock()
lggr.Info().
Uint64("chainSelector", destChainSelector).
Str("source_chain", ccipModule.ChainClient.GetNetworkName()).
Uint64("dest_chain", destChain).
Str("price_registry", ccipModule.PriceRegistry.Address()).
Msgf("UsdPerUnitGasUpdated event received for dest chain %d source chain %s",
Str("tx hash", raw.TxHash.Hex()).
Msgf("UsdPerUnitGasUpdated event received for dest chain: %d, source chain: %s",
destChain, ccipModule.ChainClient.GetNetworkName())
return nil
}
Expand All @@ -572,13 +583,14 @@ func (ccipModule *CCIPCommon) WatchForPriceUpdates(ctx context.Context, lggr *ze
tokenUpdateSub.Unsubscribe()
ccipModule.gasUpdateWatcher = nil
ccipModule.gasUpdateWatcherMu = nil
ccipModule.GasUpdateEvents = nil
ccipModule.tokenPriceUpdateWatcher = nil
ccipModule.tokenPriceUpdateWatcherMu = nil
}()
for {
select {
case e := <-gasUpdateEventLatest:
err := processEvent(e.Timestamp, e.DestChain)
err := processEvent(e.Value, e.Timestamp, e.DestChain, e.Raw)
if err != nil {
continue
}
Expand Down Expand Up @@ -2623,23 +2635,24 @@ func CCIPRequestFromTxHash(txHash common.Hash, chainClient blockchain.EVMClient)
}

type CCIPLane struct {
Test *testing.T
Logger *zerolog.Logger
SourceNetworkName string
DestNetworkName string
SourceChain blockchain.EVMClient
DestChain blockchain.EVMClient
Source *SourceCCIPModule
Dest *DestCCIPModule
NumberOfReq int
Reports *testreporters.CCIPLaneStats
Balance *BalanceSheet
SentReqs map[common.Hash][]CCIPRequest
TotalFee *big.Int // total fee for all the requests. Used for balance validation.
ValidationTimeout time.Duration
Context context.Context
SrcNetworkLaneCfg *laneconfig.LaneConfig
DstNetworkLaneCfg *laneconfig.LaneConfig
Test *testing.T
Logger *zerolog.Logger
SourceNetworkName string
DestNetworkName string
SourceChain blockchain.EVMClient
DestChain blockchain.EVMClient
Source *SourceCCIPModule
Dest *DestCCIPModule
NumberOfReq int
Reports *testreporters.CCIPLaneStats
Balance *BalanceSheet
SentReqs map[common.Hash][]CCIPRequest
TotalFee *big.Int // total fee for all the requests. Used for balance validation.
ValidationTimeout time.Duration
Context context.Context
SrcNetworkLaneCfg *laneconfig.LaneConfig
DstNetworkLaneCfg *laneconfig.LaneConfig
PriceReportingDisabled bool
}

func (lane *CCIPLane) TokenPricesConfig() (string, error) {
Expand Down Expand Up @@ -3645,7 +3658,7 @@ func (lane *CCIPLane) DeployNewCCIPLane(

jobParams.P2PV2Bootstrappers = []string{p2pBootstrappersCommit.P2PV2Bootstrapper()}

err = SetOCR2Config(lane.Context, lane.Logger, *testConf, commitNodes, execNodes, *lane.Dest)
err = SetOCR2Config(lane.Context, lane.Logger, *testConf, commitNodes, execNodes, *lane.Dest, lane.PriceReportingDisabled)
if err != nil {
return fmt.Errorf("failed to set ocr2 config: %w", err)
}
Expand Down Expand Up @@ -3683,6 +3696,7 @@ func SetOCR2Config(
commitNodes,
execNodes []*client.CLNodesWithKeys,
destCCIP DestCCIPModule,
priceReportingDisabled bool,
) error {
inflightExpiryExec := commonconfig.MustNewDuration(InflightExpiryExec)
inflightExpiryCommit := commonconfig.MustNewDuration(InflightExpiryCommit)
Expand Down Expand Up @@ -3719,6 +3733,7 @@ func SetOCR2Config(
*commonconfig.MustNewDuration(5 * time.Second),
1e6,
*inflightExpiryCommit,
priceReportingDisabled,
)
if err != nil {
return fmt.Errorf("failed to create commit offchain config: %w", err)
Expand Down
5 changes: 4 additions & 1 deletion integration-tests/ccip-tests/contracts/contract_deployer.go
Original file line number Diff line number Diff line change
Expand Up @@ -1399,7 +1399,8 @@ func NewCommitOffchainConfig(
ExecGasPriceDeviationPPB uint32,
TokenPriceHeartBeat config.Duration,
TokenPriceDeviationPPB uint32,
InflightCacheExpiry config.Duration) (ccipconfig.OffchainConfig, error) {
InflightCacheExpiry config.Duration,
priceReportingDisabled bool) (ccipconfig.OffchainConfig, error) {
switch VersionMap[CommitStoreContract] {
case Latest:
return testhelpers.NewCommitOffchainConfig(
Expand All @@ -1409,6 +1410,7 @@ func NewCommitOffchainConfig(
TokenPriceHeartBeat,
TokenPriceDeviationPPB,
InflightCacheExpiry,
priceReportingDisabled,
), nil
case V1_2_0:
return testhelpers_1_4_0.NewCommitOffchainConfig(
Expand All @@ -1418,6 +1420,7 @@ func NewCommitOffchainConfig(
TokenPriceHeartBeat,
TokenPriceDeviationPPB,
InflightCacheExpiry,
priceReportingDisabled,
), nil
default:
return nil, fmt.Errorf("version not supported: %s", VersionMap[CommitStoreContract])
Expand Down
9 changes: 9 additions & 0 deletions integration-tests/ccip-tests/contracts/contract_models.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,15 @@ type Version struct {
semver.Version
}

// GasUpdateEvent holds the event details of Gas price update
type GasUpdateEvent struct {
Sender string
Tx string
Value *big.Int
DestChain uint64
Source string
}

// MustVersion creates a new Version object from a semver string and panics if it fails
func MustVersion(version string) Version {
v := semver.MustParse(version)
Expand Down
3 changes: 3 additions & 0 deletions integration-tests/ccip-tests/testconfig/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,9 @@ base_url = "https://grafana..../"
dashboard_url = "/d/6vjVx-1V8/ccip-long-running-tests"
```

### CCIP.Env.Lane.LeaderLaneEnabled
Specifies whether to enable the leader lane feature. This setting is only applicable for new deployments.

## CCIP.Groups
Specifies the test config specific to each test type. Available test types are:
- **CCIP.Groups.load**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ CCIPOwnerTokens = false # if true, the test will use deploy the tokens by the CC
# ['SIMULATED_1', 'SIMULATED_2'], ['SIMULATED_1', 'SIMULATED_3'], ['SIMULATED_2', 'SIMULATED_3']
#MaxNoOfLanes = <no_of_lanes> # maximum number of lanes to be added in the test; mainly used for scalability tests


[CCIP.Groups.load]
# uncomment the following with specific values of lane combinations to be tested, if you want to run your tests to run only on these specific network pairs
# if specific network pairs are not mentioned, then all the network pairs will be tested based on values in CCIP.Env.NetworkPairs and CCIP.Groups.<test_type>.NoOfNetworks
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[CCIP]
[CCIP.Groups.smoke]
NoOfNetworks = 4
NoOfRoutersPerPair = 2
Loading

0 comments on commit a9ba0a9

Please sign in to comment.