Make votingpool package (sans tests) compile
This commit is contained in:
parent
4656a00705
commit
f143d095d6
|
@ -117,10 +117,10 @@ func getUsedAddrBucketID(seriesID uint32, branch Branch) []byte {
|
|||
|
||||
// putUsedAddrHash adds an entry (key==index, value==encryptedHash) to the used
|
||||
// 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 {
|
||||
|
||||
usedAddrs := tx.RootBucket().Bucket(poolID).Bucket(usedAddrsBucketName)
|
||||
usedAddrs := ns.NestedReadWriteBucket(poolID).NestedReadWriteBucket(usedAddrsBucketName)
|
||||
bucket, err := usedAddrs.CreateBucketIfNotExists(getUsedAddrBucketID(seriesID, branch))
|
||||
if err != nil {
|
||||
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
|
||||
// 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 {
|
||||
|
||||
usedAddrs := tx.RootBucket().Bucket(poolID).Bucket(usedAddrsBucketName)
|
||||
bucket := usedAddrs.Bucket(getUsedAddrBucketID(seriesID, branch))
|
||||
usedAddrs := ns.NestedReadBucket(poolID).NestedReadBucket(usedAddrsBucketName)
|
||||
bucket := usedAddrs.NestedReadBucket(getUsedAddrBucketID(seriesID, branch))
|
||||
if bucket == 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
|
||||
// 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)
|
||||
usedAddrs := tx.RootBucket().Bucket(poolID).Bucket(usedAddrsBucketName)
|
||||
bucket := usedAddrs.Bucket(getUsedAddrBucketID(seriesID, branch))
|
||||
usedAddrs := ns.NestedReadBucket(poolID).NestedReadBucket(usedAddrsBucketName)
|
||||
bucket := usedAddrs.NestedReadBucket(getUsedAddrBucketID(seriesID, branch))
|
||||
if bucket == 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
|
||||
// after the voting pool id and two other buckets inside it to store series and
|
||||
// used addresses for that pool.
|
||||
func putPool(tx walletdb.Tx, poolID []byte) error {
|
||||
poolBucket, err := tx.RootBucket().CreateBucket(poolID)
|
||||
func putPool(ns walletdb.ReadWriteBucket, poolID []byte) error {
|
||||
poolBucket, err := ns.CreateBucket(poolID)
|
||||
if err != nil {
|
||||
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
|
||||
// bucket, keyed by id.
|
||||
func loadAllSeries(tx walletdb.Tx, poolID []byte) (map[uint32]*dbSeriesRow, error) {
|
||||
bucket := tx.RootBucket().Bucket(poolID).Bucket(seriesBucketName)
|
||||
func loadAllSeries(ns walletdb.ReadBucket, poolID []byte) (map[uint32]*dbSeriesRow, error) {
|
||||
bucket := ns.NestedReadBucket(poolID).NestedReadBucket(seriesBucketName)
|
||||
allSeries := make(map[uint32]*dbSeriesRow)
|
||||
err := bucket.ForEach(
|
||||
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
|
||||
// voting pool id.
|
||||
func existsPool(tx walletdb.Tx, poolID []byte) bool {
|
||||
bucket := tx.RootBucket().Bucket(poolID)
|
||||
func existsPool(ns walletdb.ReadBucket, poolID []byte) bool {
|
||||
bucket := ns.NestedReadBucket(poolID)
|
||||
return bucket != nil
|
||||
}
|
||||
|
||||
// putSeries stores the given series inside a voting pool bucket named after
|
||||
// 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{
|
||||
version: version,
|
||||
active: active,
|
||||
|
@ -234,19 +234,22 @@ func putSeries(tx walletdb.Tx, poolID []byte, version, ID uint32, active bool, r
|
|||
pubKeysEncrypted: pubKeysEncrypted,
|
||||
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
|
||||
// after poolID. The voting pool bucket does not need to be created
|
||||
// beforehand.
|
||||
func putSeriesRow(tx walletdb.Tx, poolID []byte, ID uint32, row *dbSeriesRow) error {
|
||||
bucket, err := tx.RootBucket().CreateBucketIfNotExists(poolID)
|
||||
func putSeriesRow(ns walletdb.ReadWriteBucket, poolID []byte, ID uint32, row *dbSeriesRow) error {
|
||||
bucket, err := ns.CreateBucketIfNotExists(poolID)
|
||||
if err != nil {
|
||||
str := fmt.Sprintf("cannot create bucket %v", poolID)
|
||||
return newError(ErrDatabase, str, err)
|
||||
}
|
||||
bucket = bucket.Bucket(seriesBucketName)
|
||||
bucket, err = bucket.CreateBucketIfNotExists(seriesBucketName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
serialized, err := serializeSeriesRow(row)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -473,7 +476,7 @@ func serializeWithdrawal(requests []OutputRequest, startAddress WithdrawalAddres
|
|||
// deserializeWithdrawal deserializes the given byte slice into a dbWithdrawalRow,
|
||||
// converts it into an withdrawalInfo and returns it. This function must run
|
||||
// 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
|
||||
if err := gob.NewDecoder(bytes.NewReader(serialized)).Decode(&row); err != nil {
|
||||
return nil, newError(ErrWithdrawalStorage, "cannot deserialize withdrawal information",
|
||||
|
@ -509,7 +512,7 @@ func deserializeWithdrawal(p *Pool, serialized []byte) (*withdrawalInfo, error)
|
|||
requestsByOID[request.outBailmentID()] = request
|
||||
}
|
||||
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 {
|
||||
return nil, newError(ErrWithdrawalStorage, "cannot deserialize startAddress", err)
|
||||
}
|
||||
|
@ -564,13 +567,13 @@ func deserializeWithdrawal(p *Pool, serialized []byte) (*withdrawalInfo, error)
|
|||
return wInfo, nil
|
||||
}
|
||||
|
||||
func putWithdrawal(tx walletdb.Tx, poolID []byte, roundID uint32, serialized []byte) error {
|
||||
bucket := tx.RootBucket().Bucket(poolID)
|
||||
func putWithdrawal(ns walletdb.ReadWriteBucket, poolID []byte, roundID uint32, serialized []byte) error {
|
||||
bucket := ns.NestedReadWriteBucket(poolID)
|
||||
return bucket.Put(uint32ToBytes(roundID), serialized)
|
||||
}
|
||||
|
||||
func getWithdrawal(tx walletdb.Tx, poolID []byte, roundID uint32) []byte {
|
||||
bucket := tx.RootBucket().Bucket(poolID)
|
||||
func getWithdrawal(ns walletdb.ReadBucket, poolID []byte, roundID uint32) []byte {
|
||||
bucket := ns.NestedReadBucket(poolID)
|
||||
return bucket.Get(uint32ToBytes(roundID))
|
||||
}
|
||||
|
||||
|
|
|
@ -21,10 +21,11 @@ import (
|
|||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/roasbeef/btcd/chaincfg"
|
||||
"github.com/roasbeef/btcd/txscript"
|
||||
"github.com/roasbeef/btcutil"
|
||||
"github.com/roasbeef/btcwallet/wtxmgr"
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/btcsuite/btcwallet/walletdb"
|
||||
"github.com/btcsuite/btcwallet/wtxmgr"
|
||||
)
|
||||
|
||||
const eligibleInputMinConfirmations = 100
|
||||
|
@ -98,7 +99,7 @@ func (c byAddress) Less(i, j int) bool {
|
|||
// getEligibleInputs returns eligible inputs with addresses between startAddress
|
||||
// and the last used address of lastSeriesID. They're reverse ordered based on
|
||||
// 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,
|
||||
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)
|
||||
return nil, newError(ErrSeriesNotExists, str, nil)
|
||||
}
|
||||
unspents, err := store.UnspentOutputs()
|
||||
unspents, err := store.UnspentOutputs(txmgrNs)
|
||||
if err != nil {
|
||||
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...)
|
||||
}
|
||||
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 {
|
||||
return nil, newError(ErrInputSelection, "failed to get next withdrawal address", err)
|
||||
} 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
|
||||
// rules: http://opentransactions.org/wiki/index.php/Input_Selection_Algorithm_(voting_pools)
|
||||
// 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) {
|
||||
series := p.Series(seriesID)
|
||||
if series == nil {
|
||||
|
@ -152,7 +153,7 @@ func nextAddr(p *Pool, seriesID uint32, branch Branch, index Index, stopSeriesID
|
|||
}
|
||||
branch++
|
||||
if int(branch) > len(series.publicKeys) {
|
||||
highestIdx, err := p.highestUsedSeriesIndex(seriesID)
|
||||
highestIdx, err := p.highestUsedSeriesIndex(ns, seriesID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -171,14 +172,14 @@ func nextAddr(p *Pool, seriesID uint32, branch Branch, index Index, stopSeriesID
|
|||
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 {
|
||||
// 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
|
||||
// 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 "+
|
||||
"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
|
||||
}
|
||||
|
@ -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
|
||||
// used addresses for the given seriesID. It returns 0 if there are no used
|
||||
// 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)
|
||||
series := p.Series(seriesID)
|
||||
if series == nil {
|
||||
|
@ -194,7 +195,7 @@ func (p *Pool) highestUsedSeriesIndex(seriesID uint32) (Index, error) {
|
|||
newError(ErrSeriesNotExists, fmt.Sprintf("unknown seriesID: %d", seriesID), nil)
|
||||
}
|
||||
for i := range series.publicKeys {
|
||||
idx, err := p.highestUsedIndexFor(seriesID, Branch(i))
|
||||
idx, err := p.highestUsedIndexFor(ns, seriesID, Branch(i))
|
||||
if err != nil {
|
||||
return Index(0), err
|
||||
}
|
||||
|
|
|
@ -48,7 +48,6 @@ type Pool struct {
|
|||
ID []byte
|
||||
seriesLookup map[uint32]*SeriesData
|
||||
manager *waddrmgr.Manager
|
||||
namespace walletdb.Namespace
|
||||
}
|
||||
|
||||
// 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
|
||||
// and returns the Pool representing it.
|
||||
func Create(namespace walletdb.Namespace, m *waddrmgr.Manager, poolID []byte) (*Pool, error) {
|
||||
err := namespace.Update(
|
||||
func(tx walletdb.Tx) error {
|
||||
return putPool(tx, poolID)
|
||||
})
|
||||
func Create(ns walletdb.ReadWriteBucket, m *waddrmgr.Manager, poolID []byte) (*Pool, error) {
|
||||
err := putPool(ns, poolID)
|
||||
if err != nil {
|
||||
str := fmt.Sprintf("unable to add voting pool %v to db", poolID)
|
||||
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
|
||||
// representing it.
|
||||
func Load(namespace walletdb.Namespace, m *waddrmgr.Manager, poolID []byte) (*Pool, error) {
|
||||
err := namespace.View(
|
||||
func(tx walletdb.Tx) error {
|
||||
if exists := existsPool(tx, poolID); !exists {
|
||||
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
|
||||
func Load(ns walletdb.ReadBucket, m *waddrmgr.Manager, poolID []byte) (*Pool, error) {
|
||||
if !existsPool(ns, poolID) {
|
||||
str := fmt.Sprintf("unable to find voting pool %v in db", poolID)
|
||||
return nil, newError(ErrPoolNotExists, str, nil)
|
||||
}
|
||||
p := newPool(namespace, m, poolID)
|
||||
if err = p.LoadAllSeries(); err != nil {
|
||||
p := newPool(m, poolID)
|
||||
if err := p.LoadAllSeries(ns); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// 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{
|
||||
ID: poolID,
|
||||
seriesLookup: make(map[uint32]*SeriesData),
|
||||
manager: m,
|
||||
namespace: namespace,
|
||||
}
|
||||
}
|
||||
|
||||
// LoadAndGetDepositScript generates and returns a deposit script for the given seriesID,
|
||||
// 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)
|
||||
p, err := Load(namespace, m, pid)
|
||||
p, err := Load(ns, m, pid)
|
||||
if err != nil {
|
||||
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
|
||||
// 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.
|
||||
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 {
|
||||
pid := []byte(poolID)
|
||||
p, err := Load(namespace, m, pid)
|
||||
p, err := Load(ns, m, pid)
|
||||
if err != nil {
|
||||
vpErr := err.(Error)
|
||||
if vpErr.ErrorCode == ErrPoolNotExists {
|
||||
p, err = Create(namespace, m, pid)
|
||||
p, err = Create(ns, m, pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -159,31 +147,31 @@ func LoadAndCreateSeries(namespace walletdb.Namespace, m *waddrmgr.Manager, vers
|
|||
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,
|
||||
// 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 {
|
||||
pid := []byte(poolID)
|
||||
p, err := Load(namespace, m, pid)
|
||||
p, err := Load(ns, m, pid)
|
||||
if err != nil {
|
||||
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,
|
||||
// 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 {
|
||||
pid := []byte(poolID)
|
||||
pool, err := Load(namespace, m, pid)
|
||||
pool, err := Load(ns, m, pid)
|
||||
if err != nil {
|
||||
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
|
||||
|
@ -205,7 +193,7 @@ func (p *Pool) Manager() *waddrmgr.Manager {
|
|||
// first encrypting the public/private extended keys.
|
||||
//
|
||||
// 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
|
||||
encryptedPubKeys := make([][]byte, len(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 {
|
||||
return putSeries(tx, p.ID, data.version, seriesID, data.active,
|
||||
data.reqSigs, encryptedPubKeys, encryptedPrivKeys)
|
||||
})
|
||||
err = putSeries(ns, p.ID, data.version, seriesID, data.active,
|
||||
data.reqSigs, encryptedPubKeys, encryptedPrivKeys)
|
||||
if err != nil {
|
||||
str := fmt.Sprintf("cannot put series #%d into db", seriesID)
|
||||
return newError(ErrSeriesSerialization, str, err)
|
||||
|
@ -286,7 +272,7 @@ func convertAndValidatePubKeys(rawPubKeys []string) ([]*hdkeychain.ExtendedKey,
|
|||
// inRawPubKeys.
|
||||
//
|
||||
// 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 {
|
||||
str := fmt.Sprintf("need at least %d public keys to create a series", minSeriesPubKeys)
|
||||
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)),
|
||||
}
|
||||
|
||||
err = p.saveSeriesToDisk(seriesID, data)
|
||||
err = p.saveSeriesToDisk(ns, seriesID, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -326,7 +312,7 @@ func (p *Pool) putSeries(version, seriesID, reqSigs uint32, inRawPubKeys []strin
|
|||
// - seriesID must be greater than or equal 1;
|
||||
// - rawPubKeys has to contain three or more public keys;
|
||||
// - 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 {
|
||||
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.
|
||||
func (p *Pool) ActivateSeries(seriesID uint32) error {
|
||||
func (p *Pool) ActivateSeries(ns walletdb.ReadWriteBucket, seriesID uint32) error {
|
||||
series := p.Series(seriesID)
|
||||
if series == nil {
|
||||
str := fmt.Sprintf("series #%d does not exist, cannot activate it", seriesID)
|
||||
return newError(ErrSeriesNotExists, str, nil)
|
||||
}
|
||||
series.active = true
|
||||
err := p.saveSeriesToDisk(seriesID, series)
|
||||
err := p.saveSeriesToDisk(ns, seriesID, series)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -367,7 +353,7 @@ func (p *Pool) ActivateSeries(seriesID uint32) error {
|
|||
//
|
||||
// - rawPubKeys has to contain three or more public keys
|
||||
// - 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)
|
||||
if series == nil {
|
||||
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 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
|
||||
|
@ -459,13 +445,8 @@ func validateAndDecryptKeys(rawPubKeys, rawPrivKeys [][]byte, p *Pool) (pubKeys,
|
|||
// This method must be called with the Pool's manager unlocked.
|
||||
// FIXME: We should be able to get rid of this (and loadAllSeries/seriesLookup)
|
||||
// by making Series() load the series data directly from the DB.
|
||||
func (p *Pool) LoadAllSeries() error {
|
||||
var series map[uint32]*dbSeriesRow
|
||||
err := p.namespace.View(func(tx walletdb.Tx) error {
|
||||
var err error
|
||||
series, err = loadAllSeries(tx, p.ID)
|
||||
return err
|
||||
})
|
||||
func (p *Pool) LoadAllSeries(ns walletdb.ReadBucket) error {
|
||||
series, err := loadAllSeries(ns, p.ID)
|
||||
if err != nil {
|
||||
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
|
||||
// it'd be too expensive to re-generate the redeem script for all of them.
|
||||
// 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) {
|
||||
// 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 {
|
||||
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.
|
||||
//
|
||||
// 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
|
||||
series := p.Series(seriesID)
|
||||
if series == nil {
|
||||
|
@ -708,7 +689,7 @@ func (p *Pool) EmpowerSeries(seriesID uint32, rawPrivKey string) error {
|
|||
return newError(ErrKeysPrivatePublicMismatch, str, nil)
|
||||
}
|
||||
|
||||
if err = p.saveSeriesToDisk(seriesID, series); err != nil {
|
||||
if err = p.saveSeriesToDisk(ns, seriesID, series); err != nil {
|
||||
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
|
||||
// seriesID, branch and all indices up to the given one. It must be called with
|
||||
// the manager unlocked.
|
||||
func (p *Pool) EnsureUsedAddr(seriesID uint32, branch Branch, index Index) error {
|
||||
lastIdx, err := p.highestUsedIndexFor(seriesID, branch)
|
||||
func (p *Pool) EnsureUsedAddr(ns, addrmgrNs walletdb.ReadWriteBucket, seriesID uint32, branch Branch, index Index) error {
|
||||
lastIdx, err := p.highestUsedIndexFor(ns, seriesID, branch)
|
||||
if err != nil {
|
||||
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
|
||||
// given seriesID/branch, so we do this to ensure there is an entry with
|
||||
// index==0.
|
||||
if err := p.addUsedAddr(seriesID, branch, lastIdx); err != nil {
|
||||
if err := p.addUsedAddr(ns, addrmgrNs, seriesID, branch, lastIdx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
lastIdx++
|
||||
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
|
||||
}
|
||||
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,
|
||||
// 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.
|
||||
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)
|
||||
if err != nil {
|
||||
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.
|
||||
// TODO: Decide how far back we want the addr manager to rescan and set the
|
||||
// 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 {
|
||||
return err
|
||||
}
|
||||
|
@ -763,10 +744,7 @@ func (p *Pool) addUsedAddr(seriesID uint32, branch Branch, index Index) error {
|
|||
if err != nil {
|
||||
return newError(ErrCrypto, "failed to encrypt script hash", err)
|
||||
}
|
||||
err = p.namespace.Update(
|
||||
func(tx walletdb.Tx) error {
|
||||
return putUsedAddrHash(tx, p.ID, seriesID, branch, index, encryptedHash)
|
||||
})
|
||||
err = putUsedAddrHash(ns, p.ID, seriesID, branch, index, encryptedHash)
|
||||
if err != nil {
|
||||
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
|
||||
// the used addresses DB and uses that to look up the ManagedScriptAddress
|
||||
// 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) {
|
||||
|
||||
mgr := p.manager
|
||||
var encryptedHash []byte
|
||||
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)
|
||||
}
|
||||
encryptedHash := getUsedAddrHash(ns, p.ID, seriesID, branch, index)
|
||||
if encryptedHash == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -801,7 +771,7 @@ func (p *Pool) getUsedAddr(seriesID uint32, branch Branch, index Index) (
|
|||
if err != nil {
|
||||
return nil, newError(ErrInvalidScriptHash, "failed to parse script hash", err)
|
||||
}
|
||||
mAddr, err := mgr.Address(addr)
|
||||
mAddr, err := mgr.Address(addrmgrNs, addr)
|
||||
if err != nil {
|
||||
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
|
||||
// with the given seriesID and branch. It returns 0 if there are no used
|
||||
// addresses with the given seriesID and branch.
|
||||
func (p *Pool) highestUsedIndexFor(seriesID uint32, branch Branch) (Index, error) {
|
||||
maxIdx := Index(0)
|
||||
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
|
||||
func (p *Pool) highestUsedIndexFor(ns walletdb.ReadBucket, seriesID uint32, branch Branch) (Index, error) {
|
||||
return getMaxUsedIdx(ns, p.ID, seriesID, branch)
|
||||
}
|
||||
|
||||
// String returns a string encoding of the underlying bitcoin payment address.
|
||||
|
|
|
@ -149,17 +149,17 @@ func (s outputStatus) String() string {
|
|||
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())
|
||||
if err != nil {
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
// found at http://opentransactions.org/wiki/index.php/Startwithdrawal
|
||||
// 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,
|
||||
txStore *wtxmgr.Store, chainHeight int32, dustThreshold btcutil.Amount) (
|
||||
txStore *wtxmgr.Store, txmgrNs walletdb.ReadBucket, chainHeight int32, dustThreshold btcutil.Amount) (
|
||||
*WithdrawalStatus, error) {
|
||||
|
||||
status, err := getWithdrawalStatus(p, roundID, requests, startAddress, lastSeriesID,
|
||||
status, err := getWithdrawalStatus(p, ns, addrmgrNs, roundID, requests, startAddress, lastSeriesID,
|
||||
changeStart, dustThreshold)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -491,7 +491,7 @@ func (p *Pool) StartWithdrawal(roundID uint32, requests []OutputRequest,
|
|||
return status, nil
|
||||
}
|
||||
|
||||
eligible, err := p.getEligibleInputs(txStore, startAddress, lastSeriesID, dustThreshold,
|
||||
eligible, err := p.getEligibleInputs(ns, addrmgrNs, txStore, txmgrNs, startAddress, lastSeriesID, dustThreshold,
|
||||
chainHeight, eligibleInputMinConfirmations)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -511,10 +511,7 @@ func (p *Pool) StartWithdrawal(roundID uint32, requests []OutputRequest,
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = p.namespace.Update(
|
||||
func(tx walletdb.Tx) error {
|
||||
return putWithdrawal(tx, p.ID, roundID, serialized)
|
||||
})
|
||||
err = putWithdrawal(ns, p.ID, roundID, serialized)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -819,23 +816,15 @@ func (wi *withdrawalInfo) match(requests []OutputRequest, startAddress Withdrawa
|
|||
// getWithdrawalStatus returns the existing WithdrawalStatus for the given
|
||||
// withdrawal parameters, if one exists. This function must be called with the
|
||||
// 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,
|
||||
dustThreshold btcutil.Amount) (*WithdrawalStatus, error) {
|
||||
|
||||
var serialized []byte
|
||||
err := p.namespace.View(
|
||||
func(tx walletdb.Tx) error {
|
||||
serialized = getWithdrawal(tx, p.ID, roundID)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
serialized := getWithdrawal(ns, p.ID, roundID)
|
||||
if bytes.Equal(serialized, []byte{}) {
|
||||
return nil, nil
|
||||
}
|
||||
wInfo, err := deserializeWithdrawal(p, serialized)
|
||||
wInfo, err := deserializeWithdrawal(p, ns, addrmgrNs, serialized)
|
||||
if err != nil {
|
||||
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
|
||||
// script using that and the given raw signatures.
|
||||
// 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
|
||||
// anywhere -- we just need it to pass to store.PreviousPkScripts().
|
||||
rec, err := wtxmgr.NewTxRecordFromMsgTx(msgtx, time.Now())
|
||||
if err != nil {
|
||||
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 {
|
||||
return newError(ErrTxSigning, "failed to obtain pkScripts for signing", err)
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
// be called with the manager unlocked.
|
||||
func getRedeemScript(mgr *waddrmgr.Manager, addr *btcutil.AddressScriptHash) ([]byte, error) {
|
||||
address, err := mgr.Address(addr)
|
||||
func getRedeemScript(mgr *waddrmgr.Manager, addrmgrNs walletdb.ReadBucket, addr *btcutil.AddressScriptHash) ([]byte, error) {
|
||||
address, err := mgr.Address(addrmgrNs, addr)
|
||||
if err != nil {
|
||||
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
|
||||
// script as OP_CHECKMULTISIG expects that.
|
||||
// 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())
|
||||
if err != nil {
|
||||
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 {
|
||||
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 {
|
||||
return newError(ErrTxSigning, "unable to retrieve redeem script", err)
|
||||
}
|
||||
|
@ -1047,9 +1036,9 @@ func nextChangeAddress(a ChangeAddress) (ChangeAddress, error) {
|
|||
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 {
|
||||
if err := tx.addSelfToStore(store); err != nil {
|
||||
if err := tx.addSelfToStore(store, txmgrNs); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue