error.go raw

   1  package waddrmgr
   2  
   3  import (
   4  	"fmt"
   5  	"strconv"
   6  	
   7  	"github.com/p9c/p9/pkg/util/hdkeychain"
   8  )
   9  
  10  // ErrorCode identifies a kind of error.
  11  type ErrorCode int
  12  
  13  // ManagerError provides a single type for errors that can happen during address
  14  // manager operation. It is used to indicate several types of failures including
  15  // errors with caller requests such as invalid accounts or requesting private
  16  // keys against a locked address manager, errors with the database
  17  // (ErrDatabase), errors with key chain derivation (ErrKeyChain), and errors
  18  // related to crypto (ErrCrypto).
  19  //
  20  // The caller can use type assertions to determine if an error is a ManagerError
  21  // and access the ErrorCode field to ascertain the specific reason for the
  22  // failure.
  23  //
  24  // The ErrDatabase, ErrKeyChain, and ErrCrypto error codes will also have the
  25  // Err field set with the underlying error.
  26  type ManagerError struct {
  27  	ErrorCode   ErrorCode // Describes the kind of error
  28  	Description string    // Human readable description of the issue
  29  	Err         error     // Underlying error
  30  }
  31  
  32  // These constants are used to identify a specific ManagerError.
  33  const (
  34  	// ErrDatabase indicates an error with the underlying database. When this error
  35  	// code is set, the Err field of the ManagerError will be set to the underlying
  36  	// error returned from the database.
  37  	ErrDatabase ErrorCode = iota
  38  	// ErrUpgrade indicates the manager needs to be upgraded. This should not happen
  39  	// in practice unless the version number has been increased and there is not yet
  40  	// any code written to upgrade.
  41  	ErrUpgrade
  42  	// ErrKeyChain indicates an error with the key chain typically either due to the
  43  	// inability to create an extended key or deriving a child extended key. When
  44  	// this error code is set, the Err field of the ManagerError will be set to the
  45  	// underlying error.
  46  	ErrKeyChain
  47  	// ErrCrypto indicates an error with the cryptography related operations such as
  48  	// decrypting or encrypting data, parsing an EC public key, or deriving a secret
  49  	// key from a password. When this error code is set, the Err field of the
  50  	// ManagerError will be set to the underlying error.
  51  	ErrCrypto
  52  	// ErrInvalidKeyType indicates an error where an invalid crypto key type has
  53  	// been selected.
  54  	ErrInvalidKeyType
  55  	// ErrNoExist indicates that the specified database does not exist.
  56  	ErrNoExist
  57  	// ErrAlreadyExists indicates that the specified database already exists.
  58  	ErrAlreadyExists
  59  	// ErrCoinTypeTooHigh indicates that the coin type specified in the provided
  60  	// network parameters is higher than the max allowed value as defined by the
  61  	// maxCoinType constant.
  62  	ErrCoinTypeTooHigh
  63  	// ErrAccountNumTooHigh indicates that the specified account number is higher
  64  	// than the max allowed value as defined by the MaxAccountNum constant.
  65  	ErrAccountNumTooHigh
  66  	// ErrLocked indicates that an operation, which requires the account manager to
  67  	// be unlocked, was requested on a locked account manager.
  68  	ErrLocked
  69  	// ErrWatchingOnly indicates that an operation, which requires the account
  70  	// manager to have access to private data, was requested on a watching-only
  71  	// account manager.
  72  	ErrWatchingOnly
  73  	// ErrInvalidAccount indicates that the requested account is not valid.
  74  	ErrInvalidAccount
  75  	// ErrAddressNotFound indicates that the requested address is not known to the
  76  	// account manager.
  77  	ErrAddressNotFound
  78  	// ErrAccountNotFound indicates that the requested account is not known to the
  79  	// account manager.
  80  	ErrAccountNotFound
  81  	// ErrDuplicateAddress indicates an address already exists.
  82  	ErrDuplicateAddress
  83  	// ErrDuplicateAccount indicates an account already exists.
  84  	ErrDuplicateAccount
  85  	// ErrTooManyAddresses indicates that more than the maximum allowed number of
  86  	// addresses per account have been requested.
  87  	ErrTooManyAddresses
  88  	// ErrWrongPassphrase indicates that the specified passphrase is incorrect. This
  89  	// could be for either public or private master keys.
  90  	ErrWrongPassphrase
  91  	// ErrWrongNet indicates that the private key to be imported is not for the the
  92  	// same network the account manager is configured for.
  93  	ErrWrongNet
  94  	// ErrCallBackBreak is used to break from a callback function passed down to the
  95  	// manager.
  96  	ErrCallBackBreak
  97  	// ErrEmptyPassphrase indicates that the private passphrase was refused due to
  98  	// being empty.
  99  	ErrEmptyPassphrase
 100  	// ErrScopeNotFound is returned when a target scope cannot be found within the
 101  	// database.
 102  	ErrScopeNotFound
 103  )
 104  
 105  var (
 106  	// Break is a global err used to signal a break from the callback function by
 107  	// returning an error with the code ErrCallBackBreak
 108  	Break = managerError(ErrCallBackBreak, "callback break", nil)
 109  	// errAcctTooHigh is the common error description used for the
 110  	// ErrAccountNumTooHigh error code.
 111  	errAcctTooHigh = "account number may not exceed " +
 112  		strconv.FormatUint(hdkeychain.HardenedKeyStart-1, 10)
 113  	// errAlreadyExists is the common error description used for the
 114  	// ErrAlreadyExists error code.
 115  	errAlreadyExists = "the specified address manager already exists"
 116  	// errCoinTypeTooHigh is the common error description used for the
 117  	// ErrCoinTypeTooHigh error code.
 118  	errCoinTypeTooHigh = "coin type may not exceed " +
 119  		strconv.FormatUint(hdkeychain.HardenedKeyStart-1, 10)
 120  	// errLocked is the common error description used for the ErrLocked error code.
 121  	errLocked = "address manager is locked"
 122  	// errWatchingOnly is the common error description used for the ErrWatchingOnly
 123  	// error code.
 124  	errWatchingOnly = "address manager is watching-only"
 125  	// Map of ErrorCode values back to their constant names for pretty printing.
 126  	errorCodeStrings = map[ErrorCode]string{
 127  		ErrDatabase:          "ErrDatabase",
 128  		ErrUpgrade:           "ErrUpgrade",
 129  		ErrKeyChain:          "ErrKeyChain",
 130  		ErrCrypto:            "ErrCrypto",
 131  		ErrInvalidKeyType:    "ErrInvalidKeyType",
 132  		ErrNoExist:           "ErrNoExist",
 133  		ErrAlreadyExists:     "ErrAlreadyExists",
 134  		ErrCoinTypeTooHigh:   "ErrCoinTypeTooHigh",
 135  		ErrAccountNumTooHigh: "ErrAccountNumTooHigh",
 136  		ErrLocked:            "ErrLocked",
 137  		ErrWatchingOnly:      "ErrWatchingOnly",
 138  		ErrInvalidAccount:    "ErrInvalidAccount",
 139  		ErrAddressNotFound:   "ErrAddressNotFound",
 140  		ErrAccountNotFound:   "ErrAccountNotFound",
 141  		ErrDuplicateAddress:  "ErrDuplicateAddress",
 142  		ErrDuplicateAccount:  "ErrDuplicateAccount",
 143  		ErrTooManyAddresses:  "ErrTooManyAddresses",
 144  		ErrWrongPassphrase:   "ErrWrongPassphrase",
 145  		ErrWrongNet:          "ErrWrongNet",
 146  		ErrCallBackBreak:     "ErrCallBackBreak",
 147  		ErrEmptyPassphrase:   "ErrEmptyPassphrase",
 148  		ErrScopeNotFound:     "ErrScopeNotFound",
 149  	}
 150  )
 151  
 152  // String returns the ErrorCode as a human-readable name.
 153  func (e ErrorCode) String() string {
 154  	if s := errorCodeStrings[e]; s != "" {
 155  		return s
 156  	}
 157  	return fmt.Sprintf("Unknown ErrorCode (%d)", int(e))
 158  }
 159  
 160  // Error satisfies the error interface and prints human-readable errors.
 161  func (e ManagerError) Error() string {
 162  	if e.Err != nil {
 163  		return e.Description + ": " + e.Err.Error()
 164  	}
 165  	return e.Description
 166  }
 167  
 168  // IsError returns whether the error is a ManagerError with a matching error
 169  // code.
 170  func IsError(e error, code ErrorCode) bool {
 171  	er, ok := e.(ManagerError)
 172  	return ok && er.ErrorCode == code
 173  }
 174  
 175  // managerError creates a ManagerError given a set of arguments.
 176  func managerError(c ErrorCode, desc string, e error) ManagerError {
 177  	return ManagerError{ErrorCode: c, Description: desc, Err: e}
 178  }
 179