Skip to content

Commit

Permalink
Broadcast transactions only to a single healthy RPC instead of all (#…
Browse files Browse the repository at this point in the history
…14635)

* Broadcast transactions only to a single healthy RPC instead of all healthy RPCs to avoid redundant relay fees on Hedera

* fix tx test
  • Loading branch information
dhaidashenko authored Oct 4, 2024
1 parent f905a4b commit ee1d6e3
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/three-otters-drum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink": patch
---

Hedera chain type: broadcast transactions only to a single healthy RPC instead of all healthy RPCs to avoid redundant relay fees. #changed
15 changes: 15 additions & 0 deletions core/chains/evm/client/chain_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,14 @@ func (c *chainClient) BatchCallContext(ctx context.Context, b []rpc.BatchElem) e

// Similar to BatchCallContext, ensure the provided BatchElem slice is passed through
func (c *chainClient) BatchCallContextAll(ctx context.Context, b []rpc.BatchElem) error {
if c.chainType == chaintype.ChainHedera {
activeRPC, err := c.multiNode.SelectNodeRPC()
if err != nil {
return err
}

return activeRPC.BatchCallContext(ctx, b)
}
return c.multiNode.BatchCallContextAll(ctx, b)
}

Expand Down Expand Up @@ -291,6 +299,13 @@ func (c *chainClient) PendingNonceAt(ctx context.Context, account common.Address
}

func (c *chainClient) SendTransaction(ctx context.Context, tx *types.Transaction) error {
if c.chainType == chaintype.ChainHedera {
activeRPC, err := c.multiNode.SelectNodeRPC()
if err != nil {
return err
}
return activeRPC.SendTransaction(ctx, tx)
}
return c.multiNode.SendTransaction(ctx, tx)
}

Expand Down
5 changes: 3 additions & 2 deletions core/chains/evm/client/chain_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -874,8 +874,9 @@ func TestEthClient_ErroringClient(t *testing.T) {
err = erroringClient.SendTransaction(ctx, nil)
require.Equal(t, err, commonclient.ErroringNodeError)

code, err := erroringClient.SendTransactionReturnCode(ctx, nil, common.Address{})
require.Equal(t, code, commonclient.Unknown)
tx := testutils.NewLegacyTransaction(uint64(42), testutils.NewAddress(), big.NewInt(142), 242, big.NewInt(342), []byte{1, 2, 3})
code, err := erroringClient.SendTransactionReturnCode(ctx, tx, common.Address{})
require.Equal(t, code, commonclient.Retryable)
require.Equal(t, err, commonclient.ErroringNodeError)

_, err = erroringClient.SequenceAt(ctx, common.Address{}, nil)
Expand Down
6 changes: 5 additions & 1 deletion core/chains/evm/client/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,11 @@ func (s *SendError) IsL2Full(configErrors *ClientErrors) bool {

// IsServiceUnavailable indicates if the error was caused by a service being unavailable
func (s *SendError) IsServiceUnavailable(configErrors *ClientErrors) bool {
return s.is(ServiceUnavailable, configErrors)
if s == nil || s.err == nil {
return false
}

return s.is(ServiceUnavailable, configErrors) || pkgerrors.Is(s.err, commonclient.ErroringNodeError)
}

// IsTerminallyStuck indicates if a transaction was stuck without any chance of inclusion
Expand Down
7 changes: 7 additions & 0 deletions core/chains/evm/client/errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
pkgerrors "github.com/pkg/errors"
"github.com/stretchr/testify/assert"

commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
)

Expand Down Expand Up @@ -248,6 +249,12 @@ func Test_Eth_Errors(t *testing.T) {
err = newSendErrorWrapped(test.message)
assert.Equal(t, err.IsServiceUnavailable(clientErrors), test.expect)
}
{
err = evmclient.NewSendError(commonclient.ErroringNodeError)
assert.True(t, err.IsServiceUnavailable(clientErrors))
err = evmclient.NewSendError(fmt.Errorf("failed to send transaction: %w", commonclient.ErroringNodeError))
assert.True(t, err.IsServiceUnavailable(clientErrors))
}
})

t.Run("IsTxFeeExceedsCap", func(t *testing.T) {
Expand Down

0 comments on commit ee1d6e3

Please sign in to comment.