diff --git a/background/background.go b/background/background.go index 5178dfd6..4f04a9be 100644 --- a/background/background.go +++ b/background/background.go @@ -207,7 +207,7 @@ func blockConnected() { continue } - // Update vote choices on voting wallets. + // Set vote choices on voting wallets. for agenda, choice := range ticket.VoteChoices { err = walletClient.SetVoteChoice(agenda, choice, ticket.Hash) if err != nil { diff --git a/database/database.go b/database/database.go index 77779a3d..63b55118 100644 --- a/database/database.go +++ b/database/database.go @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Decred developers +// Copyright (c) 2020-2021 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -120,7 +120,6 @@ func CreateNew(dbFile, feeXPub string) error { defer db.Close() - // Create all storage buckets of the VSP if they don't already exist. err = db.Update(func(tx *bolt.Tx) error { // Create parent bucket. vspBkt, err := tx.CreateBucket(vspBktK) diff --git a/database/ticket.go b/database/ticket.go index 0354455e..ab54e491 100644 --- a/database/ticket.go +++ b/database/ticket.go @@ -210,14 +210,12 @@ func getTicketFromBkt(bkt *bolt.Bucket) (Ticket, error) { ticket.Confirmed = true } - voteChoices := make(map[string]string) - err := json.Unmarshal(bkt.Get(voteChoicesK), &voteChoices) + ticket.VoteChoices = make(map[string]string) + err := json.Unmarshal(bkt.Get(voteChoicesK), &ticket.VoteChoices) if err != nil { return ticket, err } - ticket.VoteChoices = voteChoices - return ticket, nil } diff --git a/database/upgrade_v2.go b/database/upgrade_v2.go index 2b3d7818..e5ecc499 100644 --- a/database/upgrade_v2.go +++ b/database/upgrade_v2.go @@ -1,3 +1,7 @@ +// Copyright (c) 2021 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + package database import ( diff --git a/database/upgrade_v3.go b/database/upgrade_v3.go index 8f69c28b..2d81dc24 100644 --- a/database/upgrade_v3.go +++ b/database/upgrade_v3.go @@ -1,3 +1,7 @@ +// Copyright (c) 2021 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + package database import ( diff --git a/database/upgrades.go b/database/upgrades.go index 97853bb4..29a46662 100644 --- a/database/upgrades.go +++ b/database/upgrades.go @@ -1,3 +1,7 @@ +// Copyright (c) 2021 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + package database import ( diff --git a/database/votechange.go b/database/votechange.go index 1ffa697b..118c2a58 100644 --- a/database/votechange.go +++ b/database/votechange.go @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Decred developers +// Copyright (c) 2020-2021 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -39,16 +39,16 @@ func (vdb *VspDatabase) SaveVoteChange(ticketHash string, record VoteChangeRecor // Loop through the bucket to count the records, as well as finding the // most recent and the oldest record. var count int - highest := uint32(0) - lowest := uint32(math.MaxUint32) + newest := uint32(0) + oldest := uint32(math.MaxUint32) err = bkt.ForEach(func(k, v []byte) error { count++ key := bytesToUint32(k) - if key > highest { - highest = key + if key > newest { + newest = key } - if key < lowest { - lowest = key + if key < oldest { + oldest = key } return nil }) @@ -59,7 +59,7 @@ func (vdb *VspDatabase) SaveVoteChange(ticketHash string, record VoteChangeRecor // If bucket is at (or over) the limit of max allowed records, remove // the oldest one. if count >= vdb.maxVoteChangeRecords { - err = bkt.Delete(uint32ToBytes(lowest)) + err = bkt.Delete(uint32ToBytes(oldest)) if err != nil { return fmt.Errorf("failed to delete old vote change record: %w", err) } @@ -69,7 +69,7 @@ func (vdb *VspDatabase) SaveVoteChange(ticketHash string, record VoteChangeRecor // otherwise use most recent + 1. var newKey uint32 if count > 0 { - newKey = highest + 1 + newKey = newest + 1 } // Insert record. diff --git a/webapi/getfeeaddress.go b/webapi/getfeeaddress.go index ceefff0a..8d794d40 100644 --- a/webapi/getfeeaddress.go +++ b/webapi/getfeeaddress.go @@ -19,10 +19,10 @@ import ( // addrMtx protects getNewFeeAddress. var addrMtx sync.Mutex -// getNewFeeAddress gets a new address from the address generator and stores the -// new address index in the database. In order to maintain consistency between -// the internal counter of address generator and the database, this function -// cannot be run concurrently. +// getNewFeeAddress gets a new address from the address generator, and updates +// the last used address index in the database. In order to maintain consistency +// between the internal counter of address generator and the database, this func +// uses a mutex to ensure it is not run concurrently. func getNewFeeAddress(db *database.VspDatabase, addrGen *addressGenerator) (string, uint32, error) { addrMtx.Lock() defer addrMtx.Unlock() diff --git a/webapi/helpers.go b/webapi/helpers.go index 796a222d..201f9548 100644 --- a/webapi/helpers.go +++ b/webapi/helpers.go @@ -26,9 +26,9 @@ func currentVoteVersion(params *chaincfg.Params) uint32 { return latestVersion } -// isValidVoteChoices returns an error if provided vote choices are not valid for -// the most recent agendas. -func isValidVoteChoices(params *chaincfg.Params, voteVersion uint32, voteChoices map[string]string) error { +// 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 { agendaLoop: for agenda, choice := range voteChoices { diff --git a/webapi/helpers_test.go b/webapi/helpers_test.go index de7c22b9..97971db8 100644 --- a/webapi/helpers_test.go +++ b/webapi/helpers_test.go @@ -46,7 +46,7 @@ func TestIsValidVoteChoices(t *testing.T) { } for _, test := range tests { - err := isValidVoteChoices(params, voteVersion, test.voteChoices) + err := validConsensusVoteChoices(params, voteVersion, test.voteChoices) if (err == nil) != test.valid { t.Fatalf("isValidVoteChoices failed for votechoices '%v'.", test.voteChoices) } diff --git a/webapi/payfee.go b/webapi/payfee.go index 50d857b9..9a6a7432 100644 --- a/webapi/payfee.go +++ b/webapi/payfee.go @@ -104,7 +104,7 @@ func payFee(c *gin.Context) { // Validate VoteChoices. Just log a warning if vote choices are not valid // for the current vote version - the ticket should still be registered. validVoteChoices := true - err = isValidVoteChoices(cfg.NetParams, currentVoteVersion(cfg.NetParams), request.VoteChoices) + err = validConsensusVoteChoices(cfg.NetParams, currentVoteVersion(cfg.NetParams), request.VoteChoices) if err != nil { validVoteChoices = false log.Warnf("%s: Invalid vote choices (clientIP=%s, ticketHash=%s): %v", diff --git a/webapi/setvotechoices.go b/webapi/setvotechoices.go index 347789cd..7c566169 100644 --- a/webapi/setvotechoices.go +++ b/webapi/setvotechoices.go @@ -15,10 +15,6 @@ import ( "github.com/gin-gonic/gin/binding" ) -type timestampRequest struct { - Timestamp int64 `json:"timestamp" binding:"required"` -} - // setVoteChoices is the handler for "POST /api/v3/setvotechoices". func setVoteChoices(c *gin.Context) { const funcName = "setVoteChoices" @@ -76,7 +72,9 @@ func setVoteChoices(c *gin.Context) { } for _, change := range previousChanges { - var prevReq timestampRequest + var prevReq struct { + Timestamp int64 `json:"timestamp" binding:"required"` + } err := json.Unmarshal([]byte(change.Request), &prevReq) if err != nil { log.Errorf("%s: Could not unmarshal vote change record (ticketHash=%s): %v", @@ -95,7 +93,7 @@ func setVoteChoices(c *gin.Context) { } voteChoices := request.VoteChoices - err = isValidVoteChoices(cfg.NetParams, currentVoteVersion(cfg.NetParams), voteChoices) + err = validConsensusVoteChoices(cfg.NetParams, currentVoteVersion(cfg.NetParams), voteChoices) if err != nil { log.Warnf("%s: Invalid vote choices (clientIP=%s, ticketHash=%s): %v", funcName, c.ClientIP(), ticket.Hash, err) @@ -103,8 +101,8 @@ func setVoteChoices(c *gin.Context) { return } - // Update VoteChoices in the database before updating the wallets. DB is - // source of truth and is less likely to error. + // Update VoteChoices in the database before updating the wallets. DB is the + // source of truth, and also is less likely to error. ticket.VoteChoices = voteChoices err = db.UpdateTicket(ticket) if err != nil { @@ -117,8 +115,8 @@ func setVoteChoices(c *gin.Context) { // Update vote choices on voting wallets. Tickets are only added to voting // wallets if their fee is confirmed. if ticket.FeeTxStatus == database.FeeConfirmed { - for agenda, choice := range voteChoices { - for _, walletClient := range walletClients { + for _, walletClient := range walletClients { + for agenda, choice := range voteChoices { err = walletClient.SetVoteChoice(agenda, choice, ticket.Hash) if err != nil { // If this fails, we still want to try the other wallets, so