From 318d81bc90f68adc6a615ffab003680a59c07acc Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 25 Aug 2023 15:24:16 -0500 Subject: [PATCH] multi: Wrap errors for better errors.Is/As support. This updates all remaining cases of unwrapped errors in fmt.Errorf calls to wrap the underlying errors with the %w format verb to ensure they work nicely with errors.Is and errors.As. --- addrmgr/addrmanager.go | 14 ++++++------- certgen/certgen.go | 12 +++++------ certgen/certgen_ed25519.go | 12 +++++------ cmd/gencerts/gencerts.go | 12 +++++------ dcrutil/util.go | 4 ++-- internal/blockchain/utxobackend_test.go | 8 ++++---- internal/fees/estimator.go | 25 +++++++++++------------ internal/staging/banmanager/banmanager.go | 4 ++-- rpcclient/infrastructure.go | 2 +- service_windows.go | 13 ++++++------ txscript/sign/sign.go | 8 ++++---- txscript/sign/sign_test.go | 12 +++++------ wire/error.go | 6 +++--- 13 files changed, 64 insertions(+), 68 deletions(-) diff --git a/addrmgr/addrmanager.go b/addrmgr/addrmanager.go index f0dcb44bdd..5b189c3792 100644 --- a/addrmgr/addrmanager.go +++ b/addrmgr/addrmanager.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2014 The btcsuite developers -// Copyright (c) 2015-2021 The Decred developers +// Copyright (c) 2015-2023 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -531,7 +531,7 @@ func (a *AddrManager) deserializePeers(filePath string) error { } r, err := os.Open(filePath) if err != nil { - return fmt.Errorf("%s error opening file: %v", filePath, err) + return fmt.Errorf("%s error opening file: %w", filePath, err) } defer r.Close() @@ -539,7 +539,7 @@ func (a *AddrManager) deserializePeers(filePath string) error { dec := json.NewDecoder(r) err = dec.Decode(&sam) if err != nil { - return fmt.Errorf("error reading %s: %v", filePath, err) + return fmt.Errorf("error reading %s: %w", filePath, err) } if sam.Version != serialisationVersion { @@ -551,13 +551,13 @@ func (a *AddrManager) deserializePeers(filePath string) error { for _, v := range sam.Addresses { netAddr, err := a.newAddressFromString(v.Addr) if err != nil { - return fmt.Errorf("failed to deserialize netaddress "+ - "%s: %v", v.Addr, err) + return fmt.Errorf("failed to deserialize netaddress %s: %w", v.Addr, + err) } srcAddr, err := a.newAddressFromString(v.Src) if err != nil { - return fmt.Errorf("failed to deserialize netaddress "+ - "%s: %v", v.Src, err) + return fmt.Errorf("failed to deserialize netaddress %s: %w", v.Src, + err) } ka := &KnownAddress{ diff --git a/certgen/certgen.go b/certgen/certgen.go index 635eb0cd23..0b433b1e4d 100644 --- a/certgen/certgen.go +++ b/certgen/certgen.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2015 The btcsuite developers -// Copyright (c) 2015-2017 The Decred developers +// Copyright (c) 2015-2023 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -45,7 +45,7 @@ func NewTLSCertPair(curve elliptic.Curve, organization string, validUntil time.T serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) if err != nil { - return nil, nil, fmt.Errorf("failed to generate serial number: %s", err) + return nil, nil, fmt.Errorf("failed to generate serial number: %w", err) } host, err := os.Hostname() @@ -120,24 +120,24 @@ func NewTLSCertPair(curve elliptic.Curve, organization string, validUntil time.T derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) if err != nil { - return nil, nil, fmt.Errorf("failed to create certificate: %v", err) + return nil, nil, fmt.Errorf("failed to create certificate: %w", err) } certBuf := &bytes.Buffer{} err = pem.Encode(certBuf, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) if err != nil { - return nil, nil, fmt.Errorf("failed to encode certificate: %v", err) + return nil, nil, fmt.Errorf("failed to encode certificate: %w", err) } keybytes, err := x509.MarshalECPrivateKey(priv) if err != nil { - return nil, nil, fmt.Errorf("failed to marshal private key: %v", err) + return nil, nil, fmt.Errorf("failed to marshal private key: %w", err) } keyBuf := &bytes.Buffer{} err = pem.Encode(keyBuf, &pem.Block{Type: "EC PRIVATE KEY", Bytes: keybytes}) if err != nil { - return nil, nil, fmt.Errorf("failed to encode private key: %v", err) + return nil, nil, fmt.Errorf("failed to encode private key: %w", err) } return certBuf.Bytes(), keyBuf.Bytes(), nil diff --git a/certgen/certgen_ed25519.go b/certgen/certgen_ed25519.go index 841ae2b390..9ae3974983 100644 --- a/certgen/certgen_ed25519.go +++ b/certgen/certgen_ed25519.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2015 The btcsuite developers -// Copyright (c) 2015-2019 The Decred developers +// Copyright (c) 2015-2023 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -48,7 +48,7 @@ func NewEd25519TLSCertPair(organization string, validUntil time.Time, extraHosts serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) if err != nil { - return nil, nil, fmt.Errorf("failed to generate serial number: %s", err) + return nil, nil, fmt.Errorf("failed to generate serial number: %w", err) } host, err := os.Hostname() @@ -123,24 +123,24 @@ func NewEd25519TLSCertPair(organization string, validUntil time.Time, extraHosts derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, priv.Public(), priv) if err != nil { - return nil, nil, fmt.Errorf("failed to create certificate: %v", err) + return nil, nil, fmt.Errorf("failed to create certificate: %w", err) } certBuf := &bytes.Buffer{} err = pem.Encode(certBuf, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) if err != nil { - return nil, nil, fmt.Errorf("failed to encode certificate: %v", err) + return nil, nil, fmt.Errorf("failed to encode certificate: %w", err) } keybytes, err := x509.MarshalPKCS8PrivateKey(priv) if err != nil { - return nil, nil, fmt.Errorf("failed to marshal private key: %v", err) + return nil, nil, fmt.Errorf("failed to marshal private key: %w", err) } keyBuf := &bytes.Buffer{} err = pem.Encode(keyBuf, &pem.Block{Type: "PRIVATE KEY", Bytes: keybytes}) if err != nil { - return nil, nil, fmt.Errorf("failed to encode private key: %v", err) + return nil, nil, fmt.Errorf("failed to encode private key: %w", err) } return certBuf.Bytes(), keyBuf.Bytes(), nil diff --git a/cmd/gencerts/gencerts.go b/cmd/gencerts/gencerts.go index 04bd8684b9..2a673026ed 100644 --- a/cmd/gencerts/gencerts.go +++ b/cmd/gencerts/gencerts.go @@ -1,4 +1,4 @@ -// Copyright (c) 2020-2021 The Decred developers +// Copyright (c) 2020-2023 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -206,7 +206,7 @@ func randomX509SerialNumber() (*big.Int, error) { serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) if err != nil { - return nil, fmt.Errorf("failed to generate serial number: %s", err) + return nil, fmt.Errorf("failed to generate serial number: %w", err) } return serialNumber, nil } @@ -277,7 +277,7 @@ func generateAuthority(pub, priv interface{}, hosts []string, org string, years buf := new(bytes.Buffer) err = pem.Encode(buf, &pem.Block{Type: "CERTIFICATE", Bytes: cert}) if err != nil { - return nil, fmt.Errorf("failed to encode certificate: %v", err) + return nil, fmt.Errorf("failed to encode certificate: %w", err) } pemBlock := buf.Bytes() @@ -317,7 +317,7 @@ func createIssuedCert(pub, caPriv interface{}, ca *x509.Certificate, buf := new(bytes.Buffer) err = pem.Encode(buf, &pem.Block{Type: "CERTIFICATE", Bytes: cert}) if err != nil { - return nil, fmt.Errorf("failed to encode certificate: %v", err) + return nil, fmt.Errorf("failed to encode certificate: %w", err) } pemBlock := buf.Bytes() @@ -336,12 +336,12 @@ func createIssuedCert(pub, caPriv interface{}, ca *x509.Certificate, func marshalPrivateKey(key interface{}) ([]byte, error) { der, err := x509.MarshalPKCS8PrivateKey(key) if err != nil { - return nil, fmt.Errorf("failed to marshal private key: %v", err) + return nil, fmt.Errorf("failed to marshal private key: %w", err) } buf := new(bytes.Buffer) err = pem.Encode(buf, &pem.Block{Type: "PRIVATE KEY", Bytes: der}) if err != nil { - return nil, fmt.Errorf("failed to encode private key: %v", err) + return nil, fmt.Errorf("failed to encode private key: %w", err) } return buf.Bytes(), nil } diff --git a/dcrutil/util.go b/dcrutil/util.go index f1a9733392..06f18156aa 100644 --- a/dcrutil/util.go +++ b/dcrutil/util.go @@ -1,5 +1,5 @@ // Copyright (c) 2013, 2014 The btcsuite developers -// Copyright (c) 2015-2021 The Decred developers +// Copyright (c) 2015-2023 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -62,7 +62,7 @@ func VerifyMessage(address string, signature string, message string, params Addr // Decode base64 signature. sig, err := base64.StdEncoding.DecodeString(signature) if err != nil { - return fmt.Errorf("malformed base64 encoding: %v", err) + return fmt.Errorf("malformed base64 encoding: %w", err) } // Validate the signature - this just shows that it was valid for any pubkey diff --git a/internal/blockchain/utxobackend_test.go b/internal/blockchain/utxobackend_test.go index acd3eaa8f6..2510b14615 100644 --- a/internal/blockchain/utxobackend_test.go +++ b/internal/blockchain/utxobackend_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2021-2022 The Decred developers +// Copyright (c) 2021-2023 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -73,14 +73,14 @@ func TestConvertLdbErr(t *testing.T) { gotErr := convertLdbErr(test.ldbErr, test.desc) // Validate the error kind. - if gotErr.Err != test.want { + if !errors.Is(gotErr.Err, test.want) { t.Errorf("%q: mismatched error kind:\nwant: %v\n got: %v\n", test.name, test.want, gotErr.Err) continue } - wantDesc := fmt.Sprintf("%s: %v", test.desc, test.ldbErr) // Validate the error description. + wantDesc := fmt.Sprintf("%s: %v", test.desc, test.ldbErr) if gotErr.Description != wantDesc { t.Errorf("%q: mismatched error description:\nwant: %v\n got: %v\n", test.name, wantDesc, gotErr.Description) @@ -88,7 +88,7 @@ func TestConvertLdbErr(t *testing.T) { } // Validate the raw error. - if gotErr.RawErr != test.ldbErr { + if !errors.Is(gotErr.RawErr, test.ldbErr) { t.Errorf("%q: mismatched raw error:\nwant: %v\n got: %v\n", test.name, test.ldbErr, gotErr.RawErr) continue diff --git a/internal/fees/estimator.go b/internal/fees/estimator.go index f6e0b46367..d22c18a9da 100644 --- a/internal/fees/estimator.go +++ b/internal/fees/estimator.go @@ -1,4 +1,4 @@ -// Copyright (c) 2018-2022 The Decred developers +// Copyright (c) 2018-2023 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -228,13 +228,13 @@ func NewEstimator(cfg *EstimatorConfig) (*Estimator, error) { if cfg.DatabaseFile != "" { db, err := leveldb.OpenFile(cfg.DatabaseFile, nil) if err != nil { - return nil, fmt.Errorf("error opening estimator database: %v", err) + return nil, fmt.Errorf("error opening estimator database: %w", err) } res.db = db err = res.loadFromDatabase(cfg.ReplaceBucketsOnLoad) if err != nil { - return nil, fmt.Errorf("error loading estimator data from db: %v", + return nil, fmt.Errorf("error loading estimator data from db: %w", err) } } @@ -307,7 +307,7 @@ func (stats *Estimator) loadFromDatabase(replaceBuckets bool) error { version, err := stats.db.Get(dbKeyVersion, nil) if err != nil && !errors.Is(err, leveldb.ErrNotFound) { - return fmt.Errorf("error reading version from db: %v", err) + return fmt.Errorf("error reading version from db: %w", err) } if len(version) < 1 { // No data in the file. Fill with the current config. @@ -326,19 +326,19 @@ func (stats *Estimator) loadFromDatabase(replaceBuckets bool) error { err := binary.Write(b, dbByteOrder, stats.bucketFeeBounds) if err != nil { - return fmt.Errorf("error writing bucket fees to db: %v", err) + return fmt.Errorf("error writing bucket fees to db: %w", err) } batch.Put(dbKeyBucketFees, b.Bytes()) err = stats.db.Write(batch, nil) if err != nil { - return fmt.Errorf("error writing initial estimator db file: %v", + return fmt.Errorf("error writing initial estimator db file: %w", err) } err = stats.updateDatabase() if err != nil { - return fmt.Errorf("error adding initial estimator data to db: %v", + return fmt.Errorf("error adding initial estimator data to db: %w", err) } @@ -354,7 +354,7 @@ func (stats *Estimator) loadFromDatabase(replaceBuckets bool) error { maxConfirmsBytes, err := stats.db.Get(dbKeyMaxConfirms, nil) if err != nil { return fmt.Errorf("error reading max confirmation range from db file: "+ - "%v", err) + "%w", err) } if len(maxConfirmsBytes) != 4 { return errors.New("wrong number of bytes in stored maxConfirms") @@ -367,7 +367,7 @@ func (stats *Estimator) loadFromDatabase(replaceBuckets bool) error { feesBytes, err := stats.db.Get(dbKeyBucketFees, nil) if err != nil { - return fmt.Errorf("error reading fee bounds from db file: %v", err) + return fmt.Errorf("error reading fee bounds from db file: %w", err) } if feesBytes == nil { return errors.New("fee bounds not found in database file") @@ -381,7 +381,7 @@ func (stats *Estimator) loadFromDatabase(replaceBuckets bool) error { err = binary.Read(bytes.NewReader(feesBytes), dbByteOrder, &fileBucketFees) if err != nil { - return fmt.Errorf("error decoding file bucket fees: %v", err) + return fmt.Errorf("error decoding file bucket fees: %w", err) } if !replaceBuckets { @@ -450,7 +450,7 @@ func (stats *Estimator) loadFromDatabase(replaceBuckets bool) error { } err = iter.Error() if err != nil { - return fmt.Errorf("error on bucket iterator: %v", err) + return fmt.Errorf("error on bucket iterator: %w", err) } stats.bucketFeeBounds = fileBucketFees @@ -502,8 +502,7 @@ func (stats *Estimator) updateDatabase() error { err := stats.db.Write(batch, nil) if err != nil { - return fmt.Errorf("error writing update to estimator db file: %v", - err) + return fmt.Errorf("error writing update to estimator db file: %w", err) } return nil diff --git a/internal/staging/banmanager/banmanager.go b/internal/staging/banmanager/banmanager.go index 96ceb519d4..f85bfb81e5 100644 --- a/internal/staging/banmanager/banmanager.go +++ b/internal/staging/banmanager/banmanager.go @@ -1,4 +1,4 @@ -// Copyright (c) 2021 The Decred developers +// Copyright (c) 2021-2023 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -119,7 +119,7 @@ func (bm *BanManager) AddPeer(p *peer.Peer) error { host, _, err := net.SplitHostPort(p.Addr()) if err != nil { p.Disconnect() - return fmt.Errorf("cannot split hostport %v", err) + return fmt.Errorf("cannot split hostport %w", err) } bm.mtx.Lock() diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index a764709dc3..d9285b7f3c 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -759,7 +759,7 @@ func (c *Client) handleSendPostMessage(details *sendPostDetails) { respBytes, err := io.ReadAll(httpResponse.Body) httpResponse.Body.Close() if err != nil { - err = fmt.Errorf("error reading json reply: %v", err) + err = fmt.Errorf("error reading json reply: %w", err) jReq.responseChan <- &response{err: err} return } diff --git a/service_windows.go b/service_windows.go index a85c63d865..931e13fa04 100644 --- a/service_windows.go +++ b/service_windows.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2016 The btcsuite developers -// Copyright (c) 2015-2016 The Decred developers +// Copyright (c) 2015-2023 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -183,13 +183,13 @@ func startService() error { service, err := serviceManager.OpenService(svcName) if err != nil { - return fmt.Errorf("could not access service: %v", err) + return fmt.Errorf("could not access service: %w", err) } defer service.Close() err = service.Start(os.Args...) if err != nil { - return fmt.Errorf("could not start service: %v", err) + return fmt.Errorf("could not start service: %w", err) } return nil @@ -208,13 +208,13 @@ func controlService(c svc.Cmd, to svc.State) error { service, err := serviceManager.OpenService(svcName) if err != nil { - return fmt.Errorf("could not access service: %v", err) + return fmt.Errorf("could not access service: %w", err) } defer service.Close() status, err := service.Control(c) if err != nil { - return fmt.Errorf("could not send control=%d: %v", c, err) + return fmt.Errorf("could not send control=%d: %w", c, err) } // Send the control message. @@ -227,8 +227,7 @@ func controlService(c svc.Cmd, to svc.State) error { time.Sleep(300 * time.Millisecond) status, err = service.Query() if err != nil { - return fmt.Errorf("could not retrieve service "+ - "status: %v", err) + return fmt.Errorf("could not retrieve service status: %w", err) } } diff --git a/txscript/sign/sign.go b/txscript/sign/sign.go index 1406ab9395..dc3f0c536d 100644 --- a/txscript/sign/sign.go +++ b/txscript/sign/sign.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2015 The btcsuite developers -// Copyright (c) 2015-2021 The Decred developers +// Copyright (c) 2015-2023 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -48,14 +48,14 @@ func RawTxInSignature(tx *wire.MsgTx, idx int, subScript []byte, } sig, err := priv.Sign(hash) if err != nil { - return nil, fmt.Errorf("cannot sign tx input: %s", err) + return nil, fmt.Errorf("cannot sign tx input: %w", err) } sigBytes = sig.Serialize() case dcrec.STSchnorrSecp256k1: priv := secp256k1.PrivKeyFromBytes(key) sig, err := schnorr.Sign(priv, hash) if err != nil { - return nil, fmt.Errorf("cannot sign tx input: %s", err) + return nil, fmt.Errorf("cannot sign tx input: %w", err) } sigBytes = sig.Serialize() default: @@ -645,7 +645,7 @@ func TSpendSignatureScript(msgTx *wire.MsgTx, privKey []byte) ([]byte, error) { priv := secp256k1.PrivKeyFromBytes(privKey) sig, err := schnorr.Sign(priv, hash) if err != nil { - return nil, fmt.Errorf("cannot sign tx input: %s", err) + return nil, fmt.Errorf("cannot sign tx input: %w", err) } sigBytes := sig.Serialize() pkBytes := priv.PubKey().SerializeCompressed() diff --git a/txscript/sign/sign_test.go b/txscript/sign/sign_test.go index 58bca15055..8f323222f4 100644 --- a/txscript/sign/sign_test.go +++ b/txscript/sign/sign_test.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2016 The btcsuite developers -// Copyright (c) 2015-2021 The Decred developers +// Copyright (c) 2015-2023 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -103,14 +103,12 @@ func checkScripts(msg string, tx *wire.MsgTx, idx int, sigScript, pkScript []byt var scriptFlags txscript.ScriptFlags vm, err := txscript.NewEngine(pkScript, tx, idx, scriptFlags, 0, nil) if err != nil { - return fmt.Errorf("failed to make script engine for %s: %v", - msg, err) + return fmt.Errorf("failed to make script engine for %s: %w", msg, err) } err = vm.Execute() if err != nil { - return fmt.Errorf("invalid script signature for %s: %v", msg, - err) + return fmt.Errorf("invalid script signature for %s: %w", msg, err) } return nil @@ -123,7 +121,7 @@ func signAndCheck(msg string, tx *wire.MsgTx, idx int, pkScript []byte, sigScript, err := SignTxOutput(testingParams, tx, idx, pkScript, hashType, kdb, sdb, nil, isTreasuryEnabled) if err != nil { - return fmt.Errorf("failed to sign output %s: %v", msg, err) + return fmt.Errorf("failed to sign output %s: %w", msg, err) } return checkScripts(msg, tx, idx, sigScript, pkScript) @@ -140,7 +138,7 @@ func signBadAndCheck(msg string, tx *wire.MsgTx, idx int, pkScript []byte, sigScript, err := SignTxOutput(testingParams, tx, idx, pkScript, hashType, kdb, sdb, nil, isTreasuryEnabled) if err != nil { - return fmt.Errorf("failed to sign output %s: %v", msg, err) + return fmt.Errorf("failed to sign output %s: %w", msg, err) } // Be sure to reset the value in when we're done creating the diff --git a/wire/error.go b/wire/error.go index df41e642ff..9f6ebd2b31 100644 --- a/wire/error.go +++ b/wire/error.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2015 The btcsuite developers -// Copyright (c) 2015-2020 The Decred developers +// Copyright (c) 2015-2023 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -222,8 +222,8 @@ func (m MessageError) Error() string { } // messageError creates an Error given a set of arguments. -func messageError(Func string, c ErrorCode, desc string) *MessageError { - return &MessageError{Func: Func, ErrorCode: c, Description: desc} +func messageError(funcName string, c ErrorCode, desc string) *MessageError { + return &MessageError{Func: funcName, ErrorCode: c, Description: desc} } // Is implements the interface to work with the standard library's errors.Is.