Skip to content

Commit

Permalink
refactor: use ChainInfo in authority to allow support chains dyna…
Browse files Browse the repository at this point in the history
…mically (#2380)

* add combine list function

* remove unused functions and add combine default list method

* use test package for chain_test

* use additional info parameter for methods

* rename additional chains

* add GetChainList to authority interface

* iteration 1

* crosschain refactoring

* fungible refacotring

* lightclient refactoring

* observer refactoring

* add additional chain list in context

* zetaclient modification

* fix build error

* format

* changelog

* fix lint

* test fixes 2

* observer test fix

* zetaclient tests

* fix test 2

* add more tests

* rename getChainList

* add issues

* fix tests

* Update pkg/chains/chains.go

Co-authored-by: Dmitry S <[email protected]>

* Update pkg/chains/chains.go

Co-authored-by: Dmitry S <[email protected]>

* add TODO

* Update x/authority/keeper/chain_info.go

Co-authored-by: Dmitry S <[email protected]>

* Update cmd/zetaclientd/debug.go

Co-authored-by: Charlie Chen <[email protected]>

* remove pointers in chains

* complete chain remove pointer

* fix tests

* dmitry comments

* update comment

* fix merge error

* comments

* use nil

---------

Co-authored-by: Dmitry S <[email protected]>
Co-authored-by: Charlie Chen <[email protected]>
  • Loading branch information
3 people authored Jul 2, 2024
1 parent ba6bc6f commit 8982129
Show file tree
Hide file tree
Showing 139 changed files with 1,806 additions and 1,467 deletions.
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
* [2357](https://github.com/zeta-chain/node/pull/2357) - integrate base Signer structure into EVM/Bitcoin Signer
* [2359](https://github.com/zeta-chain/node/pull/2359) - integrate base Observer structure into EVM/Bitcoin Observer
* [2375](https://github.com/zeta-chain/node/pull/2375) - improve & speedup code formatting
* [2380](https://github.com/zeta-chain/node/pull/2380) - use `ChainInfo` in `authority` to allow dynamically support new chains
* [2395](https://github.com/zeta-chain/node/pull/2395) - converge AppContext with ZetaCoreContext in zetaclient

### Tests
Expand Down
16 changes: 8 additions & 8 deletions cmd/zetaclientd/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,28 +86,28 @@ func debugCmd(_ *cobra.Command, args []string) error {
if err != nil {
return err
}
chain := chains.GetChainFromChainID(chainID)
if chain == nil {
chain, found := chains.GetChainFromChainID(chainID, appContext.GetAdditionalChains())
if !found {
return fmt.Errorf("invalid chain id")
}

// get ballot identifier according to the chain type
if chains.IsEVMChain(chain.ChainId) {
if chains.IsEVMChain(chain.ChainId, appContext.GetAdditionalChains()) {
evmObserver := evmobserver.Observer{}
evmObserver.WithZetacoreClient(client)
var ethRPC *ethrpc.EthRPC
var client *ethclient.Client
coinType := coin.CoinType_Cmd
for chain, evmConfig := range cfg.GetAllEVMConfigs() {
if chainID == chain {
for chainIDFromConfig, evmConfig := range cfg.GetAllEVMConfigs() {
if chainIDFromConfig == chainID {
ethRPC = ethrpc.NewEthRPC(evmConfig.Endpoint)
client, err = ethclient.Dial(evmConfig.Endpoint)
if err != nil {
return err
}
evmObserver.WithEvmClient(client)
evmObserver.WithEvmJSONRPC(ethRPC)
evmObserver.WithChain(*chains.GetChainFromChainID(chainID))
evmObserver.WithChain(chain)
}
}
hash := ethcommon.HexToHash(inboundHash)
Expand Down Expand Up @@ -168,10 +168,10 @@ func debugCmd(_ *cobra.Command, args []string) error {
fmt.Println("CoinType not detected")
}
fmt.Println("CoinType : ", coinType)
} else if chains.IsBitcoinChain(chain.ChainId) {
} else if chains.IsBitcoinChain(chain.ChainId, appContext.GetAdditionalChains()) {
btcObserver := btcobserver.Observer{}
btcObserver.WithZetacoreClient(client)
btcObserver.WithChain(*chains.GetChainFromChainID(chainID))
btcObserver.WithChain(chain)
connCfg := &rpcclient.ConnConfig{
Host: cfg.BitcoinConfig.RPCHost,
User: cfg.BitcoinConfig.RPCUsername,
Expand Down
127 changes: 40 additions & 87 deletions pkg/chains/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,9 @@ import (
"strings"

"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcutil"
ethcommon "github.com/ethereum/go-ethereum/common"
)

type SigninAlgo string

// Chains represent a slice of Chain
type Chains []Chain

// Validate checks whether the chain is valid
// The function check the chain ID is positive and all enum fields have a defined value
func (chain Chain) Validate() error {
Expand Down Expand Up @@ -44,11 +38,6 @@ func (chain Chain) Validate() error {
return nil
}

// IsEqual compare two chain to see whether they represent the same chain
func (chain Chain) IsEqual(c Chain) bool {
return chain.ChainId == c.ChainId
}

// IsZetaChain returns true if the chain is a ZetaChain chain
func (chain Chain) IsZetaChain() bool {
return chain.Network == Network_zeta
Expand All @@ -63,13 +52,13 @@ func (chain Chain) IsExternalChain() bool {
// on EVM chain, it is 20Bytes
// on Bitcoin chain, it is P2WPKH address, []byte(bech32 encoded string)
func (chain Chain) EncodeAddress(b []byte) (string, error) {
if IsEVMChain(chain.ChainId) {
if chain.Consensus == Consensus_ethereum {
addr := ethcommon.BytesToAddress(b)
if addr == (ethcommon.Address{}) {
return "", fmt.Errorf("invalid EVM address")
}
return addr.Hex(), nil
} else if IsBitcoinChain(chain.ChainId) {
} else if chain.Consensus == Consensus_bitcoin {
addrStr := string(b)
chainParams, err := GetBTCChainParams(chain.ChainId)
if err != nil {
Expand All @@ -87,107 +76,75 @@ func (chain Chain) EncodeAddress(b []byte) (string, error) {
return "", fmt.Errorf("chain (%d) not supported", chain.ChainId)
}

func (chain Chain) BTCAddressFromWitnessProgram(witnessProgram []byte) (string, error) {
chainParams, err := GetBTCChainParams(chain.ChainId)
if err != nil {
return "", err
}
address, err := btcutil.NewAddressWitnessPubKeyHash(witnessProgram, chainParams)
if err != nil {
return "", err
}
return address.EncodeAddress(), nil
func (chain Chain) IsEVMChain() bool {
return chain.Consensus == Consensus_ethereum
}

// DecodeAddress decode the address string to bytes
func (chain Chain) DecodeAddress(addr string) ([]byte, error) {
return DecodeAddressFromChainID(chain.ChainId, addr)
func (chain Chain) IsBitcoinChain() bool {
return chain.Consensus == Consensus_bitcoin
}

// DecodeAddressFromChainID decode the address string to bytes
func DecodeAddressFromChainID(chainID int64, addr string) ([]byte, error) {
if IsEVMChain(chainID) {
// additionalChains is a list of additional chains to search from
// in practice, it is used in the protocol to dynamically support new chains without doing an upgrade
func DecodeAddressFromChainID(chainID int64, addr string, additionalChains []Chain) ([]byte, error) {
switch {
case IsEVMChain(chainID, additionalChains):
return ethcommon.HexToAddress(addr).Bytes(), nil
} else if IsBitcoinChain(chainID) {
case IsBitcoinChain(chainID, additionalChains):
return []byte(addr), nil
default:
return nil, fmt.Errorf("chain (%d) not supported", chainID)
}
return nil, fmt.Errorf("chain (%d) not supported", chainID)
}

// IsEVMChain returns true if the chain is an EVM chain or uses the ethereum consensus mechanism for block finality
func IsEVMChain(chainID int64) bool {
return ChainIDInChainList(chainID, ChainListByConsensus(Consensus_ethereum))
// additionalChains is a list of additional chains to search from
// in practice, it is used in the protocol to dynamically support new chains without doing an upgrade
func IsEVMChain(chainID int64, additionalChains []Chain) bool {
return ChainIDInChainList(chainID, ChainListByConsensus(Consensus_ethereum, additionalChains))
}

// IsBitcoinChain returns true if the chain is a Bitcoin-based chain or uses the bitcoin consensus mechanism for block finality
func IsBitcoinChain(chainID int64) bool {
return ChainIDInChainList(chainID, ChainListByConsensus(Consensus_bitcoin))
// additionalChains is a list of additional chains to search from
// in practice, it is used in the protocol to dynamically support new chains without doing an upgrade
func IsBitcoinChain(chainID int64, additionalChains []Chain) bool {
return ChainIDInChainList(chainID, ChainListByConsensus(Consensus_bitcoin, additionalChains))
}

// IsEthereumChain returns true if the chain is an Ethereum chain
func IsEthereumChain(chainID int64) bool {
return ChainIDInChainList(chainID, ChainListByNetwork(Network_eth))
// additionalChains is a list of additional chains to search from
// in practice, it is used in the protocol to dynamically support new chains without doing an upgrade
func IsEthereumChain(chainID int64, additionalChains []Chain) bool {
return ChainIDInChainList(chainID, ChainListByNetwork(Network_eth, additionalChains))
}

// IsZetaChain returns true if the chain is a Zeta chain
func IsZetaChain(chainID int64) bool {
return ChainIDInChainList(chainID, ChainListByNetwork(Network_zeta))
}

// IsHeaderSupportedChain returns true if the chain's consensus supports block header-based verification
func IsHeaderSupportedChain(chainID int64) bool {
return ChainIDInChainList(chainID, ChainListForHeaderSupport())
}

// SupportMerkleProof returns true if the chain supports block header-based verification
func (chain Chain) SupportMerkleProof() bool {
return IsEVMChain(chain.ChainId) || IsBitcoinChain(chain.ChainId)
// additionalChains is a list of additional chains to search from
// in practice, it is used in the protocol to dynamically support new chains without doing an upgrade
func IsZetaChain(chainID int64, additionalChains []Chain) bool {
return ChainIDInChainList(chainID, ChainListByNetwork(Network_zeta, additionalChains))
}

// IsEmpty is to determinate whether the chain is empty
func (chain Chain) IsEmpty() bool {
return strings.TrimSpace(chain.String()) == ""
}

// Has check whether chain c is in the list
func (chains Chains) Has(c Chain) bool {
for _, ch := range chains {
if ch.IsEqual(c) {
return true
}
}
return false
}

// Distinct return a distinct set of chains, no duplicates
func (chains Chains) Distinct() Chains {
var newChains Chains
for _, chain := range chains {
if !newChains.Has(chain) {
newChains = append(newChains, chain)
}
}
return newChains
}

func (chains Chains) Strings() []string {
str := make([]string, len(chains))
for i, c := range chains {
str[i] = c.String()
}
return str
}

func GetChainFromChainID(chainID int64) *Chain {
chains := DefaultChainsList()
// GetChainFromChainID returns the chain from the chain ID
// additionalChains is a list of additional chains to search from
// in practice, it is used in the protocol to dynamically support new chains without doing an upgrade
func GetChainFromChainID(chainID int64, additionalChains []Chain) (Chain, bool) {
chains := CombineDefaultChainsList(additionalChains)
for _, chain := range chains {
if chainID == chain.ChainId {
return chain
return chain, true
}
}
return nil
return Chain{}, false
}

// GetBTCChainParams returns the bitcoin chain config params from the chain ID
func GetBTCChainParams(chainID int64) (*chaincfg.Params, error) {
switch chainID {
case 18444:
Expand All @@ -201,6 +158,7 @@ func GetBTCChainParams(chainID int64) (*chaincfg.Params, error) {
}
}

// GetBTCChainIDFromChainParams returns the bitcoin chain ID from the chain config params
func GetBTCChainIDFromChainParams(params *chaincfg.Params) (int64, error) {
switch params.Name {
case chaincfg.RegressionNetParams.Name:
Expand All @@ -214,13 +172,8 @@ func GetBTCChainIDFromChainParams(params *chaincfg.Params) (int64, error) {
}
}

// InChainList checks whether the chain is in the chain list
func (chain Chain) InChainList(chainList []*Chain) bool {
return ChainIDInChainList(chain.ChainId, chainList)
}

// ChainIDInChainList checks whether the chainID is in the chain list
func ChainIDInChainList(chainID int64, chainList []*Chain) bool {
func ChainIDInChainList(chainID int64, chainList []Chain) bool {
for _, c := range chainList {
if chainID == c.ChainId {
return true
Expand Down
Loading

0 comments on commit 8982129

Please sign in to comment.