multi: Move netparams to internal.
A new internal package named config contains all of the hard-coded, network specific values used by vspd.
This commit is contained in:
parent
17fe1d7db1
commit
d5d1c3239c
@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2022 The Decred developers
|
// Copyright (c) 2022-2023 The Decred developers
|
||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
@ -11,11 +11,11 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/decred/dcrd/chaincfg/v3"
|
|
||||||
"github.com/decred/slog"
|
"github.com/decred/slog"
|
||||||
"github.com/jessevdk/go-flags"
|
"github.com/jessevdk/go-flags"
|
||||||
|
|
||||||
"github.com/decred/vspd/database"
|
"github.com/decred/vspd/database"
|
||||||
|
"github.com/decred/vspd/internal/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -58,20 +58,19 @@ func run() int {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
var dcrdata *dcrdataClient
|
var network *config.Network
|
||||||
var params *chaincfg.Params
|
|
||||||
if cfg.Testnet {
|
if cfg.Testnet {
|
||||||
dcrdata = &dcrdataClient{URL: "https://testnet.dcrdata.org"}
|
network = &config.TestNet3
|
||||||
params = chaincfg.TestNet3Params()
|
|
||||||
} else {
|
} else {
|
||||||
dcrdata = &dcrdataClient{URL: "https://explorer.dcrdata.org"}
|
network = &config.MainNet
|
||||||
params = chaincfg.MainNetParams()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dcrdata := &dcrdataClient{URL: network.BlockExplorerURL}
|
||||||
|
|
||||||
// Get the latest vote version. Any votes which don't match this version
|
// Get the latest vote version. Any votes which don't match this version
|
||||||
// will be ignored.
|
// will be ignored.
|
||||||
var latestVoteVersion uint32
|
var latestVoteVersion uint32
|
||||||
for version := range params.Deployments {
|
for version := range network.Deployments {
|
||||||
if version > latestVoteVersion {
|
if version > latestVoteVersion {
|
||||||
latestVoteVersion = version
|
latestVoteVersion = version
|
||||||
}
|
}
|
||||||
@ -163,7 +162,7 @@ func run() int {
|
|||||||
|
|
||||||
// Get the recorded on-chain votes for this ticket.
|
// Get the recorded on-chain votes for this ticket.
|
||||||
actualVote := make(map[string]string)
|
actualVote := make(map[string]string)
|
||||||
agendas := params.Deployments[latestVoteVersion]
|
agendas := network.Deployments[latestVoteVersion]
|
||||||
for _, agenda := range agendas {
|
for _, agenda := range agendas {
|
||||||
for _, choice := range agenda.Vote.Choices {
|
for _, choice := range agenda.Vote.Choices {
|
||||||
if votebits&agenda.Vote.Mask == choice.Bits {
|
if votebits&agenda.Vote.Mask == choice.Bits {
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import (
|
|||||||
"github.com/decred/dcrd/hdkeychain/v3"
|
"github.com/decred/dcrd/hdkeychain/v3"
|
||||||
"github.com/decred/slog"
|
"github.com/decred/slog"
|
||||||
"github.com/decred/vspd/database"
|
"github.com/decred/vspd/database"
|
||||||
|
"github.com/decred/vspd/internal/config"
|
||||||
"github.com/decred/vspd/internal/version"
|
"github.com/decred/vspd/internal/version"
|
||||||
flags "github.com/jessevdk/go-flags"
|
flags "github.com/jessevdk/go-flags"
|
||||||
)
|
)
|
||||||
@ -45,8 +46,8 @@ var (
|
|||||||
defaultDesignation = "Voting Service Provider"
|
defaultDesignation = "Voting Service Provider"
|
||||||
)
|
)
|
||||||
|
|
||||||
// config defines the configuration options for the VSP.
|
// vspdConfig defines the configuration options for the vspd process.
|
||||||
type config struct {
|
type vspdConfig struct {
|
||||||
Listen string `long:"listen" ini-name:"listen" description:"The ip:port to listen for API requests."`
|
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"`
|
LogLevel string `long:"loglevel" ini-name:"loglevel" description:"Logging level." choice:"trace" choice:"debug" choice:"info" choice:"warn" choice:"error" choice:"critical"`
|
||||||
MaxLogSize int64 `long:"maxlogsize" ini-name:"maxlogsize" description:"File size threshold for log file rotation (MB)."`
|
MaxLogSize int64 `long:"maxlogsize" ini-name:"maxlogsize" description:"File size threshold for log file rotation (MB)."`
|
||||||
@ -79,7 +80,7 @@ type config struct {
|
|||||||
logLevel slog.Level
|
logLevel slog.Level
|
||||||
|
|
||||||
dbPath string
|
dbPath string
|
||||||
netParams *netParams
|
network *config.Network
|
||||||
dcrdCert []byte
|
dcrdCert []byte
|
||||||
walletHosts, walletUsers, walletPasswords []string
|
walletHosts, walletUsers, walletPasswords []string
|
||||||
walletCerts [][]byte
|
walletCerts [][]byte
|
||||||
@ -169,10 +170,10 @@ func normalizeAddress(addr, defaultPort string) string {
|
|||||||
// The above results in vspd functioning properly without any config settings
|
// The above results in vspd functioning properly without any config settings
|
||||||
// while still allowing the user to override settings with config files and
|
// while still allowing the user to override settings with config files and
|
||||||
// command line options. Command line options always take precedence.
|
// command line options. Command line options always take precedence.
|
||||||
func loadConfig() (*config, error) {
|
func loadConfig() (*vspdConfig, error) {
|
||||||
|
|
||||||
// Default config.
|
// Default config.
|
||||||
cfg := config{
|
cfg := vspdConfig{
|
||||||
Listen: defaultListen,
|
Listen: defaultListen,
|
||||||
LogLevel: defaultLogLevel,
|
LogLevel: defaultLogLevel,
|
||||||
MaxLogSize: defaultMaxLogSize,
|
MaxLogSize: defaultMaxLogSize,
|
||||||
@ -280,11 +281,11 @@ func loadConfig() (*config, error) {
|
|||||||
// Set the active network.
|
// Set the active network.
|
||||||
switch cfg.Network {
|
switch cfg.Network {
|
||||||
case "testnet":
|
case "testnet":
|
||||||
cfg.netParams = &testNet3Params
|
cfg.network = &config.TestNet3
|
||||||
case "mainnet":
|
case "mainnet":
|
||||||
cfg.netParams = &mainNetParams
|
cfg.network = &config.MainNet
|
||||||
case "simnet":
|
case "simnet":
|
||||||
cfg.netParams = &simNetParams
|
cfg.network = &config.SimNet
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure backup interval is greater than 30 seconds.
|
// Ensure backup interval is greater than 30 seconds.
|
||||||
@ -388,26 +389,26 @@ func loadConfig() (*config, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Verify minimum number of voting wallets are configured.
|
// Verify minimum number of voting wallets are configured.
|
||||||
if numHost < cfg.netParams.minWallets {
|
if numHost < cfg.network.MinWallets {
|
||||||
return nil, fmt.Errorf("minimum required voting wallets has not been met: %d < %d",
|
return nil, fmt.Errorf("minimum required voting wallets has not been met: %d < %d",
|
||||||
numHost, cfg.netParams.minWallets)
|
numHost, cfg.network.MinWallets)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add default port for the active network if there is no port specified.
|
// Add default port for the active network if there is no port specified.
|
||||||
for i := 0; i < numHost; i++ {
|
for i := 0; i < numHost; i++ {
|
||||||
cfg.walletHosts[i] = normalizeAddress(cfg.walletHosts[i], cfg.netParams.walletRPCServerPort)
|
cfg.walletHosts[i] = normalizeAddress(cfg.walletHosts[i], cfg.network.WalletRPCServerPort)
|
||||||
}
|
}
|
||||||
cfg.DcrdHost = normalizeAddress(cfg.DcrdHost, cfg.netParams.dcrdRPCServerPort)
|
cfg.DcrdHost = normalizeAddress(cfg.DcrdHost, cfg.network.DcrdRPCServerPort)
|
||||||
|
|
||||||
// Create the data directory.
|
// Create the data directory.
|
||||||
dataDir := filepath.Join(cfg.HomeDir, "data", cfg.netParams.Name)
|
dataDir := filepath.Join(cfg.HomeDir, "data", cfg.network.Name)
|
||||||
err = os.MkdirAll(dataDir, 0700)
|
err = os.MkdirAll(dataDir, 0700)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to create data directory: %w", err)
|
return nil, fmt.Errorf("failed to create data directory: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize loggers and log rotation.
|
// Initialize loggers and log rotation.
|
||||||
logDir := filepath.Join(cfg.HomeDir, "logs", cfg.netParams.Name)
|
logDir := filepath.Join(cfg.HomeDir, "logs", cfg.network.Name)
|
||||||
cfg.logBackend, err = newLogBackend(logDir, appName, cfg.MaxLogSize, cfg.LogsToKeep)
|
cfg.logBackend, err = newLogBackend(logDir, appName, cfg.MaxLogSize, cfg.LogsToKeep)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to initialize logger: %w", err)
|
return nil, fmt.Errorf("failed to initialize logger: %w", err)
|
||||||
@ -431,7 +432,7 @@ func loadConfig() (*config, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure provided value is a valid key for the selected network.
|
// Ensure provided value is a valid key for the selected network.
|
||||||
_, err = hdkeychain.NewKeyFromString(cfg.FeeXPub, cfg.netParams.Params)
|
_, err = hdkeychain.NewKeyFromString(cfg.FeeXPub, cfg.network.Params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to parse feexpub: %w", err)
|
return nil, fmt.Errorf("failed to parse feexpub: %w", err)
|
||||||
}
|
}
|
||||||
@ -444,7 +445,6 @@ func loadConfig() (*config, error) {
|
|||||||
|
|
||||||
// Exit with success
|
// Exit with success
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If database does not exist, return error.
|
// If database does not exist, return error.
|
||||||
@ -456,7 +456,7 @@ func loadConfig() (*config, error) {
|
|||||||
return &cfg, nil
|
return &cfg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *config) logger(subsystem string) slog.Logger {
|
func (cfg *vspdConfig) logger(subsystem string) slog.Logger {
|
||||||
log := cfg.logBackend.Logger(subsystem)
|
log := cfg.logBackend.Logger(subsystem)
|
||||||
log.SetLevel(cfg.logLevel)
|
log.SetLevel(cfg.logLevel)
|
||||||
return log
|
return log
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/decred/vspd/internal/config"
|
||||||
"github.com/decred/vspd/internal/version"
|
"github.com/decred/vspd/internal/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -32,7 +33,7 @@ func run() int {
|
|||||||
log.Criticalf("Version %s (Go version %s %s/%s)", version.String(),
|
log.Criticalf("Version %s (Go version %s %s/%s)", version.String(),
|
||||||
runtime.Version(), runtime.GOOS, runtime.GOARCH)
|
runtime.Version(), runtime.GOOS, runtime.GOARCH)
|
||||||
|
|
||||||
if cfg.netParams == &mainNetParams && version.IsPreRelease() {
|
if cfg.network == &config.MainNet && version.IsPreRelease() {
|
||||||
log.Warnf("")
|
log.Warnf("")
|
||||||
log.Warnf("\tWARNING: This is a pre-release version of vspd which should not be used on mainnet.")
|
log.Warnf("\tWARNING: This is a pre-release version of vspd which should not be used on mainnet.")
|
||||||
log.Warnf("")
|
log.Warnf("")
|
||||||
|
|||||||
@ -1,61 +0,0 @@
|
|||||||
// Copyright (c) 2020-2022 The Decred developers
|
|
||||||
// Use of this source code is governed by an ISC
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/decred/dcrd/chaincfg/v3"
|
|
||||||
)
|
|
||||||
|
|
||||||
type netParams struct {
|
|
||||||
*chaincfg.Params
|
|
||||||
dcrdRPCServerPort string
|
|
||||||
walletRPCServerPort string
|
|
||||||
blockExplorerURL string
|
|
||||||
// minWallets is the minimum number of voting wallets required for a vspd
|
|
||||||
// deployment on this network. vspd will log an error and refuse to start if
|
|
||||||
// fewer wallets are configured.
|
|
||||||
minWallets int
|
|
||||||
// dcp0005Height is the activation height of DCP-0005 block header
|
|
||||||
// commitments agenda on this network.
|
|
||||||
dcp0005Height int64
|
|
||||||
}
|
|
||||||
|
|
||||||
var mainNetParams = netParams{
|
|
||||||
Params: chaincfg.MainNetParams(),
|
|
||||||
dcrdRPCServerPort: "9109",
|
|
||||||
walletRPCServerPort: "9110",
|
|
||||||
blockExplorerURL: "https://dcrdata.decred.org",
|
|
||||||
minWallets: 3,
|
|
||||||
// dcp0005Height on mainnet is block
|
|
||||||
// 000000000000000010815bed2c4dc431c34a859f4fc70774223dde788e95a01e.
|
|
||||||
dcp0005Height: 431488,
|
|
||||||
}
|
|
||||||
|
|
||||||
var testNet3Params = netParams{
|
|
||||||
Params: chaincfg.TestNet3Params(),
|
|
||||||
dcrdRPCServerPort: "19109",
|
|
||||||
walletRPCServerPort: "19110",
|
|
||||||
blockExplorerURL: "https://testnet.dcrdata.org",
|
|
||||||
minWallets: 1,
|
|
||||||
// dcp0005Height on testnet3 is block
|
|
||||||
// 0000003e54421d585f4a609393a8694509af98f62b8449f245b09fe1389f8f77.
|
|
||||||
dcp0005Height: 323328,
|
|
||||||
}
|
|
||||||
|
|
||||||
var simNetParams = netParams{
|
|
||||||
Params: chaincfg.SimNetParams(),
|
|
||||||
dcrdRPCServerPort: "19556",
|
|
||||||
walletRPCServerPort: "19557",
|
|
||||||
blockExplorerURL: "...",
|
|
||||||
minWallets: 1,
|
|
||||||
// dcp0005Height on simnet is 1 because the agenda will always be active.
|
|
||||||
dcp0005Height: 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
// dcp5Active returns true if the DCP-0005 block header commitments agenda is
|
|
||||||
// active on this network at the provided height, otherwise false.
|
|
||||||
func (n *netParams) dcp5Active(height int64) bool {
|
|
||||||
return height >= n.dcp0005Height
|
|
||||||
}
|
|
||||||
@ -66,7 +66,7 @@ func (s *spentTicket) missed() bool {
|
|||||||
// height of the most recent scanned block.
|
// height of the most recent scanned block.
|
||||||
func (v *vspd) findSpentTickets(ctx context.Context, toCheck database.TicketList,
|
func (v *vspd) findSpentTickets(ctx context.Context, toCheck database.TicketList,
|
||||||
startHeight int64) ([]spentTicket, int64, error) {
|
startHeight int64) ([]spentTicket, int64, error) {
|
||||||
params := v.cfg.netParams
|
network := v.cfg.network
|
||||||
|
|
||||||
dcrdClient, _, err := v.dcrd.Client()
|
dcrdClient, _, err := v.dcrd.Client()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -102,7 +102,7 @@ func (v *vspd) findSpentTickets(ctx context.Context, toCheck database.TicketList
|
|||||||
tickets := make([]ticketTuple, 0, len(toCheck))
|
tickets := make([]ticketTuple, 0, len(toCheck))
|
||||||
scripts := make([][]byte, 0, len(toCheck))
|
scripts := make([][]byte, 0, len(toCheck))
|
||||||
for _, ticket := range toCheck {
|
for _, ticket := range toCheck {
|
||||||
parsedAddr, err := stdaddr.DecodeAddress(ticket.CommitmentAddress, params)
|
parsedAddr, err := stdaddr.DecodeAddress(ticket.CommitmentAddress, network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
@ -135,7 +135,7 @@ func (v *vspd) findSpentTickets(ctx context.Context, toCheck database.TicketList
|
|||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
verifyProof := v.cfg.netParams.dcp5Active(iHeight)
|
verifyProof := network.DCP5Active(iHeight)
|
||||||
key, filter, err := dcrdClient.GetCFilterV2(iHeader, verifyProof)
|
key, filter, err := dcrdClient.GetCFilterV2(iHeader, verifyProof)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
@ -166,7 +166,7 @@ func (v *vspd) findSpentTickets(ctx context.Context, toCheck database.TicketList
|
|||||||
|
|
||||||
spent = append(spent, spentTicket{
|
spent = append(spent, spentTicket{
|
||||||
dbTicket: tickets[i].dbTicket,
|
dbTicket: tickets[i].dbTicket,
|
||||||
expiryHeight: tickets[i].dbTicket.PurchaseHeight + int64(params.TicketMaturity) + int64(params.TicketExpiry),
|
expiryHeight: tickets[i].dbTicket.PurchaseHeight + int64(network.TicketMaturity) + int64(network.TicketExpiry),
|
||||||
heightSpent: iHeight,
|
heightSpent: iHeight,
|
||||||
spendingTx: blkTx,
|
spendingTx: blkTx,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -40,7 +40,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type vspd struct {
|
type vspd struct {
|
||||||
cfg *config
|
cfg *vspdConfig
|
||||||
log slog.Logger
|
log slog.Logger
|
||||||
db *database.VspDatabase
|
db *database.VspDatabase
|
||||||
dcrd rpc.DcrdConnect
|
dcrd rpc.DcrdConnect
|
||||||
@ -55,7 +55,7 @@ type vspd struct {
|
|||||||
|
|
||||||
// newVspd creates the essential resources required by vspd - a database, logger
|
// newVspd creates the essential resources required by vspd - a database, logger
|
||||||
// and RPC clients - then returns an instance of vspd which is ready to be run.
|
// and RPC clients - then returns an instance of vspd which is ready to be run.
|
||||||
func newVspd(cfg *config, log slog.Logger) (*vspd, error) {
|
func newVspd(cfg *vspdConfig, log slog.Logger) (*vspd, error) {
|
||||||
// Open database.
|
// Open database.
|
||||||
db, err := database.Open(cfg.dbPath, cfg.logger(" DB"), maxVoteChangeRecords)
|
db, err := database.Open(cfg.dbPath, cfg.logger(" DB"), maxVoteChangeRecords)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -69,10 +69,10 @@ func newVspd(cfg *config, log slog.Logger) (*vspd, error) {
|
|||||||
|
|
||||||
// Create RPC client for local dcrd instance (used for broadcasting and
|
// Create RPC client for local dcrd instance (used for broadcasting and
|
||||||
// checking the status of fee transactions).
|
// checking the status of fee transactions).
|
||||||
dcrd := rpc.SetupDcrd(cfg.DcrdUser, cfg.DcrdPass, cfg.DcrdHost, cfg.dcrdCert, cfg.netParams.Params, rpcLog, blockNotifChan)
|
dcrd := rpc.SetupDcrd(cfg.DcrdUser, cfg.DcrdPass, cfg.DcrdHost, cfg.dcrdCert, cfg.network.Params, rpcLog, blockNotifChan)
|
||||||
|
|
||||||
// Create RPC client for remote dcrwallet instances (used for voting).
|
// Create RPC client for remote dcrwallet instances (used for voting).
|
||||||
wallets := rpc.SetupWallet(cfg.walletUsers, cfg.walletPasswords, cfg.walletHosts, cfg.walletCerts, cfg.netParams.Params, rpcLog)
|
wallets := rpc.SetupWallet(cfg.walletUsers, cfg.walletPasswords, cfg.walletHosts, cfg.walletCerts, cfg.network.Params, rpcLog)
|
||||||
|
|
||||||
v := &vspd{
|
v := &vspd{
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
@ -142,8 +142,7 @@ func (v *vspd) run() int {
|
|||||||
// Create and start webapi server.
|
// Create and start webapi server.
|
||||||
apiCfg := webapi.Config{
|
apiCfg := webapi.Config{
|
||||||
VSPFee: v.cfg.VSPFee,
|
VSPFee: v.cfg.VSPFee,
|
||||||
NetParams: v.cfg.netParams.Params,
|
Network: v.cfg.network,
|
||||||
BlockExplorerURL: v.cfg.netParams.blockExplorerURL,
|
|
||||||
SupportEmail: v.cfg.SupportEmail,
|
SupportEmail: v.cfg.SupportEmail,
|
||||||
VspClosed: v.cfg.VspClosed,
|
VspClosed: v.cfg.VspClosed,
|
||||||
VspClosedMsg: v.cfg.VspClosedMsg,
|
VspClosedMsg: v.cfg.VspClosedMsg,
|
||||||
@ -292,7 +291,7 @@ func (v *vspd) checkRevoked(ctx context.Context) error {
|
|||||||
|
|
||||||
// Search for the transactions which spend these tickets, starting at the
|
// Search for the transactions which spend these tickets, starting at the
|
||||||
// earliest height one of them matured.
|
// earliest height one of them matured.
|
||||||
startHeight := revoked.EarliestPurchaseHeight() + int64(v.cfg.netParams.TicketMaturity)
|
startHeight := revoked.EarliestPurchaseHeight() + int64(v.cfg.network.TicketMaturity)
|
||||||
|
|
||||||
spent, _, err := v.findSpentTickets(ctx, revoked, startHeight)
|
spent, _, err := v.findSpentTickets(ctx, revoked, startHeight)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -561,7 +560,7 @@ func (v *vspd) blockConnected(ctx context.Context) {
|
|||||||
// Use the earliest height at which a votable ticket matured if vspd has
|
// Use the earliest height at which a votable ticket matured if vspd has
|
||||||
// not performed a scan for spent tickets since it started. This will
|
// not performed a scan for spent tickets since it started. This will
|
||||||
// catch any tickets which were spent whilst vspd was offline.
|
// catch any tickets which were spent whilst vspd was offline.
|
||||||
startHeight = votableTickets.EarliestPurchaseHeight() + int64(v.cfg.netParams.TicketMaturity)
|
startHeight = votableTickets.EarliestPurchaseHeight() + int64(v.cfg.network.TicketMaturity)
|
||||||
} else {
|
} else {
|
||||||
startHeight = v.lastScannedBlock
|
startHeight = v.lastScannedBlock
|
||||||
}
|
}
|
||||||
|
|||||||
61
internal/config/network.go
Normal file
61
internal/config/network.go
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// Copyright (c) 2020-2023 The Decred developers
|
||||||
|
// Use of this source code is governed by an ISC
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/decred/dcrd/chaincfg/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Network struct {
|
||||||
|
*chaincfg.Params
|
||||||
|
DcrdRPCServerPort string
|
||||||
|
WalletRPCServerPort string
|
||||||
|
BlockExplorerURL string
|
||||||
|
// MinWallets is the minimum number of voting wallets required for a vspd
|
||||||
|
// deployment on this network. vspd will log an error and refuse to start if
|
||||||
|
// fewer wallets are configured.
|
||||||
|
MinWallets int
|
||||||
|
// DCP0005Height is the activation height of DCP-0005 block header
|
||||||
|
// commitments agenda on this network.
|
||||||
|
DCP0005Height int64
|
||||||
|
}
|
||||||
|
|
||||||
|
var MainNet = Network{
|
||||||
|
Params: chaincfg.MainNetParams(),
|
||||||
|
DcrdRPCServerPort: "9109",
|
||||||
|
WalletRPCServerPort: "9110",
|
||||||
|
BlockExplorerURL: "https://dcrdata.decred.org",
|
||||||
|
MinWallets: 3,
|
||||||
|
// DCP0005Height on mainnet is block
|
||||||
|
// 000000000000000010815bed2c4dc431c34a859f4fc70774223dde788e95a01e.
|
||||||
|
DCP0005Height: 431488,
|
||||||
|
}
|
||||||
|
|
||||||
|
var TestNet3 = Network{
|
||||||
|
Params: chaincfg.TestNet3Params(),
|
||||||
|
DcrdRPCServerPort: "19109",
|
||||||
|
WalletRPCServerPort: "19110",
|
||||||
|
BlockExplorerURL: "https://testnet.dcrdata.org",
|
||||||
|
MinWallets: 1,
|
||||||
|
// DCP0005Height on testnet3 is block
|
||||||
|
// 0000003e54421d585f4a609393a8694509af98f62b8449f245b09fe1389f8f77.
|
||||||
|
DCP0005Height: 323328,
|
||||||
|
}
|
||||||
|
|
||||||
|
var SimNet = Network{
|
||||||
|
Params: chaincfg.SimNetParams(),
|
||||||
|
DcrdRPCServerPort: "19556",
|
||||||
|
WalletRPCServerPort: "19557",
|
||||||
|
BlockExplorerURL: "...",
|
||||||
|
MinWallets: 1,
|
||||||
|
// DCP0005Height on simnet is 1 because the agenda will always be active.
|
||||||
|
DCP0005Height: 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
// DCP5Active returns true if the DCP-0005 block header commitments agenda is
|
||||||
|
// active on this network at the provided height, otherwise false.
|
||||||
|
func (n *Network) DCP5Active(height int64) bool {
|
||||||
|
return height >= n.DCP0005Height
|
||||||
|
}
|
||||||
@ -62,7 +62,7 @@ func (s *server) getCurrentFee(dcrdClient *rpc.DcrdRPC) (dcrutil.Amount, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fee := txrules.StakePoolTicketFee(sDiff, defaultMinRelayTxFee,
|
fee := txrules.StakePoolTicketFee(sDiff, defaultMinRelayTxFee,
|
||||||
int32(bestBlock.Height), s.cfg.VSPFee, s.cfg.NetParams, isDCP0010Active)
|
int32(bestBlock.Height), s.cfg.VSPFee, s.cfg.Network.Params, isDCP0010Active)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -116,7 +116,7 @@ func (s *server) feeAddress(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure this ticket is eligible to vote at some point in the future.
|
// Ensure this ticket is eligible to vote at some point in the future.
|
||||||
canVote, err := canTicketVote(rawTicket, dcrdClient, s.cfg.NetParams)
|
canVote, err := canTicketVote(rawTicket, dcrdClient, s.cfg.Network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Errorf("%s: canTicketVote error (ticketHash=%s): %v", funcName, ticketHash, err)
|
s.log.Errorf("%s: canTicketVote error (ticketHash=%s): %v", funcName, ticketHash, err)
|
||||||
s.sendError(types.ErrInternalError, c)
|
s.sendError(types.ErrInternalError, c)
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import (
|
|||||||
dcrdtypes "github.com/decred/dcrd/rpc/jsonrpc/types/v4"
|
dcrdtypes "github.com/decred/dcrd/rpc/jsonrpc/types/v4"
|
||||||
"github.com/decred/dcrd/wire"
|
"github.com/decred/dcrd/wire"
|
||||||
"github.com/decred/vspd/database"
|
"github.com/decred/vspd/database"
|
||||||
|
"github.com/decred/vspd/internal/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func currentVoteVersion(params *chaincfg.Params) uint32 {
|
func currentVoteVersion(params *chaincfg.Params) uint32 {
|
||||||
@ -31,12 +32,12 @@ func currentVoteVersion(params *chaincfg.Params) uint32 {
|
|||||||
|
|
||||||
// validConsensusVoteChoices returns an error if provided vote choices are not
|
// validConsensusVoteChoices returns an error if provided vote choices are not
|
||||||
// valid for the most recent consensus agendas.
|
// valid for the most recent consensus agendas.
|
||||||
func validConsensusVoteChoices(params *chaincfg.Params, voteVersion uint32, voteChoices map[string]string) error {
|
func validConsensusVoteChoices(network *config.Network, voteVersion uint32, voteChoices map[string]string) error {
|
||||||
|
|
||||||
agendaLoop:
|
agendaLoop:
|
||||||
for agenda, choice := range voteChoices {
|
for agenda, choice := range voteChoices {
|
||||||
// Does the agenda exist?
|
// Does the agenda exist?
|
||||||
for _, v := range params.Deployments[voteVersion] {
|
for _, v := range network.Deployments[voteVersion] {
|
||||||
if v.Vote.Id == agenda {
|
if v.Vote.Id == agenda {
|
||||||
// Agenda exists - does the vote choice exist?
|
// Agenda exists - does the vote choice exist?
|
||||||
for _, c := range v.Vote.Choices {
|
for _, c := range v.Vote.Choices {
|
||||||
@ -107,9 +108,9 @@ func validPolicyOption(policy string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func validateSignature(hash, commitmentAddress, signature, message string,
|
func validateSignature(hash, commitmentAddress, signature, message string,
|
||||||
db *database.VspDatabase, params *chaincfg.Params) error {
|
db *database.VspDatabase, network *config.Network) error {
|
||||||
|
|
||||||
firstErr := dcrutil.VerifyMessage(commitmentAddress, signature, message, params)
|
firstErr := dcrutil.VerifyMessage(commitmentAddress, signature, message, network)
|
||||||
if firstErr != nil {
|
if firstErr != nil {
|
||||||
// Don't return an error straight away if sig validation fails -
|
// Don't return an error straight away if sig validation fails -
|
||||||
// first check if we have an alternate sign address for this ticket.
|
// first check if we have an alternate sign address for this ticket.
|
||||||
@ -121,7 +122,7 @@ func validateSignature(hash, commitmentAddress, signature, message string,
|
|||||||
// If we have no alternate sign address, or if validating with the
|
// If we have no alternate sign address, or if validating with the
|
||||||
// alt sign addr fails, return an error to the client.
|
// alt sign addr fails, return an error to the client.
|
||||||
if altSigData == nil ||
|
if altSigData == nil ||
|
||||||
dcrutil.VerifyMessage(altSigData.AltSignAddr, signature, message, params) != nil {
|
dcrutil.VerifyMessage(altSigData.AltSignAddr, signature, message, network) != nil {
|
||||||
return fmt.Errorf("bad signature")
|
return fmt.Errorf("bad signature")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,17 +173,17 @@ func validateTicketHash(hash string) error {
|
|||||||
// canTicketVote checks determines whether a ticket is able to vote at some
|
// canTicketVote checks determines whether a ticket is able to vote at some
|
||||||
// point in the future by checking that it is currently either in the mempool,
|
// point in the future by checking that it is currently either in the mempool,
|
||||||
// immature or live.
|
// immature or live.
|
||||||
func canTicketVote(rawTx *dcrdtypes.TxRawResult, dcrdClient node, netParams *chaincfg.Params) (bool, error) {
|
func canTicketVote(rawTx *dcrdtypes.TxRawResult, dcrdClient node, network *config.Network) (bool, error) {
|
||||||
|
|
||||||
// Tickets which have more than (TicketMaturity+TicketExpiry+1)
|
// Tickets which have more than (TicketMaturity+TicketExpiry+1)
|
||||||
// confirmations are too old to vote.
|
// confirmations are too old to vote.
|
||||||
if rawTx.Confirmations > int64(uint32(netParams.TicketMaturity)+netParams.TicketExpiry)+1 {
|
if rawTx.Confirmations > int64(uint32(network.TicketMaturity)+network.TicketExpiry)+1 {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// If ticket is currently immature (or in the mempool), it will be able to
|
// If ticket is currently immature (or in the mempool), it will be able to
|
||||||
// vote in future.
|
// vote in future.
|
||||||
if rawTx.Confirmations <= int64(netParams.TicketMaturity) {
|
if rawTx.Confirmations <= int64(network.TicketMaturity) {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2020-2022 The Decred developers
|
// Copyright (c) 2020-2023 The Decred developers
|
||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
@ -7,7 +7,7 @@ package webapi
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/decred/dcrd/chaincfg/v3"
|
"github.com/decred/vspd/internal/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIsValidVoteChoices(t *testing.T) {
|
func TestIsValidVoteChoices(t *testing.T) {
|
||||||
@ -15,7 +15,7 @@ func TestIsValidVoteChoices(t *testing.T) {
|
|||||||
// Mainnet vote version 4 contains 2 agendas - sdiffalgorithm and lnsupport.
|
// Mainnet vote version 4 contains 2 agendas - sdiffalgorithm and lnsupport.
|
||||||
// Both agendas have vote choices yes/no/abstain.
|
// Both agendas have vote choices yes/no/abstain.
|
||||||
voteVersion := uint32(4)
|
voteVersion := uint32(4)
|
||||||
params := chaincfg.MainNetParams()
|
network := config.MainNet
|
||||||
|
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
voteChoices map[string]string
|
voteChoices map[string]string
|
||||||
@ -46,7 +46,7 @@ func TestIsValidVoteChoices(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
err := validConsensusVoteChoices(params, voteVersion, test.voteChoices)
|
err := validConsensusVoteChoices(&network, voteVersion, test.voteChoices)
|
||||||
if (err == nil) != test.valid {
|
if (err == nil) != test.valid {
|
||||||
t.Fatalf("isValidVoteChoices failed for votechoices '%v': %v",
|
t.Fatalf("isValidVoteChoices failed for votechoices '%v': %v",
|
||||||
test.voteChoices, err)
|
test.voteChoices, err)
|
||||||
|
|||||||
@ -387,7 +387,7 @@ func (s *server) vspAuth(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
addr, err := stake.AddrFromSStxPkScrCommitment(msgTx.TxOut[1].PkScript, s.cfg.NetParams)
|
addr, err := stake.AddrFromSStxPkScrCommitment(msgTx.TxOut[1].PkScript, s.cfg.Network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Errorf("%s: AddrFromSStxPkScrCommitment error (clientIP=%s, ticketHash=%s): %v",
|
s.log.Errorf("%s: AddrFromSStxPkScrCommitment error (clientIP=%s, ticketHash=%s): %v",
|
||||||
funcName, c.ClientIP(), hash, err)
|
funcName, c.ClientIP(), hash, err)
|
||||||
@ -407,7 +407,7 @@ func (s *server) vspAuth(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate request signature to ensure ticket ownership.
|
// Validate request signature to ensure ticket ownership.
|
||||||
err = validateSignature(hash, commitmentAddress, signature, string(reqBytes), s.db, s.cfg.NetParams)
|
err = validateSignature(hash, commitmentAddress, signature, string(reqBytes), s.db, s.cfg.Network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Errorf("%s: Couldn't validate signature (clientIP=%s, ticketHash=%s): %v",
|
s.log.Errorf("%s: Couldn't validate signature (clientIP=%s, ticketHash=%s): %v",
|
||||||
funcName, c.ClientIP(), hash, err)
|
funcName, c.ClientIP(), hash, err)
|
||||||
|
|||||||
@ -68,7 +68,7 @@ func (s *server) payFee(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure this ticket is eligible to vote at some point in the future.
|
// Ensure this ticket is eligible to vote at some point in the future.
|
||||||
canVote, err := canTicketVote(rawTicket, dcrdClient, s.cfg.NetParams)
|
canVote, err := canTicketVote(rawTicket, dcrdClient, s.cfg.Network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Errorf("%s: canTicketVote error (ticketHash=%s): %v", funcName, ticket.Hash, err)
|
s.log.Errorf("%s: canTicketVote error (ticketHash=%s): %v", funcName, ticket.Hash, err)
|
||||||
s.sendError(types.ErrInternalError, c)
|
s.sendError(types.ErrInternalError, c)
|
||||||
@ -91,7 +91,7 @@ func (s *server) payFee(c *gin.Context) {
|
|||||||
|
|
||||||
// Validate VotingKey.
|
// Validate VotingKey.
|
||||||
votingKey := request.VotingKey
|
votingKey := request.VotingKey
|
||||||
votingWIF, err := dcrutil.DecodeWIF(votingKey, s.cfg.NetParams.PrivateKeyID)
|
votingWIF, err := dcrutil.DecodeWIF(votingKey, s.cfg.Network.PrivateKeyID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Warnf("%s: Failed to decode WIF (clientIP=%s, ticketHash=%s): %v",
|
s.log.Warnf("%s: Failed to decode WIF (clientIP=%s, ticketHash=%s): %v",
|
||||||
funcName, c.ClientIP(), ticket.Hash, err)
|
funcName, c.ClientIP(), ticket.Hash, err)
|
||||||
@ -103,7 +103,7 @@ func (s *server) payFee(c *gin.Context) {
|
|||||||
// the ticket should still be registered.
|
// the ticket should still be registered.
|
||||||
|
|
||||||
validVoteChoices := true
|
validVoteChoices := true
|
||||||
err = validConsensusVoteChoices(s.cfg.NetParams, currentVoteVersion(s.cfg.NetParams), request.VoteChoices)
|
err = validConsensusVoteChoices(s.cfg.Network, currentVoteVersion(s.cfg.Network.Params), request.VoteChoices)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
validVoteChoices = false
|
validVoteChoices = false
|
||||||
s.log.Warnf("%s: Invalid consensus vote choices (clientIP=%s, ticketHash=%s): %v",
|
s.log.Warnf("%s: Invalid consensus vote choices (clientIP=%s, ticketHash=%s): %v",
|
||||||
@ -135,7 +135,7 @@ func (s *server) payFee(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = blockchain.CheckTransactionSanity(feeTx, uint64(s.cfg.NetParams.MaxTxSize))
|
err = blockchain.CheckTransactionSanity(feeTx, uint64(s.cfg.Network.MaxTxSize))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Warnf("%s: Fee tx failed sanity check (clientIP=%s, ticketHash=%s): %v",
|
s.log.Warnf("%s: Fee tx failed sanity check (clientIP=%s, ticketHash=%s): %v",
|
||||||
funcName, c.ClientIP(), ticket.Hash, err)
|
funcName, c.ClientIP(), ticket.Hash, err)
|
||||||
@ -144,7 +144,7 @@ func (s *server) payFee(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Decode fee address to get its payment script details.
|
// Decode fee address to get its payment script details.
|
||||||
feeAddr, err := stdaddr.DecodeAddress(ticket.FeeAddress, s.cfg.NetParams)
|
feeAddr, err := stdaddr.DecodeAddress(ticket.FeeAddress, s.cfg.Network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Errorf("%s: Failed to decode fee address (ticketHash=%s): %v",
|
s.log.Errorf("%s: Failed to decode fee address (ticketHash=%s): %v",
|
||||||
funcName, ticket.Hash, err)
|
funcName, ticket.Hash, err)
|
||||||
@ -185,7 +185,7 @@ func (s *server) payFee(c *gin.Context) {
|
|||||||
|
|
||||||
// Decode the provided voting WIF to get its voting rights script.
|
// Decode the provided voting WIF to get its voting rights script.
|
||||||
pkHash := stdaddr.Hash160(votingWIF.PubKey())
|
pkHash := stdaddr.Hash160(votingWIF.PubKey())
|
||||||
wifAddr, err := stdaddr.NewAddressPubKeyHashEcdsaSecp256k1V0(pkHash, s.cfg.NetParams)
|
wifAddr, err := stdaddr.NewAddressPubKeyHashEcdsaSecp256k1V0(pkHash, s.cfg.Network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Errorf("%s: Failed to get voting address from WIF (ticketHash=%s, clientIP=%s): %v",
|
s.log.Errorf("%s: Failed to get voting address from WIF (ticketHash=%s, clientIP=%s): %v",
|
||||||
funcName, ticket.Hash, c.ClientIP(), err)
|
funcName, ticket.Hash, c.ClientIP(), err)
|
||||||
|
|||||||
@ -64,7 +64,7 @@ func (s *server) setAltSignAddr(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fail fast if the pubkey doesn't decode properly.
|
// Fail fast if the pubkey doesn't decode properly.
|
||||||
addr, err := stdaddr.DecodeAddressV0(altSignAddr, s.cfg.NetParams)
|
addr, err := stdaddr.DecodeAddressV0(altSignAddr, s.cfg.Network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Warnf("%s: Alt sign address cannot be decoded (clientIP=%s): %v", funcName, c.ClientIP(), err)
|
s.log.Warnf("%s: Alt sign address cannot be decoded (clientIP=%s): %v", funcName, c.ClientIP(), err)
|
||||||
s.sendErrorWithMsg(err.Error(), types.ErrBadRequest, c)
|
s.sendErrorWithMsg(err.Error(), types.ErrBadRequest, c)
|
||||||
@ -85,7 +85,7 @@ func (s *server) setAltSignAddr(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure this ticket is eligible to vote at some point in the future.
|
// Ensure this ticket is eligible to vote at some point in the future.
|
||||||
canVote, err := canTicketVote(rawTicket, dcrdClient, s.cfg.NetParams)
|
canVote, err := canTicketVote(rawTicket, dcrdClient, s.cfg.Network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Errorf("%s: canTicketVote error (ticketHash=%s): %v", funcName, ticketHash, err)
|
s.log.Errorf("%s: canTicketVote error (ticketHash=%s): %v", funcName, ticketHash, err)
|
||||||
s.sendError(types.ErrInternalError, c)
|
s.sendError(types.ErrInternalError, c)
|
||||||
|
|||||||
@ -18,10 +18,10 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/decred/dcrd/chaincfg/v3"
|
|
||||||
dcrdtypes "github.com/decred/dcrd/rpc/jsonrpc/types/v4"
|
dcrdtypes "github.com/decred/dcrd/rpc/jsonrpc/types/v4"
|
||||||
"github.com/decred/slog"
|
"github.com/decred/slog"
|
||||||
"github.com/decred/vspd/database"
|
"github.com/decred/vspd/database"
|
||||||
|
"github.com/decred/vspd/internal/config"
|
||||||
"github.com/decred/vspd/types/v2"
|
"github.com/decred/vspd/types/v2"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
@ -64,7 +64,7 @@ func TestMain(m *testing.M) {
|
|||||||
|
|
||||||
// Set up some global params.
|
// Set up some global params.
|
||||||
cfg := Config{
|
cfg := Config{
|
||||||
NetParams: chaincfg.MainNetParams(),
|
Network: &config.MainNet,
|
||||||
}
|
}
|
||||||
_, signPrivKey, _ := ed25519.GenerateKey(seededRand)
|
_, signPrivKey, _ := ed25519.GenerateKey(seededRand)
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2020-2022 The Decred developers
|
// Copyright (c) 2020-2023 The Decred developers
|
||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ func (s *server) setVoteChoices(c *gin.Context) {
|
|||||||
|
|
||||||
// Validate vote choices (consensus, tspend policy and treasury policy).
|
// Validate vote choices (consensus, tspend policy and treasury policy).
|
||||||
|
|
||||||
err = validConsensusVoteChoices(s.cfg.NetParams, currentVoteVersion(s.cfg.NetParams), request.VoteChoices)
|
err = validConsensusVoteChoices(s.cfg.Network, currentVoteVersion(s.cfg.Network.Params), request.VoteChoices)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Warnf("%s: Invalid consensus vote choices (clientIP=%s, ticketHash=%s): %v",
|
s.log.Warnf("%s: Invalid consensus vote choices (clientIP=%s, ticketHash=%s): %v",
|
||||||
funcName, c.ClientIP(), ticket.Hash, err)
|
funcName, c.ClientIP(), ticket.Hash, err)
|
||||||
|
|||||||
@ -20,7 +20,7 @@ func (s *server) vspInfo(c *gin.Context) {
|
|||||||
Timestamp: time.Now().Unix(),
|
Timestamp: time.Now().Unix(),
|
||||||
PubKey: s.signPubKey,
|
PubKey: s.signPubKey,
|
||||||
FeePercentage: s.cfg.VSPFee,
|
FeePercentage: s.cfg.VSPFee,
|
||||||
Network: s.cfg.NetParams.Name,
|
Network: s.cfg.Network.Name,
|
||||||
VspClosed: s.cfg.VspClosed,
|
VspClosed: s.cfg.VspClosed,
|
||||||
VspClosedMsg: s.cfg.VspClosedMsg,
|
VspClosedMsg: s.cfg.VspClosedMsg,
|
||||||
VspdVersion: version.String(),
|
VspdVersion: version.String(),
|
||||||
|
|||||||
@ -17,9 +17,9 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/decred/dcrd/chaincfg/v3"
|
|
||||||
"github.com/decred/slog"
|
"github.com/decred/slog"
|
||||||
"github.com/decred/vspd/database"
|
"github.com/decred/vspd/database"
|
||||||
|
"github.com/decred/vspd/internal/config"
|
||||||
"github.com/decred/vspd/rpc"
|
"github.com/decred/vspd/rpc"
|
||||||
"github.com/decred/vspd/types/v2"
|
"github.com/decred/vspd/types/v2"
|
||||||
"github.com/dustin/go-humanize"
|
"github.com/dustin/go-humanize"
|
||||||
@ -29,8 +29,7 @@ import (
|
|||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
VSPFee float64
|
VSPFee float64
|
||||||
NetParams *chaincfg.Params
|
Network *config.Network
|
||||||
BlockExplorerURL string
|
|
||||||
FeeAccountName string
|
FeeAccountName string
|
||||||
SupportEmail string
|
SupportEmail string
|
||||||
VspClosed bool
|
VspClosed bool
|
||||||
@ -77,10 +76,10 @@ type server struct {
|
|||||||
|
|
||||||
func Start(ctx context.Context, requestShutdown func(), shutdownWg *sync.WaitGroup,
|
func Start(ctx context.Context, requestShutdown func(), shutdownWg *sync.WaitGroup,
|
||||||
listen string, vdb *database.VspDatabase, log slog.Logger, dcrd rpc.DcrdConnect,
|
listen string, vdb *database.VspDatabase, log slog.Logger, dcrd rpc.DcrdConnect,
|
||||||
wallets rpc.WalletConnect, config Config) error {
|
wallets rpc.WalletConnect, cfg Config) error {
|
||||||
|
|
||||||
s := &server{
|
s := &server{
|
||||||
cfg: config,
|
cfg: cfg,
|
||||||
db: vdb,
|
db: vdb,
|
||||||
log: log,
|
log: log,
|
||||||
}
|
}
|
||||||
@ -110,7 +109,7 @@ func Start(ctx context.Context, requestShutdown func(), shutdownWg *sync.WaitGro
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("db.GetFeeXPub error: %w", err)
|
return fmt.Errorf("db.GetFeeXPub error: %w", err)
|
||||||
}
|
}
|
||||||
s.addrGen, err = newAddressGenerator(feeXPub, config.NetParams, idx, log)
|
s.addrGen, err = newAddressGenerator(feeXPub, cfg.Network.Params, idx, log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to initialize fee address generator: %w", err)
|
return fmt.Errorf("failed to initialize fee address generator: %w", err)
|
||||||
}
|
}
|
||||||
@ -200,11 +199,13 @@ func (s *server) router(cookieSecret []byte, dcrd rpc.DcrdConnect, wallets rpc.W
|
|||||||
|
|
||||||
router := gin.New()
|
router := gin.New()
|
||||||
|
|
||||||
|
explorerURL := s.cfg.Network.BlockExplorerURL
|
||||||
|
|
||||||
// Add custom functions for use in templates.
|
// Add custom functions for use in templates.
|
||||||
router.SetFuncMap(template.FuncMap{
|
router.SetFuncMap(template.FuncMap{
|
||||||
"txURL": txURL(s.cfg.BlockExplorerURL),
|
"txURL": txURL(explorerURL),
|
||||||
"addressURL": addressURL(s.cfg.BlockExplorerURL),
|
"addressURL": addressURL(explorerURL),
|
||||||
"blockURL": blockURL(s.cfg.BlockExplorerURL),
|
"blockURL": blockURL(explorerURL),
|
||||||
"dateTime": dateTime,
|
"dateTime": dateTime,
|
||||||
"stripWss": stripWss,
|
"stripWss": stripWss,
|
||||||
"indentJSON": indentJSON(s.log),
|
"indentJSON": indentJSON(s.log),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user