Skip to content

Commit

Permalink
pkg/solana: bump multinode; update tx sender
Browse files Browse the repository at this point in the history
  • Loading branch information
jmank88 committed Feb 3, 2025
1 parent 2425295 commit 388fc96
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 67 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down
2 changes: 1 addition & 1 deletion integration-tests/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions integration-tests/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down
15 changes: 7 additions & 8 deletions pkg/solana/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
)

Expand All @@ -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() })
Expand Down
27 changes: 12 additions & 15 deletions pkg/solana/chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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)
})
}

Expand Down
52 changes: 14 additions & 38 deletions pkg/solana/client/multinode_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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
}

0 comments on commit 388fc96

Please sign in to comment.