Clarify "setaltsig" terminology.
Stardardize "alt sig"/"alt signature"/"alt signing address" terminology to "alternate signing address".
This commit is contained in:
parent
b1a68a94fe
commit
ab5aa4dd6d
@ -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 {
|
||||
|
||||
@ -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
|
||||
})
|
||||
}
|
||||
@ -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
123
database/altsignaddr.go
Normal 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
|
||||
})
|
||||
}
|
||||
118
database/altsignaddr_test.go
Normal file
118
database/altsignaddr_test.go
Normal 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)
|
||||
}
|
||||
@ -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 (
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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"
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@ -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,
|
||||
},
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -43,8 +43,8 @@
|
||||
<tr>
|
||||
<th>Alternate Signing Address</th>
|
||||
<td>
|
||||
<a href="{{ addressURL .AltSig }}">
|
||||
{{ .AltSig }}
|
||||
<a href="{{ addressURL .AltSignAddr }}">
|
||||
{{ .AltSignAddr }}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@ -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"`
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user