github.com/turingchain2020/turingchain@v1.1.21/types/config.go (about)

     1  // Copyright Turing Corp. 2018 All Rights Reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package types
     6  
     7  import (
     8  	"bytes"
     9  	"encoding/json"
    10  	"io/ioutil"
    11  	"strconv"
    12  	"strings"
    13  	"sync"
    14  
    15  	"fmt"
    16  
    17  	"github.com/turingchain2020/turingchain/common/address"
    18  	"github.com/turingchain2020/turingchain/types/chaincfg"
    19  	tml "github.com/BurntSushi/toml"
    20  )
    21  
    22  //Create ...
    23  type Create func(cfg *TuringchainConfig)
    24  
    25  //区块链共识相关的参数,重要参数不要随便修改
    26  var (
    27  	AllowUserExec = [][]byte{ExecerNone}
    28  	EmptyValue    = []byte("FFFFFFFFemptyBVBiCj5jvE15pEiwro8TQRGnJSNsJF") //这字符串表示数据库中的空值
    29  	cliSysParam   = make(map[string]*TuringchainConfig)                       // map key is title
    30  	regModuleInit = make(map[string]Create)
    31  	regExecInit   = make(map[string]Create)
    32  	runonce       = sync.Once{}
    33  )
    34  
    35  // coin conversation
    36  const (
    37  	Coin            int64 = 1e8
    38  	MaxCoin         int64 = 1e17
    39  	MaxTxSize             = 100000 //100K
    40  	MaxTxGroupSize  int32 = 20
    41  	MaxBlockSize          = 20000000 //20M
    42  	MaxTxsPerBlock        = 100000
    43  	TokenPrecision  int64 = 1e8
    44  	MaxTokenBalance int64 = 900 * 1e8 * TokenPrecision //900亿
    45  	DefaultMinFee   int64 = 1e5
    46  )
    47  
    48  //TuringchainConfig ...
    49  type TuringchainConfig struct {
    50  	mcfg       *Config
    51  	scfg       *ConfigSubModule
    52  	minerExecs []string
    53  	title      string
    54  
    55  	mu              sync.Mutex
    56  	chainConfig     map[string]interface{}
    57  	mver            *mversion
    58  	coinSymbol      string
    59  	forks           *Forks
    60  	enableCheckFork bool
    61  	chainID         int32
    62  }
    63  
    64  //ChainParam 结构体
    65  type ChainParam struct {
    66  	MaxTxNumber  int64
    67  	PowLimitBits uint32
    68  }
    69  
    70  //RegFork Reg 注册每个模块的自动初始化函数
    71  func RegFork(name string, create Create) {
    72  	if create == nil {
    73  		panic("config: Register Module Init is nil")
    74  	}
    75  	if _, dup := regModuleInit[name]; dup {
    76  		panic("config: Register Init called twice for driver " + name)
    77  	}
    78  	regModuleInit[name] = create
    79  }
    80  
    81  //RegForkInit ...
    82  func RegForkInit(cfg *TuringchainConfig) {
    83  	for _, item := range regModuleInit {
    84  		item(cfg)
    85  	}
    86  }
    87  
    88  //RegExec ...
    89  func RegExec(name string, create Create) {
    90  	if create == nil {
    91  		panic("config: Register Exec Init is nil")
    92  	}
    93  	if _, dup := regExecInit[name]; dup {
    94  		panic("config: Register Exec called twice for driver " + name)
    95  	}
    96  	regExecInit[name] = create
    97  }
    98  
    99  //RegExecInit ...
   100  func RegExecInit(cfg *TuringchainConfig) {
   101  	runonce.Do(func() {
   102  		for _, item := range regExecInit {
   103  			item(cfg)
   104  		}
   105  	})
   106  }
   107  
   108  //NewTuringchainConfig ...
   109  func NewTuringchainConfig(cfgstring string) *TuringchainConfig {
   110  	turingchainCfg := NewTuringchainConfigNoInit(cfgstring)
   111  	turingchainCfg.turingchainCfgInit(turingchainCfg.mcfg)
   112  	return turingchainCfg
   113  }
   114  
   115  //NewTuringchainConfigNoInit ...
   116  func NewTuringchainConfigNoInit(cfgstring string) *TuringchainConfig {
   117  	cfg, sub := InitCfgString(cfgstring)
   118  	turingchainCfg := &TuringchainConfig{
   119  		mcfg:        cfg,
   120  		scfg:        sub,
   121  		minerExecs:  []string{"ticket"}, //挖矿的合约名单,适配旧配置,默认ticket
   122  		title:       cfg.Title,
   123  		chainConfig: make(map[string]interface{}),
   124  		coinSymbol:  "trc",
   125  		forks:       &Forks{make(map[string]int64)},
   126  		chainID:     cfg.ChainID,
   127  	}
   128  	// 先将每个模块的fork初始化到TuringchainConfig中,然后如果需要再将toml中的替换
   129  	turingchainCfg.setDefaultConfig()
   130  	turingchainCfg.setFlatConfig(cfgstring)
   131  	turingchainCfg.setMver(cfgstring)
   132  	// TODO 需要测试是否与NewTuringchainConfig分开
   133  	RegForkInit(turingchainCfg)
   134  	RegExecInit(turingchainCfg)
   135  
   136  	//设置生成账户地址的版本号
   137  	address.SetNormalAddrVer(cfg.AddrVer)
   138  
   139  	return turingchainCfg
   140  }
   141  
   142  //GetModuleConfig ...
   143  func (c *TuringchainConfig) GetModuleConfig() *Config {
   144  	return c.mcfg
   145  }
   146  
   147  //GetSubConfig ...
   148  func (c *TuringchainConfig) GetSubConfig() *ConfigSubModule {
   149  	return c.scfg
   150  }
   151  
   152  //EnableCheckFork ...
   153  func (c *TuringchainConfig) EnableCheckFork(enable bool) {
   154  	c.enableCheckFork = false
   155  }
   156  
   157  //GetForks ...
   158  func (c *TuringchainConfig) GetForks() (map[string]int64, error) {
   159  	if c.forks == nil {
   160  		return nil, ErrNotFound
   161  	}
   162  	return c.forks.forks, nil
   163  }
   164  
   165  func (c *TuringchainConfig) setDefaultConfig() {
   166  	c.S("TestNet", false)
   167  	c.SetMinFee(DefaultMinFee)
   168  	for key, cfg := range chaincfg.LoadAll() {
   169  		c.S("cfg."+key, cfg)
   170  	}
   171  	//防止报error 错误,不影响功能
   172  	if !c.HasConf("cfg.turingchain") {
   173  		c.S("cfg.turingchain", "")
   174  	}
   175  	if !c.HasConf("cfg.local") {
   176  		c.S("cfg.local", "")
   177  	}
   178  }
   179  
   180  func (c *TuringchainConfig) setFlatConfig(cfgstring string) {
   181  	c.mu.Lock()
   182  	defer c.mu.Unlock()
   183  	cfg := make(map[string]interface{})
   184  	if _, err := tml.Decode(cfgstring, &cfg); err != nil {
   185  		panic(err)
   186  	}
   187  	flat := FlatConfig(cfg)
   188  	for k, v := range flat {
   189  		c.setChainConfig("config."+k, v)
   190  	}
   191  }
   192  
   193  func (c *TuringchainConfig) setChainConfig(key string, value interface{}) {
   194  	c.chainConfig[key] = value
   195  }
   196  
   197  func (c *TuringchainConfig) getChainConfig(key string) (value interface{}, err error) {
   198  	if data, ok := c.chainConfig[key]; ok {
   199  		return data, nil
   200  	}
   201  	//报错警告
   202  	tlog.Error("chain config " + key + " not found")
   203  	return nil, ErrNotFound
   204  }
   205  
   206  // Init 初始化
   207  func (c *TuringchainConfig) turingchainCfgInit(cfg *Config) {
   208  	c.mu.Lock()
   209  	defer c.mu.Unlock()
   210  
   211  	if c.forks == nil {
   212  		c.forks = &Forks{}
   213  	}
   214  	c.forks.SetTestNetFork()
   215  
   216  	if cfg != nil {
   217  		if c.isLocal() {
   218  			c.setTestNet(true)
   219  		} else {
   220  			c.setTestNet(cfg.TestNet)
   221  		}
   222  
   223  		if cfg.Wallet.MinFee < cfg.Mempool.MinTxFeeRate {
   224  			panic("config must meet: wallet.minFee >= mempool.minTxFeeRate")
   225  		}
   226  		if cfg.Mempool.MaxTxFeeRate == 0 {
   227  			cfg.Mempool.MaxTxFeeRate = 1e7 //0.1 coins
   228  		}
   229  		if cfg.Mempool.MaxTxFee == 0 {
   230  			cfg.Mempool.MaxTxFee = 1e9 // 10 coins
   231  		}
   232  		c.setTxFeeConfig(cfg.Mempool.MinTxFeeRate, cfg.Mempool.MaxTxFeeRate, cfg.Mempool.MaxTxFee)
   233  		if cfg.Consensus != nil {
   234  			c.setMinerExecs(cfg.Consensus.MinerExecs)
   235  		}
   236  		c.setChainConfig("FixTime", cfg.FixTime)
   237  		if cfg.CoinSymbol != "" {
   238  			if strings.Contains(cfg.CoinSymbol, "-") {
   239  				panic("config CoinSymbol must without '-'")
   240  			}
   241  			c.coinSymbol = cfg.CoinSymbol
   242  		} else {
   243  			if c.isPara() {
   244  				panic("must config CoinSymbol in para chain")
   245  			} else {
   246  				c.coinSymbol = DefaultCoinsSymbol
   247  			}
   248  		}
   249  		//TxHeight
   250  		c.setChainConfig("TxHeight", cfg.TxHeight)
   251  	}
   252  	if c.needSetForkZero() { //local 只用于单元测试
   253  		if c.isLocal() {
   254  			c.forks.setLocalFork()
   255  			c.setChainConfig("Debug", true)
   256  		} else {
   257  			c.forks.setForkForParaZero()
   258  		}
   259  	} else {
   260  		if cfg != nil && cfg.Fork != nil {
   261  			c.initForkConfig(cfg.Fork)
   262  		}
   263  	}
   264  	// 更新fork配置信息
   265  	if c.mver != nil {
   266  		c.mver.UpdateFork(c.forks)
   267  	}
   268  }
   269  
   270  func (c *TuringchainConfig) needSetForkZero() bool {
   271  	if c.isLocal() {
   272  		return true
   273  	} else if c.isPara() &&
   274  		(c.mcfg == nil || c.mcfg.Fork == nil || c.mcfg.Fork.System == nil) &&
   275  		!c.mcfg.EnableParaFork {
   276  		//如果para 没有配置fork,那么默认所有的fork 为 0(一般只用于测试)
   277  		return true
   278  	}
   279  	return false
   280  }
   281  
   282  func (c *TuringchainConfig) setTestNet(isTestNet bool) {
   283  	if !isTestNet {
   284  		c.setChainConfig("TestNet", false)
   285  		return
   286  	}
   287  	c.setChainConfig("TestNet", true)
   288  	//const 初始化TestNet 的初始化参数
   289  }
   290  
   291  // GetP 获取ChainParam
   292  func (c *TuringchainConfig) GetP(height int64) *ChainParam {
   293  	conf := Conf(c, "mver.consensus")
   294  	chain := &ChainParam{}
   295  	chain.MaxTxNumber = conf.MGInt("maxTxNumber", height)
   296  	chain.PowLimitBits = uint32(conf.MGInt("powLimitBits", height))
   297  	return chain
   298  }
   299  
   300  // GetMinerExecs 获取挖矿的合约名单
   301  func (c *TuringchainConfig) GetMinerExecs() []string {
   302  	return c.minerExecs
   303  }
   304  
   305  func (c *TuringchainConfig) setMinerExecs(execs []string) {
   306  	if len(execs) > 0 {
   307  		c.minerExecs = execs
   308  	}
   309  }
   310  
   311  // GetFundAddr 获取基金账户地址
   312  func (c *TuringchainConfig) GetFundAddr() string {
   313  	return c.MGStr("mver.consensus.fundKeyAddr", 0)
   314  }
   315  
   316  // G 获取ChainConfig中的配置
   317  func (c *TuringchainConfig) G(key string) (value interface{}, err error) {
   318  	c.mu.Lock()
   319  	defer c.mu.Unlock()
   320  	value, err = c.getChainConfig(key)
   321  	return
   322  }
   323  
   324  // MG 获取mver config中的配置
   325  func (c *TuringchainConfig) MG(key string, height int64) (value interface{}, err error) {
   326  	c.mu.Lock()
   327  	defer c.mu.Unlock()
   328  	if c.mver == nil {
   329  		panic("mver is nil")
   330  	}
   331  	return c.mver.Get(key, height)
   332  }
   333  
   334  // GStr 获取ChainConfig中的字符串格式
   335  func (c *TuringchainConfig) GStr(name string) string {
   336  	value, err := c.G(name)
   337  	if err != nil {
   338  		return ""
   339  	}
   340  	if i, ok := value.(string); ok {
   341  		return i
   342  	}
   343  	return ""
   344  }
   345  
   346  // MGStr 获取mver config 中的字符串格式
   347  func (c *TuringchainConfig) MGStr(name string, height int64) string {
   348  	value, err := c.MG(name, height)
   349  	if err != nil {
   350  		return ""
   351  	}
   352  	if i, ok := value.(string); ok {
   353  		return i
   354  	}
   355  	return ""
   356  }
   357  
   358  func parseInt(value interface{}) int64 {
   359  	if i, ok := value.(int64); ok {
   360  		return i
   361  	}
   362  	if s, ok := value.(string); ok {
   363  		if strings.HasPrefix(s, "0x") {
   364  			i, err := strconv.ParseUint(s, 0, 64)
   365  			if err == nil {
   366  				return int64(i)
   367  			}
   368  		}
   369  	}
   370  	return 0
   371  }
   372  
   373  // GInt 解析ChainConfig配置
   374  func (c *TuringchainConfig) GInt(name string) int64 {
   375  	value, err := c.G(name)
   376  	if err != nil {
   377  		return 0
   378  	}
   379  	return parseInt(value)
   380  }
   381  
   382  // MGInt 解析mver config 配置
   383  func (c *TuringchainConfig) MGInt(name string, height int64) int64 {
   384  	value, err := c.MG(name, height)
   385  	if err != nil {
   386  		return 0
   387  	}
   388  	return parseInt(value)
   389  }
   390  
   391  // IsEnable 解析ChainConfig配置
   392  func (c *TuringchainConfig) IsEnable(name string) bool {
   393  	isenable, err := c.G(name)
   394  	if err == nil && isenable.(bool) {
   395  		return true
   396  	}
   397  	return false
   398  }
   399  
   400  // MIsEnable 解析mver config 配置
   401  func (c *TuringchainConfig) MIsEnable(name string, height int64) bool {
   402  	isenable, err := c.MG(name, height)
   403  	if err == nil && isenable.(bool) {
   404  		return true
   405  	}
   406  	return false
   407  }
   408  
   409  // HasConf 解析chainConfig配置
   410  func (c *TuringchainConfig) HasConf(key string) bool {
   411  	c.mu.Lock()
   412  	defer c.mu.Unlock()
   413  	_, ok := c.chainConfig[key]
   414  	return ok
   415  }
   416  
   417  // S 设置chainConfig配置
   418  func (c *TuringchainConfig) S(key string, value interface{}) {
   419  	c.mu.Lock()
   420  	defer c.mu.Unlock()
   421  	if strings.HasPrefix(key, "config.") {
   422  		if !c.isLocal() && !c.isTestPara() { //only local and test para can modify for test
   423  			panic("prefix config. is readonly")
   424  		} else {
   425  			tlog.Error("modify " + key + " is only for test")
   426  		}
   427  	}
   428  	c.setChainConfig(key, value)
   429  }
   430  
   431  //SetTitleOnlyForTest set title only for test use
   432  func (c *TuringchainConfig) SetTitleOnlyForTest(ti string) {
   433  	c.mu.Lock()
   434  	defer c.mu.Unlock()
   435  	c.title = ti
   436  
   437  }
   438  
   439  // GetTitle 获取title
   440  func (c *TuringchainConfig) GetTitle() string {
   441  	c.mu.Lock()
   442  	defer c.mu.Unlock()
   443  	return c.title
   444  }
   445  
   446  // GetCoinSymbol 获取 coin symbol
   447  func (c *TuringchainConfig) GetCoinSymbol() string {
   448  	c.mu.Lock()
   449  	defer c.mu.Unlock()
   450  	return c.coinSymbol
   451  }
   452  
   453  func (c *TuringchainConfig) isLocal() bool {
   454  	return c.title == "local"
   455  }
   456  
   457  // IsLocal 是否locak title
   458  func (c *TuringchainConfig) IsLocal() bool {
   459  	c.mu.Lock()
   460  	defer c.mu.Unlock()
   461  	return c.isLocal()
   462  }
   463  
   464  // GetMinTxFeeRate get min transaction fee rate
   465  func (c *TuringchainConfig) GetMinTxFeeRate() int64 {
   466  	return c.GInt("MinTxFeeRate")
   467  }
   468  
   469  // GetMaxTxFeeRate get max transaction fee rate
   470  func (c *TuringchainConfig) GetMaxTxFeeRate() int64 {
   471  	return c.GInt("MaxTxFeeRate")
   472  }
   473  
   474  // GetMaxTxFee get max transaction fee
   475  func (c *TuringchainConfig) GetMaxTxFee() int64 {
   476  	return c.GInt("MaxTxFee")
   477  }
   478  
   479  // SetTxFeeConfig 设置交易费相关配置
   480  func (c *TuringchainConfig) SetTxFeeConfig(minTxFeeRate, maxTxFeeRate, maxTxFee int64) {
   481  	c.mu.Lock()
   482  	defer c.mu.Unlock()
   483  	c.setTxFeeConfig(minTxFeeRate, maxTxFeeRate, maxTxFee)
   484  }
   485  
   486  func (c *TuringchainConfig) setTxFeeConfig(minTxFeeRate, maxTxFeeRate, maxTxFee int64) {
   487  	if minTxFeeRate < 0 {
   488  		panic("minTxFeeRate less than zero")
   489  	}
   490  
   491  	if minTxFeeRate > maxTxFeeRate || maxTxFeeRate > maxTxFee {
   492  		panic("SetTxFee, tx fee must meet, minTxFeeRate <= maxTxFeeRate <= maxTxFee")
   493  	}
   494  	c.setChainConfig("MinTxFeeRate", minTxFeeRate)
   495  	c.setChainConfig("MaxTxFeeRate", maxTxFeeRate)
   496  	c.setChainConfig("MaxTxFee", maxTxFee)
   497  	c.setChainConfig("MinBalanceTransfer", minTxFeeRate*10)
   498  }
   499  
   500  // SetMinFee 设置最小费用
   501  func (c *TuringchainConfig) SetMinFee(fee int64) {
   502  	c.mu.Lock()
   503  	defer c.mu.Unlock()
   504  	c.setTxFeeConfig(fee, fee*100, fee*10000)
   505  }
   506  
   507  func (c *TuringchainConfig) isPara() bool {
   508  	return strings.Count(c.title, ".") == 3 && strings.HasPrefix(c.title, ParaKeyX)
   509  }
   510  
   511  func (c *TuringchainConfig) isTestPara() bool {
   512  	return strings.Count(c.title, ".") == 3 && strings.HasPrefix(c.title, ParaKeyX) && strings.HasSuffix(c.title, "test.")
   513  }
   514  
   515  // IsPara 是否平行链
   516  func (c *TuringchainConfig) IsPara() bool {
   517  	c.mu.Lock()
   518  	defer c.mu.Unlock()
   519  	return c.isPara()
   520  }
   521  
   522  // IsParaExecName 是否平行链执行器
   523  func IsParaExecName(exec string) bool {
   524  	return strings.HasPrefix(exec, ParaKeyX)
   525  }
   526  
   527  //IsMyParaExecName 是否是我的para链的执行器
   528  func (c *TuringchainConfig) IsMyParaExecName(exec string) bool {
   529  	return IsParaExecName(exec) && strings.HasPrefix(exec, c.GetTitle())
   530  }
   531  
   532  //IsSpecificParaExecName 是否是某一个平行链的执行器
   533  func IsSpecificParaExecName(title, exec string) bool {
   534  	return IsParaExecName(exec) && strings.HasPrefix(exec, title)
   535  }
   536  
   537  //GetParaExecTitleName 如果是平行链执行器,获取对应title
   538  func GetParaExecTitleName(exec string) (string, bool) {
   539  	if IsParaExecName(exec) {
   540  		for i := len(ParaKey); i < len(exec); i++ {
   541  			if exec[i] == '.' {
   542  				return exec[:i+1], true
   543  			}
   544  		}
   545  	}
   546  	return "", false
   547  }
   548  
   549  // IsTestNet 是否测试链
   550  func (c *TuringchainConfig) IsTestNet() bool {
   551  	return c.IsEnable("TestNet")
   552  }
   553  
   554  // GetParaName 获取平行链name
   555  func (c *TuringchainConfig) GetParaName() string {
   556  	if c.IsPara() {
   557  		return c.GetTitle()
   558  	}
   559  	return ""
   560  }
   561  
   562  // FlagKV 获取kv对
   563  func FlagKV(key []byte, value int64) *KeyValue {
   564  	return &KeyValue{Key: key, Value: Encode(&Int64{Data: value})}
   565  }
   566  
   567  // MergeConfig Merge配置
   568  func MergeConfig(conf map[string]interface{}, def map[string]interface{}) string {
   569  	errstr := checkConfig("", conf, def)
   570  	if errstr != "" {
   571  		return errstr
   572  	}
   573  	mergeConfig(conf, def)
   574  	return ""
   575  }
   576  
   577  //检查默认配置文件
   578  func checkConfig(key string, conf map[string]interface{}, def map[string]interface{}) string {
   579  	errstr := ""
   580  	for key1, value1 := range conf {
   581  		if vdef, ok := def[key1]; ok {
   582  			conf1, ok1 := value1.(map[string]interface{})
   583  			def1, ok2 := vdef.(map[string]interface{})
   584  			if ok1 && ok2 {
   585  				errstr += checkConfig(getkey(key, key1), conf1, def1)
   586  			} else {
   587  				errstr += "rewrite defalut key " + getkey(key, key1) + "\n"
   588  			}
   589  		}
   590  	}
   591  	return errstr
   592  }
   593  
   594  func mergeConfig(conf map[string]interface{}, def map[string]interface{}) {
   595  	for key1, value1 := range def {
   596  		if vdef, ok := conf[key1]; ok {
   597  			conf1, ok1 := value1.(map[string]interface{})
   598  			def1, ok2 := vdef.(map[string]interface{})
   599  			if ok1 && ok2 {
   600  				mergeConfig(conf1, def1)
   601  				conf[key1] = conf1
   602  			}
   603  		} else {
   604  			conf[key1] = value1
   605  		}
   606  	}
   607  }
   608  
   609  func getkey(key, key1 string) string {
   610  	if key == "" {
   611  		return key1
   612  	}
   613  	return key + "." + key1
   614  }
   615  
   616  //MergeCfg ...
   617  func MergeCfg(cfgstring, cfgdefault string) string {
   618  	if cfgdefault != "" {
   619  		return mergeCfgString(cfgstring, cfgdefault)
   620  	}
   621  	return cfgstring
   622  }
   623  
   624  func mergeCfgString(cfgstring, cfgdefault string) string {
   625  	//1. defconfig
   626  	def := make(map[string]interface{})
   627  	_, err := tml.Decode(cfgdefault, &def)
   628  	if err != nil {
   629  		panic(err)
   630  	}
   631  	//2. userconfig
   632  	conf := make(map[string]interface{})
   633  	_, err = tml.Decode(cfgstring, &conf)
   634  	if err != nil {
   635  		panic(err)
   636  	}
   637  	errstr := MergeConfig(conf, def)
   638  	if errstr != "" {
   639  		panic(errstr)
   640  	}
   641  	buf := new(bytes.Buffer)
   642  	tml.NewEncoder(buf).Encode(conf)
   643  	return buf.String()
   644  }
   645  
   646  func initCfgString(cfgstring string) (*Config, error) {
   647  	var cfg Config
   648  	if _, err := tml.Decode(cfgstring, &cfg); err != nil {
   649  		return nil, err
   650  	}
   651  	return &cfg, nil
   652  }
   653  
   654  // InitCfg 初始化配置
   655  func InitCfg(path string) (*Config, *ConfigSubModule) {
   656  	return InitCfgString(readFile(path))
   657  }
   658  
   659  func flatConfig(key string, conf map[string]interface{}, flat map[string]interface{}) {
   660  	for key1, value1 := range conf {
   661  		conf1, ok := value1.(map[string]interface{})
   662  		if ok {
   663  			flatConfig(getkey(key, key1), conf1, flat)
   664  		} else {
   665  			flat[getkey(key, key1)] = value1
   666  		}
   667  	}
   668  }
   669  
   670  // FlatConfig Flat配置
   671  func FlatConfig(conf map[string]interface{}) map[string]interface{} {
   672  	flat := make(map[string]interface{})
   673  	flatConfig("", conf, flat)
   674  	return flat
   675  }
   676  
   677  func (c *TuringchainConfig) setMver(cfgstring string) {
   678  	c.mu.Lock()
   679  	defer c.mu.Unlock()
   680  	c.mver = newMversion(cfgstring)
   681  }
   682  
   683  // InitCfgString 初始化配置
   684  func InitCfgString(cfgstring string) (*Config, *ConfigSubModule) {
   685  	//cfgstring = c.mergeCfg(cfgstring) // TODO 是否可以去除
   686  	//setFlatConfig(cfgstring)         // 将set的全部去除
   687  	cfg, err := initCfgString(cfgstring)
   688  	if err != nil {
   689  		panic(err)
   690  	}
   691  	//setMver(cfg.Title, cfgstring)    // 将set的全部去除
   692  	sub, err := initSubModuleString(cfgstring)
   693  	if err != nil {
   694  		panic(err)
   695  	}
   696  	return cfg, sub
   697  }
   698  
   699  //ReadFile ...
   700  func ReadFile(path string) string {
   701  	return readFile(path)
   702  }
   703  
   704  func readFile(path string) string {
   705  	data, err := ioutil.ReadFile(path)
   706  	if err != nil {
   707  		panic(err)
   708  	}
   709  	return string(data)
   710  }
   711  
   712  func initSubModuleString(cfgstring string) (*ConfigSubModule, error) {
   713  	var cfg subModule
   714  	if _, err := tml.Decode(cfgstring, &cfg); err != nil {
   715  		return nil, err
   716  	}
   717  	return parseSubModule(&cfg)
   718  }
   719  
   720  func parseSubModule(cfg *subModule) (*ConfigSubModule, error) {
   721  	var subcfg ConfigSubModule
   722  	subcfg.Store = parseItem(cfg.Store)
   723  	subcfg.Exec = parseItem(cfg.Exec)
   724  	subcfg.Consensus = parseItem(cfg.Consensus)
   725  	subcfg.Wallet = parseItem(cfg.Wallet)
   726  	subcfg.Mempool = parseItem(cfg.Mempool)
   727  	subcfg.Metrics = parseItem(cfg.Metrics)
   728  	subcfg.P2P = parseItem(cfg.P2P)
   729  	subcfg.Crypto = parseItem(cfg.Crypto)
   730  	return &subcfg, nil
   731  }
   732  
   733  //ModifySubConfig json data modify
   734  func ModifySubConfig(sub []byte, key string, value interface{}) ([]byte, error) {
   735  	var data map[string]interface{}
   736  	err := json.Unmarshal(sub, &data)
   737  	if err != nil {
   738  		return nil, err
   739  	}
   740  	data[key] = value
   741  	return json.Marshal(data)
   742  }
   743  
   744  func parseItem(data map[string]interface{}) map[string][]byte {
   745  	subconfig := make(map[string][]byte)
   746  	if len(data) == 0 {
   747  		return subconfig
   748  	}
   749  	for key := range data {
   750  		if key == "sub" {
   751  			subcfg := data[key].(map[string]interface{})
   752  			for k := range subcfg {
   753  				subconfig[k], _ = json.Marshal(subcfg[k])
   754  			}
   755  		}
   756  	}
   757  	return subconfig
   758  }
   759  
   760  // ConfQuery 结构体
   761  type ConfQuery struct {
   762  	cfg    *TuringchainConfig
   763  	prefix string
   764  }
   765  
   766  // Conf 配置
   767  func Conf(cfg *TuringchainConfig, prefix string) *ConfQuery {
   768  	if prefix == "" || (!strings.HasPrefix(prefix, "config.") && !strings.HasPrefix(prefix, "mver.")) {
   769  		panic("ConfQuery must init buy prefix config. or mver.")
   770  	}
   771  	return &ConfQuery{cfg: cfg, prefix: prefix}
   772  }
   773  
   774  // ConfSub 子模块配置
   775  func ConfSub(cfg *TuringchainConfig, name string) *ConfQuery {
   776  	return Conf(cfg, "config.exec.sub."+name)
   777  }
   778  
   779  // G 获取指定key的配置信息
   780  func (query *ConfQuery) G(key string) (interface{}, error) {
   781  	return query.cfg.G(getkey(query.prefix, key))
   782  }
   783  
   784  func parseStrList(data interface{}) []string {
   785  	var list []string
   786  	if item, ok := data.([]interface{}); ok {
   787  		for i := 0; i < len(item); i++ {
   788  			one, ok := item[i].(string)
   789  			if ok {
   790  				list = append(list, one)
   791  			}
   792  		}
   793  	}
   794  	return list
   795  }
   796  
   797  // GStrList 解析字符串列表
   798  func (query *ConfQuery) GStrList(key string) []string {
   799  	data, err := query.G(key)
   800  	if err == nil {
   801  		return parseStrList(data)
   802  	}
   803  	return []string{}
   804  }
   805  
   806  // GInt 解析int类型
   807  func (query *ConfQuery) GInt(key string) int64 {
   808  	return query.cfg.GInt(getkey(query.prefix, key))
   809  }
   810  
   811  // GStr 解析string类型
   812  func (query *ConfQuery) GStr(key string) string {
   813  	return query.cfg.GStr(getkey(query.prefix, key))
   814  }
   815  
   816  // IsEnable 解析bool类型
   817  func (query *ConfQuery) IsEnable(key string) bool {
   818  	return query.cfg.IsEnable(getkey(query.prefix, key))
   819  }
   820  
   821  // MG 解析mversion
   822  func (query *ConfQuery) MG(key string, height int64) (interface{}, error) {
   823  	return query.cfg.MG(getkey(query.prefix, key), height)
   824  }
   825  
   826  // MGInt 解析mversion int类型配置
   827  func (query *ConfQuery) MGInt(key string, height int64) int64 {
   828  	return query.cfg.MGInt(getkey(query.prefix, key), height)
   829  }
   830  
   831  // MGStr 解析mversion string类型配置
   832  func (query *ConfQuery) MGStr(key string, height int64) string {
   833  	return query.cfg.MGStr(getkey(query.prefix, key), height)
   834  }
   835  
   836  // MGStrList 解析mversion string list类型配置
   837  func (query *ConfQuery) MGStrList(key string, height int64) []string {
   838  	data, err := query.MG(key, height)
   839  	if err == nil {
   840  		return parseStrList(data)
   841  	}
   842  	return []string{}
   843  }
   844  
   845  // MIsEnable 解析mversion bool类型配置
   846  func (query *ConfQuery) MIsEnable(key string, height int64) bool {
   847  	return query.cfg.MIsEnable(getkey(query.prefix, key), height)
   848  }
   849  
   850  //SetCliSysParam ...
   851  func SetCliSysParam(title string, cfg *TuringchainConfig) {
   852  	if cfg == nil {
   853  		panic("set cli system TuringchainConfig param is nil")
   854  	}
   855  	cliSysParam[title] = cfg
   856  }
   857  
   858  //GetCliSysParam ...
   859  func GetCliSysParam(title string) *TuringchainConfig {
   860  	if v, ok := cliSysParam[title]; ok {
   861  		return v
   862  	}
   863  	panic(fmt.Sprintln("can not find CliSysParam title", title))
   864  }
   865  
   866  //AssertConfig ...
   867  func AssertConfig(check interface{}) {
   868  	if check == nil {
   869  		panic("check object is nil (TuringchainConfig)")
   870  	}
   871  }
   872  
   873  // GetChainID 获取链ID,提供给其他模块使用
   874  func (c *TuringchainConfig) GetChainID() int32 {
   875  	c.mu.Lock()
   876  	defer c.mu.Unlock()
   877  	return c.chainID
   878  }