11 log "github.com/sirupsen/logrus"
13 "github.com/bytom/vapor/crypto/ed25519/chainkd"
17 // CommonConfig means config object
22 // Top level options use an anonymous struct
23 BaseConfig `mapstructure:",squash"`
24 // Options for services
25 P2P *P2PConfig `mapstructure:"p2p"`
26 Wallet *WalletConfig `mapstructure:"wallet"`
27 Auth *RPCAuthConfig `mapstructure:"auth"`
28 Web *WebConfig `mapstructure:"web"`
29 Websocket *WebsocketConfig `mapstructure:"ws"`
30 Federation *FederationConfig `mapstructure:"federation"`
31 CrossChain *CrossChainConfig `mapstructure:"cross_chain"`
34 // Default configurable parameters.
35 func DefaultConfig() *Config {
37 BaseConfig: DefaultBaseConfig(),
38 P2P: DefaultP2PConfig(),
39 Wallet: DefaultWalletConfig(),
40 Auth: DefaultRPCAuthConfig(),
41 Web: DefaultWebConfig(),
42 Websocket: DefaultWebsocketConfig(),
43 Federation: DefaultFederationConfig(),
44 CrossChain: DefaultCrossChainConfig(),
48 // Set the RootDir for all Config structs
49 func (cfg *Config) SetRoot(root string) *Config {
50 cfg.BaseConfig.RootDir = root
54 // NodeKey retrieves the currently configured private key of the node, checking
55 // first any manually set key, falling back to the one found in the configured
56 // data folder. If no key can be found, a new one is generated.
57 func (cfg *Config) PrivateKey() *chainkd.XPrv {
62 filePath := rootify(cfg.PrivateKeyFile, cfg.BaseConfig.RootDir)
63 fildReader, err := os.Open(filePath)
65 log.WithField("err", err).Panic("fail on open private key file")
68 defer fildReader.Close()
69 buf := make([]byte, 128)
70 if _, err = io.ReadFull(fildReader, buf); err != nil {
71 log.WithField("err", err).Panic("fail on read private key file")
75 if _, err := hex.Decode(xprv[:], buf); err != nil {
76 log.WithField("err", err).Panic("fail on decode private key")
80 xpub := cfg.XPrv.XPub()
85 //-----------------------------------------------------------------------------
87 type BaseConfig struct {
88 // The root directory for all data.
89 // This should be set in viper so it can unmarshal into this struct
90 RootDir string `mapstructure:"home"`
92 //The ID of the network to json
93 ChainID string `mapstructure:"chain_id"`
96 LogLevel string `mapstructure:"log_level"`
98 // A custom human readable name for this node
99 Moniker string `mapstructure:"moniker"`
101 // TCP or UNIX socket address for the profiling server to listen on
102 ProfListenAddress string `mapstructure:"prof_laddr"`
104 Mining bool `mapstructure:"mining"`
106 // Database backend: leveldb | memdb
107 DBBackend string `mapstructure:"db_backend"`
109 // Database directory
110 DBPath string `mapstructure:"db_dir"`
112 // Keystore directory
113 KeysPath string `mapstructure:"keys_dir"`
115 ApiAddress string `mapstructure:"api_addr"`
117 VaultMode bool `mapstructure:"vault_mode"`
120 LogFile string `mapstructure:"log_file"`
122 PrivateKeyFile string `mapstructure:"private_key_file"`
126 // Federation file name
127 FederationFileName string `mapstructure:"federation_file"`
130 // Default configurable base parameters.
131 func DefaultBaseConfig() BaseConfig {
133 Moniker: "anonymous",
134 ProfListenAddress: "",
136 DBBackend: "leveldb",
138 KeysPath: "keystore",
140 PrivateKeyFile: "node_key.txt",
141 FederationFileName: "federation.json",
145 func (b BaseConfig) DBDir() string {
146 return rootify(b.DBPath, b.RootDir)
149 func (b BaseConfig) LogDir() string {
150 return rootify(b.LogFile, b.RootDir)
153 func (b BaseConfig) KeysDir() string {
154 return rootify(b.KeysPath, b.RootDir)
157 func (b BaseConfig) FederationFile() string {
158 return rootify(b.FederationFileName, b.RootDir)
162 type P2PConfig struct {
163 ListenAddress string `mapstructure:"laddr"`
164 Seeds string `mapstructure:"seeds"`
165 SkipUPNP bool `mapstructure:"skip_upnp"`
166 LANDiscover bool `mapstructure:"lan_discoverable"`
167 MaxNumPeers int `mapstructure:"max_num_peers"`
168 HandshakeTimeout int `mapstructure:"handshake_timeout"`
169 DialTimeout int `mapstructure:"dial_timeout"`
170 ProxyAddress string `mapstructure:"proxy_address"`
171 ProxyUsername string `mapstructure:"proxy_username"`
172 ProxyPassword string `mapstructure:"proxy_password"`
173 KeepDial string `mapstructure:"keep_dial"`
174 Compression string `mapstructure:"compression_backend"`
177 // Default configurable p2p parameters.
178 func DefaultP2PConfig() *P2PConfig {
180 ListenAddress: "tcp://0.0.0.0:56656",
184 HandshakeTimeout: 30,
189 Compression: "snappy",
193 //-----------------------------------------------------------------------------
194 type WalletConfig struct {
195 Disable bool `mapstructure:"disable"`
196 Rescan bool `mapstructure:"rescan"`
197 TxIndex bool `mapstructure:"txindex"`
198 MaxTxFee uint64 `mapstructure:"max_tx_fee"`
201 type RPCAuthConfig struct {
202 Disable bool `mapstructure:"disable"`
205 type WebConfig struct {
206 Closed bool `mapstructure:"closed"`
209 type WebsocketConfig struct {
210 MaxNumWebsockets int `mapstructure:"max_num_websockets"`
211 MaxNumConcurrentReqs int `mapstructure:"max_num_concurrent_reqs"`
214 type FederationConfig struct {
215 Xpubs []chainkd.XPub `json:"xpubs"`
216 Quorum int `json:"quorum"`
219 type CrossChainConfig struct {
220 AssetWhitelist string `mapstructure:"asset_whitelist"`
223 // Default configurable rpc's auth parameters.
224 func DefaultRPCAuthConfig() *RPCAuthConfig {
225 return &RPCAuthConfig{
230 // Default configurable web parameters.
231 func DefaultWebConfig() *WebConfig {
237 // Default configurable wallet parameters.
238 func DefaultWalletConfig() *WalletConfig {
239 return &WalletConfig{
243 MaxTxFee: uint64(1000000000),
247 // Default configurable websocket parameters.
248 func DefaultWebsocketConfig() *WebsocketConfig {
249 return &WebsocketConfig{
250 MaxNumWebsockets: 25,
251 MaxNumConcurrentReqs: 20,
255 // Default configurable federation parameters.
256 func DefaultFederationConfig() *FederationConfig {
257 return &FederationConfig{
258 Xpubs: []chainkd.XPub{
259 xpub("580daf48fa8962100047cb1391da890bb7f2c849fdbc9b368cb4394a4c7cbb0977e2e7ebbf055dc0ef90af6a0d2af01ce7ec56b735d016aab597815ec48552e5"),
260 xpub("f3f6bcf61b65fa9d1566455a5688ca8b395efdc22e654963134b5e5cb0a45d8be522d21abc384a73177a7b9d64eba915fcfe2862d86a508a3c46dc410bdd72ad"),
261 xpub("53559612f2b7bcada18948b7de39d63947a0e2bd7336d07db1350c54ba5743996b84bf9d18ff7a2457e1a5c70ce5013e4a3b62666ddb03294c53051d5f5c70c0"),
262 xpub("7c88cc58adfc71818b08308d43c29de22460b0ea6895449cbec6e458d7dc09e0aea243fa5075ee6621da0d805bd047f6bb207329c5bd2ca3253b172fb323b512"),
268 // Default configurable crosschain parameters.
269 func DefaultCrossChainConfig() *CrossChainConfig {
270 return &CrossChainConfig{}
273 func xpub(str string) (xpub chainkd.XPub) {
274 if err := xpub.UnmarshalText([]byte(str)); err != nil {
275 log.Panicf("Fail converts a string to xpub")
280 //-----------------------------------------------------------------------------
283 // helper function to make config creation independent of root dir
284 func rootify(path, root string) string {
285 if filepath.IsAbs(path) {
288 return filepath.Join(root, path)
291 // DefaultDataDir is the default data directory to use for the databases and other
292 // persistence requirements.
293 func DefaultDataDir() string {
294 // Try to place the data folder in the user's home dir
299 switch runtime.GOOS {
301 return filepath.Join(home, "Library", "Application Support", "Vapor")
303 return filepath.Join(home, "AppData", "Roaming", "Vapor")
305 return filepath.Join(home, ".vapor")
309 func isFolderNotExists(path string) bool {
310 _, err := os.Stat(path)
311 return os.IsNotExist(err)
314 func homeDir() string {
315 if home := os.Getenv("HOME"); home != "" {
318 if usr, err := user.Current(); err == nil {