Skip to content

Commit

Permalink
feat(solana): implement solana's SetConfig (#209)
Browse files Browse the repository at this point in the history
Implement the `Configurer` component and associated `SetConfig` method
in the `sdk.solana` package.

It closely follows the reference "set config" integration test provided
by the `chainlink-ccip` repository. Unlike the EVM implementation,
Solana's set config requires multiple blockchain calls because the list
of signers must be sent using multiple onchain calls:

* `InitializeSigners()`
* `for each batch { AppendSigners(batch) }`
* `FinalizeSigners()`

And only then:
* `SetConfig()`

This PR adds an e2e test for the SetConfig call and additionally
reorganizes the folder layout, splitting evm and solana tests into their
own subfolders.

<!-- DON'T DELETE. add your comments above llm generated contents -->
  • Loading branch information
gustavogama-cll authored Jan 9, 2025
1 parent d316c57 commit a71dd79
Show file tree
Hide file tree
Showing 34 changed files with 1,392 additions and 101 deletions.
5 changes: 5 additions & 0 deletions .changeset/hot-colts-grab.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@smartcontractkit/mcms": minor
---

Add the `Configurer` component and `SetConfig` call to the Solana SDK.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ go.work.sum

# env file
e2e/custom_configs/.env
e2e/artifacts/

# Editor config directories
.idea/
Expand Down
8 changes: 7 additions & 1 deletion .mockery.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,15 @@ packages:
github.com/smartcontractkit/mcms/sdk:
github.com/smartcontractkit/mcms/sdk/evm:
github.com/smartcontractkit/mcms/sdk/evm/bindings:
github.com/gagliardetto/solana-go/rpc:
interfaces:
JSONRPCClient:
config:
dir: "./sdk/solana/mocks"
filename: "jsonrpcclient.go"

# Required to fix the following deprecation warning:
# https://vektra.github.io/mockery/v2.48/deprecations/#issue-845-fix
#
# This is a temporary fix until the issue is resolved mockery v3.
issue-845-fix: True
issue-845-fix: True
7 changes: 4 additions & 3 deletions e2e/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ private_keys = [
]

[solana_config]
chain_id = "EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG"
chain_id = "EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG" # devnet chain id; fixme: figure out how to use local solana-test-validator
port = "8999"
type = "solana"
public_key ="9n1pyVGGo6V4mpiSDMVay5As9NurEkY283wwRk1Kto2C"
# to run this locally replace with the path to the contracts directory
#contracts_dir = "/Users/ggoh/work/mcms/e2e/artifacts/solana"

[solana_config.out]
family = "solana"

[solana_config.solana_programs]
mcm = "6UmMZr5MEqiKWD5jqTJd1WCR5kT8oZuFYBLJFi1o6GQX"
15 changes: 8 additions & 7 deletions e2e/tests/executable_test.go → e2e/tests/evm/executable.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//go:build e2e
// +build e2e

package e2e
package e2e_evm

import (
"context"
Expand All @@ -16,6 +16,7 @@ import (
cselectors "github.com/smartcontractkit/chain-selectors"

"github.com/smartcontractkit/mcms"
e2e "github.com/smartcontractkit/mcms/e2e/tests"
testutils "github.com/smartcontractkit/mcms/e2e/utils"
"github.com/smartcontractkit/mcms/sdk"
"github.com/smartcontractkit/mcms/sdk/evm"
Expand All @@ -32,12 +33,12 @@ type ExecutionTestSuite struct {
signerAddresses []common.Address
auth *bind.TransactOpts
timelockContract *bindings.RBACTimelock
TestSetup
e2e.TestSetup
}

// SetupSuite runs before the test suite
func (s *ExecutionTestSuite) SetupSuite() {
s.TestSetup = *InitializeSharedTestSetup(s.T())
s.TestSetup = *e2e.InitializeSharedTestSetup(s.T())
// Get deployer's private key
privateKeyHex := s.Settings.PrivateKeys[0]
privateKey, err := crypto.HexToECDSA(privateKeyHex[2:]) // Strip "0x" prefix
Expand Down Expand Up @@ -118,8 +119,8 @@ func (s *ExecutionTestSuite) TestExecuteProposal() {
ctx := context.Background()
opts := &bind.CallOpts{
Context: ctx,
From: s.auth.From, // Set the "from" address (optional)
BlockNumber: nil, // Use the latest block (nil by default)
From: s.auth.From, // Set the "from" address (optional)
BlockNumber: nil, // Use the latest block (nil by default)
}
// Construct example transaction
role, err := s.timelockContract.PROPOSERROLE(&bind.CallOpts{})
Expand Down Expand Up @@ -243,8 +244,8 @@ func (s *ExecutionTestSuite) TestExecuteProposalMultiple() {
ctx := context.Background()
opts := &bind.CallOpts{
Context: ctx,
From: s.auth.From, // Set the "from" address (optional)
BlockNumber: nil, // Use the latest block (nil by default)
From: s.auth.From, // Set the "from" address (optional)
BlockNumber: nil, // Use the latest block (nil by default)
}
// Construct example transaction
role, err := s.timelockContract.PROPOSERROLE(&bind.CallOpts{})
Expand Down
7 changes: 4 additions & 3 deletions e2e/tests/inspection_test.go → e2e/tests/evm/inspection.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//go:build e2e
// +build e2e

package e2e
package e2e_evm

import (
"context"
Expand All @@ -13,6 +13,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/suite"

e2e "github.com/smartcontractkit/mcms/e2e/tests"
testutils "github.com/smartcontractkit/mcms/e2e/utils"
"github.com/smartcontractkit/mcms/sdk/evm"
"github.com/smartcontractkit/mcms/sdk/evm/bindings"
Expand All @@ -25,12 +26,12 @@ type InspectionTestSuite struct {
deployerKey common.Address
signerAddresses []common.Address
auth *bind.TransactOpts
TestSetup
e2e.TestSetup
}

// SetupSuite runs before the test suite
func (s *InspectionTestSuite) SetupSuite() {
s.TestSetup = *InitializeSharedTestSetup(s.T())
s.TestSetup = *e2e.InitializeSharedTestSetup(s.T())

// Get deployer's private key
privateKeyHex := s.Settings.PrivateKeys[0]
Expand Down
7 changes: 4 additions & 3 deletions e2e/tests/set_root_test.go → e2e/tests/evm/set_root.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//go:build e2e
// +build e2e

package e2e
package e2e_evm

import (
"context"
Expand All @@ -16,6 +16,7 @@ import (
"github.com/stretchr/testify/suite"

"github.com/smartcontractkit/mcms"
e2e "github.com/smartcontractkit/mcms/e2e/tests"
testutils "github.com/smartcontractkit/mcms/e2e/utils"
"github.com/smartcontractkit/mcms/sdk"
"github.com/smartcontractkit/mcms/sdk/evm"
Expand All @@ -32,12 +33,12 @@ type SetRootTestSuite struct {
auth *bind.TransactOpts
timelockContract *bindings.RBACTimelock
chainSelector mcmtypes.ChainSelector
TestSetup
e2e.TestSetup
}

// SetupSuite runs before the test suite
func (s *SetRootTestSuite) SetupSuite() {
s.TestSetup = *InitializeSharedTestSetup(s.T())
s.TestSetup = *e2e.InitializeSharedTestSetup(s.T())
// Get deployer's private key
privateKeyHex := s.Settings.PrivateKeys[0]
privateKey, err := crypto.HexToECDSA(privateKeyHex[2:]) // Strip "0x" prefix
Expand Down
7 changes: 4 additions & 3 deletions e2e/tests/signing_test.go → e2e/tests/evm/signing.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//go:build e2e
// +build e2e

package e2e
package e2e_evm

import (
"encoding/json"
Expand All @@ -14,6 +14,7 @@ import (
"github.com/stretchr/testify/suite"

"github.com/smartcontractkit/mcms"
e2e "github.com/smartcontractkit/mcms/e2e/tests"
testutils "github.com/smartcontractkit/mcms/e2e/utils"
"github.com/smartcontractkit/mcms/sdk"
"github.com/smartcontractkit/mcms/sdk/evm"
Expand All @@ -23,15 +24,15 @@ import (
// SigningTestSuite tests signing a proposal and converting back to a file
type SigningTestSuite struct {
suite.Suite
TestSetup
e2e.TestSetup

client *ethclient.Client
chainSelector mcmtypes.ChainSelector
}

// SetupSuite runs before the test suite
func (s *SigningTestSuite) SetupSuite() {
s.TestSetup = *InitializeSharedTestSetup(s.T())
s.TestSetup = *e2e.InitializeSharedTestSetup(s.T())

chainDetails, err := cselectors.GetChainDetailsByChainIDAndFamily(s.BlockchainA.Out.ChainID, s.BlockchainA.Out.Family)
s.Require().NoError(err)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//go:build e2e
// +build e2e

package e2e
package e2e_evm

import (
"context"
Expand All @@ -15,6 +15,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/suite"

e2e "github.com/smartcontractkit/mcms/e2e/tests"
testutils "github.com/smartcontractkit/mcms/e2e/utils"
"github.com/smartcontractkit/mcms/sdk/evm"
"github.com/smartcontractkit/mcms/sdk/evm/bindings"
Expand All @@ -28,7 +29,7 @@ type TimelockInspectionTestSuite struct {
auth *bind.TransactOpts
publicKey common.Address
timelockContract *bindings.RBACTimelock
TestSetup
e2e.TestSetup
}

func (s *TimelockInspectionTestSuite) granRole(role [32]byte, address common.Address) {
Expand All @@ -45,7 +46,7 @@ func (s *TimelockInspectionTestSuite) granRole(role [32]byte, address common.Add

// SetupSuite runs before the test suite
func (s *TimelockInspectionTestSuite) SetupSuite() {
s.TestSetup = *InitializeSharedTestSetup(s.T())
s.TestSetup = *e2e.InitializeSharedTestSetup(s.T())
// Get deployer's private key
privateKeyHex := s.Settings.PrivateKeys[0]
privateKey, err := crypto.HexToECDSA(privateKeyHex[2:]) // Strip "0x" prefix
Expand Down
26 changes: 14 additions & 12 deletions e2e/tests/runner_test.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
//go:build e2e
// +build e2e

package e2e

//go:generate ./compile-mcm-solana.sh
package e2e_test

import (
"testing"

"github.com/stretchr/testify/suite"

"github.com/smartcontractkit/mcms/e2e/tests/evm"
"github.com/smartcontractkit/mcms/e2e/tests/solana"
)

// Run the test suite
func TestE2ESuite(t *testing.T) {
t.Parallel()
func TestEVMSuite(t *testing.T) {
suite.Run(t, new(e2e_evm.InspectionTestSuite))
suite.Run(t, new(e2e_evm.ExecutionTestSuite))
suite.Run(t, new(e2e_evm.TimelockInspectionTestSuite))
suite.Run(t, new(e2e_evm.SetRootTestSuite))
suite.Run(t, new(e2e_evm.SigningTestSuite))
}

suite.Run(t, new(TimelockInspectionTestSuite))
suite.Run(t, new(InspectionTestSuite))
suite.Run(t, new(ExecutionTestSuite))
suite.Run(t, new(SetRootTestSuite))
suite.Run(t, new(SigningTestSuite))
suite.Run(t, new(SolanaInspectionTestSuite))
//go:generate ./solana/compile-mcm-contracts.sh
func TestSolanaSuite(t *testing.T) {
suite.Run(t, new(e2e_solana.SolanaTestSuite))
}
13 changes: 8 additions & 5 deletions e2e/tests/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package e2e
import (
"context"
"os"
"path/filepath"
"runtime"
"strings"
"sync"
"testing"
Expand All @@ -17,8 +19,10 @@ import (

// Shared test setup
var (
sharedSetup *TestSetup
setupOnce sync.Once
sharedSetup *TestSetup
setupOnce sync.Once
_, fileName, _, _ = runtime.Caller(0)
ProjectRoot = filepath.Dir(filepath.Dir(filepath.Dir(fileName)))
)

// Config defines the blockchain configuration
Expand Down Expand Up @@ -91,9 +95,8 @@ func InitializeSharedTestSetup(t *testing.T) *TestSetup {
var solanaWsClient *ws.Client
var solanaBlockChainOutput *blockchain.Output
if in.SolanaChain != nil {
// provide the contracts dir if running in CI
if len(in.SolanaChain.ContractsDir) == 0 && os.Getenv("CI") == "true" {
in.SolanaChain.ContractsDir = "/home/runner/work/mcms/mcms/e2e/artifacts/solana"
if in.SolanaChain.ContractsDir == "" {
in.SolanaChain.ContractsDir = filepath.Join(ProjectRoot, "/e2e/artifacts/solana")
}

// Initialize Solana client
Expand Down
Loading

0 comments on commit a71dd79

Please sign in to comment.