github.com/elastos/Elastos.ELA.SideChain.ETH@v0.2.2/chainbridge-core/config/config.go (about)

     1  // Copyright 2020 ChainSafe Systems
     2  // SPDX-License-Identifier: LGPL-3.0-only
     3  
     4  package config
     5  
     6  import (
     7  	"encoding/json"
     8  	"fmt"
     9  	"os"
    10  	"path/filepath"
    11  
    12  	"github.com/elastos/Elastos.ELA.SideChain.ESC/chainbridge-core/bridgelog"
    13  	"github.com/elastos/Elastos.ELA.SideChain.ESC/chainbridge-core/crypto/secp256k1"
    14  )
    15  
    16  var (
    17  	DefaultConfigDir    = "./chainbridge/config/chain_bridge.json"
    18  	KeystoreFlagName    = "./data/keystore/"
    19  	BlockstoreFlagName  = "./chainbridge/blockstore"
    20  	FreshStartFlagName  = "fresh"
    21  	LatestBlockFlagName = "latest"
    22  )
    23  
    24  type GeneralChainConfig struct {
    25  	Name           string `json:"name"`     // Human-readable chain name
    26  	Id             uint64 `json:"id"`       //ChainID
    27  	Endpoint       string `json:"endpoint"` // url for rpc endpoint
    28  	From           string `json:"from"`     // address of key to use
    29  	KeystorePath   string // Location of key files
    30  	Insecure       bool   // Indicated whether the test keyring should be used
    31  	BlockstorePath string // Location of blockstore
    32  	FreshStart     bool   // If true, blockstore is ignored at start.
    33  	LatestBlock    bool   // If true, overrides blockstore or latest block in config and starts from current block
    34  	Opts           OpsConfig
    35  	Kp             *secp256k1.Keypair
    36  }
    37  
    38  func (c *GeneralChainConfig) Validate() error {
    39  	// viper defaults to 0 for not specified ints, but we must have a valid chain id
    40  	// Previous method of checking used a string cast like below
    41  	//chainId := string(c.Id)
    42  	if c.Id == 0 {
    43  		return fmt.Errorf("required field chain.Id empty for chain %v", c.Id)
    44  	}
    45  	if c.Endpoint == "" {
    46  		return fmt.Errorf("required field chain.Endpoint empty for chain %v", c.Id)
    47  	}
    48  	if c.Name == "" {
    49  		return fmt.Errorf("required field chain.Name empty for chain %v", c.Id)
    50  	}
    51  	if err := c.Opts.Validate(); err != nil {
    52  		return err
    53  	}
    54  	return nil
    55  }
    56  
    57  type BridgeConfig struct {
    58  	Chains []GeneralChainConfig `json:"chains"`
    59  }
    60  
    61  func NewConfig() *BridgeConfig {
    62  	return &BridgeConfig{
    63  		Chains: []GeneralChainConfig{},
    64  	}
    65  }
    66  
    67  func (c *BridgeConfig) validateAndParse() error {
    68  	for _, chain := range c.Chains {
    69  		err := chain.Validate()
    70  		if err != nil {
    71  			return err
    72  		}
    73  		ops, err := chain.Opts.ParseConfig()
    74  		if err != nil {
    75  			return err
    76  		}
    77  		chain.Opts = *ops
    78  	}
    79  	return nil
    80  }
    81  
    82  func GetConfig(path string) (*BridgeConfig, error) {
    83  	var fig = NewConfig()
    84  	if path == "" {
    85  		path = DefaultConfigDir
    86  	}
    87  
    88  	err := loadConfig(path, fig)
    89  	if err != nil {
    90  		bridgelog.Warn("err loading json file", "err", err.Error())
    91  		return fig, err
    92  	}
    93  
    94  	err = fig.validateAndParse()
    95  	if err != nil {
    96  		return nil, err
    97  	}
    98  	return fig, nil
    99  }
   100  
   101  func loadConfig(file string, config *BridgeConfig) error {
   102  	ext := filepath.Ext(file)
   103  	fp, err := filepath.Abs(file)
   104  	if err != nil {
   105  		return err
   106  	}
   107  	f, err := os.Open(filepath.Clean(fp))
   108  	if err != nil {
   109  		return err
   110  	}
   111  
   112  	if ext == ".json" {
   113  		if err = json.NewDecoder(f).Decode(&config); err != nil {
   114  			return err
   115  		}
   116  	} else {
   117  		return fmt.Errorf("unrecognized extention: %s", ext)
   118  	}
   119  	return nil
   120  }