Skip to content

Commit

Permalink
Merge branch 'develop' into nonevm-984-reorg
Browse files Browse the repository at this point in the history
  • Loading branch information
Farber98 authored Jan 2, 2025
2 parents da1ee68 + 2e24ead commit 6c08a75
Show file tree
Hide file tree
Showing 32 changed files with 583 additions and 463 deletions.
2 changes: 1 addition & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ run:
linters:
enable:
- exhaustive
- exportloopref
- copyloopvar
- revive
- goimports
- gosec
Expand Down
126 changes: 72 additions & 54 deletions integration-tests/relayinterface/chain_components_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ package relayinterface
import (
"context"
"encoding/binary"
"encoding/json"
"io"
"os"
"path/filepath"
"sync"
"testing"
"time"

Expand All @@ -18,14 +20,16 @@ import (
"github.com/gagliardetto/solana-go/text"
"github.com/stretchr/testify/require"

"github.com/smartcontractkit/chainlink-common/pkg/codec"
commoncodec "github.com/smartcontractkit/chainlink-common/pkg/codec"
"github.com/smartcontractkit/chainlink-common/pkg/logger"
commontestutils "github.com/smartcontractkit/chainlink-common/pkg/loop/testutils"
"github.com/smartcontractkit/chainlink-common/pkg/types"
. "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint common practice to import test mods with .
"github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives"
"github.com/smartcontractkit/chainlink-common/pkg/utils/tests"

"github.com/smartcontractkit/chainlink-solana/pkg/solana/codec"

contract "github.com/smartcontractkit/chainlink-solana/contracts/generated/contract_reader_interface"
"github.com/smartcontractkit/chainlink-solana/integration-tests/solclient"
"github.com/smartcontractkit/chainlink-solana/integration-tests/utils"
Expand All @@ -36,9 +40,28 @@ import (

func TestChainComponents(t *testing.T) {
t.Parallel()
it := &SolanaChainComponentsInterfaceTester[*testing.T]{Helper: &helper{}}
it.Init(t)
helper := &helper{}
helper.Init(t)

t.Run("RunChainComponentsSolanaTests", func(t *testing.T) {
t.Parallel()
it := &SolanaChainComponentsInterfaceTester[*testing.T]{Helper: helper}
DisableTests(it)
it.Setup(t)
RunChainComponentsSolanaTests(t, it)
})

t.Run("RunChainComponentsInLoopSolanaTests", func(t *testing.T) {
t.Parallel()
it := &SolanaChainComponentsInterfaceTester[*testing.T]{Helper: helper}
DisableTests(it)
wrapped := commontestutils.WrapContractReaderTesterForLoop(it)
wrapped.Setup(t)
RunChainComponentsInLoopSolanaTests(t, wrapped)
})
}

func DisableTests(it *SolanaChainComponentsInterfaceTester[*testing.T]) {
it.DisableTests([]string{
// disable tests that set values
ContractReaderGetLatestValueBasedOnConfidenceLevel,
Expand Down Expand Up @@ -70,9 +93,6 @@ func TestChainComponents(t *testing.T) {
ContractReaderQueryKeysCanFilterWithValueComparator,
ContractReaderQueryKeysCanLimitResultsWithCursor,
})

RunChainComponentsSolanaTests(t, it)
RunChainComponentsInLoopSolanaTests(t, commontestutils.WrapContractReaderTesterForLoop(it))
}

func RunChainComponentsSolanaTests[T TestingT[T]](t T, it *SolanaChainComponentsInterfaceTester[T]) {
Expand All @@ -86,17 +106,17 @@ func RunChainComponentsInLoopSolanaTests[T TestingT[T]](t T, it ChainComponentsI
}

func RunContractReaderSolanaTests[T TestingT[T]](t T, it *SolanaChainComponentsInterfaceTester[T]) {
RunContractReaderInterfaceTests(t, it, false, false)
RunContractReaderInterfaceTests(t, it, false, true)

testCases := []Testcase[T]{}
var testCases []Testcase[T]

RunTests(t, it, testCases)
}

func RunContractReaderInLoopTests[T TestingT[T]](t T, it ChainComponentsInterfaceTester[T]) {
RunContractReaderInterfaceTests(t, it, false, false)
RunContractReaderInterfaceTests(t, it, false, true)

testCases := []Testcase[T]{}
var testCases []Testcase[T]

RunTests(t, it, testCases)
}
Expand All @@ -112,61 +132,47 @@ type SolanaChainComponentsInterfaceTesterHelper[T TestingT[T]] interface {

type SolanaChainComponentsInterfaceTester[T TestingT[T]] struct {
TestSelectionSupport
Helper SolanaChainComponentsInterfaceTesterHelper[T]
cr *chainreader.SolanaChainReaderService
chainReaderConfig config.ChainReader
accountPubKey solana.PublicKey
secondAccountPubKey solana.PublicKey
Helper SolanaChainComponentsInterfaceTesterHelper[T]
cr *chainreader.SolanaChainReaderService
contractReaderConfig config.ContractReader
}

func (it *SolanaChainComponentsInterfaceTester[T]) Setup(t T) {
t.Cleanup(func() {})

it.chainReaderConfig = config.ChainReader{
Namespaces: map[string]config.ChainReaderMethods{
it.contractReaderConfig = config.ContractReader{
Namespaces: map[string]config.ChainContractReader{
AnyContractName: {
Methods: map[string]config.ChainDataReader{
IDL: mustUnmarshalIDL(t, string(it.Helper.GetJSONEncodedIDL(t))),
Reads: map[string]config.ReadDefinition{
MethodReturningUint64: {
AnchorIDL: string(it.Helper.GetJSONEncodedIDL(t)),
Encoding: config.EncodingTypeBorsh,
Procedure: config.ChainReaderProcedure{
IDLAccount: "DataAccount",
OutputModifications: codec.ModifiersConfig{
&codec.PropertyExtractorConfig{FieldName: "U64Value"},
},
ChainSpecificName: "DataAccount",
ReadType: config.Account,
OutputModifications: commoncodec.ModifiersConfig{
&commoncodec.PropertyExtractorConfig{FieldName: "U64Value"},
},
},
MethodReturningUint64Slice: {
AnchorIDL: string(it.Helper.GetJSONEncodedIDL(t)),
Encoding: config.EncodingTypeBorsh,
Procedure: config.ChainReaderProcedure{
IDLAccount: "DataAccount",
OutputModifications: codec.ModifiersConfig{
&codec.PropertyExtractorConfig{FieldName: "U64Slice"},
},
ChainSpecificName: "DataAccount",
OutputModifications: commoncodec.ModifiersConfig{
&commoncodec.PropertyExtractorConfig{FieldName: "U64Slice"},
},
},
},
},
AnySecondContractName: {
Methods: map[string]config.ChainDataReader{
IDL: mustUnmarshalIDL(t, string(it.Helper.GetJSONEncodedIDL(t))),
Reads: map[string]config.ReadDefinition{
MethodReturningUint64: {
AnchorIDL: string(it.Helper.GetJSONEncodedIDL(t)),
Encoding: config.EncodingTypeBorsh,
Procedure: config.ChainReaderProcedure{
IDLAccount: "DataAccount",
OutputModifications: codec.ModifiersConfig{
&codec.PropertyExtractorConfig{FieldName: "U64Value"},
},
ChainSpecificName: "DataAccount",
OutputModifications: commoncodec.ModifiersConfig{
&commoncodec.PropertyExtractorConfig{FieldName: "U64Value"},
},
},
},
},
},
}

it.accountPubKey = it.Helper.CreateAccount(t, AnyValueToReadWithoutAnArgument)
it.secondAccountPubKey = it.Helper.CreateAccount(t, AnyDifferentValueToReadWithoutAnArgument)
}

func (it *SolanaChainComponentsInterfaceTester[T]) Name() string {
Expand All @@ -187,7 +193,7 @@ func (it *SolanaChainComponentsInterfaceTester[T]) GetContractReader(t T) types.
return it.cr
}

svc, err := chainreader.NewChainReaderService(it.Helper.Logger(t), it.Helper.RPCClient(), it.chainReaderConfig)
svc, err := chainreader.NewChainReaderService(it.Helper.Logger(t), it.Helper.RPCClient(), it.contractReaderConfig)

require.NoError(t, err)
require.NoError(t, svc.Start(ctx))
Expand All @@ -202,10 +208,10 @@ func (it *SolanaChainComponentsInterfaceTester[T]) GetContractWriter(t T) types.
}

func (it *SolanaChainComponentsInterfaceTester[T]) GetBindings(t T) []types.BoundContract {
// at the moment, use only a single account address for everything
// Create a new account with fresh state for each test
return []types.BoundContract{
{Name: AnyContractName, Address: it.accountPubKey.String()},
{Name: AnySecondContractName, Address: it.secondAccountPubKey.String()},
{Name: AnyContractName, Address: it.Helper.CreateAccount(t, AnyValueToReadWithoutAnArgument).String()},
{Name: AnySecondContractName, Address: it.Helper.CreateAccount(t, AnyDifferentValueToReadWithoutAnArgument).String()},
}
}

Expand All @@ -219,10 +225,6 @@ func (it *SolanaChainComponentsInterfaceTester[T]) GenerateBlocksTillConfidenceL

}

func (it *SolanaChainComponentsInterfaceTester[T]) Init(t T) {
it.Helper.Init(t)
}

type helper struct {
programID solana.PublicKey
rpcURL string
Expand All @@ -231,6 +233,7 @@ type helper struct {
wsClient *ws.Client
idlBts []byte
nonce uint64
nonceMu sync.Mutex
}

func (h *helper) Init(t *testing.T) {
Expand Down Expand Up @@ -292,10 +295,14 @@ func (h *helper) GetJSONEncodedIDL(t *testing.T) []byte {
func (h *helper) CreateAccount(t *testing.T, value uint64) solana.PublicKey {
t.Helper()

// avoid collisions in parallel tests
h.nonceMu.Lock()
h.nonce++
nonce := h.nonce
h.nonceMu.Unlock()

bts := make([]byte, 8)
binary.LittleEndian.PutUint64(bts, h.nonce*value)
binary.LittleEndian.PutUint64(bts, nonce*value)

pubKey, _, err := solana.FindProgramAddress([][]byte{[]byte("data"), bts}, h.programID)
require.NoError(t, err)
Expand All @@ -304,7 +311,7 @@ func (h *helper) CreateAccount(t *testing.T, value uint64) solana.PublicKey {
privateKey, err := solana.PrivateKeyFromBase58(solclient.DefaultPrivateKeysSolValidator[1])
require.NoError(t, err)

h.runInitialize(t, value, pubKey, func(key solana.PublicKey) *solana.PrivateKey {
h.runInitialize(t, nonce, value, pubKey, func(key solana.PublicKey) *solana.PrivateKey {
return &privateKey
}, privateKey.PublicKey())

Expand All @@ -313,14 +320,15 @@ func (h *helper) CreateAccount(t *testing.T, value uint64) solana.PublicKey {

func (h *helper) runInitialize(
t *testing.T,
nonce uint64,
value uint64,
data solana.PublicKey,
signerFunc func(key solana.PublicKey) *solana.PrivateKey,
payer solana.PublicKey,
) {
t.Helper()

inst, err := contract.NewInitializeInstruction(h.nonce*value, value, data, payer, solana.SystemProgramID).ValidateAndBuild()
inst, err := contract.NewInitializeInstruction(nonce*value, value, data, payer, solana.SystemProgramID).ValidateAndBuild()
require.NoError(t, err)

h.sendInstruction(t, inst, signerFunc, payer)
Expand Down Expand Up @@ -409,3 +417,13 @@ func setupTestValidator(t *testing.T, upgradeAuthority string) (string, string)

return client.SetupLocalSolNodeWithFlags(t, flags...)
}

func mustUnmarshalIDL[T TestingT[T]](t T, rawIDL string) codec.IDL {
var idl codec.IDL
if err := json.Unmarshal([]byte(rawIDL), &idl); err != nil {
t.Errorf("failed to unmarshal test IDL", err)
t.FailNow()
}

return idl
}
1 change: 0 additions & 1 deletion integration-tests/smoke/ocr2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ func TestSolanaOCRV2Smoke(t *testing.T) {
t.Fatal(err)
}

test := test
t.Run(test.name, func(t *testing.T) {
t.Parallel()
_, sg := startOCR2DataFeedsSmokeTest(t, test.name, test.env, config, "")
Expand Down
1 change: 0 additions & 1 deletion integration-tests/soak/ocr2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ func TestSolanaOCRV2Soak(t *testing.T) {
t.Fatal(err)
}

test := test
t.Run(test.name, func(t *testing.T) {
t.Parallel()

Expand Down
2 changes: 0 additions & 2 deletions integration-tests/solclient/deployer.go
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,6 @@ func (c *ContractDeployer) DeployAnchorProgramsRemote(contractsDir string, env *
log.Debug().Interface("Binaries", contractBinaries).Msg("Program binaries")
g := errgroup.Group{}
for _, bin := range contractBinaries {
bin := bin
g.Go(func() error {
return c.DeployProgramRemote(bin, env)
})
Expand All @@ -519,7 +518,6 @@ func (c *ContractDeployer) DeployAnchorProgramsRemoteDocker(baseDir, subDir stri
log.Info().Interface("Binaries", contractBinaries).Msg(fmt.Sprintf("Program binaries [%s]", filepath.Join("programs", subDir)))
g := errgroup.Group{}
for _, bin := range contractBinaries {
bin := bin
g.Go(func() error {
return c.DeployProgramRemoteLocal(filepath.Join(subDir, bin), sol, programIDBuilder)
})
Expand Down
2 changes: 1 addition & 1 deletion integration-tests/testconfig/default.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ inside_k8 = false
network = "localnet"
user = "default"
stateful_db = false
devnet_image = "anzaxyz/agave:v2.0.20"
devnet_image = "anzaxyz/agave:v2.0.21"

[OCR2]
node_count = 6
Expand Down
30 changes: 16 additions & 14 deletions pkg/solana/chainreader/account_read_binding.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,32 @@ import (
"context"

"github.com/gagliardetto/solana-go"
"github.com/gagliardetto/solana-go/rpc"

"github.com/smartcontractkit/chainlink-common/pkg/types"

"github.com/smartcontractkit/chainlink-solana/pkg/solana/codec"
)

// accountReadBinding provides decoding and reading Solana Account data using a defined codec. The
// `idlAccount` refers to the account name in the IDL for which the codec has a type mapping.
// accountReadBinding provides decoding and reading Solana Account data using a defined codec.
type accountReadBinding struct {
idlAccount string
codec types.RemoteCodec
key solana.PublicKey
opts *rpc.GetAccountInfoOpts
namespace, genericName string
codec types.RemoteCodec
key solana.PublicKey
}

func newAccountReadBinding(acct string, codec types.RemoteCodec, opts *rpc.GetAccountInfoOpts) *accountReadBinding {
func newAccountReadBinding(namespace, genericName string) *accountReadBinding {
return &accountReadBinding{
idlAccount: acct,
codec: codec,
opts: opts,
namespace: namespace,
genericName: genericName,
}
}

var _ readBinding = &accountReadBinding{}

func (b *accountReadBinding) SetCodec(codec types.RemoteCodec) {
b.codec = codec
}

func (b *accountReadBinding) SetAddress(key solana.PublicKey) {
b.key = key
}
Expand All @@ -36,10 +38,10 @@ func (b *accountReadBinding) GetAddress() solana.PublicKey {
return b.key
}

func (b *accountReadBinding) CreateType(_ bool) (any, error) {
return b.codec.CreateType(b.idlAccount, false)
func (b *accountReadBinding) CreateType(forEncoding bool) (any, error) {
return b.codec.CreateType(codec.WrapItemType(forEncoding, b.namespace, b.genericName, codec.ChainConfigTypeAccountDef), forEncoding)
}

func (b *accountReadBinding) Decode(ctx context.Context, bts []byte, outVal any) error {
return b.codec.Decode(ctx, bts, outVal, b.idlAccount)
return b.codec.Decode(ctx, bts, outVal, codec.WrapItemType(false, b.namespace, b.genericName, codec.ChainConfigTypeAccountDef))
}
1 change: 0 additions & 1 deletion pkg/solana/chainreader/batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ func doMethodBatchCall(ctx context.Context, client MultipleAccountGetter, bindin
results[idx].err,
binding.Decode(ctx, data[idx], results[idx].returnVal),
)

continue
}

Expand Down
Loading

0 comments on commit 6c08a75

Please sign in to comment.