diff --git a/Dockerfile b/Dockerfile index a96c4d0..df5045f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,7 @@ ARG ARCH=amd64 -FROM golang:1.18.2 AS build-container +FROM golang:1.19 AS build-container ARG ARCH diff --git a/chain/interface.go b/chain/interface.go index 31d4556..ce1a2d9 100644 --- a/chain/interface.go +++ b/chain/interface.go @@ -25,7 +25,9 @@ func BackEnds() []string { } // Interface allows more than one backing blockchain source, such as a -// RPC chain server, or an SPV library, as long as we write a driver for +// +// RPC chain server, or an SPV library, as long as we write a driver for +// // it. type Interface interface { Start() error diff --git a/chain/utils_test.go b/chain/utils_test.go index 1b6c5e7..506645b 100644 --- a/chain/utils_test.go +++ b/chain/utils_test.go @@ -66,7 +66,8 @@ func pipe(c1, c2 *conn) (*conn, *conn) { // returns the root of the tree. // // This function was copied from: -// https://github.com/lbryio/lbcd/blob/36a96f6a0025b6aeaebe4106821c2d46ee4be8d4/blockchain/fullblocktests/generate.go#L303 +// +// https://github.com/lbryio/lbcd/blob/36a96f6a0025b6aeaebe4106821c2d46ee4be8d4/blockchain/fullblocktests/generate.go#L303 func calcMerkleRoot(txns []*wire.MsgTx) chainhash.Hash { if len(txns) == 0 { return chainhash.Hash{} @@ -86,7 +87,8 @@ func calcMerkleRoot(txns []*wire.MsgTx) chainhash.Hash { // with the solution. False is returned if no solution exists. // // This function was copied from: -// https://github.com/lbryio/lbcd/blob/36a96f6a0025b6aeaebe4106821c2d46ee4be8d4/blockchain/fullblocktests/generate.go#L324 +// +// https://github.com/lbryio/lbcd/blob/36a96f6a0025b6aeaebe4106821c2d46ee4be8d4/blockchain/fullblocktests/generate.go#L324 func solveBlock(header *wire.BlockHeader) bool { // sbResult is used by the solver goroutines to send results. type sbResult struct { diff --git a/config.go b/config.go index 279bb2a..91f1efa 100644 --- a/config.go +++ b/config.go @@ -251,10 +251,10 @@ func parseAndSetDebugLevels(debugLevel string) error { // line options. // // The configuration proceeds as follows: -// 1) Start with a default config with sane settings -// 2) Pre-parse the command line to check for an alternative config file -// 3) Load configuration file overwriting defaults with any specified options -// 4) Parse CLI options and overwrite/add any specified options +// 1. Start with a default config with sane settings +// 2. Pre-parse the command line to check for an alternative config file +// 3. Load configuration file overwriting defaults with any specified options +// 4. Parse CLI options and overwrite/add any specified options // // The above results in lbcwallet functioning properly without any config // settings while still allowing the user to override settings with config files diff --git a/netparams/params.go b/netparams/params.go index e575049..c310598 100644 --- a/netparams/params.go +++ b/netparams/params.go @@ -18,7 +18,8 @@ type Params struct { } // MainNetParams contains parameters specific running lbcwallet and -// on the main network (wire.MainNet). +// +// on the main network (wire.MainNet). var MainNetParams = Params{ Params: &chaincfg.MainNetParams, RPCClientPort: "9245", @@ -26,7 +27,8 @@ var MainNetParams = Params{ } // TestNet3Params contains parameters specific running lbcwallet and -// on the test network (version 3) (wire.TestNet3). +// +// on the test network (version 3) (wire.TestNet3). var TestNet3Params = Params{ Params: &chaincfg.TestNet3Params, RPCClientPort: "19245", diff --git a/rpc/legacyrpc/methods.go b/rpc/legacyrpc/methods.go index 90d3c52..9221d6b 100644 --- a/rpc/legacyrpc/methods.go +++ b/rpc/legacyrpc/methods.go @@ -1226,14 +1226,17 @@ func listLockUnspent(icmd interface{}, w *wallet.Wallet) (interface{}, error) { // listReceivedByAccount handles a listreceivedbyaccount request by returning // a slice of objects, each one containing: -// "account": the receiving account; -// "amount": total amount received by the account; -// "confirmations": number of confirmations of the most recent transaction. +// +// "account": the receiving account; +// "amount": total amount received by the account; +// "confirmations": number of confirmations of the most recent transaction. +// // It takes two parameters: -// "minconf": minimum number of confirmations to consider a transaction - -// default: one; -// "includeempty": whether or not to include addresses that have no transactions - -// default: false. +// +// "minconf": minimum number of confirmations to consider a transaction - +// default: one; +// "includeempty": whether or not to include addresses that have no transactions - +// default: false. func listReceivedByAccount(icmd interface{}, w *wallet.Wallet) (interface{}, error) { cmd := icmd.(*btcjson.ListReceivedByAccountCmd) @@ -1257,15 +1260,18 @@ func listReceivedByAccount(icmd interface{}, w *wallet.Wallet) (interface{}, err // listReceivedByAddress handles a listreceivedbyaddress request by returning // a slice of objects, each one containing: -// "account": the account of the receiving address; -// "address": the receiving address; -// "amount": total amount received by the address; -// "confirmations": number of confirmations of the most recent transaction. +// +// "account": the account of the receiving address; +// "address": the receiving address; +// "amount": total amount received by the address; +// "confirmations": number of confirmations of the most recent transaction. +// // It takes two parameters: -// "minconf": minimum number of confirmations to consider a transaction - -// default: one; -// "includeempty": whether or not to include addresses that have no transactions - -// default: false. +// +// "minconf": minimum number of confirmations to consider a transaction - +// default: one; +// "includeempty": whether or not to include addresses that have no transactions - +// default: false. func listReceivedByAddress(icmd interface{}, w *wallet.Wallet) (interface{}, error) { cmd := icmd.(*btcjson.ListReceivedByAddressCmd) diff --git a/rpc/legacyrpc/server.go b/rpc/legacyrpc/server.go index b3d9995..2a6c30b 100644 --- a/rpc/legacyrpc/server.go +++ b/rpc/legacyrpc/server.go @@ -165,7 +165,7 @@ func NewServer(opts *Options, walletLoader *wallet.Loader, listeners []net.Liste // httpBasicAuth returns the UTF-8 bytes of the HTTP Basic authentication // string: // -// "Basic " + base64(username + ":" + password) +// "Basic " + base64(username + ":" + password) func httpBasicAuth(username, password string) []byte { const header = "Basic " base64 := base64.StdEncoding diff --git a/rpc/rpcserver/server.go b/rpc/rpcserver/server.go index e38f6c7..d63ec1c 100644 --- a/rpc/rpcserver/server.go +++ b/rpc/rpcserver/server.go @@ -8,11 +8,11 @@ // Full documentation of the API implemented by this package is maintained in a // language-agnostic document: // -// https://github.com/lbryio/lbcwallet/blob/master/rpc/documentation/api.md +// https://github.com/lbryio/lbcwallet/blob/master/rpc/documentation/api.md // // Any API changes must be performed according to the steps listed here: // -// https://github.com/lbryio/lbcwallet/blob/master/rpc/documentation/serverchanges.md +// https://github.com/lbryio/lbcwallet/blob/master/rpc/documentation/serverchanges.md package rpcserver import ( @@ -487,12 +487,12 @@ func (s *walletServer) SignTransaction(ctx context.Context, req *pb.SignTransact } // BUGS: -// - The transaction is not inspected to be relevant before publishing using -// sendrawtransaction, so connection errors to could result in the tx -// never being added to the wallet database. -// - Once the above bug is fixed, wallet will require a way to purge invalid -// transactions from the database when they are rejected by the network, other -// than double spending them. +// - The transaction is not inspected to be relevant before publishing using +// sendrawtransaction, so connection errors to could result in the tx +// never being added to the wallet database. +// - Once the above bug is fixed, wallet will require a way to purge invalid +// transactions from the database when they are rejected by the network, other +// than double spending them. func (s *walletServer) PublishTransaction(ctx context.Context, req *pb.PublishTransactionRequest) ( *pb.PublishTransactionResponse, error) { diff --git a/rpc/walletrpc/api.pb.go b/rpc/walletrpc/api.pb.go index be07bff..b0f57bf 100644 --- a/rpc/walletrpc/api.pb.go +++ b/rpc/walletrpc/api.pb.go @@ -5,9 +5,11 @@ Package walletrpc is a generated protocol buffer package. It is generated from these files: + api.proto It has these top-level messages: + VersionRequest VersionResponse TransactionDetails diff --git a/waddrmgr/db.go b/waddrmgr/db.go index 30f2e85..d4ccf29 100644 --- a/waddrmgr/db.go +++ b/waddrmgr/db.go @@ -2383,9 +2383,10 @@ func putBirthday(ns walletdb.ReadWriteBucket, t time.Time) error { // FetchBirthdayBlock retrieves the birthday block from the database. // // The block is serialized as follows: -// [0:4] block height -// [4:36] block hash -// [36:44] block timestamp +// +// [0:4] block height +// [4:36] block hash +// [36:44] block timestamp func FetchBirthdayBlock(ns walletdb.ReadBucket) (BlockStamp, error) { var block BlockStamp @@ -2423,9 +2424,10 @@ func DeleteBirthdayBlock(ns walletdb.ReadWriteBucket) error { // PutBirthdayBlock stores the provided birthday block to the database. // // The block is serialized as follows: -// [0:4] block height -// [4:36] block hash -// [36:44] block timestamp +// +// [0:4] block height +// [4:36] block hash +// [36:44] block timestamp // // NOTE: This does not alter the birthday block verification state. func PutBirthdayBlock(ns walletdb.ReadWriteBucket, block BlockStamp) error { diff --git a/waddrmgr/doc.go b/waddrmgr/doc.go index aa14430..1439b65 100644 --- a/waddrmgr/doc.go +++ b/waddrmgr/doc.go @@ -6,7 +6,7 @@ Package waddrmgr provides a secure hierarchical deterministic wallet address manager. -Overview +# Overview One of the fundamental jobs of a wallet is to manage addresses, private keys, and script data associated with them. At a high level, this package provides @@ -52,14 +52,14 @@ used to decrypt private keys and scripts on demand. Relocking the address manager actively zeros all private material from memory. In addition, temp private key material used internally is zeroed as soon as it's used. -Locking and Unlocking +# Locking and Unlocking As previously mentioned, this package provide facilities for locking and unlocking the address manager to protect access to private material and remove it from memory when locked. The Lock, Unlock, and IsLocked functions are used for this purpose. -Creating a New Address Manager +# Creating a New Address Manager A new address manager is created via the Create function. This function accepts a wallet database namespace, passphrases, network, and perhaps most importantly, @@ -69,28 +69,28 @@ to be recovered with only the seed. The GenerateSeed function in the hdkeychain package can be used as a convenient way to create a random seed for use with this function. The address manager is locked immediately upon being created. -Opening an Existing Address Manager +# Opening an Existing Address Manager An existing address manager is opened via the Open function. This function accepts an existing wallet database namespace, the public passphrase, and network. The address manager is opened locked as expected since the open function does not take the private passphrase to unlock it. -Closing the Address Manager +# Closing the Address Manager The Close method should be called on the address manager when the caller is done with it. While it is not required, it is recommended because it sanely shuts down the database and ensures all private and public key material is purged from memory. -Managed Addresses +# Managed Addresses Each address returned by the address manager satisifies the ManagedAddress interface as well as either the ManagedPubKeyAddress or ManagedScriptAddress interfaces. These interfaces provide the means to obtain relevant information about the addresses such as their private keys and scripts. -Chained Addresses +# Chained Addresses Most callers will make use of the chained addresses for normal operations. Internal addresses are intended for internal wallet uses such as change outputs, @@ -101,13 +101,13 @@ been provided. In addition, the LastInternalAddress and LastExternalAddress functions can be used to get the most recently provided internal and external address, respectively. -Requesting Existing Addresses +# Requesting Existing Addresses In addition to generating new addresses, access to old addresses is often required. Most notably, to sign transactions in order to redeem them. The Address function provides this capability and returns a ManagedAddress. -Importing Addresses +# Importing Addresses While the recommended approach is to use the chained addresses discussed above because they can be deterministically regenerated to avoid losing funds as long @@ -116,27 +116,27 @@ and as a result, this package provides the ability to import existing private keys in Wallet Import Format (WIF) and hence the associated public key and address. -Importing Scripts +# Importing Scripts In order to support pay-to-script-hash transactions, the script must be securely stored as it is needed to redeem the transaction. This can be useful for a variety of scenarios, however the most common use is currently multi-signature transactions. -Syncing +# Syncing The address manager also supports storing and retrieving a block hash and height which the manager is known to have all addresses synced through. The manager itself does not have any notion of which addresses are synced or not. It only provides the storage as a convenience for the caller. -Network +# Network The address manager must be associated with a given network in order to provide appropriate addresses and reject imported addresses and scripts which don't apply to the associated network. -Errors +# Errors All errors returned from this package are of type ManagerError. This allows the caller to programmatically ascertain the specific reasons for failure by @@ -144,12 +144,12 @@ examining the ErrorCode field of the type asserted ManagerError. For certain error codes, as documented by the specific error codes, the underlying error will be contained in the Err field. -Bitcoin Improvement Proposals +# Bitcoin Improvement Proposals This package includes concepts outlined by the following BIPs: - BIP0032 (https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) - BIP0043 (https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki) - BIP0044 (https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) + BIP0032 (https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) + BIP0043 (https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki) + BIP0044 (https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) */ package waddrmgr diff --git a/waddrmgr/manager.go b/waddrmgr/manager.go index 381851c..91e604f 100644 --- a/waddrmgr/manager.go +++ b/waddrmgr/manager.go @@ -1479,7 +1479,8 @@ func deriveCoinTypeKey(masterNode *hdkeychain.ExtendedKey, // hierarchy described by BIP0044 given the master node. // // In particular this is the hierarchical deterministic extended key path: -// m/purpose'/'/' +// +// m/purpose'/'/' func deriveAccountKey(coinTypeKey *hdkeychain.ExtendedKey, account uint32) (*hdkeychain.ExtendedKey, error) { @@ -1502,7 +1503,8 @@ func deriveAccountKey(coinTypeKey *hdkeychain.ExtendedKey, // already derived accordingly. // // In particular this is the hierarchical deterministic extended key path: -// m/purpose'/'/'/ +// +// m/purpose'/'/'/ // // The branch is 0 for external addresses and 1 for internal addresses. func checkBranchKeys(acctKey *hdkeychain.ExtendedKey) error { diff --git a/wallet/doc.go b/wallet/doc.go index f99a856..c562d58 100644 --- a/wallet/doc.go +++ b/wallet/doc.go @@ -7,6 +7,5 @@ Package wallet provides ... TODO: Flesh out this section Overview - */ package wallet diff --git a/wallet/recovery.go b/wallet/recovery.go index 83b7f6b..41ed9b5 100644 --- a/wallet/recovery.go +++ b/wallet/recovery.go @@ -189,11 +189,11 @@ func (rm *RecoveryManager) State() *RecoveryState { // // These are defined as: // - Inter-Block Gap: The maximum difference between the derived child indexes -// of the last addresses used in any block and the next address consumed -// by a later block. +// of the last addresses used in any block and the next address consumed +// by a later block. // - Intra-Block Gap: The maximum difference between the derived child indexes -// of the first address used in any block and the last address used in the -// same block. +// of the first address used in any block and the last address used in the +// same block. type RecoveryState struct { // recoveryWindow defines the key-derivation lookahead used when // attempting to recover the set of used addresses. This value will be @@ -282,12 +282,12 @@ func NewScopeRecoveryState(recoveryWindow uint32) *ScopeRecoveryState { // derivation branch. // // A branch recovery state supports operations for: -// - Expanding the look-ahead horizon based on which indexes have been found. -// - Registering derived addresses with indexes within the horizon. -// - Reporting an invalid child index that falls into the horizon. -// - Reporting that an address has been found. -// - Retrieving all currently derived addresses for the branch. -// - Looking up a particular address by its child index. +// - Expanding the look-ahead horizon based on which indexes have been found. +// - Registering derived addresses with indexes within the horizon. +// - Reporting an invalid child index that falls into the horizon. +// - Reporting that an address has been found. +// - Retrieving all currently derived addresses for the branch. +// - Looking up a particular address by its child index. type BranchRecoveryState struct { // recoveryWindow defines the key-derivation lookahead used when // attempting to recover the set of addresses on this branch. diff --git a/wallet/wallet.go b/wallet/wallet.go index 3970296..100e5e6 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -756,13 +756,13 @@ func (w *Wallet) recovery(chainClient chain.Interface, // previously used addresses for a particular account derivation path. At a high // level, the algorithm works as follows: // -// 1) Ensure internal and external branch horizons are fully expanded. -// 2) Filter the entire range of blocks, stopping if a non-zero number of -// address are contained in a particular block. -// 3) Record all internal and external addresses found in the block. -// 4) Record any outpoints found in the block that should be watched for spends -// 5) Trim the range of blocks up to and including the one reporting the addrs. -// 6) Repeat from (1) if there are still more blocks in the range. +// 1. Ensure internal and external branch horizons are fully expanded. +// 2. Filter the entire range of blocks, stopping if a non-zero number of +// address are contained in a particular block. +// 3. Record all internal and external addresses found in the block. +// 4. Record any outpoints found in the block that should be watched for spends +// 5. Trim the range of blocks up to and including the one reporting the addrs. +// 6. Repeat from (1) if there are still more blocks in the range. // // TODO(conner): parallelize/pipeline/cache intermediate network requests func (w *Wallet) recoverScopedAddresses( @@ -2093,13 +2093,9 @@ func (w *Wallet) ListTransactions(from, count int) ([]btcjson.ListTransactionsRe // include the next count transactions. skipped := 0 n := 0 - rangeFn := func(details []wtxmgr.TxDetails) (bool, error) { - // Iterate over transactions at this height in reverse order. - // This does nothing for unmined transactions, which are - // unsorted, but it will process mined transactions in the - // reverse order they were marked mined. - for i := len(details) - 1; i >= 0; i-- { + + for _, detail := range details { if from > skipped { skipped++ continue @@ -2110,7 +2106,7 @@ func (w *Wallet) ListTransactions(from, count int) ([]btcjson.ListTransactionsRe return true, nil } - jsonResults := listTransactions(tx, &details[i], + jsonResults := listTransactions(tx, &detail, w.Manager, syncBlock.Height, w.chainParams) txList = append(txList, jsonResults...) @@ -2124,8 +2120,10 @@ func (w *Wallet) ListTransactions(from, count int) ([]btcjson.ListTransactionsRe // Return newer results first by starting at mempool height and working // down to the genesis block. - return w.TxStore.RangeTransactions(txmgrNs, -1, 0, rangeFn) + // return w.TxStore.RangeTransactions(txmgrNs, -1, 0, rangeFn) + return w.TxStore.RangeTransactions(txmgrNs, 0, -1, rangeFn) }) + return txList, err } diff --git a/wallet/wallet_test.go b/wallet/wallet_test.go index d2e6da2..de82c0a 100644 --- a/wallet/wallet_test.go +++ b/wallet/wallet_test.go @@ -17,7 +17,7 @@ var ( ) // TestLocateBirthdayBlock ensures we can properly map a block in the chain to a -//timestamp. +// timestamp. func TestLocateBirthdayBlock(t *testing.T) { t.Parallel() diff --git a/walletdb/bdb/doc.go b/walletdb/bdb/doc.go index af8ffd4..d5d6e38 100644 --- a/walletdb/bdb/doc.go +++ b/walletdb/bdb/doc.go @@ -6,7 +6,7 @@ Package bdb implements an instance of walletdb that uses boltdb for the backing datastore. -Usage +# Usage This package is only a driver to the walletdb package and provides the database type of "bdb". The only parameters the Open and Create functions take are the diff --git a/walletdb/doc.go b/walletdb/doc.go index 9c1e992..5631931 100644 --- a/walletdb/doc.go +++ b/walletdb/doc.go @@ -5,7 +5,7 @@ /* Package walletdb provides a namespaced database interface for lbcwallet. -Overview +# Overview A wallet essentially consists of a multitude of stored data such as private and public keys, key derivation bits, pay-to-script-hash scripts, and various @@ -26,16 +26,16 @@ the wallet. A quick overview of the features walletdb provides are as follows: - - Key/value store - - Namespace support - - Allows multiple packages to have their own area in the database without - worrying about conflicts - - Read-only and read-write transactions with both manual and managed modes - - Nested buckets - - Supports registration of backend databases - - Comprehensive test coverage + - Key/value store + - Namespace support + - Allows multiple packages to have their own area in the database without + worrying about conflicts + - Read-only and read-write transactions with both manual and managed modes + - Nested buckets + - Supports registration of backend databases + - Comprehensive test coverage -Database +# Database The main entry point is the DB interface. It exposes functionality for creating, retrieving, and removing namespaces. It is obtained via the Create @@ -43,7 +43,7 @@ and Open functions which take a database type string that identifies the specific database driver (backend) to use as well as arguments specific to the specified driver. -Namespaces +# Namespaces The Namespace interface is an abstraction that provides facilities for obtaining transactions (the Tx interface) that are the basis of all database reads and @@ -55,14 +55,14 @@ The Begin function provides an unmanaged transaction while the View and Update functions provide a managed transaction. These are described in more detail below. -Transactions +# Transactions The Tx interface provides facilities for rolling back or commiting changes that took place while the transaction was active. It also provides the root bucket under which all keys, values, and nested buckets are stored. A transaction can either be read-only or read-write and managed or unmanaged. -Managed versus Unmanaged Transactions +# Managed versus Unmanaged Transactions A managed transaction is one where the caller provides a function to execute within the context of the transaction and the commit or rollback is handled @@ -75,7 +75,7 @@ call Commit or Rollback when they are finished with it. Leaving transactions open for long periods of time can have several adverse effects, so it is recommended that managed transactions are used instead. -Buckets +# Buckets The Bucket interface provides the ability to manipulate key/value pairs and nested buckets as well as iterate through them. @@ -85,7 +85,7 @@ CreateBucket, CreateBucketIfNotExists, and DeleteBucket functions work with buckets. The ForEach function allows the caller to provide a function to be called with each key/value pair and nested bucket in the current bucket. -Root Bucket +# Root Bucket As discussed above, all of the functions which are used to manipulate key/value pairs and nested buckets exist on the Bucket interface. The root bucket is the @@ -93,7 +93,7 @@ upper-most bucket in a namespace under which data is stored and is created at the same time as the namespace. Use the RootBucket function on the Tx interface to retrieve it. -Nested Buckets +# Nested Buckets The CreateBucket and CreateBucketIfNotExists functions on the Bucket interface provide the ability to create an arbitrary number of nested buckets. It is diff --git a/wtxmgr/db.go b/wtxmgr/db.go index 998283a..004e965 100644 --- a/wtxmgr/db.go +++ b/wtxmgr/db.go @@ -678,21 +678,21 @@ func deleteRawCredit(ns walletdb.ReadWriteBucket, k []byte) error { // // Example usage: // -// prefix := keyTxRecord(txHash, block) -// it := makeCreditIterator(ns, prefix) -// for it.next() { -// // Use it.elem -// // If necessary, read additional details from it.ck, it.cv -// } -// if it.err != nil { -// // Handle error -// } +// prefix := keyTxRecord(txHash, block) +// it := makeCreditIterator(ns, prefix) +// for it.next() { +// // Use it.elem +// // If necessary, read additional details from it.ck, it.cv +// } +// if it.err != nil { +// // Handle error +// } // // The elem's Spent field is not set to true if the credit is spent by an // unmined transaction. To check for this case: // -// k := canonicalOutPoint(&txHash, it.elem.Index) -// it.elem.Spent = existsRawUnminedInput(ns, k) != nil +// k := canonicalOutPoint(&txHash, it.elem.Index) +// it.elem.Spent = existsRawUnminedInput(ns, k) != nil type creditIterator struct { c walletdb.ReadWriteCursor // Set to nil after final iteration prefix []byte @@ -918,15 +918,15 @@ func deleteRawDebit(ns walletdb.ReadWriteBucket, k []byte) error { // // Example usage: // -// prefix := keyTxRecord(txHash, block) -// it := makeDebitIterator(ns, prefix) -// for it.next() { -// // Use it.elem -// // If necessary, read additional details from it.ck, it.cv -// } -// if it.err != nil { -// // Handle error -// } +// prefix := keyTxRecord(txHash, block) +// it := makeDebitIterator(ns, prefix) +// for it.next() { +// // Use it.elem +// // If necessary, read additional details from it.ck, it.cv +// } +// if it.err != nil { +// // Handle error +// } type debitIterator struct { c walletdb.ReadWriteCursor // Set to nil after final iteration prefix []byte @@ -1092,22 +1092,22 @@ func deleteRawUnminedCredit(ns walletdb.ReadWriteBucket, k []byte) error { // unminedCreditIterator allows for cursor iteration over all credits, in order, // from a single unmined transaction. // -// Example usage: +// Example usage: // -// it := makeUnminedCreditIterator(ns, txHash) -// for it.next() { -// // Use it.elem, it.ck and it.cv -// // Optionally, use it.delete() to remove this k/v pair -// } -// if it.err != nil { -// // Handle error -// } +// it := makeUnminedCreditIterator(ns, txHash) +// for it.next() { +// // Use it.elem, it.ck and it.cv +// // Optionally, use it.delete() to remove this k/v pair +// } +// if it.err != nil { +// // Handle error +// } // // The spentness of the credit is not looked up for performance reasons (because // for unspent credits, it requires another lookup in another bucket). If this // is needed, it may be checked like this: // -// spent := existsRawUnminedInput(ns, it.ck) != nil +// spent := existsRawUnminedInput(ns, it.ck) != nil type unminedCreditIterator struct { c walletdb.ReadWriteCursor prefix []byte