mirror of
https://github.com/LBRYFoundation/lbcwallet.git
synced 2025-08-27 15:31:30 +00:00
Make votingpool package (sans tests) compile
This commit is contained in:
parent
4656a00705
commit
f143d095d6
4 changed files with 113 additions and 157 deletions
|
@ -117,10 +117,10 @@ func getUsedAddrBucketID(seriesID uint32, branch Branch) []byte {
|
||||||
|
|
||||||
// putUsedAddrHash adds an entry (key==index, value==encryptedHash) to the used
|
// putUsedAddrHash adds an entry (key==index, value==encryptedHash) to the used
|
||||||
// addresses bucket of the given pool, series and branch.
|
// addresses bucket of the given pool, series and branch.
|
||||||
func putUsedAddrHash(tx walletdb.Tx, poolID []byte, seriesID uint32, branch Branch,
|
func putUsedAddrHash(ns walletdb.ReadWriteBucket, poolID []byte, seriesID uint32, branch Branch,
|
||||||
index Index, encryptedHash []byte) error {
|
index Index, encryptedHash []byte) error {
|
||||||
|
|
||||||
usedAddrs := tx.RootBucket().Bucket(poolID).Bucket(usedAddrsBucketName)
|
usedAddrs := ns.NestedReadWriteBucket(poolID).NestedReadWriteBucket(usedAddrsBucketName)
|
||||||
bucket, err := usedAddrs.CreateBucketIfNotExists(getUsedAddrBucketID(seriesID, branch))
|
bucket, err := usedAddrs.CreateBucketIfNotExists(getUsedAddrBucketID(seriesID, branch))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newError(ErrDatabase, "failed to store used address hash", err)
|
return newError(ErrDatabase, "failed to store used address hash", err)
|
||||||
|
@ -130,11 +130,11 @@ func putUsedAddrHash(tx walletdb.Tx, poolID []byte, seriesID uint32, branch Bran
|
||||||
|
|
||||||
// getUsedAddrHash returns the addr hash with the given index from the used
|
// getUsedAddrHash returns the addr hash with the given index from the used
|
||||||
// addresses bucket of the given pool, series and branch.
|
// addresses bucket of the given pool, series and branch.
|
||||||
func getUsedAddrHash(tx walletdb.Tx, poolID []byte, seriesID uint32, branch Branch,
|
func getUsedAddrHash(ns walletdb.ReadBucket, poolID []byte, seriesID uint32, branch Branch,
|
||||||
index Index) []byte {
|
index Index) []byte {
|
||||||
|
|
||||||
usedAddrs := tx.RootBucket().Bucket(poolID).Bucket(usedAddrsBucketName)
|
usedAddrs := ns.NestedReadBucket(poolID).NestedReadBucket(usedAddrsBucketName)
|
||||||
bucket := usedAddrs.Bucket(getUsedAddrBucketID(seriesID, branch))
|
bucket := usedAddrs.NestedReadBucket(getUsedAddrBucketID(seriesID, branch))
|
||||||
if bucket == nil {
|
if bucket == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -143,10 +143,10 @@ func getUsedAddrHash(tx walletdb.Tx, poolID []byte, seriesID uint32, branch Bran
|
||||||
|
|
||||||
// getMaxUsedIdx returns the highest used index from the used addresses bucket
|
// getMaxUsedIdx returns the highest used index from the used addresses bucket
|
||||||
// of the given pool, series and branch.
|
// of the given pool, series and branch.
|
||||||
func getMaxUsedIdx(tx walletdb.Tx, poolID []byte, seriesID uint32, branch Branch) (Index, error) {
|
func getMaxUsedIdx(ns walletdb.ReadBucket, poolID []byte, seriesID uint32, branch Branch) (Index, error) {
|
||||||
maxIdx := Index(0)
|
maxIdx := Index(0)
|
||||||
usedAddrs := tx.RootBucket().Bucket(poolID).Bucket(usedAddrsBucketName)
|
usedAddrs := ns.NestedReadBucket(poolID).NestedReadBucket(usedAddrsBucketName)
|
||||||
bucket := usedAddrs.Bucket(getUsedAddrBucketID(seriesID, branch))
|
bucket := usedAddrs.NestedReadBucket(getUsedAddrBucketID(seriesID, branch))
|
||||||
if bucket == nil {
|
if bucket == nil {
|
||||||
return maxIdx, nil
|
return maxIdx, nil
|
||||||
}
|
}
|
||||||
|
@ -173,8 +173,8 @@ func getMaxUsedIdx(tx walletdb.Tx, poolID []byte, seriesID uint32, branch Branch
|
||||||
// putPool stores a voting pool in the database, creating a bucket named
|
// putPool stores a voting pool in the database, creating a bucket named
|
||||||
// after the voting pool id and two other buckets inside it to store series and
|
// after the voting pool id and two other buckets inside it to store series and
|
||||||
// used addresses for that pool.
|
// used addresses for that pool.
|
||||||
func putPool(tx walletdb.Tx, poolID []byte) error {
|
func putPool(ns walletdb.ReadWriteBucket, poolID []byte) error {
|
||||||
poolBucket, err := tx.RootBucket().CreateBucket(poolID)
|
poolBucket, err := ns.CreateBucket(poolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newError(ErrDatabase, fmt.Sprintf("cannot create pool %v", poolID), err)
|
return newError(ErrDatabase, fmt.Sprintf("cannot create pool %v", poolID), err)
|
||||||
}
|
}
|
||||||
|
@ -198,8 +198,8 @@ func putPool(tx walletdb.Tx, poolID []byte) error {
|
||||||
|
|
||||||
// loadAllSeries returns a map of all the series stored inside a voting pool
|
// loadAllSeries returns a map of all the series stored inside a voting pool
|
||||||
// bucket, keyed by id.
|
// bucket, keyed by id.
|
||||||
func loadAllSeries(tx walletdb.Tx, poolID []byte) (map[uint32]*dbSeriesRow, error) {
|
func loadAllSeries(ns walletdb.ReadBucket, poolID []byte) (map[uint32]*dbSeriesRow, error) {
|
||||||
bucket := tx.RootBucket().Bucket(poolID).Bucket(seriesBucketName)
|
bucket := ns.NestedReadBucket(poolID).NestedReadBucket(seriesBucketName)
|
||||||
allSeries := make(map[uint32]*dbSeriesRow)
|
allSeries := make(map[uint32]*dbSeriesRow)
|
||||||
err := bucket.ForEach(
|
err := bucket.ForEach(
|
||||||
func(k, v []byte) error {
|
func(k, v []byte) error {
|
||||||
|
@ -219,14 +219,14 @@ func loadAllSeries(tx walletdb.Tx, poolID []byte) (map[uint32]*dbSeriesRow, erro
|
||||||
|
|
||||||
// existsPool checks the existence of a bucket named after the given
|
// existsPool checks the existence of a bucket named after the given
|
||||||
// voting pool id.
|
// voting pool id.
|
||||||
func existsPool(tx walletdb.Tx, poolID []byte) bool {
|
func existsPool(ns walletdb.ReadBucket, poolID []byte) bool {
|
||||||
bucket := tx.RootBucket().Bucket(poolID)
|
bucket := ns.NestedReadBucket(poolID)
|
||||||
return bucket != nil
|
return bucket != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// putSeries stores the given series inside a voting pool bucket named after
|
// putSeries stores the given series inside a voting pool bucket named after
|
||||||
// poolID. The voting pool bucket does not need to be created beforehand.
|
// poolID. The voting pool bucket does not need to be created beforehand.
|
||||||
func putSeries(tx walletdb.Tx, poolID []byte, version, ID uint32, active bool, reqSigs uint32, pubKeysEncrypted, privKeysEncrypted [][]byte) error {
|
func putSeries(ns walletdb.ReadWriteBucket, poolID []byte, version, ID uint32, active bool, reqSigs uint32, pubKeysEncrypted, privKeysEncrypted [][]byte) error {
|
||||||
row := &dbSeriesRow{
|
row := &dbSeriesRow{
|
||||||
version: version,
|
version: version,
|
||||||
active: active,
|
active: active,
|
||||||
|
@ -234,19 +234,22 @@ func putSeries(tx walletdb.Tx, poolID []byte, version, ID uint32, active bool, r
|
||||||
pubKeysEncrypted: pubKeysEncrypted,
|
pubKeysEncrypted: pubKeysEncrypted,
|
||||||
privKeysEncrypted: privKeysEncrypted,
|
privKeysEncrypted: privKeysEncrypted,
|
||||||
}
|
}
|
||||||
return putSeriesRow(tx, poolID, ID, row)
|
return putSeriesRow(ns, poolID, ID, row)
|
||||||
}
|
}
|
||||||
|
|
||||||
// putSeriesRow stores the given series row inside a voting pool bucket named
|
// putSeriesRow stores the given series row inside a voting pool bucket named
|
||||||
// after poolID. The voting pool bucket does not need to be created
|
// after poolID. The voting pool bucket does not need to be created
|
||||||
// beforehand.
|
// beforehand.
|
||||||
func putSeriesRow(tx walletdb.Tx, poolID []byte, ID uint32, row *dbSeriesRow) error {
|
func putSeriesRow(ns walletdb.ReadWriteBucket, poolID []byte, ID uint32, row *dbSeriesRow) error {
|
||||||
bucket, err := tx.RootBucket().CreateBucketIfNotExists(poolID)
|
bucket, err := ns.CreateBucketIfNotExists(poolID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
str := fmt.Sprintf("cannot create bucket %v", poolID)
|
str := fmt.Sprintf("cannot create bucket %v", poolID)
|
||||||
return newError(ErrDatabase, str, err)
|
return newError(ErrDatabase, str, err)
|
||||||
}
|
}
|
||||||
bucket = bucket.Bucket(seriesBucketName)
|
bucket, err = bucket.CreateBucketIfNotExists(seriesBucketName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
serialized, err := serializeSeriesRow(row)
|
serialized, err := serializeSeriesRow(row)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -473,7 +476,7 @@ func serializeWithdrawal(requests []OutputRequest, startAddress WithdrawalAddres
|
||||||
// deserializeWithdrawal deserializes the given byte slice into a dbWithdrawalRow,
|
// deserializeWithdrawal deserializes the given byte slice into a dbWithdrawalRow,
|
||||||
// converts it into an withdrawalInfo and returns it. This function must run
|
// converts it into an withdrawalInfo and returns it. This function must run
|
||||||
// with the address manager unlocked.
|
// with the address manager unlocked.
|
||||||
func deserializeWithdrawal(p *Pool, serialized []byte) (*withdrawalInfo, error) {
|
func deserializeWithdrawal(p *Pool, ns, addrmgrNs walletdb.ReadBucket, serialized []byte) (*withdrawalInfo, error) {
|
||||||
var row dbWithdrawalRow
|
var row dbWithdrawalRow
|
||||||
if err := gob.NewDecoder(bytes.NewReader(serialized)).Decode(&row); err != nil {
|
if err := gob.NewDecoder(bytes.NewReader(serialized)).Decode(&row); err != nil {
|
||||||
return nil, newError(ErrWithdrawalStorage, "cannot deserialize withdrawal information",
|
return nil, newError(ErrWithdrawalStorage, "cannot deserialize withdrawal information",
|
||||||
|
@ -509,7 +512,7 @@ func deserializeWithdrawal(p *Pool, serialized []byte) (*withdrawalInfo, error)
|
||||||
requestsByOID[request.outBailmentID()] = request
|
requestsByOID[request.outBailmentID()] = request
|
||||||
}
|
}
|
||||||
startAddr := row.StartAddress
|
startAddr := row.StartAddress
|
||||||
wAddr, err := p.WithdrawalAddress(startAddr.SeriesID, startAddr.Branch, startAddr.Index)
|
wAddr, err := p.WithdrawalAddress(ns, addrmgrNs, startAddr.SeriesID, startAddr.Branch, startAddr.Index)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, newError(ErrWithdrawalStorage, "cannot deserialize startAddress", err)
|
return nil, newError(ErrWithdrawalStorage, "cannot deserialize startAddress", err)
|
||||||
}
|
}
|
||||||
|
@ -564,13 +567,13 @@ func deserializeWithdrawal(p *Pool, serialized []byte) (*withdrawalInfo, error)
|
||||||
return wInfo, nil
|
return wInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func putWithdrawal(tx walletdb.Tx, poolID []byte, roundID uint32, serialized []byte) error {
|
func putWithdrawal(ns walletdb.ReadWriteBucket, poolID []byte, roundID uint32, serialized []byte) error {
|
||||||
bucket := tx.RootBucket().Bucket(poolID)
|
bucket := ns.NestedReadWriteBucket(poolID)
|
||||||
return bucket.Put(uint32ToBytes(roundID), serialized)
|
return bucket.Put(uint32ToBytes(roundID), serialized)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getWithdrawal(tx walletdb.Tx, poolID []byte, roundID uint32) []byte {
|
func getWithdrawal(ns walletdb.ReadBucket, poolID []byte, roundID uint32) []byte {
|
||||||
bucket := tx.RootBucket().Bucket(poolID)
|
bucket := ns.NestedReadBucket(poolID)
|
||||||
return bucket.Get(uint32ToBytes(roundID))
|
return bucket.Get(uint32ToBytes(roundID))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,10 +21,11 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/roasbeef/btcd/chaincfg"
|
"github.com/btcsuite/btcd/chaincfg"
|
||||||
"github.com/roasbeef/btcd/txscript"
|
"github.com/btcsuite/btcd/txscript"
|
||||||
"github.com/roasbeef/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/roasbeef/btcwallet/wtxmgr"
|
"github.com/btcsuite/btcwallet/walletdb"
|
||||||
|
"github.com/btcsuite/btcwallet/wtxmgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
const eligibleInputMinConfirmations = 100
|
const eligibleInputMinConfirmations = 100
|
||||||
|
@ -98,7 +99,7 @@ func (c byAddress) Less(i, j int) bool {
|
||||||
// getEligibleInputs returns eligible inputs with addresses between startAddress
|
// getEligibleInputs returns eligible inputs with addresses between startAddress
|
||||||
// and the last used address of lastSeriesID. They're reverse ordered based on
|
// and the last used address of lastSeriesID. They're reverse ordered based on
|
||||||
// their address.
|
// their address.
|
||||||
func (p *Pool) getEligibleInputs(store *wtxmgr.Store, startAddress WithdrawalAddress,
|
func (p *Pool) getEligibleInputs(ns, addrmgrNs walletdb.ReadBucket, store *wtxmgr.Store, txmgrNs walletdb.ReadBucket, startAddress WithdrawalAddress,
|
||||||
lastSeriesID uint32, dustThreshold btcutil.Amount, chainHeight int32,
|
lastSeriesID uint32, dustThreshold btcutil.Amount, chainHeight int32,
|
||||||
minConf int) ([]credit, error) {
|
minConf int) ([]credit, error) {
|
||||||
|
|
||||||
|
@ -106,7 +107,7 @@ func (p *Pool) getEligibleInputs(store *wtxmgr.Store, startAddress WithdrawalAdd
|
||||||
str := fmt.Sprintf("lastSeriesID (%d) does not exist", lastSeriesID)
|
str := fmt.Sprintf("lastSeriesID (%d) does not exist", lastSeriesID)
|
||||||
return nil, newError(ErrSeriesNotExists, str, nil)
|
return nil, newError(ErrSeriesNotExists, str, nil)
|
||||||
}
|
}
|
||||||
unspents, err := store.UnspentOutputs()
|
unspents, err := store.UnspentOutputs(txmgrNs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, newError(ErrInputSelection, "failed to get unspent outputs", err)
|
return nil, newError(ErrInputSelection, "failed to get unspent outputs", err)
|
||||||
}
|
}
|
||||||
|
@ -128,7 +129,7 @@ func (p *Pool) getEligibleInputs(store *wtxmgr.Store, startAddress WithdrawalAdd
|
||||||
}
|
}
|
||||||
inputs = append(inputs, eligibles...)
|
inputs = append(inputs, eligibles...)
|
||||||
}
|
}
|
||||||
nAddr, err := nextAddr(p, address.seriesID, address.branch, address.index, lastSeriesID+1)
|
nAddr, err := nextAddr(p, ns, addrmgrNs, address.seriesID, address.branch, address.index, lastSeriesID+1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, newError(ErrInputSelection, "failed to get next withdrawal address", err)
|
return nil, newError(ErrInputSelection, "failed to get next withdrawal address", err)
|
||||||
} else if nAddr == nil {
|
} else if nAddr == nil {
|
||||||
|
@ -144,7 +145,7 @@ func (p *Pool) getEligibleInputs(store *wtxmgr.Store, startAddress WithdrawalAdd
|
||||||
// nextAddr returns the next WithdrawalAddress according to the input selection
|
// nextAddr returns the next WithdrawalAddress according to the input selection
|
||||||
// rules: http://opentransactions.org/wiki/index.php/Input_Selection_Algorithm_(voting_pools)
|
// rules: http://opentransactions.org/wiki/index.php/Input_Selection_Algorithm_(voting_pools)
|
||||||
// It returns nil if the new address' seriesID is >= stopSeriesID.
|
// It returns nil if the new address' seriesID is >= stopSeriesID.
|
||||||
func nextAddr(p *Pool, seriesID uint32, branch Branch, index Index, stopSeriesID uint32) (
|
func nextAddr(p *Pool, ns, addrmgrNs walletdb.ReadBucket, seriesID uint32, branch Branch, index Index, stopSeriesID uint32) (
|
||||||
*WithdrawalAddress, error) {
|
*WithdrawalAddress, error) {
|
||||||
series := p.Series(seriesID)
|
series := p.Series(seriesID)
|
||||||
if series == nil {
|
if series == nil {
|
||||||
|
@ -152,7 +153,7 @@ func nextAddr(p *Pool, seriesID uint32, branch Branch, index Index, stopSeriesID
|
||||||
}
|
}
|
||||||
branch++
|
branch++
|
||||||
if int(branch) > len(series.publicKeys) {
|
if int(branch) > len(series.publicKeys) {
|
||||||
highestIdx, err := p.highestUsedSeriesIndex(seriesID)
|
highestIdx, err := p.highestUsedSeriesIndex(ns, seriesID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -171,14 +172,14 @@ func nextAddr(p *Pool, seriesID uint32, branch Branch, index Index, stopSeriesID
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
addr, err := p.WithdrawalAddress(seriesID, branch, index)
|
addr, err := p.WithdrawalAddress(ns, addrmgrNs, seriesID, branch, index)
|
||||||
if err != nil && err.(Error).ErrorCode == ErrWithdrawFromUnusedAddr {
|
if err != nil && err.(Error).ErrorCode == ErrWithdrawFromUnusedAddr {
|
||||||
// The used indices will vary between branches so sometimes we'll try to
|
// The used indices will vary between branches so sometimes we'll try to
|
||||||
// get a WithdrawalAddress that hasn't been used before, and in such
|
// get a WithdrawalAddress that hasn't been used before, and in such
|
||||||
// cases we just need to move on to the next one.
|
// cases we just need to move on to the next one.
|
||||||
log.Debugf("nextAddr(): skipping addr (series #%d, branch #%d, index #%d) as it hasn't "+
|
log.Debugf("nextAddr(): skipping addr (series #%d, branch #%d, index #%d) as it hasn't "+
|
||||||
"been used before", seriesID, branch, index)
|
"been used before", seriesID, branch, index)
|
||||||
return nextAddr(p, seriesID, branch, index, stopSeriesID)
|
return nextAddr(p, ns, addrmgrNs, seriesID, branch, index, stopSeriesID)
|
||||||
}
|
}
|
||||||
return addr, err
|
return addr, err
|
||||||
}
|
}
|
||||||
|
@ -186,7 +187,7 @@ func nextAddr(p *Pool, seriesID uint32, branch Branch, index Index, stopSeriesID
|
||||||
// highestUsedSeriesIndex returns the highest index among all of this Pool's
|
// highestUsedSeriesIndex returns the highest index among all of this Pool's
|
||||||
// used addresses for the given seriesID. It returns 0 if there are no used
|
// used addresses for the given seriesID. It returns 0 if there are no used
|
||||||
// addresses with the given seriesID.
|
// addresses with the given seriesID.
|
||||||
func (p *Pool) highestUsedSeriesIndex(seriesID uint32) (Index, error) {
|
func (p *Pool) highestUsedSeriesIndex(ns walletdb.ReadBucket, seriesID uint32) (Index, error) {
|
||||||
maxIdx := Index(0)
|
maxIdx := Index(0)
|
||||||
series := p.Series(seriesID)
|
series := p.Series(seriesID)
|
||||||
if series == nil {
|
if series == nil {
|
||||||
|
@ -194,7 +195,7 @@ func (p *Pool) highestUsedSeriesIndex(seriesID uint32) (Index, error) {
|
||||||
newError(ErrSeriesNotExists, fmt.Sprintf("unknown seriesID: %d", seriesID), nil)
|
newError(ErrSeriesNotExists, fmt.Sprintf("unknown seriesID: %d", seriesID), nil)
|
||||||
}
|
}
|
||||||
for i := range series.publicKeys {
|
for i := range series.publicKeys {
|
||||||
idx, err := p.highestUsedIndexFor(seriesID, Branch(i))
|
idx, err := p.highestUsedIndexFor(ns, seriesID, Branch(i))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Index(0), err
|
return Index(0), err
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,6 @@ type Pool struct {
|
||||||
ID []byte
|
ID []byte
|
||||||
seriesLookup map[uint32]*SeriesData
|
seriesLookup map[uint32]*SeriesData
|
||||||
manager *waddrmgr.Manager
|
manager *waddrmgr.Manager
|
||||||
namespace walletdb.Namespace
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PoolAddress represents a voting pool P2SH address, generated by
|
// PoolAddress represents a voting pool P2SH address, generated by
|
||||||
|
@ -83,54 +82,43 @@ type WithdrawalAddress struct {
|
||||||
|
|
||||||
// Create creates a new entry in the database with the given ID
|
// Create creates a new entry in the database with the given ID
|
||||||
// and returns the Pool representing it.
|
// and returns the Pool representing it.
|
||||||
func Create(namespace walletdb.Namespace, m *waddrmgr.Manager, poolID []byte) (*Pool, error) {
|
func Create(ns walletdb.ReadWriteBucket, m *waddrmgr.Manager, poolID []byte) (*Pool, error) {
|
||||||
err := namespace.Update(
|
err := putPool(ns, poolID)
|
||||||
func(tx walletdb.Tx) error {
|
|
||||||
return putPool(tx, poolID)
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
str := fmt.Sprintf("unable to add voting pool %v to db", poolID)
|
str := fmt.Sprintf("unable to add voting pool %v to db", poolID)
|
||||||
return nil, newError(ErrPoolAlreadyExists, str, err)
|
return nil, newError(ErrPoolAlreadyExists, str, err)
|
||||||
}
|
}
|
||||||
return newPool(namespace, m, poolID), nil
|
return newPool(m, poolID), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load fetches the entry in the database with the given ID and returns the Pool
|
// Load fetches the entry in the database with the given ID and returns the Pool
|
||||||
// representing it.
|
// representing it.
|
||||||
func Load(namespace walletdb.Namespace, m *waddrmgr.Manager, poolID []byte) (*Pool, error) {
|
func Load(ns walletdb.ReadBucket, m *waddrmgr.Manager, poolID []byte) (*Pool, error) {
|
||||||
err := namespace.View(
|
if !existsPool(ns, poolID) {
|
||||||
func(tx walletdb.Tx) error {
|
str := fmt.Sprintf("unable to find voting pool %v in db", poolID)
|
||||||
if exists := existsPool(tx, poolID); !exists {
|
return nil, newError(ErrPoolNotExists, str, nil)
|
||||||
str := fmt.Sprintf("unable to find voting pool %v in db", poolID)
|
|
||||||
return newError(ErrPoolNotExists, str, nil)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
p := newPool(namespace, m, poolID)
|
p := newPool(m, poolID)
|
||||||
if err = p.LoadAllSeries(); err != nil {
|
if err := p.LoadAllSeries(ns); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// newPool creates a new Pool instance.
|
// newPool creates a new Pool instance.
|
||||||
func newPool(namespace walletdb.Namespace, m *waddrmgr.Manager, poolID []byte) *Pool {
|
func newPool(m *waddrmgr.Manager, poolID []byte) *Pool {
|
||||||
return &Pool{
|
return &Pool{
|
||||||
ID: poolID,
|
ID: poolID,
|
||||||
seriesLookup: make(map[uint32]*SeriesData),
|
seriesLookup: make(map[uint32]*SeriesData),
|
||||||
manager: m,
|
manager: m,
|
||||||
namespace: namespace,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadAndGetDepositScript generates and returns a deposit script for the given seriesID,
|
// LoadAndGetDepositScript generates and returns a deposit script for the given seriesID,
|
||||||
// branch and index of the Pool identified by poolID.
|
// branch and index of the Pool identified by poolID.
|
||||||
func LoadAndGetDepositScript(namespace walletdb.Namespace, m *waddrmgr.Manager, poolID string, seriesID uint32, branch Branch, index Index) ([]byte, error) {
|
func LoadAndGetDepositScript(ns walletdb.ReadBucket, m *waddrmgr.Manager, poolID string, seriesID uint32, branch Branch, index Index) ([]byte, error) {
|
||||||
pid := []byte(poolID)
|
pid := []byte(poolID)
|
||||||
p, err := Load(namespace, m, pid)
|
p, err := Load(ns, m, pid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -144,14 +132,14 @@ func LoadAndGetDepositScript(namespace walletdb.Namespace, m *waddrmgr.Manager,
|
||||||
// LoadAndCreateSeries loads the Pool with the given ID, creating a new one if it doesn't
|
// LoadAndCreateSeries loads the Pool with the given ID, creating a new one if it doesn't
|
||||||
// yet exist, and then creates and returns a Series with the given seriesID, rawPubKeys
|
// yet exist, and then creates and returns a Series with the given seriesID, rawPubKeys
|
||||||
// and reqSigs. See CreateSeries for the constraints enforced on rawPubKeys and reqSigs.
|
// and reqSigs. See CreateSeries for the constraints enforced on rawPubKeys and reqSigs.
|
||||||
func LoadAndCreateSeries(namespace walletdb.Namespace, m *waddrmgr.Manager, version uint32,
|
func LoadAndCreateSeries(ns walletdb.ReadWriteBucket, m *waddrmgr.Manager, version uint32,
|
||||||
poolID string, seriesID, reqSigs uint32, rawPubKeys []string) error {
|
poolID string, seriesID, reqSigs uint32, rawPubKeys []string) error {
|
||||||
pid := []byte(poolID)
|
pid := []byte(poolID)
|
||||||
p, err := Load(namespace, m, pid)
|
p, err := Load(ns, m, pid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
vpErr := err.(Error)
|
vpErr := err.(Error)
|
||||||
if vpErr.ErrorCode == ErrPoolNotExists {
|
if vpErr.ErrorCode == ErrPoolNotExists {
|
||||||
p, err = Create(namespace, m, pid)
|
p, err = Create(ns, m, pid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -159,31 +147,31 @@ func LoadAndCreateSeries(namespace walletdb.Namespace, m *waddrmgr.Manager, vers
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return p.CreateSeries(version, seriesID, reqSigs, rawPubKeys)
|
return p.CreateSeries(ns, version, seriesID, reqSigs, rawPubKeys)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadAndReplaceSeries loads the voting pool with the given ID and calls ReplaceSeries,
|
// LoadAndReplaceSeries loads the voting pool with the given ID and calls ReplaceSeries,
|
||||||
// passing the given series ID, public keys and reqSigs to it.
|
// passing the given series ID, public keys and reqSigs to it.
|
||||||
func LoadAndReplaceSeries(namespace walletdb.Namespace, m *waddrmgr.Manager, version uint32,
|
func LoadAndReplaceSeries(ns walletdb.ReadWriteBucket, m *waddrmgr.Manager, version uint32,
|
||||||
poolID string, seriesID, reqSigs uint32, rawPubKeys []string) error {
|
poolID string, seriesID, reqSigs uint32, rawPubKeys []string) error {
|
||||||
pid := []byte(poolID)
|
pid := []byte(poolID)
|
||||||
p, err := Load(namespace, m, pid)
|
p, err := Load(ns, m, pid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return p.ReplaceSeries(version, seriesID, reqSigs, rawPubKeys)
|
return p.ReplaceSeries(ns, version, seriesID, reqSigs, rawPubKeys)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadAndEmpowerSeries loads the voting pool with the given ID and calls EmpowerSeries,
|
// LoadAndEmpowerSeries loads the voting pool with the given ID and calls EmpowerSeries,
|
||||||
// passing the given series ID and private key to it.
|
// passing the given series ID and private key to it.
|
||||||
func LoadAndEmpowerSeries(namespace walletdb.Namespace, m *waddrmgr.Manager,
|
func LoadAndEmpowerSeries(ns walletdb.ReadWriteBucket, m *waddrmgr.Manager,
|
||||||
poolID string, seriesID uint32, rawPrivKey string) error {
|
poolID string, seriesID uint32, rawPrivKey string) error {
|
||||||
pid := []byte(poolID)
|
pid := []byte(poolID)
|
||||||
pool, err := Load(namespace, m, pid)
|
pool, err := Load(ns, m, pid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return pool.EmpowerSeries(seriesID, rawPrivKey)
|
return pool.EmpowerSeries(ns, seriesID, rawPrivKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Series returns the series with the given ID, or nil if it doesn't
|
// Series returns the series with the given ID, or nil if it doesn't
|
||||||
|
@ -205,7 +193,7 @@ func (p *Pool) Manager() *waddrmgr.Manager {
|
||||||
// first encrypting the public/private extended keys.
|
// first encrypting the public/private extended keys.
|
||||||
//
|
//
|
||||||
// This method must be called with the Pool's manager unlocked.
|
// This method must be called with the Pool's manager unlocked.
|
||||||
func (p *Pool) saveSeriesToDisk(seriesID uint32, data *SeriesData) error {
|
func (p *Pool) saveSeriesToDisk(ns walletdb.ReadWriteBucket, seriesID uint32, data *SeriesData) error {
|
||||||
var err error
|
var err error
|
||||||
encryptedPubKeys := make([][]byte, len(data.publicKeys))
|
encryptedPubKeys := make([][]byte, len(data.publicKeys))
|
||||||
for i, pubKey := range data.publicKeys {
|
for i, pubKey := range data.publicKeys {
|
||||||
|
@ -230,10 +218,8 @@ func (p *Pool) saveSeriesToDisk(seriesID uint32, data *SeriesData) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = p.namespace.Update(func(tx walletdb.Tx) error {
|
err = putSeries(ns, p.ID, data.version, seriesID, data.active,
|
||||||
return putSeries(tx, p.ID, data.version, seriesID, data.active,
|
data.reqSigs, encryptedPubKeys, encryptedPrivKeys)
|
||||||
data.reqSigs, encryptedPubKeys, encryptedPrivKeys)
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
str := fmt.Sprintf("cannot put series #%d into db", seriesID)
|
str := fmt.Sprintf("cannot put series #%d into db", seriesID)
|
||||||
return newError(ErrSeriesSerialization, str, err)
|
return newError(ErrSeriesSerialization, str, err)
|
||||||
|
@ -286,7 +272,7 @@ func convertAndValidatePubKeys(rawPubKeys []string) ([]*hdkeychain.ExtendedKey,
|
||||||
// inRawPubKeys.
|
// inRawPubKeys.
|
||||||
//
|
//
|
||||||
// This method must be called with the Pool's manager unlocked.
|
// This method must be called with the Pool's manager unlocked.
|
||||||
func (p *Pool) putSeries(version, seriesID, reqSigs uint32, inRawPubKeys []string) error {
|
func (p *Pool) putSeries(ns walletdb.ReadWriteBucket, version, seriesID, reqSigs uint32, inRawPubKeys []string) error {
|
||||||
if len(inRawPubKeys) < minSeriesPubKeys {
|
if len(inRawPubKeys) < minSeriesPubKeys {
|
||||||
str := fmt.Sprintf("need at least %d public keys to create a series", minSeriesPubKeys)
|
str := fmt.Sprintf("need at least %d public keys to create a series", minSeriesPubKeys)
|
||||||
return newError(ErrTooFewPublicKeys, str, nil)
|
return newError(ErrTooFewPublicKeys, str, nil)
|
||||||
|
@ -313,7 +299,7 @@ func (p *Pool) putSeries(version, seriesID, reqSigs uint32, inRawPubKeys []strin
|
||||||
privateKeys: make([]*hdkeychain.ExtendedKey, len(keys)),
|
privateKeys: make([]*hdkeychain.ExtendedKey, len(keys)),
|
||||||
}
|
}
|
||||||
|
|
||||||
err = p.saveSeriesToDisk(seriesID, data)
|
err = p.saveSeriesToDisk(ns, seriesID, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -326,7 +312,7 @@ func (p *Pool) putSeries(version, seriesID, reqSigs uint32, inRawPubKeys []strin
|
||||||
// - seriesID must be greater than or equal 1;
|
// - seriesID must be greater than or equal 1;
|
||||||
// - rawPubKeys has to contain three or more public keys;
|
// - rawPubKeys has to contain three or more public keys;
|
||||||
// - reqSigs has to be less or equal than the number of public keys in rawPubKeys.
|
// - reqSigs has to be less or equal than the number of public keys in rawPubKeys.
|
||||||
func (p *Pool) CreateSeries(version, seriesID, reqSigs uint32, rawPubKeys []string) error {
|
func (p *Pool) CreateSeries(ns walletdb.ReadWriteBucket, version, seriesID, reqSigs uint32, rawPubKeys []string) error {
|
||||||
if seriesID == 0 {
|
if seriesID == 0 {
|
||||||
return newError(ErrSeriesIDInvalid, "series ID cannot be 0", nil)
|
return newError(ErrSeriesIDInvalid, "series ID cannot be 0", nil)
|
||||||
}
|
}
|
||||||
|
@ -344,18 +330,18 @@ func (p *Pool) CreateSeries(version, seriesID, reqSigs uint32, rawPubKeys []stri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.putSeries(version, seriesID, reqSigs, rawPubKeys)
|
return p.putSeries(ns, version, seriesID, reqSigs, rawPubKeys)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ActivateSeries marks the series with the given ID as active.
|
// ActivateSeries marks the series with the given ID as active.
|
||||||
func (p *Pool) ActivateSeries(seriesID uint32) error {
|
func (p *Pool) ActivateSeries(ns walletdb.ReadWriteBucket, seriesID uint32) error {
|
||||||
series := p.Series(seriesID)
|
series := p.Series(seriesID)
|
||||||
if series == nil {
|
if series == nil {
|
||||||
str := fmt.Sprintf("series #%d does not exist, cannot activate it", seriesID)
|
str := fmt.Sprintf("series #%d does not exist, cannot activate it", seriesID)
|
||||||
return newError(ErrSeriesNotExists, str, nil)
|
return newError(ErrSeriesNotExists, str, nil)
|
||||||
}
|
}
|
||||||
series.active = true
|
series.active = true
|
||||||
err := p.saveSeriesToDisk(seriesID, series)
|
err := p.saveSeriesToDisk(ns, seriesID, series)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -367,7 +353,7 @@ func (p *Pool) ActivateSeries(seriesID uint32) error {
|
||||||
//
|
//
|
||||||
// - rawPubKeys has to contain three or more public keys
|
// - rawPubKeys has to contain three or more public keys
|
||||||
// - reqSigs has to be less or equal than the number of public keys in rawPubKeys.
|
// - reqSigs has to be less or equal than the number of public keys in rawPubKeys.
|
||||||
func (p *Pool) ReplaceSeries(version, seriesID, reqSigs uint32, rawPubKeys []string) error {
|
func (p *Pool) ReplaceSeries(ns walletdb.ReadWriteBucket, version, seriesID, reqSigs uint32, rawPubKeys []string) error {
|
||||||
series := p.Series(seriesID)
|
series := p.Series(seriesID)
|
||||||
if series == nil {
|
if series == nil {
|
||||||
str := fmt.Sprintf("series #%d does not exist, cannot replace it", seriesID)
|
str := fmt.Sprintf("series #%d does not exist, cannot replace it", seriesID)
|
||||||
|
@ -379,7 +365,7 @@ func (p *Pool) ReplaceSeries(version, seriesID, reqSigs uint32, rawPubKeys []str
|
||||||
return newError(ErrSeriesAlreadyEmpowered, str, nil)
|
return newError(ErrSeriesAlreadyEmpowered, str, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.putSeries(version, seriesID, reqSigs, rawPubKeys)
|
return p.putSeries(ns, version, seriesID, reqSigs, rawPubKeys)
|
||||||
}
|
}
|
||||||
|
|
||||||
// decryptExtendedKey uses Manager.Decrypt() to decrypt the encrypted byte slice and return
|
// decryptExtendedKey uses Manager.Decrypt() to decrypt the encrypted byte slice and return
|
||||||
|
@ -459,13 +445,8 @@ func validateAndDecryptKeys(rawPubKeys, rawPrivKeys [][]byte, p *Pool) (pubKeys,
|
||||||
// This method must be called with the Pool's manager unlocked.
|
// This method must be called with the Pool's manager unlocked.
|
||||||
// FIXME: We should be able to get rid of this (and loadAllSeries/seriesLookup)
|
// FIXME: We should be able to get rid of this (and loadAllSeries/seriesLookup)
|
||||||
// by making Series() load the series data directly from the DB.
|
// by making Series() load the series data directly from the DB.
|
||||||
func (p *Pool) LoadAllSeries() error {
|
func (p *Pool) LoadAllSeries(ns walletdb.ReadBucket) error {
|
||||||
var series map[uint32]*dbSeriesRow
|
series, err := loadAllSeries(ns, p.ID)
|
||||||
err := p.namespace.View(func(tx walletdb.Tx) error {
|
|
||||||
var err error
|
|
||||||
series, err = loadAllSeries(tx, p.ID)
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -620,10 +601,10 @@ func (p *Pool) ChangeAddress(seriesID uint32, index Index) (*ChangeAddress, erro
|
||||||
// processing withdrawals we may iterate over a huge number of addresses and
|
// processing withdrawals we may iterate over a huge number of addresses and
|
||||||
// it'd be too expensive to re-generate the redeem script for all of them.
|
// it'd be too expensive to re-generate the redeem script for all of them.
|
||||||
// This method must be called with the manager unlocked.
|
// This method must be called with the manager unlocked.
|
||||||
func (p *Pool) WithdrawalAddress(seriesID uint32, branch Branch, index Index) (
|
func (p *Pool) WithdrawalAddress(ns, addrmgrNs walletdb.ReadBucket, seriesID uint32, branch Branch, index Index) (
|
||||||
*WithdrawalAddress, error) {
|
*WithdrawalAddress, error) {
|
||||||
// TODO: Ensure the given series is hot.
|
// TODO: Ensure the given series is hot.
|
||||||
addr, err := p.getUsedAddr(seriesID, branch, index)
|
addr, err := p.getUsedAddr(ns, addrmgrNs, seriesID, branch, index)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -661,7 +642,7 @@ func (p *Pool) poolAddress(seriesID uint32, branch Branch, index Index, script [
|
||||||
// private extended key and must match one of the series' extended public keys.
|
// private extended key and must match one of the series' extended public keys.
|
||||||
//
|
//
|
||||||
// This method must be called with the Pool's manager unlocked.
|
// This method must be called with the Pool's manager unlocked.
|
||||||
func (p *Pool) EmpowerSeries(seriesID uint32, rawPrivKey string) error {
|
func (p *Pool) EmpowerSeries(ns walletdb.ReadWriteBucket, seriesID uint32, rawPrivKey string) error {
|
||||||
// make sure this series exists
|
// make sure this series exists
|
||||||
series := p.Series(seriesID)
|
series := p.Series(seriesID)
|
||||||
if series == nil {
|
if series == nil {
|
||||||
|
@ -708,7 +689,7 @@ func (p *Pool) EmpowerSeries(seriesID uint32, rawPrivKey string) error {
|
||||||
return newError(ErrKeysPrivatePublicMismatch, str, nil)
|
return newError(ErrKeysPrivatePublicMismatch, str, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = p.saveSeriesToDisk(seriesID, series); err != nil {
|
if err = p.saveSeriesToDisk(ns, seriesID, series); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -718,8 +699,8 @@ func (p *Pool) EmpowerSeries(seriesID uint32, rawPrivKey string) error {
|
||||||
// EnsureUsedAddr ensures we have entries in our used addresses DB for the given
|
// EnsureUsedAddr ensures we have entries in our used addresses DB for the given
|
||||||
// seriesID, branch and all indices up to the given one. It must be called with
|
// seriesID, branch and all indices up to the given one. It must be called with
|
||||||
// the manager unlocked.
|
// the manager unlocked.
|
||||||
func (p *Pool) EnsureUsedAddr(seriesID uint32, branch Branch, index Index) error {
|
func (p *Pool) EnsureUsedAddr(ns, addrmgrNs walletdb.ReadWriteBucket, seriesID uint32, branch Branch, index Index) error {
|
||||||
lastIdx, err := p.highestUsedIndexFor(seriesID, branch)
|
lastIdx, err := p.highestUsedIndexFor(ns, seriesID, branch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -727,13 +708,13 @@ func (p *Pool) EnsureUsedAddr(seriesID uint32, branch Branch, index Index) error
|
||||||
// highestUsedIndexFor() returns 0 when there are no used addresses for a
|
// highestUsedIndexFor() returns 0 when there are no used addresses for a
|
||||||
// given seriesID/branch, so we do this to ensure there is an entry with
|
// given seriesID/branch, so we do this to ensure there is an entry with
|
||||||
// index==0.
|
// index==0.
|
||||||
if err := p.addUsedAddr(seriesID, branch, lastIdx); err != nil {
|
if err := p.addUsedAddr(ns, addrmgrNs, seriesID, branch, lastIdx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lastIdx++
|
lastIdx++
|
||||||
for lastIdx <= index {
|
for lastIdx <= index {
|
||||||
if err := p.addUsedAddr(seriesID, branch, lastIdx); err != nil {
|
if err := p.addUsedAddr(ns, addrmgrNs, seriesID, branch, lastIdx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
lastIdx++
|
lastIdx++
|
||||||
|
@ -744,7 +725,7 @@ func (p *Pool) EnsureUsedAddr(seriesID uint32, branch Branch, index Index) error
|
||||||
// addUsedAddr creates a deposit script for the given seriesID/branch/index,
|
// addUsedAddr creates a deposit script for the given seriesID/branch/index,
|
||||||
// ensures it is imported into the address manager and finaly adds the script
|
// ensures it is imported into the address manager and finaly adds the script
|
||||||
// hash to our used addresses DB. It must be called with the manager unlocked.
|
// hash to our used addresses DB. It must be called with the manager unlocked.
|
||||||
func (p *Pool) addUsedAddr(seriesID uint32, branch Branch, index Index) error {
|
func (p *Pool) addUsedAddr(ns, addrmgrNs walletdb.ReadWriteBucket, seriesID uint32, branch Branch, index Index) error {
|
||||||
script, err := p.DepositScript(seriesID, branch, index)
|
script, err := p.DepositScript(seriesID, branch, index)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -754,7 +735,7 @@ func (p *Pool) addUsedAddr(seriesID uint32, branch Branch, index Index) error {
|
||||||
// to have it in the used addresses DB but not in the address manager.
|
// to have it in the used addresses DB but not in the address manager.
|
||||||
// TODO: Decide how far back we want the addr manager to rescan and set the
|
// TODO: Decide how far back we want the addr manager to rescan and set the
|
||||||
// BlockStamp height according to that.
|
// BlockStamp height according to that.
|
||||||
_, err = p.manager.ImportScript(script, &waddrmgr.BlockStamp{})
|
_, err = p.manager.ImportScript(addrmgrNs, script, &waddrmgr.BlockStamp{})
|
||||||
if err != nil && err.(waddrmgr.ManagerError).ErrorCode != waddrmgr.ErrDuplicateAddress {
|
if err != nil && err.(waddrmgr.ManagerError).ErrorCode != waddrmgr.ErrDuplicateAddress {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -763,10 +744,7 @@ func (p *Pool) addUsedAddr(seriesID uint32, branch Branch, index Index) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newError(ErrCrypto, "failed to encrypt script hash", err)
|
return newError(ErrCrypto, "failed to encrypt script hash", err)
|
||||||
}
|
}
|
||||||
err = p.namespace.Update(
|
err = putUsedAddrHash(ns, p.ID, seriesID, branch, index, encryptedHash)
|
||||||
func(tx walletdb.Tx) error {
|
|
||||||
return putUsedAddrHash(tx, p.ID, seriesID, branch, index, encryptedHash)
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newError(ErrDatabase, "failed to store used addr script hash", err)
|
return newError(ErrDatabase, "failed to store used addr script hash", err)
|
||||||
}
|
}
|
||||||
|
@ -777,19 +755,11 @@ func (p *Pool) addUsedAddr(seriesID uint32, branch Branch, index Index) error {
|
||||||
// getUsedAddr gets the script hash for the given series, branch and index from
|
// getUsedAddr gets the script hash for the given series, branch and index from
|
||||||
// the used addresses DB and uses that to look up the ManagedScriptAddress
|
// the used addresses DB and uses that to look up the ManagedScriptAddress
|
||||||
// from the address manager. It must be called with the manager unlocked.
|
// from the address manager. It must be called with the manager unlocked.
|
||||||
func (p *Pool) getUsedAddr(seriesID uint32, branch Branch, index Index) (
|
func (p *Pool) getUsedAddr(ns, addrmgrNs walletdb.ReadBucket, seriesID uint32, branch Branch, index Index) (
|
||||||
waddrmgr.ManagedScriptAddress, error) {
|
waddrmgr.ManagedScriptAddress, error) {
|
||||||
|
|
||||||
mgr := p.manager
|
mgr := p.manager
|
||||||
var encryptedHash []byte
|
encryptedHash := getUsedAddrHash(ns, p.ID, seriesID, branch, index)
|
||||||
err := p.namespace.View(
|
|
||||||
func(tx walletdb.Tx) error {
|
|
||||||
encryptedHash = getUsedAddrHash(tx, p.ID, seriesID, branch, index)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError(ErrDatabase, "failed to lookup script hash for used addr", err)
|
|
||||||
}
|
|
||||||
if encryptedHash == nil {
|
if encryptedHash == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
@ -801,7 +771,7 @@ func (p *Pool) getUsedAddr(seriesID uint32, branch Branch, index Index) (
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, newError(ErrInvalidScriptHash, "failed to parse script hash", err)
|
return nil, newError(ErrInvalidScriptHash, "failed to parse script hash", err)
|
||||||
}
|
}
|
||||||
mAddr, err := mgr.Address(addr)
|
mAddr, err := mgr.Address(addrmgrNs, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -811,15 +781,8 @@ func (p *Pool) getUsedAddr(seriesID uint32, branch Branch, index Index) (
|
||||||
// highestUsedIndexFor returns the highest index from this Pool's used addresses
|
// highestUsedIndexFor returns the highest index from this Pool's used addresses
|
||||||
// with the given seriesID and branch. It returns 0 if there are no used
|
// with the given seriesID and branch. It returns 0 if there are no used
|
||||||
// addresses with the given seriesID and branch.
|
// addresses with the given seriesID and branch.
|
||||||
func (p *Pool) highestUsedIndexFor(seriesID uint32, branch Branch) (Index, error) {
|
func (p *Pool) highestUsedIndexFor(ns walletdb.ReadBucket, seriesID uint32, branch Branch) (Index, error) {
|
||||||
maxIdx := Index(0)
|
return getMaxUsedIdx(ns, p.ID, seriesID, branch)
|
||||||
err := p.namespace.View(
|
|
||||||
func(tx walletdb.Tx) error {
|
|
||||||
var err error
|
|
||||||
maxIdx, err = getMaxUsedIdx(tx, p.ID, seriesID, branch)
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
return maxIdx, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a string encoding of the underlying bitcoin payment address.
|
// String returns a string encoding of the underlying bitcoin payment address.
|
||||||
|
|
|
@ -149,17 +149,17 @@ func (s outputStatus) String() string {
|
||||||
return strings[s]
|
return strings[s]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *changeAwareTx) addSelfToStore(store *wtxmgr.Store) error {
|
func (tx *changeAwareTx) addSelfToStore(store *wtxmgr.Store, txmgrNs walletdb.ReadWriteBucket) error {
|
||||||
rec, err := wtxmgr.NewTxRecordFromMsgTx(tx.MsgTx, time.Now())
|
rec, err := wtxmgr.NewTxRecordFromMsgTx(tx.MsgTx, time.Now())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newError(ErrWithdrawalTxStorage, "error constructing TxRecord for storing", err)
|
return newError(ErrWithdrawalTxStorage, "error constructing TxRecord for storing", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.InsertTx(rec, nil); err != nil {
|
if err := store.InsertTx(txmgrNs, rec, nil); err != nil {
|
||||||
return newError(ErrWithdrawalTxStorage, "error adding tx to store", err)
|
return newError(ErrWithdrawalTxStorage, "error adding tx to store", err)
|
||||||
}
|
}
|
||||||
if tx.changeIdx != -1 {
|
if tx.changeIdx != -1 {
|
||||||
if err = store.AddCredit(rec, nil, uint32(tx.changeIdx), true); err != nil {
|
if err = store.AddCredit(txmgrNs, rec, nil, uint32(tx.changeIdx), true); err != nil {
|
||||||
return newError(ErrWithdrawalTxStorage, "error adding tx credits to store", err)
|
return newError(ErrWithdrawalTxStorage, "error adding tx credits to store", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -477,12 +477,12 @@ func newWithdrawal(roundID uint32, requests []OutputRequest, inputs []credit,
|
||||||
// of those transaction's inputs. More details about the actual algorithm can be
|
// of those transaction's inputs. More details about the actual algorithm can be
|
||||||
// found at http://opentransactions.org/wiki/index.php/Startwithdrawal
|
// found at http://opentransactions.org/wiki/index.php/Startwithdrawal
|
||||||
// This method must be called with the address manager unlocked.
|
// This method must be called with the address manager unlocked.
|
||||||
func (p *Pool) StartWithdrawal(roundID uint32, requests []OutputRequest,
|
func (p *Pool) StartWithdrawal(ns walletdb.ReadWriteBucket, addrmgrNs walletdb.ReadBucket, roundID uint32, requests []OutputRequest,
|
||||||
startAddress WithdrawalAddress, lastSeriesID uint32, changeStart ChangeAddress,
|
startAddress WithdrawalAddress, lastSeriesID uint32, changeStart ChangeAddress,
|
||||||
txStore *wtxmgr.Store, chainHeight int32, dustThreshold btcutil.Amount) (
|
txStore *wtxmgr.Store, txmgrNs walletdb.ReadBucket, chainHeight int32, dustThreshold btcutil.Amount) (
|
||||||
*WithdrawalStatus, error) {
|
*WithdrawalStatus, error) {
|
||||||
|
|
||||||
status, err := getWithdrawalStatus(p, roundID, requests, startAddress, lastSeriesID,
|
status, err := getWithdrawalStatus(p, ns, addrmgrNs, roundID, requests, startAddress, lastSeriesID,
|
||||||
changeStart, dustThreshold)
|
changeStart, dustThreshold)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -491,7 +491,7 @@ func (p *Pool) StartWithdrawal(roundID uint32, requests []OutputRequest,
|
||||||
return status, nil
|
return status, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
eligible, err := p.getEligibleInputs(txStore, startAddress, lastSeriesID, dustThreshold,
|
eligible, err := p.getEligibleInputs(ns, addrmgrNs, txStore, txmgrNs, startAddress, lastSeriesID, dustThreshold,
|
||||||
chainHeight, eligibleInputMinConfirmations)
|
chainHeight, eligibleInputMinConfirmations)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -511,10 +511,7 @@ func (p *Pool) StartWithdrawal(roundID uint32, requests []OutputRequest,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = p.namespace.Update(
|
err = putWithdrawal(ns, p.ID, roundID, serialized)
|
||||||
func(tx walletdb.Tx) error {
|
|
||||||
return putWithdrawal(tx, p.ID, roundID, serialized)
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -819,23 +816,15 @@ func (wi *withdrawalInfo) match(requests []OutputRequest, startAddress Withdrawa
|
||||||
// getWithdrawalStatus returns the existing WithdrawalStatus for the given
|
// getWithdrawalStatus returns the existing WithdrawalStatus for the given
|
||||||
// withdrawal parameters, if one exists. This function must be called with the
|
// withdrawal parameters, if one exists. This function must be called with the
|
||||||
// address manager unlocked.
|
// address manager unlocked.
|
||||||
func getWithdrawalStatus(p *Pool, roundID uint32, requests []OutputRequest,
|
func getWithdrawalStatus(p *Pool, ns, addrmgrNs walletdb.ReadBucket, roundID uint32, requests []OutputRequest,
|
||||||
startAddress WithdrawalAddress, lastSeriesID uint32, changeStart ChangeAddress,
|
startAddress WithdrawalAddress, lastSeriesID uint32, changeStart ChangeAddress,
|
||||||
dustThreshold btcutil.Amount) (*WithdrawalStatus, error) {
|
dustThreshold btcutil.Amount) (*WithdrawalStatus, error) {
|
||||||
|
|
||||||
var serialized []byte
|
serialized := getWithdrawal(ns, p.ID, roundID)
|
||||||
err := p.namespace.View(
|
|
||||||
func(tx walletdb.Tx) error {
|
|
||||||
serialized = getWithdrawal(tx, p.ID, roundID)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if bytes.Equal(serialized, []byte{}) {
|
if bytes.Equal(serialized, []byte{}) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
wInfo, err := deserializeWithdrawal(p, serialized)
|
wInfo, err := deserializeWithdrawal(p, ns, addrmgrNs, serialized)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -907,19 +896,19 @@ func getRawSigs(transactions []*withdrawalTx) (map[Ntxid]TxSigs, error) {
|
||||||
// manager) the redeem script for each of them and constructing the signature
|
// manager) the redeem script for each of them and constructing the signature
|
||||||
// script using that and the given raw signatures.
|
// script using that and the given raw signatures.
|
||||||
// This function must be called with the manager unlocked.
|
// This function must be called with the manager unlocked.
|
||||||
func SignTx(msgtx *wire.MsgTx, sigs TxSigs, mgr *waddrmgr.Manager, store *wtxmgr.Store) error {
|
func SignTx(msgtx *wire.MsgTx, sigs TxSigs, mgr *waddrmgr.Manager, addrmgrNs walletdb.ReadBucket, store *wtxmgr.Store, txmgrNs walletdb.ReadBucket) error {
|
||||||
// We use time.Now() here as we're not going to store the new TxRecord
|
// We use time.Now() here as we're not going to store the new TxRecord
|
||||||
// anywhere -- we just need it to pass to store.PreviousPkScripts().
|
// anywhere -- we just need it to pass to store.PreviousPkScripts().
|
||||||
rec, err := wtxmgr.NewTxRecordFromMsgTx(msgtx, time.Now())
|
rec, err := wtxmgr.NewTxRecordFromMsgTx(msgtx, time.Now())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newError(ErrTxSigning, "failed to construct TxRecord for signing", err)
|
return newError(ErrTxSigning, "failed to construct TxRecord for signing", err)
|
||||||
}
|
}
|
||||||
pkScripts, err := store.PreviousPkScripts(rec, nil)
|
pkScripts, err := store.PreviousPkScripts(txmgrNs, rec, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newError(ErrTxSigning, "failed to obtain pkScripts for signing", err)
|
return newError(ErrTxSigning, "failed to obtain pkScripts for signing", err)
|
||||||
}
|
}
|
||||||
for i, pkScript := range pkScripts {
|
for i, pkScript := range pkScripts {
|
||||||
if err = signMultiSigUTXO(mgr, msgtx, i, pkScript, sigs[i]); err != nil {
|
if err = signMultiSigUTXO(mgr, addrmgrNs, msgtx, i, pkScript, sigs[i]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -928,8 +917,8 @@ func SignTx(msgtx *wire.MsgTx, sigs TxSigs, mgr *waddrmgr.Manager, store *wtxmgr
|
||||||
|
|
||||||
// getRedeemScript returns the redeem script for the given P2SH address. It must
|
// getRedeemScript returns the redeem script for the given P2SH address. It must
|
||||||
// be called with the manager unlocked.
|
// be called with the manager unlocked.
|
||||||
func getRedeemScript(mgr *waddrmgr.Manager, addr *btcutil.AddressScriptHash) ([]byte, error) {
|
func getRedeemScript(mgr *waddrmgr.Manager, addrmgrNs walletdb.ReadBucket, addr *btcutil.AddressScriptHash) ([]byte, error) {
|
||||||
address, err := mgr.Address(addr)
|
address, err := mgr.Address(addrmgrNs, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -943,7 +932,7 @@ func getRedeemScript(mgr *waddrmgr.Manager, addr *btcutil.AddressScriptHash) ([]
|
||||||
// The order of the signatures must match that of the public keys in the multi-sig
|
// The order of the signatures must match that of the public keys in the multi-sig
|
||||||
// script as OP_CHECKMULTISIG expects that.
|
// script as OP_CHECKMULTISIG expects that.
|
||||||
// This function must be called with the manager unlocked.
|
// This function must be called with the manager unlocked.
|
||||||
func signMultiSigUTXO(mgr *waddrmgr.Manager, tx *wire.MsgTx, idx int, pkScript []byte, sigs []RawSig) error {
|
func signMultiSigUTXO(mgr *waddrmgr.Manager, addrmgrNs walletdb.ReadBucket, tx *wire.MsgTx, idx int, pkScript []byte, sigs []RawSig) error {
|
||||||
class, addresses, _, err := txscript.ExtractPkScriptAddrs(pkScript, mgr.ChainParams())
|
class, addresses, _, err := txscript.ExtractPkScriptAddrs(pkScript, mgr.ChainParams())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newError(ErrTxSigning, "unparseable pkScript", err)
|
return newError(ErrTxSigning, "unparseable pkScript", err)
|
||||||
|
@ -951,7 +940,7 @@ func signMultiSigUTXO(mgr *waddrmgr.Manager, tx *wire.MsgTx, idx int, pkScript [
|
||||||
if class != txscript.ScriptHashTy {
|
if class != txscript.ScriptHashTy {
|
||||||
return newError(ErrTxSigning, fmt.Sprintf("pkScript is not P2SH: %s", class), nil)
|
return newError(ErrTxSigning, fmt.Sprintf("pkScript is not P2SH: %s", class), nil)
|
||||||
}
|
}
|
||||||
redeemScript, err := getRedeemScript(mgr, addresses[0].(*btcutil.AddressScriptHash))
|
redeemScript, err := getRedeemScript(mgr, addrmgrNs, addresses[0].(*btcutil.AddressScriptHash))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newError(ErrTxSigning, "unable to retrieve redeem script", err)
|
return newError(ErrTxSigning, "unable to retrieve redeem script", err)
|
||||||
}
|
}
|
||||||
|
@ -1047,9 +1036,9 @@ func nextChangeAddress(a ChangeAddress) (ChangeAddress, error) {
|
||||||
return *addr, err
|
return *addr, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func storeTransactions(store *wtxmgr.Store, transactions []*changeAwareTx) error {
|
func storeTransactions(store *wtxmgr.Store, txmgrNs walletdb.ReadWriteBucket, transactions []*changeAwareTx) error {
|
||||||
for _, tx := range transactions {
|
for _, tx := range transactions {
|
||||||
if err := tx.addSelfToStore(store); err != nil {
|
if err := tx.addSelfToStore(store, txmgrNs); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue