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

[SHIP-2001] Cherry Pick - Decouple ChainType Setting (#13272) #13316

Merged
merged 1 commit into from
May 24, 2024
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/young-candles-brush.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink": patch
---

#bugfix allow ChainType to be set to xdai
117 changes: 93 additions & 24 deletions common/config/chaintype.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ import (
"strings"
)

// ChainType denotes the chain or network to work with
type ChainType string

// nolint
const (
ChainArbitrum ChainType = "arbitrum"
ChainCelo ChainType = "celo"
Expand All @@ -18,11 +16,103 @@ const (
ChainOptimismBedrock ChainType = "optimismBedrock"
ChainScroll ChainType = "scroll"
ChainWeMix ChainType = "wemix"
ChainXDai ChainType = "xdai" // Deprecated: use ChainGnosis instead
ChainXLayer ChainType = "xlayer"
ChainZkSync ChainType = "zksync"
)

// IsL2 returns true if this chain is a Layer 2 chain. Notably:
// - the block numbers used for log searching are different from calling block.number
// - gas bumping is not supported, since there is no tx mempool
func (c ChainType) IsL2() bool {
switch c {
case ChainArbitrum, ChainMetis:
return true
default:
return false
}
}

func (c ChainType) IsValid() bool {
switch c {
case "", ChainArbitrum, ChainCelo, ChainGnosis, ChainKroma, ChainMetis, ChainOptimismBedrock, ChainScroll, ChainWeMix, ChainXLayer, ChainZkSync:
return true
}
return false
}

func ChainTypeFromSlug(slug string) ChainType {
switch slug {
case "arbitrum":
return ChainArbitrum
case "celo":
return ChainCelo
case "gnosis", "xdai":
return ChainGnosis
case "kroma":
return ChainKroma
case "metis":
return ChainMetis
case "optimismBedrock":
return ChainOptimismBedrock
case "scroll":
return ChainScroll
case "wemix":
return ChainWeMix
case "xlayer":
return ChainXLayer
case "zksync":
return ChainZkSync
default:
return ChainType(slug)
}
}

type ChainTypeConfig struct {
value ChainType
slug string
}

func NewChainTypeConfig(slug string) *ChainTypeConfig {
return &ChainTypeConfig{
value: ChainTypeFromSlug(slug),
slug: slug,
}
}

func (c *ChainTypeConfig) MarshalText() ([]byte, error) {
if c == nil {
return nil, nil
}
return []byte(c.slug), nil
}

func (c *ChainTypeConfig) UnmarshalText(b []byte) error {
c.slug = string(b)
c.value = ChainTypeFromSlug(c.slug)
return nil
}

func (c *ChainTypeConfig) Slug() string {
if c == nil {
return ""
}
return c.slug
}

func (c *ChainTypeConfig) ChainType() ChainType {
if c == nil {
return ""
}
return c.value
}

func (c *ChainTypeConfig) String() string {
if c == nil {
return ""
}
return string(c.value)
}

var ErrInvalidChainType = fmt.Errorf("must be one of %s or omitted", strings.Join([]string{
string(ChainArbitrum),
string(ChainCelo),
Expand All @@ -35,24 +125,3 @@ var ErrInvalidChainType = fmt.Errorf("must be one of %s or omitted", strings.Joi
string(ChainXLayer),
string(ChainZkSync),
}, ", "))

// IsValid returns true if the ChainType value is known or empty.
func (c ChainType) IsValid() bool {
switch c {
case "", ChainArbitrum, ChainCelo, ChainGnosis, ChainKroma, ChainMetis, ChainOptimismBedrock, ChainScroll, ChainWeMix, ChainXDai, ChainXLayer, ChainZkSync:
return true
}
return false
}

// IsL2 returns true if this chain is a Layer 2 chain. Notably:
// - the block numbers used for log searching are different from calling block.number
// - gas bumping is not supported, since there is no tx mempool
func (c ChainType) IsL2() bool {
switch c {
case ChainArbitrum, ChainMetis:
return true
default:
return false
}
}
3 changes: 2 additions & 1 deletion core/chains/evm/client/config_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"go.uber.org/multierr"

commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config"
"github.com/smartcontractkit/chainlink/v2/common/config"

commonclient "github.com/smartcontractkit/chainlink/v2/common/client"
evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config"
Expand Down Expand Up @@ -55,7 +56,7 @@ func NewClientConfigs(
chainConfig := &evmconfig.EVMConfig{
C: &toml.EVMConfig{
Chain: toml.Chain{
ChainType: &chainType,
ChainType: config.NewChainTypeConfig(chainType),
FinalityDepth: finalityDepth,
FinalityTagEnabled: finalityTagEnabled,
NoNewHeadsThreshold: commonconfig.MustNewDuration(noNewHeadsThreshold),
Expand Down
2 changes: 0 additions & 2 deletions core/chains/evm/client/pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,6 @@ func TestPool_Dial(t *testing.T) {
if err == nil {
t.Cleanup(func() { assert.NoError(t, p.Close()) })
}
assert.True(t, p.ChainType().IsValid())
assert.False(t, p.ChainType().IsL2())
if test.errStr != "" {
require.Error(t, err)
Expand Down Expand Up @@ -333,7 +332,6 @@ func TestUnit_Pool_BatchCallContextAll(t *testing.T) {

p := evmclient.NewPool(logger.Test(t), defaultConfig.NodeSelectionMode(), defaultConfig.LeaseDuration(), time.Second*0, nodes, sendonlys, &cltest.FixtureChainID, "")

assert.True(t, p.ChainType().IsValid())
assert.False(t, p.ChainType().IsL2())
require.NoError(t, p.BatchCallContextAll(ctx, b))
}
Expand Down
2 changes: 1 addition & 1 deletion core/chains/evm/config/chain_scoped.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func (e *EVMConfig) ChainType() commonconfig.ChainType {
if e.C.ChainType == nil {
return ""
}
return commonconfig.ChainType(*e.C.ChainType)
return e.C.ChainType.ChainType()
}

func (e *EVMConfig) ChainID() *big.Int {
Expand Down
4 changes: 2 additions & 2 deletions core/chains/evm/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ func Test_chainScopedConfig_Validate(t *testing.T) {
t.Run("arbitrum-estimator", func(t *testing.T) {
t.Run("custom", func(t *testing.T) {
cfg := configWithChains(t, 0, &toml.Chain{
ChainType: ptr(string(commonconfig.ChainArbitrum)),
ChainType: commonconfig.NewChainTypeConfig(string(commonconfig.ChainArbitrum)),
GasEstimator: toml.GasEstimator{
Mode: ptr("BlockHistory"),
},
Expand Down Expand Up @@ -437,7 +437,7 @@ func Test_chainScopedConfig_Validate(t *testing.T) {
t.Run("optimism-estimator", func(t *testing.T) {
t.Run("custom", func(t *testing.T) {
cfg := configWithChains(t, 0, &toml.Chain{
ChainType: ptr(string(commonconfig.ChainOptimismBedrock)),
ChainType: commonconfig.NewChainTypeConfig(string(commonconfig.ChainOptimismBedrock)),
GasEstimator: toml.GasEstimator{
Mode: ptr("BlockHistory"),
},
Expand Down
26 changes: 9 additions & 17 deletions core/chains/evm/config/toml/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,18 +294,14 @@ func (c *EVMConfig) ValidateConfig() (err error) {
} else if c.ChainID.String() == "" {
err = multierr.Append(err, commonconfig.ErrEmpty{Name: "ChainID", Msg: "required for all chains"})
} else if must, ok := ChainTypeForID(c.ChainID); ok { // known chain id
if c.ChainType == nil && must != "" {
err = multierr.Append(err, commonconfig.ErrMissing{Name: "ChainType",
Msg: fmt.Sprintf("only %q can be used with this chain id", must)})
} else if c.ChainType != nil && *c.ChainType != string(must) {
if *c.ChainType == "" {
err = multierr.Append(err, commonconfig.ErrEmpty{Name: "ChainType",
Msg: fmt.Sprintf("only %q can be used with this chain id", must)})
} else if must == "" {
err = multierr.Append(err, commonconfig.ErrInvalid{Name: "ChainType", Value: *c.ChainType,
// Check if the parsed value matched the expected value
is := c.ChainType.ChainType()
if is != must {
if must == "" {
err = multierr.Append(err, commonconfig.ErrInvalid{Name: "ChainType", Value: c.ChainType.ChainType(),
Msg: "must not be set with this chain id"})
} else {
err = multierr.Append(err, commonconfig.ErrInvalid{Name: "ChainType", Value: *c.ChainType,
err = multierr.Append(err, commonconfig.ErrInvalid{Name: "ChainType", Value: c.ChainType.ChainType(),
Msg: fmt.Sprintf("only %q can be used with this chain id", must)})
}
}
Expand Down Expand Up @@ -345,7 +341,7 @@ type Chain struct {
AutoCreateKey *bool
BlockBackfillDepth *uint32
BlockBackfillSkip *bool
ChainType *string
ChainType *config.ChainTypeConfig
FinalityDepth *uint32
FinalityTagEnabled *bool
FlagsContractAddress *types.EIP55Address
Expand Down Expand Up @@ -375,12 +371,8 @@ type Chain struct {
}

func (c *Chain) ValidateConfig() (err error) {
var chainType config.ChainType
if c.ChainType != nil {
chainType = config.ChainType(*c.ChainType)
}
if !chainType.IsValid() {
err = multierr.Append(err, commonconfig.ErrInvalid{Name: "ChainType", Value: *c.ChainType,
if !c.ChainType.ChainType().IsValid() {
err = multierr.Append(err, commonconfig.ErrInvalid{Name: "ChainType", Value: c.ChainType.ChainType(),
Msg: config.ErrInvalidChainType.Error()})
}

Expand Down
5 changes: 1 addition & 4 deletions core/chains/evm/config/toml/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,7 @@ func Defaults(chainID *big.Big, with ...*Chain) Chain {
func ChainTypeForID(chainID *big.Big) (config.ChainType, bool) {
s := chainID.String()
if d, ok := defaults[s]; ok {
if d.ChainType == nil {
return "", true
}
return config.ChainType(*d.ChainType), true
return d.ChainType.ChainType(), true
}
return "", false
}
Expand Down
5 changes: 0 additions & 5 deletions core/chains/evm/gas/block_history_estimator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -993,11 +993,6 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) {
bhe.Recalculate(cltest.Head(0))
require.Equal(t, assets.NewWeiI(80), gas.GetGasPrice(bhe))

// Same for xDai (deprecated)
cfg.ChainTypeF = string(config.ChainXDai)
bhe.Recalculate(cltest.Head(0))
require.Equal(t, assets.NewWeiI(80), gas.GetGasPrice(bhe))

// And for X Layer
cfg.ChainTypeF = string(config.ChainXLayer)
bhe.Recalculate(cltest.Head(0))
Expand Down
2 changes: 1 addition & 1 deletion core/chains/evm/gas/chain_specific.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
// chainSpecificIsUsable allows for additional logic specific to a particular
// Config that determines whether a transaction should be used for gas estimation
func chainSpecificIsUsable(tx evmtypes.Transaction, baseFee *assets.Wei, chainType config.ChainType, minGasPriceWei *assets.Wei) bool {
if chainType == config.ChainGnosis || chainType == config.ChainXDai || chainType == config.ChainXLayer {
if chainType == config.ChainGnosis || chainType == config.ChainXLayer {
// GasPrice 0 on most chains is great since it indicates cheap/free transactions.
// However, Gnosis and XLayer reserve a special type of "bridge" transaction with 0 gas
// price that is always processed at top priority. Ordinary transactions
Expand Down
3 changes: 2 additions & 1 deletion core/config/docs/docs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
stkcfg "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config"

"github.com/smartcontractkit/chainlink-common/pkg/config"
commonconfig "github.com/smartcontractkit/chainlink/v2/common/config"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
Expand Down Expand Up @@ -46,7 +47,7 @@ func TestDoc(t *testing.T) {
fallbackDefaults := evmcfg.Defaults(nil)
docDefaults := defaults.EVM[0].Chain

require.Equal(t, "", *docDefaults.ChainType)
require.Equal(t, commonconfig.ChainType(""), docDefaults.ChainType.ChainType())
docDefaults.ChainType = nil

// clean up KeySpecific as a special case
Expand Down
5 changes: 2 additions & 3 deletions core/services/chainlink/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"github.com/smartcontractkit/chainlink-solana/pkg/solana"
stkcfg "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config"

commoncfg "github.com/smartcontractkit/chainlink/v2/common/config"
evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/config/docs"
"github.com/smartcontractkit/chainlink/v2/core/config/env"
Expand Down Expand Up @@ -79,10 +78,10 @@ func (c *Config) valueWarnings() (err error) {
func (c *Config) deprecationWarnings() (err error) {
// ChainType xdai is deprecated and has been renamed to gnosis
for _, evm := range c.EVM {
if evm.ChainType != nil && *evm.ChainType == string(commoncfg.ChainXDai) {
if evm.ChainType != nil && evm.ChainType.Slug() == "xdai" {
err = multierr.Append(err, config.ErrInvalid{
Name: "EVM.ChainType",
Value: *evm.ChainType,
Value: evm.ChainType.Slug(),
Msg: "deprecated and will be removed in v2.13.0, use 'gnosis' instead",
})
}
Expand Down
6 changes: 3 additions & 3 deletions core/services/chainlink/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ import (
solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config"
stkcfg "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config"
commonconfig "github.com/smartcontractkit/chainlink/v2/common/config"

"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"

"github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/types"
Expand Down Expand Up @@ -495,7 +495,7 @@ func TestConfig_Marshal(t *testing.T) {
},
BlockBackfillDepth: ptr[uint32](100),
BlockBackfillSkip: ptr(true),
ChainType: ptr("Optimism"),
ChainType: commonconfig.NewChainTypeConfig("Optimism"),
FinalityDepth: ptr[uint32](42),
FinalityTagEnabled: ptr[bool](false),
FlagsContractAddress: mustAddress("0xae4E781a6218A8031764928E88d457937A954fC3"),
Expand Down Expand Up @@ -1626,7 +1626,7 @@ func TestConfig_warnings(t *testing.T) {
{
name: "Value warning - ChainType=xdai is deprecated",
config: Config{
EVM: evmcfg.EVMConfigs{{Chain: evmcfg.Chain{ChainType: ptr(string(commonconfig.ChainXDai))}}},
EVM: evmcfg.EVMConfigs{{Chain: evmcfg.Chain{ChainType: commonconfig.NewChainTypeConfig("xdai")}}},
},
expectedErrors: []string{"EVM.ChainType: invalid value (xdai): deprecated and will be removed in v2.13.0, use 'gnosis' instead"},
},
Expand Down
2 changes: 1 addition & 1 deletion core/services/ocr/contract_tracker.go
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ func (t *OCRContractTracker) LatestBlockHeight(ctx context.Context) (blockheight
// care about the block height; we have no way of getting the L1 block
// height anyway
return 0, nil
case "", config.ChainArbitrum, config.ChainCelo, config.ChainGnosis, config.ChainKroma, config.ChainOptimismBedrock, config.ChainScroll, config.ChainWeMix, config.ChainXDai, config.ChainXLayer, config.ChainZkSync:
case "", config.ChainArbitrum, config.ChainCelo, config.ChainGnosis, config.ChainKroma, config.ChainOptimismBedrock, config.ChainScroll, config.ChainWeMix, config.ChainXLayer, config.ChainZkSync:
// continue
}
latestBlockHeight := t.getLatestBlockHeight()
Expand Down
2 changes: 1 addition & 1 deletion core/services/ocrcommon/block_translator.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func NewBlockTranslator(cfg Config, client evmclient.Client, lggr logger.Logger)
switch cfg.ChainType() {
case config.ChainArbitrum:
return NewArbitrumBlockTranslator(client, lggr)
case "", config.ChainCelo, config.ChainGnosis, config.ChainKroma, config.ChainMetis, config.ChainOptimismBedrock, config.ChainScroll, config.ChainWeMix, config.ChainXDai, config.ChainXLayer, config.ChainZkSync:
case "", config.ChainCelo, config.ChainGnosis, config.ChainKroma, config.ChainMetis, config.ChainOptimismBedrock, config.ChainScroll, config.ChainWeMix, config.ChainXLayer, config.ChainZkSync:
fallthrough
default:
return &l1BlockTranslator{}
Expand Down
Loading
Loading