forked from EOSIO/taurus-node
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhelp_text.cpp.in
More file actions
353 lines (303 loc) · 20.1 KB
/
help_text.cpp.in
File metadata and controls
353 lines (303 loc) · 20.1 KB
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
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
#include "help_text.hpp"
#include <regex>
#include <fc/io/json.hpp>
#include <eosio/chain/exceptions.hpp>
#if !defined(_)
#define _(str) str
#endif
using namespace eosio::chain;
const char* transaction_help_text_header = _("An error occurred while submitting the transaction for this command!");
const char* duplicate_transaction_help_text = _(R"text(The transaction is a duplicate of one already pushed to the producers. If this
is an intentionally repeated transaction there are a few ways to resolve the
issue:
- wait for the next block
- combine duplicate transactions into a single transaction
- adjust the expiration time using the `--expiration <milliseconds>` option
- use the `--force-unique` option to add additional nonce data
Please note, this will consume more bandwidth than the base transaction )text");
const char* missing_perms_help_text = _(R"text(The transaction requires permissions that were not granted by the transaction.
Missing permission from:
- {1}
Please use the `-p,--permissions` option to add the missing accounts!
Note: you will need an unlocked wallet that can authorized these permissions.)text");
const char* missing_sigs_help_text = _(R"text(The transaction requires permissions that could not be authorized by the wallet.
Missing authrizations:
- {1}@{2}
Please make sure the proper keys are imported into an unlocked wallet and try again!)text");
const char* missing_scope_help_text = _(R"text(The transaction requires scopes that were not listed by the transaction.
Missing scope(s):
- {1}
Please use the `-S,--scope` option to add the missing accounts!)text");
const char* tx_unknown_account_help_text = _("The transaction references an account which does not exist.");
const char* unknown_account_help_text = _(R"text(Unknown accounts:
- {1}
Please check the account names and try again!)text");
const char* missing_abi_help_text = _(R"text(The ABI for action "{2}" on code account "{1}" is unknown.
The payload cannot be automatically serialized.
You can push an arbitrary transaction using the 'push action' subcommand)text");
const char* unknown_wallet_help_text = _("Unable to find a wallet named \"{1}\", are you sure you typed the name correctly?");
const char* bad_wallet_password_help_text = _("Invalid password for wallet named \"{1}\"");
const char* locked_wallet_help_text = _("The wallet named \"{1}\" is locked. Please unlock it and try again.");
const char* duplicate_key_import_help_text = _("This key is already imported into the wallet named \"{1}\".");
const char* unknown_abi_table_help_text = _(R"text(The ABI for the code on account "{1}" does not specify table "{2}".
Please check the account and table name, and verify that the account has the expected code using:
@CLI_CLIENT_EXECUTABLE_NAME@ get code {1})text");
const char* unknown_abi_kv_table_help_text = _(R"text(The ABI for the code on account "{1}" does not specify kv_table "{2}".
Please check the account and kv_table name, and verify that the account has the expected code using:
@CLI_CLIENT_EXECUTABLE_NAME@ get code {1})text");
const char* failed_to_find_transaction_text = _("Failed to fetch information for transaction: \033[1m{1}\033[0m from the history plugin\n\n"
"\033[32mIf you know the block number which included this transaction you providing it with the \033[2m--block-hint\033[22m option may help\033[0m");
const char* failed_to_find_transaction_with_block_text = _("Failed to fetch information for transaction: \033[1m{1}\033[0m from the history plugin and the transaction was not present in block \033[1m{2}\033[0m\n");
const char* history_plugin_advice_text = _("\033[32mPlease ensure that the \033[2meosio::history_plugin\033[22m is enabled on the RPC node you are connecting to and that an account involved in this transaction was configured in the \033[2mfilter-on\033[22m setting.\033[0m\n");
const std::vector<std::pair<const char*, std::vector<const char *>>> error_help_text {
{"Error\n: 3030011", {transaction_help_text_header, duplicate_transaction_help_text}},
{"Error\n: 3030001[^\\x00]*\\{\"acct\":\"([^\"]*)\"\\}", {transaction_help_text_header, missing_perms_help_text}},
{"Error\n: 3030002[^\\x00]*Transaction declares authority.*account\":\"([^\"]*)\",\"permission\":\"([^\"]*)\"", {transaction_help_text_header, missing_sigs_help_text}},
{"Error\n: 3030008[^\\x00]*\\{\"scope\":\"([^\"]*)\"\\}", {transaction_help_text_header, missing_scope_help_text}},
{"Account not found: ([\\S]*)", {transaction_help_text_header, tx_unknown_account_help_text, unknown_account_help_text}},
{"Error\n: 303", {transaction_help_text_header}},
{"unknown key[^\\x00]*abi_json_to_bin.*code\":\"([^\"]*)\".*action\":\"([^\"]*)\"", {missing_abi_help_text}},
{"unknown key[^\\x00]*chain/get_code.*name\":\"([^\"]*)\"", {unknown_account_help_text}},
{"Unable to open file[^\\x00]*wallet/open.*postdata\":\"([^\"]*)\"", {unknown_wallet_help_text}},
{"AES error[^\\x00]*wallet/unlock.*postdata\":\\[\"([^\"]*)\"", {bad_wallet_password_help_text}},
{"Wallet is locked: ([\\S]*)", {locked_wallet_help_text}},
{"Key already in wallet[^\\x00]*wallet/import_key.*postdata\":\\[\"([^\"]*)\"", {duplicate_key_import_help_text}},
{"ABI does not define table[^\\x00]*get_table_rows.*code\":\"([^\"]*)\",\"table\":\"([^\"]*)\"", {unknown_abi_table_help_text}},
{"ABI does not define kv_table[^\\x00]*get_kv_table_rows.*code\":\"([^\"]*)\",\"kv_table\":\"([^\"]*)\"", {unknown_abi_kv_table_help_text}},
{"Transaction ([^ ]{8})[^ ]* not found in history and no block hint was given", {failed_to_find_transaction_text, history_plugin_advice_text}},
{"Transaction ([^ ]{8})[^ ]* not found in history or in block number ([0-9]*)", {failed_to_find_transaction_with_block_text, history_plugin_advice_text}},
};
const char* error_advice_name_type_exception = R"=====(Name should be less than 13 characters and only contains the following symbol .12345abcdefghijklmnopqrstuvwxyz)=====";
const char* error_advice_public_key_type_exception = R"=====(Public key should be encoded in base58 and starts with EOS prefix)=====";
const char* error_advice_private_key_type_exception = R"=====(Private key should be encoded in base58 WIF)=====";
const char* error_advice_authority_type_exception = R"=====(Ensure that your authority JSON is valid follows the following format!
{
"threshold": <INTEGER [1-2^32): the threshold that must be met to satisfy this authority>,
"keys": [ <keys must be alpha-numerically sorted by their string representations and unique>
...
{
"key": <STRING: EOS.IO compatible Public Key>,
"weight": <INTEGER [1-2^16): a signature from this key contributes this to satisfying the threshold>
}
...
],
"accounts": [ <accounts must be alpha-numerically sorted by their permission (actor, then permission) and unique>
...
{
"permission": {
"actor": <STRING: account name of the delegated signer>,
"permission": <STRING: permission level on the account that must be satisfied>,
},
"weight": <INTEGER [1-2^16): satisfying the delegation contributes this to satisfying the threshold>
}
...
],
"waits": [ <waits must be sorted by wait_sec, largest first, and be unique>
...
{
"wait_sec": <INTEGER [1-2^32): seconds of delay which qualifies as passing this wait>
"weight": <INTEGER [1-2^16): satisfying the delay contributes this to satisfying the threshold>
}
...
]
}
)=====";
const char* error_advice_action_type_exception = R"=====(Ensure that your action JSON follows the contract's abi!)=====";
const char* error_advice_transaction_type_exception = R"=====(Ensure that your transaction JSON follows the right transaction format!)=====";
const char* error_advice_abi_type_exception = R"=====(Ensure that your abi JSON follows the following format!
{
"types" : [{ "new_type_name":"type_name", "type":"type_name" }],
"structs" : [{ "name":"type_name", "base":"type_name", "fields": [{ "name":"field_name", "type": "type_name" }] }],
"actions" : [{ "name":"action_name","type":"type_name"}],
"tables" : [{
"name":"table_name",
"index_type":"type_name",
"key_names":[ "field_name" ],
"key_types":[ "type_name" ],
"type":"type_name" "
}],
"ricardian_clauses": [{ "id": "string", "body": "string" }]
}
e.g.
{
"types" : [{ "new_type_name":"account_name", "type":"name" }],
"structs" : [
{ "name":"foo", "base":"", "fields": [{ "name":"by", "type": "account_name" }] },
{ "name":"foobar", "base":"", "fields": [{ "name":"by", "type": "account_name" }] }
],
"actions" : [{ "name":"foo","type":"foo"}],
"tables" : [{
"name":"foobar_table",
"index_type":"i64",
"key_names":[ "by" ],
"key_types":[ "account_name" ],
"type":"foobar"
}],
"ricardian_clauses": [{ "id": "foo", "body": "bar" }]
})=====";
const char* error_advice_block_id_type_exception = "Ensure that the block ID is a SHA-256 hexadecimal string!";
const char* error_advice_transaction_id_type_exception = "Ensure that the transaction ID is a SHA-256 hexadecimal string!";
const char* error_advice_packed_transaction_type_exception = R"=====(Ensure that your packed transaction JSON follows the following format!
{
"signatures" : [ "signature" ],
"compression" : enum("none", "zlib"),
"packed_context_free_data" : "bytes",
"packed_trx" : "bytes";
}
e.g.
{
"signatures" : [ "SIG_K1_Jze4m1ZHQ4UjuHpBcX6uHPN4Xyggv52raQMTBZJghzDLepaPcSGCNYTxaP2NiaF4yRF5RaYwqsQYAwBwFtfuTJr34Z5GJX" ],
"compression" : "none",
"packed_context_free_data" : "6c36a25a00002602626c5e7f0000000000010000001e4d75af460000000000a53176010000000000ea305500000000a8ed3232180000001e4d75af4680969800000000000443555200000000",
"packed_trx" : "6c36a25a00002602626c5e7f0000000000010000001e4d75af460000000000a53176010000000000ea305500000000a8ed3232180000001e4d75af4680969800000000000443555200000000"
})=====";
const char* error_advice_transaction_exception = "Ensure that your transaction satisfy the contract's constraint!";
const char* error_advice_expired_tx_exception = "Please increase the expiration time of your transaction!";
const char* error_advice_tx_exp_too_far_exception = "Please decrease the expiration time of your transaction!";
const char* error_advice_invalid_ref_block_exception = "Ensure that the reference block exist in the blockchain!";
const char* error_advice_tx_duplicate = "You can try embedding eosio nonce action inside your transaction to ensure uniqueness.";
const char* error_advice_invalid_action_args_exception = R"=====(Ensure that your arguments follow the contract abi!
You can check the contract's abi by using '@CLI_CLIENT_EXECUTABLE_NAME@ get code' command.)=====";
const char* error_advice_permission_query_exception = "Most likely, the given account/ permission doesn't exist in the blockchain.";
const char* error_advice_account_query_exception = "Most likely, the given account doesn't exist in the blockchain.";
const char* error_advice_contract_table_query_exception = "Most likely, the given table doesn't exist in the blockchain.";
const char* error_advice_contract_query_exception = "Most likely, the given contract doesn't exist in the blockchain.";
const char* error_advice_tx_irrelevant_sig = "Please remove the unnecessary signature from your transaction!";
const char* error_advice_unsatisfied_authorization = "Ensure that you have the related private keys inside your wallet and your wallet is unlocked.";
const char* error_advice_missing_auth_exception = R"=====(Ensure that you have the related authority inside your transaction!;
If you are currently using '@CLI_CLIENT_EXECUTABLE_NAME@ push action' command, try to add the relevant authority using -p option.)=====";
const char* error_advice_irrelevant_auth_exception = "Please remove the unnecessary authority from your action!";
const char* error_advice_missing_chain_api_plugin_exception = "Ensure that you have \033[2meosio::chain_api_plugin\033[0m\033[32m added to your node's configuration!";
const char* error_advice_missing_wallet_api_plugin_exception = "Ensure that you have \033[2meosio::wallet_api_plugin\033[0m\033[32m added to your node's configuration!\n"\
"Otherwise specify your wallet location with \033[2m--wallet-url\033[0m\033[32m argument!";
const char* error_advice_missing_history_api_plugin_exception = "Ensure that you have \033[2meosio::history_api_plugin\033[0m\033[32m added to your node's configuration!";
const char* error_advice_missing_net_api_plugin_exception = "Ensure that you have \033[2meosio::net_api_plugin\033[0m\033[32m added to your node's configuration!";
const char* error_advice_wallet_exist_exception = "Try to use different wallet name.";
const char* error_advice_wallet_nonexistent_exception = "Are you sure you typed the wallet name correctly?";
const char* error_advice_wallet_locked_exception = "Ensure that your wallet is unlocked before using it!";
const char* error_advice_wallet_missing_pub_key_exception = "Ensure that you have the relevant private key imported!";
const char* error_advice_wallet_invalid_password_exception = "Are you sure you are using the right password?";
const char* error_advice_wallet_not_available_exception = "Ensure that you have created a wallet and have it open";
const std::map<int64_t, std::string> error_advice = {
{ name_type_exception::code_value, error_advice_name_type_exception },
{ public_key_type_exception::code_value, error_advice_public_key_type_exception },
{ private_key_type_exception::code_value, error_advice_private_key_type_exception },
{ authority_type_exception::code_value, error_advice_authority_type_exception },
{ action_type_exception::code_value, error_advice_action_type_exception },
{ transaction_type_exception::code_value, error_advice_transaction_type_exception },
{ abi_type_exception::code_value, error_advice_abi_type_exception },
{ block_id_type_exception::code_value, error_advice_block_id_type_exception },
{ transaction_id_type_exception::code_value, error_advice_transaction_id_type_exception },
{ packed_transaction_type_exception::code_value, error_advice_packed_transaction_type_exception },
{ transaction_exception::code_value, error_advice_transaction_exception },
{ expired_tx_exception::code_value, error_advice_expired_tx_exception },
{ tx_exp_too_far_exception::code_value, error_advice_tx_exp_too_far_exception },
{ invalid_ref_block_exception::code_value, error_advice_invalid_ref_block_exception },
{ tx_duplicate::code_value, error_advice_tx_duplicate },
{ invalid_action_args_exception::code_value, error_advice_invalid_action_args_exception },
{ permission_query_exception::code_value, error_advice_permission_query_exception },
{ account_query_exception::code_value, error_advice_account_query_exception },
{ contract_table_query_exception::code_value, error_advice_contract_table_query_exception },
{ contract_query_exception::code_value, error_advice_contract_query_exception },
{ tx_irrelevant_sig::code_value, error_advice_tx_irrelevant_sig },
{ unsatisfied_authorization::code_value, error_advice_unsatisfied_authorization },
{ missing_auth_exception::code_value, error_advice_missing_auth_exception },
{ irrelevant_auth_exception::code_value, error_advice_irrelevant_auth_exception },
{ missing_chain_api_plugin_exception::code_value, error_advice_missing_chain_api_plugin_exception },
{ missing_wallet_api_plugin_exception::code_value, error_advice_missing_wallet_api_plugin_exception },
{ missing_history_api_plugin_exception::code_value, error_advice_missing_history_api_plugin_exception },
{ missing_net_api_plugin_exception::code_value, error_advice_missing_net_api_plugin_exception },
{ wallet_exist_exception::code_value, error_advice_wallet_exist_exception },
{ wallet_nonexistent_exception::code_value, error_advice_wallet_nonexistent_exception },
{ wallet_locked_exception::code_value, error_advice_wallet_locked_exception },
{ wallet_missing_pub_key_exception::code_value, error_advice_wallet_missing_pub_key_exception },
{ wallet_invalid_password_exception::code_value, error_advice_wallet_invalid_password_exception },
{ wallet_not_available_exception::code_value, error_advice_wallet_not_available_exception }
};
namespace eosio { namespace client { namespace help {
bool print_recognized_errors(const fc::exception& e, const bool verbose_errors, std::ostream& err) {
// eos recognized error code is from 3000000
// refer to libraries/chain/include/eosio/chain/exceptions.hpp
if (e.code() >= chain_exception::code_value) {
std::string advice, explanation, stack_trace;
// Get advice, if any
const auto advice_itr = error_advice.find(e.code());
if (advice_itr != error_advice.end()) advice = advice_itr->second;
// Get explanation from log, if any
for (auto &log : e.get_log()) {
explanation += log.get_message();
// Check if there's stack trace to be added
if (!log.get_context().get_method().empty() && verbose_errors) {
stack_trace += "\n" +
log.get_context().get_file() + ":" +
fc::to_string(log.get_context().get_line_number()) + " " +
log.get_context().get_method();
}
}
// Append header
if (!explanation.empty()) explanation = std::string("Error Details:") + explanation;
if (!stack_trace.empty()) stack_trace = std::string("Stack Trace:") + stack_trace;
err << "Error " << e.code() << ": " << e.what();
if (!advice.empty()) err << "\n" << advice;
if (!explanation.empty()) err << "\n" << explanation;
if (!stack_trace.empty()) err << "\n" << stack_trace;
err << std::endl;
return true;
}
return false;
}
void output_error_msg(const char* raw_fmt, const std::smatch& smatch, std::ostream& err) {
std::vector<std::string> v;
for (size_t index = 0; index < smatch.size(); index++) {
if (smatch[index].matched)
v.push_back(smatch.str(index));
else
v.push_back("");
}
switch (smatch.size()) {
case 0:
err << fmt::format(raw_fmt) << std::endl;
break;
case 1:
err << fmt::format(raw_fmt, fmt::arg(boost::lexical_cast<std::string>(0).c_str(), v[0])) << std::endl;
break;
case 2:
err << fmt::format(raw_fmt, fmt::arg(boost::lexical_cast<std::string>(0).c_str(), v[0]),
fmt::arg(boost::lexical_cast<std::string>(1).c_str(), v[1])) << std::endl;
break;
case 3:
err << fmt::format(raw_fmt, fmt::arg(boost::lexical_cast<std::string>(0).c_str(), v[0]),
fmt::arg(boost::lexical_cast<std::string>(1).c_str(), v[1]),
fmt::arg(boost::lexical_cast<std::string>(2).c_str(), v[2])) << std::endl;
break;
default:
err << fmt::format(raw_fmt, fmt::arg(boost::lexical_cast<std::string>(0).c_str(), v[0]),
fmt::arg(boost::lexical_cast<std::string>(1).c_str(), v[1]),
fmt::arg(boost::lexical_cast<std::string>(2).c_str(), v[2])) << "..." << std::endl;;
}
}
bool print_help_text(const fc::exception& e, std::ostream& err) {
bool result = false;
// Large input strings to std::regex can cause SIGSEGV, this is a known bug in libstdc++.
// See https://stackoverflow.com/questions/36304204/%D0%A1-regex-segfault-on-long-sequences
auto detail_str = e.to_detail_string();
// 2048 nice round number. Picked for no particular reason. Bug above was reported for 22K+ strings.
if (detail_str.size() > 2048) return result;
try {
for (const auto& candidate : error_help_text) {
auto expr = std::regex {candidate.first};
std::smatch matches;
if (std::regex_search(detail_str, matches, expr)) {
for (const auto& msg: candidate.second) {
output_error_msg(msg, matches, err);
}
result = true;
break;
}
}
} catch (const std::regex_error& e ) {
err << "Error locating help text: " << std::to_string((int64_t)e.code()) << e.what() << std::endl;
}
return result;
}
}}}