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 capability AddChain/AddLane workflow tests #1342

Closed
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
2 changes: 1 addition & 1 deletion core/scripts/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ require (
github.com/sethvargo/go-retry v0.2.4 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/shirou/gopsutil/v3 v3.24.3 // indirect
github.com/smartcontractkit/chainlink-ccip v0.0.0-20240816163757-48726fd8165f // indirect
github.com/smartcontractkit/chainlink-ccip v0.0.0-20240820142424-1b2d9ea02c35 // indirect
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 // indirect
github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240718160222-2dc0c8136bfa // indirect
github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827 // indirect
Expand Down
4 changes: 2 additions & 2 deletions core/scripts/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1070,8 +1070,8 @@ github.com/smartcontractkit/chain-selectors v1.0.21 h1:KCR9SA7PhOexaBzFieHoLv1Wo
github.com/smartcontractkit/chain-selectors v1.0.21/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE=
github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8=
github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM=
github.com/smartcontractkit/chainlink-ccip v0.0.0-20240816163757-48726fd8165f h1:lQZBOjeYFpCdk0mGQUhbrJipd00tu49xK4zSijC/9Co=
github.com/smartcontractkit/chainlink-ccip v0.0.0-20240816163757-48726fd8165f/go.mod h1:/ZWraCBaDDgaIN1prixYcbVvIk/6HeED9+8zbWQ+TMo=
github.com/smartcontractkit/chainlink-ccip v0.0.0-20240820142424-1b2d9ea02c35 h1:35SN1dx03/J0xac0YKtJH9CyqQEsMqap9aBMpu+TQoM=
github.com/smartcontractkit/chainlink-ccip v0.0.0-20240820142424-1b2d9ea02c35/go.mod h1:xoO0vYi0LNn8QK23fvMVNvyIOgaLVTFgi5RprDsxK8M=
github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 h1:pTf4xdcmiWBqWZ6rTy2RMTDBzhHk89VC1pM7jXKQztI=
github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0=
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ require (
github.com/shopspring/decimal v1.4.0
github.com/smartcontractkit/chain-selectors v1.0.21
github.com/smartcontractkit/chainlink-automation v1.0.4
github.com/smartcontractkit/chainlink-ccip v0.0.0-20240816163757-48726fd8165f
github.com/smartcontractkit/chainlink-ccip v0.0.0-20240820142424-1b2d9ea02c35
github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45
github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240718160222-2dc0c8136bfa
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1027,8 +1027,8 @@ github.com/smartcontractkit/chain-selectors v1.0.21 h1:KCR9SA7PhOexaBzFieHoLv1Wo
github.com/smartcontractkit/chain-selectors v1.0.21/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE=
github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8=
github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM=
github.com/smartcontractkit/chainlink-ccip v0.0.0-20240816163757-48726fd8165f h1:lQZBOjeYFpCdk0mGQUhbrJipd00tu49xK4zSijC/9Co=
github.com/smartcontractkit/chainlink-ccip v0.0.0-20240816163757-48726fd8165f/go.mod h1:/ZWraCBaDDgaIN1prixYcbVvIk/6HeED9+8zbWQ+TMo=
github.com/smartcontractkit/chainlink-ccip v0.0.0-20240820142424-1b2d9ea02c35 h1:35SN1dx03/J0xac0YKtJH9CyqQEsMqap9aBMpu+TQoM=
github.com/smartcontractkit/chainlink-ccip v0.0.0-20240820142424-1b2d9ea02c35/go.mod h1:xoO0vYi0LNn8QK23fvMVNvyIOgaLVTFgi5RprDsxK8M=
github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 h1:pTf4xdcmiWBqWZ6rTy2RMTDBzhHk89VC1pM7jXKQztI=
github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0=
Expand Down
Empty file.
216 changes: 216 additions & 0 deletions integration-tests/deployment/ccip/add_chain.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
package ccipdeployment

import (
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
chainsel "github.com/smartcontractkit/chain-selectors"

"github.com/smartcontractkit/chainlink/integration-tests/deployment"
"github.com/smartcontractkit/chainlink/integration-tests/deployment/executable"
"github.com/smartcontractkit/chainlink/integration-tests/deployment/managed"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry"

"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry"
)

// AddChain deploys chain contracts for a new chain
// and generates 3 proposals to connect that new chain to all existing chains.
// We testing in between each proposal.
func NewChainInbound(
e deployment.Environment,
ab deployment.AddressBook,
homeChainSel uint64,
newChainSel uint64,
sources []uint64,
) ([]managed.MCMSWithTimelockProposal, deployment.AddressBook, error) {
// 1. Deploy contracts to new chain and wire them.
newAddresses, err := DeployChainContracts(e, e.Chains[newChainSel], deployment.NewMemoryAddressBook())
if err != nil {
return nil, ab, err
}
if err := ab.Merge(newAddresses); err != nil {
return nil, ab, err
}
state, err := LoadOnchainState(e, ab)
if err != nil {
return nil, ab, err
}

// 2. Generate proposal which enables new destination (from test router) on all source chains.
var batches []managed.DetailedBatchChainOperation
metaDataPerChain := make(map[string]managed.MCMSWithTimelockChainMetadata)
for _, source := range sources {
chain, _ := chainsel.ChainBySelector(source)
enableOnRampDest, err := state.Chains[source].OnRamp.ApplyDestChainConfigUpdates(SimTransactOpts(), []onramp.OnRampDestChainConfigArgs{
{
DestChainSelector: newChainSel,
Router: state.Chains[source].TestRouter.Address(),
},
})
if err != nil {
return nil, ab, err
}
enablePriceRegDest, err := state.Chains[source].PriceRegistry.ApplyDestChainConfigUpdates(
SimTransactOpts(),
[]price_registry.PriceRegistryDestChainConfigArgs{
{
DestChainSelector: newChainSel,
DestChainConfig: defaultPriceRegistryDestChainConfig(),
},
})
if err != nil {
return nil, ab, err
}
initialPrices, err := state.Chains[source].PriceRegistry.UpdatePrices(
SimTransactOpts(),
price_registry.InternalPriceUpdates{
TokenPriceUpdates: []price_registry.InternalTokenPriceUpdate{},
GasPriceUpdates: []price_registry.InternalGasPriceUpdate{
{
DestChainSelector: newChainSel,
// TODO: parameterize
UsdPerUnitGas: big.NewInt(2e12),
},
}})
if err != nil {
return nil, ab, err
}
batches = append(batches, managed.DetailedBatchChainOperation{
ChainIdentifier: chain.Name,
Batch: []managed.DetailedOperation{
{
// Enable the source in on ramp
Operation: executable.Operation{
To: state.Chains[source].OnRamp.Address(),
Data: hexutil.Encode(enableOnRampDest.Data()),
Value: 0,
},
},
{
// Set initial dest prices to unblock testing.
Operation: executable.Operation{
To: state.Chains[source].PriceRegistry.Address(),
Data: hexutil.Encode(initialPrices.Data()),
Value: 0,
},
},
{
// Set initial dest prices to unblock testing.
Operation: executable.Operation{
To: state.Chains[source].PriceRegistry.Address(),
Data: hexutil.Encode(enablePriceRegDest.Data()),
Value: 0,
},
},
},
})
metaDataPerChain[chain.Name] = managed.MCMSWithTimelockChainMetadata{
ExecutableMCMSChainMetadata: executable.ExecutableMCMSChainMetadata{
NonceOffset: 0,
MCMAddress: state.Chains[source].McmAddr,
},
TimelockAddress: state.Chains[source].TimelockAddr,
}
}

// Home chain new don.
// - Add new DONs for destination to home chain
nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain)
if err != nil {
return nil, ab, err
}
newDONArgs, err := BuildAddDONArgs(e.Logger, state.Chains[newChainSel].OffRamp, e.Chains[newChainSel], nodes)
if err != nil {
return nil, ab, err
}
addDON, err := state.Chains[homeChainSel].CapabilityRegistry.AddDON(SimTransactOpts(),
nodes.PeerIDs(newChainSel), []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{
{
CapabilityId: CCIPCapabilityId,
Config: newDONArgs,
},
}, false, false, nodes.DefaultF())
if err != nil {
return nil, ab, err
}
homeChain, _ := chainsel.ChainBySelector(homeChainSel)
metaDataPerChain[homeChain.Name] = managed.MCMSWithTimelockChainMetadata{
ExecutableMCMSChainMetadata: executable.ExecutableMCMSChainMetadata{
NonceOffset: 0,
MCMAddress: state.Chains[homeChainSel].McmAddr,
},
TimelockAddress: state.Chains[homeChainSel].TimelockAddr,
}
batches = append(batches, managed.DetailedBatchChainOperation{
ChainIdentifier: homeChain.Name,
Batch: []managed.DetailedOperation{
{
// Enable the source in on ramp
Operation: executable.Operation{
To: state.Chains[homeChainSel].CapabilityRegistry.Address(),
Data: hexutil.Encode(addDON.Data()),
Value: 0,
},
},
},
})
newDestProposal := managed.MCMSWithTimelockProposal{
Operation: managed.Schedule,
MinDelay: "1h",
ChainMetadata: metaDataPerChain,
Transactions: batches,
}

// New chain we can configure directly with deployer key first.
var offRampEnables []offramp.OffRampSourceChainConfigArgs
for _, source := range sources {
offRampEnables = append(offRampEnables, offramp.OffRampSourceChainConfigArgs{
Router: state.Chains[newChainSel].Router.Address(),
SourceChainSelector: source,
IsEnabled: true,
OnRamp: common.LeftPadBytes(state.Chains[source].OnRamp.Address().Bytes(), 32),
})
}
tx, err := state.Chains[newChainSel].OffRamp.ApplySourceChainConfigUpdates(e.Chains[newChainSel].DeployerKey, offRampEnables)
if err := deployment.ConfirmIfNoError(e.Chains[newChainSel], tx, err); err != nil {
return nil, ab, err
}

// We won't actually be able to setOCR3Config on the remote until the first proposal goes through.
// TODO: Outbound
return []managed.MCMSWithTimelockProposal{newDestProposal}, ab, nil
}

//func ApplyInboundChainProposal(
// e deployment.Environment,
// ab deployment.AddressBook,
// proposal managed.MCMSWithTimelockProposal,
//) (deployment.AddressBook, error) {
// state, err := LoadOnchainState(e, ab)
// if err != nil {
// return ab, err
// }
//
// // Apply the proposal.
//})

// 1. Deploy contracts
// 2. Proposal 1 (allow for inbound testing)
// - Enables new destination in onramps using test router
// - Enables the sources in the offramp and real router.
// - Sets initial prices for destination in price reg.
// - Add new DONs for destination to home chain
// - SetOCR3Config(s) on destination offramp.
// 3. At this point should be able to test from all sources
// and ensure that its writing those source prices to the new chain.
// 4. Proposal 2 (allow for outbound testing)
// - Add new destinations on onramp/price reg can use real router.
// No initial prices needed because DON updating them.
// - Add new sources to the remote offramps (test router).
// - Add ChainConfig to home chain so existing OCR instances become aware of the source.
// 5. Now we can test the other direction.
// 6 . Proposal 3 move onramp/offramps on existing chains to real router.
78 changes: 78 additions & 0 deletions integration-tests/deployment/ccip/add_chain_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package ccipdeployment

import (
"encoding/json"
"testing"

"github.com/ethereum/go-ethereum/crypto"
chainsel "github.com/smartcontractkit/chain-selectors"
"github.com/stretchr/testify/require"

"github.com/smartcontractkit/chainlink/integration-tests/deployment/executable"

"github.com/smartcontractkit/chainlink/v2/core/logger"
)

func TestAddChain(t *testing.T) {
// 4 chains where the 4th is added after initial deployment.
e := NewEnvironmentWithCRAndJobs(t, logger.TestLogger(t), 4)
state, err := LoadOnchainState(e.Env, e.Ab)
require.NoError(t, err)
sels := e.Env.AllChainSelectors()
initialDeploy := sels[0:3]
newChain := sels[3]

ab, err := DeployCCIPContracts(e.Env, DeployCCIPContractConfig{
HomeChainSel: e.HomeChainSel,
ChainsToDeploy: initialDeploy,
CCIPOnChainState: state,
})
require.NoError(t, err)
require.NoError(t, e.Ab.Merge(ab))
state, err = LoadOnchainState(e.Env, e.Ab)
require.NoError(t, err)

// Contracts deployed and initial DONs set up.
// Connect all the lanes
for _, source := range initialDeploy {
for _, dest := range initialDeploy {
if source != dest {
require.NoError(t, AddLane(e.Env, state, uint64(source), uint64(dest)))
}
}
}

executorClients := make(map[string]executable.ContractDeployBackend)
for _, chain := range e.Env.Chains {
chainselc, exists := chainsel.ChainBySelector(chain.Selector)
require.True(t, exists)
executorClients[chainselc.Name] = chain.Client
}

// Enable inbound to new 4th chain.
proposals, ab, err := NewChainInbound(e.Env, e.Ab, e.HomeChainSel, newChain, initialDeploy)
require.NoError(t, err)
require.Equal(t, 3, len(proposals[0].ChainMetadata))
// Sign this proposal with the deployer key.
execProposal, err := proposals[0].ToExecutableMCMSProposal()
require.NoError(t, err)
require.Equal(t, 4, len(execProposal.ExecutableMCMSProposalBase.ChainMetadata))
exec, err := execProposal.ToExecutor(executorClients)
require.NoError(t, err)
payload, err := exec.SigningHash()
require.NoError(t, err)
// Sign the payload
sig, err := crypto.Sign(payload.Bytes(), TestXXXMCMSSigner)
require.NoError(t, err)

// Sign the payload
unmarshalledSig := executable.Signature{}
err = json.Unmarshal(sig, &unmarshalledSig)
require.NoError(t, err)

// Add signature to proposal
proposals[0].AddSignature(unmarshalledSig)
require.NoError(t, exec.Execute())

t.Log(proposals, ab)
}
10 changes: 5 additions & 5 deletions integration-tests/deployment/ccip/add_lane.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ func AddLane(e deployment.Environment, state CCIPOnChainState, from, to uint64)
tx, err := state.Chains[from].Router.ApplyRampUpdates(e.Chains[from].DeployerKey, []router.RouterOnRamp{
{
DestChainSelector: to,
OnRamp: state.Chains[from].EvmOnRampV160.Address(),
OnRamp: state.Chains[from].OnRamp.Address(),
},
}, []router.RouterOffRamp{}, []router.RouterOffRamp{})
if err := deployment.ConfirmIfNoError(e.Chains[from], tx, err); err != nil {
return err
}
tx, err = state.Chains[from].EvmOnRampV160.ApplyDestChainConfigUpdates(e.Chains[from].DeployerKey,
tx, err = state.Chains[from].OnRamp.ApplyDestChainConfigUpdates(e.Chains[from].DeployerKey,
[]onramp.OnRampDestChainConfigArgs{
{
DestChainSelector: to,
Expand Down Expand Up @@ -70,13 +70,13 @@ func AddLane(e deployment.Environment, state CCIPOnChainState, from, to uint64)
return err
}

tx, err = state.Chains[to].EvmOffRampV160.ApplySourceChainConfigUpdates(e.Chains[to].DeployerKey,
tx, err = state.Chains[to].OffRamp.ApplySourceChainConfigUpdates(e.Chains[to].DeployerKey,
[]offramp.OffRampSourceChainConfigArgs{
{
Router: state.Chains[to].Router.Address(),
SourceChainSelector: from,
IsEnabled: true,
OnRamp: common.LeftPadBytes(state.Chains[from].EvmOnRampV160.Address().Bytes(), 32),
OnRamp: common.LeftPadBytes(state.Chains[from].OnRamp.Address().Bytes(), 32),
},
})
if err := deployment.ConfirmIfNoError(e.Chains[to], tx, err); err != nil {
Expand All @@ -85,7 +85,7 @@ func AddLane(e deployment.Environment, state CCIPOnChainState, from, to uint64)
tx, err = state.Chains[to].Router.ApplyRampUpdates(e.Chains[to].DeployerKey, []router.RouterOnRamp{}, []router.RouterOffRamp{}, []router.RouterOffRamp{
{
SourceChainSelector: from,
OffRamp: state.Chains[to].EvmOffRampV160.Address(),
OffRamp: state.Chains[to].OffRamp.Address(),
},
})
return deployment.ConfirmIfNoError(e.Chains[to], tx, err)
Expand Down
Loading