From 36edd2f27b23df5eaff024d07054709a415940f4 Mon Sep 17 00:00:00 2001 From: Emmanuel Odeke Date: Sun, 13 Aug 2017 18:50:54 -0600 Subject: [PATCH] all: replace unnecesary fmt.Errorf("[^%]*") calls with errors.New After running ```shell grep -Rn 'fmt.Errorf("[^%]*")' * ``` noticed that there were too many unnecessary function calls to fmt.Errorf(PLAIN_STRING) of which these calls can be directly replaced with errors.New(PLAIN_STRING), which is anyways invoked by fmt.Errorf and this change avoids incurring extraneous function calls at runtime. This work is a token from your friends from @tendermint --- accounts/abi/abi.go | 7 ++++- accounts/abi/bind/util.go | 11 +++++-- accounts/abi/unpack.go | 5 +++- accounts/keystore/keystore.go | 5 ++-- cmd/utils/cmd.go | 7 +++-- contracts/chequebook/cheque.go | 10 +++++-- core/blockchain.go | 13 ++++++--- core/chain_indexer.go | 7 ++++- core/genesis.go | 10 +++++-- crypto/ecies/ecies.go | 19 ++++++------ crypto/ecies/params.go | 6 ++-- crypto/signature_nocgo.go | 6 +++- eth/backend.go | 6 +++- eth/filters/api.go | 13 ++++++--- eth/filters/filter_system.go | 5 ++-- ethclient/ethclient.go | 21 ++++++++++---- internal/build/archive.go | 7 ++++- internal/ethapi/api.go | 19 ++++++++---- internal/ethapi/tracer.go | 9 ++++-- les/backend.go | 8 ++++-- miner/worker.go | 7 ++++- node/api.go | 10 +++++-- p2p/discv5/net.go | 6 +++- p2p/discv5/ticket.go | 5 +++- p2p/nat/natpmp.go | 5 +++- p2p/peer.go | 7 ++++- p2p/rlpx.go | 9 ++++-- p2p/server.go | 10 +++++-- rlp/encode.go | 7 ++++- rpc/json.go | 10 +++++-- rpc/types.go | 8 ++++-- swarm/api/filesystem.go | 15 +++++++--- swarm/api/manifest.go | 4 +-- swarm/fuse/swarmfs_util.go | 8 ++++-- swarm/network/hive.go | 7 ++++- swarm/network/kademlia/kademlia.go | 7 ++++- swarm/network/protocol.go | 9 ++++-- swarm/network/syncer.go | 9 ++++-- swarm/storage/dbstore.go | 7 ++++- swarm/swarm.go | 10 +++++-- whisper/whisperv2/api.go | 13 +++++++-- whisper/whisperv2/envelope.go | 7 ++++- whisper/whisperv2/main.go | 5 +++- whisper/whisperv5/api.go | 8 ++++-- whisper/whisperv5/filter.go | 2 +- whisper/whisperv5/whisper.go | 46 ++++++++++++++++++++---------- 46 files changed, 322 insertions(+), 113 deletions(-) diff --git a/accounts/abi/abi.go b/accounts/abi/abi.go index 2a06d474b8..ae1f28301d 100644 --- a/accounts/abi/abi.go +++ b/accounts/abi/abi.go @@ -18,6 +18,7 @@ package abi import ( "encoding/json" + "errors" "fmt" "io" "reflect" @@ -85,12 +86,16 @@ var ( r_byte = reflect.TypeOf(byte(0)) ) +var ( + errEmptyABIOutput = errors.New("abi: unmarshalling empty output") +) + // Unpack output in v according to the abi specification func (abi ABI) Unpack(v interface{}, name string, output []byte) error { var method = abi.Methods[name] if len(output) == 0 { - return fmt.Errorf("abi: unmarshalling empty output") + return errEmptyABIOutput } // make sure the passed value is a pointer diff --git a/accounts/abi/bind/util.go b/accounts/abi/bind/util.go index d129993ca1..10ec71087b 100644 --- a/accounts/abi/bind/util.go +++ b/accounts/abi/bind/util.go @@ -18,7 +18,7 @@ package bind import ( "context" - "fmt" + "errors" "time" "github.com/ethereum/go-ethereum/common" @@ -52,18 +52,23 @@ func WaitMined(ctx context.Context, b DeployBackend, tx *types.Transaction) (*ty } } +var ( + errTxNotContractCreation = errors.New("tx is not contract creation") + errZeroAddress = errors.New("zero address") +) + // WaitDeployed waits for a contract deployment transaction and returns the on-chain // contract address when it is mined. It stops waiting when ctx is canceled. func WaitDeployed(ctx context.Context, b DeployBackend, tx *types.Transaction) (common.Address, error) { if tx.To() != nil { - return common.Address{}, fmt.Errorf("tx is not contract creation") + return common.Address{}, errTxNotContractCreation } receipt, err := WaitMined(ctx, b, tx) if err != nil { return common.Address{}, err } if receipt.ContractAddress == (common.Address{}) { - return common.Address{}, fmt.Errorf("zero address") + return common.Address{}, errZeroAddress } // Check that code has indeed been deployed at the address. // This matters on pre-Homestead chains: OOG in the constructor diff --git a/accounts/abi/unpack.go b/accounts/abi/unpack.go index fc41c88ac7..28eeafc0da 100644 --- a/accounts/abi/unpack.go +++ b/accounts/abi/unpack.go @@ -18,6 +18,7 @@ package abi import ( "encoding/binary" + "errors" "fmt" "math/big" "reflect" @@ -160,9 +161,11 @@ func readInteger(kind reflect.Kind, b []byte) interface{} { } } +var errIncorrectWordLength = errors.New("abi: fatal error: incorrect word length") + func readBool(word []byte) (bool, error) { if len(word) != 32 { - return false, fmt.Errorf("abi: fatal error: incorrect word length") + return false, errIncorrectWordLength } for i, b := range word { diff --git a/accounts/keystore/keystore.go b/accounts/keystore/keystore.go index 9df7f2dd96..a7c55d0e24 100644 --- a/accounts/keystore/keystore.go +++ b/accounts/keystore/keystore.go @@ -24,7 +24,6 @@ import ( "crypto/ecdsa" crand "crypto/rand" "errors" - "fmt" "math/big" "os" "path/filepath" @@ -44,6 +43,8 @@ var ( ErrLocked = accounts.NewAuthNeededError("password or unlock") ErrNoMatch = errors.New("no key for given address or file") ErrDecrypt = errors.New("could not decrypt key with given passphrase") + + errAccountExists = errors.New("account already exists") ) // KeyStoreType is the reflect type of a keystore backend. @@ -448,7 +449,7 @@ func (ks *KeyStore) Import(keyJSON []byte, passphrase, newPassphrase string) (ac func (ks *KeyStore) ImportECDSA(priv *ecdsa.PrivateKey, passphrase string) (accounts.Account, error) { key := newKeyFromECDSA(priv) if ks.cache.hasAddress(key.Address) { - return accounts.Account{}, fmt.Errorf("account already exists") + return accounts.Account{}, errAccountExists } return ks.importKey(key, passphrase) } diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go index 17c258c6c8..4c7c5ee303 100644 --- a/cmd/utils/cmd.go +++ b/cmd/utils/cmd.go @@ -19,6 +19,7 @@ package utils import ( "compress/gzip" + "errors" "fmt" "io" "os" @@ -80,6 +81,8 @@ func StartNode(stack *node.Node) { }() } +var errInterrupted = errors.New("interrupted") + func ImportChain(chain *core.BlockChain, fn string) error { // Watch for Ctrl-C while the import is running. // If a signal is received, the import will stop at the next batch. @@ -125,7 +128,7 @@ func ImportChain(chain *core.BlockChain, fn string) error { for batch := 0; ; batch++ { // Load a batch of RLP blocks. if checkInterrupt() { - return fmt.Errorf("interrupted") + return errInterrupted } i := 0 for ; i < importBatchSize; i++ { @@ -148,7 +151,7 @@ func ImportChain(chain *core.BlockChain, fn string) error { } // Import the batch. if checkInterrupt() { - return fmt.Errorf("interrupted") + return errInterrupted } if hasAllBlocks(chain, blocks[:i]) { log.Info("Skipping batch as all blocks present", "batch", batch, "first", blocks[0].Hash(), "last", blocks[i-1].Hash()) diff --git a/contracts/chequebook/cheque.go b/contracts/chequebook/cheque.go index 09daa92484..a40f4bef34 100644 --- a/contracts/chequebook/cheque.go +++ b/contracts/chequebook/cheque.go @@ -29,6 +29,7 @@ import ( "context" "crypto/ecdsa" "encoding/json" + "errors" "fmt" "io/ioutil" "math/big" @@ -443,11 +444,16 @@ type Inbox struct { log log.Logger // contextual logger with the contract address embedded } +var ( + errNilSigner = errors.New("signer is null") + errInvalidAmount = errors.New("invalid amount") +) + // NewInbox creates an Inbox. An Inboxes is not persisted, the cumulative sum is updated // from blockchain when first cheque is received. func NewInbox(prvKey *ecdsa.PrivateKey, contractAddr, beneficiary common.Address, signer *ecdsa.PublicKey, abigen bind.ContractBackend) (self *Inbox, err error) { if signer == nil { - return nil, fmt.Errorf("signer is null") + return nil, errNilSigner } chbook, err := contract.NewChequebook(contractAddr, abigen) if err != nil { @@ -584,7 +590,7 @@ func (self *Inbox) Receive(promise swap.Promise) (*big.Int, error) { func (self *Cheque) Verify(signerKey *ecdsa.PublicKey, contract, beneficiary common.Address, sum *big.Int) (*big.Int, error) { log.Trace("Verifying chequebook cheque", "cheque", self, "sum", sum) if sum == nil { - return nil, fmt.Errorf("invalid amount") + return nil, errInvalidAmount } if self.Beneficiary != beneficiary { diff --git a/core/blockchain.go b/core/blockchain.go index 3fb8be15f4..e869f2a6b0 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1079,6 +1079,11 @@ func countTransactions(chain []*types.Block) (c int) { return c } +var ( + errInvalidOldChain = errors.New("Invalid old chain") + errInvalidNewChain = errors.New("Invalid new chain") +) + // reorgs takes two blocks, an old chain and a new chain and will reconstruct the blocks and inserts them // to be part of the new canonical chain and accumulates potential missing transactions and post an // event about them @@ -1121,10 +1126,10 @@ func (bc *BlockChain) reorg(oldBlock, newBlock *types.Block) error { } } if oldBlock == nil { - return fmt.Errorf("Invalid old chain") + return errInvalidOldChain } if newBlock == nil { - return fmt.Errorf("Invalid new chain") + return errInvalidNewChain } for { @@ -1140,10 +1145,10 @@ func (bc *BlockChain) reorg(oldBlock, newBlock *types.Block) error { oldBlock, newBlock = bc.GetBlock(oldBlock.ParentHash(), oldBlock.NumberU64()-1), bc.GetBlock(newBlock.ParentHash(), newBlock.NumberU64()-1) if oldBlock == nil { - return fmt.Errorf("Invalid old chain") + return errInvalidOldChain } if newBlock == nil { - return fmt.Errorf("Invalid new chain") + return errInvalidNewChain } } // Ensure the user sees large reorgs diff --git a/core/chain_indexer.go b/core/chain_indexer.go index 9a88a5b1b8..6f3192ee04 100644 --- a/core/chain_indexer.go +++ b/core/chain_indexer.go @@ -18,6 +18,7 @@ package core import ( "encoding/binary" + "errors" "fmt" "sync" "sync/atomic" @@ -287,6 +288,10 @@ func (c *ChainIndexer) updateLoop() { } } +var ( + errChainReorgedInProcessing = errors.New("chain reorged during section processing") +) + // processSection processes an entire section by calling backend functions while // ensuring the continuity of the passed headers. Since the chain mutex is not // held while processing, the continuity can be broken by a long reorg, in which @@ -306,7 +311,7 @@ func (c *ChainIndexer) processSection(section uint64, lastHead common.Hash) (com if header == nil { return common.Hash{}, fmt.Errorf("block #%d [%x…] not found", number, hash[:4]) } else if header.ParentHash != lastHead { - return common.Hash{}, fmt.Errorf("chain reorged during section processing") + return common.Hash{}, errChainReorgedInProcessing } c.backend.Process(header) lastHead = header.Hash() diff --git a/core/genesis.go b/core/genesis.go index fd6ed61159..b36d9fcdaf 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -39,7 +39,11 @@ import ( //go:generate gencodec -type Genesis -field-override genesisSpecMarshaling -out gen_genesis.go //go:generate gencodec -type GenesisAccount -field-override genesisAccountMarshaling -out gen_genesis_account.go -var errGenesisNoConfig = errors.New("genesis has no chain configuration") +var ( + errGenesisNoConfig = errors.New("genesis has no chain configuration") + errMissingHeaderHashBlockNumber = errors.New("missing block number for head header hash") + errGenesisBlockNumberNonZero = errors.New("can't commit genesis block with number > 0") +) // Genesis specifies the header fields, state of a genesis block. It also defines hard // fork switch-over blocks through the chain configuration. @@ -198,7 +202,7 @@ func SetupGenesisBlock(db ethdb.Database, genesis *Genesis) (*params.ChainConfig // are returned to the caller unless we're already at block zero. height := GetBlockNumber(db, GetHeadHeaderHash(db)) if height == missingNumber { - return newcfg, stored, fmt.Errorf("missing block number for head header hash") + return newcfg, stored, errMissingHeaderHashBlockNumber } compatErr := storedcfg.CheckCompatible(newcfg, height) if compatErr != nil && height != 0 && compatErr.RewindTo != 0 { @@ -260,7 +264,7 @@ func (g *Genesis) ToBlock() (*types.Block, *state.StateDB) { func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) { block, statedb := g.ToBlock() if block.Number().Sign() != 0 { - return nil, fmt.Errorf("can't commit genesis block with number > 0") + return nil, errGenesisBlockNumberNonZero } if _, err := statedb.CommitTo(db, false); err != nil { return nil, fmt.Errorf("cannot write state: %v", err) diff --git a/crypto/ecies/ecies.go b/crypto/ecies/ecies.go index 1d5f96ed27..1859e0261d 100644 --- a/crypto/ecies/ecies.go +++ b/crypto/ecies/ecies.go @@ -35,6 +35,7 @@ import ( "crypto/elliptic" "crypto/hmac" "crypto/subtle" + "errors" "fmt" "hash" "io" @@ -42,12 +43,12 @@ import ( ) var ( - ErrImport = fmt.Errorf("ecies: failed to import key") - ErrInvalidCurve = fmt.Errorf("ecies: invalid elliptic curve") - ErrInvalidParams = fmt.Errorf("ecies: invalid ECIES parameters") - ErrInvalidPublicKey = fmt.Errorf("ecies: invalid public key") - ErrSharedKeyIsPointAtInfinity = fmt.Errorf("ecies: shared key is point at infinity") - ErrSharedKeyTooBig = fmt.Errorf("ecies: shared key params are too big") + ErrImport = errors.New("ecies: failed to import key") + ErrInvalidCurve = errors.New("ecies: invalid elliptic curve") + ErrInvalidParams = errors.New("ecies: invalid ECIES parameters") + ErrInvalidPublicKey = errors.New("ecies: invalid public key") + ErrSharedKeyIsPointAtInfinity = errors.New("ecies: shared key is point at infinity") + ErrSharedKeyTooBig = errors.New("ecies: shared key params are too big") ) // PublicKey is a representation of an elliptic curve public key. @@ -138,9 +139,9 @@ func (prv *PrivateKey) GenerateShared(pub *PublicKey, skLen, macLen int) (sk []b } var ( - ErrKeyDataTooLong = fmt.Errorf("ecies: can't supply requested key data") - ErrSharedTooLong = fmt.Errorf("ecies: shared secret is too long") - ErrInvalidMessage = fmt.Errorf("ecies: invalid message") + ErrKeyDataTooLong = errors.New("ecies: can't supply requested key data") + ErrSharedTooLong = errors.New("ecies: shared secret is too long") + ErrInvalidMessage = errors.New("ecies: invalid message") ) var ( diff --git a/crypto/ecies/params.go b/crypto/ecies/params.go index 6312daf5a1..c5eb475a29 100644 --- a/crypto/ecies/params.go +++ b/crypto/ecies/params.go @@ -39,7 +39,7 @@ import ( "crypto/elliptic" "crypto/sha256" "crypto/sha512" - "fmt" + "errors" "hash" ethcrypto "github.com/ethereum/go-ethereum/crypto" @@ -47,8 +47,8 @@ import ( var ( DefaultCurve = ethcrypto.S256() - ErrUnsupportedECDHAlgorithm = fmt.Errorf("ecies: unsupported ECDH algorithm") - ErrUnsupportedECIESParameters = fmt.Errorf("ecies: unsupported ECIES parameters") + ErrUnsupportedECDHAlgorithm = errors.New("ecies: unsupported ECDH algorithm") + ErrUnsupportedECIESParameters = errors.New("ecies: unsupported ECIES parameters") ) type ECIESParams struct { diff --git a/crypto/signature_nocgo.go b/crypto/signature_nocgo.go index a022eef9a4..7c45f530c7 100644 --- a/crypto/signature_nocgo.go +++ b/crypto/signature_nocgo.go @@ -45,6 +45,10 @@ func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) { return (*ecdsa.PublicKey)(pub), err } +var ( + errPrivKeyCurveNotSecp256k1 = errors.New("private key curve is not secp256k1") +) + // Sign calculates an ECDSA signature. // // This function is susceptible to chosen plaintext attacks that can leak @@ -58,7 +62,7 @@ func Sign(hash []byte, prv *ecdsa.PrivateKey) ([]byte, error) { return nil, fmt.Errorf("hash is required to be exactly 32 bytes (%d)", len(hash)) } if prv.Curve != btcec.S256() { - return nil, fmt.Errorf("private key curve is not secp256k1") + return nil, errPrivKeyCurveNotSecp256k1 } sig, err := btcec.SignCompact(btcec.S256(), (*btcec.PrivateKey)(prv), hash, false) if err != nil { diff --git a/eth/backend.go b/eth/backend.go index 8a837f7b88..e1eb8a7046 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -296,6 +296,10 @@ func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) { s.blockchain.ResetWithGenesisBlock(gb) } +var ( + errEtherbaseAddressWanted = errors.New("etherbase address must be explicitly specified") +) + func (s *Ethereum) Etherbase() (eb common.Address, err error) { s.lock.RLock() etherbase := s.etherbase @@ -309,7 +313,7 @@ func (s *Ethereum) Etherbase() (eb common.Address, err error) { return accounts[0].Address, nil } } - return common.Address{}, fmt.Errorf("etherbase address must be explicitly specified") + return common.Address{}, errEtherbaseAddressWanted } // set in js console via admin interface or wrapper from cli flags diff --git a/eth/filters/api.go b/eth/filters/api.go index fff58a268e..1d64e458a0 100644 --- a/eth/filters/api.go +++ b/eth/filters/api.go @@ -359,6 +359,11 @@ func (api *PublicFilterAPI) UninstallFilter(id rpc.ID) bool { return found } +var ( + errFilterNotFound = errors.New("filter not found") + errInvalidTopics = errors.New("invalid topic(s)") +) + // GetFilterLogs returns the logs for the filter with the given id. // If the filter could not be found an empty array of logs is returned. // @@ -369,7 +374,7 @@ func (api *PublicFilterAPI) GetFilterLogs(ctx context.Context, id rpc.ID) ([]*ty api.filtersMu.Unlock() if !found || f.typ != LogsSubscription { - return nil, fmt.Errorf("filter not found") + return nil, errFilterNotFound } filter := New(api.backend, api.useMipMap) @@ -424,7 +429,7 @@ func (api *PublicFilterAPI) GetFilterChanges(id rpc.ID) (interface{}, error) { } } - return []interface{}{}, fmt.Errorf("filter not found") + return []interface{}{}, errFilterNotFound } // returnHashes is a helper that will return an empty hash array case the given hash array is nil, @@ -524,11 +529,11 @@ func (args *FilterCriteria) UnmarshalJSON(data []byte) error { } args.Topics[i] = append(args.Topics[i], parsed) } else { - return fmt.Errorf("invalid topic(s)") + return errInvalidTopics } } default: - return fmt.Errorf("invalid topic(s)") + return errInvalidTopics } } } diff --git a/eth/filters/filter_system.go b/eth/filters/filter_system.go index ab0b7473ea..fa549388d7 100644 --- a/eth/filters/filter_system.go +++ b/eth/filters/filter_system.go @@ -21,7 +21,6 @@ package filters import ( "context" "errors" - "fmt" "sync" "time" @@ -56,6 +55,8 @@ const ( var ( ErrInvalidSubscriptionID = errors.New("invalid id") + + errInvalidFromToBlockCombination = errors.New("invalid from and to block combination: from > to") ) type subscription struct { @@ -182,7 +183,7 @@ func (es *EventSystem) SubscribeLogs(crit FilterCriteria, logs chan []*types.Log if from >= 0 && to == rpc.LatestBlockNumber { return es.subscribeLogs(crit, logs), nil } - return nil, fmt.Errorf("invalid from and to block combination: from > to") + return nil, errInvalidFromToBlockCombination } // subscribeMinedPendingLogs creates a subscription that returned mined and diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index 48639d9492..8995e85629 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -20,6 +20,7 @@ package ethclient import ( "context" "encoding/json" + "errors" "fmt" "math/big" @@ -94,16 +95,16 @@ func (ec *Client) getBlock(ctx context.Context, method string, args ...interface } // Quick-verify transaction and uncle lists. This mostly helps with debugging the server. if head.UncleHash == types.EmptyUncleHash && len(body.UncleHashes) > 0 { - return nil, fmt.Errorf("server returned non-empty uncle list but block header indicates no uncles") + return nil, errServerUnexpectedNonEmptyUncles } if head.UncleHash != types.EmptyUncleHash && len(body.UncleHashes) == 0 { - return nil, fmt.Errorf("server returned empty uncle list but block header indicates uncles") + return nil, errServerUnexpectedEmptyUncles } if head.TxHash == types.EmptyRootHash && len(body.Transactions) > 0 { - return nil, fmt.Errorf("server returned non-empty transaction list but block header indicates no transactions") + return nil, errServerUnexpectedNonEmptyTransactions } if head.TxHash != types.EmptyRootHash && len(body.Transactions) == 0 { - return nil, fmt.Errorf("server returned empty transaction list but block header indicates transactions") + return nil, errServerUnexpectedEmptyTransactions } // Load uncles because they are not included in the block response. var uncles []*types.Header @@ -153,6 +154,14 @@ func (ec *Client) HeaderByNumber(ctx context.Context, number *big.Int) (*types.H return head, err } +var ( + errServerTxWithoutSignature = errors.New("server returned transaction without signature") + errServerUnexpectedNonEmptyUncles = errors.New("server returned non-empty uncle list but block header indicates no uncles") + errServerUnexpectedEmptyUncles = errors.New("server returned empty uncle list but block header indicates uncles") + errServerUnexpectedNonEmptyTransactions = errors.New("server returned non-empty transaction list but block header indicates no transactions") + errServerUnexpectedEmptyTransactions = errors.New("server returned empty transaction list but block header indicates transactions") +) + // TransactionByHash returns the transaction with the given hash. func (ec *Client) TransactionByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error) { var raw json.RawMessage @@ -165,7 +174,7 @@ func (ec *Client) TransactionByHash(ctx context.Context, hash common.Hash) (tx * if err := json.Unmarshal(raw, &tx); err != nil { return nil, false, err } else if _, r, _ := tx.RawSignatureValues(); r == nil { - return nil, false, fmt.Errorf("server returned transaction without signature") + return nil, false, errServerTxWithoutSignature } var block struct{ BlockNumber *string } if err := json.Unmarshal(raw, &block); err != nil { @@ -189,7 +198,7 @@ func (ec *Client) TransactionInBlock(ctx context.Context, blockHash common.Hash, if tx == nil { return nil, ethereum.NotFound } else if _, r, _ := tx.RawSignatureValues(); r == nil { - return nil, fmt.Errorf("server returned transaction without signature") + return nil, errServerTxWithoutSignature } } return tx, err diff --git a/internal/build/archive.go b/internal/build/archive.go index ac680ba63d..490b23a748 100644 --- a/internal/build/archive.go +++ b/internal/build/archive.go @@ -20,6 +20,7 @@ import ( "archive/tar" "archive/zip" "compress/gzip" + "errors" "fmt" "io" "os" @@ -73,6 +74,10 @@ func AddFile(a Archive, file string) error { return nil } +var ( + errUnknownArchiveExtension = errors.New("unknown archive extension") +) + // WriteArchive creates an archive containing the given files. func WriteArchive(name string, files []string) (err error) { archfd, err := os.Create(name) @@ -89,7 +94,7 @@ func WriteArchive(name string, files []string) (err error) { }() archive, basename := NewArchive(archfd) if archive == nil { - return fmt.Errorf("unknown archive extension") + return errUnknownArchiveExtension } fmt.Println(name) if err := archive.Directory(basename); err != nil { diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 7874b7101f..4aa87ccb45 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -385,6 +385,15 @@ func (s *PrivateAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr c return signature, nil } +var ( + err65ByteSignatureWanted = errors.New("signature must be 65 bytes long") + errEthereumSignature27or28Wanted = errors.New("invalid Ethereum signature (V is not 27 or 28)") + + errMissingTxNonceInSpec = errors.New("missing transaction nonce in transaction spec") + errChainDBCompactNotForMemoryDB = errors.New("chaindbCompact does not work for memory databases") + errChainDBPropertyNotForMemoryDB = errors.New("chaindbProperty does not work for memory databases") +) + // EcRecover returns the address for the account that was used to create the signature. // Note, this function is compatible with eth_sign and personal_sign. As such it recovers // the address of: @@ -397,10 +406,10 @@ func (s *PrivateAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr c // https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecover func (s *PrivateAccountAPI) EcRecover(ctx context.Context, data, sig hexutil.Bytes) (common.Address, error) { if len(sig) != 65 { - return common.Address{}, fmt.Errorf("signature must be 65 bytes long") + return common.Address{}, err65ByteSignatureWanted } if sig[64] != 27 && sig[64] != 28 { - return common.Address{}, fmt.Errorf("invalid Ethereum signature (V is not 27 or 28)") + return common.Address{}, errEthereumSignature27or28Wanted } sig[64] -= 27 // Transform yellow paper V from 27/28 to 0/1 @@ -1211,7 +1220,7 @@ func (s *PublicTransactionPoolAPI) PendingTransactions() ([]*RPCTransaction, err // the given transaction from the pool and reinsert it with the new gas price and limit. func (s *PublicTransactionPoolAPI) Resend(ctx context.Context, sendArgs SendTxArgs, gasPrice, gasLimit *hexutil.Big) (common.Hash, error) { if sendArgs.Nonce == nil { - return common.Hash{}, fmt.Errorf("missing transaction nonce in transaction spec") + return common.Hash{}, errMissingTxNonceInSpec } if err := sendArgs.setDefaults(ctx, s.b); err != nil { return common.Hash{}, err @@ -1313,7 +1322,7 @@ func (api *PrivateDebugAPI) ChaindbProperty(property string) (string, error) { LDB() *leveldb.DB }) if !ok { - return "", fmt.Errorf("chaindbProperty does not work for memory databases") + return "", errChainDBPropertyNotForMemoryDB } if property == "" { property = "leveldb.stats" @@ -1328,7 +1337,7 @@ func (api *PrivateDebugAPI) ChaindbCompact() error { LDB() *leveldb.DB }) if !ok { - return fmt.Errorf("chaindbCompact does not work for memory databases") + return errChainDBCompactNotForMemoryDB } for b := byte(0); b < 255; b++ { log.Info("Compacting chain database", "range", fmt.Sprintf("0x%0.2X-0x%0.2X", b, b+1)) diff --git a/internal/ethapi/tracer.go b/internal/ethapi/tracer.go index fc66839ea5..27ca42fb17 100644 --- a/internal/ethapi/tracer.go +++ b/internal/ethapi/tracer.go @@ -215,6 +215,11 @@ type JavascriptTracer struct { err error // Error, if one has occurred } +var ( + errTraceMustExposeFunctionStep = errors.New("Trace object must expose a function step()") + errTraceMustExposeFunctionResult = errors.New("Trace object must expose a function result()") +) + // NewJavascriptTracer instantiates a new JavascriptTracer instance. // code specifies a Javascript snippet, which must evaluate to an expression // returning an object with 'step' and 'result' functions. @@ -237,7 +242,7 @@ func NewJavascriptTracer(code string) (*JavascriptTracer, error) { return nil, err } if !step.IsFunction() { - return nil, fmt.Errorf("Trace object must expose a function step()") + return nil, errTraceMustExposeFunctionStep } result, err := jstracer.Get("result") @@ -245,7 +250,7 @@ func NewJavascriptTracer(code string) (*JavascriptTracer, error) { return nil, err } if !result.IsFunction() { - return nil, fmt.Errorf("Trace object must expose a function result()") + return nil, errTraceMustExposeFunctionResult } // Create the persistent log object diff --git a/les/backend.go b/les/backend.go index a4e7726717..f5f10127ae 100644 --- a/les/backend.go +++ b/les/backend.go @@ -18,7 +18,7 @@ package les import ( - "fmt" + "errors" "sync" "time" @@ -132,14 +132,16 @@ func lesTopic(genesisHash common.Hash) discv5.Topic { type LightDummyAPI struct{} +var errNotSupported = errors.New("not supported") + // Etherbase is the address that mining rewards will be send to func (s *LightDummyAPI) Etherbase() (common.Address, error) { - return common.Address{}, fmt.Errorf("not supported") + return common.Address{}, errNotSupported } // Coinbase is the address that mining rewards will be send to (alias for Etherbase) func (s *LightDummyAPI) Coinbase() (common.Address, error) { - return common.Address{}, fmt.Errorf("not supported") + return common.Address{}, errNotSupported } // Hashrate returns the POW hashrate diff --git a/miner/worker.go b/miner/worker.go index dab192c24f..4174766566 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -18,6 +18,7 @@ package miner import ( "bytes" + "errors" "fmt" "math/big" "sync" @@ -472,10 +473,14 @@ func (self *worker) commitNewWork() { self.push(work) } +var ( + errUncleNotUnique = errors.New("uncle not unique") +) + func (self *worker) commitUncle(work *Work, uncle *types.Header) error { hash := uncle.Hash() if work.uncles.Has(hash) { - return fmt.Errorf("uncle not unique") + return errUncleNotUnique } if !work.ancestors.Has(uncle.ParentHash) { return fmt.Errorf("uncle's parent unknown (%x)", uncle.ParentHash[0:4]) diff --git a/node/api.go b/node/api.go index 570cb9d98e..c686fd3e80 100644 --- a/node/api.go +++ b/node/api.go @@ -17,6 +17,7 @@ package node import ( + "errors" "fmt" "strings" "time" @@ -115,13 +116,18 @@ func (api *PrivateAdminAPI) StartRPC(host *string, port *int, cors *string, apis return true, nil } +var ( + errHTTPRPCNotRunning = errors.New("HTTP RPC not running") + errWebsocketRPCNotRunning = errors.New("WebSocket RPC not running") +) + // StopRPC terminates an already running HTTP RPC API endpoint. func (api *PrivateAdminAPI) StopRPC() (bool, error) { api.node.lock.Lock() defer api.node.lock.Unlock() if api.node.httpHandler == nil { - return false, fmt.Errorf("HTTP RPC not running") + return false, errHTTPRPCNotRunning } api.node.stopHTTP() return true, nil @@ -175,7 +181,7 @@ func (api *PrivateAdminAPI) StopWS() (bool, error) { defer api.node.lock.Unlock() if api.node.wsHandler == nil { - return false, fmt.Errorf("WebSocket RPC not running") + return false, errWebsocketRPCNotRunning } api.node.stopWS() return true, nil diff --git a/p2p/discv5/net.go b/p2p/discv5/net.go index a39cfcc645..879ee3fb0e 100644 --- a/p2p/discv5/net.go +++ b/p2p/discv5/net.go @@ -1052,6 +1052,10 @@ func (net *Network) handle(n *Node, ev nodeEvent, pkt *ingressPacket) error { return err } +var ( + errPongReplyMismatch = errors.New("pong reply token mismatch") +) + func (net *Network) checkPacket(n *Node, ev nodeEvent, pkt *ingressPacket) error { // Replay prevention checks. switch ev { @@ -1061,7 +1065,7 @@ func (net *Network) checkPacket(n *Node, ev nodeEvent, pkt *ingressPacket) error case pongPacket: if !bytes.Equal(pkt.data.(*pong).ReplyTok, n.pingEcho) { // fmt.Println("pong reply token mismatch") - return fmt.Errorf("pong reply token mismatch") + return errPongReplyMismatch } n.pingEcho = nil } diff --git a/p2p/discv5/ticket.go b/p2p/discv5/ticket.go index 48dd114f06..e44e47c6ae 100644 --- a/p2p/discv5/ticket.go +++ b/p2p/discv5/ticket.go @@ -19,6 +19,7 @@ package discv5 import ( "bytes" "encoding/binary" + "errors" "fmt" "math" "math/rand" @@ -88,13 +89,15 @@ func (ref ticketRef) topicRegTime() mclock.AbsTime { return ref.t.regTime[ref.idx] } +var errBadTopicHash = errors.New("bad topic hash") + func pongToTicket(localTime mclock.AbsTime, topics []Topic, node *Node, p *ingressPacket) (*ticket, error) { wps := p.data.(*pong).WaitPeriods if len(topics) != len(wps) { return nil, fmt.Errorf("bad wait period list: got %d values, want %d", len(topics), len(wps)) } if rlpHash(topics) != p.data.(*pong).TopicHash { - return nil, fmt.Errorf("bad topic hash") + return nil, errBadTopicHash } t := &ticket{ issueTime: localTime, diff --git a/p2p/nat/natpmp.go b/p2p/nat/natpmp.go index 577a424fbe..b6574f1a19 100644 --- a/p2p/nat/natpmp.go +++ b/p2p/nat/natpmp.go @@ -17,6 +17,7 @@ package nat import ( + "errors" "fmt" "net" "strings" @@ -44,9 +45,11 @@ func (n *pmp) ExternalIP() (net.IP, error) { return response.ExternalIPAddress[:], nil } +var errPositiveLifetime = errors.New("lifetime must not be <= 0") + func (n *pmp) AddMapping(protocol string, extport, intport int, name string, lifetime time.Duration) error { if lifetime <= 0 { - return fmt.Errorf("lifetime must not be <= 0") + return errPositiveLifetime } // Note order of port arguments is switched between our // AddMapping and the client's AddPortMapping. diff --git a/p2p/peer.go b/p2p/peer.go index a9c20189a4..3518e90daa 100644 --- a/p2p/peer.go +++ b/p2p/peer.go @@ -17,6 +17,7 @@ package p2p import ( + "errors" "fmt" "io" "net" @@ -332,6 +333,10 @@ type protoRW struct { w MsgWriter } +var ( + errShuttingDown = errors.New("shutting down") +) + func (rw *protoRW) WriteMsg(msg Msg) (err error) { if msg.Code >= rw.Length { return newPeerError(errInvalidMsgCode, "not handled") @@ -346,7 +351,7 @@ func (rw *protoRW) WriteMsg(msg Msg) (err error) { // as well but we don't want to rely on that. rw.werr <- err case <-rw.closed: - err = fmt.Errorf("shutting down") + err = errShuttingDown } return err } diff --git a/p2p/rlpx.go b/p2p/rlpx.go index b2775cacdc..61fb640104 100644 --- a/p2p/rlpx.go +++ b/p2p/rlpx.go @@ -130,13 +130,18 @@ func (t *rlpx) doProtoHandshake(our *protoHandshake) (their *protoHandshake, err return their, nil } +var ( + errMessageTooBig = errors.New("message too big") + errInvalidPublicKey = errors.New("invalid public key") +) + func readProtocolHandshake(rw MsgReader, our *protoHandshake) (*protoHandshake, error) { msg, err := rw.ReadMsg() if err != nil { return nil, err } if msg.Size > baseProtocolMaxMsgSize { - return nil, fmt.Errorf("message too big") + return nil, errMessageTooBig } if msg.Code == discMsg { // Disconnect before protocol handshake is valid according to the @@ -515,7 +520,7 @@ func importPublicKey(pubKey []byte) (*ecies.PublicKey, error) { // TODO: fewer pointless conversions pub := crypto.ToECDSAPub(pubKey65) if pub.X == nil { - return nil, fmt.Errorf("invalid public key") + return nil, errInvalidPublicKey } return ecies.ImportECDSAPublic(pub), nil } diff --git a/p2p/server.go b/p2p/server.go index d7909d53a9..d204e785ad 100644 --- a/p2p/server.go +++ b/p2p/server.go @@ -20,7 +20,6 @@ package p2p import ( "crypto/ecdsa" "errors" - "fmt" "net" "sync" "time" @@ -339,20 +338,25 @@ func (srv *Server) Stop() { srv.loopWG.Wait() } +var ( + errNilServerPrivateKey = errors.New("Server.PrivateKey must be set to a non-nil key") + errServerAlreadyRunning = errors.New("server already running") +) + // Start starts running the server. // Servers can not be re-used after stopping. func (srv *Server) Start() (err error) { srv.lock.Lock() defer srv.lock.Unlock() if srv.running { - return errors.New("server already running") + return errServerAlreadyRunning } srv.running = true log.Info("Starting P2P networking") // static fields if srv.PrivateKey == nil { - return fmt.Errorf("Server.PrivateKey must be set to a non-nil key") + return errNilServerPrivateKey } if srv.newTransport == nil { srv.newTransport = newRLPX diff --git a/rlp/encode.go b/rlp/encode.go index 44592c2f53..4276bd18d8 100644 --- a/rlp/encode.go +++ b/rlp/encode.go @@ -17,6 +17,7 @@ package rlp import ( + "errors" "fmt" "io" "math/big" @@ -428,9 +429,13 @@ func writeBigIntNoPtr(val reflect.Value, w *encbuf) error { return writeBigInt(&i, w) } +var ( + errRLPEncodeNegativeBigInt = errors.New("rlp: cannot encode negative *big.Int") +) + func writeBigInt(i *big.Int, w *encbuf) error { if cmp := i.Cmp(big0); cmp == -1 { - return fmt.Errorf("rlp: cannot encode negative *big.Int") + return errRLPEncodeNegativeBigInt } else if cmp == 0 { w.str = append(w.str, 0x80) } else { diff --git a/rpc/json.go b/rpc/json.go index 2e7fd599e2..76346fab7f 100644 --- a/rpc/json.go +++ b/rpc/json.go @@ -19,6 +19,7 @@ package rpc import ( "bytes" "encoding/json" + "errors" "fmt" "io" "reflect" @@ -134,11 +135,16 @@ func (c *jsonCodec) ReadRequestHeaders() ([]rpcRequest, bool, Error) { return parseRequest(incomingMsg) } +var ( + errMissingRequestID = errors.New("missing request id") + errInvalidRequestID = errors.New("invalid request id") +) + // checkReqId returns an error when the given reqId isn't valid for RPC method calls. // valid id's are strings, numbers or null func checkReqId(reqId json.RawMessage) error { if len(reqId) == 0 { - return fmt.Errorf("missing request id") + return errMissingRequestID } if _, err := strconv.ParseFloat(string(reqId), 64); err == nil { return nil @@ -147,7 +153,7 @@ func checkReqId(reqId json.RawMessage) error { if err := json.Unmarshal(reqId, &str); err == nil { return nil } - return fmt.Errorf("invalid request id") + return errInvalidRequestID } // parseRequest will parse a single request from the given RawMessage. It will return diff --git a/rpc/types.go b/rpc/types.go index f2375604ed..26790e3ab5 100644 --- a/rpc/types.go +++ b/rpc/types.go @@ -17,7 +17,7 @@ package rpc import ( - "fmt" + "errors" "math" "reflect" "strings" @@ -124,6 +124,10 @@ const ( EarliestBlockNumber = BlockNumber(0) ) +var ( + errBlockNumberTooHigh = errors.New("Blocknumber too high") +) + // UnmarshalJSON parses the given JSON fragment into a BlockNumber. It supports: // - "latest", "earliest" or "pending" as string arguments // - the block number @@ -153,7 +157,7 @@ func (bn *BlockNumber) UnmarshalJSON(data []byte) error { return err } if blckNum > math.MaxInt64 { - return fmt.Errorf("Blocknumber too high") + return errBlockNumberTooHigh } *bn = BlockNumber(blckNum) diff --git a/swarm/api/filesystem.go b/swarm/api/filesystem.go index f5dc90e2e5..2ce51a19fe 100644 --- a/swarm/api/filesystem.go +++ b/swarm/api/filesystem.go @@ -18,6 +18,7 @@ package api import ( "bufio" + "errors" "fmt" "io" "net/http" @@ -41,6 +42,12 @@ func NewFileSystem(api *Api) *FileSystem { return &FileSystem{api} } +var ( + errPathTooShort = errors.New("Path is too short") + errAborted = errors.New("aborted") + errManifestNotFound = errors.New("Manifest not Found") +) + // Upload replicates a local directory as a manifest file and uploads it // using dpa store // TODO: localpath should point to a manifest @@ -69,7 +76,7 @@ func (self *FileSystem) Upload(lpath, index string) (string, error) { err = filepath.Walk(localpath, func(path string, info os.FileInfo, err error) error { if (err == nil) && !info.IsDir() { if len(path) <= start { - return fmt.Errorf("Path is too short") + return errPathTooShort } if path[:start] != localpath { return fmt.Errorf("Path prefix of '%s' does not match localpath '%s'", path, localpath) @@ -86,7 +93,7 @@ func (self *FileSystem) Upload(lpath, index string) (string, error) { dir := filepath.Dir(localpath) start = len(dir) if len(localpath) <= start { - return "", fmt.Errorf("Path is too short") + return "", errPathTooShort } if localpath[:start] != dir { return "", fmt.Errorf("Path prefix of '%s' does not match dir '%s'", localpath, dir) @@ -240,7 +247,7 @@ func (self *FileSystem) Download(bzzpath, localpath string) error { case done <- true: wg.Add(1) case <-quitC: - return fmt.Errorf("aborted") + return errAborted } go func(i int, entry *downloadListEntry) { defer wg.Done() @@ -263,7 +270,7 @@ func (self *FileSystem) Download(bzzpath, localpath string) error { case err = <-errC: return err case <-quitC: - return fmt.Errorf("aborted") + return errAborted } } diff --git a/swarm/api/manifest.go b/swarm/api/manifest.go index 90f287677b..5e748a01d5 100644 --- a/swarm/api/manifest.go +++ b/swarm/api/manifest.go @@ -193,7 +193,7 @@ func readManifest(manifestReader storage.LazySectionReader, hash storage.Key, dp size, err := manifestReader.Size(quitC) if err != nil { // size == 0 // can't determine size means we don't have the root chunk - err = fmt.Errorf("Manifest not Found") + err = errManifestNotFound return } manifestData := make([]byte, size) @@ -379,7 +379,7 @@ func (self *manifestTrie) listWithPrefixInt(prefix, rp string, quitC chan bool, for i := start; i <= stop; i++ { select { case <-quitC: - return fmt.Errorf("aborted") + return errAborted default: } entry := self.entries[i] diff --git a/swarm/fuse/swarmfs_util.go b/swarm/fuse/swarmfs_util.go index d39966c0e3..b71752fe9b 100644 --- a/swarm/fuse/swarmfs_util.go +++ b/swarm/fuse/swarmfs_util.go @@ -20,13 +20,17 @@ package fuse import ( "context" - "fmt" + "errors" "os/exec" "runtime" "github.com/ethereum/go-ethereum/log" ) +var ( + errUnmountUnimplemented = errors.New("unmount: unimplemented") +) + func externalUnmount(mountPoint string) error { ctx, cancel := context.WithTimeout(context.Background(), unmountTimeout) defer cancel() @@ -42,7 +46,7 @@ func externalUnmount(mountPoint string) error { case "linux": return exec.CommandContext(ctx, "fusermount", "-u", mountPoint).Run() default: - return fmt.Errorf("unmount: unimplemented") + return errUnmountUnimplemented } } diff --git a/swarm/network/hive.go b/swarm/network/hive.go index 70652c4509..7b1eb08de5 100644 --- a/swarm/network/hive.go +++ b/swarm/network/hive.go @@ -17,6 +17,7 @@ package network import ( + "errors" "fmt" "math/rand" "path/filepath" @@ -317,12 +318,16 @@ func (self *peer) LastActive() time.Time { return self.lastActive } +var ( + errInvalidType = errors.New("invalid type") +) + // reads the serialised form of sync state persisted as the 'Meta' attribute // and sets the decoded syncState on the online node func loadSync(record *kademlia.NodeRecord, node kademlia.Node) error { p, ok := node.(*peer) if !ok { - return fmt.Errorf("invalid type") + return errInvalidType } if record.Meta == nil { log.Debug(fmt.Sprintf("no sync state for node record %v setting default", record)) diff --git a/swarm/network/kademlia/kademlia.go b/swarm/network/kademlia/kademlia.go index bf976a3e1d..de8ebac36b 100644 --- a/swarm/network/kademlia/kademlia.go +++ b/swarm/network/kademlia/kademlia.go @@ -17,6 +17,7 @@ package kademlia import ( + "errors" "fmt" "sort" "strings" @@ -113,6 +114,10 @@ func (self *Kademlia) DBCount() int { return self.db.count() } +var ( + errBucketFull = errors.New("bucket full") +) + // On is the entry point called when a new nodes is added // unsafe in that node is not checked to be already active node (to be called once) func (self *Kademlia) On(node Node, cb func(*NodeRecord, Node) error) (err error) { @@ -159,7 +164,7 @@ func (self *Kademlia) On(node Node, cb func(*NodeRecord, Node) error) (err error } if replaced == nil { log.Debug(fmt.Sprintf("all peers wanted, PO%03d bucket full", index)) - return fmt.Errorf("bucket full") + return errBucketFull } log.Debug(fmt.Sprintf("node %v replaced by %v (idle for %v > %v)", replaced, node, idle, self.MaxIdleInterval)) replaced.Drop() diff --git a/swarm/network/protocol.go b/swarm/network/protocol.go index d013b3109b..d23cdfa008 100644 --- a/swarm/network/protocol.go +++ b/swarm/network/protocol.go @@ -186,6 +186,11 @@ func (self *bzz) Drop() { self.peer.Disconnect(p2p.DiscSubprotocolError) } +var ( + errProtocolHandlerNilReqKey = errors.New("protocol handler: req.Key == nil || req.Timeout == nil") + errNetworkWriteBlocked = errors.New("network write blocked") +) + // one cycle of the main forever loop that handles and dispatches incoming messages func (self *bzz) handle() error { msg, err := self.rw.ReadMsg() @@ -233,7 +238,7 @@ func (self *bzz) handle() error { if req.isLookup() { log.Trace(fmt.Sprintf("self lookup for %v: responding with peers only...", req.from)) } else if req.Key == nil { - return fmt.Errorf("protocol handler: req.Key == nil || req.Timeout == nil") + return errProtocolHandlerNilReqKey } else { // swap accounting is done within netStore self.storage.HandleRetrieveRequestMsg(&req, &peer{bzz: self}) @@ -502,7 +507,7 @@ func (self *bzz) peers(req *peersMsgData) error { func (self *bzz) send(msg uint64, data interface{}) error { if self.hive.blockWrite { - return fmt.Errorf("network write blocked") + return errNetworkWriteBlocked } log.Trace(fmt.Sprintf("-> %v: %v (%T) to %v", msg, data, data, self)) err := p2p.Send(self.rw, msg, data) diff --git a/swarm/network/syncer.go b/swarm/network/syncer.go index 20129c2a81..fafe989cae 100644 --- a/swarm/network/syncer.go +++ b/swarm/network/syncer.go @@ -19,6 +19,7 @@ package network import ( "encoding/binary" "encoding/json" + "errors" "fmt" "path/filepath" @@ -231,13 +232,17 @@ func encodeSync(state *syncState) (*json.RawMessage, error) { return &meta, nil } +var ( + errDecodeNilSyncState = errors.New("unable to deserialise sync state from ") +) + func decodeSync(meta *json.RawMessage) (*syncState, error) { if meta == nil { - return nil, fmt.Errorf("unable to deserialise sync state from ") + return nil, errDecodeNilSyncState } data := []byte(*(meta)) if len(data) == 0 { - return nil, fmt.Errorf("unable to deserialise sync state from ") + return nil, errDecodeNilSyncState } state := &syncState{DbSyncState: &storage.DbSyncState{}} err := json.Unmarshal(data, state) diff --git a/swarm/storage/dbstore.go b/swarm/storage/dbstore.go index 0761130846..3d7c4b0490 100644 --- a/swarm/storage/dbstore.go +++ b/swarm/storage/dbstore.go @@ -27,6 +27,7 @@ import ( "bytes" "encoding/binary" "encoding/hex" + "errors" "fmt" "io" "io/ioutil" @@ -555,10 +556,14 @@ type dbSyncIterator struct { DbSyncState } +var ( + errNoEntriesFound = errors.New("no entries found") +) + // initialises a sync iterator from a syncToken (passed in with the handshake) func (self *DbStore) NewSyncIterator(state DbSyncState) (si *dbSyncIterator, err error) { if state.First > state.Last { - return nil, fmt.Errorf("no entries found") + return nil, errNoEntriesFound } si = &dbSyncIterator{ it: self.db.NewIterator(), diff --git a/swarm/swarm.go b/swarm/swarm.go index 8304908433..f71d85640a 100644 --- a/swarm/swarm.go +++ b/swarm/swarm.go @@ -20,6 +20,7 @@ import ( "bytes" "context" "crypto/ecdsa" + "errors" "fmt" "net" @@ -74,14 +75,19 @@ func (self *Swarm) API() *SwarmAPI { } } +var ( + errEmptyPublicKey = errors.New("empty public key") + errEmptyBzzKey = errors.New("empty bzz key") +) + // creates a new swarm service instance // implements node.Service func NewSwarm(ctx *node.ServiceContext, backend chequebook.Backend, ensClient *ethclient.Client, config *api.Config, swapEnabled, syncEnabled bool, cors string) (self *Swarm, err error) { if bytes.Equal(common.FromHex(config.PublicKey), storage.ZeroKey) { - return nil, fmt.Errorf("empty public key") + return nil, errEmptyPublicKey } if bytes.Equal(common.FromHex(config.BzzKey), storage.ZeroKey) { - return nil, fmt.Errorf("empty bzz key") + return nil, errEmptyBzzKey } self = &Swarm{ diff --git a/whisper/whisperv2/api.go b/whisper/whisperv2/api.go index 5c6d170959..e1fca53db6 100644 --- a/whisper/whisperv2/api.go +++ b/whisper/whisperv2/api.go @@ -18,6 +18,7 @@ package whisperv2 import ( "encoding/json" + "errors" "fmt" "sync" "time" @@ -243,6 +244,12 @@ func (args *PostArgs) UnmarshalJSON(data []byte) (err error) { return nil } +var ( + errToNotAString = errors.New("to is not a string") + errFromNotAString = errors.New("from is not a string") + errTopicsNotArray = errors.New("topics is not an array") +) + // UnmarshalJSON implements the json.Unmarshaler interface, invoked to convert a // JSON message blob into a WhisperFilterArgs structure. func (args *NewFilterArgs) UnmarshalJSON(b []byte) (err error) { @@ -262,7 +269,7 @@ func (args *NewFilterArgs) UnmarshalJSON(b []byte) (err error) { } else { argstr, ok := obj.To.(string) if !ok { - return fmt.Errorf("to is not a string") + return errToNotAString } args.To = argstr } @@ -271,7 +278,7 @@ func (args *NewFilterArgs) UnmarshalJSON(b []byte) (err error) { } else { argstr, ok := obj.From.(string) if !ok { - return fmt.Errorf("from is not a string") + return errFromNotAString } args.From = argstr } @@ -280,7 +287,7 @@ func (args *NewFilterArgs) UnmarshalJSON(b []byte) (err error) { // Make sure we have an actual topic array list, ok := obj.Topics.([]interface{}) if !ok { - return fmt.Errorf("topics is not an array") + return errTopicsNotArray } // Iterate over each topic and handle nil, string or array topics := make([][]string, len(list)) diff --git a/whisper/whisperv2/envelope.go b/whisper/whisperv2/envelope.go index 9f1c682040..345fef132e 100644 --- a/whisper/whisperv2/envelope.go +++ b/whisper/whisperv2/envelope.go @@ -22,6 +22,7 @@ package whisperv2 import ( "crypto/ecdsa" "encoding/binary" + "errors" "fmt" "math/big" "time" @@ -84,6 +85,10 @@ func (self *Envelope) rlpWithoutNonce() []byte { return enc } +var ( + errUnableToOpenEnvelope = errors.New("unable to open envelope. First bit set but len(data) < len(signature)") +) + // Open extracts the message contained within a potentially encrypted envelope. func (self *Envelope) Open(key *ecdsa.PrivateKey) (msg *Message, err error) { // Split open the payload into a message construct @@ -99,7 +104,7 @@ func (self *Envelope) Open(key *ecdsa.PrivateKey) (msg *Message, err error) { if message.Flags&signatureFlag == signatureFlag { if len(data) < signatureLength { - return nil, fmt.Errorf("unable to open envelope. First bit set but len(data) < len(signature)") + return nil, errUnableToOpenEnvelope } message.Signature, data = data[:signatureLength], data[signatureLength:] } diff --git a/whisper/whisperv2/main.go b/whisper/whisperv2/main.go index be41604890..6670790b41 100644 --- a/whisper/whisperv2/main.go +++ b/whisper/whisperv2/main.go @@ -22,6 +22,7 @@ package main import ( + "errors" "fmt" "log" "os" @@ -70,6 +71,8 @@ func main() { } } +var errMsgRecvTimedout = errors.New("failed to receive message in time") + // SendSelf wraps a payload into a Whisper envelope and forwards it to itself. func selfSend(shh *whisper.Whisper, payload []byte) error { ok := make(chan struct{}) @@ -100,7 +103,7 @@ func selfSend(shh *whisper.Whisper, payload []byte) error { select { case <-ok: case <-time.After(time.Second): - return fmt.Errorf("failed to receive message in time") + return errMsgRecvTimedout } return nil } diff --git a/whisper/whisperv5/api.go b/whisper/whisperv5/api.go index 5b84b99eb4..77bc7bdba5 100644 --- a/whisper/whisperv5/api.go +++ b/whisper/whisperv5/api.go @@ -104,7 +104,7 @@ func (api *PublicWhisperAPI) Info(ctx context.Context) Info { stats := api.w.Stats() return Info{ Memory: stats.memoryUsed, - Messages: len(api.w.messageQueue) + len(api.w.p2pMsgQueue), + Messages: len(api.w.messageQueue) + len(api.w.p2pMsgQueue), MinPow: api.w.MinPow(), MaxMessageSize: api.w.MaxMessageSize(), } @@ -489,6 +489,10 @@ func toMessage(messages []*ReceivedMessage) []*Message { return msgs } +var ( + errFilterNotFound = errors.New("filter not found") +) + // GetFilterMessages returns the messages that match the filter criteria and // are received between the last poll and now. func (api *PublicWhisperAPI) GetFilterMessages(id string) ([]*Message, error) { @@ -496,7 +500,7 @@ func (api *PublicWhisperAPI) GetFilterMessages(id string) ([]*Message, error) { f := api.w.GetFilter(id) if f == nil { api.mu.Unlock() - return nil, fmt.Errorf("filter not found") + return nil, errFilterNotFound } api.lastUsed[id] = time.Now() api.mu.Unlock() diff --git a/whisper/whisperv5/filter.go b/whisper/whisperv5/filter.go index d571160d7f..77bbb27845 100644 --- a/whisper/whisperv5/filter.go +++ b/whisper/whisperv5/filter.go @@ -65,7 +65,7 @@ func (fs *Filters) Install(watcher *Filter) (string, error) { defer fs.mutex.Unlock() if fs.watchers[id] != nil { - return "", fmt.Errorf("failed to generate unique ID") + return "", errFailedToGenerateUniqueID } fs.watchers[id] = watcher diff --git a/whisper/whisperv5/whisper.go b/whisper/whisperv5/whisper.go index d09246f699..33cbe0126b 100644 --- a/whisper/whisperv5/whisper.go +++ b/whisper/whisperv5/whisper.go @@ -236,6 +236,22 @@ func (w *Whisper) SendP2PDirect(peer *Peer, envelope *Envelope) error { return p2p.Send(peer.ws, p2pCode, envelope) } +var ( + errInvalidID = errors.New("invalid id") + errVeryOldMessage = errors.New("very old message") + errFailedToGenerateUniqueID = errors.New("failed to generate unique ID") + errFailedToGenerateValidKey = errors.New("failed to generate valid key") + errFailedToAddEnvelope = errors.New("failed to add envelope") + errNonExistentKeyID = errors.New("non-existent key ID") + errUnsubscribeInvalidID = errors.New("Unsubscribe: Invalid ID") + errInvalidP2PRequest = errors.New("invalid p2p request") + errInvalidDirectMessage = errors.New("invalid direct message") + errGenRandomIDRandomData = errors.New("error in generateRandomID: crypto/rand failed to generate random data") + + errGenSymKeyRandomData = errors.New("error in GenerateSymKey: crypto/rand failed to generate random data") + errCriticalFailedToGenerateUniqueID = errors.New("critical error: failed to generate unique ID") +) + // NewKeyPair generates a new cryptographic identity for the client, and injects // it into the known identities for message decryption. Returns ID of the new key pair. func (w *Whisper) NewKeyPair() (string, error) { @@ -247,7 +263,7 @@ func (w *Whisper) NewKeyPair() (string, error) { return "", err } if !validatePrivateKey(key) { - return "", fmt.Errorf("failed to generate valid key") + return "", errFailedToGenerateValidKey } id, err := GenerateRandomID() @@ -259,7 +275,7 @@ func (w *Whisper) NewKeyPair() (string, error) { defer w.keyMu.Unlock() if w.privateKeys[id] != nil { - return "", fmt.Errorf("failed to generate unique ID") + return "", errFailedToGenerateUniqueID } w.privateKeys[id] = key return id, nil @@ -305,7 +321,7 @@ func (w *Whisper) GetPrivateKey(id string) (*ecdsa.PrivateKey, error) { defer w.keyMu.RUnlock() key := w.privateKeys[id] if key == nil { - return nil, fmt.Errorf("invalid id") + return nil, errInvalidID } return key, nil } @@ -318,7 +334,7 @@ func (w *Whisper) GenerateSymKey() (string, error) { if err != nil { return "", err } else if !validateSymmetricKey(key) { - return "", fmt.Errorf("error in GenerateSymKey: crypto/rand failed to generate random data") + return "", errGenSymKeyRandomData } id, err := GenerateRandomID() @@ -330,7 +346,7 @@ func (w *Whisper) GenerateSymKey() (string, error) { defer w.keyMu.Unlock() if w.symKeys[id] != nil { - return "", fmt.Errorf("failed to generate unique ID") + return "", errFailedToGenerateUniqueID } w.symKeys[id] = key return id, nil @@ -351,7 +367,7 @@ func (w *Whisper) AddSymKeyDirect(key []byte) (string, error) { defer w.keyMu.Unlock() if w.symKeys[id] != nil { - return "", fmt.Errorf("failed to generate unique ID") + return "", errFailedToGenerateUniqueID } w.symKeys[id] = key return id, nil @@ -364,7 +380,7 @@ func (w *Whisper) AddSymKeyFromPassword(password string) (string, error) { return "", fmt.Errorf("failed to generate ID: %s", err) } if w.HasSymKey(id) { - return "", fmt.Errorf("failed to generate unique ID") + return "", errFailedToGenerateUniqueID } derived, err := deriveKeyMaterial([]byte(password), EnvelopeVersion) @@ -377,7 +393,7 @@ func (w *Whisper) AddSymKeyFromPassword(password string) (string, error) { // double check is necessary, because deriveKeyMaterial() is very slow if w.symKeys[id] != nil { - return "", fmt.Errorf("critical error: failed to generate unique ID") + return "", errCriticalFailedToGenerateUniqueID } w.symKeys[id] = derived return id, nil @@ -409,7 +425,7 @@ func (w *Whisper) GetSymKey(id string) ([]byte, error) { if w.symKeys[id] != nil { return w.symKeys[id], nil } - return nil, fmt.Errorf("non-existent key ID") + return nil, errNonExistentKeyID } // Subscribe installs a new message handler used for filtering, decrypting @@ -427,7 +443,7 @@ func (w *Whisper) GetFilter(id string) *Filter { func (w *Whisper) Unsubscribe(id string) error { ok := w.filters.Uninstall(id) if !ok { - return fmt.Errorf("Unsubscribe: Invalid ID") + return errUnsubscribeInvalidID } return nil } @@ -440,7 +456,7 @@ func (w *Whisper) Send(envelope *Envelope) error { return err } if !ok { - return fmt.Errorf("failed to add envelope") + return errFailedToAddEnvelope } return err } @@ -535,7 +551,7 @@ func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error { var envelope Envelope if err := packet.Decode(&envelope); err != nil { log.Warn("failed to decode direct message, peer will be disconnected", "peer", p.peer.ID(), "err", err) - return errors.New("invalid direct message") + return errInvalidDirectMessage } wh.postEvent(&envelope, true) } @@ -545,7 +561,7 @@ func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error { var request Envelope if err := packet.Decode(&request); err != nil { log.Warn("failed to decode p2p request message, peer will be disconnected", "peer", p.peer.ID(), "err", err) - return errors.New("invalid p2p request") + return errInvalidP2PRequest } wh.mailServer.DeliverMail(p, &request) } @@ -576,7 +592,7 @@ func (wh *Whisper) add(envelope *Envelope) (bool, error) { if envelope.Expiry < now { if envelope.Expiry+SynchAllowance*2 < now { - return false, fmt.Errorf("very old message") + return false, errVeryOldMessage } else { log.Debug("expired envelope dropped", "hash", envelope.Hash().Hex()) return false, nil // drop envelope without error @@ -851,7 +867,7 @@ func GenerateRandomID() (id string, err error) { return "", err } if !validateSymmetricKey(buf) { - return "", fmt.Errorf("error in generateRandomID: crypto/rand failed to generate random data") + return "", errGenRandomIDRandomData } id = common.Bytes2Hex(buf) return id, err