rpc: reverse output order of listransactions
#14
24 changed files with 169 additions and 205 deletions
57
.github/workflows/golangci-lint.yml
vendored
57
.github/workflows/golangci-lint.yml
vendored
|
@ -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
|
|
20
.github/workflows/main.yml
vendored
20
.github/workflows/main.yml
vendored
|
@ -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
|
||||||
|
|
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
4
Makefile
4
Makefile
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
||||||
|
|
|
@ -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{} }
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -7,6 +7,5 @@ Package wallet provides ...
|
||||||
TODO: Flesh out this section
|
TODO: Flesh out this section
|
||||||
|
|
||||||
Overview
|
Overview
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package wallet
|
package wallet
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
60
wtxmgr/db.go
60
wtxmgr/db.go
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue