Skip to content

Commit

Permalink
store other pdas in state
Browse files Browse the repository at this point in the history
  • Loading branch information
tt-cll committed Jan 30, 2025
1 parent a9c5c17 commit ae4ab02
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 60 deletions.
12 changes: 3 additions & 9 deletions deployment/ccip/changeset/solana/cs_chain_contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,15 +218,10 @@ func doAddRemoteChainToSolana(
}
e.Logger.Infow("Confirmed instruction", "instruction", instruction)

err = ab.Save(chainSel, sourceChainStatePDA.String(), cs.SerializeSolanaStateForAB(cs.RouterSource, strconv.FormatUint(destination, 10), deployment.Version1_0_0))
err = ab.Save(chainSel, cs.SerializeSolanaStateForAB(cs.RemoteChain, strconv.FormatUint(destination, 10)), deployment.NewTypeAndVersion(cs.RemoteChain, deployment.Version1_0_0))
if err != nil {
return fmt.Errorf("failed to save source chain state to address book: %w", err)
}

err = ab.Save(chainSel, destChainStatePDA.String(), cs.SerializeSolanaStateForAB(cs.RouterDest, strconv.FormatUint(destination, 10), deployment.Version1_0_0))
if err != nil {
return fmt.Errorf("failed to save dest chain state to address book: %w", err)
}
}

