diff --git a/go.mod b/go.mod index 63b90f20a..602265192 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/smartcontractkit/chainlink-ccip v0.0.0-20250128162345-af4c8fd4481a github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250128162345-af4c8fd4481a github.com/smartcontractkit/chainlink-common v0.4.2-0.20250127125541-a8fa42cc0f36 - github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250121205514-f73e2f86c23b + github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250203183025-939526523893 github.com/smartcontractkit/libocr v0.0.0-20241223215956-e5b78d8e3919 github.com/stretchr/testify v1.10.0 go.uber.org/zap v1.27.0 diff --git a/go.sum b/go.sum index 6116fab5c..038a893d8 100644 --- a/go.sum +++ b/go.sum @@ -581,8 +581,8 @@ github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250128162345-a github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250128162345-af4c8fd4481a/go.mod h1:Bmwq4lNb5tE47sydN0TKetcLEGbgl+VxHEWp4S0LI60= github.com/smartcontractkit/chainlink-common v0.4.2-0.20250127125541-a8fa42cc0f36 h1:dytZPggag6auyzmbhpIDmkHu7KrflIBEhLLec4/xFIk= github.com/smartcontractkit/chainlink-common v0.4.2-0.20250127125541-a8fa42cc0f36/go.mod h1:Z2e1ynSJ4pg83b4Qldbmryc5lmnrI3ojOdg1FUloa68= -github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250121205514-f73e2f86c23b h1:TO1pwFeQKDOmv3loFiLJvYhtymuTgQUw9WgtwK1rueg= -github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250121205514-f73e2f86c23b/go.mod h1:4JqpgFy01LaqG1yM2iFTzwX3ZgcAvW9WdstBZQgPHzU= +github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250203183025-939526523893 h1:hQEEpKrWRqZ//SkA/m1G5puVHK1mYhZzturgX7VsPhk= +github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250203183025-939526523893/go.mod h1:4JqpgFy01LaqG1yM2iFTzwX3ZgcAvW9WdstBZQgPHzU= 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-20241223215956-e5b78d8e3919 h1:IpGoPTXpvllN38kT2z2j13sifJMz4nbHglidvop7mfg= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index a0c085341..00029bc56 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -348,7 +348,7 @@ require ( github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250121195549-294ec6a40b92 // indirect - github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250121205514-f73e2f86c23b // indirect + github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250203183025-939526523893 // indirect github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 // indirect github.com/smartcontractkit/chainlink-protos/svr v0.0.0-20250123084029-58cce9b32112 // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20250117224137-afdcdd75070d // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 3d5778d8e..a62706f8a 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1241,8 +1241,8 @@ github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6An github.com/smartcontractkit/chainlink-feeds v0.1.1/go.mod h1:55EZ94HlKCfAsUiKUTNI7QlE/3d3IwTlsU3YNa/nBb4= github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250121195549-294ec6a40b92 h1:lJi0dWfgNJl4Um5KzeZZPVBi//CPDfzzeVmv4Z2OGNY= github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250121195549-294ec6a40b92/go.mod h1:tHem58EihQh63kR2LlAOKDAs9Vbghf1dJKZRGy6LG8g= -github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250121205514-f73e2f86c23b h1:TO1pwFeQKDOmv3loFiLJvYhtymuTgQUw9WgtwK1rueg= -github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250121205514-f73e2f86c23b/go.mod h1:4JqpgFy01LaqG1yM2iFTzwX3ZgcAvW9WdstBZQgPHzU= +github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250203183025-939526523893 h1:hQEEpKrWRqZ//SkA/m1G5puVHK1mYhZzturgX7VsPhk= +github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250203183025-939526523893/go.mod h1:4JqpgFy01LaqG1yM2iFTzwX3ZgcAvW9WdstBZQgPHzU= github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 h1:ZBat8EBvE2LpSQR9U1gEbRV6PfAkiFdINmQ8nVnXIAQ= github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= github.com/smartcontractkit/chainlink-protos/svr v0.0.0-20250123084029-58cce9b32112 h1:c77Gi/APraqwbBO8fbd/5JY2wW+MSIpYg8Uma9MEZFE= diff --git a/pkg/solana/chain.go b/pkg/solana/chain.go index 5f5f63646..ba9f367af 100644 --- a/pkg/solana/chain.go +++ b/pkg/solana/chain.go @@ -109,7 +109,7 @@ type chain struct { // if multiNode is enabled, the clientCache will not be used multiNode *mn.MultiNode[mn.StringID, *client.MultiNodeClient] - txSender *mn.TransactionSender[*solanago.Transaction, *client.SendTxResult, mn.StringID, *client.MultiNodeClient] + txSender *mn.TransactionSender[*solanago.Transaction, solanago.Signature, mn.StringID, *client.MultiNodeClient] multiClient *client.MultiClient // tracking node chain id for verification @@ -297,12 +297,14 @@ func newChain(id string, cfg *config.TOMLConfig, ks core.Keystore, lggr logger.L mnCfg.DeathDeclarationDelay(), ) - txSender := mn.NewTransactionSender[*solanago.Transaction, *client.SendTxResult, mn.StringID, *client.MultiNodeClient]( + txSender := mn.NewTransactionSender[*solanago.Transaction, solanago.Signature, mn.StringID, *client.MultiNodeClient]( lggr, mn.StringID(id), chainFamily, multiNode, - client.NewSendTxResult, + func(err error) mn.SendTxReturnCode { + return client.ClassifySendError(nil, err) + }, 0, // use the default value provided by the implementation ) @@ -314,11 +316,8 @@ func newChain(id string, cfg *config.TOMLConfig, ks core.Keystore, lggr logger.L // Send tx using MultiNode transaction sender sendTx = func(ctx context.Context, tx *solanago.Transaction) (solanago.Signature, error) { - result := ch.txSender.SendTransaction(ctx, tx) - if result == nil { - return solanago.Signature{}, errors.New("tx sender returned nil result") - } - return result.Signature(), result.Error() + sig, _, err := ch.txSender.SendTransaction(ctx, tx) + return sig, err } tc = internal.NewLoader[client.ReaderWriter](func() (client.ReaderWriter, error) { return ch.multiNode.SelectRPC() }) diff --git a/pkg/solana/chain_test.go b/pkg/solana/chain_test.go index df51c313f..2e3157844 100644 --- a/pkg/solana/chain_test.go +++ b/pkg/solana/chain_test.go @@ -436,11 +436,10 @@ func TestChain_MultiNode_TransactionSender(t *testing.T) { t.Run("successful transaction", func(t *testing.T) { // Send tx using transaction sender - result := c.txSender.SendTransaction(ctx, createTx(sender, receiver)) - require.NotNil(t, result) - require.NoError(t, result.Error()) - require.Equal(t, mn.Successful, result.Code()) - require.NotEmpty(t, result.Signature()) + sig, code, err := c.txSender.SendTransaction(ctx, createTx(sender, receiver)) + require.NoError(t, err) + require.Equal(t, mn.Successful, code) + require.NotEmpty(t, sig) }) t.Run("unsigned transaction error", func(t *testing.T) { @@ -468,19 +467,17 @@ func TestChain_MultiNode_TransactionSender(t *testing.T) { } // Send tx using transaction sender - result := c.txSender.SendTransaction(ctx, unsignedTx(receiver.PublicKey())) - require.NotNil(t, result) - require.Error(t, result.Error()) - require.Equal(t, mn.Fatal, result.Code()) - require.Empty(t, result.Signature()) + sig, code, err := c.txSender.SendTransaction(ctx, unsignedTx(receiver.PublicKey())) + require.Error(t, err) + require.Equal(t, mn.Fatal, code) + require.Empty(t, sig) }) t.Run("empty transaction", func(t *testing.T) { - result := c.txSender.SendTransaction(ctx, &solana.Transaction{}) - require.NotNil(t, result) - require.Error(t, result.Error()) - require.Equal(t, mn.Fatal, result.Code()) - require.Empty(t, result.Signature()) + sig, code, err := c.txSender.SendTransaction(ctx, &solana.Transaction{}) + require.Error(t, err) + require.Equal(t, mn.Fatal, code) + require.Empty(t, sig) }) } diff --git a/pkg/solana/client/multinode_client.go b/pkg/solana/client/multinode_client.go index b97525044..ac772677c 100644 --- a/pkg/solana/client/multinode_client.go +++ b/pkg/solana/client/multinode_client.go @@ -10,6 +10,7 @@ import ( "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/rpc" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" mn "github.com/smartcontractkit/chainlink-framework/multinode" @@ -36,12 +37,17 @@ func (h *Head) BlockDifficulty() *big.Int { return nil } +func (h *Head) GetTotalDifficulty() *big.Int { + // Not relevant for Solana + return nil +} + func (h *Head) IsValid() bool { return h != nil && h.BlockHeight != nil && *h.BlockHeight > 0 && h.BlockHash != nil } var _ mn.RPCClient[mn.StringID, *Head] = (*MultiNodeClient)(nil) -var _ mn.SendTxRPCClient[*solana.Transaction, *SendTxResult] = (*MultiNodeClient)(nil) +var _ mn.SendTxRPCClient[*solana.Transaction, solana.Signature] = (*MultiNodeClient)(nil) type MultiNodeClient struct { Client @@ -108,7 +114,7 @@ func (m *MultiNodeClient) SubscribeToHeads(ctx context.Context) (<-chan *Head, m } timeout := pollInterval poller, channel := mn.NewPoller[*Head](pollInterval, func(pollRequestCtx context.Context) (*Head, error) { - if mn.CtxIsHeathCheckRequest(ctx) { + if mn.CtxIsHealthCheckRequest(ctx) { pollRequestCtx = mn.CtxAddHealthCheckFlag(pollRequestCtx) } return m.LatestBlock(pollRequestCtx) @@ -137,7 +143,7 @@ func (m *MultiNodeClient) SubscribeToFinalizedHeads(ctx context.Context) (<-chan } timeout := finalizedBlockPollInterval poller, channel := mn.NewPoller[*Head](finalizedBlockPollInterval, func(pollRequestCtx context.Context) (*Head, error) { - if mn.CtxIsHeathCheckRequest(ctx) { + if mn.CtxIsHealthCheckRequest(ctx) { pollRequestCtx = mn.CtxAddHealthCheckFlag(pollRequestCtx) } return m.LatestFinalizedBlock(pollRequestCtx) @@ -205,7 +211,7 @@ func (m *MultiNodeClient) onNewHead(ctx context.Context, requestCh <-chan struct m.chainInfoLock.Lock() defer m.chainInfoLock.Unlock() - if !mn.CtxIsHeathCheckRequest(ctx) { + if !mn.CtxIsHealthCheckRequest(ctx) { m.highestUserObservations.BlockNumber = max(m.highestUserObservations.BlockNumber, head.BlockNumber()) } select { @@ -222,7 +228,7 @@ func (m *MultiNodeClient) onNewFinalizedHead(ctx context.Context, requestCh <-ch } m.chainInfoLock.Lock() defer m.chainInfoLock.Unlock() - if !mn.CtxIsHeathCheckRequest(ctx) { + if !mn.CtxIsHealthCheckRequest(ctx) { m.highestUserObservations.FinalizedBlockNumber = max(m.highestUserObservations.FinalizedBlockNumber, head.BlockNumber()) } select { @@ -319,37 +325,7 @@ func (m *MultiNodeClient) GetInterceptedChainInfo() (latest, highestUserObservat return m.latestChainInfo, m.highestUserObservations } -type SendTxResult struct { - err error - code mn.SendTxReturnCode - sig solana.Signature -} - -var _ mn.SendTxResult = (*SendTxResult)(nil) - -func NewSendTxResult(err error) *SendTxResult { - result := &SendTxResult{ - err: err, - } - result.code = ClassifySendError(nil, err) - return result -} - -func (r *SendTxResult) Error() error { - return r.err -} - -func (r *SendTxResult) Code() mn.SendTxReturnCode { - return r.code -} - -func (r *SendTxResult) Signature() solana.Signature { - return r.sig -} - -func (m *MultiNodeClient) SendTransaction(ctx context.Context, tx *solana.Transaction) *SendTxResult { - var sendTxResult = &SendTxResult{} - sendTxResult.sig, sendTxResult.err = m.SendTx(ctx, tx) - sendTxResult.code = ClassifySendError(tx, sendTxResult.err) - return sendTxResult +func (m *MultiNodeClient) SendTransaction(ctx context.Context, tx *solana.Transaction) (solana.Signature, mn.SendTxReturnCode, error) { + sig, err := m.SendTx(ctx, tx) + return sig, ClassifySendError(tx, err), err }