Skip to content

Commit

Permalink
Merge core changes into CCIP (#1589)
Browse files Browse the repository at this point in the history
Cherry picking core PRs into ccip:
1. smartcontractkit/chainlink#15828 
2. smartcontractkit/chainlink#15858
3. smartcontractkit/chainlink#15735

---------

Co-authored-by: Jasmin Bakalovic <[email protected]>
Co-authored-by: joaoluisam <[email protected]>
Co-authored-by: Friedemann Fürst <[email protected]>
Co-authored-by: Sishir Giri <[email protected]>
Co-authored-by: Dmytro Haidashenko <[email protected]>
  • Loading branch information
6 people authored Jan 8, 2025
1 parent 30e5f71 commit 386f02c
Show file tree
Hide file tree
Showing 34 changed files with 684 additions and 76 deletions.
5 changes: 5 additions & 0 deletions .changeset/clever-knives-tap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink": patch
---

#added Sei config and error mapping
5 changes: 5 additions & 0 deletions .changeset/eighty-geckos-switch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink": patch
---

Reduce PriceMin on Avalanche to 1 gwei #nops
5 changes: 2 additions & 3 deletions ccip/config/evm/Avalanche_Fuji.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ RPCBlockQueryDelay = 2
NoNewFinalizedHeadsThreshold = '1m'

[GasEstimator]
PriceDefault = '25 gwei'
PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether'
PriceMin = '25 gwei'
PriceMin = '1 gwei'
PriceDefault = '1 gwei'

[GasEstimator.BlockHistory]
BlockHistorySize = 24
Expand Down
5 changes: 2 additions & 3 deletions ccip/config/evm/Avalanche_Mainnet.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ RPCBlockQueryDelay = 2
NoNewFinalizedHeadsThreshold = '1m'

[GasEstimator]
PriceDefault = '25 gwei'
PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether'
PriceMin = '25 gwei'
PriceMin = '1 gwei'
PriceDefault = '1 gwei'

[GasEstimator.BlockHistory]
# Average block time of 2s
Expand Down
18 changes: 18 additions & 0 deletions ccip/config/evm/Sei_Testnet_Atlantic.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
ChainID = '1328'
ChainType = 'sei'
# finality_depth: instant
FinalityDepth = 10
# block_time: ~0.4s, adding 1 second buffer
LogPollInterval = '2s'
# finality_depth * block_time / 60 secs = ~0.8 min (finality time)
NoNewFinalizedHeadsThreshold = '5m'
# "RPC node returned multiple missing blocks on query for block numbers [31592085 31592084] even though the WS subscription already sent us these blocks. It might help to increase EVM.RPCBlockQueryDelay (currently 1)"
RPCBlockQueryDelay = 5

[GasEstimator]
EIP1559DynamicFees = false
Mode = 'BlockHistory'
PriceMax = '3000 gwei' # recommended by ds&a

[GasEstimator.BlockHistory]
BlockHistorySize = 200
3 changes: 3 additions & 0 deletions core/build/platform_arch_guard.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
//go:build !amd64 && !arm64
package build
"non-64-bits architectures are not supported"
12 changes: 11 additions & 1 deletion core/chains/evm/client/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,14 +284,24 @@ var gnosis = ClientErrors{
TransactionAlreadyInMempool: regexp.MustCompile(`(: |^)(alreadyknown)`),
}

var sei = ClientErrors{
// https://github.com/sei-protocol/sei-tendermint/blob/e9a22c961e83579d8a68cd045c532980d82fb2a0/types/mempool.go#L12
TransactionAlreadyInMempool: regexp.MustCompile("tx already exists in cache"),
// https://github.com/sei-protocol/sei-cosmos/blob/a4eb451c957b1ca7ca9118406682f93fe83d1f61/types/errors/errors.go#L50
// https://github.com/sei-protocol/sei-cosmos/blob/a4eb451c957b1ca7ca9118406682f93fe83d1f61/types/errors/errors.go#L56
// https://github.com/sei-protocol/sei-cosmos/blob/a4eb451c957b1ca7ca9118406682f93fe83d1f61/client/broadcast.go#L27
// https://github.com/sei-protocol/sei-cosmos/blob/a4eb451c957b1ca7ca9118406682f93fe83d1f61/types/errors/errors.go#L32
Fatal: regexp.MustCompile(`(: |^)'*out of gas|insufficient fee|Tx too large. Max size is \d+, but got \d+|: insufficient funds`),
}

const TerminallyStuckMsg = "transaction terminally stuck"

// Tx.Error messages that are set internally so they are not chain or client specific
var internal = ClientErrors{
TerminallyStuck: regexp.MustCompile(TerminallyStuckMsg),
}

var clients = []ClientErrors{parity, geth, arbitrum, metis, substrate, avalanche, nethermind, harmony, besu, erigon, klaytn, celo, zkSync, zkEvm, treasure, mantle, aStar, hedera, gnosis, internal}
var clients = []ClientErrors{parity, geth, arbitrum, metis, substrate, avalanche, nethermind, harmony, besu, erigon, klaytn, celo, zkSync, zkEvm, treasure, mantle, aStar, hedera, gnosis, sei, internal}

// ClientErrorRegexes returns a map of compiled regexes for each error type
func ClientErrorRegexes(errsRegex config.ClientErrors) *ClientErrors {
Expand Down
6 changes: 6 additions & 0 deletions core/chains/evm/client/errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ func Test_Eth_Errors(t *testing.T) {
{"client error transaction already in mempool", true, "tomlConfig"},
{"alreadyknown", true, "Gnosis"},
{"failed to forward tx to sequencer, please try again. Error message: 'already known'", true, "Mantle"},
{"tx already exists in cache", true, "Sei"},
}
for _, test := range tests {
err = evmclient.NewSendErrorS(test.message)
Expand Down Expand Up @@ -420,6 +421,11 @@ func Test_Eth_Errors_Fatal(t *testing.T) {
{"client error fatal", true, "tomlConfig"},
{"[Request ID: d9711488-4c1e-4af2-bc1f-7969913d7b60] Error invoking RPC: transaction [email protected] failed precheck with status INVALID_SIGNATURE", true, "hedera"},
{"invalid chain id for signer", true, "Treasure"},

{": out of gas", true, "Sei"},
{"Tx too large. Max size is 2048576, but got 2097431", true, "Sei"},
{": insufficient funds", true, "Sei"},
{"insufficient fee", true, "Sei"},
}

for _, test := range tests {
Expand Down
8 changes: 6 additions & 2 deletions core/chains/evm/client/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"math/big"
"net/url"
"sync"
"testing"
"time"

Expand Down Expand Up @@ -219,6 +220,7 @@ const HeadResult = `{"difficulty":"0xf3a00","extraData":"0xd88301050384676574688
type mockSubscription struct {
unsubscribed bool
Errors chan error
unsub sync.Once
}

func NewMockSubscription() *mockSubscription {
Expand All @@ -228,8 +230,10 @@ func NewMockSubscription() *mockSubscription {
func (mes *mockSubscription) Err() <-chan error { return mes.Errors }

func (mes *mockSubscription) Unsubscribe() {
mes.unsubscribed = true
close(mes.Errors)
mes.unsub.Do(func() {
mes.unsubscribed = true
close(mes.Errors)
})
}

func ParseTestNodeConfigs(nodes []NodeConfig) ([]*toml.Node, error) {
Expand Down
72 changes: 66 additions & 6 deletions core/chains/evm/client/rpc_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"errors"
"fmt"
"math"
"math/big"
"net/url"
"strconv"
Expand Down Expand Up @@ -152,6 +153,7 @@ type rpcClient struct {
latestChainInfo commonclient.ChainInfo
}

// NewRPCCLient returns a new *rpcClient as commonclient.RPC
// NewRPCCLient returns a new *rpcClient as commonclient.RPC
func NewRPCClient(
lggr logger.Logger,
Expand All @@ -167,6 +169,22 @@ func NewRPCClient(
rpcTimeout time.Duration,
chainType chaintype.ChainType,
) RPCClient {
return newRPCClient(lggr, wsuri, httpuri, name, id, chainID, tier, finalizedBlockPollInterval, newHeadsPollInterval, largePayloadRpcTimeout, rpcTimeout, chainType)
}
func newRPCClient(
lggr logger.Logger,
wsuri *url.URL,
httpuri *url.URL,
name string,
id int,
chainID *big.Int,
tier commonclient.NodeTier,
finalizedBlockPollInterval time.Duration,
newHeadsPollInterval time.Duration,
largePayloadRpcTimeout time.Duration,
rpcTimeout time.Duration,
chainType chaintype.ChainType,
) *rpcClient {
r := &rpcClient{
largePayloadRpcTimeout: largePayloadRpcTimeout,
rpcTimeout: rpcTimeout,
Expand Down Expand Up @@ -436,6 +454,10 @@ func (r *rpcClient) BatchCallContext(rootCtx context.Context, b []rpc.BatchElem)
var requestedFinalizedBlock bool
if r.chainType == chaintype.ChainAstar {
for _, el := range b {
if el.Method == "eth_getLogs" {
r.rpcLog.Critical("evmclient.BatchCallContext: eth_getLogs is not supported")
return errors.New("evmclient.BatchCallContext: eth_getLogs is not supported")
}
if !isRequestingFinalizedBlock(el) {
continue
}
Expand Down Expand Up @@ -555,10 +577,10 @@ func (r *rpcClient) SubscribeNewHead(ctx context.Context, channel chan<- *evmtyp
r.logResult(lggr, err, duration, r.getRPCDomain(), "EthSubscribe")
err = r.wrapWS(err)
}()
subForwarder := newSubForwarder(channel, func(head *evmtypes.Head) *evmtypes.Head {
subForwarder := newSubForwarder(channel, func(head *evmtypes.Head) (*evmtypes.Head, error) {
head.EVMChainID = ubig.New(r.chainID)
r.onNewHead(ctx, chStopInFlight, head)
return head
return head, nil
}, r.wrapRPCClientError)
err = subForwarder.start(ws.rpc.EthSubscribe(ctx, subForwarder.srcCh, args...))
if err != nil {
Expand Down Expand Up @@ -610,10 +632,10 @@ func (r *rpcClient) SubscribeToHeads(ctx context.Context) (ch <-chan *evmtypes.H
}()

channel := make(chan *evmtypes.Head)
forwarder := newSubForwarder(channel, func(head *evmtypes.Head) *evmtypes.Head {
forwarder := newSubForwarder(channel, func(head *evmtypes.Head) (*evmtypes.Head, error) {
head.EVMChainID = ubig.New(r.chainID)
r.onNewHead(ctx, chStopInFlight, head)
return head
return head, nil
}, r.wrapRPCClientError)

err = forwarder.start(ws.rpc.EthSubscribe(ctx, forwarder.srcCh, args...))
Expand Down Expand Up @@ -1291,8 +1313,11 @@ func (r *rpcClient) FilterLogs(ctx context.Context, q ethereum.FilterQuery) (l [
l, err = ws.geth.FilterLogs(ctx, q)
err = r.wrapWS(err)
}
duration := time.Since(start)

if err == nil {
err = r.makeLogsValid(l)
}
duration := time.Since(start)
r.logResult(lggr, err, duration, r.getRPCDomain(), "FilterLogs",
"log", l,
)
Expand Down Expand Up @@ -1320,7 +1345,7 @@ func (r *rpcClient) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQu
r.logResult(lggr, err, duration, r.getRPCDomain(), "SubscribeFilterLogs")
err = r.wrapWS(err)
}()
sub := newSubForwarder(ch, nil, r.wrapRPCClientError)
sub := newSubForwarder(ch, r.makeLogValid, r.wrapRPCClientError)
err = sub.start(ws.geth.SubscribeFilterLogs(ctx, q, sub.srcCh))
if err != nil {
return
Expand Down Expand Up @@ -1548,3 +1573,38 @@ func ToBlockNumArg(number *big.Int) string {
}
return hexutil.EncodeBig(number)
}

func (r *rpcClient) makeLogsValid(logs []types.Log) error {
if r.chainType != chaintype.ChainSei {
return nil
}

for i := range logs {
var err error
logs[i], err = r.makeLogValid(logs[i])
if err != nil {
return err
}
}

return nil
}

func (r *rpcClient) makeLogValid(log types.Log) (types.Log, error) {
if r.chainType != chaintype.ChainSei {
return log, nil
}

if log.TxIndex > math.MaxUint32 {
return types.Log{}, fmt.Errorf("TxIndex of tx %s exceeds max supported value of %d", log.TxHash, math.MaxUint32)
}

if log.Index > math.MaxUint32 {
return types.Log{}, fmt.Errorf("log's index %d of tx %s exceeds max supported value of %d", log.Index, log.TxHash, math.MaxUint32)
}

// it's safe as we have a build guard to guarantee 64-bit system
newIndex := uint64(log.TxIndex<<32) | uint64(log.Index)
log.Index = uint(newIndex)
return log, nil
}
93 changes: 93 additions & 0 deletions core/chains/evm/client/rpc_client_internal_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package client

import (
"errors"
"math"
"testing"

ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/stretchr/testify/require"

commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype"
"github.com/smartcontractkit/chainlink/v2/core/logger"
)

func TestRPCClient_MakeLogsValid(t *testing.T) {
testCases := []struct {
Name string
TxIndex uint
LogIndex uint
ExpectedLogIndex uint
ExpectedError error
}{
{
Name: "TxIndex = 0 LogIndex = 0",
TxIndex: 0,
LogIndex: 0,
ExpectedLogIndex: 0,
ExpectedError: nil,
},
{
Name: "TxIndex = 0 LogIndex = 1",
TxIndex: 0,
LogIndex: 1,
ExpectedLogIndex: 1,
ExpectedError: nil,
},
{
Name: "TxIndex = 0 LogIndex = MaxUint32",
TxIndex: 0,
LogIndex: math.MaxUint32,
ExpectedLogIndex: math.MaxUint32,
ExpectedError: nil,
},
{
Name: "LogIndex = MaxUint32 + 1 => returns an error",
TxIndex: 0,
LogIndex: math.MaxUint32 + 1,
ExpectedLogIndex: 0,
ExpectedError: errors.New("log's index 4294967296 of tx 0x0000000000000000000000000000000000000000000000000000000000000000 exceeds max supported value of 4294967295"),
},
{
Name: "TxIndex = 1 LogIndex = 0",
TxIndex: 1,
LogIndex: 0,
ExpectedLogIndex: math.MaxUint32 + 1,
ExpectedError: nil,
},
{
Name: "TxIndex = MaxUint32 LogIndex = MaxUint32",
TxIndex: math.MaxUint32,
LogIndex: math.MaxUint32,
ExpectedLogIndex: math.MaxUint64,
ExpectedError: nil,
},
{
Name: "TxIndex = MaxUint32 + 1 => returns an error",
TxIndex: math.MaxUint32 + 1,
LogIndex: 0,
ExpectedLogIndex: 0,
ExpectedError: errors.New("TxIndex of tx 0x0000000000000000000000000000000000000000000000000000000000000000 exceeds max supported value of 4294967295"),
},
}
for _, tc := range testCases {
t.Run(tc.Name, func(t *testing.T) {
rpc := newRPCClient(logger.TestLogger(t), nil, nil, "eth-primary-rpc-0", 0, nil, commonclient.Primary, 0, 0, commonclient.QueryTimeout, commonclient.QueryTimeout, "")
log, err := rpc.makeLogValid(ethtypes.Log{TxIndex: tc.TxIndex, Index: tc.LogIndex})
// non sei should return as is
require.NoError(t, err)
require.Equal(t, tc.TxIndex, log.TxIndex)
require.Equal(t, tc.LogIndex, log.Index)
seiRPC := newRPCClient(logger.TestLogger(t), nil, nil, "eth-primary-rpc-0", 0, nil, commonclient.Primary, 0, 0, commonclient.QueryTimeout, commonclient.QueryTimeout, chaintype.ChainSei)
log, err = seiRPC.makeLogValid(ethtypes.Log{TxIndex: tc.TxIndex, Index: tc.LogIndex})
if tc.ExpectedError != nil {
require.EqualError(t, err, tc.ExpectedError.Error())
return
}

require.Equal(t, tc.ExpectedLogIndex, log.Index)
require.Equal(t, tc.TxIndex, log.TxIndex)
})
}
}
Loading

0 comments on commit 386f02c

Please sign in to comment.