Clarify "setaltsig" terminology.

Stardardize "alt sig"/"alt signature"/"alt signing address" terminology to "alternate signing address".
This commit is contained in:
jholdstock 2021-11-14 12:50:31 +00:00 committed by Jamie Holdstock
parent b1a68a94fe
commit ab5aa4dd6d
17 changed files with 355 additions and 350 deletions

View File

@ -103,11 +103,11 @@ func blockConnected() {
funcName, ticket.Hash, err)
}
// This will not error if an alternate signature does not
// This will not error if an alternate signing address does not
// exist for ticket.
err = db.DeleteAltSig(ticket.Hash)
err = db.DeleteAltSignAddr(ticket.Hash)
if err != nil {
log.Errorf("%s: db.DeleteAltSig error (ticketHash=%s): %v",
log.Errorf("%s: db.DeleteAltSignAddr error (ticketHash=%s): %v",
funcName, ticket.Hash, err)
}
} else {

View File

@ -1,124 +0,0 @@
// 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.
package database
import (
"errors"
"fmt"
bolt "go.etcd.io/bbolt"
)
// The keys used to store the altsig in the database.
var (
altSigAddrK = []byte("altsig")
reqK = []byte("req")
reqSigK = []byte("reqsig")
resK = []byte("res")
resSigK = []byte("ressig")
)
// AltSigData holds the information needed to prove that a client added an
// alternate signature address.
type AltSigData struct {
// AltSigAddr is the new alternate signature address. It is base 58
// encoded.
AltSigAddr string
// Req is the original request to set an alternate signature.
Req []byte
// ReqSig is the request's signature signed by the private key that
// corresponds to the address. It is base 64 encoded.
ReqSig string
// Res is the original response from the server to the alternate
// signature address.
Res []byte
// ResSig is the response's signature signed by the server. It is base
// 64 encoded.
ResSig string
}
// InsertAltSig will insert the provided ticket into the database. Returns an
// error if data for the ticket hash already exist.
//
// Passed data must have no empty fields.
func (vdb *VspDatabase) InsertAltSig(ticketHash string, data *AltSigData) error {
if data == nil {
return errors.New("alt sig data must not be nil for inserts")
}
if data.AltSigAddr == "" || len(data.Req) == 0 || data.ReqSig == "" ||
len(data.Res) == 0 || data.ResSig == "" {
return errors.New("alt sig data has empty parameters")
}
return vdb.db.Update(func(tx *bolt.Tx) error {
altSigBkt := tx.Bucket(vspBktK).Bucket(altSigBktK)
// Create a bucket for the new altsig. Returns an error if bucket
// already exists.
bkt, err := altSigBkt.CreateBucket([]byte(ticketHash))
if err != nil {
return fmt.Errorf("could not create bucket for altsig: %w", err)
}
if err := bkt.Put(altSigAddrK, []byte(data.AltSigAddr)); err != nil {
return err
}
if err := bkt.Put(reqK, data.Req); err != nil {
return err
}
if err := bkt.Put(reqSigK, []byte(data.ReqSig)); err != nil {
return err
}
if err := bkt.Put(resK, data.Res); err != nil {
return err
}
return bkt.Put(resSigK, []byte(data.ResSig))
})
}
// DeleteAltSig deletes an altsig from the database. Does not error if there is
// no altsig in the database.
func (vdb *VspDatabase) DeleteAltSig(ticketHash string) error {
return vdb.db.Update(func(tx *bolt.Tx) error {
altSigBkt := tx.Bucket(vspBktK).Bucket(altSigBktK)
// Don't attempt delete if doesn't exist.
bkt := altSigBkt.Bucket([]byte(ticketHash))
if bkt == nil {
return nil
}
err := altSigBkt.DeleteBucket([]byte(ticketHash))
if err != nil {
return fmt.Errorf("could not delete altsig: %w", err)
}
return nil
})
}
// AltSigData retrieves a ticket's alternate signature data. Existence of an
// alternate signature can be inferred by no error and nil data return.
func (vdb *VspDatabase) AltSigData(ticketHash string) (*AltSigData, error) {
var h *AltSigData
return h, vdb.db.View(func(tx *bolt.Tx) error {
bkt := tx.Bucket(vspBktK).Bucket(altSigBktK).Bucket([]byte(ticketHash))
if bkt == nil {
return nil
}
h = &AltSigData{
AltSigAddr: string(bkt.Get(altSigAddrK)),
Req: bkt.Get(reqK),
ReqSig: string(bkt.Get(reqSigK)),
Res: bkt.Get(resK),
ResSig: string(bkt.Get(resSigK)),
}
return nil
})
}

View File

@ -1,117 +0,0 @@
// 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.
package database
import (
"reflect"
"testing"
)
func exampleAltSigData() *AltSigData {
return &AltSigData{
AltSigAddr: randString(35, addrCharset),
Req: randBytes(1000),
ReqSig: randString(96, sigCharset),
Res: randBytes(1000),
ResSig: randString(96, sigCharset),
}
}
func ensureData(t *testing.T, ticketHash string, wantData *AltSigData) {
t.Helper()
data, err := db.AltSigData(ticketHash)
if err != nil {
t.Fatalf("unexpected error fetching alt signature data: %v", err)
}
if !reflect.DeepEqual(wantData, data) {
t.Fatal("want data different than actual")
}
}
func testAltSigData(t *testing.T) {
ticketHash := randString(64, hexCharset)
// Not added yet so no values should exist in the db.
h, err := db.AltSigData(ticketHash)
if err != nil {
t.Fatalf("unexpected error fetching alt signature data: %v", err)
}
if h != nil {
t.Fatal("expected no data")
}
// Insert an altsig.
data := exampleAltSigData()
if err := db.InsertAltSig(ticketHash, data); err != nil {
t.Fatalf("unexpected error storing altsig in database: %v", err)
}
ensureData(t, ticketHash, data)
}
func testInsertAltSig(t *testing.T) {
ticketHash := randString(64, hexCharset)
// Not added yet so no values should exist in the db.
ensureData(t, ticketHash, nil)
data := exampleAltSigData()
// Clear alt sig addr for test.
data.AltSigAddr = ""
if err := db.InsertAltSig(ticketHash, data); err == nil {
t.Fatalf("expected error for insert blank address")
}
if err := db.InsertAltSig(ticketHash, nil); err == nil {
t.Fatalf("expected error for nil data")
}
// Still no change on errors.
ensureData(t, ticketHash, nil)
// Re-add alt sig addr.
data.AltSigAddr = randString(35, addrCharset)
// Insert an altsig.
if err := db.InsertAltSig(ticketHash, data); err != nil {
t.Fatalf("unexpected error storing altsig in database: %v", err)
}
ensureData(t, ticketHash, data)
// Further additions should error and not change the data.
secondData := exampleAltSigData()
secondData.AltSigAddr = data.AltSigAddr
if err := db.InsertAltSig(ticketHash, secondData); err == nil {
t.Fatalf("expected error for second altsig addition")
}
ensureData(t, ticketHash, data)
}
func testDeleteAltSig(t *testing.T) {
ticketHash := randString(64, hexCharset)
// Nothing to delete.
if err := db.DeleteAltSig(ticketHash); err != nil {
t.Fatalf("unexpected error deleting nonexistant altsig")
}
// Insert an altsig.
data := exampleAltSigData()
if err := db.InsertAltSig(ticketHash, data); err != nil {
t.Fatalf("unexpected error storing altsig in database: %v", err)
}
ensureData(t, ticketHash, data)
if err := db.DeleteAltSig(ticketHash); err != nil {
t.Fatalf("unexpected error deleting altsig: %v", err)
}
ensureData(t, ticketHash, nil)
}

123
database/altsignaddr.go Normal file
View File

@ -0,0 +1,123 @@
// 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.
package database
import (
"errors"
"fmt"
bolt "go.etcd.io/bbolt"
)
// The keys used to store alternate signing addresses in the database.
var (
altSignAddrK = []byte("altsig")
reqK = []byte("req")
reqSigK = []byte("reqsig")
respK = []byte("res")
respSigK = []byte("ressig")
)
// AltSignAddrData holds the information needed to prove that a client added an
// alternate signing address.
type AltSignAddrData struct {
// AltSignAddr is the new alternate signing address. It is base 58 encoded.
AltSignAddr string
// Req is the original request to set an alternate signing address.
Req []byte
// ReqSig is the request's signature signed by the commitment address of the
// corresponding ticket. It is base 64 encoded.
ReqSig string
// Resp is the original response from the server to the alternate signing
// address.
Resp []byte
// RespSig is the response's signature signed by the server. It is base 64
// encoded.
RespSig string
}
// InsertAltSignAddr will insert the provided alternate signing address into the
// database. Returns an error if data for the ticket hash already exist.
//
// Passed data must have no empty fields.
func (vdb *VspDatabase) InsertAltSignAddr(ticketHash string, data *AltSignAddrData) error {
if data == nil {
return errors.New("alt sign addr data must not be nil for inserts")
}
if data.AltSignAddr == "" || len(data.Req) == 0 || data.ReqSig == "" ||
len(data.Resp) == 0 || data.RespSig == "" {
return errors.New("alt sign addr data has empty parameters")
}
return vdb.db.Update(func(tx *bolt.Tx) error {
altSignAddrBkt := tx.Bucket(vspBktK).Bucket(altSignAddrBktK)
// Create a bucket for the new alt sign addr. Returns an error if bucket
// already exists.
bkt, err := altSignAddrBkt.CreateBucket([]byte(ticketHash))
if err != nil {
return fmt.Errorf("could not create bucket for alt sign addr: %w", err)
}
if err := bkt.Put(altSignAddrK, []byte(data.AltSignAddr)); err != nil {
return err
}
if err := bkt.Put(reqK, data.Req); err != nil {
return err
}
if err := bkt.Put(reqSigK, []byte(data.ReqSig)); err != nil {
return err
}
if err := bkt.Put(respK, data.Resp); err != nil {
return err
}
return bkt.Put(respSigK, []byte(data.RespSig))
})
}
// DeleteAltSignAddr deletes an alternate signing address from the database.
// Does not error if there is no record in the database to delete.
func (vdb *VspDatabase) DeleteAltSignAddr(ticketHash string) error {
return vdb.db.Update(func(tx *bolt.Tx) error {
altSignAddrBkt := tx.Bucket(vspBktK).Bucket(altSignAddrBktK)
// Don't attempt delete if doesn't exist.
bkt := altSignAddrBkt.Bucket([]byte(ticketHash))
if bkt == nil {
return nil
}
err := altSignAddrBkt.DeleteBucket([]byte(ticketHash))
if err != nil {
return fmt.Errorf("could not delete altsignaddr: %w", err)
}
return nil
})
}
// AltSignAddrData retrieves a ticket's alternate signing data. Existence of an
// alternate signing address can be inferred by no error and nil data return.
func (vdb *VspDatabase) AltSignAddrData(ticketHash string) (*AltSignAddrData, error) {
var h *AltSignAddrData
return h, vdb.db.View(func(tx *bolt.Tx) error {
bkt := tx.Bucket(vspBktK).Bucket(altSignAddrBktK).Bucket([]byte(ticketHash))
if bkt == nil {
return nil
}
h = &AltSignAddrData{
AltSignAddr: string(bkt.Get(altSignAddrK)),
Req: bkt.Get(reqK),
ReqSig: string(bkt.Get(reqSigK)),
Resp: bkt.Get(respK),
RespSig: string(bkt.Get(respSigK)),
}
return nil
})
}

View File

@ -0,0 +1,118 @@
// 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.
package database
import (
"reflect"
"testing"
)
func exampleAltSignAddrData() *AltSignAddrData {
return &AltSignAddrData{
AltSignAddr: randString(35, addrCharset),
Req: randBytes(1000),
ReqSig: randString(96, sigCharset),
Resp: randBytes(1000),
RespSig: randString(96, sigCharset),
}
}
// ensureData will confirm that the provided data exists in the database.
func ensureData(t *testing.T, ticketHash string, wantData *AltSignAddrData) {
t.Helper()
data, err := db.AltSignAddrData(ticketHash)
if err != nil {
t.Fatalf("unexpected error fetching alt sign address data: %v", err)
}
if !reflect.DeepEqual(wantData, data) {
t.Fatal("want data different than actual")
}
}
func testAltSignAddrData(t *testing.T) {
ticketHash := randString(64, hexCharset)
// Not added yet so no values should exist in the db.
h, err := db.AltSignAddrData(ticketHash)
if err != nil {
t.Fatalf("unexpected error fetching alt sign address data: %v", err)
}
if h != nil {
t.Fatal("expected no data")
}
// Insert an alt sign address.
data := exampleAltSignAddrData()
if err := db.InsertAltSignAddr(ticketHash, data); err != nil {
t.Fatalf("unexpected error storing alt sign addr in database: %v", err)
}
ensureData(t, ticketHash, data)
}
func testInsertAltSignAddr(t *testing.T) {
ticketHash := randString(64, hexCharset)
// Not added yet so no values should exist in the db.
ensureData(t, ticketHash, nil)
data := exampleAltSignAddrData()
// Clear alt sign addr for test.
data.AltSignAddr = ""
if err := db.InsertAltSignAddr(ticketHash, data); err == nil {
t.Fatalf("expected error for insert blank address")
}
if err := db.InsertAltSignAddr(ticketHash, nil); err == nil {
t.Fatalf("expected error for nil data")
}
// Still no change on errors.
ensureData(t, ticketHash, nil)
// Re-add alt sig addr.
data.AltSignAddr = randString(35, addrCharset)
// Insert an alt sign addr.
if err := db.InsertAltSignAddr(ticketHash, data); err != nil {
t.Fatalf("unexpected error storing alt sig addr in database: %v", err)
}
ensureData(t, ticketHash, data)
// Further additions should error and not change the data.
secondData := exampleAltSignAddrData()
secondData.AltSignAddr = data.AltSignAddr
if err := db.InsertAltSignAddr(ticketHash, secondData); err == nil {
t.Fatalf("expected error for second alt sig addr addition")
}
ensureData(t, ticketHash, data)
}
func testDeleteAltSignAddr(t *testing.T) {
ticketHash := randString(64, hexCharset)
// Nothing to delete.
if err := db.DeleteAltSignAddr(ticketHash); err != nil {
t.Fatalf("unexpected error deleting nonexistant alt sign addr")
}
// Insert an alt sign addr.
data := exampleAltSignAddrData()
if err := db.InsertAltSignAddr(ticketHash, data); err != nil {
t.Fatalf("unexpected error storing alt sign addr in database: %v", err)
}
ensureData(t, ticketHash, data)
if err := db.DeleteAltSignAddr(ticketHash); err != nil {
t.Fatalf("unexpected error deleting alt sign addr: %v", err)
}
ensureData(t, ticketHash, nil)
}

View File

@ -50,8 +50,8 @@ var (
privateKeyK = []byte("privatekey")
// lastaddressindex is the index of the last address used for fees.
lastAddressIndexK = []byte("lastaddressindex")
// altSigBktK stores alternate signatures.
altSigBktK = []byte("altsigbkt")
// altSignAddrBktK stores alternate signing addresses.
altSignAddrBktK = []byte("altsigbkt")
)
const (

View File

@ -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.
@ -24,8 +24,12 @@ const (
feeXPub = "feexpub"
maxVoteChangeRecords = 3
// addrCharset is a list of all valid DCR address characters.
addrCharset = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
// hexCharset is a list of all valid hexadecimal characters.
hexCharset = "1234567890abcdef"
// sigCharset is a list of all valid request/response signature characters
// (base64 encoding).
sigCharset = "0123456789ABCDEFGHJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/="
)
@ -72,9 +76,9 @@ func TestDatabase(t *testing.T) {
"testDeleteTicket": testDeleteTicket,
"testVoteChangeRecords": testVoteChangeRecords,
"testHTTPBackup": testHTTPBackup,
"testAltSigData": testAltSigData,
"testInsertAltSig": testInsertAltSig,
"testDeleteAltSig": testDeleteAltSig,
"testAltSignAddrData": testAltSignAddrData,
"testInsertAltSignAddr": testInsertAltSignAddr,
"testDeleteAltSignAddr": testDeleteAltSignAddr,
}
for testName, test := range tests {

View File

@ -10,22 +10,22 @@ import (
bolt "go.etcd.io/bbolt"
)
func altSigUpgrade(db *bolt.DB) error {
log.Infof("Upgrading database to version %d", altSigVersion)
func altSignAddrUpgrade(db *bolt.DB) error {
log.Infof("Upgrading database to version %d", altSignAddrVersion)
// Run the upgrade in a single database transaction so it can be safely
// rolled back if an error is encountered.
err := db.Update(func(tx *bolt.Tx) error {
vspBkt := tx.Bucket(vspBktK)
// Create altsig bucket.
_, err := vspBkt.CreateBucket(altSigBktK)
// Create alt sign addr bucket.
_, err := vspBkt.CreateBucket(altSignAddrBktK)
if err != nil {
return fmt.Errorf("failed to create %s bucket: %w", altSigBktK, err)
return fmt.Errorf("failed to create %s bucket: %w", altSignAddrBktK, err)
}
// Update database version.
err = vspBkt.Put(versionK, uint32ToBytes(altSigVersion))
err = vspBkt.Put(versionK, uint32ToBytes(altSignAddrVersion))
if err != nil {
return fmt.Errorf("failed to update db version: %w", err)
}

View File

@ -25,14 +25,14 @@ const (
// moves each ticket into its own bucket and does away with JSON encoding.
ticketBucketVersion = 3
// altSigVersion adds a bucket to store alternate signatures used to verify
// messages sent to the vspd.
altSigVersion = 4
// altSignAddrVersion adds a bucket to store alternate sign addresses used
// to verify messages sent to the vspd.
altSignAddrVersion = 4
// latestVersion is the latest version of the database that is understood by
// vspd. Databases with recorded versions higher than this will fail to open
// (meaning any upgrades prevent reverting to older software).
latestVersion = altSigVersion
latestVersion = altSignAddrVersion
)
// upgrades maps between old database versions and the upgrade function to
@ -40,7 +40,7 @@ const (
var upgrades = []func(tx *bolt.DB) error{
initialVersion: removeOldFeeTxUpgrade,
removeOldFeeTxVersion: ticketBucketUpgrade,
ticketBucketVersion: altSigUpgrade,
ticketBucketVersion: altSignAddrUpgrade,
}
// v1Ticket has the json tags required to unmarshal tickets stored in the

View File

@ -69,12 +69,12 @@ its voting wallets unless both of these calls have succeeded.**
Set an alternate signing address for a ticket. The ticket must be valid and will
be transmitted to the network if not found. If set, for all future requests
involving this ticket, the vsp will check that a signature is good for this
involving this ticket, the VSP will check that a signature is good for this
address and fallback to the commitment address if not. The address must be valid
for the network and a pay to secp256k1 ECDSA pubkey hash script. The address can
only be set once. Further requests to set a new address will be rejected.
- `POST /api/v3/setaltsig`
- `POST /api/v3/setaltsignaddr`
Request:
@ -84,7 +84,7 @@ only be set once. Further requests to set a new address will be rejected.
"tickethash":"1b9f5dc3b4872c47f66b148b0633647458123d72a0f0623a90890cc51a668737",
"tickethex":"0100000001a8...bfa6e4bf9c5ec1",
"parenthex":"0100000022a7...580771a3064710",
"altsigaddress":"Tsfkn6k9AoYgVZRV6ZzcgmuVSgCdJQt9JY2"
"altsignaddress":"Tsfkn6k9AoYgVZRV6ZzcgmuVSgCdJQt9JY2"
}
```

View File

@ -41,7 +41,7 @@ type searchResult struct {
Hash string
Found bool
Ticket database.Ticket
AltSig string
AltSignAddr string
VoteChanges map[uint32]database.VoteChangeRecord
MaxVoteChanges int
}
@ -169,16 +169,16 @@ func ticketSearch(c *gin.Context) {
return
}
altSigData, err := db.AltSigData(hash)
altSignAddrData, err := db.AltSignAddrData(hash)
if err != nil {
log.Errorf("db.AltSigData error (ticketHash=%s): %v", hash, err)
log.Errorf("db.AltSignAddrData error (ticketHash=%s): %v", hash, err)
c.String(http.StatusInternalServerError, "Error getting alt sig from db")
return
}
altSig := ""
if altSigData != nil {
altSig = altSigData.AltSigAddr
altSignAddr := ""
if altSignAddrData != nil {
altSignAddr = altSignAddrData.AltSignAddr
}
c.HTML(http.StatusOK, "admin.html", gin.H{
@ -186,7 +186,7 @@ func ticketSearch(c *gin.Context) {
Hash: hash,
Found: found,
Ticket: ticket,
AltSig: altSig,
AltSignAddr: altSignAddr,
VoteChanges: voteChanges,
MaxVoteChanges: cfg.MaxVoteChangeRecords,
},

View File

@ -359,17 +359,17 @@ func vspAuth() gin.HandlerFunc {
err = validateSignature(reqBytes, commitmentAddress, c)
if err != nil {
// Don't return an error straight away if sig validation fails -
// first check if we have an alternate sig address for this ticket.
altSigData, err := db.AltSigData(hash)
// first check if we have an alternate sign address for this ticket.
altSigData, err := db.AltSignAddrData(hash)
if err != nil {
log.Errorf("%s: db.AltSigData failed (ticketHash=%s): %v", funcName, hash, err)
log.Errorf("%s: db.AltSignAddrData failed (ticketHash=%s): %v", funcName, hash, err)
sendError(errInternalError, c)
return
}
// If we have no alternate sig, or if validating with the alt sig
// fails, return an error to the client.
if altSigData == nil || validateSignature(reqBytes, altSigData.AltSigAddr, c) != nil {
// 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 || validateSignature(reqBytes, altSigData.AltSignAddr, c) != nil {
log.Warnf("%s: Bad signature (clientIP=%s, ticketHash=%s)", funcName, c.ClientIP(), hash)
sendError(errBadSignature, c)
return

View File

@ -25,10 +25,10 @@ type Node interface {
GetRawTransaction(txHash string) (*dcrdtypes.TxRawResult, error)
}
// setAltSig is the handler for "POST /api/v3/setaltsig".
func setAltSig(c *gin.Context) {
// setAltSignAddr is the handler for "POST /api/v3/setaltsignaddr".
func setAltSignAddr(c *gin.Context) {
const funcName = "setAltSig"
const funcName = "setAltSignAddr"
// Get values which have been added to context by middleware.
dcrdClient := c.MustGet(dcrdKey).(Node)
@ -45,23 +45,23 @@ func setAltSig(c *gin.Context) {
return
}
var request setAltSigRequest
var request setAltSignAddrRequest
if err := binding.JSON.BindBody(reqBytes, &request); err != nil {
log.Warnf("%s: Bad request (clientIP=%s): %v", funcName, c.ClientIP(), err)
sendErrorWithMsg(err.Error(), errBadRequest, c)
return
}
altSigAddr, ticketHash := request.AltSigAddress, request.TicketHash
altSignAddr, ticketHash := request.AltSignAddress, request.TicketHash
currentData, err := db.AltSigData(ticketHash)
currentData, err := db.AltSignAddrData(ticketHash)
if err != nil {
log.Errorf("%s: db.AltSigData (ticketHash=%s): %v", funcName, ticketHash, err)
log.Errorf("%s: db.AltSignAddrData (ticketHash=%s): %v", funcName, ticketHash, err)
sendError(errInternalError, c)
return
}
if currentData != nil {
msg := "alternate signature data already exists"
msg := "alternate sign address data already exists"
log.Warnf("%s: %s (ticketHash=%s)", funcName, msg, ticketHash)
sendErrorWithMsg(msg, errBadRequest, c)
return
@ -69,14 +69,14 @@ func setAltSig(c *gin.Context) {
}
// Fail fast if the pubkey doesn't decode properly.
addr, err := stdaddr.DecodeAddressV0(altSigAddr, cfg.NetParams)
addr, err := stdaddr.DecodeAddressV0(altSignAddr, cfg.NetParams)
if err != nil {
log.Warnf("%s: Alt sig address cannot be decoded (clientIP=%s): %v", funcName, c.ClientIP(), err)
log.Warnf("%s: Alt sign address cannot be decoded (clientIP=%s): %v", funcName, c.ClientIP(), err)
sendErrorWithMsg(err.Error(), errBadRequest, c)
return
}
if _, ok := addr.(*stdaddr.AddressPubKeyHashEcdsaSecp256k1V0); !ok {
log.Warnf("%s: Alt sig address is unexpected type (clientIP=%s, type=%T)", funcName, c.ClientIP(), addr)
log.Warnf("%s: Alt sign address is unexpected type (clientIP=%s, type=%T)", funcName, c.ClientIP(), addr)
sendErrorWithMsg("wrong type for alternate signing address", errBadRequest, c)
return
}
@ -103,28 +103,26 @@ func setAltSig(c *gin.Context) {
return
}
sigStr := c.GetHeader("VSP-Client-Signature")
// Send success response to client.
res, resSig := sendJSONResponse(setAltSigResponse{
resp, respSig := sendJSONResponse(setAltSignAddrResponse{
Timestamp: time.Now().Unix(),
Request: reqBytes,
}, c)
data := &database.AltSigData{
AltSigAddr: altSigAddr,
data := &database.AltSignAddrData{
AltSignAddr: altSignAddr,
Req: reqBytes,
ReqSig: sigStr,
Res: []byte(res),
ResSig: resSig,
ReqSig: c.GetHeader("VSP-Client-Signature"),
Resp: []byte(resp),
RespSig: respSig,
}
err = db.InsertAltSig(ticketHash, data)
err = db.InsertAltSignAddr(ticketHash, data)
if err != nil {
log.Errorf("%s: db.InsertAltSig error, failed to set alt data (ticketHash=%s): %v",
log.Errorf("%s: db.InsertAltSignAddr error (ticketHash=%s): %v",
funcName, ticketHash, err)
return
}
log.Debugf("%s: New alt sig pubkey set for ticket: (ticketHash=%s)", funcName, ticketHash)
log.Debugf("%s: New alt sign address set for ticket: (ticketHash=%s)", funcName, ticketHash)
}

View File

@ -27,8 +27,11 @@ import (
)
const (
sigCharset = "0123456789ABCDEFGHJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/="
// hexCharset is a list of all valid hexadecimal characters.
hexCharset = "1234567890abcdef"
// sigCharset is a list of all valid request/response signature characters
// (base64 encoding).
sigCharset = "0123456789ABCDEFGHJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/="
testDb = "test.db"
backupDb = "test.db-backup"
)
@ -115,7 +118,7 @@ func (n *testNode) GetRawTransaction(txHash string) (*dcrdtypes.TxRawResult, err
return nil, n.getRawTransactionErr
}
func TestSetAltSig(t *testing.T) {
func TestSetAltSignAddress(t *testing.T) {
const testAddr = "DsVoDXNQqyF3V83PJJ5zMdnB4pQuJHBAh15"
tests := []struct {
name string
@ -125,7 +128,7 @@ func TestSetAltSig(t *testing.T) {
addr string
getRawTransactionErr error
canTicketNotVote bool
isExistingAltSig bool
isExistingAltSignAddr bool
canTicketVoteErr error
wantCode int
}{{
@ -171,18 +174,18 @@ func TestSetAltSig(t *testing.T) {
}, {
name: "hist at max",
addr: testAddr,
isExistingAltSig: true,
isExistingAltSignAddr: true,
wantCode: http.StatusBadRequest,
}}
for _, test := range tests {
ticketHash := randString(64, hexCharset)
req := &setAltSigRequest{
req := &setAltSignAddrRequest{
Timestamp: time.Now().Unix(),
TicketHash: ticketHash,
TicketHex: randString(504, hexCharset),
ParentHex: randString(504, hexCharset),
AltSigAddress: test.addr,
AltSignAddress: test.addr,
}
reqSig := randString(504, hexCharset)
b, err := json.Marshal(req)
@ -190,16 +193,16 @@ func TestSetAltSig(t *testing.T) {
t.Fatal(err)
}
if test.isExistingAltSig {
data := &database.AltSigData{
AltSigAddr: test.addr,
if test.isExistingAltSignAddr {
data := &database.AltSignAddrData{
AltSignAddr: test.addr,
Req: b,
ReqSig: reqSig,
Res: randBytes(1000),
ResSig: randString(96, sigCharset),
Resp: randBytes(1000),
RespSig: randString(96, sigCharset),
}
if err := db.InsertAltSig(ticketHash, data); err != nil {
t.Fatalf("%q: unable to insert ticket: %v", test.name, err)
if err := db.InsertAltSignAddr(ticketHash, data); err != nil {
t.Fatalf("%q: unable to insert alt sign addr: %v", test.name, err)
}
}
@ -223,7 +226,7 @@ func TestSetAltSig(t *testing.T) {
c.Set(dcrdKey, tNode)
c.Set(dcrdErrorKey, dcrdErr)
c.Set(requestBytesKey, b[test.deformReq:])
setAltSig(c)
setAltSignAddr(c)
}
r.POST("/", handle)
@ -241,20 +244,20 @@ func TestSetAltSig(t *testing.T) {
t.Errorf("%q: expected status %d, got %d", test.name, test.wantCode, w.Code)
}
altsig, err := db.AltSigData(ticketHash)
altsig, err := db.AltSignAddrData(ticketHash)
if err != nil {
t.Fatalf("%q: unable to get alt sig data: %v", test.name, err)
t.Fatalf("%q: unable to get alt sign addr data: %v", test.name, err)
}
if test.wantCode != http.StatusOK && !test.isExistingAltSig {
if test.wantCode != http.StatusOK && !test.isExistingAltSignAddr {
if altsig != nil {
t.Fatalf("%q: expected no alt sig saved for errored state", test.name)
t.Fatalf("%q: expected no alt sign addr saved for errored state", test.name)
}
continue
}
if !bytes.Equal(b, altsig.Req) || altsig.ReqSig != reqSig {
t.Fatalf("%q: expected alt sig data different than actual", test.name)
t.Fatalf("%q: expected alt sign addr data different than actual", test.name)
}
}
}

View File

@ -43,8 +43,8 @@
<tr>
<th>Alternate Signing Address</th>
<td>
<a href="{{ addressURL .AltSig }}">
{{ .AltSig }}
<a href="{{ addressURL .AltSignAddr }}">
{{ .AltSignAddr }}
</a>
</td>
</tr>

View File

@ -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.
@ -72,15 +72,15 @@ type ticketStatusResponse struct {
Request []byte `json:"request"`
}
type setAltSigRequest struct {
type setAltSignAddrRequest struct {
Timestamp int64 `json:"timestamp" binding:"required"`
TicketHash string `json:"tickethash" binding:"required"`
TicketHex string `json:"tickethex" binding:"required"`
ParentHex string `json:"parenthex" binding:"required"`
AltSigAddress string `json:"altsigaddress" binding:"required"`
AltSignAddress string `json:"altsignaddress" binding:"required"`
}
type setAltSigResponse struct {
type setAltSignAddrResponse struct {
Timestamp int64 `json:"timestamp"`
Request []byte `json:"request"`
}

View File

@ -228,7 +228,7 @@ func router(debugMode bool, cookieSecret []byte, dcrd rpc.DcrdConnect, wallets r
api := router.Group("/api/v3")
api.GET("/vspinfo", vspInfo)
api.POST("/setaltsig", withDcrdClient(dcrd), broadcastTicket(), vspAuth(), setAltSig)
api.POST("/setaltsignaddr", withDcrdClient(dcrd), broadcastTicket(), vspAuth(), setAltSignAddr)
api.POST("/feeaddress", withDcrdClient(dcrd), broadcastTicket(), vspAuth(), feeAddress)
api.POST("/ticketstatus", withDcrdClient(dcrd), vspAuth(), ticketStatus)
api.POST("/payfee", withDcrdClient(dcrd), vspAuth(), payFee)