rpc: reverse output order of listransactions #14

Merged
roylee17 merged 4 commits from roylee/reverse-order-of-listransactions into master 2022-08-08 10:26:28 +02:00
24 changed files with 169 additions and 205 deletions

View file

@ -1,57 +0,0 @@
name: golangci-lint
env:
# go needs absolute directories, using the $HOME variable doesn't work here.
GOCACHE: /home/runner/work/go/pkg/build
GOPATH: /home/runner/work/go
GO_VERSION: '^1.18.2'
on:
push:
tags:
- v*
branches:
- "*"
pull_request:
branches:
- "*"
jobs:
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- name: setup go ${{ env.GO_VERSION }}
uses: actions/setup-go@v2
with:
go-version: '${{ env.GO_VERSION }}'
- name: checkout source
uses: actions/checkout@v2
- name: compile code
run: go install -v ./...
- name: golangci-lint
uses: golangci/golangci-lint-action@v2
with:
# Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
version: latest
# Optional: working directory, useful for monorepos
# working-directory: somedir
# Optional: golangci-lint command line arguments.
# args: --issues-exit-code=0
# Optional: show only new issues if it's a pull request. The default value is `false`.
# only-new-issues: true
# Optional: if set to true then the action will use pre-installed Go.
skip-go-installation: true
# Optional: if set to true then the action don't cache or restore ~/go/pkg.
# skip-pkg-cache: true
# Optional: if set to true then the action don't cache or restore ~/.cache/go-build.
# skip-build-cache: true

View file

@ -26,32 +26,32 @@ env:
GOCACHE: /home/runner/work/go/pkg/build GOCACHE: /home/runner/work/go/pkg/build
GOPATH: /home/runner/work/go GOPATH: /home/runner/work/go
GO_VERSION: '^1.18.2' GO_VERSION: '^1.19'
jobs: jobs:
######################## ########################
# Format, compileation and lint check # Format, compileation and lint check
######################## ########################
golangci: lint-check:
name: lint name: Format, compilation and lint check
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: git checkout
uses: actions/checkout@v2
- name: setup go ${{ env.GO_VERSION }} - name: setup go ${{ env.GO_VERSION }}
uses: actions/setup-go@v2 uses: actions/setup-go@v2
with: with:
go-version: '${{ env.GO_VERSION }}' go-version: '${{ env.GO_VERSION }}'
- name: checkout source - name: run format
uses: actions/checkout@v2 run: make fmt
- name: compile code - name: compile code
run: go install -v ./... run: go install -v ./...
- name: golangci-lint - name: run lint
uses: golangci/golangci-lint-action@v2 run: make lint
with:
version: latest
skip-go-installation: true
######################## ########################
# run unit tests # run unit tests

View file

@ -28,7 +28,7 @@ jobs:
name: Set up Go name: Set up Go
uses: actions/setup-go@v2 uses: actions/setup-go@v2
with: with:
go-version: 1.18.2 go-version: 1.19
# Login against a Docker registry except on PR # Login against a Docker registry except on PR
# https://github.com/docker/login-action # https://github.com/docker/login-action

View file

@ -103,7 +103,7 @@ linters:
# - noctx # - noctx
# - nolintlint # - nolintlint
# - prealloc # - prealloc
- rowserrcheck # - rowserrcheck # Disabled due to generic, see https://github.com/golangci/golangci-lint/issues/2649
# - revive # - revive
# - scopelint # - scopelint
# - staticcheck # - staticcheck

View file

@ -15,7 +15,7 @@
ARG ARCH=amd64 ARG ARCH=amd64
FROM golang:1.18.2 AS build-container FROM golang:1.19 AS build-container
ARG ARCH ARG ARCH

View file

@ -9,8 +9,8 @@ GO_BIN := ${GOPATH}/bin
LINT_BIN := ${GO_BIN}/golangci-lint LINT_BIN := ${GO_BIN}/golangci-lint
GOACC_BIN := $(GO_BIN)/go-acc GOACC_BIN := $(GO_BIN)/go-acc
LINT_COMMIT := v1.42.1 LINT_COMMIT := v1.48
GOACC_COMMIT := v0.2.6 GOACC_COMMIT := v0.2.8
DEPGET := go install DEPGET := go install
GOBUILD := go build -v GOBUILD := go build -v

View file

