lbcwallet/wallet/utxos.go

91 lines
2.6 KiB
Go
Raw Normal View History

// Copyright (c) 2016 The Decred developers
// Copyright (c) 2017 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package wallet
import (
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcwallet/walletdb"
)
// OutputSelectionPolicy describes the rules for selecting an output from the
// wallet.
type OutputSelectionPolicy struct {
Account uint32
RequiredConfirmations int32
}
func (p *OutputSelectionPolicy) meetsRequiredConfs(txHeight, curHeight int32) bool {
return confirmed(p.RequiredConfirmations, txHeight, curHeight)
}
// UnspentOutputs fetches all unspent outputs from the wallet that match rules
// described in the passed policy.
func (w *Wallet) UnspentOutputs(policy OutputSelectionPolicy) ([]*TransactionOutput, error) {
var outputResults []*TransactionOutput
err := walletdb.View(w.db, func(tx walletdb.ReadTx) error {
addrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey)
txmgrNs := tx.ReadBucket(wtxmgrNamespaceKey)
syncBlock := w.Manager.SyncedTo()
// TODO: actually stream outputs from the db instead of fetching
// all of them at once.
outputs, err := w.TxStore.UnspentOutputs(txmgrNs)
if err != nil {
return err
}
for _, output := range outputs {
// Ignore outputs that haven't reached the required
// number of confirmations.
if !policy.meetsRequiredConfs(output.Height, syncBlock.Height) {
continue
}
// Ignore outputs that are not controlled by the account.
_, addrs, _, err := txscript.ExtractPkScriptAddrs(output.PkScript,
w.chainParams)
if err != nil || len(addrs) == 0 {
// Cannot determine which account this belongs
// to without a valid address. TODO: Fix this
// by saving outputs per account, or accounts
// per output.
continue
}
outputAcct, err := w.Manager.AddrAccount(addrmgrNs, addrs[0])
if err != nil {
return err
}
if outputAcct != policy.Account {
continue
}
// Stakebase isn't exposed by wtxmgr so those will be
// OutputKindNormal for now.
outputSource := OutputKindNormal
if output.FromCoinBase {
outputSource = OutputKindCoinbase
}
result := &TransactionOutput{
OutPoint: output.OutPoint,
Output: wire.TxOut{
Value: int64(output.Amount),
PkScript: output.PkScript,
},
OutputKind: outputSource,
ContainingBlock: BlockIdentity(output.Block),
ReceiveTime: output.Received,
}
outputResults = append(outputResults, result)
}
return nil
})
return outputResults, err
}