├── types
├── go.mod
├── types_test.go
├── errors_test.go
├── errors.go
└── types.go
├── docs
├── img
│ └── stakey.png
├── release-notes
│ ├── release-notes.1.1.1.md
│ ├── release-notes.1.2.1.md
│ ├── release-notes.1.3.1.md
│ ├── release-notes.1.3.2.md
│ ├── release-notes.1.0.0.md
│ ├── release-notes.1.2.0.md
│ ├── release-notes.1.3.0.md
│ └── release-notes.1.4.0.md
├── two-way-accountability.md
└── listing.md
├── internal
├── webapi
│ ├── public
│ │ ├── images
│ │ │ ├── favicon
│ │ │ │ ├── favicon.ico
│ │ │ │ ├── favicon-16x16.png
│ │ │ │ ├── favicon-32x32.png
│ │ │ │ ├── mstile-70x70.png
│ │ │ │ ├── ic_launcher_hdpi.png
│ │ │ │ ├── ic_launcher_mdpi.png
│ │ │ │ ├── mstile-144x144.png
│ │ │ │ ├── mstile-150x150.png
│ │ │ │ ├── mstile-310x150.png
│ │ │ │ ├── mstile-310x310.png
│ │ │ │ ├── ic_launcher_xhdpi.png
│ │ │ │ ├── ic_launcher_xxhdpi.png
│ │ │ │ ├── ic_launcher_xxxhdpi.png
│ │ │ │ ├── apple-touch-icon-57x57.png
│ │ │ │ ├── apple-touch-icon-60x60.png
│ │ │ │ ├── apple-touch-icon-72x72.png
│ │ │ │ ├── apple-touch-icon-76x76.png
│ │ │ │ ├── apple-touch-icon-114x114.png
│ │ │ │ ├── apple-touch-icon-120x120.png
│ │ │ │ ├── apple-touch-icon-144x144.png
│ │ │ │ ├── apple-touch-icon-152x152.png
│ │ │ │ ├── apple-touch-icon-180x180.png
│ │ │ │ ├── browserconfig.xml
│ │ │ │ └── manifest.json
│ │ │ ├── success-icon.svg
│ │ │ └── error-icon.svg
│ │ └── css
│ │ │ ├── fonts
│ │ │ ├── SourceSansPro-It
│ │ │ │ ├── SourceSansPro-It.eot
│ │ │ │ ├── SourceSansPro-It.ttf
│ │ │ │ ├── SourceSansPro-It.ttf.woff
│ │ │ │ └── SourceSansPro-It.ttf.woff2
│ │ │ ├── SourceCodePro-Regular
│ │ │ │ ├── SourceCodePro-Regular.eot
│ │ │ │ ├── SourceCodePro-Regular.ttf
│ │ │ │ ├── SourceCodePro-Regular.ttf.woff
│ │ │ │ └── SourceCodePro-Regular.ttf.woff2
│ │ │ ├── SourceSansPro-Regular
│ │ │ │ ├── SourceSansPro-Regular.eot
│ │ │ │ ├── SourceSansPro-Regular.ttf
│ │ │ │ ├── SourceSansPro-Regular.ttf.woff
│ │ │ │ └── SourceSansPro-Regular.ttf.woff2
│ │ │ ├── SourceSansPro-Semibold
│ │ │ │ ├── SourceSansPro-Semibold.eot
│ │ │ │ ├── SourceSansPro-Semibold.ttf
│ │ │ │ ├── SourceSansPro-Semibold.ttf.woff
│ │ │ │ └── SourceSansPro-Semibold.ttf.woff2
│ │ │ └── SourceSansPro-SemiboldIt
│ │ │ │ ├── SourceSansPro-SemiboldIt.eot
│ │ │ │ ├── SourceSansPro-SemiboldIt.ttf
│ │ │ │ ├── SourceSansPro-SemiboldIt.ttf.woff
│ │ │ │ └── SourceSansPro-SemiboldIt.ttf.woff2
│ │ │ └── fonts.css
│ ├── homepage.go
│ ├── templates
│ │ ├── login.html
│ │ ├── footer.html
│ │ ├── vsp-stats.html
│ │ ├── homepage.html
│ │ └── header.html
│ ├── vspinfo.go
│ ├── formatting_test.go
│ ├── middleware_test.go
│ ├── ticketstatus.go
│ ├── formatting.go
│ ├── addressgenerator.go
│ ├── binding_test.go
│ ├── recovery.go
│ ├── cache.go
│ ├── setaltsignaddr.go
│ ├── helpers_test.go
│ └── helpers.go
├── signal
│ ├── signal_syscall.go
│ └── signal.go
├── config
│ ├── flags.go
│ └── network.go
├── version
│ └── version.go
└── vspd
│ ├── vspd.go
│ └── databaseintegrity.go
├── .gitignore
├── rpc
├── semver.go
├── notifs.go
└── client.go
├── LICENSE
├── .github
└── workflows
│ └── go.yml
├── cmd
├── v3tool
│ ├── README.md
│ └── dcrwallet.go
├── vote-validator
│ ├── README.md
│ ├── results.go
│ └── dcrdata.go
├── vspd
│ ├── log.go
│ └── main.go
└── vspadmin
│ └── README.md
├── client
├── go.mod
├── go.sum
└── client_test.go
├── run_tests.sh
├── .golangci.yml
├── database
├── upgrade_v4.go
├── encoding.go
├── votechange_test.go
├── upgrade_v2.go
├── encoding_test.go
├── upgrade_v5.go
├── upgrade_v3.go
├── upgrades.go
├── altsignaddr_test.go
├── feexpub_test.go
├── votechange.go
├── altsignaddr.go
├── feexpub.go
└── database_test.go
├── go.mod
├── README.md
└── harness.sh
/types/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/decred/vspd/types/v3
2 |
3 | go 1.19
4 |
--------------------------------------------------------------------------------
/docs/img/stakey.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/docs/img/stakey.png
--------------------------------------------------------------------------------
/internal/webapi/public/images/favicon/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/images/favicon/favicon.ico
--------------------------------------------------------------------------------
/internal/webapi/public/images/favicon/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/images/favicon/favicon-16x16.png
--------------------------------------------------------------------------------
/internal/webapi/public/images/favicon/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/images/favicon/favicon-32x32.png
--------------------------------------------------------------------------------
/internal/webapi/public/images/favicon/mstile-70x70.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/images/favicon/mstile-70x70.png
--------------------------------------------------------------------------------
/internal/webapi/public/images/favicon/ic_launcher_hdpi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/images/favicon/ic_launcher_hdpi.png
--------------------------------------------------------------------------------
/internal/webapi/public/images/favicon/ic_launcher_mdpi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/images/favicon/ic_launcher_mdpi.png
--------------------------------------------------------------------------------
/internal/webapi/public/images/favicon/mstile-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/images/favicon/mstile-144x144.png
--------------------------------------------------------------------------------
/internal/webapi/public/images/favicon/mstile-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/images/favicon/mstile-150x150.png
--------------------------------------------------------------------------------
/internal/webapi/public/images/favicon/mstile-310x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/images/favicon/mstile-310x150.png
--------------------------------------------------------------------------------
/internal/webapi/public/images/favicon/mstile-310x310.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/images/favicon/mstile-310x310.png
--------------------------------------------------------------------------------
/internal/webapi/public/images/favicon/ic_launcher_xhdpi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/images/favicon/ic_launcher_xhdpi.png
--------------------------------------------------------------------------------
/internal/webapi/public/images/favicon/ic_launcher_xxhdpi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/images/favicon/ic_launcher_xxhdpi.png
--------------------------------------------------------------------------------
/internal/webapi/public/images/favicon/ic_launcher_xxxhdpi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/images/favicon/ic_launcher_xxxhdpi.png
--------------------------------------------------------------------------------
/internal/webapi/public/images/favicon/apple-touch-icon-57x57.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/images/favicon/apple-touch-icon-57x57.png
--------------------------------------------------------------------------------
/internal/webapi/public/images/favicon/apple-touch-icon-60x60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/images/favicon/apple-touch-icon-60x60.png
--------------------------------------------------------------------------------
/internal/webapi/public/images/favicon/apple-touch-icon-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/images/favicon/apple-touch-icon-72x72.png
--------------------------------------------------------------------------------
/internal/webapi/public/images/favicon/apple-touch-icon-76x76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/images/favicon/apple-touch-icon-76x76.png
--------------------------------------------------------------------------------
/internal/webapi/public/images/favicon/apple-touch-icon-114x114.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/images/favicon/apple-touch-icon-114x114.png
--------------------------------------------------------------------------------
/internal/webapi/public/images/favicon/apple-touch-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/images/favicon/apple-touch-icon-120x120.png
--------------------------------------------------------------------------------
/internal/webapi/public/images/favicon/apple-touch-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/images/favicon/apple-touch-icon-144x144.png
--------------------------------------------------------------------------------
/internal/webapi/public/images/favicon/apple-touch-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/images/favicon/apple-touch-icon-152x152.png
--------------------------------------------------------------------------------
/internal/webapi/public/images/favicon/apple-touch-icon-180x180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/images/favicon/apple-touch-icon-180x180.png
--------------------------------------------------------------------------------
/internal/webapi/public/css/fonts/SourceSansPro-It/SourceSansPro-It.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/css/fonts/SourceSansPro-It/SourceSansPro-It.eot
--------------------------------------------------------------------------------
/internal/webapi/public/css/fonts/SourceSansPro-It/SourceSansPro-It.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/css/fonts/SourceSansPro-It/SourceSansPro-It.ttf
--------------------------------------------------------------------------------
/internal/webapi/public/css/fonts/SourceSansPro-It/SourceSansPro-It.ttf.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/css/fonts/SourceSansPro-It/SourceSansPro-It.ttf.woff
--------------------------------------------------------------------------------
/internal/webapi/public/css/fonts/SourceSansPro-It/SourceSansPro-It.ttf.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/css/fonts/SourceSansPro-It/SourceSansPro-It.ttf.woff2
--------------------------------------------------------------------------------
/internal/webapi/public/css/fonts/SourceCodePro-Regular/SourceCodePro-Regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/css/fonts/SourceCodePro-Regular/SourceCodePro-Regular.eot
--------------------------------------------------------------------------------
/internal/webapi/public/css/fonts/SourceCodePro-Regular/SourceCodePro-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/css/fonts/SourceCodePro-Regular/SourceCodePro-Regular.ttf
--------------------------------------------------------------------------------
/internal/webapi/public/css/fonts/SourceSansPro-Regular/SourceSansPro-Regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/css/fonts/SourceSansPro-Regular/SourceSansPro-Regular.eot
--------------------------------------------------------------------------------
/internal/webapi/public/css/fonts/SourceSansPro-Regular/SourceSansPro-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/css/fonts/SourceSansPro-Regular/SourceSansPro-Regular.ttf
--------------------------------------------------------------------------------
/internal/webapi/public/css/fonts/SourceSansPro-Semibold/SourceSansPro-Semibold.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/css/fonts/SourceSansPro-Semibold/SourceSansPro-Semibold.eot
--------------------------------------------------------------------------------
/internal/webapi/public/css/fonts/SourceSansPro-Semibold/SourceSansPro-Semibold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/css/fonts/SourceSansPro-Semibold/SourceSansPro-Semibold.ttf
--------------------------------------------------------------------------------
/internal/webapi/public/css/fonts/SourceCodePro-Regular/SourceCodePro-Regular.ttf.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/css/fonts/SourceCodePro-Regular/SourceCodePro-Regular.ttf.woff
--------------------------------------------------------------------------------
/internal/webapi/public/css/fonts/SourceSansPro-Regular/SourceSansPro-Regular.ttf.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/css/fonts/SourceSansPro-Regular/SourceSansPro-Regular.ttf.woff
--------------------------------------------------------------------------------
/internal/webapi/public/css/fonts/SourceCodePro-Regular/SourceCodePro-Regular.ttf.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/css/fonts/SourceCodePro-Regular/SourceCodePro-Regular.ttf.woff2
--------------------------------------------------------------------------------
/internal/webapi/public/css/fonts/SourceSansPro-Regular/SourceSansPro-Regular.ttf.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/css/fonts/SourceSansPro-Regular/SourceSansPro-Regular.ttf.woff2
--------------------------------------------------------------------------------
/internal/webapi/public/css/fonts/SourceSansPro-Semibold/SourceSansPro-Semibold.ttf.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/css/fonts/SourceSansPro-Semibold/SourceSansPro-Semibold.ttf.woff
--------------------------------------------------------------------------------
/internal/webapi/public/css/fonts/SourceSansPro-Semibold/SourceSansPro-Semibold.ttf.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/css/fonts/SourceSansPro-Semibold/SourceSansPro-Semibold.ttf.woff2
--------------------------------------------------------------------------------
/internal/webapi/public/css/fonts/SourceSansPro-SemiboldIt/SourceSansPro-SemiboldIt.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/css/fonts/SourceSansPro-SemiboldIt/SourceSansPro-SemiboldIt.eot
--------------------------------------------------------------------------------
/internal/webapi/public/css/fonts/SourceSansPro-SemiboldIt/SourceSansPro-SemiboldIt.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/css/fonts/SourceSansPro-SemiboldIt/SourceSansPro-SemiboldIt.ttf
--------------------------------------------------------------------------------
/internal/webapi/public/css/fonts/SourceSansPro-SemiboldIt/SourceSansPro-SemiboldIt.ttf.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/css/fonts/SourceSansPro-SemiboldIt/SourceSansPro-SemiboldIt.ttf.woff
--------------------------------------------------------------------------------
/internal/webapi/public/css/fonts/SourceSansPro-SemiboldIt/SourceSansPro-SemiboldIt.ttf.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/decred/vspd/HEAD/internal/webapi/public/css/fonts/SourceSansPro-SemiboldIt/SourceSansPro-SemiboldIt.ttf.woff2
--------------------------------------------------------------------------------
/internal/webapi/public/images/success-icon.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/internal/webapi/homepage.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020-2022 The Decred developers
2 | // Use of this source code is governed by an ISC
3 | // license that can be found in the LICENSE file.
4 |
5 | package webapi
6 |
7 | import (
8 | "net/http"
9 |
10 | "github.com/gin-gonic/gin"
11 | )
12 |
13 | func (w *WebAPI) homepage(c *gin.Context) {
14 | cacheData := c.MustGet(cacheKey).(cacheData)
15 |
16 | c.HTML(http.StatusOK, "homepage.html", gin.H{
17 | "WebApiCache": cacheData,
18 | "WebApiCfg": w.cfg,
19 | })
20 | }
21 |
--------------------------------------------------------------------------------
/docs/release-notes/release-notes.1.1.1.md:
--------------------------------------------------------------------------------
1 | # vspd 1.1.1
2 |
3 | This is a patch release of vspd which includes the following changes:
4 |
5 | - Fix assignment to nil map ([#333](https://github.com/decred/vspd/pull/333)).
6 |
7 | ## Dependencies
8 |
9 | vspd 1.1.1 must be built with go 1.16 or later, and requires:
10 |
11 | - dcrd 1.7.1
12 | - dcrwallet 1.7.1
13 |
14 | When deploying vspd to production, always use release versions of all binaries.
15 | Neither vspd nor its dependencies should be built from master when handling
16 | mainnet tickets.
17 |
--------------------------------------------------------------------------------
/internal/signal/signal_syscall.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 The btcsuite developers
2 | // Copyright (c) 2021-2023 The Decred developers
3 | // Use of this source code is governed by an ISC
4 | // license that can be found in the LICENSE file.
5 |
6 | //go:build windows || aix || android || darwin || dragonfly || freebsd || hurd || illumos || ios || linux || netbsd || openbsd || solaris
7 |
8 | package signal
9 |
10 | import (
11 | "syscall"
12 | )
13 |
14 | func init() {
15 | interruptSignals = append(interruptSignals, syscall.SIGTERM, syscall.SIGHUP)
16 | }
17 |
--------------------------------------------------------------------------------
/docs/release-notes/release-notes.1.2.1.md:
--------------------------------------------------------------------------------
1 | # vspd 1.2.1
2 |
3 | This is a patch release of vspd which includes the following changes:
4 |
5 | - rpc: Ignore another "duplicate tx" error ([#398](https://github.com/decred/vspd/pull/398)).
6 |
7 | ## Dependencies
8 |
9 | vspd 1.2.1 must be built with go 1.19 or later, and requires:
10 |
11 | - dcrd 1.8.0
12 | - dcrwallet 1.8.0
13 |
14 | When deploying vspd to production, always use release versions of all binaries.
15 | Neither vspd nor its dependencies should be built from master when handling
16 | mainnet tickets.
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Executables built by this repo.
2 | /cmd/vspd/vspd.exe
3 | /cmd/vspd/vspd
4 | /vspd.exe
5 | /vspd
6 |
7 | /cmd/vote-validator/vote-validator.exe
8 | /cmd/vote-validator/vote-validator
9 | /vote-validator.exe
10 | /vote-validator
11 |
12 | /cmd/v3tool/v3tool.exe
13 | /cmd/v3tool/v3tool
14 | /v3tool.exe
15 | /v3tool
16 |
17 | vote-validator.log
18 |
19 | # Harness dir.
20 | vspd-harness/
21 |
22 | # Testing, profiling, and benchmarking artifacts
23 | cov.out
24 | *cpu.out
25 | *mem.out
26 | internal/webapi/test.db
27 | database/test.db
28 |
29 | # Go workspace
30 | go.work
31 | go.work.sum
32 |
--------------------------------------------------------------------------------
/internal/webapi/templates/login.html:
--------------------------------------------------------------------------------
1 | {{ template "header" . }}
2 |
3 |
15 |
16 | {{ template "footer" . }}
17 |
--------------------------------------------------------------------------------
/internal/webapi/public/images/favicon/browserconfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | #091440
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/docs/release-notes/release-notes.1.3.1.md:
--------------------------------------------------------------------------------
1 | # vspd 1.3.1
2 |
3 | This is a patch release of vspd which includes the following changes:
4 |
5 | - webapi: Add missed tickets to admin page ([#451](https://github.com/decred/vspd/pull/451)).
6 |
7 | Please read the [vspd 1.3.0 release notes](https://github.com/decred/vspd/releases/tag/release-v1.3.0)
8 | for a full list of changes since vspd 1.2.
9 |
10 | ## Dependencies
11 |
12 | vspd 1.3.1 must be built with go 1.20 or later, and requires:
13 |
14 | - dcrd 1.8.0
15 | - dcrwallet 1.8.0
16 |
17 | When deploying vspd to production, always use release versions of all binaries.
18 | Neither vspd nor its dependencies should be built from master when handling
19 | mainnet tickets.
20 |
--------------------------------------------------------------------------------
/internal/config/flags.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2024-2025 The Decred developers
2 | // Use of this source code is governed by an ISC
3 | // license that can be found in the LICENSE file.
4 |
5 | package config
6 |
7 | import (
8 | "github.com/jessevdk/go-flags"
9 | )
10 |
11 | // WriteHelp will write the application help to stdout if it has been requested
12 | // via command line options. Only the help option is evaluated, any invalid
13 | // options are ignored. The return value indicates whether the help message was
14 | // printed or not.
15 | func WriteHelp(cfg any) bool {
16 | helpOpts := flags.Options(flags.HelpFlag | flags.PrintErrors | flags.IgnoreUnknown)
17 | _, err := flags.NewParser(cfg, helpOpts).Parse()
18 | return flags.WroteHelp(err)
19 | }
20 |
--------------------------------------------------------------------------------
/rpc/semver.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020 The Decred developers
2 | // Use of this source code is governed by an ISC
3 | // license that can be found in the LICENSE file.
4 |
5 | package rpc
6 |
7 | import "fmt"
8 |
9 | type semver struct {
10 | Major uint32
11 | Minor uint32
12 | Patch uint32
13 | }
14 |
15 | func semverCompatible(required, actual semver) bool {
16 | switch {
17 | case required.Major != actual.Major:
18 | return false
19 | case required.Minor > actual.Minor:
20 | return false
21 | case required.Minor == actual.Minor && required.Patch > actual.Patch:
22 | return false
23 | default:
24 | return true
25 | }
26 | }
27 |
28 | func (s semver) String() string {
29 | return fmt.Sprintf("%d.%d.%d", s.Major, s.Minor, s.Patch)
30 | }
31 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | ISC License
2 |
3 | Copyright (c) 2020-2024 The Decred developers
4 |
5 | Permission to use, copy, modify, and distribute this software for any
6 | purpose with or without fee is hereby granted, provided that the above
7 | copyright notice and this permission notice appear in all copies.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
--------------------------------------------------------------------------------
/docs/release-notes/release-notes.1.3.2.md:
--------------------------------------------------------------------------------
1 | # vspd 1.3.2
2 |
3 | This is a patch release of vspd which includes the following changes:
4 |
5 | - Downgrade dcrwallet dep to v3 ([#454](https://github.com/decred/vspd/pull/454)).
6 | - webapi: Wait for unknown outputs to propagate ([#455](https://github.com/decred/vspd/pull/455)).
7 |
8 | Please read the [vspd 1.3.0 release notes](https://github.com/decred/vspd/releases/tag/release-v1.3.0)
9 | for a full list of changes since vspd 1.2.
10 |
11 | ## Dependencies
12 |
13 | vspd 1.3.2 must be built with go 1.20 or later, and requires:
14 |
15 | - dcrd 1.8.0
16 | - dcrwallet 1.8.0
17 |
18 | When deploying vspd to production, always use release versions of all binaries.
19 | Neither vspd nor its dependencies should be built from master when handling
20 | mainnet tickets.
21 |
--------------------------------------------------------------------------------
/.github/workflows/go.yml:
--------------------------------------------------------------------------------
1 | name: Build and Test
2 | on: [push, pull_request]
3 | jobs:
4 | build:
5 | name: Go CI
6 | runs-on: ubuntu-latest
7 | strategy:
8 | matrix:
9 | go: ["1.24", "1.25"]
10 | steps:
11 | - name: Set up Go
12 | uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c #v6.1.0
13 | with:
14 | go-version: ${{ matrix.go }}
15 | - name: Check out source
16 | uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 #v6.0.0
17 | - name: Build
18 | run: go build ./...
19 | - name: Install Linters
20 | run: "curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.6.2"
21 | - name: Test and Lint
22 | run: ./run_tests.sh
23 |
--------------------------------------------------------------------------------
/cmd/v3tool/README.md:
--------------------------------------------------------------------------------
1 | # v3tool
2 |
3 | v3tool is a simple client for manual testing of vspd.
4 | It is a developer tool, not suitable for end users or production use.
5 |
6 | ## Prerequisites
7 |
8 | 1. An instance of dcrwallet which owns at least one mempool, immature or live ticket.
9 | 1. An instance of vspd to test.
10 |
11 | ## What v3tool does
12 |
13 | 1. Retrieve the pubkey from vspd.
14 | 1. Retrieve the list of owned mempool/immature/live tickets from dcrwallet.
15 | 1. For each ticket:
16 | 1. Use dcrwallet to find the tx hex, voting privkey and commitment address of the ticket.
17 | 1. Get a fee address and amount from vspd to register this ticket.
18 | 1. Create the fee tx and send it to vspd.
19 | 1. Get the ticket status.
20 | 1. Change vote choices on the ticket.
21 | 1. Get the ticket status again.
22 |
--------------------------------------------------------------------------------
/cmd/vote-validator/README.md:
--------------------------------------------------------------------------------
1 | # vote-validator
2 |
3 | vote-validator is a tool for VSP admins to verify that their vspd deployment
4 | is voting correctly according to user preferences.
5 |
6 | ## What it does
7 |
8 | 1. Retrieve all voted tickets from the provided vspd database file.
9 | 1. Retrieve vote info from dcrdata for every voted ticket.
10 | 1. For the n most recently voted tickets, compare the vote choices recorded
11 | on-chain to the vote choices set by the user.
12 | 1. Write details of any discrepancies to a file for further investigation.
13 |
14 | ## How to run it
15 |
16 | Only run vote-validator using a copy of the vspd database backup file.
17 | Never use a real production database.
18 |
19 | vote-validator can be run from the repository root as such:
20 |
21 | ```no-highlight
22 | go run ./cmd/vote-validator -n 1000 -f ./vspd.db-backup
23 | ```
24 |
--------------------------------------------------------------------------------
/client/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/decred/vspd/client/v4
2 |
3 | go 1.19
4 |
5 | require (
6 | github.com/decred/dcrd/txscript/v4 v4.1.1
7 | github.com/decred/slog v1.2.0
8 | github.com/decred/vspd/types/v3 v3.0.0
9 | )
10 |
11 | require (
12 | github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 // indirect
13 | github.com/dchest/siphash v1.2.3 // indirect
14 | github.com/decred/base58 v1.0.5 // indirect
15 | github.com/decred/dcrd/chaincfg/chainhash v1.0.4 // indirect
16 | github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect
17 | github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect
18 | github.com/decred/dcrd/dcrec v1.0.1 // indirect
19 | github.com/decred/dcrd/dcrec/edwards/v2 v2.0.3 // indirect
20 | github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
21 | github.com/decred/dcrd/wire v1.7.0 // indirect
22 | github.com/klauspost/cpuid/v2 v2.2.8 // indirect
23 | golang.org/x/sys v0.22.0 // indirect
24 | lukechampine.com/blake3 v1.3.0 // indirect
25 | )
26 |
--------------------------------------------------------------------------------
/run_tests.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # Copyright (c) 2020-2024 The Decred developers
4 | # Use of this source code is governed by an ISC
5 | # license that can be found in the LICENSE file.
6 | #
7 | # Usage:
8 | # ./run_tests.sh
9 |
10 | set -e
11 |
12 | go version
13 |
14 | # This list needs to be updated if new submodules are added to the vspd repo.
15 | submodules="client types"
16 |
17 | # Test main module.
18 | echo "==> test main module"
19 | GORACE="halt_on_error=1" go test -race ./...
20 |
21 | # Test all submodules in a subshell.
22 | for module in $submodules
23 | do
24 | echo "==> test ${module}"
25 | (
26 | cd $module
27 | GORACE="halt_on_error=1" go test -race .
28 | )
29 | done
30 |
31 | # Lint main module.
32 | echo "==> lint main module"
33 | golangci-lint run
34 |
35 | # Lint all submodules in a subshell.
36 | for module in $submodules
37 | do
38 | echo "==> lint ${module}"
39 | (
40 | cd $module
41 | golangci-lint run
42 | )
43 | done
44 |
45 | echo "-----------------------------"
46 | echo "Tests completed successfully!"
47 |
--------------------------------------------------------------------------------
/.golangci.yml:
--------------------------------------------------------------------------------
1 | version: "2"
2 | run:
3 | timeout: 10m
4 | linters:
5 | default: none
6 | enable:
7 | - asciicheck
8 | - bidichk
9 | - containedctx
10 | - copyloopvar
11 | - dupword
12 | - durationcheck
13 | - errcheck
14 | - errchkjson
15 | - errorlint
16 | - exhaustive
17 | - fatcontext
18 | - goconst
19 | - godot
20 | - govet
21 | - ineffassign
22 | - makezero
23 | - mirror
24 | - misspell
25 | - nilerr
26 | - nilnil
27 | - nosprintfhostport
28 | - prealloc
29 | - predeclared
30 | - reassign
31 | - revive
32 | - staticcheck
33 | - tparallel
34 | - unconvert
35 | - unparam
36 | - unused
37 | - usestdlibvars
38 | - usetesting
39 | exclusions:
40 | presets:
41 | - comments
42 | - std-error-handling
43 | rules:
44 | # Ignore revive linter complaining about the name of the "types" package.
45 | - path: types/*
46 | text: 'var-naming: avoid meaningless package names'
47 | formatters:
48 | enable:
49 | - gofmt
50 | - goimports
51 |
--------------------------------------------------------------------------------
/internal/webapi/public/images/favicon/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Decred",
3 | "short_name": "Decred",
4 | "icons": [
5 | {
6 | "src": "/public/images/favicon/ic_launcher_mdpi.png?v=gT6Mc",
7 | "sizes": "48x48",
8 | "type": "image/png"
9 | },
10 | {
11 | "src": "/public/images/favicon/ic_launcher_hdpi.png?v=gT6Mc",
12 | "sizes": "72x72",
13 | "type": "image/png"
14 | },
15 | {
16 | "src": "/public/images/favicon/ic_launcher_xhdpi.png?v=gT6Mc",
17 | "sizes": "96x96",
18 | "type": "image/png"
19 | },
20 | {
21 | "src": "/public/images/favicon/ic_launcher_xxhdpi.png?v=gT6Mc",
22 | "sizes": "144x144",
23 | "type": "image/png"
24 | },
25 | {
26 | "src": "/public/images/favicon/ic_launcher_xxxhdpi.png?v=gT6Mc",
27 | "sizes": "192x192",
28 | "type": "image/png"
29 | }
30 | ],
31 | "theme_color": "#091440",
32 | "background_color": "#091440",
33 | "start_url": "/",
34 | "display": "browser"
35 | }
36 |
--------------------------------------------------------------------------------
/database/upgrade_v4.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021-2022 The Decred developers
2 | // Use of this source code is governed by an ISC
3 | // license that can be found in the LICENSE file.
4 |
5 | package database
6 |
7 | import (
8 | "fmt"
9 |
10 | "github.com/decred/slog"
11 | bolt "go.etcd.io/bbolt"
12 | )
13 |
14 | func altSignAddrUpgrade(db *bolt.DB, log slog.Logger) error {
15 | log.Infof("Upgrading database to version %d", altSignAddrVersion)
16 |
17 | // Run the upgrade in a single database transaction so it can be safely
18 | // rolled back if an error is encountered.
19 | err := db.Update(func(tx *bolt.Tx) error {
20 | vspBkt := tx.Bucket(vspBktK)
21 |
22 | // Create alt sign addr bucket.
23 | _, err := vspBkt.CreateBucket(altSignAddrBktK)
24 | if err != nil {
25 | return fmt.Errorf("failed to create %s bucket: %w", altSignAddrBktK, err)
26 | }
27 |
28 | // Update database version.
29 | err = vspBkt.Put(versionK, uint32ToBytes(altSignAddrVersion))
30 | if err != nil {
31 | return fmt.Errorf("failed to update db version: %w", err)
32 | }
33 |
34 | return nil
35 | })
36 | if err != nil {
37 | return err
38 | }
39 |
40 | log.Info("Upgrade completed")
41 | return nil
42 | }
43 |
--------------------------------------------------------------------------------
/cmd/vspd/log.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020-2022 The Decred developers
2 | // Use of this source code is governed by an ISC
3 | // license that can be found in the LICENSE file.
4 |
5 | package main
6 |
7 | import (
8 | "fmt"
9 | "os"
10 | "path/filepath"
11 |
12 | "github.com/decred/slog"
13 | "github.com/jrick/logrotate/rotator"
14 | )
15 |
16 | // logWriter implements an io.Writer that outputs to both standard output and
17 | // the write-end pipe of an initialized log rotator.
18 | type logWriter struct {
19 | rotator *rotator.Rotator
20 | }
21 |
22 | func (lw logWriter) Write(p []byte) (n int, err error) {
23 | os.Stdout.Write(p)
24 | return lw.rotator.Write(p)
25 | }
26 |
27 | func newLogBackend(logDir string, appName string, maxLogSize int64, logsToKeep int) (*slog.Backend, error) {
28 | err := os.MkdirAll(logDir, 0700)
29 | if err != nil {
30 | return nil, fmt.Errorf("failed to create log directory: %w", err)
31 | }
32 |
33 | logFileName := fmt.Sprintf("%s.log", appName)
34 | logFilePath := filepath.Join(logDir, logFileName)
35 |
36 | r, err := rotator.New(logFilePath, maxLogSize*1024, false, logsToKeep)
37 | if err != nil {
38 | return nil, fmt.Errorf("failed to create log rotator: %w", err)
39 | }
40 |
41 | return slog.NewBackend(logWriter{r}), nil
42 | }
43 |
--------------------------------------------------------------------------------
/internal/webapi/vspinfo.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020-2024 The Decred developers
2 | // Use of this source code is governed by an ISC
3 | // license that can be found in the LICENSE file.
4 |
5 | package webapi
6 |
7 | import (
8 | "time"
9 |
10 | "github.com/decred/vspd/internal/version"
11 | "github.com/decred/vspd/types/v3"
12 | "github.com/gin-gonic/gin"
13 | )
14 |
15 | // vspInfo is the handler for "GET /api/v3/vspinfo".
16 | func (w *WebAPI) vspInfo(c *gin.Context) {
17 | cachedStats := c.MustGet(cacheKey).(cacheData)
18 |
19 | w.sendJSONResponse(types.VspInfoResponse{
20 | APIVersions: []int64{3},
21 | Timestamp: time.Now().Unix(),
22 | PubKey: w.signPubKey,
23 | FeePercentage: w.cfg.VSPFee,
24 | Network: w.cfg.Network.Name,
25 | VspClosed: w.cfg.VspClosed,
26 | VspClosedMsg: w.cfg.VspClosedMsg,
27 | VspdVersion: version.String(),
28 | Voting: cachedStats.Voting,
29 | Voted: cachedStats.Voted,
30 | TotalVotingWallets: cachedStats.TotalVotingWallets,
31 | VotingWalletsOnline: cachedStats.VotingWalletsOnline,
32 | Expired: cachedStats.Expired,
33 | Missed: cachedStats.Missed,
34 | BlockHeight: cachedStats.BlockHeight,
35 | NetworkProportion: cachedStats.NetworkProportion,
36 | }, c)
37 | }
38 |
--------------------------------------------------------------------------------
/cmd/vspadmin/README.md:
--------------------------------------------------------------------------------
1 | # vspadmin
2 |
3 | vspadmin is a tool to perform various VSP administration tasks.
4 |
5 | ## Usage
6 |
7 | ```no-highlight
8 | vspadmin [OPTIONS] COMMAND
9 | ```
10 |
11 | ## Options
12 |
13 | ```no-highlight
14 | --homedir= Path to application home directory. (default: /home/user/.vspd)
15 | --network=[mainnet|testnet|simnet] Decred network to use. (default: mainnet)
16 | -h, --help Show help message
17 | ```
18 |
19 | ## Commands
20 |
21 | ### `createdatabase`
22 |
23 | Creates a new database for a new deployment of vspd. Accepts the xpub key to be
24 | used for collecting fees as a parameter.
25 |
26 | Example:
27 |
28 | ```no-highlight
29 | $ go run ./cmd/vspadmin createdatabase
30 | ```
31 |
32 | ### `writeconfig`
33 |
34 | Writes a config file with default values to the application home directory.
35 |
36 | Example:
37 |
38 | ```no-highlight
39 | $ go run ./cmd/vspadmin writeconfig
40 | ```
41 |
42 | ### `retirexpub`
43 |
44 | Replaces the currently used xpub with a new one. Once an xpub key has been
45 | retired it can not be used by the VSP again.
46 |
47 | **Note:** vspd must be stopped before this command can be used because it
48 | modifies values in the vspd database.
49 |
50 | Example:
51 |
52 | ```no-highlight
53 | $ go run ./cmd/vspadmin retirexpub
54 | ```
55 |
--------------------------------------------------------------------------------
/docs/release-notes/release-notes.1.0.0.md:
--------------------------------------------------------------------------------
1 | # vspd 1.0.0
2 |
3 | This is the initial release of vspd which is intended to replace
4 | [dcrstakepool](https://github.com/decred/dcrstakepool) as the reference
5 | implementation of a Decred Voting Service Provider.
6 |
7 | The [Decred blog](https://blog.decred.org/2020/06/02/A-More-Private-Way-to-Stake/)
8 | explains the motivation for creating vspd to replace dcrstakepool.
9 |
10 | ## Dependencies
11 |
12 | vspd 1.0.0 requires:
13 |
14 | - dcrd 1.6.0
15 | - dcrwallet 1.6.0
16 |
17 | When deploying vspd to production, always use release versions of all binaries.
18 | Neither vspd nor its dependencies should be built from master when handling
19 | mainnet tickets.
20 |
21 | ## New features
22 |
23 | The key features offered by this initial version are:
24 |
25 | - HTTP API
26 | - Endpoints to allows VSP users to register their tickets with the VSP, and to
27 | check on the status of registered tickets.
28 | - A status endpoint allows VSP operators to remotely monitor vspd.
29 |
30 | - Web front-end
31 | - A public home page displays various VSP statistics.
32 | - A hidden admin page allows VSP operators to search for registered tickets
33 | and download database backups.
34 |
35 | Please review the [project README](https://github.com/decred/vspd) for extended
36 | documentation, including how to use the API and a detailed deployment guide.
37 |
--------------------------------------------------------------------------------
/internal/webapi/formatting_test.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2023-2024 The Decred developers
2 | // Use of this source code is governed by an ISC
3 | // license that can be found in the LICENSE file.
4 |
5 | package webapi
6 |
7 | import (
8 | "testing"
9 |
10 | "github.com/decred/slog"
11 | )
12 |
13 | func TestIndentJSON(t *testing.T) {
14 | t.Parallel()
15 |
16 | // Get the actual invokable func by passing a noop logger.
17 | indentJSONFunc := indentJSON(slog.Disabled)
18 |
19 | tests := map[string]struct {
20 | input string
21 | expected string
22 | }{
23 | "nothing": {
24 | input: "",
25 | expected: "",
26 | },
27 | "empty": {
28 | input: "{}",
29 | expected: "{}",
30 | },
31 | "one line JSON": {
32 | input: "{\"key\":\"value\"}",
33 | expected: "{\n \"key\": \"value\"\n}",
34 | },
35 | "nested JSON": {
36 | input: "{\"key\":{\"key2\":\"value\"}}",
37 | expected: "{\n \"key\": {\n \"key2\": \"value\"\n }\n}",
38 | },
39 | "invalid JSON": {
40 | input: "this is not valid json",
41 | expected: "this is not valid json",
42 | },
43 | }
44 |
45 | for testName, test := range tests {
46 | t.Run(testName, func(t *testing.T) {
47 | t.Parallel()
48 | actual := indentJSONFunc(test.input)
49 | if actual != test.expected {
50 | t.Fatalf("expected %q, got %q", test.expected, actual)
51 | }
52 | })
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/internal/signal/signal.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2013-2014 The btcsuite developers
2 | // Copyright (c) 2021-2023 The Decred developers
3 | // Use of this source code is governed by an ISC
4 | // license that can be found in the LICENSE file.
5 |
6 | package signal
7 |
8 | import (
9 | "context"
10 | "os"
11 | "os/signal"
12 |
13 | "github.com/decred/slog"
14 | )
15 |
16 | // interruptSignals defines the default signals to catch in order to do a proper
17 | // shutdown. This may be modified during init depending on the platform.
18 | var interruptSignals = []os.Signal{os.Interrupt}
19 |
20 | // ShutdownListener listens for OS Signals such as SIGINT (Ctrl+C) and shutdown
21 | // requests from requestShutdown. It returns a context that is canceled when
22 | // either signal is received.
23 | func ShutdownListener(log slog.Logger) context.Context {
24 | ctx, cancel := context.WithCancel(context.Background())
25 | go func() {
26 | interruptChannel := make(chan os.Signal, 1)
27 | signal.Notify(interruptChannel, interruptSignals...)
28 |
29 | // Listen for the initial shutdown signal.
30 | sig := <-interruptChannel
31 | log.Infof("Received signal (%s). Shutting down...", sig)
32 |
33 | cancel()
34 |
35 | // Listen for any more shutdown request and display a message so the
36 | // user knows the shutdown is in progress and the process is not hung.
37 | for {
38 | sig := <-interruptChannel
39 | log.Infof("Received signal (%s). Already shutting down...", sig)
40 | }
41 | }()
42 | return ctx
43 | }
44 |
--------------------------------------------------------------------------------
/internal/webapi/templates/footer.html:
--------------------------------------------------------------------------------
1 | {{ define "footer" }}
2 |
3 |
4 |
5 |
35 |
36 |