github.com/iotexproject/iotex-core@v1.14.1-rc1/blockchain/config.go (about)

     1  // Copyright (c) 2022 IoTeX Foundation
     2  // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability
     3  // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed.
     4  // This source code is governed by Apache License 2.0 that can be found in the LICENSE file.
     5  
     6  package blockchain
     7  
     8  import (
     9  	"crypto/ecdsa"
    10  	"os"
    11  	"time"
    12  
    13  	"github.com/iotexproject/go-pkgs/crypto"
    14  	"github.com/iotexproject/iotex-address/address"
    15  	"github.com/iotexproject/iotex-election/committee"
    16  	"github.com/pkg/errors"
    17  	"go.uber.org/config"
    18  	"go.uber.org/zap"
    19  
    20  	"github.com/iotexproject/iotex-core/db"
    21  	"github.com/iotexproject/iotex-core/pkg/log"
    22  )
    23  
    24  type (
    25  	// Config is the config struct for blockchain package
    26  	Config struct {
    27  		ChainDBPath                string           `yaml:"chainDBPath"`
    28  		TrieDBPatchFile            string           `yaml:"trieDBPatchFile"`
    29  		TrieDBPath                 string           `yaml:"trieDBPath"`
    30  		StakingPatchDir            string           `yaml:"stakingPatchDir"`
    31  		IndexDBPath                string           `yaml:"indexDBPath"`
    32  		BloomfilterIndexDBPath     string           `yaml:"bloomfilterIndexDBPath"`
    33  		CandidateIndexDBPath       string           `yaml:"candidateIndexDBPath"`
    34  		StakingIndexDBPath         string           `yaml:"stakingIndexDBPath"`
    35  		SGDIndexDBPath             string           `yaml:"sgdIndexDBPath"`
    36  		ContractStakingIndexDBPath string           `yaml:"contractStakingIndexDBPath"`
    37  		ID                         uint32           `yaml:"id"`
    38  		EVMNetworkID               uint32           `yaml:"evmNetworkID"`
    39  		Address                    string           `yaml:"address"`
    40  		ProducerPrivKey            string           `yaml:"producerPrivKey"`
    41  		ProducerPrivKeySchema      string           `yaml:"producerPrivKeySchema"`
    42  		SignatureScheme            []string         `yaml:"signatureScheme"`
    43  		EmptyGenesis               bool             `yaml:"emptyGenesis"`
    44  		GravityChainDB             db.Config        `yaml:"gravityChainDB"`
    45  		Committee                  committee.Config `yaml:"committee"`
    46  
    47  		EnableTrielessStateDB bool `yaml:"enableTrielessStateDB"`
    48  		// EnableStateDBCaching enables cachedStateDBOption
    49  		EnableStateDBCaching bool `yaml:"enableStateDBCaching"`
    50  		// EnableArchiveMode is only meaningful when EnableTrielessStateDB is false
    51  		EnableArchiveMode bool `yaml:"enableArchiveMode"`
    52  		// EnableAsyncIndexWrite enables writing the block actions' and receipts' index asynchronously
    53  		EnableAsyncIndexWrite bool `yaml:"enableAsyncIndexWrite"`
    54  		// deprecated
    55  		EnableSystemLogIndexer bool `yaml:"enableSystemLog"`
    56  		// EnableStakingProtocol enables staking protocol
    57  		EnableStakingProtocol bool `yaml:"enableStakingProtocol"`
    58  		// EnableStakingIndexer enables staking indexer
    59  		EnableStakingIndexer bool `yaml:"enableStakingIndexer"`
    60  		// AllowedBlockGasResidue is the amount of gas remained when block producer could stop processing more actions
    61  		AllowedBlockGasResidue uint64 `yaml:"allowedBlockGasResidue"`
    62  		// MaxCacheSize is the max number of blocks that will be put into an LRU cache. 0 means disabled
    63  		MaxCacheSize int `yaml:"maxCacheSize"`
    64  		// PollInitialCandidatesInterval is the config for committee init db
    65  		PollInitialCandidatesInterval time.Duration `yaml:"pollInitialCandidatesInterval"`
    66  		// StateDBCacheSize is the max size of statedb LRU cache
    67  		StateDBCacheSize int `yaml:"stateDBCacheSize"`
    68  		// WorkingSetCacheSize is the max size of workingset cache in state factory
    69  		WorkingSetCacheSize uint64 `yaml:"workingSetCacheSize"`
    70  		// StreamingBlockBufferSize
    71  		StreamingBlockBufferSize uint64 `yaml:"streamingBlockBufferSize"`
    72  		// PersistStakingPatchBlock is the block to persist staking patch
    73  		PersistStakingPatchBlock uint64 `yaml:"persistStakingPatchBlock"`
    74  	}
    75  )
    76  
    77  var (
    78  	// DefaultConfig is the default config of chain
    79  	DefaultConfig = Config{
    80  		ChainDBPath:                "/var/data/chain.db",
    81  		TrieDBPatchFile:            "/var/data/trie.db.patch",
    82  		TrieDBPath:                 "/var/data/trie.db",
    83  		StakingPatchDir:            "/var/data",
    84  		IndexDBPath:                "/var/data/index.db",
    85  		BloomfilterIndexDBPath:     "/var/data/bloomfilter.index.db",
    86  		CandidateIndexDBPath:       "/var/data/candidate.index.db",
    87  		StakingIndexDBPath:         "/var/data/staking.index.db",
    88  		SGDIndexDBPath:             "/var/data/sgd.index.db",
    89  		ContractStakingIndexDBPath: "/var/data/contractstaking.index.db",
    90  		ID:                         1,
    91  		EVMNetworkID:               4689,
    92  		Address:                    "",
    93  		ProducerPrivKey:            generateRandomKey(SigP256k1),
    94  		SignatureScheme:            []string{SigP256k1},
    95  		EmptyGenesis:               false,
    96  		GravityChainDB:             db.Config{DbPath: "/var/data/poll.db", NumRetries: 10},
    97  		Committee: committee.Config{
    98  			GravityChainAPIs: []string{},
    99  		},
   100  		EnableTrielessStateDB:         true,
   101  		EnableStateDBCaching:          false,
   102  		EnableArchiveMode:             false,
   103  		EnableAsyncIndexWrite:         true,
   104  		EnableSystemLogIndexer:        false,
   105  		EnableStakingProtocol:         true,
   106  		EnableStakingIndexer:          false,
   107  		AllowedBlockGasResidue:        10000,
   108  		MaxCacheSize:                  0,
   109  		PollInitialCandidatesInterval: 10 * time.Second,
   110  		StateDBCacheSize:              1000,
   111  		WorkingSetCacheSize:           20,
   112  		StreamingBlockBufferSize:      200,
   113  		PersistStakingPatchBlock:      19778037,
   114  	}
   115  
   116  	// ErrConfig config error
   117  	ErrConfig = errors.New("config error")
   118  )
   119  
   120  // ProducerAddress returns the configured producer address derived from key
   121  func (cfg *Config) ProducerAddress() address.Address {
   122  	sk := cfg.ProducerPrivateKey()
   123  	addr := sk.PublicKey().Address()
   124  	if addr == nil {
   125  		log.L().Panic("Error when constructing producer address")
   126  	}
   127  	return addr
   128  }
   129  
   130  // ProducerPrivateKey returns the configured private key
   131  func (cfg *Config) ProducerPrivateKey() crypto.PrivateKey {
   132  	sk, err := crypto.HexStringToPrivateKey(cfg.ProducerPrivKey)
   133  	if err != nil {
   134  		log.L().Panic(
   135  			"Error when decoding private key",
   136  			zap.Error(err),
   137  		)
   138  	}
   139  
   140  	if !cfg.whitelistSignatureScheme(sk) {
   141  		log.L().Panic("The private key's signature scheme is not whitelisted")
   142  	}
   143  	return sk
   144  }
   145  
   146  // SetProducerPrivKey set producer privKey by PrivKeyConfigFile info
   147  func (cfg *Config) SetProducerPrivKey() error {
   148  	switch cfg.ProducerPrivKeySchema {
   149  	case "hex", "":
   150  		// do nothing
   151  	case "hashiCorpVault":
   152  		yaml, err := config.NewYAML(config.Expand(os.LookupEnv), config.File(cfg.ProducerPrivKey))
   153  		if err != nil {
   154  			return errors.Wrap(err, "failed to init private key config")
   155  		}
   156  		hcv := &hashiCorpVault{}
   157  		if err := yaml.Get(config.Root).Populate(hcv); err != nil {
   158  			return errors.Wrap(err, "failed to unmarshal YAML config to privKeyConfig struct")
   159  		}
   160  
   161  		loader, err := newVaultPrivKeyLoader(hcv)
   162  		if err != nil {
   163  			return errors.Wrap(err, "failed to new vault client")
   164  		}
   165  		key, err := loader.load()
   166  		if err != nil {
   167  			return errors.Wrap(err, "failed to load producer private key")
   168  		}
   169  		cfg.ProducerPrivKey = key
   170  	default:
   171  		return errors.Wrap(ErrConfig, "invalid private key schema")
   172  	}
   173  
   174  	return nil
   175  }
   176  
   177  func generateRandomKey(scheme string) string {
   178  	// generate a random key
   179  	switch scheme {
   180  	case SigP256k1:
   181  		sk, _ := crypto.GenerateKey()
   182  		return sk.HexString()
   183  	case SigP256sm2:
   184  		sk, _ := crypto.GenerateKeySm2()
   185  		return sk.HexString()
   186  	}
   187  	return ""
   188  }
   189  
   190  func (cfg *Config) whitelistSignatureScheme(sk crypto.PrivateKey) bool {
   191  	var sigScheme string
   192  
   193  	switch sk.EcdsaPrivateKey().(type) {
   194  	case *ecdsa.PrivateKey:
   195  		sigScheme = SigP256k1
   196  	case *crypto.P256sm2PrvKey:
   197  		sigScheme = SigP256sm2
   198  	}
   199  
   200  	if sigScheme == "" {
   201  		return false
   202  	}
   203  	for _, e := range cfg.SignatureScheme {
   204  		if sigScheme == e {
   205  			// signature scheme is whitelisted
   206  			return true
   207  		}
   208  	}
   209  	return false
   210  }