return nil
Expand Down Expand Up @@ -274,9 +269,8 @@ func SetOCR3ConfigSolana(e deployment.Environment, cfg cs.SetOCR3OffRampConfig)
// TODO: check if ocr3 has already been set
// set, err := isOCR3ConfigSetSolana(e.Logger, e.Chains[remote], state.Chains[remote].OffRamp, args)
var instructions []solana.Instruction
ccipRouterID := solChains[remote].Router
configPDA, _, _ := solState.FindConfigPDA(ccipRouterID)
routerStatePDA, _, _ := solState.FindStatePDA(ccipRouterID)
configPDA := solChains[remote].RouterConfigPDA
routerStatePDA := solChains[remote].RouterStatePDA
for _, arg := range args {
instruction, err := ccip_router.NewSetOcrConfigInstruction(
arg.OCRPluginType,
Expand Down
5 changes: 2 additions & 3 deletions deployment/ccip/changeset/solana/cs_chain_contracts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package solana_test
import (
"context"
"math/big"
"strconv"
"testing"

"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -81,14 +80,14 @@ func TestAddRemoteChain(t *testing.T) {
state, err = changeset.LoadOnchainStateSolana(tenv.Env)
require.NoError(t, err)
var sourceChainStateAccount solRouter.SourceChain
evmSourceChainStatePDA := state.SolChains[solChain].SourceChainStatePDAs[strconv.FormatUint(evmChain, 10)]
evmSourceChainStatePDA := state.SolChains[solChain].SourceChainStatePDAs[evmChain]
err = tenv.Env.SolChains[solChain].GetAccountDataBorshInto(ctx, evmSourceChainStatePDA, &sourceChainStateAccount)
require.NoError(t, err)
require.Equal(t, uint64(1), sourceChainStateAccount.State.MinSeqNr)
require.True(t, sourceChainStateAccount.Config.IsEnabled)

var destChainStateAccount solRouter.DestChain
evmDestChainStatePDA := state.SolChains[solChain].DestChainStatePDAs[strconv.FormatUint(evmChain, 10)]
evmDestChainStatePDA := state.SolChains[solChain].DestChainStatePDAs[evmChain]
err = tenv.Env.SolChains[solChain].GetAccountDataBorshInto(ctx, evmDestChainStatePDA, &destChainStateAccount)
require.NoError(t, err)
}
Expand Down
104 changes: 58 additions & 46 deletions deployment/ccip/changeset/solana_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package changeset
import (
"errors"
"fmt"
"strconv"
"strings"

"github.com/Masterminds/semver/v3"
"github.com/gagliardetto/solana-go"

solState "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/state"

"github.com/smartcontractkit/chainlink/deployment"
commontypes "github.com/smartcontractkit/chainlink/deployment/common/types"
)
Expand All @@ -18,23 +20,26 @@ var (
Receiver deployment.ContractType = "Receiver"
SPL2022Tokens deployment.ContractType = "SPL2022Tokens"
WSOL deployment.ContractType = "WSOL"
RouterSource deployment.ContractType = "RouterSource"
RouterDest deployment.ContractType = "RouterDest"
// for PDAs from AddRemoteChainToSolana
RemoteChain deployment.ContractType = "RemoteChain"
)

// SolChainState holds a Go binding for all the currently deployed CCIP programs
// on a chain. If a binding is nil, it means here is no such contract on the chain.
type SolCCIPChainState struct {
LinkToken solana.PublicKey
Router solana.PublicKey
Timelock solana.PublicKey
AddressLookupTable solana.PublicKey // for chain writer
Receiver solana.PublicKey // for tests only
SPL2022Tokens []solana.PublicKey
TokenPool solana.PublicKey
WSOL solana.PublicKey
SourceChainStatePDAs map[string]solana.PublicKey
DestChainStatePDAs map[string]solana.PublicKey
LinkToken solana.PublicKey
Router solana.PublicKey
Timelock solana.PublicKey
AddressLookupTable solana.PublicKey // for chain writer
Receiver solana.PublicKey // for tests only
SPL2022Tokens []solana.PublicKey
TokenPool solana.PublicKey
WSOL solana.PublicKey
// PDAs to avoid redundant lookups
RouterStatePDA solana.PublicKey
RouterConfigPDA solana.PublicKey
SourceChainStatePDAs map[uint64]solana.PublicKey
DestChainStatePDAs map[uint64]solana.PublicKey
}

func LoadOnchainStateSolana(e deployment.Environment) (CCIPOnChainState, error) {
Expand Down Expand Up @@ -62,68 +67,75 @@ func LoadOnchainStateSolana(e deployment.Environment) (CCIPOnChainState, error)
// LoadChainStateSolana Loads all state for a SolChain into state
func LoadChainStateSolana(chain deployment.SolChain, addresses map[string]deployment.TypeAndVersion) (SolCCIPChainState, error) {
state := SolCCIPChainState{
SourceChainStatePDAs: make(map[string]solana.PublicKey),
DestChainStatePDAs: make(map[string]solana.PublicKey),
SourceChainStatePDAs: make(map[uint64]solana.PublicKey),
DestChainStatePDAs: make(map[uint64]solana.PublicKey),
}
var spl2022Tokens []solana.PublicKey
var selectors []uint64
for address, tvStr := range addresses {
tstr := tvStr.String()
switch {
case strings.HasPrefix(tstr, string(RouterSource)):
fmt.Printf("RouterSource tvStr: %s", tstr)
suffix, err := DeserializeSolanaStateFromAB(tstr)
switch tvStr.String() {
case deployment.NewTypeAndVersion(commontypes.LinkToken, deployment.Version1_0_0).String():
pub := solana.MustPublicKeyFromBase58(address)
state.LinkToken = pub
case deployment.NewTypeAndVersion(Router, deployment.Version1_0_0).String():
pub := solana.MustPublicKeyFromBase58(address)
state.Router = pub
routerStatePDA, _, err := solState.FindStatePDA(state.Router)
if err != nil {
return state, err
}
pub := solana.MustPublicKeyFromBase58(address)
state.SourceChainStatePDAs[suffix] = pub
case strings.HasPrefix(tstr, string(RouterDest)):
fmt.Printf("RouterDest tvStr: %s", tstr)
suffix, err := DeserializeSolanaStateFromAB(tstr)
state.RouterStatePDA = routerStatePDA
routerConfigPDA, _, err := solState.FindConfigPDA(state.Router)
if err != nil {
return state, err
}
pub := solana.MustPublicKeyFromBase58(address)
state.DestChainStatePDAs[suffix] = pub
case tstr == deployment.NewTypeAndVersion(commontypes.LinkToken, deployment.Version1_0_0).String():
pub := solana.MustPublicKeyFromBase58(address)
state.LinkToken = pub
case tstr == deployment.NewTypeAndVersion(Router, deployment.Version1_0_0).String():
pub := solana.MustPublicKeyFromBase58(address)
state.Router = pub
case tstr == deployment.NewTypeAndVersion(AddressLookupTable, deployment.Version1_0_0).String():
state.RouterConfigPDA = routerConfigPDA
case deployment.NewTypeAndVersion(AddressLookupTable, deployment.Version1_0_0).String():
pub := solana.MustPublicKeyFromBase58(address)
state.AddressLookupTable = pub
case tstr == deployment.NewTypeAndVersion(Receiver, deployment.Version1_0_0).String():
case deployment.NewTypeAndVersion(Receiver, deployment.Version1_0_0).String():
pub := solana.MustPublicKeyFromBase58(address)
state.Receiver = pub
case tstr == deployment.NewTypeAndVersion(SPL2022Tokens, deployment.Version1_0_0).String():
case deployment.NewTypeAndVersion(SPL2022Tokens, deployment.Version1_0_0).String():
pub := solana.MustPublicKeyFromBase58(address)
spl2022Tokens = append(spl2022Tokens, pub)
case tstr == deployment.NewTypeAndVersion(TokenPool, deployment.Version1_0_0).String():
case deployment.NewTypeAndVersion(TokenPool, deployment.Version1_0_0).String():
pub := solana.MustPublicKeyFromBase58(address)
state.TokenPool = pub
case deployment.NewTypeAndVersion(RemoteChain, deployment.Version1_0_0).String():
selStr, err := DeserializeSolanaStateFromAB(address)
if err != nil {
return state, err
}
selector, err := strconv.ParseUint(selStr, 10, 64)
if err != nil {
return state, err
}
selectors = append(selectors, selector)
default:
return state, fmt.Errorf("unknown contract %s", tvStr)
}
}
// store PDAs
for _, selector := range selectors {
// safe to ignore error here, as we know the contract is deployed
// Need to initialize PDAs after all contracts are loaded, so router is set
state.SourceChainStatePDAs[selector], _ = solState.FindSourceChainStatePDA(selector, state.Router)
state.DestChainStatePDAs[selector], _ = solState.FindDestChainStatePDA(selector, state.Router)
}
state.WSOL = solana.SolMint
state.SPL2022Tokens = spl2022Tokens
return state, nil
}

func SerializeSolanaStateForAB(contractType deployment.ContractType, suffix string, deploymentVersion semver.Version) deployment.TypeAndVersion {
return deployment.NewTypeAndVersion(deployment.ContractType(string(contractType)+"_"+string(suffix)), deployment.Version1_0_0)
func SerializeSolanaStateForAB(contractType deployment.ContractType, suffix string) string {
return string(contractType) + "_" + suffix
}

func DeserializeSolanaStateFromAB(tvStr string) (string, error) {
tv, err := deployment.TypeAndVersionFromString(tvStr)
if err != nil {
return "", err
}
parts := strings.Split(string(tv.Type), "_")
func DeserializeSolanaStateFromAB(address string) (string, error) {
parts := strings.Split(address, "_")
if len(parts) != 2 {
return "", fmt.Errorf("invalid contract type: %s", tv.Type)
return "", fmt.Errorf("invalid address type: %s", address)
}
return parts[1], nil
}
5 changes: 3 additions & 2 deletions deployment/ccip/changeset/testhelpers/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -1385,14 +1385,15 @@ func ValidateSolanaState(t *testing.T, e deployment.Environment, solChainSelecto
// Validate addresses
require.False(t, chainState.LinkToken.IsZero(), "Link token address is zero for chain %d", sel)
require.False(t, chainState.Router.IsZero(), "Router address is zero for chain %d", sel)
require.False(t, chainState.RouterConfigPDA.IsZero(), "RouterConfigPDA is zero for chain %d", sel)
require.False(t, chainState.RouterStatePDA.IsZero(), "RouterStatePDA is zero for chain %d", sel)
require.False(t, chainState.AddressLookupTable.IsZero(), "Address lookup table is zero for chain %d", sel)

// Get router config
var routerConfigAccount solRouter.Config
configPDA, _, _ := solState.FindConfigPDA(chainState.Router)

// Check if account exists first
err = e.SolChains[sel].GetAccountDataBorshInto(testcontext.Get(t), configPDA, &routerConfigAccount)
err = e.SolChains[sel].GetAccountDataBorshInto(testcontext.Get(t), chainState.RouterConfigPDA, &routerConfigAccount)
require.NoError(t, err, "Failed to deserialize router config for chain %d", sel)
}
}
Expand Down

0 comments on commit ae4ab02

Please sign in to comment.