To allow signing with addresses other than the commitment address, add an alternate signature address. In order to continue to prove that the address was chosen by the user, add an alternate signature history. Only allow one record per ticket to be saved to cap needed db space.
125 lines
3.4 KiB
Go
125 lines
3.4 KiB
Go
// 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
|
|
})
|
|
}
|