@ -25,7 +25,9 @@ func BackEnds() []string {
} }
// Interface allows more than one backing blockchain source, such as a // 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. // it.
type Interface interface { type Interface interface {
Start() error Start() error

View file

@ -66,7 +66,8 @@ func pipe(c1, c2 *conn) (*conn, *conn) {
// returns the root of the tree. // returns the root of the tree.
// //
// This function was copied from: // 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 { func calcMerkleRoot(txns []*wire.MsgTx) chainhash.Hash {
if len(txns) == 0 { if len(txns) == 0 {
return chainhash.Hash{} return chainhash.Hash{}
@ -86,7 +87,8 @@ func calcMerkleRoot(txns []*wire.MsgTx) chainhash.Hash {
// with the solution. False is returned if no solution exists. // with the solution. False is returned if no solution exists.
// //
// This function was copied from: // 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 { func solveBlock(header *wire.BlockHeader) bool {
// sbResult is used by the solver goroutines to send results. // sbResult is used by the solver goroutines to send results.
type sbResult struct { type sbResult struct {

View file

@ -251,10 +251,10 @@ func parseAndSetDebugLevels(debugLevel string) error {
// line options. // line options.
// //
// The configuration proceeds as follows: // The configuration proceeds as follows:
// 1) Start with a default config with sane settings // 1. Start with a default config with sane settings
// 2) Pre-parse the command line to check for an alternative config file // 2. Pre-parse the command line to check for an alternative config file
// 3) Load configuration file overwriting defaults with any specified options // 3. Load configuration file overwriting defaults with any specified options
// 4) Parse CLI options and overwrite/add any specified options // 4. Parse CLI options and overwrite/add any specified options
// //
// The above results in lbcwallet functioning properly without any config // The above results in lbcwallet functioning properly without any config
// settings while still allowing the user to override settings with config files // settings while still allowing the user to override settings with config files

View file

@ -18,7 +18,8 @@ type Params struct {
} }
// MainNetParams contains parameters specific running lbcwallet and // MainNetParams contains parameters specific running lbcwallet and
// on the main network (wire.MainNet). //
// on the main network (wire.MainNet).
var MainNetParams = Params{ var MainNetParams = Params{
Params: &chaincfg.MainNetParams, Params: &chaincfg.MainNetParams,
RPCClientPort: "9245", RPCClientPort: "9245",
@ -26,7 +27,8 @@ var MainNetParams = Params{
} }
// TestNet3Params contains parameters specific running lbcwallet and // 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{ var TestNet3Params = Params{
Params: &chaincfg.TestNet3Params, Params: &chaincfg.TestNet3Params,
RPCClientPort: "19245", RPCClientPort: "19245",

View file

@ -1226,14 +1226,17 @@ func listLockUnspent(icmd interface{}, w *wallet.Wallet) (interface{}, error) {
// listReceivedByAccount handles a listreceivedbyaccount request by returning // listReceivedByAccount handles a listreceivedbyaccount request by returning
// a slice of objects, each one containing: // a slice of objects, each one containing:
// "account": the receiving account; //
// "amount": total amount received by the account; // "account": the receiving account;
// "confirmations": number of confirmations of the most recent transaction. // "amount": total amount received by the account;
// "confirmations": number of confirmations of the most recent transaction.
//
// It takes two parameters: // It takes two parameters:
// "minconf": minimum number of confirmations to consider a transaction - //
// default: one; // "minconf": minimum number of confirmations to consider a transaction -
// "includeempty": whether or not to include addresses that have no transactions - // default: one;
// default: false. // "includeempty": whether or not to include addresses that have no transactions -
// default: false.
func listReceivedByAccount(icmd interface{}, w *wallet.Wallet) (interface{}, error) { func listReceivedByAccount(icmd interface{}, w *wallet.Wallet) (interface{}, error) {
cmd := icmd.(*btcjson.ListReceivedByAccountCmd) cmd := icmd.(*btcjson.ListReceivedByAccountCmd)
@ -1257,15 +1260,18 @@ func listReceivedByAccount(icmd interface{}, w *wallet.Wallet) (interface{}, err
// listReceivedByAddress handles a listreceivedbyaddress request by returning // listReceivedByAddress handles a listreceivedbyaddress request by returning
// a slice of objects, each one containing: // a slice of objects, each one containing:
// "account": the account of the receiving address; //
// "address": the receiving address; // "account": the account of the receiving address;
// "amount": total amount received by the address; // "address": the receiving address;
// "confirmations": number of confirmations of the most recent transaction. // "amount": total amount received by the address;
// "confirmations": number of confirmations of the most recent transaction.
//
// It takes two parameters: // It takes two parameters:
// "minconf": minimum number of confirmations to consider a transaction - //
// default: one; // "minconf": minimum number of confirmations to consider a transaction -
// "includeempty": whether or not to include addresses that have no transactions - // default: one;
// default: false. // "includeempty": whether or not to include addresses that have no transactions -
// default: false.
func listReceivedByAddress(icmd interface{}, w *wallet.Wallet) (interface{}, error) { func listReceivedByAddress(icmd interface{}, w *wallet.Wallet) (interface{}, error) {
cmd := icmd.(*btcjson.ListReceivedByAddressCmd) cmd := icmd.(*btcjson.ListReceivedByAddressCmd)
@ -1861,6 +1867,12 @@ func signRawTransaction(icmd interface{}, w *wallet.Wallet, chainClient *chain.R
if err != nil { if err != nil {
return nil, err return nil, err
} }
if result == nil {
return nil, &btcjson.RPCError{
Code: btcjson.ErrRPCNoTxInfo,
Message: "Input %s not found" + outPoint.String(),
}
}
script, err := hex.DecodeString(result.ScriptPubKey.Hex) script, err := hex.DecodeString(result.ScriptPubKey.Hex)
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -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 // httpBasicAuth returns the UTF-8 bytes of the HTTP Basic authentication
// string: // string:
// //
// "Basic " + base64(username + ":" + password) // "Basic " + base64(username + ":" + password)
func httpBasicAuth(username, password string) []byte { func httpBasicAuth(username, password string) []byte {
const header = "Basic " const header = "Basic "
base64 := base64.StdEncoding base64 := base64.StdEncoding

View file

@ -8,11 +8,11 @@
// Full documentation of the API implemented by this package is maintained in a // Full documentation of the API implemented by this package is maintained in a
// language-agnostic document: // 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: // 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 package rpcserver
import ( import (
@ -487,12 +487,12 @@ func (s *walletServer) SignTransaction(ctx context.Context, req *pb.SignTransact
} }
// BUGS: // BUGS:
// - The transaction is not inspected to be relevant before publishing using // - The transaction is not inspected to be relevant before publishing using
// sendrawtransaction, so connection errors to could result in the tx // sendrawtransaction, so connection errors to could result in the tx
// never being added to the wallet database. // never being added to the wallet database.
// - Once the above bug is fixed, wallet will require a way to purge invalid // - 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 // transactions from the database when they are rejected by the network, other
// than double spending them. // than double spending them.
func (s *walletServer) PublishTransaction(ctx context.Context, req *pb.PublishTransactionRequest) ( func (s *walletServer) PublishTransaction(ctx context.Context, req *pb.PublishTransactionRequest) (
*pb.PublishTransactionResponse, error) { *pb.PublishTransactionResponse, error) {

View file

@ -5,9 +5,11 @@
Package walletrpc is a generated protocol buffer package. Package walletrpc is a generated protocol buffer package.
It is generated from these files: It is generated from these files:
api.proto api.proto
It has these top-level messages: It has these top-level messages:
VersionRequest VersionRequest
VersionResponse VersionResponse
TransactionDetails TransactionDetails
@ -1435,7 +1437,7 @@ type StartConsensusRpcRequest struct {
Username string `protobuf:"bytes,2,opt,name=username" json:"username,omitempty"` Username string `protobuf:"bytes,2,opt,name=username" json:"username,omitempty"`
Password []byte `protobuf:"bytes,3,opt,name=password,proto3" json:"password,omitempty"` Password []byte `protobuf:"bytes,3,opt,name=password,proto3" json:"password,omitempty"`
Certificate []byte `protobuf:"bytes,4,opt,name=certificate,proto3" json:"certificate,omitempty"` Certificate []byte `protobuf:"bytes,4,opt,name=certificate,proto3" json:"certificate,omitempty"`
SkipVerify bool `protobuf:"varint,5,opt,name=skipverify,proto3" json:"skipverify,omitempty"` SkipVerify bool `protobuf:"varint,5,opt,name=skipverify,proto3" json:"skipverify,omitempty"`
} }
func (m *StartConsensusRpcRequest) Reset() { *m = StartConsensusRpcRequest{} } func (m *StartConsensusRpcRequest) Reset() { *m = StartConsensusRpcRequest{} }

View file

@ -2383,9 +2383,10 @@ func putBirthday(ns walletdb.ReadWriteBucket, t time.Time) error {
// FetchBirthdayBlock retrieves the birthday block from the database. // FetchBirthdayBlock retrieves the birthday block from the database.
// //
// The block is serialized as follows: // The block is serialized as follows:
// [0:4] block height //
// [4:36] block hash // [0:4] block height
// [36:44] block timestamp // [4:36] block hash
// [36:44] block timestamp
func FetchBirthdayBlock(ns walletdb.ReadBucket) (BlockStamp, error) { func FetchBirthdayBlock(ns walletdb.ReadBucket) (BlockStamp, error) {
var block BlockStamp var block BlockStamp
@ -2423,9 +2424,10 @@ func DeleteBirthdayBlock(ns walletdb.ReadWriteBucket) error {
// PutBirthdayBlock stores the provided birthday block to the database. // PutBirthdayBlock stores the provided birthday block to the database.
// //
// The block is serialized as follows: // The block is serialized as follows:
// [0:4] block height //
// [4:36] block hash // [0:4] block height
// [36:44] block timestamp // [4:36] block hash
// [36:44] block timestamp
// //
// NOTE: This does not alter the birthday block verification state. // NOTE: This does not alter the birthday block verification state.
func PutBirthdayBlock(ns walletdb.ReadWriteBucket, block BlockStamp) error { func PutBirthdayBlock(ns walletdb.ReadWriteBucket, block BlockStamp) error {

View file

@ -6,7 +6,7 @@
Package waddrmgr provides a secure hierarchical deterministic wallet address Package waddrmgr provides a secure hierarchical deterministic wallet address
manager. manager.
Overview # Overview
One of the fundamental jobs of a wallet is to manage addresses, private keys, 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 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 manager actively zeros all private material from memory. In addition, temp
private key material used internally is zeroed as soon as it's used. 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 As previously mentioned, this package provide facilities for locking and
unlocking the address manager to protect access to private material and remove 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 it from memory when locked. The Lock, Unlock, and IsLocked functions are used
for this purpose. 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 new address manager is created via the Create function. This function accepts
a wallet database namespace, passphrases, network, and perhaps most importantly, 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 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. 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 An existing address manager is opened via the Open function. This function
accepts an existing wallet database namespace, the public passphrase, and accepts an existing wallet database namespace, the public passphrase, and
network. The address manager is opened locked as expected since the open network. The address manager is opened locked as expected since the open
function does not take the private passphrase to unlock it. 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 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 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 down the database and ensures all private and public key material is purged from
memory. memory.
Managed Addresses # Managed Addresses
Each address returned by the address manager satisifies the ManagedAddress Each address returned by the address manager satisifies the ManagedAddress
interface as well as either the ManagedPubKeyAddress or ManagedScriptAddress interface as well as either the ManagedPubKeyAddress or ManagedScriptAddress
interfaces. These interfaces provide the means to obtain relevant information interfaces. These interfaces provide the means to obtain relevant information
about the addresses such as their private keys and scripts. 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. Most callers will make use of the chained addresses for normal operations.
Internal addresses are intended for internal wallet uses such as change outputs, 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 functions can be used to get the most recently provided internal and external
address, respectively. address, respectively.
Requesting Existing Addresses # Requesting Existing Addresses
In addition to generating new addresses, access to old addresses is often In addition to generating new addresses, access to old addresses is often
required. Most notably, to sign transactions in order to redeem them. The required. Most notably, to sign transactions in order to redeem them. The
Address function provides this capability and returns a ManagedAddress. 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 While the recommended approach is to use the chained addresses discussed above
because they can be deterministically regenerated to avoid losing funds as long 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 keys in Wallet Import Format (WIF) and hence the associated public key and
address. address.
Importing Scripts # Importing Scripts
In order to support pay-to-script-hash transactions, the script must be securely 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 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 variety of scenarios, however the most common use is currently multi-signature
transactions. transactions.
Syncing # Syncing
The address manager also supports storing and retrieving a block hash and height 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 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 itself does not have any notion of which addresses are synced or not. It only
provides the storage as a convenience for the caller. 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 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 appropriate addresses and reject imported addresses and scripts which don't
apply to the associated network. apply to the associated network.
Errors # Errors
All errors returned from this package are of type ManagerError. This allows the All errors returned from this package are of type ManagerError. This allows the
caller to programmatically ascertain the specific reasons for failure by 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 error codes, as documented by the specific error codes, the underlying error
will be contained in the Err field. will be contained in the Err field.
Bitcoin Improvement Proposals # Bitcoin Improvement Proposals
This package includes concepts outlined by the following BIPs: This package includes concepts outlined by the following BIPs:
BIP0032 (https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) BIP0032 (https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)
BIP0043 (https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki) BIP0043 (https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki)
BIP0044 (https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) BIP0044 (https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)
*/ */
package waddrmgr package waddrmgr

View file

@ -1479,7 +1479,8 @@ func deriveCoinTypeKey(masterNode *hdkeychain.ExtendedKey,
// hierarchy described by BIP0044 given the master node. // hierarchy described by BIP0044 given the master node.
// //
// In particular this is the hierarchical deterministic extended key path: // In particular this is the hierarchical deterministic extended key path:
// m/purpose'/<coin type>'/<account>' //
// m/purpose'/<coin type>'/<account>'
func deriveAccountKey(coinTypeKey *hdkeychain.ExtendedKey, func deriveAccountKey(coinTypeKey *hdkeychain.ExtendedKey,
account uint32) (*hdkeychain.ExtendedKey, error) { account uint32) (*hdkeychain.ExtendedKey, error) {
@ -1502,7 +1503,8 @@ func deriveAccountKey(coinTypeKey *hdkeychain.ExtendedKey,
// already derived accordingly. // already derived accordingly.
// //
// In particular this is the hierarchical deterministic extended key path: // In particular this is the hierarchical deterministic extended key path:
// m/purpose'/<coin type>'/<account>'/<branch> //
// m/purpose'/<coin type>'/<account>'/<branch>
// //
// The branch is 0 for external addresses and 1 for internal addresses. // The branch is 0 for external addresses and 1 for internal addresses.
func checkBranchKeys(acctKey *hdkeychain.ExtendedKey) error { func checkBranchKeys(acctKey *hdkeychain.ExtendedKey) error {

View file

@ -7,6 +7,5 @@ Package wallet provides ...
TODO: Flesh out this section TODO: Flesh out this section
Overview Overview
*/ */
package wallet package wallet

View file

@ -189,11 +189,11 @@ func (rm *RecoveryManager) State() *RecoveryState {
// //
// These are defined as: // These are defined as:
// - Inter-Block Gap: The maximum difference between the derived child indexes // - Inter-Block Gap: The maximum difference between the derived child indexes
// of the last addresses used in any block and the next address consumed // of the last addresses used in any block and the next address consumed
// by a later block. // by a later block.
// - Intra-Block Gap: The maximum difference between the derived child indexes // - 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 // of the first address used in any block and the last address used in the
// same block. // same block.
type RecoveryState struct { type RecoveryState struct {
// recoveryWindow defines the key-derivation lookahead used when // recoveryWindow defines the key-derivation lookahead used when
// attempting to recover the set of used addresses. This value will be // attempting to recover the set of used addresses. This value will be
@ -282,12 +282,12 @@ func NewScopeRecoveryState(recoveryWindow uint32) *ScopeRecoveryState {
// derivation branch. // derivation branch.
// //
// A branch recovery state supports operations for: // A branch recovery state supports operations for:
// - Expanding the look-ahead horizon based on which indexes have been found. // - Expanding the look-ahead horizon based on which indexes have been found.
// - Registering derived addresses with indexes within the horizon. // - Registering derived addresses with indexes within the horizon.
// - Reporting an invalid child index that falls into the horizon. // - Reporting an invalid child index that falls into the horizon.
// - Reporting that an address has been found. // - Reporting that an address has been found.
// - Retrieving all currently derived addresses for the branch. // - Retrieving all currently derived addresses for the branch.
// - Looking up a particular address by its child index. // - Looking up a particular address by its child index.
type BranchRecoveryState struct { type BranchRecoveryState struct {
// recoveryWindow defines the key-derivation lookahead used when // recoveryWindow defines the key-derivation lookahead used when
// attempting to recover the set of addresses on this branch. // attempting to recover the set of addresses on this branch.

View file

@ -756,13 +756,13 @@ func (w *Wallet) recovery(chainClient chain.Interface,
// previously used addresses for a particular account derivation path. At a high // previously used addresses for a particular account derivation path. At a high
// level, the algorithm works as follows: // level, the algorithm works as follows:
// //
// 1) Ensure internal and external branch horizons are fully expanded. // 1. Ensure internal and external branch horizons are fully expanded.
// 2) Filter the entire range of blocks, stopping if a non-zero number of // 2. Filter the entire range of blocks, stopping if a non-zero number of
// address are contained in a particular block. // address are contained in a particular block.
// 3) Record all internal and external addresses found in the 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 // 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. // 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. // 6. Repeat from (1) if there are still more blocks in the range.
// //
// TODO(conner): parallelize/pipeline/cache intermediate network requests // TODO(conner): parallelize/pipeline/cache intermediate network requests
func (w *Wallet) recoverScopedAddresses( func (w *Wallet) recoverScopedAddresses(
@ -2093,13 +2093,9 @@ func (w *Wallet) ListTransactions(from, count int) ([]btcjson.ListTransactionsRe
// include the next count transactions. // include the next count transactions.
skipped := 0 skipped := 0
n := 0 n := 0
rangeFn := func(details []wtxmgr.TxDetails) (bool, error) { rangeFn := func(details []wtxmgr.TxDetails) (bool, error) {
// Iterate over transactions at this height in reverse order.
// This does nothing for unmined transactions, which are for _, detail := range details {
// unsorted, but it will process mined transactions in the
// reverse order they were marked mined.
for i := len(details) - 1; i >= 0; i-- {
if from > skipped { if from > skipped {
skipped++ skipped++
continue continue
@ -2110,7 +2106,7 @@ func (w *Wallet) ListTransactions(from, count int) ([]btcjson.ListTransactionsRe
return true, nil return true, nil
} }
jsonResults := listTransactions(tx, &details[i], jsonResults := listTransactions(tx, &detail,
w.Manager, syncBlock.Height, w.chainParams) w.Manager, syncBlock.Height, w.chainParams)
txList = append(txList, jsonResults...) 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 // Return newer results first by starting at mempool height and working
// down to the genesis block. // 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 return txList, err
} }

View file

@ -17,7 +17,7 @@ var (
) )
// TestLocateBirthdayBlock ensures we can properly map a block in the chain to a // TestLocateBirthdayBlock ensures we can properly map a block in the chain to a
//timestamp. // timestamp.
func TestLocateBirthdayBlock(t *testing.T) { func TestLocateBirthdayBlock(t *testing.T) {
t.Parallel() t.Parallel()

View file

@ -6,7 +6,7 @@
Package bdb implements an instance of walletdb that uses boltdb for the backing Package bdb implements an instance of walletdb that uses boltdb for the backing
datastore. datastore.
Usage # Usage
This package is only a driver to the walletdb package and provides the database 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 type of "bdb". The only parameters the Open and Create functions take are the

View file

@ -5,7 +5,7 @@
/* /*
Package walletdb provides a namespaced database interface for lbcwallet. Package walletdb provides a namespaced database interface for lbcwallet.
Overview # Overview
A wallet essentially consists of a multitude of stored data such as private 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 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: A quick overview of the features walletdb provides are as follows:
- Key/value store - Key/value store
- Namespace support - Namespace support
- Allows multiple packages to have their own area in the database without - Allows multiple packages to have their own area in the database without
worrying about conflicts worrying about conflicts
- Read-only and read-write transactions with both manual and managed modes - Read-only and read-write transactions with both manual and managed modes
- Nested buckets - Nested buckets
- Supports registration of backend databases - Supports registration of backend databases
- Comprehensive test coverage - Comprehensive test coverage
Database # Database
The main entry point is the DB interface. It exposes functionality for The main entry point is the DB interface. It exposes functionality for
creating, retrieving, and removing namespaces. It is obtained via the Create 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 specific database driver (backend) to use as well as arguments specific to the
specified driver. specified driver.
Namespaces # Namespaces
The Namespace interface is an abstraction that provides facilities for obtaining The Namespace interface is an abstraction that provides facilities for obtaining
transactions (the Tx interface) that are the basis of all database reads and 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 functions provide a managed transaction. These are described in more detail
below. below.
Transactions # Transactions
The Tx interface provides facilities for rolling back or commiting changes that 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 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 under which all keys, values, and nested buckets are stored. A transaction
can either be read-only or read-write and managed or unmanaged. 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 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 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 open for long periods of time can have several adverse effects, so it is
recommended that managed transactions are used instead. recommended that managed transactions are used instead.
Buckets # Buckets
The Bucket interface provides the ability to manipulate key/value pairs and The Bucket interface provides the ability to manipulate key/value pairs and
nested buckets as well as iterate through them. 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 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. 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 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 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 the same time as the namespace. Use the RootBucket function on the Tx interface
to retrieve it. to retrieve it.
Nested Buckets # Nested Buckets
The CreateBucket and CreateBucketIfNotExists functions on the Bucket interface The CreateBucket and CreateBucketIfNotExists functions on the Bucket interface
provide the ability to create an arbitrary number of nested buckets. It is provide the ability to create an arbitrary number of nested buckets. It is

View file

@ -678,21 +678,21 @@ func deleteRawCredit(ns walletdb.ReadWriteBucket, k []byte) error {
// //
// Example usage: // Example usage:
// //
// prefix := keyTxRecord(txHash, block) // prefix := keyTxRecord(txHash, block)
// it := makeCreditIterator(ns, prefix) // it := makeCreditIterator(ns, prefix)
// for it.next() { // for it.next() {
// // Use it.elem // // Use it.elem
// // If necessary, read additional details from it.ck, it.cv // // If necessary, read additional details from it.ck, it.cv
// } // }
// if it.err != nil { // if it.err != nil {
// // Handle error // // Handle error
// } // }
// //
// The elem's Spent field is not set to true if the credit is spent by an // The elem's Spent field is not set to true if the credit is spent by an
// unmined transaction. To check for this case: // unmined transaction. To check for this case:
// //
// k := canonicalOutPoint(&txHash, it.elem.Index) // k := canonicalOutPoint(&txHash, it.elem.Index)
// it.elem.Spent = existsRawUnminedInput(ns, k) != nil // it.elem.Spent = existsRawUnminedInput(ns, k) != nil
type creditIterator struct { type creditIterator struct {
c walletdb.ReadWriteCursor // Set to nil after final iteration c walletdb.ReadWriteCursor // Set to nil after final iteration
prefix []byte prefix []byte
@ -918,15 +918,15 @@ func deleteRawDebit(ns walletdb.ReadWriteBucket, k []byte) error {
// //
// Example usage: // Example usage:
// //
// prefix := keyTxRecord(txHash, block) // prefix := keyTxRecord(txHash, block)
// it := makeDebitIterator(ns, prefix) // it := makeDebitIterator(ns, prefix)
// for it.next() { // for it.next() {
// // Use it.elem // // Use it.elem
// // If necessary, read additional details from it.ck, it.cv // // If necessary, read additional details from it.ck, it.cv
// } // }
// if it.err != nil { // if it.err != nil {
// // Handle error // // Handle error
// } // }
type debitIterator struct { type debitIterator struct {
c walletdb.ReadWriteCursor // Set to nil after final iteration c walletdb.ReadWriteCursor // Set to nil after final iteration
prefix []byte prefix []byte
@ -1092,22 +1092,22 @@ func deleteRawUnminedCredit(ns walletdb.ReadWriteBucket, k []byte) error {
// unminedCreditIterator allows for cursor iteration over all credits, in order, // unminedCreditIterator allows for cursor iteration over all credits, in order,
// from a single unmined transaction. // from a single unmined transaction.
// //
// Example usage: // Example usage:
// //
// it := makeUnminedCreditIterator(ns, txHash) // it := makeUnminedCreditIterator(ns, txHash)
// for it.next() { // for it.next() {
// // Use it.elem, it.ck and it.cv // // Use it.elem, it.ck and it.cv
// // Optionally, use it.delete() to remove this k/v pair // // Optionally, use it.delete() to remove this k/v pair
// } // }
// if it.err != nil { // if it.err != nil {
// // Handle error // // Handle error
// } // }
// //
// The spentness of the credit is not looked up for performance reasons (because // 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 // for unspent credits, it requires another lookup in another bucket). If this
// is needed, it may be checked like this: // is needed, it may be checked like this:
// //
// spent := existsRawUnminedInput(ns, it.ck) != nil // spent := existsRawUnminedInput(ns, it.ck) != nil
type unminedCreditIterator struct { type unminedCreditIterator struct {
c walletdb.ReadWriteCursor c walletdb.ReadWriteCursor
prefix []byte prefix []byte