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

Solana router deploy (D) #15871

Open
wants to merge 70 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
aaab52e
Adding solchains in NewEnv
yashnevatia Jan 3, 2025
f19598e
Revert "Adding solchains in NewEnv"
yashnevatia Jan 3, 2025
e4f1f05
adding sol chains to newenv
yashnevatia Jan 3, 2025
18d77d1
newEnv needs to send nil
yashnevatia Jan 3, 2025
8150d8d
adding test env setup
yashnevatia Jan 6, 2025
7a2afca
adding link token deployment and test
yashnevatia Jan 6, 2025
7da3b14
adding nil for crib sol chains
yashnevatia Jan 6, 2025
3b1e77a
Merge branch 'solana-updates' of github.com:smartcontractkit/chainlin…
yashnevatia Jan 6, 2025
1c41814
using switch case
yashnevatia Jan 7, 2025
01f39eb
Adding decimal const
yashnevatia Jan 7, 2025
3a4ae18
adding chain selectors commit
yashnevatia Jan 7, 2025
b76324d
go mod tidy
yashnevatia Jan 7, 2025
b8a9542
Merge branch 'solana-updates' of github.com:smartcontractkit/chainlin…
yashnevatia Jan 7, 2025
b36af9d
adding initial code for solana chain contracts deploy
yashnevatia Jan 7, 2025
9d87560
linting
yashnevatia Jan 7, 2025
31cde63
merging
yashnevatia Jan 7, 2025
818f7fb
adding solana state
yashnevatia Jan 7, 2025
98e3890
adding initial code for solana chain contracts deploy
yashnevatia Jan 7, 2025
7c7c36e
wip
yashnevatia Jan 7, 2025
78664bc
wip
yashnevatia Jan 7, 2025
2f98015
chain sel update
yashnevatia Jan 7, 2025
cd73657
update core/scripts go files
yashnevatia Jan 7, 2025
a4ec585
again
yashnevatia Jan 7, 2025
0a2336b
Merge remote-tracking branch 'origin/develop' into solana-updates
tt-cll Jan 7, 2025
c0f35b9
add changeset
tt-cll Jan 7, 2025
720dccb
go imports
yashnevatia Jan 8, 2025
859dd64
Merge branch 'solana-updates' of github.com:smartcontractkit/chainlin…
yashnevatia Jan 8, 2025
c08d092
go mod
yashnevatia Jan 8, 2025
d0882cd
go mod
yashnevatia Jan 8, 2025
1e55e6f
go mod tidy
yashnevatia Jan 8, 2025
8b0f261
lint
yashnevatia Jan 8, 2025
66ff0d3
Merge branch 'solana-link-deploy' of github.com:smartcontractkit/chai…
yashnevatia Jan 8, 2025
a3974dc
todo
yashnevatia Jan 8, 2025
4de2362
Merge branch 'solana-state-updates' of github.com:smartcontractkit/ch…
yashnevatia Jan 8, 2025
90b421e
deploy stuff
yashnevatia Jan 8, 2025
87c289a
Merge branch 'develop' of github.com:smartcontractkit/chainlink into …
yashnevatia Jan 8, 2025
a4b2bc6
Adding solana router deploy
yashnevatia Jan 8, 2025
074dacf
Adding
yashnevatia Jan 8, 2025
650a18a
merging
yashnevatia Jan 8, 2025
62d0e00
Merge branch 'solana-link-deploy' of github.com:smartcontractkit/chai…
yashnevatia Jan 8, 2025
7e3b169
updates
yashnevatia Jan 8, 2025
754f858
Merge branch 'solana-state-updates' of github.com:smartcontractkit/ch…
yashnevatia Jan 8, 2025
040ca48
adding stuff for tests
yashnevatia Jan 8, 2025
abb5a01
linting
yashnevatia Jan 8, 2025
e846d6f
Merge branch 'develop' into solana-link-deploy
yashnevatia Jan 9, 2025
58480cf
merging
yashnevatia Jan 9, 2025
f4c69fd
Merge branch 'solana-link-deploy' of github.com:smartcontractkit/chai…
yashnevatia Jan 9, 2025
b4a7781
linting
yashnevatia Jan 9, 2025
b325e8b
Merge branch 'solana-link-deploy' of github.com:smartcontractkit/chai…
yashnevatia Jan 9, 2025
31e8133
changing to ctf
yashnevatia Jan 9, 2025
7fcf845
bug
yashnevatia Jan 9, 2025
723cc1a
Merge branch 'develop' of github.com:smartcontractkit/chainlink into …
yashnevatia Jan 9, 2025
d8f5646
merging
yashnevatia Jan 9, 2025
12f4c9e
deployment: memory: Generate more transmitter key types, expose in JD
archseer Jan 7, 2025
6c54711
deployment: memory: Configure nodes with solana config too
archseer Jan 7, 2025
ba38563
Use CTF to spin up the solana validator for in-memory tests
archseer Jan 7, 2025
e28b265
Use autopatchelf on solana binaries to make them usable on NixOS
archseer Jan 8, 2025
5429dc5
memory: solana: Shut down the container when test terminates
archseer Jan 9, 2025
c6a65cb
go mod tidy
archseer Jan 10, 2025
480ed0b
Use latest upstream CTF
archseer Jan 10, 2025
6483a93
Add missing import
archseer Jan 10, 2025
ea35285
make modgraph
archseer Jan 10, 2025
1b3fdd6
Use framework.DefaultNetwork()
archseer Jan 10, 2025
b11f530
merging deployment-memory-solana-2
yashnevatia Jan 10, 2025
1382873
merging solana-state-updates
yashnevatia Jan 10, 2025
bd14a29
changes
yashnevatia Jan 10, 2025
c97c9aa
tidying
yashnevatia Jan 10, 2025
dc0c1a7
ignoring keypair if not provided
yashnevatia Jan 10, 2025
18ed1b4
merging
yashnevatia Jan 10, 2025
32776f1
fix
yashnevatia Jan 10, 2025
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
213 changes: 191 additions & 22 deletions deployment/ccip/changeset/cs_deploy_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,16 @@
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/gagliardetto/solana-go"
"github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock"
"golang.org/x/sync/errgroup"

