From d245d7e8686768b57b44e4c6d3c8c8452b6e3b20 Mon Sep 17 00:00:00 2001 From: Quentin Mc Gaw Date: Sun, 19 Jan 2025 22:48:49 +0100 Subject: [PATCH] chore(all): enable errorlint and fix all errors - Ignore fmt.Errorf not using wrapping with `%w` - Use `errors.Is` instead of `==` - Use `errors.As` instead of direct type assertions --- .golangci.yml | 4 ++- accounts/abi/bind/util_test.go | 2 +- accounts/abi/unpack_test.go | 3 +- accounts/keystore/account_cache_test.go | 2 +- accounts/keystore/keystore_test.go | 9 +++--- accounts/keystore/plain_test.go | 3 +- accounts/usbwallet/ledger.go | 4 +-- beacon/light/committee_chain_test.go | 7 +++-- beacon/light/sync/update_sync.go | 5 +-- cmd/clef/main.go | 4 +-- cmd/devp2p/internal/ethtest/chain.go | 2 +- cmd/devp2p/internal/v5test/discv5tests.go | 3 +- cmd/evm/runner.go | 3 +- cmd/geth/config.go | 3 +- cmd/rlpdump/main.go | 5 +-- cmd/utils/cmd.go | 6 ++-- common/bitutil/compress_test.go | 5 +-- common/hexutil/hexutil.go | 16 ++++++---- common/hexutil/json.go | 6 ++-- common/test_utils.go | 4 ++- consensus/clique/snapshot_test.go | 3 +- console/bridge.go | 10 +++--- console/console.go | 8 +++-- core/blockchain.go | 4 +-- core/blockchain_test.go | 2 +- core/forkid/forkid_test.go | 3 +- core/rawdb/freezer_table_test.go | 8 +++-- core/rawdb/freezer_test.go | 4 +-- core/state/snapshot/disklayer_test.go | 5 +-- core/state/snapshot/generate.go | 3 +- core/state/snapshot/snapshot_test.go | 13 ++++---- core/state/statedb_fuzz_test.go | 3 +- core/state/statedb_test.go | 4 ++- core/state_transition.go | 3 +- core/txpool/legacypool/journal.go | 2 +- core/txpool/legacypool/legacypool_test.go | 28 ++++++++--------- core/types/receipt_test.go | 3 +- core/types/transaction_test.go | 4 +-- core/vm/eof_test.go | 3 +- core/vm/evm.go | 12 +++---- core/vm/gas_table_test.go | 4 +-- core/vm/instructions.go | 17 +++++----- core/vm/interpreter.go | 3 +- crypto/blake2b/blake2b_test.go | 3 +- crypto/crypto.go | 7 +++-- crypto/crypto_test.go | 5 +-- crypto/ecies/ecies_test.go | 6 ++-- crypto/secp256k1/secp256_test.go | 3 +- eth/api_admin.go | 2 +- eth/catalyst/api_test.go | 12 +++++-- eth/downloader/downloader.go | 4 +-- eth/downloader/skeleton.go | 8 ++--- eth/filters/filter_system_test.go | 2 +- eth/filters/filter_test.go | 3 +- eth/gasprice/feehistory_test.go | 2 +- eth/protocols/eth/handshake.go | 12 +++---- eth/protocols/snap/sync.go | 16 +++++----- eth/state_accessor.go | 8 ++--- ethclient/ethclient_test.go | 2 +- ethdb/leveldb/leveldb.go | 4 ++- ethdb/pebble/pebble.go | 3 +- event/event_test.go | 3 +- event/subscription_test.go | 2 +- internal/build/archive.go | 2 +- internal/build/util.go | 4 ++- internal/cmdtest/test_cmd.go | 10 +++--- internal/era/e2store/e2store.go | 8 ++--- internal/era/iterator.go | 2 +- internal/jsre/pretty.go | 4 ++- metrics/disk_linux.go | 3 +- node/errors.go | 3 +- node/node_test.go | 22 +++++++------ node/rpcstack.go | 2 +- p2p/dial.go | 3 +- p2p/discover/v4_udp_test.go | 10 +++--- p2p/discover/v5_udp_test.go | 13 ++++---- p2p/discover/v5wire/encoding.go | 2 +- p2p/dnsdisc/client_test.go | 2 +- p2p/dnsdisc/error.go | 3 +- p2p/dnsdisc/tree_test.go | 5 +-- p2p/enode/nodedb.go | 10 +++--- p2p/enr/enr.go | 8 ++--- p2p/enr/enr_test.go | 12 ++++--- p2p/enr/entries.go | 4 +-- p2p/message_test.go | 7 +++-- p2p/metrics.go | 16 +++++----- p2p/netutil/error.go | 12 ++++--- p2p/netutil/error_test.go | 4 ++- p2p/netutil/net_test.go | 3 +- p2p/netutil/toobig_windows.go | 7 +++-- p2p/peer.go | 3 +- p2p/peer_error.go | 6 ++-- p2p/peer_test.go | 4 +-- p2p/server_test.go | 14 ++++----- p2p/transport.go | 3 +- rlp/decode.go | 38 ++++++++++++----------- rlp/decode_test.go | 10 +++--- rlp/encode_test.go | 2 +- rlp/raw_test.go | 6 ++-- rlp/typecache.go | 4 ++- rpc/client.go | 3 +- rpc/client_test.go | 20 ++++++------ rpc/http_test.go | 8 +++-- rpc/json.go | 10 +++--- rpc/server.go | 2 +- rpc/server_test.go | 4 ++- rpc/subscription.go | 4 +-- rpc/websocket_test.go | 2 +- signer/core/api.go | 4 +-- signer/core/api_test.go | 9 +++--- signer/core/signed_data_test.go | 5 +-- tests/init_test.go | 3 +- trie/iterator.go | 12 ++++--- trie/iterator_test.go | 7 +++-- trie/node.go | 4 ++- trie/node_test.go | 7 +++-- trie/trie_test.go | 15 +++++---- triedb/pathdb/journal.go | 2 +- 118 files changed, 428 insertions(+), 316 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index b63251055b..5fbd1b4472 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -7,6 +7,7 @@ run: linters: disable-all: true enable: + - errorlint - goimports - gosimple - govet @@ -32,12 +33,13 @@ linters: # - errcheck #lot of false positives # - contextcheck # - errchkjson # lots of false positives - # - errorlint # this check crashes # - exhaustive # silly check # - makezero # false positives # - nilerr # several intentional linters-settings: + errorlint: + errorf: false gofmt: simplify: true revive: diff --git a/accounts/abi/bind/util_test.go b/accounts/abi/bind/util_test.go index 04d1bb63bc..a846456695 100644 --- a/accounts/abi/bind/util_test.go +++ b/accounts/abi/bind/util_test.go @@ -89,7 +89,7 @@ func TestWaitDeployed(t *testing.T) { select { case <-mined: - if err != test.wantErr { + if !errors.Is(err, test.wantErr) { t.Errorf("test %q: error mismatch: want %q, got %q", name, test.wantErr, err) } if address != test.wantAddress { diff --git a/accounts/abi/unpack_test.go b/accounts/abi/unpack_test.go index 7df7b9c403..e750110990 100644 --- a/accounts/abi/unpack_test.go +++ b/accounts/abi/unpack_test.go @@ -19,6 +19,7 @@ package abi import ( "bytes" "encoding/hex" + "errors" "fmt" "math" "math/big" @@ -1105,7 +1106,7 @@ func TestPackAndUnpackIncompatibleNumber(t *testing.T) { {Type: ty}, } decoded, err := decodeABI.Unpack(packed) - if err != testCase.err { + if !errors.Is(err, testCase.err) { t.Fatalf("Expected error %v, actual error %v. case %d", testCase.err, err, i) } if err != nil { diff --git a/accounts/keystore/account_cache_test.go b/accounts/keystore/account_cache_test.go index c9a8cdfcef..edf1303324 100644 --- a/accounts/keystore/account_cache_test.go +++ b/accounts/keystore/account_cache_test.go @@ -307,7 +307,7 @@ func TestCacheFind(t *testing.T) { } for i, test := range tests { a, err := cache.find(test.Query) - if !reflect.DeepEqual(err, test.WantError) { + if !errors.Is(err, test.WantError) { t.Errorf("test %d: error mismatch for query %v\ngot %q\nwant %q", i, test.Query, err, test.WantError) continue } diff --git a/accounts/keystore/keystore_test.go b/accounts/keystore/keystore_test.go index f8922a3f3f..46c10de2a0 100644 --- a/accounts/keystore/keystore_test.go +++ b/accounts/keystore/keystore_test.go @@ -17,6 +17,7 @@ package keystore import ( + "errors" "math/rand" "os" "runtime" @@ -127,7 +128,7 @@ func TestTimedUnlock(t *testing.T) { // Signing without passphrase fails because account is locked _, err = ks.SignHash(accounts.Account{Address: a1.Address}, testSigData) - if err != ErrLocked { + if !errors.Is(err, ErrLocked) { t.Fatal("Signing should've failed with ErrLocked before unlocking, got ", err) } @@ -145,7 +146,7 @@ func TestTimedUnlock(t *testing.T) { // Signing fails again after automatic locking time.Sleep(250 * time.Millisecond) _, err = ks.SignHash(accounts.Account{Address: a1.Address}, testSigData) - if err != ErrLocked { + if !errors.Is(err, ErrLocked) { t.Fatal("Signing should've failed with ErrLocked timeout expired, got ", err) } } @@ -185,7 +186,7 @@ func TestOverrideUnlock(t *testing.T) { // Signing fails again after automatic locking time.Sleep(250 * time.Millisecond) _, err = ks.SignHash(accounts.Account{Address: a1.Address}, testSigData) - if err != ErrLocked { + if !errors.Is(err, ErrLocked) { t.Fatal("Signing should've failed with ErrLocked timeout expired, got ", err) } } @@ -206,7 +207,7 @@ func TestSignRace(t *testing.T) { } end := time.Now().Add(500 * time.Millisecond) for time.Now().Before(end) { - if _, err := ks.SignHash(accounts.Account{Address: a1.Address}, testSigData); err == ErrLocked { + if _, err := ks.SignHash(accounts.Account{Address: a1.Address}, testSigData); errors.Is(err, ErrLocked) { return } else if err != nil { t.Errorf("Sign error: %v", err) diff --git a/accounts/keystore/plain_test.go b/accounts/keystore/plain_test.go index 737eb7fd61..c90982876e 100644 --- a/accounts/keystore/plain_test.go +++ b/accounts/keystore/plain_test.go @@ -19,6 +19,7 @@ package keystore import ( "crypto/rand" "encoding/hex" + "errors" "fmt" "path/filepath" "reflect" @@ -90,7 +91,7 @@ func TestKeyStorePassphraseDecryptionFail(t *testing.T) { if err != nil { t.Fatal(err) } - if _, err = ks.GetKey(k1.Address, account.URL.Path, "bar"); err != ErrDecrypt { + if _, err = ks.GetKey(k1.Address, account.URL.Path, "bar"); !errors.Is(err, ErrDecrypt) { t.Fatalf("wrong error for invalid password\ngot %q\nwant %q", err, ErrDecrypt) } } diff --git a/accounts/usbwallet/ledger.go b/accounts/usbwallet/ledger.go index 2be6edd44f..b7ae4fe2ea 100644 --- a/accounts/usbwallet/ledger.go +++ b/accounts/usbwallet/ledger.go @@ -119,7 +119,7 @@ func (w *ledgerDriver) Open(device io.ReadWriter, passphrase string) error { _, err := w.ledgerDerive(accounts.DefaultBaseDerivationPath) if err != nil { // Ethereum app is not running or in browser mode, nothing more to do, return - if err == errLedgerReplyInvalidHeader { + if errors.Is(err, errLedgerReplyInvalidHeader) { w.browser = true } return nil @@ -141,7 +141,7 @@ func (w *ledgerDriver) Close() error { // Heartbeat implements usbwallet.driver, performing a sanity check against the // Ledger to see if it's still online. func (w *ledgerDriver) Heartbeat() error { - if _, err := w.ledgerVersion(); err != nil && err != errLedgerInvalidVersionReply { + if _, err := w.ledgerVersion(); err != nil && !errors.Is(err, errLedgerInvalidVersionReply) { w.failure = err return err } diff --git a/beacon/light/committee_chain_test.go b/beacon/light/committee_chain_test.go index 17ba135905..993f9a68d3 100644 --- a/beacon/light/committee_chain_test.go +++ b/beacon/light/committee_chain_test.go @@ -18,6 +18,7 @@ package light import ( "crypto/rand" + "errors" "testing" "time" @@ -259,13 +260,13 @@ func (c *committeeChainTest) setClockPeriod(period float64) { } func (c *committeeChainTest) addFixedCommitteeRoot(tc *testCommitteeChain, period uint64, expErr error) { - if err := c.chain.addFixedCommitteeRoot(period, tc.periods[period].committee.Root()); err != expErr { + if err := c.chain.addFixedCommitteeRoot(period, tc.periods[period].committee.Root()); !errors.Is(err, expErr) { c.t.Errorf("Incorrect error output from addFixedCommitteeRoot at period %d (expected %v, got %v)", period, expErr, err) } } func (c *committeeChainTest) addCommittee(tc *testCommitteeChain, period uint64, expErr error) { - if err := c.chain.addCommittee(period, tc.periods[period].committee); err != expErr { + if err := c.chain.addCommittee(period, tc.periods[period].committee); !errors.Is(err, expErr) { c.t.Errorf("Incorrect error output from addCommittee at period %d (expected %v, got %v)", period, expErr, err) } } @@ -275,7 +276,7 @@ func (c *committeeChainTest) insertUpdate(tc *testCommitteeChain, period uint64, if addCommittee { committee = tc.periods[period+1].committee } - if err := c.chain.InsertUpdate(tc.periods[period].update, committee); err != expErr { + if err := c.chain.InsertUpdate(tc.periods[period].update, committee); !errors.Is(err, expErr) { c.t.Errorf("Incorrect error output from InsertUpdate at period %d (expected %v, got %v)", period, expErr, err) } } diff --git a/beacon/light/sync/update_sync.go b/beacon/light/sync/update_sync.go index 9549ee5992..3e30016330 100644 --- a/beacon/light/sync/update_sync.go +++ b/beacon/light/sync/update_sync.go @@ -17,6 +17,7 @@ package sync import ( + "errors" "sort" "github.com/ethereum/go-ethereum/beacon/light" @@ -380,12 +381,12 @@ func (s *ForwardUpdateSync) Process(requester request.Requester, events []reques func (s *ForwardUpdateSync) processResponse(requester request.Requester, u updateResponse) (success bool) { for i, update := range u.response.Updates { if err := s.chain.InsertUpdate(update, u.response.Committees[i]); err != nil { - if err == light.ErrInvalidPeriod { + if errors.Is(err, light.ErrInvalidPeriod) { // there is a gap in the update periods; stop processing without // failing and try again next time return } - if err == light.ErrInvalidUpdate || err == light.ErrWrongCommitteeRoot || err == light.ErrCannotReorg { + if errors.Is(err, light.ErrInvalidUpdate) || errors.Is(err, light.ErrWrongCommitteeRoot) || errors.Is(err, light.ErrCannotReorg) { requester.Fail(u.sid.Server, "invalid update received") } else { log.Error("Unexpected InsertUpdate error", "error", err) diff --git a/cmd/clef/main.go b/cmd/clef/main.go index dde4ae853f..99bfeac4d2 100644 --- a/cmd/clef/main.go +++ b/cmd/clef/main.go @@ -923,13 +923,13 @@ func testExternalUI(api *core.SignerAPI) { } } expectApprove := func(testcase string, err error) { - if err == nil || err == accounts.ErrUnknownAccount { + if err == nil || errors.Is(err, accounts.ErrUnknownAccount) { return } addErr(fmt.Sprintf("%v: expected no error, got %v", testcase, err.Error())) } expectDeny := func(testcase string, err error) { - if err == nil || err != core.ErrRequestDenied { + if err == nil || !errors.Is(err, core.ErrRequestDenied) { addErr(fmt.Sprintf("%v: expected ErrRequestDenied, got %v", testcase, err)) } } diff --git a/cmd/devp2p/internal/ethtest/chain.go b/cmd/devp2p/internal/ethtest/chain.go index 222c66d4df..09ce4afe38 100644 --- a/cmd/devp2p/internal/ethtest/chain.go +++ b/cmd/devp2p/internal/ethtest/chain.go @@ -275,7 +275,7 @@ func blocksFromFile(chainfile string, gblock *types.Block) ([]*types.Block, erro blocks[0] = gblock for i := 0; ; i++ { var b types.Block - if err := stream.Decode(&b); err == io.EOF { + if err := stream.Decode(&b); errors.Is(err, io.EOF) { break } else if err != nil { return nil, fmt.Errorf("at block index %d: %v", i, err) diff --git a/cmd/devp2p/internal/v5test/discv5tests.go b/cmd/devp2p/internal/v5test/discv5tests.go index 7dbd3c3be5..6213bf0931 100644 --- a/cmd/devp2p/internal/v5test/discv5tests.go +++ b/cmd/devp2p/internal/v5test/discv5tests.go @@ -18,6 +18,7 @@ package v5test import ( "bytes" + "errors" "net" "slices" "sync" @@ -96,7 +97,7 @@ func (s *Suite) TestPingLargeRequestID(t *utesting.T) { case *v5wire.Pong: t.Errorf("PONG response with unknown request ID %x", resp.ReqID) case *readError: - if resp.err == v5wire.ErrInvalidReqID { + if errors.Is(resp.err, v5wire.ErrInvalidReqID) { t.Error("response with oversized request ID") } else if !netutil.IsTimeout(resp.err) { t.Error(resp) diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go index c67d3657e2..e822110b31 100644 --- a/cmd/evm/runner.go +++ b/cmd/evm/runner.go @@ -20,6 +20,7 @@ import ( "bytes" "encoding/hex" "encoding/json" + "errors" "fmt" "io" "math/big" @@ -166,7 +167,7 @@ func timedExec(bench bool, execFunc func() ([]byte, uint64, error)) ([]byte, exe if haveGasUsed != gasUsed { panic(fmt.Sprintf("gas differs, have %v want %v", haveGasUsed, gasUsed)) } - if haveErr != err { + if !errors.Is(haveErr, err) { panic(fmt.Sprintf("err differs, have %v want %v", haveErr, err)) } } diff --git a/cmd/geth/config.go b/cmd/geth/config.go index ecee2bfd80..9bc55e70c8 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -120,7 +120,8 @@ func loadConfig(file string, cfg *gethConfig) error { err = tomlSettings.NewDecoder(bufio.NewReader(f)).Decode(cfg) // Add file name to errors that have a line number. - if _, ok := err.(*toml.LineError); ok { + lineErr := new(toml.LineError) + if ok := errors.As(err, &lineErr); ok { err = errors.New(file + ", " + err.Error()) } return err diff --git a/cmd/rlpdump/main.go b/cmd/rlpdump/main.go index 685e5bb71a..7dde8c0a46 100644 --- a/cmd/rlpdump/main.go +++ b/cmd/rlpdump/main.go @@ -22,6 +22,7 @@ import ( "bytes" "container/list" "encoding/hex" + "errors" "flag" "fmt" "io" @@ -106,7 +107,7 @@ func rlpToText(in *inStream, out io.Writer) error { stream := rlp.NewStream(in, 0) for { if err := dump(in, stream, 0, out); err != nil { - if err != io.EOF { + if !errors.Is(err, io.EOF) { return err } break @@ -149,7 +150,7 @@ func dump(in *inStream, s *rlp.Stream, depth int, out io.Writer) error { if i > 0 { fmt.Fprint(out, ",\n") } - if err := dump(in, s, depth+1, out); err == rlp.EOL { + if err := dump(in, s, depth+1, out); errors.Is(err, rlp.EOL) { break } else if err != nil { return err diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go index 791b3d1d20..c71aa4c689 100644 --- a/cmd/utils/cmd.go +++ b/cmd/utils/cmd.go @@ -195,7 +195,7 @@ func ImportChain(chain *core.BlockChain, fn string) error { i := 0 for ; i < importBatchSize; i++ { var b types.Block - if err := stream.Decode(&b); err == io.EOF { + if err := stream.Decode(&b); errors.Is(err, io.EOF) { break } else if err != nil { return fmt.Errorf("at block %d: %v", n, err) @@ -515,7 +515,7 @@ func ImportPreimages(db ethdb.Database, fn string) error { var blob []byte if err := stream.Decode(&blob); err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { break } return err @@ -725,7 +725,7 @@ func ImportLDBData(db ethdb.Database, f string, startIndex int64, interrupt chan key, val []byte ) if err := stream.Decode(&op); err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { break } return err diff --git a/common/bitutil/compress_test.go b/common/bitutil/compress_test.go index c6f6fe8bcf..b54a4ba990 100644 --- a/common/bitutil/compress_test.go +++ b/common/bitutil/compress_test.go @@ -18,6 +18,7 @@ package bitutil import ( "bytes" + "errors" "fmt" "math/rand" "testing" @@ -107,7 +108,7 @@ func TestDecodingCycle(t *testing.T) { data := hexutil.MustDecode(tt.input) orig, err := bitsetDecodeBytes(data, tt.size) - if err != tt.fail { + if !errors.Is(err, tt.fail) { t.Errorf("test %d: failure mismatch: have %v, want %v", i, err, tt.fail) } if err != nil { @@ -143,7 +144,7 @@ func TestCompression(t *testing.T) { t.Errorf("decoding mismatch for dense data: have %x, want %x, error %v", data, in, err) } // Check that decompressing a longer input than the target fails - if _, err := DecompressBytes([]byte{0xc0, 0x01, 0x01}, 2); err != errExceededTarget { + if _, err := DecompressBytes([]byte{0xc0, 0x01, 0x01}, 2); !errors.Is(err, errExceededTarget) { t.Errorf("decoding error mismatch for long data: have %v, want %v", err, errExceededTarget) } } diff --git a/common/hexutil/hexutil.go b/common/hexutil/hexutil.go index d3201850a8..5bd2715526 100644 --- a/common/hexutil/hexutil.go +++ b/common/hexutil/hexutil.go @@ -32,6 +32,7 @@ package hexutil import ( "encoding/hex" + "errors" "fmt" "math/big" "strconv" @@ -223,18 +224,21 @@ func decodeNibble(in byte) uint64 { } func mapError(err error) error { - if err, ok := err.(*strconv.NumError); ok { - switch err.Err { - case strconv.ErrRange: + numErr := new(strconv.NumError) + if ok := errors.As(err, &numErr); ok { + switch { + case errors.Is(numErr.Err, strconv.ErrRange): return ErrUint64Range - case strconv.ErrSyntax: + case errors.Is(numErr.Err, strconv.ErrSyntax): return ErrSyntax } } - if _, ok := err.(hex.InvalidByteError); ok { + + var invalidByteErr hex.InvalidByteError + if ok := errors.As(err, &invalidByteErr); ok { return ErrSyntax } - if err == hex.ErrLength { + if errors.Is(err, hex.ErrLength) { return ErrOddLength } return err diff --git a/common/hexutil/json.go b/common/hexutil/json.go index e0ac98f52d..8afa38c802 100644 --- a/common/hexutil/json.go +++ b/common/hexutil/json.go @@ -19,6 +19,7 @@ package hexutil import ( "encoding/hex" "encoding/json" + "errors" "fmt" "math/big" "reflect" @@ -355,7 +356,7 @@ func (b *Uint) UnmarshalJSON(input []byte) error { func (b *Uint) UnmarshalText(input []byte) error { var u64 Uint64 err := u64.UnmarshalText(input) - if u64 > Uint64(^uint(0)) || err == ErrUint64Range { + if u64 > Uint64(^uint(0)) || errors.Is(err, ErrUint64Range) { return ErrUintRange } else if err != nil { return err @@ -410,7 +411,8 @@ func checkNumberText(input []byte) (raw []byte, err error) { } func wrapTypeError(err error, typ reflect.Type) error { - if _, ok := err.(*decError); ok { + decErr := new(decError) + if ok := errors.As(err, &decErr); ok { return &json.UnmarshalTypeError{Value: err.Error(), Type: typ} } return err diff --git a/common/test_utils.go b/common/test_utils.go index 7a175412f4..d47e71083c 100644 --- a/common/test_utils.go +++ b/common/test_utils.go @@ -18,6 +18,7 @@ package common import ( "encoding/json" + "errors" "fmt" "os" ) @@ -29,7 +30,8 @@ func LoadJSON(file string, val interface{}) error { return err } if err := json.Unmarshal(content, val); err != nil { - if syntaxerr, ok := err.(*json.SyntaxError); ok { + syntaxerr := new(json.SyntaxError) + if ok := errors.As(err, &syntaxerr); ok { line := findLine(content, syntaxerr.Offset) return fmt.Errorf("JSON syntax error at %v:%v: %v", file, line, err) } diff --git a/consensus/clique/snapshot_test.go b/consensus/clique/snapshot_test.go index a83d6ca736..144a7fd031 100644 --- a/consensus/clique/snapshot_test.go +++ b/consensus/clique/snapshot_test.go @@ -19,6 +19,7 @@ package clique import ( "bytes" "crypto/ecdsa" + "errors" "fmt" "math/big" "slices" @@ -469,7 +470,7 @@ func (tt *cliqueTest) run(t *testing.T) { t.Fatalf("failed to import batch %d, block %d: %v", j, k, err) } } - if _, err = chain.InsertChain(batches[len(batches)-1]); err != tt.failure { + if _, err = chain.InsertChain(batches[len(batches)-1]); !errors.Is(err, tt.failure) { t.Errorf("failure mismatch: have %v, want %v", err, tt.failure) } if tt.failure != nil { diff --git a/console/bridge.go b/console/bridge.go index c1d7746c02..95b3ca99f9 100644 --- a/console/bridge.go +++ b/console/bridge.go @@ -169,11 +169,13 @@ func (b *bridge) Send(call jsre.Call) (goja.Value, error) { } else { code := -32603 var data interface{} - if err, ok := err.(rpc.Error); ok { - code = err.ErrorCode() + var rcpErr rpc.Error + if ok := errors.As(err, &rcpErr); ok { + code = rcpErr.ErrorCode() } - if err, ok := err.(rpc.DataError); ok { - data = err.ErrorData() + var rcpDataErr rpc.DataError + if ok := errors.As(err, &rcpDataErr); ok { + data = rcpDataErr.ErrorData() } setError(resp, code, err.Error(), data) } diff --git a/console/console.go b/console/console.go index b5c77bd78f..9159ac4868 100644 --- a/console/console.go +++ b/console/console.go @@ -148,7 +148,8 @@ func (c *Console) init(preload []string) error { for _, path := range preload { if err := c.jsre.Exec(path); err != nil { failure := err.Error() - if gojaErr, ok := err.(*goja.Exception); ok { + gojaErr := new(goja.Exception) + if ok := errors.As(err, &gojaErr); ok { failure = gojaErr.String() } return fmt.Errorf("%s: %v", path, failure) @@ -205,7 +206,8 @@ func (c *Console) initExtensions() error { const methodNotFound = -32601 apis, err := c.client.SupportedModules() if err != nil { - if rpcErr, ok := err.(rpc.Error); ok && rpcErr.ErrorCode() == methodNotFound { + var rpcErr rpc.Error + if ok := errors.As(err, &rpcErr); ok && rpcErr.ErrorCode() == methodNotFound { log.Warn("Server does not support method rpc_modules, using default API list.") apis = defaultAPIs } else { @@ -423,7 +425,7 @@ func (c *Console) Interactive() { return case err := <-inputErr: - if err == liner.ErrPromptAborted { + if errors.Is(err, liner.ErrPromptAborted) { // When prompting for multi-line input, the first Ctrl-C resets // the multi-line state. prompt, indents, input = c.prompt, 0, "" diff --git a/core/blockchain.go b/core/blockchain.go index b056b7ed0c..4031854057 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1388,7 +1388,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [ // Write downloaded chain data and corresponding receipt chain data if len(ancientBlocks) > 0 { if n, err := writeAncient(ancientBlocks, ancientReceipts); err != nil { - if err == errInsertionInterrupted { + if errors.Is(err, errInsertionInterrupted) { return 0, nil } return n, err @@ -1396,7 +1396,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [ } if len(liveBlocks) > 0 { if n, err := writeLive(liveBlocks, liveReceipts); err != nil { - if err == errInsertionInterrupted { + if errors.Is(err, errInsertionInterrupted) { return 0, nil } return n, err diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 7805a7c6e8..fcac0878ae 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -158,7 +158,7 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error { err = blockchain.validator.ValidateBody(block) } if err != nil { - if err == ErrKnownBlock { + if errors.Is(err, ErrKnownBlock) { continue } return err diff --git a/core/forkid/forkid_test.go b/core/forkid/forkid_test.go index de589c0d44..524e79cb9d 100644 --- a/core/forkid/forkid_test.go +++ b/core/forkid/forkid_test.go @@ -18,6 +18,7 @@ package forkid import ( "bytes" + "errors" "hash/crc32" "math" "math/big" @@ -340,7 +341,7 @@ func TestValidation(t *testing.T) { genesis := core.DefaultGenesisBlock().ToBlock() for i, tt := range tests { filter := newFilter(tt.config, genesis, func() (uint64, uint64) { return tt.head, tt.time }) - if err := filter(tt.id); err != tt.err { + if err := filter(tt.id); !errors.Is(err, tt.err) { t.Errorf("test %d: validation error mismatch: have %v, want %v", i, err, tt.err) } } diff --git a/core/rawdb/freezer_table_test.go b/core/rawdb/freezer_table_test.go index fd6e3cf199..88203a06a5 100644 --- a/core/rawdb/freezer_table_test.go +++ b/core/rawdb/freezer_table_test.go @@ -19,6 +19,7 @@ package rawdb import ( "bytes" "encoding/binary" + "errors" "fmt" "math/rand" "os" @@ -68,7 +69,7 @@ func TestFreezerBasics(t *testing.T) { } // Check that we cannot read too far _, err = f.Retrieve(uint64(255)) - if err != errOutOfBounds { + if !errors.Is(err, errOutOfBounds) { t.Fatal(err) } } @@ -878,7 +879,7 @@ func checkRetrieveError(t *testing.T, f *freezerTable, items map[uint64]error) { if err == nil { t.Fatalf("unexpected value %x for item %d, want error %v", item, value, wantError) } - if err != wantError { + if !errors.Is(err, wantError) { t.Fatalf("wrong error for item %d: %v", item, err) } } @@ -1361,7 +1362,8 @@ func runRandTest(rt randTest) bool { func TestRandom(t *testing.T) { if err := quick.Check(runRandTest, nil); err != nil { - if cerr, ok := err.(*quick.CheckError); ok { + cerr := new(quick.CheckError) + if ok := errors.As(err, &cerr); ok { t.Fatalf("random test iteration %d failed: %s", cerr.Count, spew.Sdump(cerr.In)) } t.Fatal(err) diff --git a/core/rawdb/freezer_test.go b/core/rawdb/freezer_test.go index 7d82ea305f..45a001a345 100644 --- a/core/rawdb/freezer_test.go +++ b/core/rawdb/freezer_test.go @@ -104,7 +104,7 @@ func TestFreezerModifyRollback(t *testing.T) { require.NoError(t, op.AppendRaw("test", 2, make([]byte, 2048))) return theError }) - if err != theError { + if !errors.Is(err, theError) { t.Errorf("ModifyAncients returned wrong error %q", err) } checkAncientCount(t, f, "test", 0) @@ -372,7 +372,7 @@ func checkAncientCount(t *testing.T, f *Freezer, kind string, n uint64) { } if _, err := f.Ancient(kind, index); err == nil { t.Errorf("Ancient(%q, %d) didn't return expected error", kind, index) - } else if err != errOutOfBounds { + } else if !errors.Is(err, errOutOfBounds) { t.Errorf("Ancient(%q, %d) returned unexpected error %q", kind, index, err) } } diff --git a/core/state/snapshot/disklayer_test.go b/core/state/snapshot/disklayer_test.go index 6d99a90d61..e88558f253 100644 --- a/core/state/snapshot/disklayer_test.go +++ b/core/state/snapshot/disklayer_test.go @@ -18,6 +18,7 @@ package snapshot import ( "bytes" + "errors" "testing" "github.com/VictoriaMetrics/fastcache" @@ -313,7 +314,7 @@ func TestDiskPartialMerge(t *testing.T) { assertAccount := func(account common.Hash, data []byte) { t.Helper() blob, err := base.AccountRLP(account) - if bytes.Compare(account[:], genMarker) > 0 && err != ErrNotCoveredYet { + if bytes.Compare(account[:], genMarker) > 0 && !errors.Is(err, ErrNotCoveredYet) { t.Fatalf("test %d: post-marker (%x) account access (%x) succeeded: %x", i, genMarker, account, blob) } if bytes.Compare(account[:], genMarker) <= 0 && !bytes.Equal(blob, data) { @@ -329,7 +330,7 @@ func TestDiskPartialMerge(t *testing.T) { assertStorage := func(account common.Hash, slot common.Hash, data []byte) { t.Helper() blob, err := base.Storage(account, slot) - if bytes.Compare(append(account[:], slot[:]...), genMarker) > 0 && err != ErrNotCoveredYet { + if bytes.Compare(append(account[:], slot[:]...), genMarker) > 0 && !errors.Is(err, ErrNotCoveredYet) { t.Fatalf("test %d: post-marker (%x) storage access (%x:%x) succeeded: %x", i, genMarker, account, slot, blob) } if bytes.Compare(append(account[:], slot[:]...), genMarker) <= 0 && !bytes.Equal(blob, data) { diff --git a/core/state/snapshot/generate.go b/core/state/snapshot/generate.go index 01fb55ea4c..6d0fdef960 100644 --- a/core/state/snapshot/generate.go +++ b/core/state/snapshot/generate.go @@ -670,7 +670,8 @@ func (dl *diskLayer) generate(stats *generatorStats) { if err := generateAccounts(ctx, dl, accMarker); err != nil { // Extract the received interruption signal if exists - if aerr, ok := err.(*abortErr); ok { + aerr := new(abortErr) + if ok := errors.As(err, &aerr); ok { abort = aerr.abort } // Aborted by internal error, wait the signal diff --git a/core/state/snapshot/snapshot_test.go b/core/state/snapshot/snapshot_test.go index 34ef61e8d0..736b604b15 100644 --- a/core/state/snapshot/snapshot_test.go +++ b/core/state/snapshot/snapshot_test.go @@ -19,6 +19,7 @@ package snapshot import ( crand "crypto/rand" "encoding/binary" + "errors" "fmt" "math/rand" "testing" @@ -118,10 +119,10 @@ func TestDiskLayerExternalInvalidationFullFlatten(t *testing.T) { t.Fatalf("failed to merge diff layer onto disk: %v", err) } // Since the base layer was modified, ensure that data retrievals on the external reference fail - if acc, err := ref.Account(common.HexToHash("0x01")); err != ErrSnapshotStale { + if acc, err := ref.Account(common.HexToHash("0x01")); !errors.Is(err, ErrSnapshotStale) { t.Errorf("stale reference returned account: %#x (err: %v)", acc, err) } - if slot, err := ref.Storage(common.HexToHash("0xa1"), common.HexToHash("0xb1")); err != ErrSnapshotStale { + if slot, err := ref.Storage(common.HexToHash("0xa1"), common.HexToHash("0xb1")); !errors.Is(err, ErrSnapshotStale) { t.Errorf("stale reference returned storage slot: %#x (err: %v)", slot, err) } if n := len(snaps.layers); n != 1 { @@ -168,10 +169,10 @@ func TestDiskLayerExternalInvalidationPartialFlatten(t *testing.T) { t.Fatalf("failed to merge accumulator onto disk: %v", err) } // Since the base layer was modified, ensure that data retrievals on the external reference fail - if acc, err := ref.Account(common.HexToHash("0x01")); err != ErrSnapshotStale { + if acc, err := ref.Account(common.HexToHash("0x01")); !errors.Is(err, ErrSnapshotStale) { t.Errorf("stale reference returned account: %#x (err: %v)", acc, err) } - if slot, err := ref.Storage(common.HexToHash("0xa1"), common.HexToHash("0xb1")); err != ErrSnapshotStale { + if slot, err := ref.Storage(common.HexToHash("0xa1"), common.HexToHash("0xb1")); !errors.Is(err, ErrSnapshotStale) { t.Errorf("stale reference returned storage slot: %#x (err: %v)", slot, err) } if n := len(snaps.layers); n != 2 { @@ -230,10 +231,10 @@ func TestDiffLayerExternalInvalidationPartialFlatten(t *testing.T) { t.Fatalf("failed to flatten diff layer into accumulator: %v", err) } // Since the accumulator diff layer was modified, ensure that data retrievals on the external reference fail - if acc, err := ref.Account(common.HexToHash("0x01")); err != ErrSnapshotStale { + if acc, err := ref.Account(common.HexToHash("0x01")); !errors.Is(err, ErrSnapshotStale) { t.Errorf("stale reference returned account: %#x (err: %v)", acc, err) } - if slot, err := ref.Storage(common.HexToHash("0xa1"), common.HexToHash("0xb1")); err != ErrSnapshotStale { + if slot, err := ref.Storage(common.HexToHash("0xa1"), common.HexToHash("0xb1")); !errors.Is(err, ErrSnapshotStale) { t.Errorf("stale reference returned storage slot: %#x (err: %v)", slot, err) } if n := len(snaps.layers); n != 3 { diff --git a/core/state/statedb_fuzz_test.go b/core/state/statedb_fuzz_test.go index 7cbfd9b9d7..21f8877f22 100644 --- a/core/state/statedb_fuzz_test.go +++ b/core/state/statedb_fuzz_test.go @@ -437,7 +437,8 @@ func (test *stateTest) verify(root common.Hash, next common.Hash, db *triedb.Dat func TestStateChanges(t *testing.T) { config := &quick.Config{MaxCount: 1000} err := quick.Check((*stateTest).run, config) - if cerr, ok := err.(*quick.CheckError); ok { + cerr := new(quick.CheckError) + if ok := errors.As(err, &cerr); ok { test := cerr.In[0].(*stateTest) t.Errorf("%v:\n%s", test.err, test) } else if err != nil { diff --git a/core/state/statedb_test.go b/core/state/statedb_test.go index 37141e90b0..d1d3ac12f1 100644 --- a/core/state/statedb_test.go +++ b/core/state/statedb_test.go @@ -19,6 +19,7 @@ package state import ( "bytes" "encoding/binary" + "errors" "fmt" "maps" "math" @@ -304,7 +305,8 @@ func TestCopyObjectState(t *testing.T) { func TestSnapshotRandom(t *testing.T) { config := &quick.Config{MaxCount: 1000} err := quick.Check((*snapshotTest).run, config) - if cerr, ok := err.(*quick.CheckError); ok { + cerr := new(quick.CheckError) + if ok := errors.As(err, &cerr); ok { test := cerr.In[0].(*snapshotTest) t.Errorf("%v:\n%s", test.err, test) } else if err != nil { diff --git a/core/state_transition.go b/core/state_transition.go index b6203e6aae..ee296c1896 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -17,6 +17,7 @@ package core import ( + "errors" "fmt" "math" "math/big" @@ -60,7 +61,7 @@ func (result *ExecutionResult) Return() []byte { // Revert returns the concrete revert reason if the execution is aborted by `REVERT` // opcode. Note the reason can be nil if no data supplied with revert opcode. func (result *ExecutionResult) Revert() []byte { - if result.Err != vm.ErrExecutionReverted { + if !errors.Is(result.Err, vm.ErrExecutionReverted) { return nil } return common.CopyBytes(result.ReturnData) diff --git a/core/txpool/legacypool/journal.go b/core/txpool/legacypool/journal.go index 899ed00bcc..a472615dcd 100644 --- a/core/txpool/legacypool/journal.go +++ b/core/txpool/legacypool/journal.go @@ -96,7 +96,7 @@ func (journal *journal) load(add func([]*types.Transaction) []error) error { // Parse the next transaction and terminate on error tx := new(types.Transaction) if err = stream.Decode(tx); err != nil { - if err != io.EOF { + if !errors.Is(err, io.EOF) { failure = err } if batch.Len() > 0 { diff --git a/core/txpool/legacypool/legacypool_test.go b/core/txpool/legacypool/legacypool_test.go index abbde8cae3..960dabc912 100644 --- a/core/txpool/legacypool/legacypool_test.go +++ b/core/txpool/legacypool/legacypool_test.go @@ -421,7 +421,7 @@ func TestNegativeValue(t *testing.T) { tx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(-1), 100, big.NewInt(1), nil), types.HomesteadSigner{}, key) from, _ := deriveSender(tx) testAddBalance(pool, from, big.NewInt(1)) - if err := pool.addRemote(tx); err != txpool.ErrNegativeValue { + if err := pool.addRemote(tx); !errors.Is(err, txpool.ErrNegativeValue) { t.Error("expected", txpool.ErrNegativeValue, "got", err) } } @@ -434,7 +434,7 @@ func TestTipAboveFeeCap(t *testing.T) { tx := dynamicFeeTx(0, 100, big.NewInt(1), big.NewInt(2), key) - if err := pool.addRemote(tx); err != core.ErrTipAboveFeeCap { + if err := pool.addRemote(tx); !errors.Is(err, core.ErrTipAboveFeeCap) { t.Error("expected", core.ErrTipAboveFeeCap, "got", err) } } @@ -449,12 +449,12 @@ func TestVeryHighValues(t *testing.T) { veryBigNumber.Lsh(veryBigNumber, 300) tx := dynamicFeeTx(0, 100, big.NewInt(1), veryBigNumber, key) - if err := pool.addRemote(tx); err != core.ErrTipVeryHigh { + if err := pool.addRemote(tx); !errors.Is(err, core.ErrTipVeryHigh) { t.Error("expected", core.ErrTipVeryHigh, "got", err) } tx2 := dynamicFeeTx(0, 100, veryBigNumber, big.NewInt(1), key) - if err := pool.addRemote(tx2); err != core.ErrFeeCapVeryHigh { + if err := pool.addRemote(tx2); !errors.Is(err, core.ErrFeeCapVeryHigh) { t.Error("expected", core.ErrFeeCapVeryHigh, "got", err) } } @@ -1804,7 +1804,7 @@ func TestUnderpricing(t *testing.T) { t.Fatalf("failed to add well priced transaction: %v", err) } // Ensure that replacing a pending transaction with a future transaction fails - if err := pool.addRemote(pricedTransaction(5, 100000, big.NewInt(6), keys[1])); err != txpool.ErrFutureReplacePending { + if err := pool.addRemote(pricedTransaction(5, 100000, big.NewInt(6), keys[1])); !errors.Is(err, txpool.ErrFutureReplacePending) { t.Fatalf("adding future replace transaction error mismatch: have %v, want %v", err, txpool.ErrFutureReplacePending) } pending, queued = pool.Stats() @@ -2174,7 +2174,7 @@ func TestReplacement(t *testing.T) { if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1), key)); err != nil { t.Fatalf("failed to add original cheap pending transaction: %v", err) } - if err := pool.addRemote(pricedTransaction(0, 100001, big.NewInt(1), key)); err != txpool.ErrReplaceUnderpriced { + if err := pool.addRemote(pricedTransaction(0, 100001, big.NewInt(1), key)); !errors.Is(err, txpool.ErrReplaceUnderpriced) { t.Fatalf("original cheap pending transaction replacement error mismatch: have %v, want %v", err, txpool.ErrReplaceUnderpriced) } if err := pool.addRemote(pricedTransaction(0, 100000, big.NewInt(2), key)); err != nil { @@ -2187,7 +2187,7 @@ func TestReplacement(t *testing.T) { if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(price), key)); err != nil { t.Fatalf("failed to add original proper pending transaction: %v", err) } - if err := pool.addRemote(pricedTransaction(0, 100001, big.NewInt(threshold-1), key)); err != txpool.ErrReplaceUnderpriced { + if err := pool.addRemote(pricedTransaction(0, 100001, big.NewInt(threshold-1), key)); !errors.Is(err, txpool.ErrReplaceUnderpriced) { t.Fatalf("original proper pending transaction replacement error mismatch: have %v, want %v", err, txpool.ErrReplaceUnderpriced) } if err := pool.addRemote(pricedTransaction(0, 100000, big.NewInt(threshold), key)); err != nil { @@ -2201,7 +2201,7 @@ func TestReplacement(t *testing.T) { if err := pool.addRemote(pricedTransaction(2, 100000, big.NewInt(1), key)); err != nil { t.Fatalf("failed to add original cheap queued transaction: %v", err) } - if err := pool.addRemote(pricedTransaction(2, 100001, big.NewInt(1), key)); err != txpool.ErrReplaceUnderpriced { + if err := pool.addRemote(pricedTransaction(2, 100001, big.NewInt(1), key)); !errors.Is(err, txpool.ErrReplaceUnderpriced) { t.Fatalf("original cheap queued transaction replacement error mismatch: have %v, want %v", err, txpool.ErrReplaceUnderpriced) } if err := pool.addRemote(pricedTransaction(2, 100000, big.NewInt(2), key)); err != nil { @@ -2211,7 +2211,7 @@ func TestReplacement(t *testing.T) { if err := pool.addRemote(pricedTransaction(2, 100000, big.NewInt(price), key)); err != nil { t.Fatalf("failed to add original proper queued transaction: %v", err) } - if err := pool.addRemote(pricedTransaction(2, 100001, big.NewInt(threshold-1), key)); err != txpool.ErrReplaceUnderpriced { + if err := pool.addRemote(pricedTransaction(2, 100001, big.NewInt(threshold-1), key)); !errors.Is(err, txpool.ErrReplaceUnderpriced) { t.Fatalf("original proper queued transaction replacement error mismatch: have %v, want %v", err, txpool.ErrReplaceUnderpriced) } if err := pool.addRemote(pricedTransaction(2, 100000, big.NewInt(threshold), key)); err != nil { @@ -2275,7 +2275,7 @@ func TestReplacementDynamicFee(t *testing.T) { } // 2. Don't bump tip or feecap => discard tx = dynamicFeeTx(nonce, 100001, big.NewInt(2), big.NewInt(1), key) - if err := pool.addRemote(tx); err != txpool.ErrReplaceUnderpriced { + if err := pool.addRemote(tx); !errors.Is(err, txpool.ErrReplaceUnderpriced) { t.Fatalf("original cheap %s transaction replacement error mismatch: have %v, want %v", stage, err, txpool.ErrReplaceUnderpriced) } // 3. Bump both more than min => accept @@ -2298,22 +2298,22 @@ func TestReplacementDynamicFee(t *testing.T) { } // 6. Bump tip max allowed so it's still underpriced => discard tx = dynamicFeeTx(nonce, 100000, big.NewInt(gasFeeCap), big.NewInt(tipThreshold-1), key) - if err := pool.addRemote(tx); err != txpool.ErrReplaceUnderpriced { + if err := pool.addRemote(tx); !errors.Is(err, txpool.ErrReplaceUnderpriced) { t.Fatalf("original proper %s transaction replacement error mismatch: have %v, want %v", stage, err, txpool.ErrReplaceUnderpriced) } // 7. Bump fee cap max allowed so it's still underpriced => discard tx = dynamicFeeTx(nonce, 100000, big.NewInt(feeCapThreshold-1), big.NewInt(gasTipCap), key) - if err := pool.addRemote(tx); err != txpool.ErrReplaceUnderpriced { + if err := pool.addRemote(tx); !errors.Is(err, txpool.ErrReplaceUnderpriced) { t.Fatalf("original proper %s transaction replacement error mismatch: have %v, want %v", stage, err, txpool.ErrReplaceUnderpriced) } // 8. Bump tip min for acceptance => accept tx = dynamicFeeTx(nonce, 100000, big.NewInt(gasFeeCap), big.NewInt(tipThreshold), key) - if err := pool.addRemote(tx); err != txpool.ErrReplaceUnderpriced { + if err := pool.addRemote(tx); !errors.Is(err, txpool.ErrReplaceUnderpriced) { t.Fatalf("original proper %s transaction replacement error mismatch: have %v, want %v", stage, err, txpool.ErrReplaceUnderpriced) } // 9. Bump fee cap min for acceptance => accept tx = dynamicFeeTx(nonce, 100000, big.NewInt(feeCapThreshold), big.NewInt(gasTipCap), key) - if err := pool.addRemote(tx); err != txpool.ErrReplaceUnderpriced { + if err := pool.addRemote(tx); !errors.Is(err, txpool.ErrReplaceUnderpriced) { t.Fatalf("original proper %s transaction replacement error mismatch: have %v, want %v", stage, err, txpool.ErrReplaceUnderpriced) } // 10. Check events match expected (3 new executable txs during pending, 0 during queue) diff --git a/core/types/receipt_test.go b/core/types/receipt_test.go index fc51eb11a5..8ecfa0dbf1 100644 --- a/core/types/receipt_test.go +++ b/core/types/receipt_test.go @@ -19,6 +19,7 @@ package types import ( "bytes" "encoding/json" + "errors" "math" "math/big" "reflect" @@ -300,7 +301,7 @@ func TestDecodeEmptyTypedReceipt(t *testing.T) { input := []byte{0x80} var r Receipt err := rlp.DecodeBytes(input, &r) - if err != errShortTypedReceipt { + if !errors.Is(err, errShortTypedReceipt) { t.Fatal("wrong error:", err) } } diff --git a/core/types/transaction_test.go b/core/types/transaction_test.go index 17a7dda357..cb06ef9d96 100644 --- a/core/types/transaction_test.go +++ b/core/types/transaction_test.go @@ -76,7 +76,7 @@ func TestDecodeEmptyTypedTx(t *testing.T) { input := []byte{0x80} var tx Transaction err := rlp.DecodeBytes(input, &tx) - if err != errShortTypedTx { + if !errors.Is(err, errShortTypedTx) { t.Fatal("wrong error:", err) } } @@ -569,7 +569,7 @@ func TestYParityJSONUnmarshalling(t *testing.T) { // Unmarshal the tx var tx Transaction err = tx.UnmarshalJSON(jsonBytes) - if err != test.wantErr { + if !errors.Is(err, test.wantErr) { t.Fatalf("wrong error: got %v, want %v", err, test.wantErr) } }) diff --git a/core/vm/eof_test.go b/core/vm/eof_test.go index 8106a29728..44d8b47a83 100644 --- a/core/vm/eof_test.go +++ b/core/vm/eof_test.go @@ -18,6 +18,7 @@ package vm import ( "encoding/hex" + "errors" "reflect" "testing" @@ -66,7 +67,7 @@ func TestEOFMarshaling(t *testing.T) { got Container ) t.Logf("b: %#x", b) - if err := got.UnmarshalBinary(b, true); err != nil && err != test.err { + if err := got.UnmarshalBinary(b, true); err != nil && !errors.Is(err, test.err) { t.Fatalf("test %d: got error \"%v\", want \"%v\"", i, err, test.err) } if !reflect.DeepEqual(got, test.want) { diff --git a/core/vm/evm.go b/core/vm/evm.go index 1a0215459c..2130276dda 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -235,7 +235,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas // when we're in homestead this also counts for code storage gas errors. if err != nil { evm.StateDB.RevertToSnapshot(snapshot) - if err != ErrExecutionReverted { + if !errors.Is(err, ErrExecutionReverted) { if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil { evm.Config.Tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution) } @@ -291,7 +291,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, } if err != nil { evm.StateDB.RevertToSnapshot(snapshot) - if err != ErrExecutionReverted { + if !errors.Is(err, ErrExecutionReverted) { if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil { evm.Config.Tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution) } @@ -338,7 +338,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by } if err != nil { evm.StateDB.RevertToSnapshot(snapshot) - if err != ErrExecutionReverted { + if !errors.Is(err, ErrExecutionReverted) { if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil { evm.Config.Tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution) } @@ -396,7 +396,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte } if err != nil { evm.StateDB.RevertToSnapshot(snapshot) - if err != ErrExecutionReverted { + if !errors.Is(err, ErrExecutionReverted) { if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil { evm.Config.Tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution) } @@ -509,9 +509,9 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, contract.IsDeployment = true ret, err = evm.initNewContract(contract, address, value) - if err != nil && (evm.chainRules.IsHomestead || err != ErrCodeStoreOutOfGas) { + if err != nil && (evm.chainRules.IsHomestead || !errors.Is(err, ErrCodeStoreOutOfGas)) { evm.StateDB.RevertToSnapshot(snapshot) - if err != ErrExecutionReverted { + if !errors.Is(err, ErrExecutionReverted) { contract.UseGas(contract.Gas, evm.Config.Tracer, tracing.GasChangeCallFailedExecution) } } diff --git a/core/vm/gas_table_test.go b/core/vm/gas_table_test.go index be86885261..1f5d8f169d 100644 --- a/core/vm/gas_table_test.go +++ b/core/vm/gas_table_test.go @@ -43,8 +43,8 @@ func TestMemoryGasCost(t *testing.T) { } for i, tt := range tests { v, err := memoryGasCost(&Memory{}, tt.size) - if (err == ErrGasUintOverflow) != tt.overflow { - t.Errorf("test %d: overflow mismatch: have %v, want %v", i, err == ErrGasUintOverflow, tt.overflow) + if errors.Is(err, ErrGasUintOverflow) != tt.overflow { + t.Errorf("test %d: overflow mismatch: have %v, want %v", i, errors.Is(err, ErrGasUintOverflow), tt.overflow) } if v != tt.cost { t.Errorf("test %d: gas cost mismatch: have %v, want %v", i, v, tt.cost) diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 9b9a31a855..031b7aadd1 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -17,6 +17,7 @@ package vm import ( + "errors" "math" "github.com/ethereum/go-ethereum/common" @@ -679,9 +680,9 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b // homestead we must check for CodeStoreOutOfGasError (homestead only // rule) and treat as an error, if the ruleset is frontier we must // ignore this error and pretend the operation was successful. - if interpreter.evm.chainRules.IsHomestead && suberr == ErrCodeStoreOutOfGas { + if interpreter.evm.chainRules.IsHomestead && errors.Is(suberr, ErrCodeStoreOutOfGas) { stackvalue.Clear() - } else if suberr != nil && suberr != ErrCodeStoreOutOfGas { + } else if suberr != nil && !errors.Is(suberr, ErrCodeStoreOutOfGas) { stackvalue.Clear() } else { stackvalue.SetBytes(addr.Bytes()) @@ -690,7 +691,7 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b scope.Contract.RefundGas(returnGas, interpreter.evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded) - if suberr == ErrExecutionReverted { + if errors.Is(suberr, ErrExecutionReverted) { interpreter.returnData = res // set REVERT data to return data buffer return res, nil } @@ -726,7 +727,7 @@ func opCreate2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([] scope.Stack.push(&stackvalue) scope.Contract.RefundGas(returnGas, interpreter.evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded) - if suberr == ErrExecutionReverted { + if errors.Is(suberr, ErrExecutionReverted) { interpreter.returnData = res // set REVERT data to return data buffer return res, nil } @@ -760,7 +761,7 @@ func opCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byt temp.SetOne() } stack.push(&temp) - if err == nil || err == ErrExecutionReverted { + if err == nil || errors.Is(err, ErrExecutionReverted) { scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) } @@ -793,7 +794,7 @@ func opCallCode(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([ temp.SetOne() } stack.push(&temp) - if err == nil || err == ErrExecutionReverted { + if err == nil || errors.Is(err, ErrExecutionReverted) { scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) } @@ -822,7 +823,7 @@ func opDelegateCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext temp.SetOne() } stack.push(&temp) - if err == nil || err == ErrExecutionReverted { + if err == nil || errors.Is(err, ErrExecutionReverted) { scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) } @@ -851,7 +852,7 @@ func opStaticCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) temp.SetOne() } stack.push(&temp) - if err == nil || err == ErrExecutionReverted { + if err == nil || errors.Is(err, ErrExecutionReverted) { scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) } diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index 996ed6e56a..e43b5b4376 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -17,6 +17,7 @@ package vm import ( + "errors" "fmt" "github.com/ethereum/go-ethereum/common" @@ -322,7 +323,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( pc++ } - if err == errStopToken { + if errors.Is(err, errStopToken) { err = nil // clear stop token error } diff --git a/crypto/blake2b/blake2b_test.go b/crypto/blake2b/blake2b_test.go index 9d24444a27..2167c1de6a 100644 --- a/crypto/blake2b/blake2b_test.go +++ b/crypto/blake2b/blake2b_test.go @@ -8,6 +8,7 @@ import ( "bytes" "encoding" "encoding/hex" + "errors" "fmt" "hash" "io" @@ -166,7 +167,7 @@ func testHashes2X(t *testing.T) { if _, err := h.Read(sum); err != nil { t.Fatalf("#%d (single write): error from Read: %v", i, err) } - if n, err := h.Read(sum); n != 0 || err != io.EOF { + if n, err := h.Read(sum); n != 0 || !errors.Is(err, io.EOF) { t.Fatalf("#%d (single write): Read did not return (0, io.EOF) after exhaustion, got (%v, %v)", i, n, err) } if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { diff --git a/crypto/crypto.go b/crypto/crypto.go index aaa5cc43a2..77c0a9bbaf 100644 --- a/crypto/crypto.go +++ b/crypto/crypto.go @@ -191,7 +191,8 @@ func FromECDSAPub(pub *ecdsa.PublicKey) []byte { // HexToECDSA parses a secp256k1 private key. func HexToECDSA(hexkey string) (*ecdsa.PrivateKey, error) { b, err := hex.DecodeString(hexkey) - if byteErr, ok := err.(hex.InvalidByteError); ok { + var byteErr hex.InvalidByteError + if ok := errors.As(err, &byteErr); ok { return nil, fmt.Errorf("invalid hex character %q in private key", byte(byteErr)) } else if err != nil { return nil, errors.New("invalid hex data for private key") @@ -228,7 +229,7 @@ func readASCII(buf []byte, r *bufio.Reader) (n int, err error) { for ; n < len(buf); n++ { buf[n], err = r.ReadByte() switch { - case err == io.EOF || buf[n] < '!': + case errors.Is(err, io.EOF) || buf[n] < '!': return n, nil case err != nil: return n, err @@ -242,7 +243,7 @@ func checkKeyFileEnd(r *bufio.Reader) error { for i := 0; ; i++ { b, err := r.ReadByte() switch { - case err == io.EOF: + case errors.Is(err, io.EOF): return nil case err != nil: return err diff --git a/crypto/crypto_test.go b/crypto/crypto_test.go index da123cf980..7d348c137f 100644 --- a/crypto/crypto_test.go +++ b/crypto/crypto_test.go @@ -20,6 +20,7 @@ import ( "bytes" "crypto/ecdsa" "encoding/hex" + "errors" "math/big" "os" "reflect" @@ -66,11 +67,11 @@ func BenchmarkSha3(b *testing.B) { func TestUnmarshalPubkey(t *testing.T) { key, err := UnmarshalPubkey(nil) - if err != errInvalidPubkey || key != nil { + if !errors.Is(err, errInvalidPubkey) || key != nil { t.Fatalf("expected error, got %v, %v", err, key) } key, err = UnmarshalPubkey([]byte{1, 2, 3}) - if err != errInvalidPubkey || key != nil { + if !errors.Is(err, errInvalidPubkey) || key != nil { t.Fatalf("expected error, got %v, %v", err, key) } diff --git a/crypto/ecies/ecies_test.go b/crypto/ecies/ecies_test.go index e3da71010e..0b3a2e070c 100644 --- a/crypto/ecies/ecies_test.go +++ b/crypto/ecies/ecies_test.go @@ -152,12 +152,12 @@ func TestTooBigSharedKey(t *testing.T) { } _, err = prv1.GenerateShared(&prv2.PublicKey, 32, 32) - if err != ErrSharedKeyTooBig { + if !errors.Is(err, ErrSharedKeyTooBig) { t.Fatal("ecdh: shared key should be too large for curve") } _, err = prv2.GenerateShared(&prv1.PublicKey, 32, 32) - if err != ErrSharedKeyTooBig { + if !errors.Is(err, ErrSharedKeyTooBig) { t.Fatal("ecdh: shared key should be too large for curve") } } @@ -355,7 +355,7 @@ func TestBasicKeyValidation(t *testing.T) { for _, b := range badBytes { ct[0] = b _, err := prv.Decrypt(ct, nil, nil) - if err != ErrInvalidPublicKey { + if !errors.Is(err, ErrInvalidPublicKey) { t.Fatal("ecies: validated an invalid key") } } diff --git a/crypto/secp256k1/secp256_test.go b/crypto/secp256k1/secp256_test.go index 4827cc5b25..9a501999de 100644 --- a/crypto/secp256k1/secp256_test.go +++ b/crypto/secp256k1/secp256_test.go @@ -12,6 +12,7 @@ import ( "crypto/ecdsa" "crypto/rand" "encoding/hex" + "errors" "io" "testing" ) @@ -91,7 +92,7 @@ func TestInvalidRecoveryID(t *testing.T) { sig, _ := Sign(msg, seckey) sig[64] = 99 _, err := RecoverPubkey(msg, sig) - if err != ErrInvalidRecoveryID { + if !errors.Is(err, ErrInvalidRecoveryID) { t.Fatalf("got %q, want %q", err, ErrInvalidRecoveryID) } } diff --git a/eth/api_admin.go b/eth/api_admin.go index 4a3ccb84e8..a1c222bf9b 100644 --- a/eth/api_admin.go +++ b/eth/api_admin.go @@ -113,7 +113,7 @@ func (api *AdminAPI) ImportChain(file string) (bool, error) { // Load a batch of blocks from the input file for len(blocks) < cap(blocks) { block := new(types.Block) - if err := stream.Decode(block); err == io.EOF { + if err := stream.Decode(block); errors.Is(err, io.EOF) { break } else if err != nil { return false, fmt.Errorf("block %d: failed to parse: %v", index, err) diff --git a/eth/catalyst/api_test.go b/eth/catalyst/api_test.go index e0a155f12b..20aca43180 100644 --- a/eth/catalyst/api_test.go +++ b/eth/catalyst/api_test.go @@ -1295,7 +1295,9 @@ func TestNilWithdrawals(t *testing.T) { status, err = api.NewPayloadV2(*execData.ExecutionPayload) } if err != nil { - t.Fatalf("error validating payload: %v", err.(*engine.EngineAPIError).ErrorData()) + engineAPIErr := new(engine.EngineAPIError) + _ = errors.As(err, &engineAPIErr) + t.Fatalf("error validating payload: %v", engineAPIErr.ErrorData()) } else if status.Status != engine.VALID { t.Fatalf("invalid payload") } @@ -1644,7 +1646,9 @@ func TestParentBeaconBlockRoot(t *testing.T) { } resp, err := api.ForkchoiceUpdatedV3(fcState, &blockParams) if err != nil { - t.Fatalf("error preparing payload, err=%v", err.(*engine.EngineAPIError).ErrorData()) + engineAPIErr := new(engine.EngineAPIError) + _ = errors.As(err, &engineAPIErr) + t.Fatalf("error preparing payload, err=%v", engineAPIErr.ErrorData()) } if resp.PayloadStatus.Status != engine.VALID { t.Fatalf("unexpected status (got: %s, want: %s)", resp.PayloadStatus.Status, engine.VALID) @@ -1675,7 +1679,9 @@ func TestParentBeaconBlockRoot(t *testing.T) { fcState.HeadBlockHash = execData.ExecutionPayload.BlockHash resp, err = api.ForkchoiceUpdatedV3(fcState, nil) if err != nil { - t.Fatalf("error preparing payload, err=%v", err.(*engine.EngineAPIError).ErrorData()) + engineAPIErr := new(engine.EngineAPIError) + _ = errors.As(err, &engineAPIErr) + t.Fatalf("error preparing payload, err=%v", engineAPIErr.ErrorData()) } if resp.PayloadStatus.Status != engine.VALID { t.Fatalf("unexpected status (got: %s, want: %s)", resp.PayloadStatus.Status, engine.VALID) diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 8ac5d2eb31..52f1baa3df 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -566,7 +566,7 @@ func (d *Downloader) spawnSync(fetchers []func() error) error { } if got := <-errc; got != nil { err = got - if got != errCanceled { + if !errors.Is(got, errCanceled) { break // receive a meaningful error, bubble it up } } @@ -817,7 +817,7 @@ func (d *Downloader) processSnapSyncContent() error { }() closeOnErr := func(s *stateSync) { - if err := s.Wait(); err != nil && err != errCancelStateFetch && err != errCanceled && err != snap.ErrCancelled { + if err := s.Wait(); err != nil && !errors.Is(err, errCancelStateFetch) && !errors.Is(err, errCanceled) && !errors.Is(err, snap.ErrCancelled) { d.queue.Close() // wake up Results } } diff --git a/eth/downloader/skeleton.go b/eth/downloader/skeleton.go index 04421a2bf5..caba5a192a 100644 --- a/eth/downloader/skeleton.go +++ b/eth/downloader/skeleton.go @@ -278,25 +278,25 @@ func (s *skeleton) startup() { // signalling as the sync loop should never terminate (TM). newhead, err := s.sync(head) switch { - case err == errSyncLinked: + case errors.Is(err, errSyncLinked): // Sync cycle linked up to the genesis block, or the existent chain // segment. Tear down the loop and restart it so, it can properly // notify the backfiller. Don't account a new head. head = nil - case err == errSyncMerged: + case errors.Is(err, errSyncMerged): // Subchains were merged, we just need to reinit the internal // start to continue on the tail of the merged chain. Don't // announce a new head, head = nil - case err == errSyncReorged: + case errors.Is(err, errSyncReorged): // The subchain being synced got modified at the head in a // way that requires resyncing it. Restart sync with the new // head to force a cleanup. head = newhead - case err == errTerminated: + case errors.Is(err, errTerminated): // Sync was requested to be terminated from within, stop and // return (no need to pass a message, was already done internally) return diff --git a/eth/filters/filter_system_test.go b/eth/filters/filter_system_test.go index aec5ee4166..bd9e7ab001 100644 --- a/eth/filters/filter_system_test.go +++ b/eth/filters/filter_system_test.go @@ -459,7 +459,7 @@ func TestInvalidGetRangeLogsRequest(t *testing.T) { api = NewFilterAPI(sys) ) - if _, err := api.GetLogs(context.Background(), FilterCriteria{FromBlock: big.NewInt(2), ToBlock: big.NewInt(1)}); err != errInvalidBlockRange { + if _, err := api.GetLogs(context.Background(), FilterCriteria{FromBlock: big.NewInt(2), ToBlock: big.NewInt(1)}); !errors.Is(err, errInvalidBlockRange) { t.Errorf("Expected Logs for invalid range return error, but got: %v", err) } } diff --git a/eth/filters/filter_test.go b/eth/filters/filter_test.go index 6a3057326d..bf71c28811 100644 --- a/eth/filters/filter_test.go +++ b/eth/filters/filter_test.go @@ -19,6 +19,7 @@ package filters import ( "context" "encoding/json" + "errors" "math/big" "strings" "testing" @@ -382,7 +383,7 @@ func TestFilters(t *testing.T) { if err == nil { t.Fatal("expected error") } - if err != context.DeadlineExceeded { + if !errors.Is(err, context.DeadlineExceeded) { t.Fatalf("expected context.DeadlineExceeded, got %v", err) } }) diff --git a/eth/gasprice/feehistory_test.go b/eth/gasprice/feehistory_test.go index 241b91b810..5516b90ebe 100644 --- a/eth/gasprice/feehistory_test.go +++ b/eth/gasprice/feehistory_test.go @@ -90,7 +90,7 @@ func TestFeeHistory(t *testing.T) { if len(blobBaseFee) != len(baseFee) { t.Fatalf("Test case %d: blobBaseFee array length mismatch, want %d, got %d", i, len(baseFee), len(blobBaseFee)) } - if err != c.expErr && !errors.Is(err, c.expErr) { + if !errors.Is(err, c.expErr) { t.Fatalf("Test case %d: error mismatch, want %v, got %v", i, c.expErr, err) } } diff --git a/eth/protocols/eth/handshake.go b/eth/protocols/eth/handshake.go index 68cf846925..9a53e50a9f 100644 --- a/eth/protocols/eth/handshake.go +++ b/eth/protocols/eth/handshake.go @@ -116,16 +116,16 @@ func markError(p *Peer, err error) { return } m := meters.get(p.Inbound()) - switch errors.Unwrap(err) { - case errNetworkIDMismatch: + switch { + case errors.Is(err, errNetworkIDMismatch): m.networkIDMismatch.Mark(1) - case errProtocolVersionMismatch: + case errors.Is(err, errProtocolVersionMismatch): m.protocolVersionMismatch.Mark(1) - case errGenesisMismatch: + case errors.Is(err, errGenesisMismatch): m.genesisMismatch.Mark(1) - case errForkIDRejected: + case errors.Is(err, errForkIDRejected): m.forkidRejected.Mark(1) - case p2p.DiscReadTimeout: + case errors.Is(err, p2p.DiscReadTimeout): m.timeoutError.Mark(1) default: m.peerError.Mark(1) diff --git a/eth/protocols/snap/sync.go b/eth/protocols/snap/sync.go index 9e079f540f..e458bc8071 100644 --- a/eth/protocols/snap/sync.go +++ b/eth/protocols/snap/sync.go @@ -2290,11 +2290,11 @@ func (s *Syncer) processTrienodeHealResponse(res *trienodeHealResponse) { s.trienodeHealBytes += common.StorageSize(len(node)) err := s.healer.scheduler.ProcessNode(trie.NodeSyncResult{Path: res.paths[i], Data: node}) - switch err { - case nil: - case trie.ErrAlreadyProcessed: + switch { + case err == nil: + case errors.Is(err, trie.ErrAlreadyProcessed): s.trienodeHealDups++ - case trie.ErrNotRequested: + case errors.Is(err, trie.ErrNotRequested): s.trienodeHealNops++ default: log.Error("Invalid trienode processed", "hash", hash, "err", err) @@ -2377,11 +2377,11 @@ func (s *Syncer) processBytecodeHealResponse(res *bytecodeHealResponse) { s.bytecodeHealBytes += common.StorageSize(len(node)) err := s.healer.scheduler.ProcessCode(trie.CodeSyncResult{Hash: hash, Data: node}) - switch err { - case nil: - case trie.ErrAlreadyProcessed: + switch { + case err == nil: + case errors.Is(err, trie.ErrAlreadyProcessed): s.bytecodeHealDups++ - case trie.ErrNotRequested: + case errors.Is(err, trie.ErrNotRequested): s.bytecodeHealNops++ default: log.Error("Invalid bytecode processed", "hash", hash, "err", err) diff --git a/eth/state_accessor.go b/eth/state_accessor.go index 0749d73791..c9798eca05 100644 --- a/eth/state_accessor.go +++ b/eth/state_accessor.go @@ -118,12 +118,12 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u } } if err != nil { - switch err.(type) { - case *trie.MissingNodeError: + missingNodeErr := new(*trie.MissingNodeError) + ok := errors.As(err, missingNodeErr) + if ok { return nil, nil, fmt.Errorf("required historical state unavailable (reexec=%d)", reexec) - default: - return nil, nil, err } + return nil, nil, err } } // State is available at historical point, re-execute the blocks on top for diff --git a/ethclient/ethclient_test.go b/ethclient/ethclient_test.go index 4ad8a552d2..67588b1600 100644 --- a/ethclient/ethclient_test.go +++ b/ethclient/ethclient_test.go @@ -286,7 +286,7 @@ func testTransactionInBlock(t *testing.T, client *rpc.Client) { } // Test tx in block not found. - if _, err := ec.TransactionInBlock(context.Background(), block.Hash(), 20); err != ethereum.NotFound { + if _, err := ec.TransactionInBlock(context.Background(), block.Hash(), 20); !errors.Is(err, ethereum.NotFound) { t.Fatal("error should be ethereum.NotFound") } diff --git a/ethdb/leveldb/leveldb.go b/ethdb/leveldb/leveldb.go index f18503c941..948654eb96 100644 --- a/ethdb/leveldb/leveldb.go +++ b/ethdb/leveldb/leveldb.go @@ -22,6 +22,7 @@ package leveldb import ( "bytes" + stderrors "errors" "fmt" "sync" "time" @@ -120,7 +121,8 @@ func NewCustom(file string, namespace string, customize func(options *opt.Option // Open the db and recover any potential corruptions db, err := leveldb.OpenFile(file, options) - if _, corrupted := err.(*errors.ErrCorrupted); corrupted { + corruptedErr := new(errors.ErrCorrupted) + if corrupted := stderrors.As(err, &corruptedErr); corrupted { db, err = leveldb.RecoverFile(file, nil) } if err != nil { diff --git a/ethdb/pebble/pebble.go b/ethdb/pebble/pebble.go index 8d6fcd2d51..42f02678e7 100644 --- a/ethdb/pebble/pebble.go +++ b/ethdb/pebble/pebble.go @@ -19,6 +19,7 @@ package pebble import ( "bytes" + "errors" "fmt" "runtime" "sync" @@ -288,7 +289,7 @@ func (d *Database) Has(key []byte) (bool, error) { return false, pebble.ErrClosed } _, closer, err := d.db.Get(key) - if err == pebble.ErrNotFound { + if errors.Is(err, pebble.ErrNotFound) { return false, nil } else if err != nil { return false, err diff --git a/event/event_test.go b/event/event_test.go index 84b37eca3b..66c824f047 100644 --- a/event/event_test.go +++ b/event/event_test.go @@ -17,6 +17,7 @@ package event import ( + "errors" "math/rand" "sync" "testing" @@ -59,7 +60,7 @@ func TestMuxErrorAfterStop(t *testing.T) { if _, isopen := <-sub.Chan(); isopen { t.Errorf("subscription channel was not closed") } - if err := mux.Post(testEvent(0)); err != ErrMuxClosed { + if err := mux.Post(testEvent(0)); !errors.Is(err, ErrMuxClosed) { t.Errorf("Post error mismatch, got: %s, expected: %s", err, ErrMuxClosed) } } diff --git a/event/subscription_test.go b/event/subscription_test.go index 743d0bf67d..2cd5d4e7c9 100644 --- a/event/subscription_test.go +++ b/event/subscription_test.go @@ -56,7 +56,7 @@ loop: t.Fatalf("wrong int %d, want %d", got, want) } case err := <-sub.Err(): - if err != errInts { + if !errors.Is(err, errInts) { t.Fatalf("wrong error: got %q, want %q", err, errInts) } if want != 2 { diff --git a/internal/build/archive.go b/internal/build/archive.go index 645921c690..7cca8e0d90 100644 --- a/internal/build/archive.go +++ b/internal/build/archive.go @@ -218,7 +218,7 @@ func extractTarball(ar io.Reader, dest string) error { // Move to the next file header. header, err := tr.Next() if err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { return nil } return err diff --git a/internal/build/util.go b/internal/build/util.go index aee8bf0fc8..2387b27f66 100644 --- a/internal/build/util.go +++ b/internal/build/util.go @@ -19,6 +19,7 @@ package build import ( "bufio" "bytes" + "errors" "flag" "fmt" "go/parser" @@ -97,7 +98,8 @@ func RunGit(args ...string) string { var stdout, stderr bytes.Buffer cmd.Stdout, cmd.Stderr = &stdout, &stderr if err := cmd.Run(); err != nil { - if e, ok := err.(*exec.Error); ok && e.Err == exec.ErrNotFound { + e := new(exec.Error) + if ok := errors.As(err, &e); ok && errors.Is(e.Err, exec.ErrNotFound) { if !warnedAboutGit { log.Println("Warning: can't find 'git' in PATH") warnedAboutGit = true diff --git a/internal/cmdtest/test_cmd.go b/internal/cmdtest/test_cmd.go index 4890d0b7c6..a38ab27003 100644 --- a/internal/cmdtest/test_cmd.go +++ b/internal/cmdtest/test_cmd.go @@ -19,6 +19,7 @@ package cmdtest import ( "bufio" "bytes" + "errors" "fmt" "io" "os" @@ -206,11 +207,10 @@ func (tt *TestCmd) Interrupt() { // It will only return a valid value after the process has finished. func (tt *TestCmd) ExitStatus() int { if tt.Err != nil { - exitErr := tt.Err.(*exec.ExitError) - if exitErr != nil { - if status, ok := exitErr.Sys().(syscall.WaitStatus); ok { - return status.ExitStatus() - } + exitErr := new(exec.ExitError) + _ = errors.As(tt.Err, &exitErr) + if status, ok := exitErr.Sys().(syscall.WaitStatus); ok { + return status.ExitStatus() } } return 0 diff --git a/internal/era/e2store/e2store.go b/internal/era/e2store/e2store.go index 8e4d5dd24a..e176c39b34 100644 --- a/internal/era/e2store/e2store.go +++ b/internal/era/e2store/e2store.go @@ -110,7 +110,7 @@ func (r *Reader) ReadAt(entry *Entry, off int64) (int, error) { n += headerSize // An entry with a non-zero length should not return EOF when // reading the value. - if err == io.EOF { + if errors.Is(err, io.EOF) { return n, io.ErrUnexpectedEOF } return n, err @@ -151,7 +151,7 @@ func (r *Reader) LengthAt(off int64) (int64, error) { func (r *Reader) ReadMetadataAt(off int64) (typ uint16, length uint32, err error) { b := make([]byte, headerSize) if n, err := r.r.ReadAt(b, off); err != nil { - if err == io.EOF && n > 0 { + if errors.Is(err, io.EOF) && n > 0 { return 0, 0, io.ErrUnexpectedEOF } return 0, 0, err @@ -177,7 +177,7 @@ func (r *Reader) Find(want uint16) (*Entry, error) { ) for { typ, length, err = r.ReadMetadataAt(off) - if err == io.EOF { + if errors.Is(err, io.EOF) { return nil, io.EOF } else if err != nil { return nil, err @@ -204,7 +204,7 @@ func (r *Reader) FindAll(want uint16) ([]*Entry, error) { ) for { typ, length, err = r.ReadMetadataAt(off) - if err == io.EOF { + if errors.Is(err, io.EOF) { return entries, nil } else if err != nil { return entries, err diff --git a/internal/era/iterator.go b/internal/era/iterator.go index f48aab46b4..f13a95d6a0 100644 --- a/internal/era/iterator.go +++ b/internal/era/iterator.go @@ -182,7 +182,7 @@ func (it *RawIterator) Number() uint64 { // Error returns the error status of the iterator. It should be called before // reading from any of the iterator's values. func (it *RawIterator) Error() error { - if it.err == io.EOF { + if errors.Is(it.err, io.EOF) { return nil } return it.err diff --git a/internal/jsre/pretty.go b/internal/jsre/pretty.go index bd772b4927..95a06b296a 100644 --- a/internal/jsre/pretty.go +++ b/internal/jsre/pretty.go @@ -17,6 +17,7 @@ package jsre import ( + "errors" "fmt" "io" "reflect" @@ -60,7 +61,8 @@ func prettyPrint(vm *goja.Runtime, value goja.Value, w io.Writer) { // prettyError writes err to standard output. func prettyError(vm *goja.Runtime, err error, w io.Writer) { failure := err.Error() - if gojaErr, ok := err.(*goja.Exception); ok { + gojaErr := new(goja.Exception) + if ok := errors.As(err, &gojaErr); ok { failure = gojaErr.String() } fmt.Fprint(w, ErrorColor("%s", failure)) diff --git a/metrics/disk_linux.go b/metrics/disk_linux.go index 8d610cd674..0dce7f4c46 100644 --- a/metrics/disk_linux.go +++ b/metrics/disk_linux.go @@ -20,6 +20,7 @@ package metrics import ( "bufio" + "errors" "fmt" "io" "os" @@ -42,7 +43,7 @@ func ReadDiskStats(stats *DiskStats) error { // Read the next line and split to key and value line, err := in.ReadString('\n') if err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { return nil } return err diff --git a/node/errors.go b/node/errors.go index 67547bf691..2d949c4011 100644 --- a/node/errors.go +++ b/node/errors.go @@ -33,7 +33,8 @@ var ( ) func convertFileLockError(err error) error { - if errno, ok := err.(syscall.Errno); ok && datadirInUseErrnos[uint(errno)] { + var errno syscall.Errno + if ok := errors.As(err, &errno); ok && datadirInUseErrnos[uint(errno)] { return ErrDatadirUsed } return err diff --git a/node/node_test.go b/node/node_test.go index 1552728d04..93291fc86a 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -56,7 +56,7 @@ func TestNodeCloseMultipleTimes(t *testing.T) { // Ensure that a stopped node can be stopped again for i := 0; i < 3; i++ { - if err := stack.Close(); err != ErrNodeStopped { + if err := stack.Close(); !errors.Is(err, ErrNodeStopped) { t.Fatalf("iter %d: stop failure mismatch: have %v, want %v", i, err, ErrNodeStopped) } } @@ -72,14 +72,14 @@ func TestNodeStartMultipleTimes(t *testing.T) { if err := stack.Start(); err != nil { t.Fatalf("failed to start node: %v", err) } - if err := stack.Start(); err != ErrNodeRunning { + if err := stack.Start(); !errors.Is(err, ErrNodeRunning) { t.Fatalf("start failure mismatch: have %v, want %v ", err, ErrNodeRunning) } // Ensure that a node can be stopped, but only once if err := stack.Close(); err != nil { t.Fatalf("failed to stop node: %v", err) } - if err := stack.Close(); err != ErrNodeStopped { + if err := stack.Close(); !errors.Is(err, ErrNodeStopped) { t.Fatalf("stop failure mismatch: have %v, want %v ", err, ErrNodeStopped) } } @@ -101,7 +101,7 @@ func TestNodeUsedDataDir(t *testing.T) { // Create a second node based on the same data directory and ensure failure _, err = New(&Config{DataDir: dir}) - if err != ErrDatadirUsed { + if !errors.Is(err, ErrDatadirUsed) { t.Fatalf("duplicate datadir failure mismatch: have %v, want %v", err, ErrDatadirUsed) } } @@ -297,7 +297,7 @@ func TestLifecycleStartupError(t *testing.T) { stack.RegisterLifecycle(failer) // Start the protocol stack and ensure all started services stop - if err := stack.Start(); err != failure { + if err := stack.Start(); !errors.Is(err, failure) { t.Fatalf("stack startup failure mismatch: have %v, want %v", err, failure) } for id := range lifecycles { @@ -361,15 +361,17 @@ func TestLifecycleTerminationGuarantee(t *testing.T) { } // Stop the stack, verify failure and check all terminations err = stack.Close() - if err, ok := err.(*StopError); !ok { + stopErr := new(StopError) + ok := errors.As(err, &stopErr) + if !ok { t.Fatalf("termination failure mismatch: have %v, want StopError", err) } else { failer := reflect.TypeOf(&InstrumentedService{}) - if err.Services[failer] != failure { - t.Fatalf("failer termination failure mismatch: have %v, want %v", err.Services[failer], failure) + if !errors.Is(stopErr.Services[failer], failure) { + t.Fatalf("failer termination failure mismatch: have %v, want %v", stopErr.Services[failer], failure) } - if len(err.Services) != 1 { - t.Fatalf("failure count mismatch: have %d, want %d", len(err.Services), 1) + if len(stopErr.Services) != 1 { + t.Fatalf("failure count mismatch: have %d, want %d", len(stopErr.Services), 1) } } for id := range lifecycles { diff --git a/node/rpcstack.go b/node/rpcstack.go index 6d3828ec2b..50720751ad 100644 --- a/node/rpcstack.go +++ b/node/rpcstack.go @@ -281,7 +281,7 @@ func (h *httpServer) doStop() { ctx, cancel := context.WithTimeout(context.Background(), shutdownTimeout) defer cancel() err := h.server.Shutdown(ctx) - if err != nil && err == ctx.Err() { + if err != nil && errors.Is(err, ctx.Err()) { h.log.Warn("HTTP server graceful shutdown timed out") h.server.Close() } diff --git a/p2p/dial.go b/p2p/dial.go index 225709427c..aff35524b3 100644 --- a/p2p/dial.go +++ b/p2p/dial.go @@ -626,7 +626,8 @@ func (t *dialTask) String() string { } func cleanupDialErr(err error) error { - if netErr, ok := err.(*net.OpError); ok && netErr.Op == "dial" { + netErr := new(net.OpError) + if ok := errors.As(err, &netErr); ok && netErr.Op == "dial" { return netErr.Err } return err diff --git a/p2p/discover/v4_udp_test.go b/p2p/discover/v4_udp_test.go index 1af31f4f1b..92146347b1 100644 --- a/p2p/discover/v4_udp_test.go +++ b/p2p/discover/v4_udp_test.go @@ -101,7 +101,7 @@ func (test *udpTest) packetInFrom(wantError error, key *ecdsa.PrivateKey, addr n test.t.Errorf("%s encode error: %v", data.Name(), err) } test.sent = append(test.sent, enc) - if err = test.udp.handlePacket(addr, enc); err != wantError { + if err = test.udp.handlePacket(addr, enc); !errors.Is(err, wantError) { test.t.Errorf("error mismatch: got %q, want %q", err, wantError) } } @@ -112,7 +112,7 @@ func (test *udpTest) waitPacketOut(validate interface{}) (closed bool) { test.t.Helper() dgram, err := test.pipe.receive() - if err == errClosed { + if errors.Is(err, errClosed) { return true } else if err != nil { test.t.Error("packet receive error:", err) @@ -151,7 +151,7 @@ func TestUDPv4_pingTimeout(t *testing.T) { key := newkey() toaddr := &net.UDPAddr{IP: net.ParseIP("1.2.3.4"), Port: 2222} node := enode.NewV4(&key.PublicKey, toaddr.IP, 0, toaddr.Port) - if _, err := test.udp.ping(node); err != errTimeout { + if _, err := test.udp.ping(node); !errors.Is(err, errTimeout) { t.Error("expected timeout error, got", err) } } @@ -211,7 +211,7 @@ func TestUDPv4_responseTimeouts(t *testing.T) { for i := 0; i < nReqs; i++ { select { case err := <-timeoutErr: - if err != errTimeout { + if !errors.Is(err, errTimeout) { t.Fatalf("got non-timeout error on timeoutErr %d: %v", i, err) } nTimeoutsRecv++ @@ -241,7 +241,7 @@ func TestUDPv4_findnodeTimeout(t *testing.T) { toid := enode.ID{1, 2, 3, 4} target := v4wire.Pubkey{4, 5, 6, 7} result, err := test.udp.findnode(toid, toaddr, target) - if err != errTimeout { + if !errors.Is(err, errTimeout) { t.Error("expected timeout error, got", err) } if len(result) > 0 { diff --git a/p2p/discover/v5_udp_test.go b/p2p/discover/v5_udp_test.go index 8631b918ff..e0f868fca6 100644 --- a/p2p/discover/v5_udp_test.go +++ b/p2p/discover/v5_udp_test.go @@ -20,6 +20,7 @@ import ( "bytes" "crypto/ecdsa" "encoding/binary" + "errors" "fmt" "math/rand" "net" @@ -241,7 +242,7 @@ func TestUDPv5_pingCall(t *testing.T) { done <- err }() test.waitPacketOut(func(p *v5wire.Ping, addr netip.AddrPort, _ v5wire.Nonce) {}) - if err := <-done; err != errTimeout { + if err := <-done; !errors.Is(err, errTimeout) { t.Fatalf("want errTimeout, got %q", err) } @@ -266,7 +267,7 @@ func TestUDPv5_pingCall(t *testing.T) { wrongAddr := netip.MustParseAddrPort("33.44.55.22:10101") test.packetInFrom(test.remotekey, wrongAddr, &v5wire.Pong{ReqID: p.ReqID}) }) - if err := <-done; err != errTimeout { + if err := <-done; !errors.Is(err, errTimeout) { t.Fatalf("want errTimeout for reply from wrong IP, got %q", err) } } @@ -379,7 +380,7 @@ func TestUDPv5_multipleHandshakeRounds(t *testing.T) { test.waitPacketOut(func(p *v5wire.Ping, addr netip.AddrPort, nonce v5wire.Nonce) { test.packetIn(&v5wire.Whoareyou{Nonce: nonce}) }) - if err := <-done; err != errTimeout { + if err := <-done; !errors.Is(err, errTimeout) { t.Fatalf("unexpected ping error: %q", err) } } @@ -488,7 +489,7 @@ func TestUDPv5_talkRequest(t *testing.T) { done <- err }() test.waitPacketOut(func(p *v5wire.TalkRequest, addr netip.AddrPort, _ v5wire.Nonce) {}) - if err := <-done; err != errTimeout { + if err := <-done; !errors.Is(err, errTimeout) { t.Fatalf("want errTimeout, got %q", err) } @@ -817,10 +818,10 @@ func (test *udpV5Test) waitPacketOut(validate interface{}) (closed bool) { exptype := fn.Type().In(0) dgram, err := test.pipe.receive() - if err == errClosed { + if errors.Is(err, errClosed) { return true } - if err == errTimeout { + if errors.Is(err, errTimeout) { test.t.Fatalf("timed out waiting for %v", exptype) return false } diff --git a/p2p/discover/v5wire/encoding.go b/p2p/discover/v5wire/encoding.go index 904a3ddec6..e35c0009f4 100644 --- a/p2p/discover/v5wire/encoding.go +++ b/p2p/discover/v5wire/encoding.go @@ -128,7 +128,7 @@ var ( // returns false, it is pretty certain that the packet causing the error does not belong // to discv5. func IsInvalidHeader(err error) bool { - return err == errTooShort || err == errInvalidHeader || err == errMsgTooShort + return errors.Is(err, errTooShort) || errors.Is(err, errInvalidHeader) || errors.Is(err, errMsgTooShort) } // Packet sizes. diff --git a/p2p/dnsdisc/client_test.go b/p2p/dnsdisc/client_test.go index 01912e1eab..c6cc917888 100644 --- a/p2p/dnsdisc/client_test.go +++ b/p2p/dnsdisc/client_test.go @@ -95,7 +95,7 @@ func TestClientSyncTreeBadNode(t *testing.T) { c := NewClient(Config{Resolver: r, Logger: testlog.Logger(t, log.LvlTrace)}) _, err := c.SyncTree("enrtree://AKPYQIUQIL7PSIACI32J7FGZW56E5FKHEFCCOFHILBIMW3M6LWXS2@n") wantErr := nameError{name: "INDMVBZEEQ4ESVYAKGIYU74EAA.n", err: entryError{typ: "enr", err: errInvalidENR}} - if err != wantErr { + if !errors.Is(err, wantErr) { t.Fatalf("expected sync error %q, got %q", wantErr, err) } } diff --git a/p2p/dnsdisc/error.go b/p2p/dnsdisc/error.go index 39955cabff..bbeb9877ad 100644 --- a/p2p/dnsdisc/error.go +++ b/p2p/dnsdisc/error.go @@ -47,7 +47,8 @@ type nameError struct { } func (err nameError) Error() string { - if ee, ok := err.err.(entryError); ok { + ee := new(entryError) + if ok := errors.As(err.err, &ee); ok { return fmt.Sprintf("invalid %s entry at %s: %v", ee.typ, err.name, ee.err) } return err.name + ": " + err.err.Error() diff --git a/p2p/dnsdisc/tree_test.go b/p2p/dnsdisc/tree_test.go index 9ed17aa4b3..b47198a07a 100644 --- a/p2p/dnsdisc/tree_test.go +++ b/p2p/dnsdisc/tree_test.go @@ -17,6 +17,7 @@ package dnsdisc import ( + "errors" "reflect" "testing" @@ -54,7 +55,7 @@ func TestParseRoot(t *testing.T) { if !reflect.DeepEqual(e, test.e) { t.Errorf("test %d: wrong entry %s, want %s", i, spew.Sdump(e), spew.Sdump(test.e)) } - if err != test.err { + if !errors.Is(err, test.err) { t.Errorf("test %d: wrong error %q, want %q", i, err, test.err) } } @@ -131,7 +132,7 @@ func TestParseEntry(t *testing.T) { if !reflect.DeepEqual(e, test.e) { t.Errorf("test %d: wrong entry %s, want %s", i, spew.Sdump(e), spew.Sdump(test.e)) } - if err != test.err { + if !errors.Is(err, test.err) { t.Errorf("test %d: wrong error %q, want %q", i, err, test.err) } } diff --git a/p2p/enode/nodedb.go b/p2p/enode/nodedb.go index 51e554e68a..9742cb9fb9 100644 --- a/p2p/enode/nodedb.go +++ b/p2p/enode/nodedb.go @@ -20,6 +20,7 @@ import ( "bytes" "crypto/rand" "encoding/binary" + stderrors "errors" "fmt" "net/netip" "os" @@ -99,7 +100,8 @@ func newMemoryDB() (*DB, error) { func newPersistentDB(path string) (*DB, error) { opts := &opt.Options{OpenFilesCacheCapacity: 5} db, err := leveldb.OpenFile(path, opts) - if _, iscorrupted := err.(*errors.ErrCorrupted); iscorrupted { + errCorrupted := new(*errors.ErrCorrupted) + if iscorrupted := stderrors.As(err, errCorrupted); iscorrupted { db, err = leveldb.RecoverFile(path, nil) } if err != nil { @@ -111,15 +113,15 @@ func newPersistentDB(path string) (*DB, error) { currentVer = currentVer[:binary.PutVarint(currentVer, int64(dbVersion))] blob, err := db.Get([]byte(dbVersionKey), nil) - switch err { - case leveldb.ErrNotFound: + switch { + case stderrors.Is(err, leveldb.ErrNotFound): // Version not found (i.e. empty cache), insert it if err := db.Put([]byte(dbVersionKey), currentVer, nil); err != nil { db.Close() return nil, err } - case nil: + case err == nil: // Version present, flush if different if !bytes.Equal(blob, currentVer) { db.Close() diff --git a/p2p/enr/enr.go b/p2p/enr/enr.go index 2b093b2f1a..5bfbf69ad2 100644 --- a/p2p/enr/enr.go +++ b/p2p/enr/enr.go @@ -228,13 +228,13 @@ func decodeRecord(s *rlp.Stream) (dec Record, raw []byte, err error) { return dec, raw, err } if err = s.Decode(&dec.signature); err != nil { - if err == rlp.EOL { + if errors.Is(err, rlp.EOL) { err = errIncompleteList } return dec, raw, err } if err = s.Decode(&dec.seq); err != nil { - if err == rlp.EOL { + if errors.Is(err, rlp.EOL) { err = errIncompleteList } return dec, raw, err @@ -244,13 +244,13 @@ func decodeRecord(s *rlp.Stream) (dec Record, raw []byte, err error) { for i := 0; ; i++ { var kv pair if err := s.Decode(&kv.k); err != nil { - if err == rlp.EOL { + if errors.Is(err, rlp.EOL) { break } return dec, raw, err } if err := s.Decode(&kv.v); err != nil { - if err == rlp.EOL { + if errors.Is(err, rlp.EOL) { return dec, raw, errIncompletePair } return dec, raw, err diff --git a/p2p/enr/enr_test.go b/p2p/enr/enr_test.go index 4fccb0cce9..3fa2c5e9f5 100644 --- a/p2p/enr/enr_test.go +++ b/p2p/enr/enr_test.go @@ -19,6 +19,7 @@ package enr import ( "bytes" "encoding/binary" + "errors" "fmt" "math/rand" "testing" @@ -97,7 +98,8 @@ func TestLoadErrors(t *testing.T) { // Check error for invalid keys. var list []uint err = r.Load(WithEntry(ip4.ENRKey(), &list)) - kerr, ok := err.(*KeyError) + kerr := new(KeyError) + ok := errors.As(err, &kerr) if !ok { t.Fatalf("expected KeyError, got %T", err) } @@ -149,7 +151,7 @@ func TestSortedGetAndSet(t *testing.T) { func TestDirty(t *testing.T) { var r Record - if _, err := rlp.EncodeToBytes(r); err != errEncodeUnsigned { + if _, err := rlp.EncodeToBytes(r); !errors.Is(err, errEncodeUnsigned) { t.Errorf("expected errEncodeUnsigned, got %#v", err) } @@ -164,7 +166,7 @@ func TestDirty(t *testing.T) { if len(r.signature) != 0 { t.Error("signature still set after modification") } - if _, err := rlp.EncodeToBytes(r); err != errEncodeUnsigned { + if _, err := rlp.EncodeToBytes(r); !errors.Is(err, errEncodeUnsigned) { t.Errorf("expected errEncodeUnsigned, got %#v", err) } } @@ -248,7 +250,7 @@ func TestRecordTooBig(t *testing.T) { // set a big value for random key, expect error r.Set(WithEntry(key, randomString(SizeLimit))) - if err := signTest([]byte{5}, &r); err != errTooBig { + if err := signTest([]byte{5}, &r); !errors.Is(err, errTooBig) { t.Fatalf("expected to get errTooBig, got %#v", err) } @@ -274,7 +276,7 @@ func TestDecodeIncomplete(t *testing.T) { for _, test := range tests { var r Record err := rlp.DecodeBytes(test.input, &r) - if err != test.err { + if !errors.Is(err, test.err) { t.Errorf("wrong error for %X: %v", test.input, err) } } diff --git a/p2p/enr/entries.go b/p2p/enr/entries.go index 58e660c154..f160305522 100644 --- a/p2p/enr/entries.go +++ b/p2p/enr/entries.go @@ -240,7 +240,7 @@ type KeyError struct { // Error implements error. func (err *KeyError) Error() string { - if err.Err == errNotFound { + if errors.Is(err.Err, errNotFound) { return fmt.Sprintf("missing ENR key %q", err.Key) } return fmt.Sprintf("ENR key %q: %v", err.Key, err.Err) @@ -255,7 +255,7 @@ func (err *KeyError) Unwrap() error { func IsNotFound(err error) bool { var ke *KeyError if errors.As(err, &ke) { - return ke.Err == errNotFound + return errors.Is(ke.Err, errNotFound) } return false } diff --git a/p2p/message_test.go b/p2p/message_test.go index e575c5d96e..292c23071d 100644 --- a/p2p/message_test.go +++ b/p2p/message_test.go @@ -18,6 +18,7 @@ package p2p import ( "bytes" + "errors" "fmt" "io" "runtime" @@ -55,7 +56,7 @@ loop: go func() { if err := SendItems(rw1, 1); err == nil { t.Error("EncodeMsg returned nil error") - } else if err != ErrPipeClosed { + } else if !errors.Is(err, ErrPipeClosed) { t.Errorf("EncodeMsg returned wrong error: got %v, want %v", err, ErrPipeClosed) } close(done) @@ -91,7 +92,7 @@ func TestEOFSignal(t *testing.T) { // empty reader eof := make(chan struct{}, 1) sig := &eofSignal{new(bytes.Buffer), 0, eof} - if n, err := sig.Read(rb); n != 0 || err != io.EOF { + if n, err := sig.Read(rb); n != 0 || !errors.Is(err, io.EOF) { t.Errorf("Read returned unexpected values: (%v, %v)", n, err) } select { @@ -118,7 +119,7 @@ func TestEOFSignal(t *testing.T) { if n, err := sig.Read(rb); n != 4 || err != nil { t.Errorf("Read returned unexpected values: (%v, %v)", n, err) } - if n, err := sig.Read(rb); n != 0 || err != io.EOF { + if n, err := sig.Read(rb); n != 0 || !errors.Is(err, io.EOF) { t.Errorf("Read returned unexpected values: (%v, %v)", n, err) } select { diff --git a/p2p/metrics.go b/p2p/metrics.go index 1fd0f26db3..5609ccc886 100644 --- a/p2p/metrics.go +++ b/p2p/metrics.go @@ -70,20 +70,20 @@ func markDialError(err error) { if err2 := errors.Unwrap(err); err2 != nil { err = err2 } - switch err { - case DiscTooManyPeers: + switch { + case errors.Is(err, DiscTooManyPeers): dialTooManyPeers.Mark(1) - case DiscAlreadyConnected: + case errors.Is(err, DiscAlreadyConnected): dialAlreadyConnected.Mark(1) - case DiscSelf: + case errors.Is(err, DiscSelf): dialSelf.Mark(1) - case DiscUselessPeer: + case errors.Is(err, DiscUselessPeer): dialUselessPeer.Mark(1) - case DiscUnexpectedIdentity: + case errors.Is(err, DiscUnexpectedIdentity): dialUnexpectedIdentity.Mark(1) - case errEncHandshakeError: + case errors.Is(err, errEncHandshakeError): dialEncHandshakeError.Mark(1) - case errProtoHandshakeError: + case errors.Is(err, errProtoHandshakeError): dialProtoHandshakeError.Mark(1) } } diff --git a/p2p/netutil/error.go b/p2p/netutil/error.go index 5d3d9bfd65..a8e3b50aaf 100644 --- a/p2p/netutil/error.go +++ b/p2p/netutil/error.go @@ -16,18 +16,22 @@ package netutil +import "errors" + // IsTemporaryError checks whether the given error should be considered temporary. func IsTemporaryError(err error) bool { - tempErr, ok := err.(interface { + var tempErr interface { Temporary() bool - }) + } + ok := errors.As(err, &tempErr) return ok && tempErr.Temporary() || isPacketTooBig(err) } // IsTimeout checks whether the given error is a timeout. func IsTimeout(err error) bool { - timeoutErr, ok := err.(interface { + var timeoutErr interface { Timeout() bool - }) + } + ok := errors.As(err, &timeoutErr) return ok && timeoutErr.Timeout() } diff --git a/p2p/netutil/error_test.go b/p2p/netutil/error_test.go index 84d5c2c206..fc5074fa6d 100644 --- a/p2p/netutil/error_test.go +++ b/p2p/netutil/error_test.go @@ -17,6 +17,7 @@ package netutil import ( + "errors" "net" "testing" "time" @@ -52,7 +53,8 @@ func TestIsPacketTooBig(t *testing.T) { listener.SetDeadline(time.Now().Add(1 * time.Second)) n, _, err := listener.ReadFrom(buf) if err != nil { - if nerr, ok := err.(net.Error); ok && nerr.Timeout() { + var nerr net.Error + if ok := errors.As(err, &nerr); ok && nerr.Timeout() { continue } if !isPacketTooBig(err) { diff --git a/p2p/netutil/net_test.go b/p2p/netutil/net_test.go index 569c7ac454..ccc57c28a9 100644 --- a/p2p/netutil/net_test.go +++ b/p2p/netutil/net_test.go @@ -17,6 +17,7 @@ package netutil import ( + "errors" "fmt" "math/rand" "net" @@ -178,7 +179,7 @@ func TestCheckRelayIP(t *testing.T) { for _, test := range tests { err := CheckRelayIP(parseIP(test.sender), parseIP(test.addr)) - if err != test.want { + if !errors.Is(err, test.want) { t.Errorf("%s from %s: got %q, want %q", test.addr, test.sender, err, test.want) } } diff --git a/p2p/netutil/toobig_windows.go b/p2p/netutil/toobig_windows.go index 652903e83c..d9ba2ae63e 100644 --- a/p2p/netutil/toobig_windows.go +++ b/p2p/netutil/toobig_windows.go @@ -20,6 +20,7 @@ package netutil import ( + "errors" "net" "os" "syscall" @@ -31,8 +32,10 @@ const _WSAEMSGSIZE = syscall.Errno(10040) // fit the receive buffer. On Windows, WSARecvFrom returns // code WSAEMSGSIZE and no data if this happens. func isPacketTooBig(err error) bool { - if opErr, ok := err.(*net.OpError); ok { - if scErr, ok := opErr.Err.(*os.SyscallError); ok { + opErr := new(net.OpError) + if ok := errors.As(err, &opErr); ok { + scErr := new(os.SyscallError) + if ok := errors.As(opErr.Err, &scErr); ok { return scErr.Err == _WSAEMSGSIZE } return opErr.Err == _WSAEMSGSIZE diff --git a/p2p/peer.go b/p2p/peer.go index a01df63d0c..727e2ca57d 100644 --- a/p2p/peer.go +++ b/p2p/peer.go @@ -272,7 +272,8 @@ loop: } writeStart <- struct{}{} case err = <-readErr: - if r, ok := err.(DiscReason); ok { + var r DiscReason + if ok := errors.As(err, &r); ok { remoteRequested = true reason = r } else { diff --git a/p2p/peer_error.go b/p2p/peer_error.go index dcdadf7fe3..137bd71c23 100644 --- a/p2p/peer_error.go +++ b/p2p/peer_error.go @@ -103,13 +103,15 @@ func (d DiscReason) Error() string { } func discReasonForError(err error) DiscReason { - if reason, ok := err.(DiscReason); ok { + var reason DiscReason + if ok := errors.As(err, &reason); ok { return reason } if errors.Is(err, errProtocolReturned) { return DiscQuitting } - peerError, ok := err.(*peerError) + peerError := new(peerError) + ok := errors.As(err, &peerError) if ok { switch peerError.code { case errInvalidMsgCode, errInvalidMsg: diff --git a/p2p/peer_test.go b/p2p/peer_test.go index dea72875fe..d8fbd344ff 100644 --- a/p2p/peer_test.go +++ b/p2p/peer_test.go @@ -138,7 +138,7 @@ func TestPeerProtoReadMsg(t *testing.T) { select { case err := <-errc: - if err != errProtocolReturned { + if !errors.Is(err, errProtocolReturned) { t.Errorf("peer returned error: %v", err) } case <-time.After(2 * time.Second): @@ -190,7 +190,7 @@ func TestPeerDisconnect(t *testing.T) { } select { case reason := <-disc: - if reason != DiscQuitting { + if !errors.Is(reason, DiscQuitting) { t.Errorf("run returned wrong reason: got %v, want %v", reason, DiscQuitting) } case <-time.After(500 * time.Millisecond): diff --git a/p2p/server_test.go b/p2p/server_test.go index a0491e984a..45b7c79ca1 100644 --- a/p2p/server_test.go +++ b/p2p/server_test.go @@ -280,7 +280,7 @@ func TestServerAtCap(t *testing.T) { // Try inserting a non-trusted connection. anotherID := randomID() c := newconn(anotherID) - if err := srv.checkpoint(c, srv.checkpointPostHandshake); err != DiscTooManyPeers { + if err := srv.checkpoint(c, srv.checkpointPostHandshake); !errors.Is(err, DiscTooManyPeers) { t.Error("wrong error for insert:", err) } // Try inserting a trusted connection. @@ -295,7 +295,7 @@ func TestServerAtCap(t *testing.T) { // Remove from trusted set and try again srv.RemoveTrustedPeer(newNode(trustedID, "")) c = newconn(trustedID) - if err := srv.checkpoint(c, srv.checkpointPostHandshake); err != DiscTooManyPeers { + if err := srv.checkpoint(c, srv.checkpointPostHandshake); !errors.Is(err, DiscTooManyPeers) { t.Error("wrong error for insert:", err) } @@ -345,7 +345,7 @@ func TestServerPeerLimits(t *testing.T) { dialDest := clientnode conn, _ := net.Pipe() srv.SetupConn(conn, flags, dialDest) - if tp.closeErr != DiscTooManyPeers { + if !errors.Is(tp.closeErr, DiscTooManyPeers) { t.Errorf("unexpected close error: %q", tp.closeErr) } conn.Close() @@ -355,11 +355,11 @@ func TestServerPeerLimits(t *testing.T) { // Check that server allows a trusted peer despite being full. conn, _ = net.Pipe() srv.SetupConn(conn, flags, dialDest) - if tp.closeErr == DiscTooManyPeers { + if errors.Is(tp.closeErr, DiscTooManyPeers) { t.Errorf("failed to bypass MaxPeers with trusted node: %q", tp.closeErr) } - if tp.closeErr != DiscUselessPeer { + if !errors.Is(tp.closeErr, DiscUselessPeer) { t.Errorf("unexpected close error: %q", tp.closeErr) } conn.Close() @@ -369,7 +369,7 @@ func TestServerPeerLimits(t *testing.T) { // Check that server is full again. conn, _ = net.Pipe() srv.SetupConn(conn, flags, dialDest) - if tp.closeErr != DiscTooManyPeers { + if !errors.Is(tp.closeErr, DiscTooManyPeers) { t.Errorf("unexpected close error: %q", tp.closeErr) } conn.Close() @@ -564,7 +564,7 @@ func TestServerInboundThrottle(t *testing.T) { go func() { conn.SetDeadline(time.Now().Add(timeout)) buf := make([]byte, 10) - if n, err := conn.Read(buf); err != io.EOF || n != 0 { + if n, err := conn.Read(buf); !errors.Is(err, io.EOF) || n != 0 { t.Errorf("expected io.EOF and n == 0, got error %q and n == %d", err, n) } connClosed <- struct{}{} diff --git a/p2p/transport.go b/p2p/transport.go index 87d3013f11..cabf3a5c4f 100644 --- a/p2p/transport.go +++ b/p2p/transport.go @@ -113,7 +113,8 @@ func (t *rlpxTransport) close(err error) { // Tell the remote end why we're disconnecting if possible. // We only bother doing this if the underlying connection supports // setting a timeout tough. - if reason, ok := err.(DiscReason); ok && reason != DiscNetworkError { + var reason DiscReason + if ok := errors.As(err, &reason); ok && reason != DiscNetworkError { // We do not use the WriteMsg func since we want a custom deadline deadline := time.Now().Add(discWriteTimeout) if err := t.conn.SetWriteDeadline(deadline); err == nil { diff --git a/rlp/decode.go b/rlp/decode.go index 0fbca243ee..9a0b5d5348 100644 --- a/rlp/decode.go +++ b/rlp/decode.go @@ -123,25 +123,26 @@ func (err *decodeError) Error() string { } func wrapStreamError(err error, typ reflect.Type) error { - switch err { - case ErrCanonInt: + switch { + case errors.Is(err, ErrCanonInt): return &decodeError{msg: "non-canonical integer (leading zero bytes)", typ: typ} - case ErrCanonSize: + case errors.Is(err, ErrCanonSize): return &decodeError{msg: "non-canonical size information", typ: typ} - case ErrExpectedList: + case errors.Is(err, ErrExpectedList): return &decodeError{msg: "expected input list", typ: typ} - case ErrExpectedString: + case errors.Is(err, ErrExpectedString): return &decodeError{msg: "expected input string or byte", typ: typ} - case errUintOverflow: + case errors.Is(err, errUintOverflow): return &decodeError{msg: "input string too long", typ: typ} - case errNotAtEOL: + case errors.Is(err, errNotAtEOL): return &decodeError{msg: "input list has too many elements", typ: typ} } return err } func addErrorContext(err error, ctx string) error { - if decErr, ok := err.(*decodeError); ok { + decErr := new(decodeError) + if ok := errors.As(err, &decErr); ok { decErr.ctx = append(decErr.ctx, ctx) } return err @@ -326,7 +327,7 @@ func decodeSliceElems(s *Stream, val reflect.Value, elemdec decoder) error { val.SetLen(i + 1) } // decode into element - if err := elemdec(s, val.Index(i)); err == EOL { + if err := elemdec(s, val.Index(i)); errors.Is(err, EOL) { break } else if err != nil { return addErrorContext(err, fmt.Sprint("[", i, "]")) @@ -345,7 +346,7 @@ func decodeListArray(s *Stream, val reflect.Value, elemdec decoder) error { vlen := val.Len() i := 0 for ; i < vlen; i++ { - if err := elemdec(s, val.Index(i)); err == EOL { + if err := elemdec(s, val.Index(i)); errors.Is(err, EOL) { break } else if err != nil { return addErrorContext(err, fmt.Sprint("[", i, "]")) @@ -417,7 +418,7 @@ func makeStructDecoder(typ reflect.Type) (decoder, error) { } for i, f := range fields { err := f.info.decoder(s, val.Field(f.index)) - if err == EOL { + if errors.Is(err, EOL) { if f.optional { // The field is optional, so reaching the end of the list before // reaching the last field is acceptable. All remaining undecoded @@ -757,7 +758,7 @@ func (s *Stream) uint(maxbits int) (uint64, error) { } v, err := s.readUint(byte(size)) switch { - case err == ErrCanonSize: + case errors.Is(err, ErrCanonSize): // Adjust error because we're not reading a size right now. return 0, ErrCanonInt case err != nil: @@ -948,7 +949,8 @@ func (s *Stream) Decode(val interface{}) error { } err = decoder(s, rval.Elem()) - if decErr, ok := err.(*decodeError); ok && len(decErr.ctx) > 0 { + decErr := new(decodeError) + if ok := errors.As(err, &decErr); ok && len(decErr.ctx) > 0 { // Add decode target type to error so context has more meaning. decErr.ctx = append(decErr.ctx, fmt.Sprint("(", rtyp.Elem(), ")")) } @@ -1041,10 +1043,10 @@ func (s *Stream) readKind() (kind Kind, size uint64, err error) { if len(s.stack) == 0 { // At toplevel, Adjust the error to actual EOF. io.EOF is // used by callers to determine when to stop decoding. - switch err { - case io.ErrUnexpectedEOF: + switch { + case errors.Is(err, io.ErrUnexpectedEOF): err = io.EOF - case ErrValueTooLarge: + case errors.Is(err, ErrValueTooLarge): err = io.EOF } } @@ -1129,7 +1131,7 @@ func (s *Stream) readFull(buf []byte) (err error) { nn, err = s.r.Read(buf[n:]) n += nn } - if err == io.EOF { + if errors.Is(err, io.EOF) { if n < len(buf) { err = io.ErrUnexpectedEOF } else { @@ -1147,7 +1149,7 @@ func (s *Stream) readByte() (byte, error) { return 0, err } b, err := s.r.ReadByte() - if err == io.EOF { + if errors.Is(err, io.EOF) { err = io.ErrUnexpectedEOF } return b, err diff --git a/rlp/decode_test.go b/rlp/decode_test.go index 3e492188e8..3e0d91db0f 100644 --- a/rlp/decode_test.go +++ b/rlp/decode_test.go @@ -251,7 +251,7 @@ func TestStreamList(t *testing.T) { } } - if _, err := s.Uint(); err != EOL { + if _, err := s.Uint(); !errors.Is(err, EOL) { t.Errorf("Uint error mismatch, got %v, want %v", err, EOL) } if err = s.ListEnd(); err != nil { @@ -331,16 +331,16 @@ func TestStreamReadBytes(t *testing.T) { func TestDecodeErrors(t *testing.T) { r := bytes.NewReader(nil) - if err := Decode(r, nil); err != errDecodeIntoNil { + if err := Decode(r, nil); !errors.Is(err, errDecodeIntoNil) { t.Errorf("Decode(r, nil) error mismatch, got %q, want %q", err, errDecodeIntoNil) } var nilptr *struct{} - if err := Decode(r, nilptr); err != errDecodeIntoNil { + if err := Decode(r, nilptr); !errors.Is(err, errDecodeIntoNil) { t.Errorf("Decode(r, nilptr) error mismatch, got %q, want %q", err, errDecodeIntoNil) } - if err := Decode(r, struct{}{}); err != errNoPointer { + if err := Decode(r, struct{}{}); !errors.Is(err, errNoPointer) { t.Errorf("Decode(r, struct{}{}) error mismatch, got %q, want %q", err, errNoPointer) } @@ -349,7 +349,7 @@ func TestDecodeErrors(t *testing.T) { t.Errorf("Decode(r, new(chan bool)) error mismatch, got %q, want %q", err, expectErr) } - if err := Decode(r, new(uint)); err != io.EOF { + if err := Decode(r, new(uint)); !errors.Is(err, io.EOF) { t.Errorf("Decode(r, new(int)) error mismatch, got %q, want %q", err, io.EOF) } } diff --git a/rlp/encode_test.go b/rlp/encode_test.go index 314958eb56..8a6bf266ee 100644 --- a/rlp/encode_test.go +++ b/rlp/encode_test.go @@ -476,7 +476,7 @@ func TestEncodeToReaderPiecewise(t *testing.T) { } n, err := r.Read(output[start:end]) end = start + n - if err == io.EOF { + if errors.Is(err, io.EOF) { break } else if err != nil { return nil, err diff --git a/rlp/raw_test.go b/rlp/raw_test.go index 7b3255eca3..9e804060a8 100644 --- a/rlp/raw_test.go +++ b/rlp/raw_test.go @@ -129,7 +129,7 @@ func TestSplitUint64(t *testing.T) { if !bytes.Equal(rest, unhex(test.rest)) { t.Errorf("test %d: rest mismatch: got %x, want %s (input %q)", i, rest, test.rest, test.input) } - if err != test.err { + if !errors.Is(err, test.err) { t.Errorf("test %d: error mismatch: got %q, want %q", i, err, test.err) } } @@ -213,7 +213,7 @@ func TestSplit(t *testing.T) { if !bytes.Equal(rest, unhex(test.rest)) { t.Errorf("test %d: rest mismatch: got %x, want %s", i, rest, test.rest) } - if err != test.err { + if !errors.Is(err, test.err) { t.Errorf("test %d: error mismatch: got %q, want %q", i, err, test.err) } } @@ -251,7 +251,7 @@ func TestReadSize(t *testing.T) { for _, test := range tests { size, err := readSize(unhex(test.input), test.slen) - if err != test.err { + if !errors.Is(err, test.err) { t.Errorf("readSize(%s, %d): error mismatch: got %q, want %q", test.input, test.slen, err, test.err) continue } diff --git a/rlp/typecache.go b/rlp/typecache.go index eebf4cd611..dff741cd6c 100644 --- a/rlp/typecache.go +++ b/rlp/typecache.go @@ -17,6 +17,7 @@ package rlp import ( + "errors" "fmt" "maps" "reflect" @@ -140,7 +141,8 @@ func structFields(typ reflect.Type) (fields []field, err error) { // Filter/validate fields. structFields, structTags, err := rlpstruct.ProcessFields(allStructFields) if err != nil { - if tagErr, ok := err.(rlpstruct.TagError); ok { + tagErr := new(rlpstruct.TagError) + if ok := errors.As(err, &tagErr); ok { tagErr.StructType = typ.String() return nil, tagErr } diff --git a/rpc/client.go b/rpc/client.go index f9a8f1116b..c706a6019a 100644 --- a/rpc/client.go +++ b/rpc/client.go @@ -713,7 +713,8 @@ func (c *Client) drainRead() { func (c *Client) read(codec ServerCodec) { for { msgs, batch, err := codec.readBatch() - if _, ok := err.(*json.SyntaxError); ok { + jsonErr := new(json.SyntaxError) + if ok := errors.As(err, &jsonErr); ok { msg := errorMessage(&parseError{err.Error()}) codec.writeJSON(context.Background(), msg, true) } diff --git a/rpc/client_test.go b/rpc/client_test.go index 6c1a4f8f6c..f92eb6dc55 100644 --- a/rpc/client_test.go +++ b/rpc/client_test.go @@ -114,17 +114,19 @@ func TestClientErrorData(t *testing.T) { // The method handler returns an error value which implements the rpc.Error // interface, i.e. it has a custom error code. The server returns this error code. expectedCode := testError{}.ErrorCode() - if e, ok := err.(Error); !ok { + var e Error + if ok := errors.As(err, &e); !ok { t.Fatalf("client did not return rpc.Error, got %#v", e) } else if e.ErrorCode() != expectedCode { t.Fatalf("wrong error code %d, want %d", e.ErrorCode(), expectedCode) } // Check data. - if e, ok := err.(DataError); !ok { - t.Fatalf("client did not return rpc.DataError, got %#v", e) - } else if e.ErrorData() != (testError{}.ErrorData()) { - t.Fatalf("wrong error data %#v, want %#v", e.ErrorData(), testError{}.ErrorData()) + var dataErr DataError + if ok := errors.As(err, &dataErr); !ok { + t.Fatalf("client did not return rpc.DataError, got %#v", dataErr) + } else if dataErr.ErrorData() != (testError{}.ErrorData()) { + t.Fatalf("wrong error data %#v, want %#v", dataErr.ErrorData(), testError{}.ErrorData()) } } @@ -225,7 +227,7 @@ func TestClientBatchRequest_len(t *testing.T) { } } for i, elem := range batch[2:] { - if elem.Error != ErrMissingBatchResponse { + if !errors.Is(elem.Error, ErrMissingBatchResponse) { t.Errorf("wrong error %q for batch element %d", elem.Error, i+2) } } @@ -255,7 +257,7 @@ func TestClientBatchRequest_len(t *testing.T) { } } for i, elem := range batch[1:] { - if elem.Error != ErrMissingBatchResponse { + if !errors.Is(elem.Error, ErrMissingBatchResponse) { t.Errorf("wrong error %q for batch element %d", elem.Error, i+2) } } @@ -296,7 +298,7 @@ func TestClientBatchRequestLimit(t *testing.T) { // Check that remaining response batch elements are reported as absent. for i, elem := range batch[1:] { - if elem.Error != ErrMissingBatchResponse { + if !errors.Is(elem.Error, ErrMissingBatchResponse) { t.Fatalf("batch elem %d has unexpected error: %v", i+1, elem.Error) } } @@ -732,7 +734,7 @@ func TestClientNotificationStorm(t *testing.T) { t.Fatalf("(%d/%d) unexpected value %d", i, count, val) } case err := <-sub.Err(): - if wantError && err != ErrSubscriptionQueueOverflow { + if wantError && !errors.Is(err, ErrSubscriptionQueueOverflow) { t.Fatalf("(%d/%d) got error %q, want %q", i, count, err, ErrSubscriptionQueueOverflow) } else if !wantError { t.Fatalf("(%d/%d) got unexpected error %q", i, count, err) diff --git a/rpc/http_test.go b/rpc/http_test.go index 6c268b6292..d3c94cca70 100644 --- a/rpc/http_test.go +++ b/rpc/http_test.go @@ -18,6 +18,7 @@ package rpc import ( "context" + "errors" "fmt" "net/http" "net/http/httptest" @@ -164,7 +165,8 @@ func TestHTTPErrorResponse(t *testing.T) { t.Fatal("error was expected") } - httpErr, ok := err.(HTTPError) + var httpErr HTTPError + ok := errors.As(err, &httpErr) if !ok { t.Fatalf("unexpected error type %T", err) } @@ -254,12 +256,12 @@ func TestNewContextWithHeaders(t *testing.T) { ctx3 := NewContextWithHeaders(ctx2, newHdr("key-2", "val-2")) expectedHeaders = 3 - if err := client.CallContext(ctx3, nil, "test"); err != ErrNoResult { + if err := client.CallContext(ctx3, nil, "test"); !errors.Is(err, ErrNoResult) { t.Error("call failed", err) } expectedHeaders = 2 - if err := client.CallContext(ctx2, nil, "test"); err != ErrNoResult { + if err := client.CallContext(ctx2, nil, "test"); !errors.Is(err, ErrNoResult) { t.Error("call failed:", err) } } diff --git a/rpc/json.go b/rpc/json.go index e932389d17..dd6f04f22a 100644 --- a/rpc/json.go +++ b/rpc/json.go @@ -125,12 +125,12 @@ func errorMessage(err error) *jsonrpcMessage { Code: errcodeDefault, Message: err.Error(), }} - ec, ok := err.(Error) - if ok { + var ec Error + if errors.As(err, &ec) { msg.Error.Code = ec.ErrorCode() } - de, ok := err.(DataError) - if ok { + var de DataError + if errors.As(err, &de) { msg.Error.Data = de.ErrorData() } return msg @@ -311,7 +311,7 @@ func parsePositionalArguments(rawArgs json.RawMessage, types []reflect.Type) ([] var args []reflect.Value tok, err := dec.Token() switch { - case err == io.EOF || tok == nil && err == nil: + case errors.Is(err, io.EOF) || tok == nil && err == nil: // "params" is optional and may be empty. Also allow "params":null even though it's // not in the spec because our own client used to send it. case err != nil: diff --git a/rpc/server.go b/rpc/server.go index 42b59f8f6f..5460afc2e0 100644 --- a/rpc/server.go +++ b/rpc/server.go @@ -174,7 +174,7 @@ func messageForReadError(err error) string { } else { return "read error" } - } else if err != io.EOF { + } else if !errors.Is(err, io.EOF) { return "parse error" } return "" diff --git a/rpc/server_test.go b/rpc/server_test.go index 9ee545d81a..e8b03648f2 100644 --- a/rpc/server_test.go +++ b/rpc/server_test.go @@ -19,6 +19,7 @@ package rpc import ( "bufio" "bytes" + "errors" "io" "net" "os" @@ -192,7 +193,8 @@ func TestServerBatchResponseSizeLimit(t *testing.T) { continue } // After two, we expect an error. - re, ok := batch[i].Error.(Error) + var re Error + ok := errors.As(batch[i].Error, &re) if !ok { t.Fatalf("batch elem %d has wrong error: %v", i, batch[i].Error) } diff --git a/rpc/subscription.go b/rpc/subscription.go index 9e400c8b60..5fa7244167 100644 --- a/rpc/subscription.go +++ b/rpc/subscription.go @@ -304,7 +304,7 @@ func (sub *ClientSubscription) run() { // Send the error. if err != nil { - if err == ErrClientQuit { + if errors.Is(err, ErrClientQuit) { // ErrClientQuit gets here when Client.Close is called. This is reported as a // nil error because it's not an error, but we can't close sub.err here. err = nil @@ -340,7 +340,7 @@ func (sub *ClientSubscription) forward() (unsubscribeServer bool, err error) { if !recv.IsNil() { err = recv.Interface().(error) } - if err == errUnsubscribed { + if errors.Is(err, errUnsubscribed) { // Exiting because Unsubscribe was called, unsubscribe on server. return true, nil } diff --git a/rpc/websocket_test.go b/rpc/websocket_test.go index 10a998b351..fdb121ffb1 100644 --- a/rpc/websocket_test.go +++ b/rpc/websocket_test.go @@ -159,7 +159,7 @@ func TestWebsocketLargeRead(t *testing.T) { // Check over limit if overLimit > 0 { err = client.Call(&res, "test_repeat", "A", expLimit+1) - if err == nil || err != websocket.ErrReadLimit { + if err == nil || !errors.Is(err, websocket.ErrReadLimit) { t.Fatalf("wrong error with limit %d: %v expecting %v", expLimit, err, websocket.ErrReadLimit) } } diff --git a/signer/core/api.go b/signer/core/api.go index 12acf925f0..130d58d0e1 100644 --- a/signer/core/api.go +++ b/signer/core/api.go @@ -330,7 +330,7 @@ func (api *SignerAPI) startUSBListener() { for _, wallet := range am.Wallets() { if err := wallet.Open(""); err != nil { log.Warn("Failed to open wallet", "url", wallet.URL(), "err", err) - if err == usbwallet.ErrTrezorPINNeeded { + if errors.Is(err, usbwallet.ErrTrezorPINNeeded) { go api.openTrezor(wallet.URL()) } } @@ -346,7 +346,7 @@ func (api *SignerAPI) derivationLoop(events chan accounts.WalletEvent) { case accounts.WalletArrived: if err := event.Wallet.Open(""); err != nil { log.Warn("New wallet appeared, failed to open", "url", event.Wallet.URL(), "err", err) - if err == usbwallet.ErrTrezorPINNeeded { + if errors.Is(err, usbwallet.ErrTrezorPINNeeded) { go api.openTrezor(event.Wallet.URL()) } } diff --git a/signer/core/api_test.go b/signer/core/api_test.go index 69229dadaf..17a7eb1876 100644 --- a/signer/core/api_test.go +++ b/signer/core/api_test.go @@ -19,6 +19,7 @@ package core_test import ( "bytes" "context" + "errors" "fmt" "math/big" "os" @@ -155,7 +156,7 @@ func failCreateAccountWithPassword(ui *headlessUi, api *core.SignerAPI, password func failCreateAccount(ui *headlessUi, api *core.SignerAPI, t *testing.T) { ui.approveCh <- "N" addr, err := api.New(context.Background()) - if err != core.ErrRequestDenied { + if !errors.Is(err, core.ErrRequestDenied) { t.Fatal(err) } if addr != (common.Address{}) { @@ -212,7 +213,7 @@ func TestNewAcc(t *testing.T) { if len(list) != 0 { t.Fatalf("List should be empty") } - if err != core.ErrRequestDenied { + if !errors.Is(err, core.ErrRequestDenied) { t.Fatal("Expected deny") } } @@ -264,7 +265,7 @@ func TestSignTx(t *testing.T) { if res != nil { t.Errorf("Expected nil-response, got %v", res) } - if err != keystore.ErrDecrypt { + if !errors.Is(err, keystore.ErrDecrypt) { t.Errorf("Expected ErrLocked! %v", err) } control.approveCh <- "No way" @@ -272,7 +273,7 @@ func TestSignTx(t *testing.T) { if res != nil { t.Errorf("Expected nil-response, got %v", res) } - if err != core.ErrRequestDenied { + if !errors.Is(err, core.ErrRequestDenied) { t.Errorf("Expected ErrRequestDenied! %v", err) } // Sign with correct password diff --git a/signer/core/signed_data_test.go b/signer/core/signed_data_test.go index d0637010ba..10d5ff3d06 100644 --- a/signer/core/signed_data_test.go +++ b/signer/core/signed_data_test.go @@ -20,6 +20,7 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" "math/big" "os" @@ -201,7 +202,7 @@ func TestSignData(t *testing.T) { if signature != nil { t.Errorf("Expected nil-data, got %x", signature) } - if err != keystore.ErrDecrypt { + if !errors.Is(err, keystore.ErrDecrypt) { t.Errorf("Expected ErrLocked! '%v'", err) } control.approveCh <- "No way" @@ -209,7 +210,7 @@ func TestSignData(t *testing.T) { if signature != nil { t.Errorf("Expected nil-data, got %x", signature) } - if err != core.ErrRequestDenied { + if !errors.Is(err, core.ErrRequestDenied) { t.Errorf("Expected ErrRequestDenied! '%v'", err) } // text/plain diff --git a/tests/init_test.go b/tests/init_test.go index effeec2b86..c31f3b78e9 100644 --- a/tests/init_test.go +++ b/tests/init_test.go @@ -52,7 +52,8 @@ func readJSON(reader io.Reader, value interface{}) error { return fmt.Errorf("error reading JSON file: %v", err) } if err = json.Unmarshal(data, &value); err != nil { - if syntaxerr, ok := err.(*json.SyntaxError); ok { + syntaxerr := new(json.SyntaxError) + if ok := errors.As(err, &syntaxerr); ok { line := findLine(data, syntaxerr.Offset) return fmt.Errorf("JSON syntax error at line %v: %v", line, err) } diff --git a/trie/iterator.go b/trie/iterator.go index fa01611063..7057aff71a 100644 --- a/trie/iterator.go +++ b/trie/iterator.go @@ -268,10 +268,11 @@ func (it *nodeIterator) NodeBlob() []byte { } func (it *nodeIterator) Error() error { - if it.err == errIteratorEnd { + if errors.Is(it.err, errIteratorEnd) { return nil } - if seek, ok := it.err.(seekError); ok { + var seek seekError + if ok := errors.As(it.err, &seek); ok { return seek.err } return it.err @@ -282,10 +283,11 @@ func (it *nodeIterator) Error() error { // sets the Error field to the encountered failure. If `descend` is false, // skips iterating over any subnodes of the current node. func (it *nodeIterator) Next(descend bool) bool { - if it.err == errIteratorEnd { + if errors.Is(it.err, errIteratorEnd) { return false } - if seek, ok := it.err.(seekError); ok { + var seek seekError + if ok := errors.As(it.err, &seek); ok { if it.err = it.seek(seek.key); it.err != nil { return false } @@ -308,7 +310,7 @@ func (it *nodeIterator) seek(prefix []byte) error { // Move forward until we're just before the closest match to key. for { state, parentIndex, path, err := it.peekSeek(key) - if err == errIteratorEnd { + if errors.Is(err, errIteratorEnd) { return errIteratorEnd } else if err != nil { return seekError{prefix, err} diff --git a/trie/iterator_test.go b/trie/iterator_test.go index 74a1aa378c..834f9748fa 100644 --- a/trie/iterator_test.go +++ b/trie/iterator_test.go @@ -18,6 +18,7 @@ package trie import ( "bytes" + "errors" "fmt" "math/rand" "testing" @@ -438,7 +439,8 @@ func testIteratorContinueAfterError(t *testing.T, memonly bool, scheme string) { seen := make(map[string]bool) it := tr.MustNodeIterator(nil) checkIteratorNoDups(t, it, seen) - missing, ok := it.Error().(*MissingNodeError) + missing := new(MissingNodeError) + ok := errors.As(it.Error(), &missing) if !ok || missing.NodeHash != rhash { t.Fatal("didn't hit missing node, got", it.Error()) } @@ -505,7 +507,8 @@ func testIteratorContinueAfterSeekError(t *testing.T, memonly bool, scheme strin // Create a new iterator that seeks to "bars". Seeking can't proceed because // the node is missing. it := tr.MustNodeIterator([]byte("bars")) - missing, ok := it.Error().(*MissingNodeError) + missing := new(MissingNodeError) + ok := errors.As(it.Error(), &missing) if !ok { t.Fatal("want MissingNodeError, got", it.Error()) } else if missing.NodeHash != barNodeHash { diff --git a/trie/node.go b/trie/node.go index 15bbf62f1c..5a93ebc8d6 100644 --- a/trie/node.go +++ b/trie/node.go @@ -17,6 +17,7 @@ package trie import ( + "errors" "fmt" "io" "strings" @@ -242,7 +243,8 @@ func wrapError(err error, ctx string) error { if err == nil { return nil } - if decErr, ok := err.(*decodeError); ok { + decErr := new(decodeError) + if ok := errors.As(err, &decErr); ok { decErr.stack = append(decErr.stack, ctx) return decErr } diff --git a/trie/node_test.go b/trie/node_test.go index 9b8b33748f..bdbcf5f4bd 100644 --- a/trie/node_test.go +++ b/trie/node_test.go @@ -18,6 +18,7 @@ package trie import ( "bytes" + "errors" "testing" "github.com/ethereum/go-ethereum/crypto" @@ -59,7 +60,8 @@ func TestDecodeFullNodeWrongSizeChild(t *testing.T) { rlp.Encode(buf, fullNodeData) _, err := decodeNode([]byte("testdecode"), buf.Bytes()) - if _, ok := err.(*decodeError); !ok { + decodeErr := new(decodeError) + if ok := errors.As(err, &decodeErr); !ok { t.Fatalf("decodeNode returned wrong err: %v", err) } } @@ -78,7 +80,8 @@ func TestDecodeFullNodeWrongNestedFullNode(t *testing.T) { rlp.Encode(buf, fullNodeData) _, err := decodeNode([]byte("testdecode"), buf.Bytes()) - if _, ok := err.(*decodeError); !ok { + decodeErr := new(decodeError) + if ok := errors.As(err, &decodeErr); !ok { t.Fatalf("decodeNode returned wrong err: %v", err) } } diff --git a/trie/trie_test.go b/trie/trie_test.go index 423ed30fe8..63e03f7e4f 100644 --- a/trie/trie_test.go +++ b/trie/trie_test.go @@ -78,7 +78,8 @@ func testMissingRoot(t *testing.T, scheme string) { if trie != nil { t.Error("New returned non-nil trie for invalid root") } - if _, ok := err.(*MissingNodeError); !ok { + missingNodeErr := new(MissingNodeError) + if ok := errors.As(err, &missingNodeErr); !ok { t.Errorf("New returned wrong error: %v", err) } } @@ -148,11 +149,12 @@ func testMissingNode(t *testing.T, memonly bool, scheme string) { } _, err = trie.Get([]byte("120000")) - if _, ok := err.(*MissingNodeError); !ok { + missingNodeErr := new(MissingNodeError) + if ok := errors.As(err, &missingNodeErr); !ok { t.Errorf("Wrong error: %v", err) } _, err = trie.Get([]byte("120099")) - if _, ok := err.(*MissingNodeError); !ok { + if ok := errors.As(err, &missingNodeErr); !ok { t.Errorf("Wrong error: %v", err) } _, err = trie.Get([]byte("123456")) @@ -160,11 +162,11 @@ func testMissingNode(t *testing.T, memonly bool, scheme string) { t.Errorf("Unexpected error: %v", err) } err = trie.Update([]byte("120099"), []byte("zxcv")) - if _, ok := err.(*MissingNodeError); !ok { + if ok := errors.As(err, &missingNodeErr); !ok { t.Errorf("Wrong error: %v", err) } err = trie.Delete([]byte("123456")) - if _, ok := err.(*MissingNodeError); !ok { + if ok := errors.As(err, &missingNodeErr); !ok { t.Errorf("Wrong error: %v", err) } } @@ -622,7 +624,8 @@ func runRandTest(rt randTest) error { func TestRandom(t *testing.T) { if err := quick.Check(runRandTestBool, nil); err != nil { - if cerr, ok := err.(*quick.CheckError); ok { + cerr := new(quick.CheckError) + if ok := errors.As(err, &cerr); ok { t.Fatalf("random test iteration %d failed: %s", cerr.Count, spew.Sdump(cerr.In)) } t.Fatal(err) diff --git a/triedb/pathdb/journal.go b/triedb/pathdb/journal.go index 267d675bc2..368da96b84 100644 --- a/triedb/pathdb/journal.go +++ b/triedb/pathdb/journal.go @@ -150,7 +150,7 @@ func (db *Database) loadDiffLayer(parent layer, r *rlp.Stream) (layer, error) { var root common.Hash if err := r.Decode(&root); err != nil { // The first read may fail with EOF, marking the end of the journal - if err == io.EOF { + if errors.Is(err, io.EOF) { return parent, nil } return nil, fmt.Errorf("load diff root: %v", err)