diff --git a/chain/bitcoind_client.go b/chain/bitcoind_client.go index a2537da617..4997877565 100644 --- a/chain/bitcoind_client.go +++ b/chain/bitcoind_client.go @@ -330,13 +330,13 @@ func (c *BitcoindClient) NotifyBlocks() error { bestHash, bestHeight, err := c.GetBestBlock() if err != nil { atomic.StoreUint32(&c.notifyBlocks, 0) - return fmt.Errorf("unable to retrieve best block: %v", err) + return fmt.Errorf("unable to retrieve best block: %w", err) } bestHeader, err := c.GetBlockHeaderVerbose(bestHash) if err != nil { atomic.StoreUint32(&c.notifyBlocks, 0) return fmt.Errorf("unable to retrieve header for best block: "+ - "%v", err) + "%w", err) } c.bestBlockMtx.Lock() @@ -517,12 +517,12 @@ func (c *BitcoindClient) Start() error { // Retrieve the best block of the chain. bestHash, bestHeight, err := c.GetBestBlock() if err != nil { - return fmt.Errorf("unable to retrieve best block: %v", err) + return fmt.Errorf("unable to retrieve best block: %w", err) } bestHeader, err := c.GetBlockHeaderVerbose(bestHash) if err != nil { return fmt.Errorf("unable to retrieve header for best block: "+ - "%v", err) + "%w", err) } c.bestBlockMtx.Lock() @@ -849,7 +849,7 @@ func (c *BitcoindClient) reorg(currentBlock waddrmgr.BlockStamp, bestHash := reorgBlock.BlockHash() bestHeight, err := c.GetBlockHeight(&bestHash) if err != nil { - return fmt.Errorf("unable to get block height for %v: %v", + return fmt.Errorf("unable to get block height for %v: %w", bestHash, err) } @@ -871,7 +871,7 @@ func (c *BitcoindClient) reorg(currentBlock waddrmgr.BlockStamp, for i := bestHeight - 1; i >= currentBlock.Height; i-- { block, err := c.GetBlock(&previousBlock) if err != nil { - return fmt.Errorf("unable to get block %v: %v", + return fmt.Errorf("unable to get block %v: %w", previousBlock, err) } blocksToNotify.PushFront(block) @@ -885,7 +885,7 @@ func (c *BitcoindClient) reorg(currentBlock waddrmgr.BlockStamp, // We'll start by retrieving the header to the best block known to us. currentHeader, err := c.GetBlockHeader(¤tBlock.Hash) if err != nil { - return fmt.Errorf("unable to get block header for %v: %v", + return fmt.Errorf("unable to get block header for %v: %w", currentBlock.Hash, err) } @@ -908,7 +908,7 @@ func (c *BitcoindClient) reorg(currentBlock waddrmgr.BlockStamp, prevBlock := ¤tHeader.PrevBlock currentHeader, err = c.GetBlockHeader(prevBlock) if err != nil { - return fmt.Errorf("unable to get block header for %v: %v", + return fmt.Errorf("unable to get block header for %v: %w", prevBlock, err) } @@ -920,7 +920,7 @@ func (c *BitcoindClient) reorg(currentBlock waddrmgr.BlockStamp, // once we've found our common ancestor. block, err := c.GetBlock(&previousBlock) if err != nil { - return fmt.Errorf("unable to get block %v: %v", + return fmt.Errorf("unable to get block %v: %w", previousBlock, err) } blocksToNotify.PushFront(block) @@ -946,7 +946,7 @@ func (c *BitcoindClient) reorg(currentBlock waddrmgr.BlockStamp, nextHash := nextBlock.BlockHash() nextHeader, err := c.GetBlockHeader(&nextHash) if err != nil { - return fmt.Errorf("unable to get block header for %v: %v", + return fmt.Errorf("unable to get block header for %v: %w", nextHash, err) } diff --git a/chain/bitcoind_conn.go b/chain/bitcoind_conn.go index 8a580dbb5c..74bfd33450 100644 --- a/chain/bitcoind_conn.go +++ b/chain/bitcoind_conn.go @@ -171,7 +171,7 @@ func NewBitcoindConn(cfg *BitcoindConfig) (*BitcoindConn, error) { chainInfo, err := client.GetBlockChainInfo() if err != nil { return nil, fmt.Errorf("unable to determine if bitcoind is "+ - "pruned: %v", err) + "pruned: %w", err) } // Only initialize the PrunedBlockDispatcher when the connected bitcoind diff --git a/chain/bitcoind_zmq_events.go b/chain/bitcoind_zmq_events.go index 66e1f3388c..337e445b31 100644 --- a/chain/bitcoind_zmq_events.go +++ b/chain/bitcoind_zmq_events.go @@ -123,7 +123,7 @@ func newBitcoindZMQEvents(cfg *ZMQConfig, client *rpcclient.Client, ) if err != nil { return nil, fmt.Errorf("unable to subscribe for zmq block "+ - "events: %v", err) + "events: %w", err) } zmqTxConn, err := gozmq.Subscribe( @@ -137,7 +137,7 @@ func newBitcoindZMQEvents(cfg *ZMQConfig, client *rpcclient.Client, } return nil, fmt.Errorf("unable to subscribe for zmq tx "+ - "events: %v", err) + "events: %w", err) } // Create the config for mempool and attach default values if not diff --git a/chain/mempool.go b/chain/mempool.go index 88a116177d..09ebc976fe 100644 --- a/chain/mempool.go +++ b/chain/mempool.go @@ -531,7 +531,7 @@ func (m *mempool) batchGetRawTxes(txids []*chainhash.Hash, // Ask the client to send all the batched requests. err := m.cfg.client.Send() if err != nil { - return fmt.Errorf("Send GetRawTransaction got %v", err) + return fmt.Errorf("Send GetRawTransaction got %w", err) } // Iterate the recievers and fetch the response. diff --git a/chain/neutrino.go b/chain/neutrino.go index b794a667e5..0cfa1c4b6d 100644 --- a/chain/neutrino.go +++ b/chain/neutrino.go @@ -103,7 +103,7 @@ func (s *NeutrinoClient) BackEnd() string { // Start replicates the RPC client's Start method. func (s *NeutrinoClient) Start() error { if err := s.CS.Start(); err != nil { - return fmt.Errorf("error starting chain service: %v", err) + return fmt.Errorf("error starting chain service: %w", err) } s.clientMtx.Lock() @@ -426,11 +426,11 @@ func (s *NeutrinoClient) Rescan(startHash *chainhash.Hash, addrs []btcutil.Addre bestBlock, err := s.CS.BestBlock() if err != nil { - return fmt.Errorf("can't get chain service's best block: %s", err) + return fmt.Errorf("can't get chain service's best block: %w", err) } header, err := s.CS.GetBlockHeader(&bestBlock.Hash) if err != nil { - return fmt.Errorf("can't get block header for hash %v: %s", + return fmt.Errorf("can't get block header for hash %v: %w", bestBlock.Hash, err) } diff --git a/chain/pruned_block_dispatcher.go b/chain/pruned_block_dispatcher.go index bf008e1a31..0cf46db153 100644 --- a/chain/pruned_block_dispatcher.go +++ b/chain/pruned_block_dispatcher.go @@ -347,7 +347,7 @@ func (d *PrunedBlockDispatcher) connectToPeer(addr string) (bool, error) { peer, err := d.newQueryPeer(addr) if err != nil { return true, fmt.Errorf("unable to configure query peer %v: "+ - "%v", addr, err) + "%w", addr, err) } // Establish the connection and wait for the protocol negotiation to diff --git a/cmd/sweepaccount/main.go b/cmd/sweepaccount/main.go index 8edabaefc3..4d5e6a8b36 100644 --- a/cmd/sweepaccount/main.go +++ b/cmd/sweepaccount/main.go @@ -36,7 +36,7 @@ func fatalf(format string, args ...interface{}) { } func errContext(err error, context string) error { - return fmt.Errorf("%s: %v", context, err) + return fmt.Errorf("%s: %w", context, err) } // Flags. diff --git a/config.go b/config.go index f3024db23f..e1715b8f03 100644 --- a/config.go +++ b/config.go @@ -249,10 +249,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 btcwallet functioning properly without any config // settings while still allowing the user to override settings with config files @@ -435,7 +435,7 @@ func loadConfig() (*config, []string, error) { // Parse, validate, and set debug log level(s). if err := parseAndSetDebugLevels(cfg.DebugLevel); err != nil { - err := fmt.Errorf("%s: %v", "loadConfig", err.Error()) + err := fmt.Errorf("%s: %w", "loadConfig", err) fmt.Fprintln(os.Stderr, err) parser.WriteHelp(os.Stderr) return nil, nil, err diff --git a/internal/legacy/keystore/keystore.go b/internal/legacy/keystore/keystore.go index a1f6d61b56..4f38e7f488 100644 --- a/internal/legacy/keystore/keystore.go +++ b/internal/legacy/keystore/keystore.go @@ -234,7 +234,7 @@ func chainedPubKey(pubkey, chaincode []byte) ([]byte, error) { var xorBytesScalar btcec.ModNScalar overflow := xorBytesScalar.SetBytes(&xorbytes) if overflow != 0 { - return nil, fmt.Errorf("unable to create pubkey: %v", err) + return nil, fmt.Errorf("unable to create pubkey due to overflow") } var ( diff --git a/rpc/legacyrpc/methods.go b/rpc/legacyrpc/methods.go index 9467f8c941..8889f121ec 100644 --- a/rpc/legacyrpc/methods.go +++ b/rpc/legacyrpc/methods.go @@ -1073,14 +1073,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) @@ -1104,15 +1107,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) @@ -1360,12 +1366,12 @@ func makeOutputs(pairs map[string]btcutil.Amount, chainParams *chaincfg.Params) for addrStr, amt := range pairs { addr, err := btcutil.DecodeAddress(addrStr, chainParams) if err != nil { - return nil, fmt.Errorf("cannot decode address: %s", err) + return nil, fmt.Errorf("cannot decode address: %w", err) } pkScript, err := txscript.PayToAddrScript(addr) if err != nil { - return nil, fmt.Errorf("cannot create txout script: %s", err) + return nil, fmt.Errorf("cannot create txout script: %w", err) } outputs = append(outputs, wire.NewTxOut(int64(amt), pkScript)) diff --git a/waddrmgr/address.go b/waddrmgr/address.go index f2ad0faa01..547cc9a4ca 100644 --- a/waddrmgr/address.go +++ b/waddrmgr/address.go @@ -1017,7 +1017,7 @@ func newWitnessScriptAddress(m *ScopedKeyManager, account uint32, scriptIdent, tweakedPubKey, err := schnorr.ParsePubKey(scriptIdent) if err != nil { return nil, fmt.Errorf("error lifting public key from "+ - "script ident: %v", err) + "script ident: %w", err) } return &taprootScriptAddress{ diff --git a/waddrmgr/db_test.go b/waddrmgr/db_test.go index c29cb851db..0eec1529f2 100644 --- a/waddrmgr/db_test.go +++ b/waddrmgr/db_test.go @@ -119,7 +119,7 @@ func TestStoreMaxReorgDepth(t *testing.T) { firstBlock := blocks[0] _, err = fetchBlockHash(ns, firstBlock.Height) if !IsError(err, ErrBlockNotFound) { - return fmt.Errorf("expected ErrBlockNotFound, got %v", + return fmt.Errorf("expected ErrBlockNotFound, got %w", err) } diff --git a/waddrmgr/error.go b/waddrmgr/error.go index bdfd90fe2a..731d347257 100644 --- a/waddrmgr/error.go +++ b/waddrmgr/error.go @@ -184,7 +184,7 @@ func (e ErrorCode) String() string { // manager operation. It is used to indicate several types of failures // including errors with caller requests such as invalid accounts or requesting // private keys against a locked address manager, errors with the database -// (ErrDatabase), errors with key chain derivation (ErrKeyChain), and errors +// (ErrDatabase), errors with keychain derivation (ErrKeyChain), and errors // related to crypto (ErrCrypto). // // The caller can use type assertions to determine if an error is a ManagerError @@ -195,7 +195,7 @@ func (e ErrorCode) String() string { // Err field set with the underlying error. type ManagerError struct { ErrorCode ErrorCode // Describes the kind of error - Description string // Human readable description of the issue + Description string // Human-readable description of the issue Err error // Underlying error } @@ -207,6 +207,11 @@ func (e ManagerError) Error() string { return e.Description } +// Unwrap returns the underlying error, if any. +func (e ManagerError) Unwrap() error { + return e.Err +} + // managerError creates a ManagerError given a set of arguments. func managerError(c ErrorCode, desc string, err error) ManagerError { return ManagerError{ErrorCode: c, Description: desc, Err: err} diff --git a/waddrmgr/manager_test.go b/waddrmgr/manager_test.go index 7a768df641..e3ea359231 100644 --- a/waddrmgr/manager_test.go +++ b/waddrmgr/manager_test.go @@ -2544,7 +2544,7 @@ func TestScopedKeyManagerManagement(t *testing.T) { _, err := mgr.Address(ns, lastAddr.Address()) if err != nil { - return fmt.Errorf("unable to find addr: %v", err) + return fmt.Errorf("unable to find addr: %w", err) } err = mgr.MarkUsed(ns, lastAddr.Address()) diff --git a/waddrmgr/migrations.go b/waddrmgr/migrations.go index 5ed0072462..df735e4ecc 100644 --- a/waddrmgr/migrations.go +++ b/waddrmgr/migrations.go @@ -291,7 +291,7 @@ func populateBirthdayBlock(ns walletdb.ReadWriteBucket) error { // We'll start by fetching our birthday timestamp. birthdayTimestamp, err := fetchBirthday(ns) if err != nil { - return fmt.Errorf("unable to fetch birthday timestamp: %v", err) + return fmt.Errorf("unable to fetch birthday timestamp: %w", err) } log.Infof("Setting the wallet's birthday block from timestamp=%v", @@ -301,7 +301,7 @@ func populateBirthdayBlock(ns walletdb.ReadWriteBucket) error { // the corresponding chain. genesisHash, err := fetchBlockHash(ns, 0) if err != nil { - return fmt.Errorf("unable to fetch genesis block hash: %v", err) + return fmt.Errorf("unable to fetch genesis block hash: %w", err) } var genesisTimestamp time.Time diff --git a/waddrmgr/scoped_manager.go b/waddrmgr/scoped_manager.go index cb8c98ce3b..1d1f56acae 100644 --- a/waddrmgr/scoped_manager.go +++ b/waddrmgr/scoped_manager.go @@ -615,7 +615,7 @@ func (s *ScopedKeyManager) AccountProperties(ns walletdb.ReadBucket, ) if err != nil { return nil, fmt.Errorf("failed to retrieve "+ - "account public key: %v", err) + "account public key: %w", err) } } } else { @@ -2170,12 +2170,12 @@ func (s *ScopedKeyManager) ImportTaprootScript(ns walletdb.ReadWriteBucket, // tweak the taproot key. taprootKey, err := tapscript.TaprootKey() if err != nil { - return nil, fmt.Errorf("error calculating script root: %v", err) + return nil, fmt.Errorf("error calculating script root: %w", err) } script, err := tlvEncodeTaprootScript(tapscript) if err != nil { - return nil, fmt.Errorf("error encoding taproot script: %v", err) + return nil, fmt.Errorf("error encoding taproot script: %w", err) } managedAddr, err := s.importScriptAddress( diff --git a/waddrmgr/tlv.go b/waddrmgr/tlv.go index fdfaf93f34..0e238b4ec3 100644 --- a/waddrmgr/tlv.go +++ b/waddrmgr/tlv.go @@ -43,7 +43,7 @@ func tlvEncodeTaprootScript(s *Tapscript) ([]byte, error) { blockBytes, err := s.ControlBlock.ToBytes() if err != nil { return nil, fmt.Errorf("error encoding control block: "+ - "%v", err) + "%w", err) } tlvRecords = append(tlvRecords, tlv.MakePrimitiveRecord( typeTapscriptControlBlock, &blockBytes, @@ -141,7 +141,7 @@ func tlvDecodeTaprootTaprootScript(tlvData []byte) (*Tapscript, error) { ) if err != nil { return nil, fmt.Errorf("error decoding control block: "+ - "%v", err) + "%w", err) } } @@ -149,7 +149,7 @@ func tlvDecodeTaprootTaprootScript(tlvData []byte) (*Tapscript, error) { s.FullOutputKey, err = schnorr.ParsePubKey(fullOutputKeyBytes) if err != nil { return nil, fmt.Errorf("error decoding full output "+ - "key: %v", err) + "key: %w", err) } } diff --git a/wallet/createtx.go b/wallet/createtx.go index da025ab4ff..83fd0e71df 100644 --- a/wallet/createtx.go +++ b/wallet/createtx.go @@ -437,11 +437,11 @@ func validateMsgTx(tx *wire.MsgTx, prevScripts [][]byte, hashCache, int64(inputValues[i]), inputFetcher, ) if err != nil { - return fmt.Errorf("cannot create script engine: %s", err) + return fmt.Errorf("cannot create script engine: %w", err) } err = vm.Execute() if err != nil { - return fmt.Errorf("cannot validate transaction: %s", err) + return fmt.Errorf("cannot validate transaction: %w", err) } } return nil diff --git a/wallet/disksync.go b/wallet/disksync.go index 550b9b25a9..3b0f08acf5 100644 --- a/wallet/disksync.go +++ b/wallet/disksync.go @@ -16,10 +16,10 @@ func checkCreateDir(path string) error { if os.IsNotExist(err) { // Attempt data directory creation if err = os.MkdirAll(path, 0700); err != nil { - return fmt.Errorf("cannot create directory: %s", err) + return fmt.Errorf("cannot create directory: %w", err) } } else { - return fmt.Errorf("error checking directory: %s", err) + return fmt.Errorf("error checking directory: %w", err) } } else { if !fi.IsDir() { diff --git a/wallet/history.go b/wallet/history.go index a33e0e1f11..571810cb6b 100644 --- a/wallet/history.go +++ b/wallet/history.go @@ -87,7 +87,7 @@ func DropTransactionHistory(db walletdb.DB, keepLabels bool) error { return waddrmgr.PutBirthdayBlock(ns, birthdayBlock) }) if err != nil { - return fmt.Errorf("failed to drop and re-create namespace: %v", + return fmt.Errorf("failed to drop and re-create namespace: %w", err) } diff --git a/wallet/import.go b/wallet/import.go index 2fba8a2c1c..9f37e93d90 100644 --- a/wallet/import.go +++ b/wallet/import.go @@ -421,7 +421,7 @@ func (w *Wallet) ImportPublicKey(pubKey *btcec.PublicKey, err = w.chainClient.NotifyReceived([]btcutil.Address{addr.Address()}) if err != nil { return fmt.Errorf("unable to subscribe for address "+ - "notifications: %v", err) + "notifications: %w", err) } return nil @@ -474,7 +474,7 @@ func (w *Wallet) ImportTaprootScript(scope waddrmgr.KeyScope, err = w.chainClient.NotifyReceived([]btcutil.Address{addr.Address()}) if err != nil { return nil, fmt.Errorf("unable to subscribe for address "+ - "notifications: %v", err) + "notifications: %w", err) } return addr, nil @@ -571,7 +571,7 @@ func (w *Wallet) ImportPrivateKey(scope waddrmgr.KeyScope, wif *btcutil.WIF, err := w.chainClient.NotifyReceived([]btcutil.Address{addr}) if err != nil { return "", fmt.Errorf("failed to subscribe for address ntfns for "+ - "address %s: %s", addr.EncodeAddress(), err) + "address %s: %w", addr.EncodeAddress(), err) } } diff --git a/wallet/psbt.go b/wallet/psbt.go index ee2c792c09..9d4457b7c0 100644 --- a/wallet/psbt.go +++ b/wallet/psbt.go @@ -96,7 +96,7 @@ func (w *Wallet) FundPsbt(packet *psbt.Packet, keyScope *waddrmgr.KeyScope, optFuncs..., ) if err != nil { - return 0, fmt.Errorf("error creating funding TX: %v", + return 0, fmt.Errorf("error creating funding TX: %w", err) } @@ -185,14 +185,14 @@ func (w *Wallet) FundPsbt(packet *psbt.Packet, keyScope *waddrmgr.KeyScope, ) if err != nil { return fmt.Errorf("fee estimation not "+ - "successful: %v", err) + "successful: %w", err) } return nil }) if err != nil { return 0, fmt.Errorf("could not add change address to "+ - "database: %v", err) + "database: %w", err) } } @@ -224,7 +224,7 @@ func (w *Wallet) FundPsbt(packet *psbt.Packet, keyScope *waddrmgr.KeyScope, // partial inputs and outputs accordingly. err = psbt.InPlaceSort(packet) if err != nil { - return 0, fmt.Errorf("could not sort PSBT: %v", err) + return 0, fmt.Errorf("could not sort PSBT: %w", err) } // The change output index might have changed after the sorting. We need @@ -262,12 +262,12 @@ func (w *Wallet) DecorateInputs(packet *psbt.Packet, failOnUnknown bool) error { continue case err != nil: - return fmt.Errorf("error fetching UTXO: %v", err) + return fmt.Errorf("error fetching UTXO: %w", err) } addr, witnessProgram, _, err := w.ScriptForOutput(utxo) if err != nil { - return fmt.Errorf("error fetching UTXO script: %v", err) + return fmt.Errorf("error fetching UTXO script: %w", err) } switch { @@ -500,7 +500,7 @@ func (w *Wallet) FinalizePsbt(keyScope *waddrmgr.KeyScope, account uint32, }) if err != nil { return fmt.Errorf("unable to determine if account is "+ - "watch-only: %v", err) + "watch-only: %w", err) } if watchOnly { continue @@ -511,7 +511,7 @@ func (w *Wallet) FinalizePsbt(keyScope *waddrmgr.KeyScope, account uint32, ) if err != nil { return fmt.Errorf("error computing input script for "+ - "input %d: %v", idx, err) + "input %d: %w", idx, err) } // Serialize the witness format from the stack representation to @@ -519,7 +519,7 @@ func (w *Wallet) FinalizePsbt(keyScope *waddrmgr.KeyScope, account uint32, var witnessBytes bytes.Buffer err = psbt.WriteTxWitness(&witnessBytes, witness) if err != nil { - return fmt.Errorf("error serializing witness: %v", err) + return fmt.Errorf("error serializing witness: %w", err) } packet.Inputs[idx].FinalScriptWitness = witnessBytes.Bytes() packet.Inputs[idx].FinalScriptSig = sigScript @@ -529,7 +529,7 @@ func (w *Wallet) FinalizePsbt(keyScope *waddrmgr.KeyScope, account uint32, // broadcast. err = psbt.MaybeFinalizeAll(packet) if err != nil { - return fmt.Errorf("error finalizing PSBT: %v", err) + return fmt.Errorf("error finalizing PSBT: %w", err) } return nil diff --git a/wallet/utxos.go b/wallet/utxos.go index 63c6b5b770..8e7d8d23aa 100644 --- a/wallet/utxos.go +++ b/wallet/utxos.go @@ -143,7 +143,7 @@ func (w *Wallet) FetchInputInfo(prevOut *wire.OutPoint) (*wire.MsgTx, _, currentHeight, err := w.chainClient.GetBestBlock() if err != nil { return nil, nil, nil, 0, fmt.Errorf("unable to retrieve current "+ - "height: %v", err) + "height: %w", err) } confs := int64(0) if txDetail.Block.Height != -1 { diff --git a/wallet/wallet.go b/wallet/wallet.go index 335025dab4..7ac328d3bd 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -422,7 +422,7 @@ func (w *Wallet) syncWithChain(birthdayStamp *waddrmgr.BlockStamp) error { chainClient, w.Manager.Birthday(), ) if err != nil { - return fmt.Errorf("unable to locate birthday block: %v", + return fmt.Errorf("unable to locate birthday block: %w", err) } @@ -458,7 +458,7 @@ func (w *Wallet) syncWithChain(birthdayStamp *waddrmgr.BlockStamp) error { }) if err != nil { return fmt.Errorf("unable to persist initial sync "+ - "data: %v", err) + "data: %w", err) } } @@ -467,7 +467,7 @@ func (w *Wallet) syncWithChain(birthdayStamp *waddrmgr.BlockStamp) error { if w.recoveryWindow > 0 { if err := w.recovery(chainClient, birthdayStamp); err != nil { return fmt.Errorf("unable to perform wallet recovery: "+ - "%v", err) + "%w", err) } } @@ -3463,7 +3463,7 @@ func (w *Wallet) SignTransaction(tx *wire.MsgTx, hashType txscript.SigHashType, txDetails, err := w.TxStore.TxDetails(txmgrNs, prevHash) if err != nil { return fmt.Errorf("cannot query previous transaction "+ - "details for %v: %v", txIn.PreviousOutPoint, err) + "details for %v: %w", txIn.PreviousOutPoint, err) } if txDetails == nil { return fmt.Errorf("%v not found", @@ -4243,7 +4243,7 @@ func MapBroadcastBackendError(err error) error { // We received an error not matching any of the above cases. default: - returnErr = fmt.Errorf("unmatched backend error: %v", err) + returnErr = fmt.Errorf("unmatched backend error: %w", err) } return returnErr diff --git a/walletdb/bdb/driver_test.go b/walletdb/bdb/driver_test.go index 2bb4edfc88..1ffb9eb422 100644 --- a/walletdb/bdb/driver_test.go +++ b/walletdb/bdb/driver_test.go @@ -203,7 +203,7 @@ func TestPersistence(t *testing.T) { for k, v := range storeValues { if err := ns1.Put([]byte(k), []byte(v)); err != nil { - return fmt.Errorf("Put: unexpected error: %v", err) + return fmt.Errorf("Put: unexpected error: %w", err) } } diff --git a/walletdb/walletdbtest/interface.go b/walletdb/walletdbtest/interface.go index da17f1256e..1e5ebaf824 100644 --- a/walletdb/walletdbtest/interface.go +++ b/walletdb/walletdbtest/interface.go @@ -690,7 +690,7 @@ func testAdditionalErrors(tc *testContext) bool { // Create a new namespace rootBucket, err := tx.CreateTopLevelBucket(ns3Key) if err != nil { - return fmt.Errorf("CreateTopLevelBucket: unexpected error: %v", err) + return fmt.Errorf("CreateTopLevelBucket: unexpected error: %w", err) } // Ensure CreateBucket returns the expected error when no bucket diff --git a/walletsetup.go b/walletsetup.go index 8c424df576..09287707e7 100644 --- a/walletsetup.go +++ b/walletsetup.go @@ -237,10 +237,10 @@ func checkCreateDir(path string) error { if os.IsNotExist(err) { // Attempt data directory creation if err = os.MkdirAll(path, 0700); err != nil { - return fmt.Errorf("cannot create directory: %s", err) + return fmt.Errorf("cannot create directory: %w", err) } } else { - return fmt.Errorf("error checking directory: %s", err) + return fmt.Errorf("error checking directory: %w", err) } } else { if !fi.IsDir() { diff --git a/wtxmgr/error.go b/wtxmgr/error.go index 7e268324b3..e1cd1d41e6 100644 --- a/wtxmgr/error.go +++ b/wtxmgr/error.go @@ -73,7 +73,7 @@ func (e ErrorCode) String() string { // operation. type Error struct { Code ErrorCode // Describes the kind of error - Desc string // Human readable description of the issue + Desc string // Human-readable description of the issue Err error // Underlying error, optional } @@ -85,6 +85,11 @@ func (e Error) Error() string { return e.Desc } +// Unwrap returns the underlying error, if any. +func (e Error) Unwrap() error { + return e.Err +} + func storeError(c ErrorCode, desc string, err error) Error { return Error{Code: c, Desc: desc, Err: err} } diff --git a/wtxmgr/tx.go b/wtxmgr/tx.go index 1af872f015..e3fe2f8f62 100644 --- a/wtxmgr/tx.go +++ b/wtxmgr/tx.go @@ -834,7 +834,7 @@ func (s *Store) UnspentOutputs(ns walletdb.ReadBucket) ([]Credit, error) { rec, err := fetchTxRecord(ns, &op.Hash, &block) if err != nil { return fmt.Errorf("unable to retrieve transaction %v: "+ - "%v", op.Hash, err) + "%w", op.Hash, err) } txOut := rec.MsgTx.TxOut[op.Index] cred := Credit{ @@ -883,7 +883,7 @@ func (s *Store) UnspentOutputs(ns walletdb.ReadBucket) ([]Credit, error) { err = readRawTxRecord(&op.Hash, recVal, &rec) if err != nil { return fmt.Errorf("unable to retrieve raw transaction "+ - "%v: %v", op.Hash, err) + "%v: %w", op.Hash, err) } txOut := rec.MsgTx.TxOut[op.Index]