Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge core changes into CCIP #1589

Merged
merged 8 commits into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading