/
fioerror.hpp
246 lines (212 loc) · 13.3 KB
/
fioerror.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
/** FioError definitions file
* Description: Contains helper functions to generate appropriately formatted http error messages
* that are returned by the HTTP messaging layer when an assertion test fails.
* @author Phil Mesnier, Adam Androulidakis, Casey Gardiner, Ed Rotthoff
* @file fioerror.hpp
* @license FIO Foundation ( https://github.com/fioprotocol/fio/blob/master/LICENSE ) Dapix
*
* Changes:
*/
#pragma once
namespace fioio {
using namespace std;
/**
* error code definition. Error codes are bitfielded uint64_t values.
* The fields are: An itentifier, 'FIO\0', then http error code and finally a FIO specific error number.
*/
constexpr auto identOffset = 48;
constexpr uint64_t ident =
uint64_t((('F' << 4) | 'I' << 4) | 'O') << identOffset; // to distinguish the error codes generically
constexpr auto httpOffset = 32;
constexpr uint64_t httpDataError = 400LL << httpOffset;
constexpr uint64_t httpInvalidError = 403LL << httpOffset;
constexpr uint64_t httpLocationError = 404LL << httpOffset;
constexpr uint64_t httpMask = 0xfffLL << httpOffset;
constexpr uint64_t ecCodeMask = 0xff;
constexpr auto ErrorDomainAlreadyRegistered = ident | httpDataError | 100; // Domain is already registered
constexpr auto ErrorDomainNotRegistered = ident | httpDataError | 101; // Domain not yet registered
constexpr auto ErrorFioNameAlreadyRegistered = ident | httpDataError | 102; // Fioname is already registered
constexpr auto ErrorFioNameEmpty = ident | httpDataError | 103; // FIO user name is empty
constexpr auto ErrorChainEmpty = ident | httpDataError | 104; // Chain name is empty
constexpr auto ErrorChainAddressEmpty = ident | httpDataError | 105; // Chain address is empty
constexpr auto ErrorChainContainsWhiteSpace = ident | httpDataError | 106; // Chain address contains whitespace
constexpr auto ErrorChainNotSupported = ident | httpDataError | 107; // Chain isn't supported
constexpr auto ErrorFioNameNotRegistered = ident | httpLocationError | 108;
constexpr auto ErrorFioNameNotReg = ident | httpDataError | 127; // Fioname not yet registered
constexpr auto ErrorDomainExpired = ident | httpDataError | 109; // Fioname not yet registered
constexpr auto ErrorPubAddressEmpty = ident | httpDataError | 111; // Public address is empty
constexpr auto ErrorPubKeyEmpty = ident | httpDataError | 112; // Public key is empty
constexpr auto ErrorPubAddressExist = ident | httpDataError | 113; // Public address exists
constexpr auto ErrorSignature = ident | httpInvalidError | 114; // user permission failure
constexpr auto ErrorNotFound = ident | httpLocationError | 115; // cannot locate resource
constexpr auto ErrorInvalidFioNameFormat = ident | httpDataError | 116; // Public address exists
constexpr auto ErrorTransaction = ident | httpInvalidError | 117; // Transaction error
constexpr auto ErrorNoFIONames = ident | httpLocationError | 118; // No FIO Names
constexpr auto ErrorInvalidJsonInput = ident | httpDataError | 119; // invalid json sent for json input
constexpr auto ErrorRequestContextNotFound =
ident | httpDataError | 120; // the specified request context record was not found
constexpr auto ErrorChainAddressNotFound = ident | httpDataError | 121; // Chain address not found
constexpr auto ErrorNoFioRequestsFound = ident | httpLocationError | 122; // no fio requests found
constexpr auto Error400FioNameNotRegistered = ident | httpDataError | 123; // Fioname not yet registered
constexpr auto ErrorPubAddressNotFound = ident | httpLocationError | 124; //Pub Address not found
constexpr auto ErrorDomainNotFound = ident | httpLocationError | 125; // Domain not yet registered
constexpr auto ErrorLowFunds = ident | httpDataError | 126; // Insufficient balance
constexpr auto ErrorEndpointNotFound = ident | httpDataError | 127; // Fee endpoint not found.
constexpr auto ErrorNoEndpoint = ident | httpDataError | 128; // No endpoint specified.
constexpr auto ErrorNoFeesFoundForEndpoint = ident | httpDataError | 129; // No Fees found for endpoint
constexpr auto ErrorMaxFeeExceeded = ident | httpDataError | 130; // max fee exceeded.
constexpr auto InvalidTPID = ident | httpDataError | 131; // max fee exceeded.
constexpr auto ErrorProxyNotFound = ident | httpLocationError | 132;
constexpr auto ErrorPublicKeyExists = ident | httpDataError | 133; // pub key already exists.
constexpr auto ErrorNoFioAddressProducer = ident | httpDataError | 134; // producer does is not fioname
constexpr auto AddressNotProxy = ident | httpDataError | 135; // This address is not a proxy
constexpr auto InvalidAccountOrAction =
ident | httpInvalidError | 136; // Provided account or action is not valid for this endpoint.
constexpr auto ErrorActorNotInFioAccountMap = ident | httpDataError | 137; // Actor not in FIO account map
constexpr auto ErrorTokenCodeInvalid = ident | httpDataError | 138; // token code invalid
constexpr auto ErrorPubKeyValid = ident | httpDataError | 139; //Invalid FIO Public Key (400)
constexpr auto ErrorInvalidMultiplier = ident | httpInvalidError | 140; // invalid fee multiplier
constexpr auto ErrorMaxFeeInvalid = ident | httpDataError | 141; // max fee invalid.
constexpr auto ErrorFeeInvalid = ident | httpDataError | 142; // fee invalid.
constexpr auto ErrorInvalidAmount = ident | httpDataError | 143; // Invalid amount value
constexpr auto ErrorContentLimit = ident | httpDataError | 144; // constexpr auto ErrorInvalidAmount = ident | httpDataError | 143; // Invalid amount value
constexpr auto ErrorPagingInvalid = ident | httpDataError | 145; //Invalid FIO Public Key (400)
constexpr auto ErrorInvalidNumberAddresses = ident | httpDataError | 146; // Invalid number of addresses
constexpr auto ErrorInsufficientUnlockedFunds = ident | httpDataError | 147; // not enough unlocked funds
constexpr auto ErrorNoWork = ident | httpDataError | 148; // no work to perform
constexpr auto ErrorClientKeyNotFound = ident | httpDataError | 149; // Fioname not yet registered (No clientkey)
constexpr auto ErrorTimeViolation = ident | httpDataError | 150;
constexpr auto ErrorNoAuthWaits = ident | httpDataError | 151;
constexpr auto ErrorTransactionTooLarge = ident | httpDataError | 152; // Transaction too large
constexpr auto ErrorRequestStatusInvalid = ident | httpDataError | 153; // the specified request context record was not found
constexpr auto ErrorActorIsSystemAccount = ident | httpDataError | 154; // the specified actor is a FIO system account
constexpr auto ErrorInvalidUnlockPeriods = ident | httpDataError | 155; //Invalid unlock periods.
constexpr auto ErrorInvalidValue = ident | httpDataError | 155; //Invalid value.
constexpr auto ErrorNoGeneralLocksFound = ident | httpLocationError | 156; // no fio requests found
constexpr auto ErrorUnexpectedNumberResults = ident | httpLocationError | 156; // unexpected number of results
constexpr auto ErrorNoFioActionsFound = ident | httpLocationError | 157; // no actions found
constexpr auto ErrorDomainOwner = ident | httpInvalidError | 158;
constexpr auto ErrorRetireQuantity = ident | httpDataError | 159;
constexpr auto ErrorInvalidMemo = ident | httpDataError | 160;
constexpr auto ErrorDomainSaleNotFound = ident | httpInvalidError | 161; // domain not found in domainsales table
//FIP-40
constexpr auto ErrorInvalidPermissionName = ident | httpDataError | 162;
constexpr auto ErrorInvalidPermissionInfo = ident | httpDataError | 163;
constexpr auto ErrorInvalidObjectName = ident | httpDataError | 164;
constexpr auto ErrorInvalidGranteeAccount = ident | httpDataError | 165;
constexpr auto ErrorPermissionExists = ident | httpDataError | 166;
/**
* Helper funtions for detecting rich error messages and extracting bitfielded values
*/
inline bool is_fio_error(uint64_t ec) {
constexpr uint64_t mask = ident | httpMask | ecCodeMask;
return (ec & ident) == ident && (ec & ~mask) == 0;
}
inline uint16_t get_http_result(uint64_t ec) {
return static_cast<uint16_t>((ec & httpMask) >> httpOffset);
}
inline uint64_t get_fio_code(uint64_t ec) {
return ec & ecCodeMask;
};
/**
* Structures used to collect error content and format proper result messages
*/
struct Http_Result {
string type;
string message;
Http_Result(const string &t = "", const string &m = "") : type(t), message(m) {}
};
struct Code_400_Result : public Http_Result {
struct field {
string name = "";
string value = "";
string error = "";
};
vector <field> fields;
// Code_400_Result (const Code_400_field &) default;
Code_400_Result(const string &fname = "", const string &fval = "", const string &ferr = "") :
Http_Result("invalid_input",
"An invalid request was sent in, please check the nested errors for details.") {
add_field({fname, fval, ferr});
}
void add_field(const field &f) {
fields.emplace_back(move(f));
}
string to_json() const {
string json_str = "{\n \"type\": \"" + type +
"\",\n \"message\": \"" + message + "\",\n \"fields\": [\n";
for (auto f = fields.cbegin(); f != fields.cend(); f++) {
if (f != fields.cbegin())json_str += ",\n";
json_str += " {\"name\": \"" + f->name +
"\",\n \"value\": \"" + f->value +
"\",\n \"error\": \"" + f->error + "\"}";
}
json_str += "]\n}\n";
return json_str;
}
};
struct Code_403_Result : public Http_Result {
Code_403_Result(uint64_t code) :
Http_Result("invalid_signature", "Request signature is not valid or this user is not allowed to sign this transaction.") {
if (code == fioio::ErrorTransaction) {
type = "invalid_transaction";
message = "Signed transaction is not valid or is not formatted properly";
}
if (code == fioio::InvalidAccountOrAction) {
type = "invalid_account_or_action";
message = "Provided account or action is not valid for this endpoint";
}
}
string to_json() const {
string json_str = "{\n \"type\": \"" + type +
"\",\n \"message\": \"" + message + "\"\n}\n";
return json_str;
}
};
struct Code_404_Result : public Http_Result {
Code_404_Result(const string &msg) :
Http_Result("", msg) {}
string to_json() const {
string json_str = "{\n \"message\": \"" + message + "\"\n}\n";
return json_str;
}
};
}
/**
* helper macros that hide the string conversion tedium
*/
#if 0
#define FIO_400_THROW(fieldname,fieldvalue,fielderror,code) \
FC_MULTILINE_MACRO_BEGIN \
throw eosio::chain::fio_data_exception(code,fioio::Code_400_Result(fieldname, fieldvalue, fielderror).to_json().c_str()); \
FC_MULTILINE_MACRO_END
#define FIO_403_THROW(code) \
FC_MULTILINE_MACRO_BEGIN \
throw eosio::chain::fio_invalid_exception(code,fioio::Code_403_Result(code).to_json().c_str()); \
FC_MULTILINE_MACRO_END
#define FIO_404_THROW(message,code) \
FC_MULTILINE_MACRO_BEGIN \
throw eosio::chain::fio_location_exception(code,fioio::Code__400_Result(message).to_json().c_str()); \
FC_MULTILINE_MACRO_END
#endif
#define FIO_400_ASSERT(expr, fieldname, fieldvalue, fielderror, code) \
FC_MULTILINE_MACRO_BEGIN \
if( !(expr) ) \
throw eosio::chain::eosio_assert_code_exception(code, "message", fioio::Code_400_Result(fieldname, fieldvalue, fielderror).to_json().c_str()); \
FC_MULTILINE_MACRO_END
#define FIO_403_ASSERT(expr, code) \
FC_MULTILINE_MACRO_BEGIN \
if( !(expr) ) \
{ throw eosio::chain::eosio_assert_code_exception(code, "message", fioio::Code_403_Result(code).to_json().c_str()); } \
FC_MULTILINE_MACRO_END
#define FIO_404_ASSERT(expr, message, code) \
FC_MULTILINE_MACRO_BEGIN \
if( !(expr) ) \
throw eosio::chain::eosio_assert_code_exception(code, "message", fioio::Code_404_Result(message).to_json().c_str()); \
FC_MULTILINE_MACRO_END
#define fio_400_assert(test, fieldname, fieldvalue, fielderror, code) \
eosio_assert_message_code(test, fioio::Code_400_Result(fieldname, fieldvalue, fielderror).to_json().c_str(), code)
#define fio_403_assert(test, code) \
eosio_assert_message_code(test, fioio::Code_403_Result(code).to_json().c_str(), code)
#define fio_404_assert(test, message, code) \
eosio_assert_message_code(test, fioio::Code_404_Result(message).to_json().c_str(), code)