11 log "github.com/sirupsen/logrus"
13 "github.com/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"`
33 // Default configurable parameters.
34 func DefaultConfig() *Config {
36 BaseConfig: DefaultBaseConfig(),
37 P2P: DefaultP2PConfig(),
38 Wallet: DefaultWalletConfig(),
39 Auth: DefaultRPCAuthConfig(),
40 Web: DefaultWebConfig(),
41 Websocket: DefaultWebsocketConfig(),
42 Federation: DefaultFederationConfig(),
46 // Set the RootDir for all Config structs
47 func (cfg *Config) SetRoot(root string) *Config {
48 cfg.BaseConfig.RootDir = root
52 // NodeKey retrieves the currently configured private key of the node, checking
53 // first any manually set key, falling back to the one found in the configured
54 // data folder. If no key can be found, a new one is generated.
55 func (cfg *Config) PrivateKey() *chainkd.XPrv {
60 filePath := rootify(cfg.PrivateKeyFile, cfg.BaseConfig.RootDir)
61 fildReader, err := os.Open(filePath)
63 log.WithField("err", err).Panic("fail on open private key file")
66 defer fildReader.Close()
67 buf := make([]byte, 128)
68 if _, err = io.ReadFull(fildReader, buf); err != nil {
69 log.WithField("err", err).Panic("fail on read private key file")
73 if _, err := hex.Decode(xprv[:], buf); err != nil {
74 log.WithField("err", err).Panic("fail on decode private key")
78 xpub := cfg.XPrv.XPub()
83 //-----------------------------------------------------------------------------
85 type BaseConfig struct {
86 // The root directory for all data.
87 // This should be set in viper so it can unmarshal into this struct
88 RootDir string `mapstructure:"home"`
90 //The ID of the network to json
91 ChainID string `mapstructure:"chain_id"`
94 LogLevel string `mapstructure:"log_level"`
96 // A custom human readable name for this node
97 Moniker string `mapstructure:"moniker"`
99 // TCP or UNIX socket address for the profiling server to listen on
100 ProfListenAddress string `mapstructure:"prof_laddr"`
102 Mining bool `mapstructure:"mining"`
104 // Database backend: leveldb | memdb
105 DBBackend string `mapstructure:"db_backend"`
107 // Database directory
108 DBPath string `mapstructure:"db_dir"`
110 // Keystore directory
111 KeysPath string `mapstructure:"keys_dir"`
113 ApiAddress string `mapstructure:"api_addr"`
115 VaultMode bool `mapstructure:"vault_mode"`
118 LogFile string `mapstructure:"log_file"`
120 PrivateKeyFile string `mapstructure:"private_key_file"`
124 // Federation file name
125 FederationFileName string `mapstructure:"federation_file"`
128 // Default configurable base parameters.
129 func DefaultBaseConfig() BaseConfig {
131 Moniker: "anonymous",
132 ProfListenAddress: "",
134 DBBackend: "leveldb",
136 KeysPath: "keystore",
137 PrivateKeyFile: "node_key.txt",
138 FederationFileName: "federation.json",
142 func (b BaseConfig) DBDir() string {
143 return rootify(b.DBPath, b.RootDir)
146 func (b BaseConfig) KeysDir() string {
147 return rootify(b.KeysPath, b.RootDir)
150 func (b BaseConfig) FederationFile() string {
151 return rootify(b.FederationFileName, b.RootDir)
155 type P2PConfig struct {
156 ListenAddress string `mapstructure:"laddr"`
157 Seeds string `mapstructure:"seeds"`
158 SkipUPNP bool `mapstructure:"skip_upnp"`
159 LANDiscover bool `mapstructure:"lan_discoverable"`
160 MaxNumPeers int `mapstructure:"max_num_peers"`
161 HandshakeTimeout int `mapstructure:"handshake_timeout"`
162 DialTimeout int `mapstructure:"dial_timeout"`
163 ProxyAddress string `mapstructure:"proxy_address"`
164 ProxyUsername string `mapstructure:"proxy_username"`
165 ProxyPassword string `mapstructure:"proxy_password"`
166 KeepDial string `mapstructure:"keep_dial"`
167 Compression string `mapstructure:"compression_backend"`
170 // Default configurable p2p parameters.
171 func DefaultP2PConfig() *P2PConfig {
173 ListenAddress: "tcp://0.0.0.0:46656",
177 HandshakeTimeout: 30,
182 Compression: "snappy",
186 //-----------------------------------------------------------------------------
187 type WalletConfig struct {
188 Disable bool `mapstructure:"disable"`
189 Rescan bool `mapstructure:"rescan"`
190 TxIndex bool `mapstructure:"txindex"`
191 MaxTxFee uint64 `mapstructure:"max_tx_fee"`
194 type RPCAuthConfig struct {
195 Disable bool `mapstructure:"disable"`
198 type WebConfig struct {
199 Closed bool `mapstructure:"closed"`
202 type WebsocketConfig struct {
203 MaxNumWebsockets int `mapstructure:"max_num_websockets"`
204 MaxNumConcurrentReqs int `mapstructure:"max_num_concurrent_reqs"`
207 type FederationConfig struct {
208 Xpubs []chainkd.XPub `json:"xpubs"`
209 Quorum int `json:"quorum"`
212 // Default configurable rpc's auth parameters.
213 func DefaultRPCAuthConfig() *RPCAuthConfig {
214 return &RPCAuthConfig{
219 // Default configurable web parameters.
220 func DefaultWebConfig() *WebConfig {
226 // Default configurable wallet parameters.
227 func DefaultWalletConfig() *WalletConfig {
228 return &WalletConfig{
232 MaxTxFee: uint64(1000000000),
236 func DefaultWebsocketConfig() *WebsocketConfig {
237 return &WebsocketConfig{
238 MaxNumWebsockets: 25,
239 MaxNumConcurrentReqs: 20,
243 func DefaultFederationConfig() *FederationConfig {
244 return &FederationConfig{
245 Xpubs: []chainkd.XPub{
246 xpub("50ef22b3a3fca7bc08916187cc9ec2f4005c9c6b1353aa1decbd4be3f3bb0fbe1967589f0d9dec13a388c0412002d2c267bdf3b920864e1ddc50581be5604ce1"),
252 func xpub(str string) (xpub chainkd.XPub) {
253 if err := xpub.UnmarshalText([]byte(str)); err != nil {
254 log.Panicf("Fail converts a string to xpub")
259 //-----------------------------------------------------------------------------
262 // helper function to make config creation independent of root dir
263 func rootify(path, root string) string {
264 if filepath.IsAbs(path) {
267 return filepath.Join(root, path)
270 // DefaultDataDir is the default data directory to use for the databases and other
271 // persistence requirements.
272 func DefaultDataDir() string {
273 // Try to place the data folder in the user's home dir
278 switch runtime.GOOS {
280 return filepath.Join(home, "Library", "Application Support", "Vapor")
282 return filepath.Join(home, "AppData", "Roaming", "Vapor")
284 return filepath.Join(home, ".vapor")
288 func isFolderNotExists(path string) bool {
289 _, err := os.Stat(path)
290 return os.IsNotExist(err)
293 func homeDir() string {
294 if home := os.Getenv("HOME"); home != "" {
297 if usr, err := user.Current(); err == nil {