Documentation ¶
Overview ¶
Package wtxmgr provides an implementation of a transaction database handling spend tracking for a bitcoin wallet. Its primary purpose is to save transactions with outputs spendable with wallet keys and transactions that are signed by wallet keys in memory, handle spend tracking for unspent outputs and newly-inserted transactions, and report the spendable balance from each unspent transaction output. It uses walletdb as the backend for storing the serialized transaction objects in buckets.
Transaction outputs which are spendable by wallet keys are called credits (because they credit to a wallet's total spendable balance). Transaction inputs which spend previously-inserted credits are called debits (because they debit from the wallet's spendable balance).
Spend tracking is mostly automatic. When a new transaction is inserted, if it spends from any unspent credits, they are automatically marked spent by the new transaction, and each input which spent a credit is marked as a debit. However, transaction outputs of inserted transactions must manually marked as credits, as this package has no knowledge of wallet keys or addresses, and therefore cannot determine which outputs may be spent.
Details regarding individual transactions and their credits and debits may be queried either by just a transaction hash, or by hash and block. When querying for just a transaction hash, the most recent transaction with a matching hash will be queried. However, because transaction hashes may collide with other transaction hashes, methods to query for specific transactions in the chain (or unmined) are provided as well.
Index ¶
- Constants
- func Create(ns walletdb.ReadWriteBucket) (e error)
- func DoUpgrades(db walletdb.DB, namespaceKey []byte) (e error)
- func IsNoExists(e error) bool
- func RemoveConflict(ns walletdb.ReadWriteBucket, rec *TxRecord) (e error)
- type Block
- type BlockMeta
- type Credit
- type CreditRecord
- type DebitRecord
- type ErrorCode
- type Store
- func (s *Store) AddCredit(ns walletdb.ReadWriteBucket, rec *TxRecord, block *BlockMeta, index uint32, ...) (e error)
- func (s *Store) Balance(ns walletdb.ReadBucket, minConf int32, syncHeight int32) (util.Amount, error)
- func (s *Store) InsertTx(ns walletdb.ReadWriteBucket, rec *TxRecord, block *BlockMeta) (e error)
- func (s *Store) PreviousPkScripts(ns walletdb.ReadBucket, rec *TxRecord, block *Block) ([][]byte, error)
- func (s *Store) RangeTransactions(ns walletdb.ReadBucket, begin, end int32, f func([]TxDetails) (bool, error)) error
- func (s *Store) RemoveUnminedTx(ns walletdb.ReadWriteBucket, rec *TxRecord) (e error)
- func (s *Store) Rollback(ns walletdb.ReadWriteBucket, height int32) (e error)
- func (s *Store) TxDetails(ns walletdb.ReadBucket, txHash *chainhash.Hash) (*TxDetails, error)
- func (s *Store) UniqueTxDetails(ns walletdb.ReadBucket, txHash *chainhash.Hash, block *Block) (*TxDetails, error)
- func (s *Store) UnminedTxHashes(ns walletdb.ReadBucket) ([]*chainhash.Hash, error)
- func (s *Store) UnminedTxs(ns walletdb.ReadBucket) ([]*wire.MsgTx, error)
- func (s *Store) UnspentOutputs(ns walletdb.ReadBucket) ([]Credit, error)
- type TxDetails
- type TxMgrError
- type TxRecord
Constants ¶
const (
// LatestVersion is the most recent store version.
LatestVersion = 1
)
Database versions. Versions start at 1 and increment for each database change.
Variables ¶
This section is empty.
Functions ¶
func Create ¶
func Create(ns walletdb.ReadWriteBucket) (e error)
Create creates a new persistent transaction store in the walletdb namespace. Creating the store when one already exists in this namespace will error with ErrAlreadyExists.
func DoUpgrades ¶
DoUpgrades performs any necessary upgrades to the transaction history contained in the wallet database, namespaced by the top level bucket key namespaceKey.
func IsNoExists ¶
IsNoExists returns whether an error is a TxMgrError with the ErrNoExists error code.
func RemoveConflict ¶
func RemoveConflict(ns walletdb.ReadWriteBucket, rec *TxRecord) (e error)
RemoveConflict removes an unmined transaction record and all spend chains deriving from it from the store.
This is designed to remove transactions that would otherwise result in double spend conflicts if left in the store, and to remove transactions that spend coinbase transactions on reorgs.
Types ¶
type Block ¶
Block contains the minimum amount of data to uniquely identify any block on either the best or side chain.
type BlockMeta ¶
BlockMeta contains the unique identification for a block and any metadata pertaining to the block. At the moment, this additional metadata only includes the block time from the block header.
type Credit ¶
type Credit struct { wire.OutPoint BlockMeta Amount util.Amount PkScript []byte Received time.Time FromCoinBase bool }
Credit is the type representing a transaction output which was spent or is still spendable by wallet. A UTXO is an unspent Credit, but not all Credits are UTXOs.
type CreditRecord ¶
CreditRecord contains metadata regarding a transaction credit for a known transaction. Further details may be looked up by indexing a wire.MsgTx.TxOut with the Index field.
type DebitRecord ¶
DebitRecord contains metadata regarding a transaction debit for a known transaction. Further details may be looked up by indexing a wire.MsgTx.TxIn with the Index field.
type ErrorCode ¶
type ErrorCode uint8
ErrorCode identifies a category of error.
const ( // ErrDatabase indicates an error with the underlying database. When this error code is set, the Err field of the // TxMgrError will be set to the underlying error returned from the database. ErrDatabase ErrorCode = iota // ErrData describes an error where data stored in the transaction database is incorrect. This may be due to missing // values, values of wrong sizes, or data from different buckets that is inconsistent with itself. Recovering from // an ErrData requires rebuilding all transaction history or manual database surgery. If the failure was not due to // data corruption, this error category indicates a programming error in this package. ErrData // ErrInput describes an error where the variables passed into this function by the caller are obviously incorrect. // Examples include passing transactions which do not serialize, or attempting to insert a credit at an index for // which no transaction output exists. ErrInput // ErrAlreadyExists describes an error where creating the store cannot continue because a store already exists in // the namespace. ErrAlreadyExists // ErrNoExists describes an error where the store cannot be opened due to it not already existing in the namespace. // This error should be handled by creating a new store. ErrNoExists // ErrNeedsUpgrade describes an error during store opening where the database contains an older version of the // store. ErrNeedsUpgrade // ErrUnknownVersion describes an error where the store already exists but the database version is newer than latest // version known to this software. This likely indicates an outdated binary. ErrUnknownVersion )
These constants are used to identify a specific TxMgrError.
type Store ¶
type Store struct { // Event callbacks. These execute in the same goroutine as the wtxmgr caller. NotifyUnspent func(hash *chainhash.Hash, index uint32) // contains filtered or unexported fields }
Store implements a transaction store for storing and managing wallet transactions.
func Open ¶
Open opens the wallet transaction store from a walletdb namespace. If the store does not exist, ErrNoExist is returned.
func (*Store) AddCredit ¶
func (s *Store) AddCredit( ns walletdb.ReadWriteBucket, rec *TxRecord, block *BlockMeta, index uint32, change bool, ) (e error)
AddCredit marks a transaction record as containing a transaction output spendable by wallet. The output is added unspent, and is marked spent when a new transaction spending the output is inserted into the store.
TODO(jrick): This should not be necessary. Instead, pass the indexes that are known to contain credits when a
transaction or merkleblock is inserted into the store.
func (*Store) InsertTx ¶
InsertTx records a transaction as belonging to a wallet's transaction history. If block is nil, the transaction is considered unspent, and the transaction's index must be unset.
func (*Store) PreviousPkScripts ¶
func (s *Store) PreviousPkScripts(ns walletdb.ReadBucket, rec *TxRecord, block *Block) ([][]byte, error)
PreviousPkScripts returns a slice of previous output scripts for each credit output this transaction record debits from.
func (*Store) RangeTransactions ¶
func (s *Store) RangeTransactions( ns walletdb.ReadBucket, begin, end int32, f func([]TxDetails) (bool, error), ) error
RangeTransactions runs the function f on all transaction details between blocks on the best chain over the height range [begin,end]. The special height -1 may be used to also include unmined transactions. If the end height comes before the begin height, blocks are iterated in reverse order and unmined transactions (if any) are processed first.
The function f may return an error which, if non-nil, is propagated to the caller. Additionally, a boolean return value allows exiting the function early without reading any additional transactions early when true.
All calls to f are guaranteed to be passed a slice with more than zero elements. The slice may be reused for multiple blocks, so it is not safe to use it after the loop iteration it was acquired.
func (*Store) RemoveUnminedTx ¶
func (s *Store) RemoveUnminedTx(ns walletdb.ReadWriteBucket, rec *TxRecord) (e error)
RemoveUnminedTx attempts to remove an unmined transaction from the transaction store. This is to be used in the scenario that a transaction that we attempt to rebroadcast, turns out to double spend one of our existing inputs. This function we remove the conflicting transaction identified by the tx record, and also recursively remove all transactions that depend on it.
func (*Store) Rollback ¶
func (s *Store) Rollback(ns walletdb.ReadWriteBucket, height int32) (e error)
Rollback removes all blocks at height onwards, moving any transactions within each block to the unconfirmed pool.
func (*Store) TxDetails ¶
TxDetails looks up all recorded details regarding a transaction with some hash. In case of a hash collision, the most recent transaction with a matching hash is returned.
Not finding a transaction with this hash is not an error. In this case, a nil TxDetails is returned.
func (*Store) UniqueTxDetails ¶
func (s *Store) UniqueTxDetails( ns walletdb.ReadBucket, txHash *chainhash.Hash, block *Block, ) (*TxDetails, error)
UniqueTxDetails looks up all recorded details for a transaction recorded mined in some particular block, or an unmined transaction if block is nil.
Not finding a transaction with this hash from this block is not an error. In this case, a nil TxDetails is returned.
func (*Store) UnminedTxHashes ¶
UnminedTxHashes returns the hashes of all transactions not known to have been mined in a block.
func (*Store) UnminedTxs ¶
UnminedTxs returns the underlying transactions for all unmined transactions which are not known to have been mined in a block. Transactions are guaranteed to be sorted by their dependency order.
func (*Store) UnspentOutputs ¶
func (s *Store) UnspentOutputs(ns walletdb.ReadBucket) ([]Credit, error)
type TxDetails ¶
type TxDetails struct { TxRecord Block BlockMeta Credits []CreditRecord Debits []DebitRecord }
TxDetails is intended to provide callers with access to rich details regarding a relevant transaction and which inputs and outputs are credit or debits.
type TxMgrError ¶
type TxMgrError struct { Code ErrorCode // Describes the kind of error Desc string // Human readable description of the issue Err error // Underlying error, optional }
TxMgrError provides a single type for errors that can happen during Store operation.
func (TxMgrError) Error ¶
func (e TxMgrError) Error() string
TxMgrError satisfies the error interface and prints human-readable errors.
type TxRecord ¶
type TxRecord struct { MsgTx wire.MsgTx Hash chainhash.Hash Received time.Time SerializedTx []byte // Optional: may be nil }
TxRecord represents a transaction managed by the Store.
func NewTxRecord ¶
NewTxRecord creates a new transaction record that may be inserted into the store. It uses memoization to save the transaction hash and the serialized transaction.