Skip to content
This repository was archived by the owner on Mar 14, 2025. It is now read-only.

Commit 33cab61

Browse files
authored
Merge branch 'ccip-develop' into ng/attempt-fix-bgworker-timeout
2 parents 84f59e8 + 9e91b40 commit 33cab61

File tree

17 files changed

+398
-53
lines changed

17 files changed

+398
-53
lines changed

.changeset/clever-knives-tap.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"chainlink": patch
3+
---
4+
5+
#added Sei config and error mapping

ccip/config/evm/Hashkey_Mainnet.toml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,4 @@ FeeCapDefault = '1000 gwei'
99

1010
[NodePool]
1111
PollFailureThreshold = 2
12-
PollInterval = '8s'
13-
14-
[GasEstimator.DAOracle]
15-
OracleType = 'opstack'
16-
OracleAddress = '0x420000000000000000000000000000000000000F'
12+
PollInterval = '8s'

ccip/config/evm/Hashkey_Testnet.toml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,3 @@ FeeCapDefault = '1000 gwei'
1010
[NodePool]
1111
PollFailureThreshold = 2
1212
PollInterval = '8s'
13-
14-
[GasEstimator.DAOracle]
15-
OracleType = 'opstack'
16-
OracleAddress = '0x420000000000000000000000000000000000000F'
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
ChainID = '1328'
2+
ChainType = 'sei'
3+
# finality_depth: instant
4+
FinalityDepth = 10
5+
# block_time: ~0.4s, adding 1 second buffer
6+
LogPollInterval = '2s'
7+
# finality_depth * block_time / 60 secs = ~0.8 min (finality time)
8+
NoNewFinalizedHeadsThreshold = '5m'
9+
# "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)"
10+
RPCBlockQueryDelay = 5
11+
12+
[GasEstimator]
13+
EIP1559DynamicFees = false
14+
Mode = 'BlockHistory'
15+
PriceMax = '3000 gwei' # recommended by ds&a
16+
17+
[GasEstimator.BlockHistory]
18+
BlockHistorySize = 200

core/build/platform_arch_guard.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
//go:build !amd64 && !arm64
2+
package build
3+
"non-64-bits architectures are not supported"

core/chains/evm/client/errors.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,14 +284,24 @@ var gnosis = ClientErrors{
284284
TransactionAlreadyInMempool: regexp.MustCompile(`(: |^)(alreadyknown)`),
285285
}
286286

287+
var sei = ClientErrors{
288+
// https://github.com/sei-protocol/sei-tendermint/blob/e9a22c961e83579d8a68cd045c532980d82fb2a0/types/mempool.go#L12
289+
TransactionAlreadyInMempool: regexp.MustCompile("tx already exists in cache"),
290+
// https://github.com/sei-protocol/sei-cosmos/blob/a4eb451c957b1ca7ca9118406682f93fe83d1f61/types/errors/errors.go#L50
291+
// https://github.com/sei-protocol/sei-cosmos/blob/a4eb451c957b1ca7ca9118406682f93fe83d1f61/types/errors/errors.go#L56
292+
// https://github.com/sei-protocol/sei-cosmos/blob/a4eb451c957b1ca7ca9118406682f93fe83d1f61/client/broadcast.go#L27
293+
// https://github.com/sei-protocol/sei-cosmos/blob/a4eb451c957b1ca7ca9118406682f93fe83d1f61/types/errors/errors.go#L32
294+
Fatal: regexp.MustCompile(`(: |^)'*out of gas|insufficient fee|Tx too large. Max size is \d+, but got \d+|: insufficient funds`),
295+
}
296+
287297
const TerminallyStuckMsg = "transaction terminally stuck"
288298

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

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

