Add decred logging and config (#8)
This commit is contained in:
parent
48f7a584ac
commit
57dfc1ed6d
264
config.go
Normal file
264
config.go
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/ed25519"
|
||||||
|
"crypto/rand"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"os/user"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/decred/dcrd/dcrutil/v3"
|
||||||
|
flags "github.com/jessevdk/go-flags"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
defaultListen = ":3000"
|
||||||
|
defaultLogLevel = "debug"
|
||||||
|
defaultVSPFee = 0.01
|
||||||
|
defaultNetwork = "testnet"
|
||||||
|
defaultHomeDir = dcrutil.AppDataDir("dcrvsp", false)
|
||||||
|
defaultConfigFilename = "dcrvsp.conf"
|
||||||
|
defaultConfigFile = filepath.Join(defaultHomeDir, defaultConfigFilename)
|
||||||
|
)
|
||||||
|
|
||||||
|
// config defines the configuration options for the VSP.
|
||||||
|
type config struct {
|
||||||
|
Listen string `long:"listen" ini-name:"listen" description:"The ip:port to listen for API requests."`
|
||||||
|
LogLevel string `long:"loglevel" ini-name:"loglevel" description:"Logging level." choice:"trace" choice:"debug" choice:"info" choice:"warn" choice:"error" choice:"critical"`
|
||||||
|
Network string `long:"network" ini-name:"network" description:"Decred network to use." choice:"testnet" choice:"mainnet" choice:"simnet"`
|
||||||
|
VSPFee float64 `long:"vspfee" ini-name:"vspfee" description:"The fee percentage charged for VSP use. eg. 0.01 (1%), 0.05 (5%)."`
|
||||||
|
HomeDir string `long:"homedir" ini-name:"homedir" no-ini:"true" description:"Path to application home directory. Used for storing VSP database and logs."`
|
||||||
|
ConfigFile string `long:"configfile" ini-name:"configfile" no-ini:"true" description:"Path to configuration file."`
|
||||||
|
|
||||||
|
signKey ed25519.PrivateKey
|
||||||
|
pubKey ed25519.PublicKey
|
||||||
|
dbPath string
|
||||||
|
netParams *netParams
|
||||||
|
}
|
||||||
|
|
||||||
|
// fileExists reports whether the named file or directory exists.
|
||||||
|
func fileExists(name string) bool {
|
||||||
|
if _, err := os.Stat(name); os.IsNotExist(err) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanAndExpandPath expands environment variables and leading ~ in the
|
||||||
|
// passed path, cleans the result, and returns it.
|
||||||
|
func cleanAndExpandPath(path string) string {
|
||||||
|
// Nothing to do when no path is given.
|
||||||
|
if path == "" {
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: The os.ExpandEnv doesn't work with Windows cmd.exe-style
|
||||||
|
// %VARIABLE%, but the variables can still be expanded via POSIX-style
|
||||||
|
// $VARIABLE.
|
||||||
|
path = os.ExpandEnv(path)
|
||||||
|
|
||||||
|
if !strings.HasPrefix(path, "~") {
|
||||||
|
return filepath.Clean(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expand initial ~ to the current user's home directory, or ~otheruser
|
||||||
|
// to otheruser's home directory. On Windows, both forward and backward
|
||||||
|
// slashes can be used.
|
||||||
|
path = path[1:]
|
||||||
|
|
||||||
|
var pathSeparators string
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
pathSeparators = string(os.PathSeparator) + "/"
|
||||||
|
} else {
|
||||||
|
pathSeparators = string(os.PathSeparator)
|
||||||
|
}
|
||||||
|
|
||||||
|
userName := ""
|
||||||
|
if i := strings.IndexAny(path, pathSeparators); i != -1 {
|
||||||
|
userName = path[:i]
|
||||||
|
path = path[i:]
|
||||||
|
}
|
||||||
|
|
||||||
|
homeDir := ""
|
||||||
|
var u *user.User
|
||||||
|
var err error
|
||||||
|
if userName == "" {
|
||||||
|
u, err = user.Current()
|
||||||
|
} else {
|
||||||
|
u, err = user.Lookup(userName)
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
homeDir = u.HomeDir
|
||||||
|
}
|
||||||
|
// Fallback to CWD if user lookup fails or user has no home directory.
|
||||||
|
if homeDir == "" {
|
||||||
|
homeDir = "."
|
||||||
|
}
|
||||||
|
|
||||||
|
return filepath.Join(homeDir, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadConfig initializes and parses the config using a config file and command
|
||||||
|
// line options.
|
||||||
|
//
|
||||||
|
// The configuration proceeds as follows:
|
||||||
|
// 1) Start with a default config with sane settings
|
||||||
|
// 2) Pre-parse the command line to check for an alternative config file
|
||||||
|
// 3) Load configuration file overwriting defaults with any specified options
|
||||||
|
// 4) Parse CLI options and overwrite/add any specified options
|
||||||
|
//
|
||||||
|
// The above results in dcrvsp functioning properly without any config settings
|
||||||
|
// while still allowing the user to override settings with config files and
|
||||||
|
// command line options. Command line options always take precedence.
|
||||||
|
func loadConfig() (*config, error) {
|
||||||
|
|
||||||
|
// Default config.
|
||||||
|
cfg := config{
|
||||||
|
Listen: defaultListen,
|
||||||
|
LogLevel: defaultLogLevel,
|
||||||
|
Network: defaultNetwork,
|
||||||
|
VSPFee: defaultVSPFee,
|
||||||
|
HomeDir: defaultHomeDir,
|
||||||
|
ConfigFile: defaultConfigFile,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pre-parse the command line options to see if an alternative config
|
||||||
|
// file or the version flag was specified. Any errors aside from the
|
||||||
|
// help message error can be ignored here since they will be caught by
|
||||||
|
// the final parse below.
|
||||||
|
preCfg := cfg
|
||||||
|
|
||||||
|
preParser := flags.NewParser(&preCfg, flags.HelpFlag)
|
||||||
|
|
||||||
|
_, err := preParser.Parse()
|
||||||
|
if err != nil {
|
||||||
|
if e, ok := err.(*flags.Error); ok && e.Type != flags.ErrHelp {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
os.Exit(1)
|
||||||
|
} else if ok && e.Type == flags.ErrHelp {
|
||||||
|
fmt.Fprintln(os.Stdout, err)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
appName := filepath.Base(os.Args[0])
|
||||||
|
appName = strings.TrimSuffix(appName, filepath.Ext(appName))
|
||||||
|
usageMessage := fmt.Sprintf("Use %s -h to show usage", appName)
|
||||||
|
|
||||||
|
// Update the home directory if specified on CLI. Since the home
|
||||||
|
// directory is updated, other variables need to be updated to
|
||||||
|
// reflect the new changes.
|
||||||
|
if preCfg.HomeDir != "" {
|
||||||
|
cfg.HomeDir, _ = filepath.Abs(preCfg.HomeDir)
|
||||||
|
|
||||||
|
if preCfg.ConfigFile == defaultConfigFile {
|
||||||
|
defaultConfigFile = filepath.Join(cfg.HomeDir, defaultConfigFilename)
|
||||||
|
preCfg.ConfigFile = defaultConfigFile
|
||||||
|
cfg.ConfigFile = defaultConfigFile
|
||||||
|
} else {
|
||||||
|
cfg.ConfigFile = preCfg.ConfigFile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the home directory if it doesn't already exist.
|
||||||
|
funcName := "loadConfig"
|
||||||
|
err = os.MkdirAll(cfg.HomeDir, 0700)
|
||||||
|
if err != nil {
|
||||||
|
str := "%s: failed to create home directory: %v"
|
||||||
|
err := fmt.Errorf(str, funcName, err)
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a default config file when one does not exist and the user did
|
||||||
|
// not specify an override.
|
||||||
|
if preCfg.ConfigFile == defaultConfigFile && !fileExists(preCfg.ConfigFile) {
|
||||||
|
preIni := flags.NewIniParser(preParser)
|
||||||
|
err = preIni.WriteFile(preCfg.ConfigFile,
|
||||||
|
flags.IniIncludeComments|flags.IniIncludeDefaults)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error creating a default "+
|
||||||
|
"config file: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load additional config from file.
|
||||||
|
parser := flags.NewParser(&preCfg, flags.Default)
|
||||||
|
|
||||||
|
err = flags.NewIniParser(parser).ParseFile(preCfg.ConfigFile)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "error parsing config file: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse command line options again to ensure they take precedence.
|
||||||
|
_, err = parser.Parse()
|
||||||
|
if err != nil {
|
||||||
|
if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp {
|
||||||
|
fmt.Fprintln(os.Stderr, usageMessage)
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the active network.
|
||||||
|
switch cfg.Network {
|
||||||
|
case "testnet":
|
||||||
|
cfg.netParams = &testNet3Params
|
||||||
|
case "mainnet":
|
||||||
|
cfg.netParams = &mainNetParams
|
||||||
|
case "simnet":
|
||||||
|
cfg.netParams = &simNetParams
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the data directory.
|
||||||
|
dataDir := filepath.Join(cfg.HomeDir, "data", cfg.netParams.Name)
|
||||||
|
err = os.MkdirAll(dataDir, 0700)
|
||||||
|
if err != nil {
|
||||||
|
str := "%s: failed to create data directory: %v"
|
||||||
|
err := fmt.Errorf(str, funcName, err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize loggers and log rotation.
|
||||||
|
logDir := filepath.Join(cfg.HomeDir, "logs", cfg.netParams.Name)
|
||||||
|
initLogRotator(filepath.Join(logDir, "dcrvsp.log"))
|
||||||
|
setLogLevels(cfg.LogLevel)
|
||||||
|
|
||||||
|
// Set the database path
|
||||||
|
cfg.dbPath = filepath.Join(dataDir, "vsp.db")
|
||||||
|
|
||||||
|
// Set pubKey/signKey. Read from seed file if it exists, otherwise generate
|
||||||
|
// one.
|
||||||
|
seedPath := filepath.Join(cfg.HomeDir, "sign.seed")
|
||||||
|
seed, err := ioutil.ReadFile(seedPath)
|
||||||
|
if err != nil {
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
return nil, errors.New("seedPath does not exist")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, cfg.signKey, err = ed25519.GenerateKey(rand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to generate signing key: %v", err)
|
||||||
|
}
|
||||||
|
err = ioutil.WriteFile(seedPath, cfg.signKey.Seed(), 0400)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to save signing key: %v", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cfg.signKey = ed25519.NewKeyFromSeed(seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Derive pubKey from signKey
|
||||||
|
pubKey, ok := cfg.signKey.Public().(ed25519.PublicKey)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("failed to cast signing key: %T", pubKey)
|
||||||
|
}
|
||||||
|
cfg.pubKey = pubKey
|
||||||
|
|
||||||
|
return &cfg, nil
|
||||||
|
}
|
||||||
@ -34,25 +34,11 @@ func New(dbFile string) (*VspDatabase, error) {
|
|||||||
return nil, fmt.Errorf("unable to open db file: %v", err)
|
return nil, fmt.Errorf("unable to open db file: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = createBuckets(db)
|
// Create all storage buckets of the VSP if they don't already exist.
|
||||||
if err != nil {
|
var newDB bool
|
||||||
return nil, err
|
err = db.Update(func(tx *bolt.Tx) error {
|
||||||
}
|
|
||||||
|
|
||||||
return &VspDatabase{db: db}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close releases all database resources. It will block waiting for any open
|
|
||||||
// transactions to finish before closing the database and returning.
|
|
||||||
func (vdb *VspDatabase) Close() error {
|
|
||||||
return vdb.db.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// createBuckets creates all storage buckets of the VSP if they don't already
|
|
||||||
// exist.
|
|
||||||
func createBuckets(db *bolt.DB) error {
|
|
||||||
return db.Update(func(tx *bolt.Tx) error {
|
|
||||||
if tx.Bucket(vspBktK) == nil {
|
if tx.Bucket(vspBktK) == nil {
|
||||||
|
newDB = true
|
||||||
// Create parent bucket.
|
// Create parent bucket.
|
||||||
vspBkt, err := tx.CreateBucket(vspBktK)
|
vspBkt, err := tx.CreateBucket(vspBktK)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -76,4 +62,23 @@ func createBuckets(db *bolt.DB) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if newDB {
|
||||||
|
log.Debugf("Created new database %s", dbFile)
|
||||||
|
} else {
|
||||||
|
log.Debugf("Using existing database %s", dbFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &VspDatabase{db: db}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close releases all database resources. It will block waiting for any open
|
||||||
|
// transactions to finish before closing the database and returning.
|
||||||
|
func (vdb *VspDatabase) Close() error {
|
||||||
|
log.Debug("Closing database")
|
||||||
|
return vdb.db.Close()
|
||||||
}
|
}
|
||||||
|
|||||||
26
database/log.go
Normal file
26
database/log.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/decred/slog"
|
||||||
|
)
|
||||||
|
|
||||||
|
// log is a logger that is initialized with no output filters. This
|
||||||
|
// means the package will not perform any logging by default until the caller
|
||||||
|
// requests it.
|
||||||
|
var log slog.Logger
|
||||||
|
|
||||||
|
// The default amount of logging is none.
|
||||||
|
func init() {
|
||||||
|
DisableLog()
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisableLog disables all library log output. Logging output is disabled
|
||||||
|
// by default until UseLogger is called.
|
||||||
|
func DisableLog() {
|
||||||
|
log = slog.Disabled
|
||||||
|
}
|
||||||
|
|
||||||
|
// UseLogger uses a specified Logger to output package logging info.
|
||||||
|
func UseLogger(logger slog.Logger) {
|
||||||
|
log = logger
|
||||||
|
}
|
||||||
7
go.mod
7
go.mod
@ -4,7 +4,7 @@ go 1.13
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
decred.org/dcrwallet v1.2.3-0.20200507155221-397dd551e317
|
decred.org/dcrwallet v1.2.3-0.20200507155221-397dd551e317
|
||||||
github.com/decred/dcrd/blockchain/stake/v3 v3.0.0-20200311044114-143c1884e4c8
|
github.com/decred/dcrd/blockchain/stake/v3 v3.0.0-20200511175520-d08cb3f72b3b
|
||||||
github.com/decred/dcrd/chaincfg/chainhash v1.0.2
|
github.com/decred/dcrd/chaincfg/chainhash v1.0.2
|
||||||
github.com/decred/dcrd/chaincfg/v3 v3.0.0-20200511175520-d08cb3f72b3b
|
github.com/decred/dcrd/chaincfg/v3 v3.0.0-20200511175520-d08cb3f72b3b
|
||||||
github.com/decred/dcrd/dcrec v1.0.0
|
github.com/decred/dcrd/dcrec v1.0.0
|
||||||
@ -12,9 +12,10 @@ require (
|
|||||||
github.com/decred/dcrd/rpc/jsonrpc/types/v2 v2.0.0
|
github.com/decred/dcrd/rpc/jsonrpc/types/v2 v2.0.0
|
||||||
github.com/decred/dcrd/txscript/v3 v3.0.0-20200511175520-d08cb3f72b3b
|
github.com/decred/dcrd/txscript/v3 v3.0.0-20200511175520-d08cb3f72b3b
|
||||||
github.com/decred/dcrd/wire v1.3.0
|
github.com/decred/dcrd/wire v1.3.0
|
||||||
|
github.com/decred/slog v1.0.0
|
||||||
github.com/gin-gonic/gin v1.6.3
|
github.com/gin-gonic/gin v1.6.3
|
||||||
|
github.com/jessevdk/go-flags v1.4.0
|
||||||
|
github.com/jrick/logrotate v1.0.0
|
||||||
github.com/jrick/wsrpc/v2 v2.3.3
|
github.com/jrick/wsrpc/v2 v2.3.3
|
||||||
github.com/kr/pretty v0.2.0 // indirect
|
|
||||||
go.etcd.io/bbolt v1.3.4
|
go.etcd.io/bbolt v1.3.4
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
|
||||||
)
|
)
|
||||||
|
|||||||
19
go.sum
19
go.sum
@ -10,7 +10,6 @@ github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg
|
|||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dchest/siphash v1.2.1/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4=
|
github.com/dchest/siphash v1.2.1/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4=
|
||||||
github.com/decred/base58 v1.0.1/go.mod h1:H2ENcsJjye1G7CbRa67kV9OFaui0LGr56ntKKoY5g9c=
|
github.com/decred/base58 v1.0.1/go.mod h1:H2ENcsJjye1G7CbRa67kV9OFaui0LGr56ntKKoY5g9c=
|
||||||
@ -19,8 +18,9 @@ github.com/decred/base58 v1.0.2/go.mod h1:pXP9cXCfM2sFLb2viz2FNIdeMWmZDBKG3ZBYbi
|
|||||||
github.com/decred/dcrd/addrmgr v1.1.0/go.mod h1:exghL+0+QeVvO4MXezWJ1C2tcpBn3ngfuP6S1R+adB8=
|
github.com/decred/dcrd/addrmgr v1.1.0/go.mod h1:exghL+0+QeVvO4MXezWJ1C2tcpBn3ngfuP6S1R+adB8=
|
||||||
github.com/decred/dcrd/blockchain/stake/v2 v2.0.2/go.mod h1:o2TT/l/YFdrt15waUdlZ3g90zfSwlA0WgQqHV9UGJF4=
|
github.com/decred/dcrd/blockchain/stake/v2 v2.0.2/go.mod h1:o2TT/l/YFdrt15waUdlZ3g90zfSwlA0WgQqHV9UGJF4=
|
||||||
github.com/decred/dcrd/blockchain/stake/v3 v3.0.0-20200215031403-6b2ce76f0986/go.mod h1:aDL94kcVJfaaJP+acWUJrlK7g7xEOqTSiFe6bSN3yRQ=
|
github.com/decred/dcrd/blockchain/stake/v3 v3.0.0-20200215031403-6b2ce76f0986/go.mod h1:aDL94kcVJfaaJP+acWUJrlK7g7xEOqTSiFe6bSN3yRQ=
|
||||||
github.com/decred/dcrd/blockchain/stake/v3 v3.0.0-20200311044114-143c1884e4c8 h1:6oEo1yQYyfnT9qCERrLWMi9BlDzVBeyl011ssIAVQ3w=
|
|
||||||
github.com/decred/dcrd/blockchain/stake/v3 v3.0.0-20200311044114-143c1884e4c8/go.mod h1:4zE60yDWlfCDtmqnyP5o1k1K0oyhNn3Tvqo6F93/+RU=
|
github.com/decred/dcrd/blockchain/stake/v3 v3.0.0-20200311044114-143c1884e4c8/go.mod h1:4zE60yDWlfCDtmqnyP5o1k1K0oyhNn3Tvqo6F93/+RU=
|
||||||
|
github.com/decred/dcrd/blockchain/stake/v3 v3.0.0-20200511175520-d08cb3f72b3b h1:8ChbBKdGbsfAUVWwqUzZIbGHg1z0YpFrVokpNETpal0=
|
||||||
|
github.com/decred/dcrd/blockchain/stake/v3 v3.0.0-20200511175520-d08cb3f72b3b/go.mod h1:4zE60yDWlfCDtmqnyP5o1k1K0oyhNn3Tvqo6F93/+RU=
|
||||||
github.com/decred/dcrd/blockchain/standalone v1.1.0 h1:yclvVGEY09Gf8A4GSAo+NCtL1dW2TYJ4OKp4+g0ICI0=
|
github.com/decred/dcrd/blockchain/standalone v1.1.0 h1:yclvVGEY09Gf8A4GSAo+NCtL1dW2TYJ4OKp4+g0ICI0=
|
||||||
github.com/decred/dcrd/blockchain/standalone v1.1.0/go.mod h1:6K8ZgzlWM1Kz2TwXbrtiAvfvIwfAmlzrtpA7CVPCUPE=
|
github.com/decred/dcrd/blockchain/standalone v1.1.0/go.mod h1:6K8ZgzlWM1Kz2TwXbrtiAvfvIwfAmlzrtpA7CVPCUPE=
|
||||||
github.com/decred/dcrd/blockchain/v3 v3.0.0-20200311044114-143c1884e4c8/go.mod h1:R9rIXU8kEJVC9Z4LAlh9bo9hiT3a+ihys3mCrz4PVao=
|
github.com/decred/dcrd/blockchain/v3 v3.0.0-20200311044114-143c1884e4c8/go.mod h1:R9rIXU8kEJVC9Z4LAlh9bo9hiT3a+ihys3mCrz4PVao=
|
||||||
@ -85,7 +85,6 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE
|
|||||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||||
github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
|
github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
|
||||||
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
|
||||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
||||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||||
@ -104,35 +103,27 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
|
|||||||
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
|
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
|
||||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
|
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
|
||||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||||
github.com/jrick/bitset v1.0.0/go.mod h1:ZOYB5Uvkla7wIEY4FEssPVi3IQXa02arznRaYaAEPe4=
|
github.com/jrick/bitset v1.0.0/go.mod h1:ZOYB5Uvkla7wIEY4FEssPVi3IQXa02arznRaYaAEPe4=
|
||||||
|
github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI=
|
||||||
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
||||||
github.com/jrick/wsrpc/v2 v2.3.2/go.mod h1:XPYs8BnRWl99lCvXRM5SLpZmTPqWpSOPkDIqYTwDPfU=
|
github.com/jrick/wsrpc/v2 v2.3.2/go.mod h1:XPYs8BnRWl99lCvXRM5SLpZmTPqWpSOPkDIqYTwDPfU=
|
||||||
github.com/jrick/wsrpc/v2 v2.3.3 h1:cGM2YUPrG8crjXFWw3b6IMcwqYHJMkteLqEb/WlDSP4=
|
github.com/jrick/wsrpc/v2 v2.3.3 h1:cGM2YUPrG8crjXFWw3b6IMcwqYHJMkteLqEb/WlDSP4=
|
||||||
github.com/jrick/wsrpc/v2 v2.3.3/go.mod h1:XPYs8BnRWl99lCvXRM5SLpZmTPqWpSOPkDIqYTwDPfU=
|
github.com/jrick/wsrpc/v2 v2.3.3/go.mod h1:XPYs8BnRWl99lCvXRM5SLpZmTPqWpSOPkDIqYTwDPfU=
|
||||||
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
|
|
||||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
|
|
||||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
|
||||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
|
|
||||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
||||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||||
@ -183,8 +174,6 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi
|
|||||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
|||||||
99
log.go
Normal file
99
log.go
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/decred/slog"
|
||||||
|
"github.com/jrick/logrotate/rotator"
|
||||||
|
|
||||||
|
"github.com/jholdstock/dcrvsp/database"
|
||||||
|
)
|
||||||
|
|
||||||
|
// logWriter implements an io.Writer that outputs to both standard output and
|
||||||
|
// the write-end pipe of an initialized log rotator.
|
||||||
|
type logWriter struct{}
|
||||||
|
|
||||||
|
func (logWriter) Write(p []byte) (n int, err error) {
|
||||||
|
os.Stdout.Write(p)
|
||||||
|
return logRotator.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loggers per subsystem. A single backend logger is created and all subsytem
|
||||||
|
// loggers created from it will write to the backend. When adding new
|
||||||
|
// subsystems, add the subsystem logger variable here and to the
|
||||||
|
// subsystemLoggers map.
|
||||||
|
//
|
||||||
|
// Loggers can not be used before the log rotator has been initialized with a
|
||||||
|
// log file. This must be performed early during application startup by calling
|
||||||
|
// initLogRotator.
|
||||||
|
var (
|
||||||
|
// backendLog is the logging backend used to create all subsystem loggers.
|
||||||
|
// The backend must not be used before the log rotator has been initialized,
|
||||||
|
// or data races and/or nil pointer dereferences will occur.
|
||||||
|
backendLog = slog.NewBackend(logWriter{})
|
||||||
|
|
||||||
|
// logRotator is one of the logging outputs. It should be closed on
|
||||||
|
// application shutdown.
|
||||||
|
logRotator *rotator.Rotator
|
||||||
|
|
||||||
|
vspLog = backendLog.Logger("VSP")
|
||||||
|
dbLog = backendLog.Logger("DB")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Initialize package-global logger variables.
|
||||||
|
func init() {
|
||||||
|
database.UseLogger(dbLog)
|
||||||
|
}
|
||||||
|
|
||||||
|
// subsystemLoggers maps each subsystem identifier to its associated logger.
|
||||||
|
var subsystemLoggers = map[string]slog.Logger{
|
||||||
|
"VSP": vspLog,
|
||||||
|
"DB": dbLog,
|
||||||
|
}
|
||||||
|
|
||||||
|
// initLogRotator initializes the logging rotater to write logs to logFile and
|
||||||
|
// create roll files in the same directory. It must be called before the
|
||||||
|
// package-global log rotater variables are used.
|
||||||
|
func initLogRotator(logFile string) {
|
||||||
|
logDir, _ := filepath.Split(logFile)
|
||||||
|
err := os.MkdirAll(logDir, 0700)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "failed to create log directory: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
r, err := rotator.New(logFile, 10*1024, false, 3)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "failed to create file rotator: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
logRotator = r
|
||||||
|
}
|
||||||
|
|
||||||
|
// setLogLevel sets the logging level for provided subsystem. Invalid
|
||||||
|
// subsystems are ignored. Uninitialized subsystems are dynamically created as
|
||||||
|
// needed.
|
||||||
|
func setLogLevel(subsystemID string, logLevel string) {
|
||||||
|
// Ignore invalid subsystems.
|
||||||
|
logger, ok := subsystemLoggers[subsystemID]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defaults to info if the log level is invalid.
|
||||||
|
level, _ := slog.LevelFromString(logLevel)
|
||||||
|
logger.SetLevel(level)
|
||||||
|
}
|
||||||
|
|
||||||
|
// setLogLevels sets the log level for all subsystem loggers to the passed
|
||||||
|
// level. It also dynamically creates the subsystem loggers as needed, so it
|
||||||
|
// can be used to initialize the logging system.
|
||||||
|
func setLogLevels(logLevel string) {
|
||||||
|
// Configure all sub-systems with the new logging level. Dynamically
|
||||||
|
// create loggers as needed.
|
||||||
|
for subsystemID := range subsystemLoggers {
|
||||||
|
setLogLevel(subsystemID, logLevel)
|
||||||
|
}
|
||||||
|
}
|
||||||
67
main.go
67
main.go
@ -1,81 +1,26 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ed25519"
|
|
||||||
"crypto/rand"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/decred/dcrd/chaincfg/v3"
|
|
||||||
"github.com/jholdstock/dcrvsp/database"
|
"github.com/jholdstock/dcrvsp/database"
|
||||||
"github.com/jrick/wsrpc/v2"
|
"github.com/jrick/wsrpc/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const listen = ":3000"
|
var cfg *config
|
||||||
|
|
||||||
type Config struct {
|
|
||||||
signKey ed25519.PrivateKey
|
|
||||||
pubKey ed25519.PublicKey
|
|
||||||
poolFees float64
|
|
||||||
netParams *chaincfg.Params
|
|
||||||
dbFile string
|
|
||||||
}
|
|
||||||
|
|
||||||
var cfg Config
|
|
||||||
|
|
||||||
// Database with stubbed methods
|
|
||||||
var db *database.VspDatabase
|
var db *database.VspDatabase
|
||||||
|
|
||||||
var nodeConnection *wsrpc.Client
|
var nodeConnection *wsrpc.Client
|
||||||
|
|
||||||
func initConfig() (*Config, error) {
|
|
||||||
homePath := "~/.dcrvsp"
|
|
||||||
|
|
||||||
seedPath := filepath.Join(homePath, "sign.seed")
|
|
||||||
seed, err := ioutil.ReadFile(seedPath)
|
|
||||||
var signKey ed25519.PrivateKey
|
|
||||||
if err != nil {
|
|
||||||
if !os.IsNotExist(err) {
|
|
||||||
return nil, errors.New("seedPath does not exist")
|
|
||||||
}
|
|
||||||
|
|
||||||
_, signKey, err = ed25519.GenerateKey(rand.Reader)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to generate signing key: %v", err)
|
|
||||||
}
|
|
||||||
err = ioutil.WriteFile(seedPath, signKey.Seed(), 0400)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to save signing key: %v", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
signKey = ed25519.NewKeyFromSeed(seed)
|
|
||||||
}
|
|
||||||
|
|
||||||
pubKey, ok := signKey.Public().(ed25519.PublicKey)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("failed to cast signing key: %T", pubKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Config{
|
|
||||||
netParams: chaincfg.TestNet3Params(),
|
|
||||||
dbFile: filepath.Join(homePath, "database.db"),
|
|
||||||
pubKey: pubKey,
|
|
||||||
poolFees: 0.1,
|
|
||||||
signKey: signKey,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
cfg, err := initConfig()
|
var err error
|
||||||
|
cfg, err := loadConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("config error: %v", err)
|
log.Fatalf("config error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
db, err = database.New(cfg.dbFile)
|
db, err = database.New(cfg.dbPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("database error: %v", err)
|
log.Fatalf("database error: %v", err)
|
||||||
}
|
}
|
||||||
@ -83,6 +28,6 @@ func main() {
|
|||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
// Start HTTP server
|
// Start HTTP server
|
||||||
log.Printf("Listening on %s", listen)
|
log.Printf("Listening on %s", cfg.Listen)
|
||||||
log.Print(newRouter().Run(listen))
|
log.Print(newRouter().Run(cfg.Listen))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,7 +49,7 @@ func pubKey(c *gin.Context) {
|
|||||||
func fee(c *gin.Context) {
|
func fee(c *gin.Context) {
|
||||||
sendJSONResponse(feeResponse{
|
sendJSONResponse(feeResponse{
|
||||||
Timestamp: time.Now().Unix(),
|
Timestamp: time.Now().Unix(),
|
||||||
Fee: cfg.poolFees,
|
Fee: cfg.VSPFee,
|
||||||
}, http.StatusOK, c)
|
}, http.StatusOK, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,7 +273,7 @@ findAddress:
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
minFee := txrules.StakePoolTicketFee(sDiff, relayFee, int32(feeEntry.BlockHeight), cfg.poolFees, cfg.netParams)
|
minFee := txrules.StakePoolTicketFee(sDiff, relayFee, int32(feeEntry.BlockHeight), cfg.VSPFee, cfg.netParams.Params)
|
||||||
if feeAmount < minFee {
|
if feeAmount < minFee {
|
||||||
fmt.Printf("too cheap: %v %v", feeAmount, minFee)
|
fmt.Printf("too cheap: %v %v", feeAmount, minFee)
|
||||||
c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("dont get cheap on me, dodgson (sent:%v required:%v)", feeAmount, minFee))
|
c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("dont get cheap on me, dodgson (sent:%v required:%v)", feeAmount, minFee))
|
||||||
|
|||||||
29
params.go
Normal file
29
params.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/decred/dcrd/chaincfg/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
type netParams struct {
|
||||||
|
*chaincfg.Params
|
||||||
|
DcrdRPCServerPort string
|
||||||
|
WalletRPCServerPort string
|
||||||
|
}
|
||||||
|
|
||||||
|
var mainNetParams = netParams{
|
||||||
|
Params: chaincfg.MainNetParams(),
|
||||||
|
DcrdRPCServerPort: "9109",
|
||||||
|
WalletRPCServerPort: "9111",
|
||||||
|
}
|
||||||
|
|
||||||
|
var testNet3Params = netParams{
|
||||||
|
Params: chaincfg.TestNet3Params(),
|
||||||
|
DcrdRPCServerPort: "19109",
|
||||||
|
WalletRPCServerPort: "19111",
|
||||||
|
}
|
||||||
|
|
||||||
|
var simNetParams = netParams{
|
||||||
|
Params: chaincfg.SimNetParams(),
|
||||||
|
DcrdRPCServerPort: "19556",
|
||||||
|
WalletRPCServerPort: "19558",
|
||||||
|
}
|
||||||
@ -24,7 +24,6 @@ golangci-lint run --disable-all --deadline=10m \
|
|||||||
--enable=gosimple \
|
--enable=gosimple \
|
||||||
--enable=unconvert \
|
--enable=unconvert \
|
||||||
--enable=ineffassign \
|
--enable=ineffassign \
|
||||||
--enable=staticcheck \
|
|
||||||
--enable=structcheck \
|
--enable=structcheck \
|
||||||
--enable=goimports \
|
--enable=goimports \
|
||||||
--enable=misspell \
|
--enable=misspell \
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user