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 }