296306
// ClientErrorRegexes returns a map of compiled regexes for each error type
297307
func ClientErrorRegexes(errsRegex config.ClientErrors) *ClientErrors {

core/chains/evm/client/errors_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ func Test_Eth_Errors(t *testing.T) {
144144
{"client error transaction already in mempool", true, "tomlConfig"},
145145
{"alreadyknown", true, "Gnosis"},
146146
{"failed to forward tx to sequencer, please try again. Error message: 'already known'", true, "Mantle"},
147+
{"tx already exists in cache", true, "Sei"},
147148
}
148149
for _, test := range tests {
149150
err = evmclient.NewSendErrorS(test.message)
@@ -420,6 +421,11 @@ func Test_Eth_Errors_Fatal(t *testing.T) {
420421
{"client error fatal", true, "tomlConfig"},
421422
{"[Request ID: d9711488-4c1e-4af2-bc1f-7969913d7b60] Error invoking RPC: transaction [email protected] failed precheck with status INVALID_SIGNATURE", true, "hedera"},
422423
{"invalid chain id for signer", true, "Treasure"},
424+
425+
{": out of gas", true, "Sei"},
426+
{"Tx too large. Max size is 2048576, but got 2097431", true, "Sei"},
427+
{": insufficient funds", true, "Sei"},
428+
{"insufficient fee", true, "Sei"},
423429
}
424430

425431
for _, test := range tests {

core/chains/evm/client/helpers_test.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"math/big"
66
"net/url"
7+
"sync"
78
"testing"
89
"time"
910

@@ -219,6 +220,7 @@ const HeadResult = `{"difficulty":"0xf3a00","extraData":"0xd88301050384676574688
219220
type mockSubscription struct {
220221
unsubscribed bool
221222
Errors chan error
223+
unsub sync.Once
222224
}
223225

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

230232
func (mes *mockSubscription) Unsubscribe() {
231-
mes.unsubscribed = true
232-
close(mes.Errors)
233+
mes.unsub.Do(func() {
234+
mes.unsubscribed = true
235+
close(mes.Errors)
236+
})
233237
}
234238

235239
func ParseTestNodeConfigs(nodes []NodeConfig) ([]*toml.Node, error) {

core/chains/evm/client/rpc_client.go

Lines changed: 66 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/json"
66
"errors"
77
"fmt"
8+
"math"
89
"math/big"
910
"net/url"
1011
"strconv"
@@ -151,6 +152,7 @@ type rpcClient struct {
151152
latestChainInfo commonclient.ChainInfo
152153
}
153154

155+
// NewRPCCLient returns a new *rpcClient as commonclient.RPC
154156
// NewRPCCLient returns a new *rpcClient as commonclient.RPC
155157
func NewRPCClient(
156158
lggr logger.Logger,
@@ -166,6 +168,22 @@ func NewRPCClient(
166168
rpcTimeout time.Duration,
167169
chainType chaintype.ChainType,
168170
) RPCClient {
171+
return newRPCClient(lggr, wsuri, httpuri, name, id, chainID, tier, finalizedBlockPollInterval, newHeadsPollInterval, largePayloadRpcTimeout, rpcTimeout, chainType)
172+
}
173+
func newRPCClient(
174+
lggr logger.Logger,
175+
wsuri *url.URL,
176+
httpuri *url.URL,
177+
name string,
178+
id int,
179+
chainID *big.Int,
180+
tier commonclient.NodeTier,
181+
finalizedBlockPollInterval time.Duration,
182+
newHeadsPollInterval time.Duration,
183+
largePayloadRpcTimeout time.Duration,
184+
rpcTimeout time.Duration,
185+
chainType chaintype.ChainType,
186+
) *rpcClient {
169187
r := &rpcClient{
170188
largePayloadRpcTimeout: largePayloadRpcTimeout,
171189
rpcTimeout: rpcTimeout,
@@ -428,6 +446,10 @@ func (r *rpcClient) BatchCallContext(rootCtx context.Context, b []rpc.BatchElem)
428446
var requestedFinalizedBlock bool
429447
if r.chainType == chaintype.ChainAstar {
430448
for _, el := range b {
449+
if el.Method == "eth_getLogs" {
450+
r.rpcLog.Critical("evmclient.BatchCallContext: eth_getLogs is not supported")
451+
return errors.New("evmclient.BatchCallContext: eth_getLogs is not supported")
452+
}
431453
if !isRequestingFinalizedBlock(el) {
432454
continue
433455
}
@@ -547,10 +569,10 @@ func (r *rpcClient) SubscribeNewHead(ctx context.Context, channel chan<- *evmtyp
547569
r.logResult(lggr, err, duration, r.getRPCDomain(), "EthSubscribe")
548570
err = r.wrapWS(err)
549571
}()
550-
subForwarder := newSubForwarder(channel, func(head *evmtypes.Head) *evmtypes.Head {
572+
subForwarder := newSubForwarder(channel, func(head *evmtypes.Head) (*evmtypes.Head, error) {
551573
head.EVMChainID = ubig.New(r.chainID)
552574
r.onNewHead(ctx, chStopInFlight, head)
553-
return head
575+
return head, nil
554576
}, r.wrapRPCClientError)
555577
err = subForwarder.start(ws.rpc.EthSubscribe(ctx, subForwarder.srcCh, args...))
556578
if err != nil {
@@ -602,10 +624,10 @@ func (r *rpcClient) SubscribeToHeads(ctx context.Context) (ch <-chan *evmtypes.H
602624
}()
603625

604626
channel := make(chan *evmtypes.Head)
605-
forwarder := newSubForwarder(channel, func(head *evmtypes.Head) *evmtypes.Head {
627+
forwarder := newSubForwarder(channel, func(head *evmtypes.Head) (*evmtypes.Head, error) {
606628
head.EVMChainID = ubig.New(r.chainID)
607629
r.onNewHead(ctx, chStopInFlight, head)
608-
return head
630+
return head, nil
609631
}, r.wrapRPCClientError)
610632

611633
err = forwarder.start(ws.rpc.EthSubscribe(ctx, forwarder.srcCh, args...))
@@ -1283,8 +1305,11 @@ func (r *rpcClient) FilterLogs(ctx context.Context, q ethereum.FilterQuery) (l [
12831305
l, err = ws.geth.FilterLogs(ctx, q)
12841306
err = r.wrapWS(err)
12851307
}
1286-
duration := time.Since(start)
12871308

1309+
if err == nil {
1310+
err = r.makeLogsValid(l)
1311+
}
1312+
duration := time.Since(start)
12881313
r.logResult(lggr, err, duration, r.getRPCDomain(), "FilterLogs",
12891314
"log", l,
12901315
)
@@ -1312,7 +1337,7 @@ func (r *rpcClient) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQu
13121337
r.logResult(lggr, err, duration, r.getRPCDomain(), "SubscribeFilterLogs")
13131338
err = r.wrapWS(err)
13141339
}()
1315-
sub := newSubForwarder(ch, nil, r.wrapRPCClientError)
1340+
sub := newSubForwarder(ch, r.makeLogValid, r.wrapRPCClientError)
13161341
err = sub.start(ws.geth.SubscribeFilterLogs(ctx, q, sub.srcCh))
13171342
if err != nil {
13181343
return
@@ -1540,3 +1565,38 @@ func ToBlockNumArg(number *big.Int) string {
15401565
}
15411566
return hexutil.EncodeBig(number)
15421567
}
1568+
1569+
func (r *rpcClient) makeLogsValid(logs []types.Log) error {
1570+
if r.chainType != chaintype.ChainSei {
1571+
return nil
1572+
}
1573+
1574+
for i := range logs {
1575+
var err error
1576+
logs[i], err = r.makeLogValid(logs[i])
1577+
if err != nil {
1578+
return err
1579+
}
1580+
}
1581+
1582+
return nil
1583+
}
1584+
1585+
func (r *rpcClient) makeLogValid(log types.Log) (types.Log, error) {
1586+
if r.chainType != chaintype.ChainSei {
1587+
return log, nil
1588+
}
1589+
1590+
if log.TxIndex > math.MaxUint32 {
1591+
return types.Log{}, fmt.Errorf("TxIndex of tx %s exceeds max supported value of %d", log.TxHash, math.MaxUint32)
1592+
}
1593+
1594+
if log.Index > math.MaxUint32 {
1595+
return types.Log{}, fmt.Errorf("log's index %d of tx %s exceeds max supported value of %d", log.Index, log.TxHash, math.MaxUint32)
1596+
}
1597+
1598+
// it's safe as we have a build guard to guarantee 64-bit system
1599+
newIndex := uint64(log.TxIndex<<32) | uint64(log.Index)
1600+
log.Index = uint(newIndex)
1601+
return log, nil
1602+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package client
2+
3+
import (
4+
"errors"
5+
"math"
6+
"testing"
7+
8+
ethtypes "github.com/ethereum/go-ethereum/core/types"
9+
"github.com/stretchr/testify/require"
10+
11+
commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
12+
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype"
13+
"github.com/smartcontractkit/chainlink/v2/core/logger"
14+
)
15+
16+
func TestRPCClient_MakeLogsValid(t *testing.T) {
17+
testCases := []struct {
18+
Name string
19+
TxIndex uint
20+
LogIndex uint
21+
ExpectedLogIndex uint
22+
ExpectedError error
23+
}{
24+
{
25+
Name: "TxIndex = 0 LogIndex = 0",
26+
TxIndex: 0,
27+
LogIndex: 0,
28+
ExpectedLogIndex: 0,
29+
ExpectedError: nil,
30+
},
31+
{
32+
Name: "TxIndex = 0 LogIndex = 1",
33+
TxIndex: 0,
34+
LogIndex: 1,
35+
ExpectedLogIndex: 1,
36+
ExpectedError: nil,
37+
},
38+
{
39+
Name: "TxIndex = 0 LogIndex = MaxUint32",
40+
TxIndex: 0,
41+
LogIndex: math.MaxUint32,
42+
ExpectedLogIndex: math.MaxUint32,
43+
ExpectedError: nil,
44+
},
45+
{
46+
Name: "LogIndex = MaxUint32 + 1 => returns an error",
47+
TxIndex: 0,
48+
LogIndex: math.MaxUint32 + 1,
49+
ExpectedLogIndex: 0,
50+
ExpectedError: errors.New("log's index 4294967296 of tx 0x0000000000000000000000000000000000000000000000000000000000000000 exceeds max supported value of 4294967295"),
51+
},
52+
{
53+
Name: "TxIndex = 1 LogIndex = 0",
54+
TxIndex: 1,
55+
LogIndex: 0,
56+
ExpectedLogIndex: math.MaxUint32 + 1,
57+
ExpectedError: nil,
58+
},
59+
{
60+
Name: "TxIndex = MaxUint32 LogIndex = MaxUint32",
61+
TxIndex: math.MaxUint32,
62+
LogIndex: math.MaxUint32,
63+
ExpectedLogIndex: math.MaxUint64,
64+
ExpectedError: nil,
65+
},
66+
{
67+
Name: "TxIndex = MaxUint32 + 1 => returns an error",
68+
TxIndex: math.MaxUint32 + 1,
69+
LogIndex: 0,
70+
ExpectedLogIndex: 0,
71+
ExpectedError: errors.New("TxIndex of tx 0x0000000000000000000000000000000000000000000000000000000000000000 exceeds max supported value of 4294967295"),
72+
},
73+
}
74+
for _, tc := range testCases {
75+
t.Run(tc.Name, func(t *testing.T) {
76+
rpc := newRPCClient(logger.TestLogger(t), nil, nil, "eth-primary-rpc-0", 0, nil, commonclient.Primary, 0, 0, commonclient.QueryTimeout, commonclient.QueryTimeout, "")
77+
log, err := rpc.makeLogValid(ethtypes.Log{TxIndex: tc.TxIndex, Index: tc.LogIndex})
78+
// non sei should return as is
79+
require.NoError(t, err)
80+
require.Equal(t, tc.TxIndex, log.TxIndex)
81+
require.Equal(t, tc.LogIndex, log.Index)
82+
seiRPC := newRPCClient(logger.TestLogger(t), nil, nil, "eth-primary-rpc-0", 0, nil, commonclient.Primary, 0, 0, commonclient.QueryTimeout, commonclient.QueryTimeout, chaintype.ChainSei)
83+
log, err = seiRPC.makeLogValid(ethtypes.Log{TxIndex: tc.TxIndex, Index: tc.LogIndex})
84+
if tc.ExpectedError != nil {
85+
require.EqualError(t, err, tc.ExpectedError.Error())
86+
return
87+
}
88+
89+
require.Equal(t, tc.ExpectedLogIndex, log.Index)
90+
require.Equal(t, tc.TxIndex, log.TxIndex)
91+
})
92+
}
93+
}

0 commit comments

Comments
 (0)