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