From 12af59c5697053ae077a33ff789ca7291a7ba2fd Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 8 Mar 2024 16:37:47 -0800 Subject: [PATCH] Merge pull request #913 from guggero/wrap-errors Wrapp all errors --- chain/bitcoind_client.go | 20 ++++++++++---------- chain/bitcoind_conn.go | 2 +- chain/bitcoind_zmq_events.go | 4 ++-- chain/mempool.go | 2 +- chain/neutrino.go | 6 +++--- chain/pruned_block_dispatcher.go | 2 +- cmd/sweepaccount/main.go | 2 +- config.go | 2 +- internal/legacy/keystore/keystore.go | 2 +- rpc/legacyrpc/methods.go | 4 ++-- waddrmgr/address.go | 2 +- waddrmgr/db_test.go | 2 +- waddrmgr/error.go | 9 +++++++-- waddrmgr/manager_test.go | 2 +- waddrmgr/migrations.go | 4 ++-- waddrmgr/scoped_manager.go | 6 +++--- waddrmgr/tlv.go | 6 +++--- wallet/createtx.go | 4 ++-- wallet/disksync.go | 4 ++-- wallet/history.go | 2 +- wallet/import.go | 6 +++--- wallet/psbt.go | 20 ++++++++++---------- wallet/utxos.go | 2 +- wallet/wallet.go | 10 +++++----- walletdb/bdb/driver_test.go | 2 +- walletdb/walletdbtest/interface.go | 2 +- walletsetup.go | 4 ++-- wtxmgr/error.go | 7 ++++++- wtxmgr/tx.go | 4 ++-- 29 files changed, 77 insertions(+), 67 deletions(-) diff --git a/chain/bitcoind_client.go b/chain/bitcoind_client.go index fbb95e2f1c..97b535bbcc 100644 --- a/chain/bitcoind_client.go +++ b/chain/bitcoind_client.go @@ -320,13 +320,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() @@ -507,12 +507,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() @@ -839,7 +839,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) } @@ -861,7 +861,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) @@ -875,7 +875,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) } @@ -898,7 +898,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) } @@ -910,7 +910,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) @@ -936,7 +936,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 59de1aaae0..2c8d7fc5b6 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 894aafe237..7de533adab 100644 --- a/chain/bitcoind_zmq_events.go +++ b/chain/bitcoind_zmq_events.go @@ -124,7 +124,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( @@ -138,7 +138,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 414b3f2014..60fb105cb4 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 04e2f72d79..0df801400b 100644 --- a/chain/neutrino.go +++ b/chain/neutrino.go @@ -94,7 +94,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() @@ -407,11 +407,11 @@ func (s *NeutrinoClient) Rescan(startHash *chainhash.Hash, addrs []ltcutil.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 543dec3a9a..0c12e187b3 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 2c946c2521..5f002c85b2 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 995ad809f3..bf2a62420f 100644 --- a/config.go +++ b/config.go @@ -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 5ab53f7fe3..e74716c786 100644 --- a/internal/legacy/keystore/keystore.go +++ b/internal/legacy/keystore/keystore.go @@ -233,7 +233,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 c8166d42d8..df86797378 100644 --- a/rpc/legacyrpc/methods.go +++ b/rpc/legacyrpc/methods.go @@ -1366,12 +1366,12 @@ func makeOutputs(pairs map[string]ltcutil.Amount, chainParams *chaincfg.Params) for addrStr, amt := range pairs { addr, err := ltcutil.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 1405e56d61..d1f471f9fe 100644 --- a/waddrmgr/address.go +++ b/waddrmgr/address.go @@ -1018,7 +1018,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 472b636731..34dc801207 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 72ec11d647..440c2891aa 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 0fbbaed10d..d6f38b6340 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 d92eaeef58..e07c8a795b 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 59fffd6f98..380347954d 100644 --- a/waddrmgr/scoped_manager.go +++ b/waddrmgr/scoped_manager.go @@ -655,7 +655,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 { @@ -2210,12 +2210,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 05dfb00d67..0b59abfcd1 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 289e634e0b..7c0dc12760 100644 --- a/wallet/createtx.go +++ b/wallet/createtx.go @@ -431,11 +431,11 @@ func validateMsgTx(tx *wire.MsgTx, prevScripts [][]byte, inputValues []ltcutil.A txscript.StandardVerifyFlags, nil, 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 79ae0cc5a4..01a3e49c3f 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 70a2e17ac1..46d567a932 100644 --- a/wallet/import.go +++ b/wallet/import.go @@ -421,7 +421,7 @@ func (w *Wallet) ImportPublicKey(pubKey *btcec.PublicKey, err = w.chainClient.NotifyReceived([]ltcutil.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([]ltcutil.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 *ltcutil.WIF, err := w.chainClient.NotifyReceived([]ltcutil.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 bb326c2f5d..8080d2b62a 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 1e4c85c698..e527b34bc2 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 4201e4df6a..d73e5f0096 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", @@ -4233,7 +4233,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 d0792b3243..dda16ea1b2 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 c13caf898b..8675fa526b 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 7dd72ca3a8..a32b48001f 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 2900eb0d83..4b86e2abfe 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]