diff --git a/deployment/ccip/changeset/cap_reg.go b/deployment/ccip/changeset/cap_reg.go deleted file mode 100644 index 1eded730a7c..00000000000 --- a/deployment/ccip/changeset/cap_reg.go +++ /dev/null @@ -1,30 +0,0 @@ -package changeset - -import ( - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - - "github.com/smartcontractkit/chainlink/deployment" - ccipdeployment "github.com/smartcontractkit/chainlink/deployment/ccip" -) - -var _ deployment.ChangeSet = DeployCapReg - -// DeployCapReg is a separate changeset because cap reg is an env var for CL nodes. -func DeployCapReg(env deployment.Environment, config interface{}) (deployment.ChangesetOutput, error) { - homeChainSel, ok := config.(uint64) - if !ok { - return deployment.ChangesetOutput{}, deployment.ErrInvalidConfig - } - // Note we also deploy the cap reg. - ab := deployment.NewMemoryAddressBook() - _, err := ccipdeployment.DeployCapReg(env.Logger, ab, env.Chains[homeChainSel]) - if err != nil { - env.Logger.Errorw("Failed to deploy cap reg", "err", err, "addresses", ab) - return deployment.ChangesetOutput{}, err - } - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{}, - AddressBook: ab, - JobSpecs: nil, - }, nil -} diff --git a/deployment/ccip/changeset/home_chain.go b/deployment/ccip/changeset/home_chain.go new file mode 100644 index 00000000000..5fa5cab5b21 --- /dev/null +++ b/deployment/ccip/changeset/home_chain.go @@ -0,0 +1,77 @@ +package changeset + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + + "github.com/smartcontractkit/chainlink/deployment" + ccipdeployment "github.com/smartcontractkit/chainlink/deployment/ccip" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" +) + +var _ deployment.ChangeSet = DeployHomeChain + +// DeployHomeChain is a separate changeset because it is a standalone deployment performed once in home chain for the entire CCIP deployment. +func DeployHomeChain(env deployment.Environment, config interface{}) (deployment.ChangesetOutput, error) { + cfg, ok := config.(DeployHomeChainConfig) + if !ok { + return deployment.ChangesetOutput{}, deployment.ErrInvalidConfig + } + err := cfg.Validate() + if err != nil { + return deployment.ChangesetOutput{}, errors.Wrapf(deployment.ErrInvalidConfig, "%v", err) + } + ab := deployment.NewMemoryAddressBook() + // Note we also deploy the cap reg. + _, err = ccipdeployment.DeployHomeChain(env.Logger, env, ab, env.Chains[cfg.HomeChainSel], cfg.RMNStaticConfig, cfg.RMNDynamicConfig, cfg.NodeOperators, cfg.NodeP2PIDsPerNodeOpAdmin) + if err != nil { + env.Logger.Errorw("Failed to deploy cap reg", "err", err, "addresses", env.ExistingAddresses) + return deployment.ChangesetOutput{}, err + } + + return deployment.ChangesetOutput{ + Proposals: []timelock.MCMSWithTimelockProposal{}, + AddressBook: ab, + JobSpecs: nil, + }, nil +} + +type DeployHomeChainConfig struct { + HomeChainSel uint64 + RMNStaticConfig rmn_home.RMNHomeStaticConfig + RMNDynamicConfig rmn_home.RMNHomeDynamicConfig + NodeOperators []capabilities_registry.CapabilitiesRegistryNodeOperator + NodeP2PIDsPerNodeOpAdmin map[string][][32]byte +} + +func (c DeployHomeChainConfig) Validate() error { + if c.HomeChainSel == 0 { + return fmt.Errorf("home chain selector must be set") + } + if c.RMNDynamicConfig.OffchainConfig == nil { + return fmt.Errorf("offchain config for RMNHomeDynamicConfig must be set") + } + if c.RMNStaticConfig.OffchainConfig == nil { + return fmt.Errorf("offchain config for RMNHomeStaticConfig must be set") + } + if len(c.NodeOperators) == 0 { + return fmt.Errorf("node operators must be set") + } + for _, nop := range c.NodeOperators { + if nop.Admin == (common.Address{}) { + return fmt.Errorf("node operator admin address must be set") + } + if nop.Name == "" { + return fmt.Errorf("node operator name must be set") + } + if len(c.NodeP2PIDsPerNodeOpAdmin[nop.Name]) == 0 { + return fmt.Errorf("node operator %s must have node p2p ids provided", nop.Name) + } + } + + return nil +} diff --git a/deployment/ccip/changeset/home_chain_test.go b/deployment/ccip/changeset/home_chain_test.go new file mode 100644 index 00000000000..f0abdc64437 --- /dev/null +++ b/deployment/ccip/changeset/home_chain_test.go @@ -0,0 +1,63 @@ +package changeset + +import ( + "testing" + + chainsel "github.com/smartcontractkit/chain-selectors" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + + "github.com/smartcontractkit/chainlink/deployment" + ccdeploy "github.com/smartcontractkit/chainlink/deployment/ccip" + "github.com/smartcontractkit/chainlink/deployment/common/view/v1_0" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestDeployHomeChain(t *testing.T) { + lggr := logger.TestLogger(t) + e := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ + Bootstraps: 1, + Chains: 2, + Nodes: 4, + }) + homeChainSel := e.AllChainSelectors()[0] + nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) + require.NoError(t, err) + p2pIds := nodes.NonBootstraps().PeerIDs() + homeChainCfg := DeployHomeChainConfig{ + HomeChainSel: homeChainSel, + RMNStaticConfig: ccdeploy.NewTestRMNStaticConfig(), + RMNDynamicConfig: ccdeploy.NewTestRMNDynamicConfig(), + NodeOperators: ccdeploy.NewTestNodeOperator(e.Chains[homeChainSel].DeployerKey.From), + NodeP2PIDsPerNodeOpAdmin: map[string][][32]byte{ + "NodeOperator": p2pIds, + }, + } + output, err := DeployHomeChain(e, homeChainCfg) + require.NoError(t, err) + require.NoError(t, e.ExistingAddresses.Merge(output.AddressBook)) + state, err := ccdeploy.LoadOnchainState(e) + require.NoError(t, err) + require.NotNil(t, state.Chains[homeChainSel].CapabilityRegistry) + require.NotNil(t, state.Chains[homeChainSel].CCIPHome) + require.NotNil(t, state.Chains[homeChainSel].RMNHome) + snap, err := state.View([]uint64{homeChainSel}) + require.NoError(t, err) + chainid, err := chainsel.ChainIdFromSelector(homeChainSel) + require.NoError(t, err) + chainName, err := chainsel.NameFromChainId(chainid) + require.NoError(t, err) + _, ok := snap[chainName] + require.True(t, ok) + capRegSnap, ok := snap[chainName].CapabilityRegistry[state.Chains[homeChainSel].CapabilityRegistry.Address().String()] + require.True(t, ok) + require.NotNil(t, capRegSnap) + require.Equal(t, capRegSnap.Nops, []v1_0.NopView{ + { + Admin: e.Chains[homeChainSel].DeployerKey.From, + Name: "NodeOperator", + }, + }) + require.Len(t, capRegSnap.Nodes, len(p2pIds)) +} diff --git a/deployment/ccip/deploy.go b/deployment/ccip/deploy.go index 4d90422c843..f407b9856c4 100644 --- a/deployment/ccip/deploy.go +++ b/deployment/ccip/deploy.go @@ -12,6 +12,7 @@ import ( owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/registry_module_owner_custom" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" @@ -187,15 +188,6 @@ func DeployCCIPContracts(e deployment.Environment, ab deployment.AddressBook, c return fmt.Errorf("ccip home address mismatch") } - // Signal to CR that our nodes support CCIP capability. - if err := AddNodes( - e.Logger, - capReg, - e.Chains[c.HomeChainSel], - nodes.NonBootstraps().PeerIDs(), - ); err != nil { - return err - } rmnHome := existingState.Chains[c.HomeChainSel].RMNHome if rmnHome == nil { e.Logger.Errorw("Failed to get rmn home", "err", err) diff --git a/deployment/ccip/deploy_home_chain.go b/deployment/ccip/deploy_home_chain.go index 3f614b8510f..341f53a0438 100644 --- a/deployment/ccip/deploy_home_chain.go +++ b/deployment/ccip/deploy_home_chain.go @@ -15,6 +15,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "golang.org/x/exp/maps" "github.com/smartcontractkit/chainlink-ccip/chainconfig" "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" @@ -85,7 +86,24 @@ func MustABIEncode(abiString string, args ...interface{}) []byte { return encoded } -func DeployCapReg(lggr logger.Logger, ab deployment.AddressBook, chain deployment.Chain) (*ContractDeploy[*capabilities_registry.CapabilitiesRegistry], error) { +// DeployCapReg deploys the CapabilitiesRegistry contract if it is not already deployed +// and returns a ContractDeploy struct with the address and contract instance. +func DeployCapReg( + lggr logger.Logger, + state CCIPOnChainState, + ab deployment.AddressBook, + chain deployment.Chain, +) (*ContractDeploy[*capabilities_registry.CapabilitiesRegistry], error) { + homeChainState, exists := state.Chains[chain.Selector] + if exists { + cr := homeChainState.CapabilityRegistry + if cr != nil { + lggr.Infow("Found CapabilitiesRegistry in chain state", "address", cr.Address().String()) + return &ContractDeploy[*capabilities_registry.CapabilitiesRegistry]{ + Address: cr.Address(), Contract: cr, Tv: deployment.NewTypeAndVersion(CapabilitiesRegistry, deployment.Version1_0_0), + }, nil + } + } capReg, err := deployContract(lggr, chain, ab, func(chain deployment.Chain) ContractDeploy[*capabilities_registry.CapabilitiesRegistry] { crAddr, tx, cr, err2 := capabilities_registry.DeployCapabilitiesRegistry( @@ -100,8 +118,31 @@ func DeployCapReg(lggr logger.Logger, ab deployment.AddressBook, chain deploymen lggr.Errorw("Failed to deploy capreg", "err", err) return nil, err } + return capReg, nil +} - lggr.Infow("deployed capreg", "addr", capReg.Address) +func DeployHomeChain( + lggr logger.Logger, + e deployment.Environment, + ab deployment.AddressBook, + chain deployment.Chain, + rmnHomeStatic rmn_home.RMNHomeStaticConfig, + rmnHomeDynamic rmn_home.RMNHomeDynamicConfig, + nodeOps []capabilities_registry.CapabilitiesRegistryNodeOperator, + nodeP2PIDsPerNodeOpAdmin map[string][][32]byte, +) (*ContractDeploy[*capabilities_registry.CapabilitiesRegistry], error) { + // load existing state + state, err := LoadOnchainState(e) + if err != nil { + return nil, fmt.Errorf("failed to load onchain state: %w", err) + } + // Deploy CapabilitiesRegistry, CCIPHome, RMNHome + capReg, err := DeployCapReg(lggr, state, ab, chain) + if err != nil { + return nil, err + } + + lggr.Infow("deployed/connected to capreg", "addr", capReg.Address) ccipHome, err := deployContract( lggr, chain, ab, func(chain deployment.Chain) ContractDeploy[*ccip_home.CCIPHome] { @@ -138,14 +179,8 @@ func DeployCapReg(lggr logger.Logger, ab deployment.AddressBook, chain deploymen } lggr.Infow("deployed RMNHome", "addr", rmnHome.Address) - // TODO: properly configure RMNHome - tx, err := rmnHome.Contract.SetCandidate(chain.DeployerKey, rmn_home.RMNHomeStaticConfig{ - Nodes: []rmn_home.RMNHomeNode{}, - OffchainConfig: []byte("static config"), - }, rmn_home.RMNHomeDynamicConfig{ - SourceChains: []rmn_home.RMNHomeSourceChain{}, - OffchainConfig: []byte("dynamic config"), - }, [32]byte{}) + // considering the RMNHome is recently deployed, there is no digest to overwrite + tx, err := rmnHome.Contract.SetCandidate(chain.DeployerKey, rmnHomeStatic, rmnHomeDynamic, [32]byte{}) if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { lggr.Errorw("Failed to set candidate on RMNHome", "err", err) return nil, err @@ -189,20 +224,63 @@ func DeployCapReg(lggr logger.Logger, ab deployment.AddressBook, chain deploymen lggr.Errorw("Failed to add capabilities", "err", err) return nil, err } - // TODO: Just one for testing. - tx, err = capReg.Contract.AddNodeOperators(chain.DeployerKey, []capabilities_registry.CapabilitiesRegistryNodeOperator{ - { - Admin: chain.DeployerKey.From, - Name: "NodeOperator", - }, - }) - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + + tx, err = capReg.Contract.AddNodeOperators(chain.DeployerKey, nodeOps) + txBlockNum, err := deployment.ConfirmIfNoError(chain, tx, err) + if err != nil { lggr.Errorw("Failed to add node operators", "err", err) return nil, err } + addedEvent, err := capReg.Contract.FilterNodeOperatorAdded(&bind.FilterOpts{ + Start: txBlockNum, + Context: context.Background(), + }, nil, nil) + if err != nil { + lggr.Errorw("Failed to filter NodeOperatorAdded event", "err", err) + return capReg, err + } + // Need to fetch nodeoperators ids to be able to add nodes for corresponding node operators + p2pIDsByNodeOpId := make(map[uint32][][32]byte) + for addedEvent.Next() { + for nopName, p2pId := range nodeP2PIDsPerNodeOpAdmin { + if addedEvent.Event.Name == nopName { + lggr.Infow("Added node operator", "admin", addedEvent.Event.Admin, "name", addedEvent.Event.Name) + p2pIDsByNodeOpId[addedEvent.Event.NodeOperatorId] = p2pId + } + } + } + if len(p2pIDsByNodeOpId) != len(nodeP2PIDsPerNodeOpAdmin) { + lggr.Errorw("Failed to add all node operators", "added", maps.Keys(p2pIDsByNodeOpId), "expected", maps.Keys(nodeP2PIDsPerNodeOpAdmin)) + return capReg, errors.New("failed to add all node operators") + } + // Adds initial set of nodes to CR, who all have the CCIP capability + if err := AddNodes(lggr, capReg.Contract, chain, p2pIDsByNodeOpId); err != nil { + return capReg, err + } return capReg, nil } +// getNodeOperatorIDMap returns a map of node operator names to their IDs +// If maxNops is greater than the number of node operators, it will return all node operators +func getNodeOperatorIDMap(capReg *capabilities_registry.CapabilitiesRegistry, maxNops uint32) (map[string]uint32, error) { + nopIdByName := make(map[string]uint32) + operators, err := capReg.GetNodeOperators(nil) + if err != nil { + return nil, err + } + if len(operators) < int(maxNops) { + maxNops = uint32(len(operators)) + } + for i := uint32(1); i <= maxNops; i++ { + operator, err := capReg.GetNodeOperator(nil, i) + if err != nil { + return nil, err + } + nopIdByName[operator.Name] = i + } + return nopIdByName, nil +} + func isEqualCapabilitiesRegistryNodeParams(a, b capabilities_registry.CapabilitiesRegistryNodeParams) (bool, error) { aBytes, err := json.Marshal(a) if err != nil { @@ -219,7 +297,7 @@ func AddNodes( lggr logger.Logger, capReg *capabilities_registry.CapabilitiesRegistry, chain deployment.Chain, - p2pIDs [][32]byte, + p2pIDsByNodeOpId map[uint32][][32]byte, ) error { var nodeParams []capabilities_registry.CapabilitiesRegistryNodeParams nodes, err := capReg.GetNodes(nil) @@ -235,26 +313,28 @@ func AddNodes( HashedCapabilityIds: node.HashedCapabilityIds, } } - for _, p2pID := range p2pIDs { - // if any p2pIDs are empty throw error - if bytes.Equal(p2pID[:], make([]byte, 32)) { - return errors.Wrapf(errors.New("empty p2pID"), "p2pID: %x selector: %d", p2pID, chain.Selector) - } - nodeParam := capabilities_registry.CapabilitiesRegistryNodeParams{ - NodeOperatorId: NodeOperatorID, - Signer: p2pID, // Not used in tests - P2pId: p2pID, - EncryptionPublicKey: p2pID, // Not used in tests - HashedCapabilityIds: [][32]byte{CCIPCapabilityID}, - } - if existing, ok := existingNodeParams[p2pID]; ok { - if isEqual, err := isEqualCapabilitiesRegistryNodeParams(existing, nodeParam); err != nil && isEqual { - lggr.Infow("Node already exists", "p2pID", p2pID) - continue + for nopID, p2pIDs := range p2pIDsByNodeOpId { + for _, p2pID := range p2pIDs { + // if any p2pIDs are empty throw error + if bytes.Equal(p2pID[:], make([]byte, 32)) { + return errors.Wrapf(errors.New("empty p2pID"), "p2pID: %x selector: %d", p2pID, chain.Selector) + } + nodeParam := capabilities_registry.CapabilitiesRegistryNodeParams{ + NodeOperatorId: nopID, + Signer: p2pID, // Not used in tests + P2pId: p2pID, + EncryptionPublicKey: p2pID, // Not used in tests + HashedCapabilityIds: [][32]byte{CCIPCapabilityID}, + } + if existing, ok := existingNodeParams[p2pID]; ok { + if isEqual, err := isEqualCapabilitiesRegistryNodeParams(existing, nodeParam); err != nil && isEqual { + lggr.Infow("Node already exists", "p2pID", p2pID) + continue + } } - } - nodeParams = append(nodeParams, nodeParam) + nodeParams = append(nodeParams, nodeParam) + } } if len(nodeParams) == 0 { lggr.Infow("No new nodes to add") diff --git a/deployment/ccip/deploy_test.go b/deployment/ccip/deploy_test.go index ecb17017193..63aeacb4bdf 100644 --- a/deployment/ccip/deploy_test.go +++ b/deployment/ccip/deploy_test.go @@ -25,6 +25,18 @@ func TestDeployCCIPContracts(t *testing.T) { homeChainSel, feedChainSel := allocateCCIPChainSelectors(e.Chains) _ = DeployTestContracts(t, lggr, e.ExistingAddresses, homeChainSel, feedChainSel, e.Chains) + nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) + require.NoError(t, err) + + _, err = DeployHomeChain(lggr, e, e.ExistingAddresses, e.Chains[homeChainSel], + NewTestRMNStaticConfig(), + NewTestRMNDynamicConfig(), + NewTestNodeOperator(e.Chains[homeChainSel].DeployerKey.From), + map[string][][32]byte{ + "NodeOperator": nodes.NonBootstraps().PeerIDs(), + }, + ) + require.NoError(t, err) // Load the state after deploying the cap reg and feeds. s, err := LoadOnchainState(e) require.NoError(t, err) diff --git a/deployment/ccip/test_helpers.go b/deployment/ccip/test_helpers.go index de1ebd7e675..74cf98cab9f 100644 --- a/deployment/ccip/test_helpers.go +++ b/deployment/ccip/test_helpers.go @@ -3,12 +3,13 @@ package ccipdeployment import ( "context" "fmt" - mapset "github.com/deckarep/golang-set/v2" "math/big" "sort" "testing" "time" + mapset "github.com/deckarep/golang-set/v2" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/core/types" @@ -111,7 +112,11 @@ func DeployTestContracts(t *testing.T, feedChainSel uint64, chains map[uint64]deployment.Chain, ) deployment.CapabilityRegistryConfig { - capReg, err := DeployCapReg(lggr, ab, chains[homeChainSel]) + capReg, err := DeployCapReg(lggr, + // deploying cap reg for the first time on a blank chain state + CCIPOnChainState{ + Chains: make(map[uint64]CCIPChainState), + }, ab, chains[homeChainSel]) require.NoError(t, err) _, err = DeployFeeds(lggr, ab, chains[feedChainSel]) require.NoError(t, err) @@ -172,9 +177,20 @@ func NewMemoryEnvironment(t *testing.T, lggr logger.Logger, numChains int, numNo require.NoError(t, node.App.Stop()) }) } - e := memory.NewMemoryEnvironmentFromChainsNodes(t, lggr, chains, nodes) + envNodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) + require.NoError(t, err) e.ExistingAddresses = ab + _, err = DeployHomeChain(lggr, e, e.ExistingAddresses, chains[homeChainSel], + NewTestRMNStaticConfig(), + NewTestRMNDynamicConfig(), + NewTestNodeOperator(chains[homeChainSel].DeployerKey.From), + map[string][][32]byte{ + "NodeOperator": envNodes.NonBootstraps().PeerIDs(), + }, + ) + require.NoError(t, err) + return DeployedEnv{ Env: e, HomeChainSel: homeChainSel, diff --git a/deployment/ccip/test_params.go b/deployment/ccip/test_params.go new file mode 100644 index 00000000000..531c48532f1 --- /dev/null +++ b/deployment/ccip/test_params.go @@ -0,0 +1,31 @@ +package ccipdeployment + +import ( + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" +) + +func NewTestRMNStaticConfig() rmn_home.RMNHomeStaticConfig { + return rmn_home.RMNHomeStaticConfig{ + Nodes: []rmn_home.RMNHomeNode{}, + OffchainConfig: []byte("static config"), + } +} + +func NewTestRMNDynamicConfig() rmn_home.RMNHomeDynamicConfig { + return rmn_home.RMNHomeDynamicConfig{ + SourceChains: []rmn_home.RMNHomeSourceChain{}, + OffchainConfig: []byte("dynamic config"), + } +} + +func NewTestNodeOperator(admin common.Address) []capabilities_registry.CapabilitiesRegistryNodeOperator { + return []capabilities_registry.CapabilitiesRegistryNodeOperator{ + { + Admin: admin, + Name: "NodeOperator", + }, + } +} diff --git a/deployment/changeset.go b/deployment/changeset.go index 687d772bf73..e6c0988e67e 100644 --- a/deployment/changeset.go +++ b/deployment/changeset.go @@ -8,7 +8,7 @@ import ( ) var ( - ErrInvalidConfig = errors.New("invalid config") + ErrInvalidConfig = errors.New("invalid changeset config") ) // ChangeSet represents a set of changes to be made to an environment. diff --git a/deployment/go.mod b/deployment/go.mod index 727e11215c8..c659795a77f 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -34,6 +34,7 @@ require ( github.com/testcontainers/testcontainers-go v0.34.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 + golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c golang.org/x/sync v0.8.0 google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.35.1 @@ -478,7 +479,6 @@ require ( go4.org/netipx v0.0.0-20230125063823-8449b0a6169f // indirect golang.org/x/arch v0.11.0 // indirect golang.org/x/crypto v0.28.0 // indirect - golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect golang.org/x/mod v0.21.0 // indirect golang.org/x/net v0.30.0 // indirect golang.org/x/oauth2 v0.23.0 // indirect diff --git a/integration-tests/ccip-tests/testsetups/test_helpers.go b/integration-tests/ccip-tests/testsetups/test_helpers.go index 4a63d109992..4de5d0988a2 100644 --- a/integration-tests/ccip-tests/testsetups/test_helpers.go +++ b/integration-tests/ccip-tests/testsetups/test_helpers.go @@ -95,11 +95,22 @@ func NewLocalDevEnvironment(t *testing.T, lggr logger.Logger) (ccipdeployment.De crConfig, testEnv, cfg) require.NoError(t, err) - e, don, err := devenv.NewEnvironment(ctx, lggr, *envConfig) require.NoError(t, err) require.NotNil(t, e) e.ExistingAddresses = ab + + envNodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) + require.NoError(t, err) + _, err = ccipdeployment.DeployHomeChain(lggr, *e, e.ExistingAddresses, chains[homeChainSel], + ccipdeployment.NewTestRMNStaticConfig(), + ccipdeployment.NewTestRMNDynamicConfig(), + ccipdeployment.NewTestNodeOperator(chains[homeChainSel].DeployerKey.From), + map[string][][32]byte{ + "NodeOperator": envNodes.NonBootstraps().PeerIDs(), + }, + ) + require.NoError(t, err) zeroLogLggr := logging.GetTestLogger(t) // fund the nodes FundNodes(t, zeroLogLggr, testEnv, cfg, don.PluginNodes())