From 0cadb537b727ba134c32fb21818b969d1ede96f8 Mon Sep 17 00:00:00 2001 From: "app-token-issuer-infra-releng[bot]" <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com> Date: Thu, 5 Dec 2024 11:02:36 +0000 Subject: [PATCH 1/5] [automated] bump solana image to v2.0.18 (#955) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Jonghyeon Park --- integration-tests/testconfig/default.toml | 2 +- scripts/install-solana-ci.sh | 2 +- scripts/setup-localnet/localnet.sh | 2 +- solana.nix | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/integration-tests/testconfig/default.toml b/integration-tests/testconfig/default.toml index 8ab8f166b..55711bd86 100644 --- a/integration-tests/testconfig/default.toml +++ b/integration-tests/testconfig/default.toml @@ -38,7 +38,7 @@ inside_k8 = false network = "localnet" user = "default" stateful_db = false -devnet_image = "anzaxyz/agave:v2.0.17" +devnet_image = "anzaxyz/agave:v2.0.18" [OCR2] node_count = 6 diff --git a/scripts/install-solana-ci.sh b/scripts/install-solana-ci.sh index c80d17797..762d3f37c 100755 --- a/scripts/install-solana-ci.sh +++ b/scripts/install-solana-ci.sh @@ -2,5 +2,5 @@ set -euxo pipefail -sh -c "$(curl -sSfL https://release.anza.xyz/v2.0.17/install)" +sh -c "$(curl -sSfL https://release.anza.xyz/v2.0.18/install)" echo "PATH=$HOME/.local/share/solana/install/active_release/bin:$PATH" >> $GITHUB_ENV diff --git a/scripts/setup-localnet/localnet.sh b/scripts/setup-localnet/localnet.sh index c0e2d4061..ac83d0d8e 100755 --- a/scripts/setup-localnet/localnet.sh +++ b/scripts/setup-localnet/localnet.sh @@ -6,7 +6,7 @@ cpu_struct="linux"; # Clean up first bash "$(dirname -- "$0";)/localnet.down.sh" -container_version=v2.0.17 +container_version=v2.0.18 container_name="chainlink-solana.test-validator" echo "Starting $container_name@$container_version" diff --git a/solana.nix b/solana.nix index d8a780931..50ab2229f 100644 --- a/solana.nix +++ b/solana.nix @@ -5,7 +5,7 @@ # Solana integration let - version = "v2.0.17"; + version = "v2.0.18"; getBinDerivation = { name, @@ -37,14 +37,14 @@ let name = "solana-cli-x86_64-linux"; filename = "solana-release-x86_64-unknown-linux-gnu.tar.bz2"; ### BEGIN_LINUX_SHA256 ### - sha256 = "sha256-6+whUT3WZqkRV5Xl8SSzrsMjhoOfKcQxJWqpR6SbyAc="; + sha256 = "sha256-3FW6IMZeDtyU4GTsRIwT9BFLNzLPEuP+oiQdur7P13s="; ### END_LINUX_SHA256 ### }; aarch64-apple-darwin = getBinDerivation { name = "solana-cli-aarch64-apple-darwin"; filename = "solana-release-aarch64-apple-darwin.tar.bz2"; ### BEGIN_DARWIN_SHA256 ### - sha256 = "sha256-rcc/e9BvEQXVaS1Jl4f58jVmLMKoAJCQGR+lEiYxwpY="; + sha256 = "sha256-6VjycYU0NU0evXoqtGAZMYGHQEKijofnFQnBJNVsb6Q="; ### END_DARWIN_SHA256 ### }; }; From 75e06e64bcc7eef0932e92b04b593618f8b24020 Mon Sep 17 00:00:00 2001 From: Aaron Lu <50029043+aalu1418@users.noreply.github.com> Date: Thu, 5 Dec 2024 10:07:02 -0700 Subject: [PATCH 2/5] fix: add chainlink/deployment bump to updater workflow (#961) --- integration-tests/go.mod | 10 +++++----- integration-tests/go.sum | 16 ++++++++-------- scripts/update-e2e.sh | 4 +++- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 1c2332792..0c5efbd92 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -15,12 +15,12 @@ require ( github.com/pelletier/go-toml/v2 v2.2.3 github.com/rs/zerolog v1.33.0 github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4 - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241127210503-88cca3779525 - github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.17 + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99 + github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18 github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9 - github.com/smartcontractkit/chainlink/deployment v0.0.0-20241127192805-54ea74a13bfe - github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20241204033247-732cc15aa87d - github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241204033247-732cc15aa87d + github.com/smartcontractkit/chainlink/deployment v0.0.0-20241205144849-138d4c51ad0d + github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20241205144849-138d4c51ad0d + github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241205144849-138d4c51ad0d github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.34.0 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 59b3a9d3f..2dda62636 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1429,20 +1429,20 @@ github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2 h1:onBe3DqNrbtO github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 h1:tNS7U9lrxkFvEuyxQv11HHOiV9LPDGC9wYEy+yM/Jv4= github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8/go.mod h1:EBrEgcdIbwepqguClkv8Ohy7CbyWSJaE4EC9aBJlQK0= -github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.17 h1:Fw2F8fKa5QdOUzLAj6Y/EB6XFC0QtK2pw5bqQSatL4A= -github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.17/go.mod h1:NwmlNKqrb02v4Sci4b5KW644nfH2BW+FrKbWwTN5r6M= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18 h1:a3xetGZh2nFO1iX5xd9OuqiCkgbWLvW6fTN6fgVubPo= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18/go.mod h1:NwmlNKqrb02v4Sci4b5KW644nfH2BW+FrKbWwTN5r6M= github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 h1:VIxK8u0Jd0Q/VuhmsNm6Bls6Tb31H/sA3A/rbc5hnhg= github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0/go.mod h1:lyAu+oMXdNUzEDScj2DXB2IueY+SDXPPfyl/kb63tMM= github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9 h1:yB1x5UXvpZNka+5h57yo1/GrKfXKCqMzChCISpldZx4= github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9/go.mod h1:lJk0atEJ5Zyo3Tqrmf1Pl9jUEe79EgDb9bD3K5OTUBI= github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 h1:7bCdbTUWzyczQg+kwHCxlx6y07zE8HNB8+ntTne6qd8= github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2/go.mod h1:MltlNu3jcXm/DyLN98I5TFNtu/o1NNAcaPAFKMXWk70= -github.com/smartcontractkit/chainlink/deployment v0.0.0-20241127192805-54ea74a13bfe h1:jUS49b8OODR6552wqvzNBMXHwgXV7iPZmz9lmESTsto= -github.com/smartcontractkit/chainlink/deployment v0.0.0-20241127192805-54ea74a13bfe/go.mod h1:ueUOL11tGBu1TTonZcIeD6/3av2iZE5AydxtclG8Dvo= -github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20241204033247-732cc15aa87d h1:vV41ofCA5TGaHpoD2UHiN/VAR8xRqycWw4Fy75pXQj8= -github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20241204033247-732cc15aa87d/go.mod h1:xCJuze3GgG6Ec/gLMAS/47FC/SzEa/Y+YiD5g4wvYTM= -github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241204033247-732cc15aa87d h1:W5f72PgRWg1ChYQBcwBZosrypWSwx7ShQNx3TKi7rwI= -github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241204033247-732cc15aa87d/go.mod h1:ofC2S3XuOMdqEew73eCNmV7jgWxayBayuEOLELR1CBM= +github.com/smartcontractkit/chainlink/deployment v0.0.0-20241205144849-138d4c51ad0d h1:nxjwsxk3qZOEFuoYJN9a61xBvwkFZLNMv24Z9QjYlnE= +github.com/smartcontractkit/chainlink/deployment v0.0.0-20241205144849-138d4c51ad0d/go.mod h1:jz4/Ko0lL7fhiuiBsVB53MNX2lEWK0VRfsxz232XRGA= +github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20241205144849-138d4c51ad0d h1:Sl3/QHSA91H9nSaAVo9biKRpqIfWTKcGAKbCoWO6jr8= +github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20241205144849-138d4c51ad0d/go.mod h1:iRiKHT+MfvjrIuJuO/cGuWBxULctmlz2DFD3KDDU7oI= +github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241205144849-138d4c51ad0d h1:YSHlmOAuZvaBmjhENcLuyaDRy6+CcVqvsy6bF30Ovxw= +github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241205144849-138d4c51ad0d/go.mod h1:r2inuDnmNVZzUD/AsqgBs9exi9mIYwg8BgAnT+PyXU4= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 h1:NzZGjaqez21I3DU7objl3xExTH4fxYvzTqar8DC6360= diff --git a/scripts/update-e2e.sh b/scripts/update-e2e.sh index 33198d5df..c1c4186fe 100755 --- a/scripts/update-e2e.sh +++ b/scripts/update-e2e.sh @@ -6,7 +6,9 @@ SHA=$(curl https://api.github.com/repos/smartcontractkit/chainlink/commits/devel echo "Chainlink Develop Commit: $SHA" # update dependencies +export GOPRIVATE=github.com/smartcontractkit/chainlink go get github.com/smartcontractkit/chainlink/integration-tests@$SHA -go mod tidy || echo -e "------\nInitial go mod tidy failed - will update chainlink dep and try tidy again\n------" +go mod tidy || echo -e "------\nInitial go mod tidy failed - will update chainlink + deployment dep and try tidy again\n------" go get github.com/smartcontractkit/chainlink/v2@$SHA +go get github.com/smartcontractkit/chainlink/deployment@$SHA go mod tidy From f7ecca855f8656712b779b37768950cc6b454db4 Mon Sep 17 00:00:00 2001 From: Dylan Tinianov Date: Thu, 5 Dec 2024 13:11:25 -0500 Subject: [PATCH 3/5] Update Solana Client for LogPoller (#933) * Add required methods * Add GetBlocks * Add GetBlocks method --- pkg/solana/client/client.go | 53 +++++++ pkg/solana/client/client_test.go | 46 ++++++ pkg/solana/client/mocks/reader_writer.go | 180 +++++++++++++++++++++++ 3 files changed, 279 insertions(+) diff --git a/pkg/solana/client/client.go b/pkg/solana/client/client.go index f9f6715b0..a015fdc1f 100644 --- a/pkg/solana/client/client.go +++ b/pkg/solana/client/client.go @@ -36,8 +36,11 @@ type Reader interface { ChainID(ctx context.Context) (mn.StringID, error) GetFeeForMessage(ctx context.Context, msg string) (uint64, error) GetLatestBlock(ctx context.Context) (*rpc.GetBlockResult, error) + GetTransaction(ctx context.Context, txHash solana.Signature, opts *rpc.GetTransactionOpts) (*rpc.GetTransactionResult, error) + GetBlocks(ctx context.Context, startSlot uint64, endSlot *uint64) (rpc.BlocksResult, error) GetBlocksWithLimit(ctx context.Context, startSlot uint64, limit uint64) (*rpc.BlocksResult, error) GetBlock(ctx context.Context, slot uint64) (*rpc.GetBlockResult, error) + GetSignaturesForAddressWithOpts(ctx context.Context, addr solana.PublicKey, opts *rpc.GetSignaturesForAddressOpts) ([]*rpc.TransactionSignature, error) } // AccountReader is an interface that allows users to pass either the solana rpc client or the relay client @@ -121,6 +124,43 @@ func (c *Client) SlotHeightWithCommitment(ctx context.Context, commitment rpc.Co return v.(uint64), err } +func (c *Client) GetSignaturesForAddressWithOpts(ctx context.Context, addr solana.PublicKey, opts *rpc.GetSignaturesForAddressOpts) ([]*rpc.TransactionSignature, error) { + done := c.latency("signatures_for_address") + defer done() + + ctx, cancel := context.WithTimeout(ctx, c.contextDuration) + defer cancel() + if opts == nil { + opts = &rpc.GetSignaturesForAddressOpts{} + } + if opts.Commitment == "" { + opts.Commitment = c.commitment + } + return c.rpc.GetSignaturesForAddressWithOpts(ctx, addr, opts) +} + +func (c *Client) GetTransaction(ctx context.Context, txHash solana.Signature, opts *rpc.GetTransactionOpts) (*rpc.GetTransactionResult, error) { + done := c.latency("transaction") + defer done() + + ctx, cancel := context.WithTimeout(ctx, c.contextDuration) + defer cancel() + + if opts == nil { + opts = &rpc.GetTransactionOpts{ + Encoding: solana.EncodingBase64, + } + } + if opts.Commitment == "" { + opts.Commitment = c.commitment + } + + v, err, _ := c.requestGroup.Do("GetTransaction", func() (interface{}, error) { + return c.rpc.GetTransaction(ctx, txHash, opts) + }) + return v.(*rpc.GetTransactionResult), err +} + func (c *Client) GetAccountInfoWithOpts(ctx context.Context, addr solana.PublicKey, opts *rpc.GetAccountInfoOpts) (*rpc.GetAccountInfoResult, error) { done := c.latency("account_info") defer done() @@ -131,6 +171,19 @@ func (c *Client) GetAccountInfoWithOpts(ctx context.Context, addr solana.PublicK return c.rpc.GetAccountInfoWithOpts(ctx, addr, opts) } +func (c *Client) GetBlocks(ctx context.Context, startSlot uint64, endSlot *uint64) (out rpc.BlocksResult, err error) { + done := c.latency("blocks") + defer done() + + ctx, cancel := context.WithTimeout(ctx, c.contextDuration) + defer cancel() + + v, err, _ := c.requestGroup.Do("GetBlocks", func() (interface{}, error) { + return c.rpc.GetBlocks(ctx, startSlot, endSlot, c.commitment) + }) + return v.(rpc.BlocksResult), err +} + func (c *Client) LatestBlockhash(ctx context.Context) (*rpc.GetLatestBlockhashResult, error) { done := c.latency("latest_blockhash") defer done() diff --git a/pkg/solana/client/client_test.go b/pkg/solana/client/client_test.go index ceb94035e..20b67ac8d 100644 --- a/pkg/solana/client/client_test.go +++ b/pkg/solana/client/client_test.go @@ -242,6 +242,52 @@ func TestClient_Writer_Integration(t *testing.T) { assert.Nil(t, statuses[0].Err) assert.NotNil(t, statuses[1].Err) + + getTxResult, err := c.GetTransaction(ctx, sigSuccess, nil) + assert.NoError(t, err) + assert.NotNil(t, getTxResult) + + sigs, err := c.GetSignaturesForAddressWithOpts(ctx, pubKey, nil) + assert.NoError(t, err) + requiredSigs := map[solana.Signature]bool{ + sigSuccess: false, + sigFail: false, + } + for _, sig := range sigs { + if _, required := requiredSigs[sig.Signature]; required { + requiredSigs[sig.Signature] = true + } + } + require.True(t, requiredSigs[sigSuccess] && requiredSigs[sigFail]) +} + +func TestClient_GetBlocks(t *testing.T) { + url := SetupLocalSolNode(t) + privKey, err := solana.NewRandomPrivateKey() + require.NoError(t, err) + pubKey := privKey.PublicKey() + FundTestAccounts(t, []solana.PublicKey{pubKey}, url) + + requestTimeout := 5 * time.Second + lggr := logger.Test(t) + cfg := config.NewDefault() + + ctx := tests.Context(t) + c, err := NewClient(url, cfg, requestTimeout, lggr) + require.NoError(t, err) + + // Verify we can retrieve blocks + startSlot := uint64(1) + endSlot := uint64(6) + require.Eventually(t, + func() bool { + blocks, err := c.GetBlocks(ctx, startSlot, &endSlot) + if err != nil { + return false + } + return len(blocks) == 5 + }, + requestTimeout, 500*time.Millisecond) } func TestClient_SendTxDuplicates_Integration(t *testing.T) { diff --git a/pkg/solana/client/mocks/reader_writer.go b/pkg/solana/client/mocks/reader_writer.go index 86285fdf5..c64a4a9ad 100644 --- a/pkg/solana/client/mocks/reader_writer.go +++ b/pkg/solana/client/mocks/reader_writer.go @@ -257,6 +257,66 @@ func (_c *ReaderWriter_GetBlock_Call) RunAndReturn(run func(context.Context, uin return _c } +// GetBlocks provides a mock function with given fields: ctx, startSlot, endSlot +func (_m *ReaderWriter) GetBlocks(ctx context.Context, startSlot uint64, endSlot *uint64) (rpc.BlocksResult, error) { + ret := _m.Called(ctx, startSlot, endSlot) + + if len(ret) == 0 { + panic("no return value specified for GetBlocks") + } + + var r0 rpc.BlocksResult + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, *uint64) (rpc.BlocksResult, error)); ok { + return rf(ctx, startSlot, endSlot) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, *uint64) rpc.BlocksResult); ok { + r0 = rf(ctx, startSlot, endSlot) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(rpc.BlocksResult) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, *uint64) error); ok { + r1 = rf(ctx, startSlot, endSlot) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ReaderWriter_GetBlocks_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetBlocks' +type ReaderWriter_GetBlocks_Call struct { + *mock.Call +} + +// GetBlocks is a helper method to define mock.On call +// - ctx context.Context +// - startSlot uint64 +// - endSlot *uint64 +func (_e *ReaderWriter_Expecter) GetBlocks(ctx interface{}, startSlot interface{}, endSlot interface{}) *ReaderWriter_GetBlocks_Call { + return &ReaderWriter_GetBlocks_Call{Call: _e.mock.On("GetBlocks", ctx, startSlot, endSlot)} +} + +func (_c *ReaderWriter_GetBlocks_Call) Run(run func(ctx context.Context, startSlot uint64, endSlot *uint64)) *ReaderWriter_GetBlocks_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint64), args[2].(*uint64)) + }) + return _c +} + +func (_c *ReaderWriter_GetBlocks_Call) Return(_a0 rpc.BlocksResult, _a1 error) *ReaderWriter_GetBlocks_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ReaderWriter_GetBlocks_Call) RunAndReturn(run func(context.Context, uint64, *uint64) (rpc.BlocksResult, error)) *ReaderWriter_GetBlocks_Call { + _c.Call.Return(run) + return _c +} + // GetBlocksWithLimit provides a mock function with given fields: ctx, startSlot, limit func (_m *ReaderWriter) GetBlocksWithLimit(ctx context.Context, startSlot uint64, limit uint64) (*rpc.BlocksResult, error) { ret := _m.Called(ctx, startSlot, limit) @@ -432,6 +492,126 @@ func (_c *ReaderWriter_GetLatestBlock_Call) RunAndReturn(run func(context.Contex return _c } +// GetSignaturesForAddressWithOpts provides a mock function with given fields: ctx, addr, opts +func (_m *ReaderWriter) GetSignaturesForAddressWithOpts(ctx context.Context, addr solana.PublicKey, opts *rpc.GetSignaturesForAddressOpts) ([]*rpc.TransactionSignature, error) { + ret := _m.Called(ctx, addr, opts) + + if len(ret) == 0 { + panic("no return value specified for GetSignaturesForAddressWithOpts") + } + + var r0 []*rpc.TransactionSignature + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, solana.PublicKey, *rpc.GetSignaturesForAddressOpts) ([]*rpc.TransactionSignature, error)); ok { + return rf(ctx, addr, opts) + } + if rf, ok := ret.Get(0).(func(context.Context, solana.PublicKey, *rpc.GetSignaturesForAddressOpts) []*rpc.TransactionSignature); ok { + r0 = rf(ctx, addr, opts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*rpc.TransactionSignature) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, solana.PublicKey, *rpc.GetSignaturesForAddressOpts) error); ok { + r1 = rf(ctx, addr, opts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ReaderWriter_GetSignaturesForAddressWithOpts_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSignaturesForAddressWithOpts' +type ReaderWriter_GetSignaturesForAddressWithOpts_Call struct { + *mock.Call +} + +// GetSignaturesForAddressWithOpts is a helper method to define mock.On call +// - ctx context.Context +// - addr solana.PublicKey +// - opts *rpc.GetSignaturesForAddressOpts +func (_e *ReaderWriter_Expecter) GetSignaturesForAddressWithOpts(ctx interface{}, addr interface{}, opts interface{}) *ReaderWriter_GetSignaturesForAddressWithOpts_Call { + return &ReaderWriter_GetSignaturesForAddressWithOpts_Call{Call: _e.mock.On("GetSignaturesForAddressWithOpts", ctx, addr, opts)} +} + +func (_c *ReaderWriter_GetSignaturesForAddressWithOpts_Call) Run(run func(ctx context.Context, addr solana.PublicKey, opts *rpc.GetSignaturesForAddressOpts)) *ReaderWriter_GetSignaturesForAddressWithOpts_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(solana.PublicKey), args[2].(*rpc.GetSignaturesForAddressOpts)) + }) + return _c +} + +func (_c *ReaderWriter_GetSignaturesForAddressWithOpts_Call) Return(_a0 []*rpc.TransactionSignature, _a1 error) *ReaderWriter_GetSignaturesForAddressWithOpts_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ReaderWriter_GetSignaturesForAddressWithOpts_Call) RunAndReturn(run func(context.Context, solana.PublicKey, *rpc.GetSignaturesForAddressOpts) ([]*rpc.TransactionSignature, error)) *ReaderWriter_GetSignaturesForAddressWithOpts_Call { + _c.Call.Return(run) + return _c +} + +// GetTransaction provides a mock function with given fields: ctx, txHash, opts +func (_m *ReaderWriter) GetTransaction(ctx context.Context, txHash solana.Signature, opts *rpc.GetTransactionOpts) (*rpc.GetTransactionResult, error) { + ret := _m.Called(ctx, txHash, opts) + + if len(ret) == 0 { + panic("no return value specified for GetTransaction") + } + + var r0 *rpc.GetTransactionResult + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, solana.Signature, *rpc.GetTransactionOpts) (*rpc.GetTransactionResult, error)); ok { + return rf(ctx, txHash, opts) + } + if rf, ok := ret.Get(0).(func(context.Context, solana.Signature, *rpc.GetTransactionOpts) *rpc.GetTransactionResult); ok { + r0 = rf(ctx, txHash, opts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*rpc.GetTransactionResult) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, solana.Signature, *rpc.GetTransactionOpts) error); ok { + r1 = rf(ctx, txHash, opts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ReaderWriter_GetTransaction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTransaction' +type ReaderWriter_GetTransaction_Call struct { + *mock.Call +} + +// GetTransaction is a helper method to define mock.On call +// - ctx context.Context +// - txHash solana.Signature +// - opts *rpc.GetTransactionOpts +func (_e *ReaderWriter_Expecter) GetTransaction(ctx interface{}, txHash interface{}, opts interface{}) *ReaderWriter_GetTransaction_Call { + return &ReaderWriter_GetTransaction_Call{Call: _e.mock.On("GetTransaction", ctx, txHash, opts)} +} + +func (_c *ReaderWriter_GetTransaction_Call) Run(run func(ctx context.Context, txHash solana.Signature, opts *rpc.GetTransactionOpts)) *ReaderWriter_GetTransaction_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(solana.Signature), args[2].(*rpc.GetTransactionOpts)) + }) + return _c +} + +func (_c *ReaderWriter_GetTransaction_Call) Return(_a0 *rpc.GetTransactionResult, _a1 error) *ReaderWriter_GetTransaction_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ReaderWriter_GetTransaction_Call) RunAndReturn(run func(context.Context, solana.Signature, *rpc.GetTransactionOpts) (*rpc.GetTransactionResult, error)) *ReaderWriter_GetTransaction_Call { + _c.Call.Return(run) + return _c +} + // LatestBlockhash provides a mock function with given fields: ctx func (_m *ReaderWriter) LatestBlockhash(ctx context.Context) (*rpc.GetLatestBlockhashResult, error) { ret := _m.Called(ctx) From 77c427565dd5d21e9631a6dff212c795dcf76ed8 Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Fri, 6 Dec 2024 18:48:18 +0100 Subject: [PATCH 4/5] [TT-1806] add required chain.link labels to k8s soak test (#944) * add required chain.link labels to k8s soak test * tagged CTF + team input in the soak workflow * add missing import * fix compilation * fix CL version in go.mod * add missing var to e2e tests * use chainlink & integration-tests commit from develop branch * fix: add chainlink/deployment bump to updater workflow (#961) * Update Solana Client for LogPoller (#933) * Add required methods * Add GetBlocks * Add GetBlocks method --------- Co-authored-by: Aaron Lu <50029043+aalu1418@users.noreply.github.com> Co-authored-by: Dylan Tinianov --- .github/workflows/e2e_custom_cl.yml | 5 +++++ .github/workflows/e2e_testnet_daily.yml | 7 ++++++- .github/workflows/soak.yml | 9 ++++++++- integration-tests/common/common.go | 14 ++++++++++++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/.github/workflows/e2e_custom_cl.yml b/.github/workflows/e2e_custom_cl.yml index 55e8dc316..a32244438 100644 --- a/.github/workflows/e2e_custom_cl.yml +++ b/.github/workflows/e2e_custom_cl.yml @@ -8,6 +8,10 @@ on: required: true default: develop type: string + team: + description: Team to run the tests for (e.g. BIX, CCIP) + required: true + type: string env: CL_ECR: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink @@ -335,6 +339,7 @@ jobs: env: E2E_TEST_CHAINLINK_IMAGE: ${{ env.CL_ECR }} E2E_TEST_SOLANA_SECRET: thisisatestingonlysecret + CHAINLINK_USER_TEAM: ${{ github.event.inputs.team || 'BIX' }} e2e_program_upgrade_tests: name: E2E Program Upgrade Tests diff --git a/.github/workflows/e2e_testnet_daily.yml b/.github/workflows/e2e_testnet_daily.yml index 918737aca..6b6245635 100644 --- a/.github/workflows/e2e_testnet_daily.yml +++ b/.github/workflows/e2e_testnet_daily.yml @@ -11,6 +11,10 @@ on: description: 'Key to run tests with custom test secrets like ws url, rpc url, private key, etc.' required: false type: string + team: + description: Team to run the tests for (e.g. BIX, CCIP) + required: true + type: string schedule: - cron: '0 6 * * *' # Only run 1 of this workflow at a time per PR @@ -175,4 +179,5 @@ jobs: E2E_TEST_COMMON_PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }} # default private key E2E_TEST_COMMON_RPC_URL: https://api.devnet.solana.com # default url E2E_TEST_COMMON_WS_URL: https://api.devnet.solana.com # default url - E2E_TEST_SOLANA_SECRET: thisisatestingonlysecret \ No newline at end of file + E2E_TEST_SOLANA_SECRET: thisisatestingonlysecret + CHAINLINK_USER_TEAM: ${{ github.event.inputs.team || 'BIX' }} \ No newline at end of file diff --git a/.github/workflows/soak.yml b/.github/workflows/soak.yml index da9c1f93c..921a6872c 100644 --- a/.github/workflows/soak.yml +++ b/.github/workflows/soak.yml @@ -19,6 +19,11 @@ on: default: develop required: true type: string + team: + description: Team to run the tests for (e.g. BIX, CCIP) + required: true + type: string + default: BIX env: CL_ECR: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink CONTRACT_ARTIFACTS_PATH: contracts/target/deploy @@ -41,6 +46,7 @@ jobs: e2e_custom_build_artifacts: name: E2E Custom Build Artifacts environment: integration + runs-on: ubuntu-latest permissions: id-token: write contents: read @@ -116,4 +122,5 @@ jobs: cache_key_id: solana-e2e-${{ env.MOD_CACHE_VERSION }} cache_restore_only: "false" env: - E2E_TEST_SOLANA_SECRET: thisisatestingonlysecret \ No newline at end of file + E2E_TEST_SOLANA_SECRET: thisisatestingonlysecret + CHAINLINK_USER_TEAM: ${{ inputs.team }} \ No newline at end of file diff --git a/integration-tests/common/common.go b/integration-tests/common/common.go index 558f2bb47..bf0887c4d 100644 --- a/integration-tests/common/common.go +++ b/integration-tests/common/common.go @@ -384,10 +384,24 @@ func BuildNodeContractPairID(node *client.ChainlinkClient, ocr2Addr string) (str } func (c *Common) Default(t *testing.T, namespacePrefix string) (*Common, error) { + productName := "data-feedsv2.0" + nsLabels, err := environment.GetRequiredChainLinkNamespaceLabels(productName, "soak") + if err != nil { + return nil, err + } + + workloadPodLabels, err := environment.GetRequiredChainLinkWorkloadAndPodLabels(productName, "soak") + if err != nil { + return nil, err + } + c.TestEnvDetails.K8Config = &environment.Config{ NamespacePrefix: fmt.Sprintf("solana-%s", namespacePrefix), TTL: c.TestEnvDetails.TestDuration, Test: t, + Labels: nsLabels, + WorkloadLabels: workloadPodLabels, + PodLabels: workloadPodLabels, } if *c.TestConfig.Common.InsideK8s { From 1357aa026176c196063f6665c239fea814198557 Mon Sep 17 00:00:00 2001 From: Aaron Lu <50029043+aalu1418@users.noreply.github.com> Date: Tue, 10 Dec 2024 08:41:21 -0700 Subject: [PATCH 5/5] fix: handle compute unit + lookup tables, and improve flaky tests (#965) * fix: handle compute unit + lookup tables, and improve flaky tests * more complex: multiple instructions + multiple indices --- pkg/solana/client/client_test.go | 8 ++--- pkg/solana/fees/computebudget.go | 11 ++++++ pkg/solana/fees/computebudget_test.go | 50 +++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 5 deletions(-) diff --git a/pkg/solana/client/client_test.go b/pkg/solana/client/client_test.go index 20b67ac8d..8149b0839 100644 --- a/pkg/solana/client/client_test.go +++ b/pkg/solana/client/client_test.go @@ -278,14 +278,12 @@ func TestClient_GetBlocks(t *testing.T) { // Verify we can retrieve blocks startSlot := uint64(1) - endSlot := uint64(6) + endSlot := uint64(10) require.Eventually(t, func() bool { blocks, err := c.GetBlocks(ctx, startSlot, &endSlot) - if err != nil { - return false - } - return len(blocks) == 5 + require.NoError(t, err) // don't mask error within false + return len(blocks) >= 2 // slots != blocks (expect multiple blocks for 10 slots) }, requestTimeout, 500*time.Millisecond) } diff --git a/pkg/solana/fees/computebudget.go b/pkg/solana/fees/computebudget.go index aa21c1105..4fd7ab808 100644 --- a/pkg/solana/fees/computebudget.go +++ b/pkg/solana/fees/computebudget.go @@ -151,6 +151,17 @@ func set(tx *solana.Transaction, baseData instruction, appendToFront bool) error // https://github.com/gagliardetto/solana-go/blob/618f56666078f8131a384ab27afd918d248c08b7/transaction.go#L293 tx.Message.Header.NumReadonlyUnsignedAccounts++ + + // lookup table addresses are indexed after the tx.Message.AccountKeys + // higher indices must be increased + // https://github.com/gagliardetto/solana-go/blob/da2193071f56059aa35010a239cece016c4e827f/transaction.go#L440 + for i, ix := range tx.Message.Instructions { + for j, v := range ix.Accounts { + if int(v) >= programIdx { + tx.Message.Instructions[i].Accounts[j]++ + } + } + } } // get instruction data diff --git a/pkg/solana/fees/computebudget_test.go b/pkg/solana/fees/computebudget_test.go index c5cacabd4..a6cba383b 100644 --- a/pkg/solana/fees/computebudget_test.go +++ b/pkg/solana/fees/computebudget_test.go @@ -6,6 +6,7 @@ import ( "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/programs/system" + "github.com/gagliardetto/solana-go/programs/token" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -136,6 +137,55 @@ func testSet[V instruction](t *testing.T, builder func(uint) V, setter func(*sol assert.NoError(t, err) assert.Equal(t, data, []byte(tx.Message.Instructions[computeIndex].Data)) }) + + t.Run("with_lookuptables", func(t *testing.T) { + t.Parallel() + + // build base tx (no fee) + tx, err := solana.NewTransaction([]solana.Instruction{ + system.NewTransferInstruction( + 1, + solana.PublicKey{1}, + solana.PublicKey{2}, + ).Build(), + token.NewTransferInstruction( + uint64(1), + solana.PublicKey{11}, + solana.PublicKey{12}, + solana.PublicKey{13}, + []solana.PublicKey{ + solana.PublicKey{14}, + }, + ).Build(), + }, + solana.Hash{}, + solana.TransactionAddressTables(map[solana.PublicKey]solana.PublicKeySlice{ + solana.PublicKey{}: solana.PublicKeySlice{solana.PublicKey{1}, solana.PublicKey{2}, solana.PublicKey{11}, solana.PublicKey{12}, solana.PublicKey{13}, solana.PublicKey{14}}, + }), + ) + require.NoError(t, err) + + // check current account indices + assert.Equal(t, 2, len(tx.Message.Instructions)) + assert.Equal(t, []uint16{0, 4}, tx.Message.Instructions[0].Accounts) + assert.Equal(t, []uint16{5, 6, 7, 1}, tx.Message.Instructions[1].Accounts) + assert.Equal(t, 4, len(tx.Message.AccountKeys)) + + // add fee + require.NoError(t, setter(tx, builder(0))) + + // evaluate + assert.Equal(t, 3, len(tx.Message.Instructions)) + computeUnitIndex := getIndex(len(tx.Message.Instructions)) + transferIndex := 0 + if computeUnitIndex == transferIndex { + transferIndex = 1 + } + assert.Equal(t, 5, len(tx.Message.AccountKeys)) + assert.Equal(t, uint16(4), tx.Message.Instructions[computeUnitIndex].ProgramIDIndex) + assert.Equal(t, []uint16{0, 5}, tx.Message.Instructions[transferIndex].Accounts) + assert.Equal(t, []uint16{6, 7, 8, 1}, tx.Message.Instructions[transferIndex+1].Accounts) + }) } func TestParse(t *testing.T) {