vspd/database/altsignaddr.go
2022-01-13 12:40:16 +00:00

124 lines
3.7 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 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 string
// 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 string
// 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, []byte(data.Req)); err != nil {
return err
}
if err := bkt.Put(reqSigK, []byte(data.ReqSig)); err != nil {
return err
}
if err := bkt.Put(respK, []byte(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: string(bkt.Get(reqK)),
ReqSig: string(bkt.Get(reqSigK)),
Resp: string(bkt.Get(respK)),
RespSig: string(bkt.Get(respSigK)),
}
return nil
})
}