"github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/ccip_router"

solBinary "github.com/gagliardetto/binary"
solRpc "github.com/gagliardetto/solana-go/rpc"
chainsel "github.com/smartcontractkit/chain-selectors"

"github.com/smartcontractkit/chainlink/deployment"
"github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home"
Expand All @@ -25,6 +32,10 @@

var _ deployment.ChangeSet[DeployChainContractsConfig] = DeployChainContracts

var (
EnableExecutionAfter = int64(1800) // 30min
)

// DeployChainContracts deploys all new CCIP v1.6 or later contracts for the given chains.
// It returns the new addresses for the contracts.
// DeployChainContracts is idempotent. If there is an error, it will return the successfully deployed addresses and the error so that the caller can call the
Expand Down Expand Up @@ -68,17 +79,12 @@
return nil
}

func deployChainContractsForChains(
e deployment.Environment,
ab deployment.AddressBook,
homeChainSel uint64,
chainsToDeploy []uint64) error {
func validateHomeChainState(e deployment.Environment, homeChainSel uint64, existingState CCIPOnChainState) error {
existingState, err := LoadOnchainState(e)
if err != nil {
e.Logger.Errorw("Failed to load existing onchain state", "err")
return err
}

capReg := existingState.Chains[homeChainSel].CapabilityRegistry
if capReg == nil {
e.Logger.Errorw("Failed to get capability registry")
Expand Down Expand Up @@ -113,24 +119,67 @@
e.Logger.Errorw("Failed to get rmn home", "err", err)
return errors.New("rmn home not found")
}
return nil
}

func deployChainContractsForChains(
e deployment.Environment,
ab deployment.AddressBook,
homeChainSel uint64,
chainsToDeploy []uint64) error {
existingEVMState, err := LoadOnchainState(e)
if err != nil {
e.Logger.Errorw("Failed to load existing onchain state", "err")
return err
}

err = validateHomeChainState(e, homeChainSel, existingEVMState)
if err != nil {
return err
}

err = deployment.ValidateSelectorsInEnvironment(e, chainsToDeploy)
if err != nil {
return err
}

rmnHome := existingEVMState.Chains[homeChainSel].RMNHome

existingSolState, err := LoadOnchainStateSolana(e)
if err != nil {
e.Logger.Errorw("Failed to load existing onchain solanastate", "err")
return err
}

deployGrp := errgroup.Group{}

for _, chainSel := range chainsToDeploy {
chain, ok := e.Chains[chainSel]
if !ok {
return fmt.Errorf("chain %d not found", chainSel)
}
if existingState.Chains[chainSel].LinkToken == nil || existingState.Chains[chainSel].Weth9 == nil {
return fmt.Errorf("fee tokens not found for chain %d", chainSel)
// already validated family
family, _ := chainsel.GetSelectorFamily(chainSel)
var deployFn func() error
switch family {
case chainsel.FamilyEVM:
chain := e.Chains[chainSel]
if existingEVMState.Chains[chainSel].LinkToken == nil || existingEVMState.Chains[chainSel].Weth9 == nil {
return fmt.Errorf("fee tokens not found for chain %d", chainSel)
}
deployFn = func() error { return deployChainContractsEVM(e, chain, ab, rmnHome) }

case chainsel.FamilySolana:
chain := e.SolChains[chainSel]
if existingSolState.SolChains[chainSel].LinkToken.IsZero() {
return fmt.Errorf("fee tokens not found for chain %d", chainSel)
}
deployFn = func() error { return deployChainContractsSolana(e, chain, ab) }
}
deployGrp.Go(
func() error {
err := deployChainContracts(e, chain, ab, rmnHome)
if err != nil {
e.Logger.Errorw("Failed to deploy chain contracts", "chain", chainSel, "err", err)
return fmt.Errorf("failed to deploy chain contracts for chain %d: %w", chainSel, err)
}
return nil
})
deployGrp.Go(func() error {
err := deployFn()
if err != nil {
e.Logger.Errorw("Failed to deploy chain contracts", "chain", chainSel, "err", err)
return fmt.Errorf("failed to deploy chain contracts for chain %d: %w", chainSel, err)
}
return nil
})
}
if err := deployGrp.Wait(); err != nil {
e.Logger.Errorw("Failed to deploy chain contracts", "err", err)
Expand All @@ -139,7 +188,7 @@
return nil
}

func deployChainContracts(
func deployChainContractsEVM(
e deployment.Environment,
chain deployment.Chain,
ab deployment.AddressBook,
Expand Down Expand Up @@ -401,3 +450,123 @@
e.Logger.Infow("Added nonce manager authorized callers", "chain", chain.String(), "callers", []common.Address{offRampContract.Address(), onRampContract.Address()})
return nil
}

func solRouterProgramData(e deployment.Environment, chain deployment.SolChain, ccipRouterProgram solana.PublicKey) (struct {
DataType uint32
Address solana.PublicKey
}, error) {
var programData struct {
DataType uint32
Address solana.PublicKey
}
data, err := chain.Client.GetAccountInfoWithOpts(e.GetContext(), ccipRouterProgram, &solRpc.GetAccountInfoOpts{
Commitment: solRpc.CommitmentConfirmed,
})
if err != nil {
return programData, fmt.Errorf("failed to deploy program: %w", err)
}

err = solBinary.UnmarshalBorsh(&programData, data.Bytes())
if err != nil {
return programData, fmt.Errorf("failed to unmarshal program data: %w", err)
}
return programData, nil
}

func checkRouterInitialized(e deployment.Environment, chain deployment.SolChain, ccipRouterProgram solana.PublicKey) (bool, error) {
routerConfigPDA := GetRouterConfigPDA(ccipRouterProgram)
routerConfigInfo, err := chain.Client.GetAccountInfoWithOpts(e.GetContext(), routerConfigPDA, &solRpc.GetAccountInfoOpts{
Commitment: solRpc.CommitmentConfirmed,
})
if err != nil {
return false, nil
}
return routerConfigInfo != nil && len(routerConfigInfo.Value.Data.GetBinary()) > 0, nil
}

func deployChainContractsSolana(
e deployment.Environment,
chain deployment.SolChain,
ab deployment.AddressBook,
) error {
state, err := LoadOnchainStateSolana(e)
if err != nil {
e.Logger.Errorw("Failed to load existing onchain state", "err")
return err
}
chainState, chainExists := state.SolChains[chain.Selector]
if !chainExists {
return fmt.Errorf("chain %s not found in existing state, deploy the prerequisites first", chain.String())
}
linkTokenContract := chainState.LinkToken
e.Logger.Infow("link token", "addr", linkTokenContract.String())

var ccipRouterProgram solana.PublicKey
if chainState.SolCcipRouter.IsZero() {
//deploy router
programID, err := chain.DeployProgram(e.Logger, "ccip_router")
if err != nil {
return fmt.Errorf("failed to deploy program: %w", err)
}

tv := deployment.NewTypeAndVersion("SolCcipRouter", deployment.Version1_0_0)
e.Logger.Infow("Deployed contract", "Contract", tv.String(), "addr", programID, "chain", chain.String())

ccipRouterProgram = solana.MustPublicKeyFromBase58(programID)
err = ab.Save(chain.Selector, programID, tv)
if err != nil {
return fmt.Errorf("failed to save address: %w", err)
}
} else {
e.Logger.Infow("Using existing router", "addr", chainState.SolCcipRouter.String())
ccipRouterProgram = chainState.SolCcipRouter
}
ccip_router.SetProgramID(ccipRouterProgram)

// check if solana router is initalised

Check failure on line 526 in deployment/ccip/changeset/cs_deploy_chain.go

View workflow job for this annotation

GitHub Actions / GolangCI Lint (deployment)

`initalised` is a misspelling of `initialised` (misspell)
initialized, err := checkRouterInitialized(e, chain, ccipRouterProgram)
if err != nil {
return err
}
if initialized {
e.Logger.Infow("Router already initialized, skipping initialization", "chain", chain.String())
return nil
}

programData, err := solRouterProgramData(e, chain, ccipRouterProgram)
if err != nil {
return fmt.Errorf("failed to get solana router program data: %w", err)
}

defaultGasLimit := solBinary.Uint128{Lo: 3000, Hi: 0, Endianness: nil}

instruction, err := ccip_router.NewInitializeInstruction(
chain.Selector, // chain selector
defaultGasLimit, // default gas limit
true, // allow out of order execution
EnableExecutionAfter, // period to wait before allowing manual execution
solana.PublicKey{},
GetRouterConfigPDA(ccipRouterProgram),
GetRouterStatePDA(ccipRouterProgram),
chain.DeployerKey.PublicKey(),
solana.SystemProgramID,
ccipRouterProgram,
programData.Address,
GetExternalExecutionConfigPDA(ccipRouterProgram),
GetExternalTokenPoolsSignerPDA(ccipRouterProgram),
).ValidateAndBuild()

if err != nil {
return fmt.Errorf("failed to build instruction: %w", err)
}
err = chain.Confirm([]solana.Instruction{instruction})

if err != nil {
return fmt.Errorf("failed to confirm instructions: %w", err)
}

//TODO: deploy token pool contract
//TODO: log errors

return nil
}
21 changes: 18 additions & 3 deletions deployment/ccip/changeset/cs_deploy_chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,15 @@ func TestDeployChainContractsChangeset(t *testing.T) {
e := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{
Bootstraps: 1,
Chains: 2,
SolChains: 1,
Nodes: 4,
})
selectors := e.AllChainSelectors()
homeChainSel := selectors[0]
evmSelectors := e.AllChainSelectors()
homeChainSel := evmSelectors[0]
solChainSelectors := e.AllChainSelectorsSolana()
selectors := make([]uint64, 0, len(evmSelectors)+len(solChainSelectors))
selectors = append(selectors, evmSelectors...)
selectors = append(selectors, solChainSelectors...)
nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain)
require.NoError(t, err)
p2pIds := nodes.NonBootstraps().PeerIDs()
Expand All @@ -39,6 +44,8 @@ func TestDeployChainContractsChangeset(t *testing.T) {
ChainSelector: chain,
})
}

SavePreloadedSolAddresses(e, solChainSelectors[0])
e, err = commonchangeset.ApplyChangesets(t, e, nil, []commonchangeset.ChangesetApplication{
{
Changeset: commonchangeset.WrapChangeSet(DeployHomeChain),
Expand Down Expand Up @@ -84,7 +91,7 @@ func TestDeployChainContractsChangeset(t *testing.T) {
require.NotNil(t, state.Chains[homeChainSel].CapabilityRegistry)
require.NotNil(t, state.Chains[homeChainSel].CCIPHome)
require.NotNil(t, state.Chains[homeChainSel].RMNHome)
for _, sel := range selectors {
for _, sel := range evmSelectors {
require.NotNil(t, state.Chains[sel].LinkToken)
require.NotNil(t, state.Chains[sel].Weth9)
require.NotNil(t, state.Chains[sel].TokenAdminRegistry)
Expand All @@ -97,6 +104,14 @@ func TestDeployChainContractsChangeset(t *testing.T) {
require.NotNil(t, state.Chains[sel].OffRamp)
require.NotNil(t, state.Chains[sel].OnRamp)
}

solState, err := LoadOnchainStateSolana(e)
require.NoError(t, err)
for _, sel := range solChainSelectors {
require.NotNil(t, solState.SolChains[sel].LinkToken)
require.NotNil(t, solState.SolChains[sel].SolCcipRouter)
}

}

func TestDeployCCIPContracts(t *testing.T) {
Expand Down
Binary file not shown.
Loading
Loading