diff --git a/cmd/vote-validator/main.go b/cmd/vote-validator/main.go index 4e80b02..a7a06cd 100644 --- a/cmd/vote-validator/main.go +++ b/cmd/vote-validator/main.go @@ -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 // license that can be found in the LICENSE file. @@ -11,11 +11,11 @@ import ( "os" "sort" - "github.com/decred/dcrd/chaincfg/v3" "github.com/decred/slog" "github.com/jessevdk/go-flags" "github.com/decred/vspd/database" + "github.com/decred/vspd/internal/config" ) const ( @@ -58,20 +58,19 @@ func run() int { return 1 } - var dcrdata *dcrdataClient - var params *chaincfg.Params + var network *config.Network if cfg.Testnet { - dcrdata = &dcrdataClient{URL: "https://testnet.dcrdata.org"} - params = chaincfg.TestNet3Params() + network = &config.TestNet3 } else { - dcrdata = &dcrdataClient{URL: "https://explorer.dcrdata.org"} - params = chaincfg.MainNetParams() + network = &config.MainNet } + dcrdata := &dcrdataClient{URL: network.BlockExplorerURL} + // Get the latest vote version. Any votes which don't match this version // will be ignored. var latestVoteVersion uint32 - for version := range params.Deployments { + for version := range network.Deployments { if version > latestVoteVersion { latestVoteVersion = version } @@ -163,7 +162,7 @@ func run() int { // Get the recorded on-chain votes for this ticket. actualVote := make(map[string]string) - agendas := params.Deployments[latestVoteVersion] + agendas := network.Deployments[latestVoteVersion] for _, agenda := range agendas { for _, choice := range agenda.Vote.Choices { if votebits&agenda.Vote.Mask == choice.Bits { diff --git a/cmd/vspd/config.go b/cmd/vspd/config.go index d5df409..efaf05e 100644 --- a/cmd/vspd/config.go +++ b/cmd/vspd/config.go @@ -20,6 +20,7 @@ import ( "github.com/decred/dcrd/hdkeychain/v3" "github.com/decred/slog" "github.com/decred/vspd/database" + "github.com/decred/vspd/internal/config" "github.com/decred/vspd/internal/version" flags "github.com/jessevdk/go-flags" ) @@ -45,8 +46,8 @@ var ( defaultDesignation = "Voting Service Provider" ) -// config defines the configuration options for the VSP. -type config struct { +// vspdConfig defines the configuration options for the vspd process. +type vspdConfig 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"` 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 dbPath string - netParams *netParams + network *config.Network dcrdCert []byte walletHosts, walletUsers, walletPasswords []string walletCerts [][]byte @@ -169,10 +170,10 @@ func normalizeAddress(addr, defaultPort string) string { // The above results in vspd 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) { +func loadConfig() (*vspdConfig, error) { // Default config. - cfg := config{ + cfg := vspdConfig{ Listen: defaultListen, LogLevel: defaultLogLevel, MaxLogSize: defaultMaxLogSize, @@ -280,11 +281,11 @@ func loadConfig() (*config, error) { // Set the active network. switch cfg.Network { case "testnet": - cfg.netParams = &testNet3Params + cfg.network = &config.TestNet3 case "mainnet": - cfg.netParams = &mainNetParams + cfg.network = &config.MainNet case "simnet": - cfg.netParams = &simNetParams + cfg.network = &config.SimNet } // Ensure backup interval is greater than 30 seconds. @@ -388,26 +389,26 @@ func loadConfig() (*config, error) { } // 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", - numHost, cfg.netParams.minWallets) + numHost, cfg.network.MinWallets) } // Add default port for the active network if there is no port specified. 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. - dataDir := filepath.Join(cfg.HomeDir, "data", cfg.netParams.Name) + dataDir := filepath.Join(cfg.HomeDir, "data", cfg.network.Name) err = os.MkdirAll(dataDir, 0700) if err != nil { return nil, fmt.Errorf("failed to create data directory: %w", err) } // 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) if err != nil { 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. - _, err = hdkeychain.NewKeyFromString(cfg.FeeXPub, cfg.netParams.Params) + _, err = hdkeychain.NewKeyFromString(cfg.FeeXPub, cfg.network.Params) if err != nil { return nil, fmt.Errorf("failed to parse feexpub: %w", err) } @@ -444,7 +445,6 @@ func loadConfig() (*config, error) { // Exit with success os.Exit(0) - } // If database does not exist, return error. @@ -456,7 +456,7 @@ func loadConfig() (*config, error) { 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.SetLevel(cfg.logLevel) return log diff --git a/cmd/vspd/main.go b/cmd/vspd/main.go index d2c0593..b6e4342 100644 --- a/cmd/vspd/main.go +++ b/cmd/vspd/main.go @@ -9,6 +9,7 @@ import ( "os" "runtime" + "github.com/decred/vspd/internal/config" "github.com/decred/vspd/internal/version" ) @@ -32,7 +33,7 @@ func run() int { log.Criticalf("Version %s (Go version %s %s/%s)", version.String(), runtime.Version(), runtime.GOOS, runtime.GOARCH) - if cfg.netParams == &mainNetParams && version.IsPreRelease() { + if cfg.network == &config.MainNet && version.IsPreRelease() { log.Warnf("") log.Warnf("\tWARNING: This is a pre-release version of vspd which should not be used on mainnet.") log.Warnf("") diff --git a/cmd/vspd/params.go b/cmd/vspd/params.go deleted file mode 100644 index bb0d2bd..0000000 --- a/cmd/vspd/params.go +++ /dev/null @@ -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 -} diff --git a/cmd/vspd/spentticket.go b/cmd/vspd/spentticket.go index ddbfaab..9c61c98 100644 --- a/cmd/vspd/spentticket.go +++ b/cmd/vspd/spentticket.go @@ -66,7 +66,7 @@ func (s *spentTicket) missed() bool { // height of the most recent scanned block. func (v *vspd) findSpentTickets(ctx context.Context, toCheck database.TicketList, startHeight int64) ([]spentTicket, int64, error) { - params := v.cfg.netParams + network := v.cfg.network dcrdClient, _, err := v.dcrd.Client() if err != nil { @@ -102,7 +102,7 @@ func (v *vspd) findSpentTickets(ctx context.Context, toCheck database.TicketList tickets := make([]ticketTuple, 0, len(toCheck)) scripts := make([][]byte, 0, len(toCheck)) for _, ticket := range toCheck { - parsedAddr, err := stdaddr.DecodeAddress(ticket.CommitmentAddress, params) + parsedAddr, err := stdaddr.DecodeAddress(ticket.CommitmentAddress, network) if err != nil { return nil, 0, err } @@ -135,7 +135,7 @@ func (v *vspd) findSpentTickets(ctx context.Context, toCheck database.TicketList return nil, 0, err } - verifyProof := v.cfg.netParams.dcp5Active(iHeight) + verifyProof := network.DCP5Active(iHeight) key, filter, err := dcrdClient.GetCFilterV2(iHeader, verifyProof) if err != nil { return nil, 0, err @@ -166,7 +166,7 @@ func (v *vspd) findSpentTickets(ctx context.Context, toCheck database.TicketList spent = append(spent, spentTicket{ 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, spendingTx: blkTx, }) diff --git a/cmd/vspd/vspd.go b/cmd/vspd/vspd.go index 9243b9c..a869959 100644 --- a/cmd/vspd/vspd.go +++ b/cmd/vspd/vspd.go @@ -40,7 +40,7 @@ const ( ) type vspd struct { - cfg *config + cfg *vspdConfig log slog.Logger db *database.VspDatabase dcrd rpc.DcrdConnect @@ -55,7 +55,7 @@ type vspd struct { // 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. -func newVspd(cfg *config, log slog.Logger) (*vspd, error) { +func newVspd(cfg *vspdConfig, log slog.Logger) (*vspd, error) { // Open database. db, err := database.Open(cfg.dbPath, cfg.logger(" DB"), maxVoteChangeRecords) 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 // 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). - 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{ cfg: cfg, @@ -142,8 +142,7 @@ func (v *vspd) run() int { // Create and start webapi server. apiCfg := webapi.Config{ VSPFee: v.cfg.VSPFee, - NetParams: v.cfg.netParams.Params, - BlockExplorerURL: v.cfg.netParams.blockExplorerURL, + Network: v.cfg.network, SupportEmail: v.cfg.SupportEmail, VspClosed: v.cfg.VspClosed, 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 // 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) 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 // not performed a scan for spent tickets since it started. This will // 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 { startHeight = v.lastScannedBlock } diff --git a/internal/config/network.go b/internal/config/network.go new file mode 100644 index 0000000..a275f6c --- /dev/null +++ b/internal/config/network.go @@ -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 +} diff --git a/internal/webapi/getfeeaddress.go b/internal/webapi/getfeeaddress.go index ab5fe6a..619e590 100644 --- a/internal/webapi/getfeeaddress.go +++ b/internal/webapi/getfeeaddress.go @@ -62,7 +62,7 @@ func (s *server) getCurrentFee(dcrdClient *rpc.DcrdRPC) (dcrutil.Amount, error) } 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 { 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. - canVote, err := canTicketVote(rawTicket, dcrdClient, s.cfg.NetParams) + canVote, err := canTicketVote(rawTicket, dcrdClient, s.cfg.Network) if err != nil { s.log.Errorf("%s: canTicketVote error (ticketHash=%s): %v", funcName, ticketHash, err) s.sendError(types.ErrInternalError, c) diff --git a/internal/webapi/helpers.go b/internal/webapi/helpers.go index 84f89bb..4790e68 100644 --- a/internal/webapi/helpers.go +++ b/internal/webapi/helpers.go @@ -17,6 +17,7 @@ import ( dcrdtypes "github.com/decred/dcrd/rpc/jsonrpc/types/v4" "github.com/decred/dcrd/wire" "github.com/decred/vspd/database" + "github.com/decred/vspd/internal/config" ) 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 // 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: for agenda, choice := range voteChoices { // Does the agenda exist? - for _, v := range params.Deployments[voteVersion] { + for _, v := range network.Deployments[voteVersion] { if v.Vote.Id == agenda { // Agenda exists - does the vote choice exist? for _, c := range v.Vote.Choices { @@ -107,9 +108,9 @@ func validPolicyOption(policy string) error { } 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 { // Don't return an error straight away if sig validation fails - // 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 // alt sign addr fails, return an error to the client. if altSigData == nil || - dcrutil.VerifyMessage(altSigData.AltSignAddr, signature, message, params) != nil { + dcrutil.VerifyMessage(altSigData.AltSignAddr, signature, message, network) != nil { 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 // point in the future by checking that it is currently either in the mempool, // 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) // 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 } // If ticket is currently immature (or in the mempool), it will be able to // vote in future. - if rawTx.Confirmations <= int64(netParams.TicketMaturity) { + if rawTx.Confirmations <= int64(network.TicketMaturity) { return true, nil } diff --git a/internal/webapi/helpers_test.go b/internal/webapi/helpers_test.go index 8ecd221..e913a12 100644 --- a/internal/webapi/helpers_test.go +++ b/internal/webapi/helpers_test.go @@ -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 // license that can be found in the LICENSE file. @@ -7,7 +7,7 @@ package webapi import ( "testing" - "github.com/decred/dcrd/chaincfg/v3" + "github.com/decred/vspd/internal/config" ) func TestIsValidVoteChoices(t *testing.T) { @@ -15,7 +15,7 @@ func TestIsValidVoteChoices(t *testing.T) { // Mainnet vote version 4 contains 2 agendas - sdiffalgorithm and lnsupport. // Both agendas have vote choices yes/no/abstain. voteVersion := uint32(4) - params := chaincfg.MainNetParams() + network := config.MainNet var tests = []struct { voteChoices map[string]string @@ -46,7 +46,7 @@ func TestIsValidVoteChoices(t *testing.T) { } for _, test := range tests { - err := validConsensusVoteChoices(params, voteVersion, test.voteChoices) + err := validConsensusVoteChoices(&network, voteVersion, test.voteChoices) if (err == nil) != test.valid { t.Fatalf("isValidVoteChoices failed for votechoices '%v': %v", test.voteChoices, err) diff --git a/internal/webapi/middleware.go b/internal/webapi/middleware.go index d1e9e59..85b6a8a 100644 --- a/internal/webapi/middleware.go +++ b/internal/webapi/middleware.go @@ -387,7 +387,7 @@ func (s *server) vspAuth(c *gin.Context) { 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 { s.log.Errorf("%s: AddrFromSStxPkScrCommitment error (clientIP=%s, ticketHash=%s): %v", funcName, c.ClientIP(), hash, err) @@ -407,7 +407,7 @@ func (s *server) vspAuth(c *gin.Context) { } // 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 { s.log.Errorf("%s: Couldn't validate signature (clientIP=%s, ticketHash=%s): %v", funcName, c.ClientIP(), hash, err) diff --git a/internal/webapi/payfee.go b/internal/webapi/payfee.go index 979e5a9..052107e 100644 --- a/internal/webapi/payfee.go +++ b/internal/webapi/payfee.go @@ -68,7 +68,7 @@ func (s *server) payFee(c *gin.Context) { } // 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 { s.log.Errorf("%s: canTicketVote error (ticketHash=%s): %v", funcName, ticket.Hash, err) s.sendError(types.ErrInternalError, c) @@ -91,7 +91,7 @@ func (s *server) payFee(c *gin.Context) { // Validate 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 { s.log.Warnf("%s: Failed to decode WIF (clientIP=%s, ticketHash=%s): %v", funcName, c.ClientIP(), ticket.Hash, err) @@ -103,7 +103,7 @@ func (s *server) payFee(c *gin.Context) { // the ticket should still be registered. 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 { validVoteChoices = false 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 } - err = blockchain.CheckTransactionSanity(feeTx, uint64(s.cfg.NetParams.MaxTxSize)) + err = blockchain.CheckTransactionSanity(feeTx, uint64(s.cfg.Network.MaxTxSize)) if err != nil { s.log.Warnf("%s: Fee tx failed sanity check (clientIP=%s, ticketHash=%s): %v", 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. - feeAddr, err := stdaddr.DecodeAddress(ticket.FeeAddress, s.cfg.NetParams) + feeAddr, err := stdaddr.DecodeAddress(ticket.FeeAddress, s.cfg.Network) if err != nil { s.log.Errorf("%s: Failed to decode fee address (ticketHash=%s): %v", 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. pkHash := stdaddr.Hash160(votingWIF.PubKey()) - wifAddr, err := stdaddr.NewAddressPubKeyHashEcdsaSecp256k1V0(pkHash, s.cfg.NetParams) + wifAddr, err := stdaddr.NewAddressPubKeyHashEcdsaSecp256k1V0(pkHash, s.cfg.Network) if err != nil { s.log.Errorf("%s: Failed to get voting address from WIF (ticketHash=%s, clientIP=%s): %v", funcName, ticket.Hash, c.ClientIP(), err) diff --git a/internal/webapi/setaltsignaddr.go b/internal/webapi/setaltsignaddr.go index 93dcacf..2abe0a4 100644 --- a/internal/webapi/setaltsignaddr.go +++ b/internal/webapi/setaltsignaddr.go @@ -64,7 +64,7 @@ func (s *server) setAltSignAddr(c *gin.Context) { } // 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 { s.log.Warnf("%s: Alt sign address cannot be decoded (clientIP=%s): %v", funcName, c.ClientIP(), err) 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. - canVote, err := canTicketVote(rawTicket, dcrdClient, s.cfg.NetParams) + canVote, err := canTicketVote(rawTicket, dcrdClient, s.cfg.Network) if err != nil { s.log.Errorf("%s: canTicketVote error (ticketHash=%s): %v", funcName, ticketHash, err) s.sendError(types.ErrInternalError, c) diff --git a/internal/webapi/setaltsignaddr_test.go b/internal/webapi/setaltsignaddr_test.go index 3841fe5..bde951f 100644 --- a/internal/webapi/setaltsignaddr_test.go +++ b/internal/webapi/setaltsignaddr_test.go @@ -18,10 +18,10 @@ import ( "testing" "time" - "github.com/decred/dcrd/chaincfg/v3" dcrdtypes "github.com/decred/dcrd/rpc/jsonrpc/types/v4" "github.com/decred/slog" "github.com/decred/vspd/database" + "github.com/decred/vspd/internal/config" "github.com/decred/vspd/types/v2" "github.com/gin-gonic/gin" ) @@ -64,7 +64,7 @@ func TestMain(m *testing.M) { // Set up some global params. cfg := Config{ - NetParams: chaincfg.MainNetParams(), + Network: &config.MainNet, } _, signPrivKey, _ := ed25519.GenerateKey(seededRand) diff --git a/internal/webapi/setvotechoices.go b/internal/webapi/setvotechoices.go index 489a5d6..272852f 100644 --- a/internal/webapi/setvotechoices.go +++ b/internal/webapi/setvotechoices.go @@ -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 // 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). - 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 { s.log.Warnf("%s: Invalid consensus vote choices (clientIP=%s, ticketHash=%s): %v", funcName, c.ClientIP(), ticket.Hash, err) diff --git a/internal/webapi/vspinfo.go b/internal/webapi/vspinfo.go index 908810e..d0c96d1 100644 --- a/internal/webapi/vspinfo.go +++ b/internal/webapi/vspinfo.go @@ -20,7 +20,7 @@ func (s *server) vspInfo(c *gin.Context) { Timestamp: time.Now().Unix(), PubKey: s.signPubKey, FeePercentage: s.cfg.VSPFee, - Network: s.cfg.NetParams.Name, + Network: s.cfg.Network.Name, VspClosed: s.cfg.VspClosed, VspClosedMsg: s.cfg.VspClosedMsg, VspdVersion: version.String(), diff --git a/internal/webapi/webapi.go b/internal/webapi/webapi.go index b057132..9e23f00 100644 --- a/internal/webapi/webapi.go +++ b/internal/webapi/webapi.go @@ -17,9 +17,9 @@ import ( "sync" "time" - "github.com/decred/dcrd/chaincfg/v3" "github.com/decred/slog" "github.com/decred/vspd/database" + "github.com/decred/vspd/internal/config" "github.com/decred/vspd/rpc" "github.com/decred/vspd/types/v2" "github.com/dustin/go-humanize" @@ -29,8 +29,7 @@ import ( type Config struct { VSPFee float64 - NetParams *chaincfg.Params - BlockExplorerURL string + Network *config.Network FeeAccountName string SupportEmail string VspClosed bool @@ -77,10 +76,10 @@ type server struct { func Start(ctx context.Context, requestShutdown func(), shutdownWg *sync.WaitGroup, 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{ - cfg: config, + cfg: cfg, db: vdb, log: log, } @@ -110,7 +109,7 @@ func Start(ctx context.Context, requestShutdown func(), shutdownWg *sync.WaitGro if err != nil { 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 { 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() + explorerURL := s.cfg.Network.BlockExplorerURL + // Add custom functions for use in templates. router.SetFuncMap(template.FuncMap{ - "txURL": txURL(s.cfg.BlockExplorerURL), - "addressURL": addressURL(s.cfg.BlockExplorerURL), - "blockURL": blockURL(s.cfg.BlockExplorerURL), + "txURL": txURL(explorerURL), + "addressURL": addressURL(explorerURL), + "blockURL": blockURL(explorerURL), "dateTime": dateTime, "stripWss": stripWss, "indentJSON": indentJSON(s.log),