未验证 提交 1cfd8a69 编写于 作者: W wanderingbort 提交者: GitHub

Merge pull request #1188 from EOSIO/DAWN-512

DAWN-512 - Improve eosioc error message
......@@ -20,6 +20,7 @@ namespace eosio { namespace chain {
FC_DECLARE_DERIVED_EXCEPTION( unlinkable_block_exception, eosio::chain::chain_exception, 3090000, "unlinkable block" )
FC_DECLARE_DERIVED_EXCEPTION( black_swan_exception, eosio::chain::chain_exception, 3100000, "black swan" )
FC_DECLARE_DERIVED_EXCEPTION( unknown_block_exception, eosio::chain::chain_exception, 3110000, "unknown block" )
FC_DECLARE_DERIVED_EXCEPTION( chain_type_exception, eosio::chain::chain_exception, 3120000, "chain type exception" )
FC_DECLARE_DERIVED_EXCEPTION( block_tx_output_exception, eosio::chain::block_validate_exception, 3020001, "transaction outputs in block do not match transaction outputs from applying block" )
FC_DECLARE_DERIVED_EXCEPTION( block_concurrency_exception, eosio::chain::block_validate_exception, 3020002, "block does not guarantee concurrent exection without conflicts" )
......@@ -52,6 +53,13 @@ namespace eosio { namespace chain {
FC_DECLARE_DERIVED_EXCEPTION( pop_empty_chain, eosio::chain::undo_database_exception, 3070001, "there are no blocks to pop" )
FC_DECLARE_DERIVED_EXCEPTION( name_type_exception, eosio::chain::chain_type_exception, 3120001, "Invalid name" )
FC_DECLARE_DERIVED_EXCEPTION( public_key_type_exception, eosio::chain::chain_type_exception, 3120002, "Invalid public key" )
FC_DECLARE_DERIVED_EXCEPTION( authority_type_exception, eosio::chain::chain_type_exception, 3120003, "Invalid authority" )
FC_DECLARE_DERIVED_EXCEPTION( action_type_exception, eosio::chain::chain_type_exception, 3120004, "Invalid action" )
FC_DECLARE_DERIVED_EXCEPTION( transaction_type_exception, eosio::chain::chain_type_exception, 3120005, "Invalid transaction" )
FC_DECLARE_DERIVED_EXCEPTION( abi_type_exception, eosio::chain::chain_type_exception, 3120006, "Invalid ABI" )
#define EOS_RECODE_EXC( cause_type, effect_type ) \
catch( const cause_type& e ) \
......
......@@ -2,15 +2,16 @@
#include <fc/variant.hpp>
#include <boost/algorithm/string.hpp>
#include <fc/exception/exception.hpp>
#include <eosio/chain/exceptions.hpp>
namespace eosio { namespace chain {
void name::set( const char* str ) {
try {
const auto len = strnlen(str,14);
FC_ASSERT( len <= 13 );
EOS_ASSERT( len <= 13, name_type_exception, "Name is longer than 13 characters (${name}) ", ("name",string(str)) );
value = string_to_name(str);
FC_ASSERT( to_string() == string(str), "name not properly normalized", ("name",string(str))("normalized",to_string()) );
EOS_ASSERT( to_string() == string(str), name_type_exception, "Name not properly normalized (name: ${name}, normalized: ${normalized}) ", ("name",string(str))("normalized",to_string()) );
}FC_CAPTURE_AND_RETHROW( (str) ) }
name::operator string()const {
......
......@@ -8,6 +8,15 @@
FC_THROW_EXCEPTION( exc_type, FORMAT, __VA_ARGS__ ); \
FC_MULTILINE_MACRO_END
#define EOS_CAPTURE_AND_RETHROW(exc_type, FORMAT, ... ) \
catch (fc::exception& e) { \
exc_type new_exception(FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ )); \
for (const auto& log: e.get_log()) { \
new_exception.append_log(log); \
} \
throw new_exception; \
}
#define EOS_DECLARE_OP_BASE_EXCEPTIONS( op_name ) \
FC_DECLARE_DERIVED_EXCEPTION( \
......
......@@ -96,9 +96,134 @@ auto smatch_to_variant(const std::smatch& smatch) {
return result;
};
const char* error_advice_3120001 = R"=====(Name should be less than 13 characters and only contains the following symbol .12345abcdefghijklmnopqrstuvwxyz)=====";
const char* error_advice_3120002 = R"=====(Public key should be encoded in base58 and starts with EOS prefix)=====";
const char* error_advice_3120003 = R"=====(Ensure that your authority JSON follows the following format!
{
"threshold":"uint32_t",
"keys":[{ "key":"public_key", "weight":"uint16_t" }],
"accounts":[{
"permission":{ "actor":"account_name", "permission":"permission_name" },
"weight":"uint16_t"
}]
}
e.g.
{
"threshold":"1",
"keys":[{ "key":"EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", "weight":"1" }],
"accounts":[{
"permission":{ "actor":"initb", "permission":"social" },
"weight":"1
}]
})=====";
const char* error_advice_3120004 = R"=====(Ensure that your action JSON follows the contract's abi!)=====";
const char* error_advice_3120005 = R"=====(Ensure that your transaction JSON follows the following format!\n"
{
"ref_block_num":"uint16_t",
"ref_block_prefix":"uint32_t",
"expiration":"YYYY-MM-DDThh:mm",
"region": "uint16_t",
"read_scope":[ "account_name" ],
"write_scope":[ "account_name" ],
"actions":[{
"account":"account_name",
"name":"action_name",
"authorization":[{ "actor":"account_name","permission":"permission_name" }],
"data":"bytes"
}]
}"
e.g.
{
"ref_block_num":"1000",
"ref_block_prefix":"3463702842",
"expiration":"2018-01-23T01:51:05",
"region": "0",
"read_scope":[ "initb", "initc" ],
"write_scope":[ "initb", "initc" ],
"actions":[{
"account":"eosio",
"name":"transfer",
"authorization":[{ "actor":"initb","permission":"active" }],
"data":"000000008093dd74000000000094dd74e80300000000000000"
}]
})=====";
const char* error_advice_3120006 = 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" "
}]
}
e.g.
{
"types" : [{ "new_type_name":"account_name", "type":"name" }],
"structs" : [
{ "name":"foo", "base":"", "fields": [{ "name":"by", "type": "account_name" }] },\n "
{ "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" "
}]
})=====";
const std::map<int64_t, std::string> error_advice = {
{ 3120001, error_advice_3120001 },
{ 3120002, error_advice_3120002 },
{ 3120003, error_advice_3120003 },
{ 3120004, error_advice_3120004 },
{ 3120005, error_advice_3120005 },
{ 3120006, error_advice_3120006 }
};
namespace eosio { namespace client { namespace help {
bool print_recognized_error_code(const fc::exception& e) {
// eos recognized error code is from 3000000 to 3999999
// refer to libraries/chain/include/eosio/chain/exceptions.hpp
if (e.code() >= 3000000 && e.code() <= 3999999) {
std::string advice, explanation;
// 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()) {
// Check if there's a log to display
if (!log.get_format().empty()) {
// Localize the message as needed
explanation += "\n " + localized_with_variant(log.get_format().data(), log.get_data());
}
}
if (!explanation.empty()) explanation = std::string("Error Details:") + explanation;
std::cerr << "\033[31m" << "Error " << e.code() << ": " << e.what() << "\033[0m";
if (!advice.empty()) std::cerr << "\n" << "\033[32m" << advice << "\033[0m";
if (!explanation.empty()) std::cerr << "\n" << "\033[33m" << explanation << "\033[0m" << std::endl;
return true;
}
return false;
}
bool print_help_text(const fc::exception& e) {
// Check if the exception has recognized error code
if (print_recognized_error_code(e)) return true;
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
......
......@@ -34,7 +34,6 @@ Subcommands:
set Set or update blockchain state
transfer Transfer EOS from account to account
wallet Interact with local wallet
benchmark Configure and execute benchmarks
push Push arbitrary transactions to the blockchain
```
......@@ -361,16 +360,20 @@ struct set_account_permission_subcommand {
} else {
authority auth;
if (boost::istarts_with(authorityJsonOrFile, "EOS")) {
auth = authority(public_key_type(authorityJsonOrFile));
try {
auth = authority(public_key_type(authorityJsonOrFile));
} EOS_CAPTURE_AND_RETHROW(public_key_type_exception, "")
} else {
fc::variant parsedAuthority;
if (boost::istarts_with(authorityJsonOrFile, "{")) {
parsedAuthority = fc::json::from_string(authorityJsonOrFile);
} else {
parsedAuthority = fc::json::from_file(authorityJsonOrFile);
}
auth = parsedAuthority.as<authority>();
try {
if (boost::istarts_with(authorityJsonOrFile, "{")) {
parsedAuthority = fc::json::from_string(authorityJsonOrFile);
} else {
parsedAuthority = fc::json::from_file(authorityJsonOrFile);
}
auth = parsedAuthority.as<authority>();
} EOS_CAPTURE_AND_RETHROW(authority_type_exception, "Fail to parse Authority JSON")
}
name parent;
......@@ -478,18 +481,23 @@ int main( int argc, char** argv ) {
// create account
string creator;
string account_name;
string ownerKey;
string activeKey;
string owner_key_str;
string active_key_str;
bool skip_sign = false;
auto createAccount = create->add_subcommand("account", localized("Create a new account on the blockchain"), false);
createAccount->add_option("creator", creator, localized("The name of the account creating the new account"))->required();
createAccount->add_option("name", account_name, localized("The name of the new account"))->required();
createAccount->add_option("OwnerKey", ownerKey, localized("The owner public key for the account"))->required();
createAccount->add_option("ActiveKey", activeKey, localized("The active public key for the account"))->required();
createAccount->add_option("OwnerKey", owner_key_str, localized("The owner public key for the account"))->required();
createAccount->add_option("ActiveKey", active_key_str, localized("The active public key for the account"))->required();
createAccount->add_flag("-s,--skip-signature", skip_sign, localized("Specify that unlocked wallet keys should not be used to sign transaction"));
add_standard_transaction_options(createAccount);
createAccount->set_callback([&] {
create_account(creator, account_name, public_key_type(ownerKey), public_key_type(activeKey), skip_sign);
public_key_type owner_key, active_key;
try {
owner_key = public_key_type(owner_key_str);
active_key = public_key_type(active_key_str);
} EOS_CAPTURE_AND_RETHROW(public_key_type_exception, "Invalid Public Key")
create_account(creator, account_name, owner_key, active_key, skip_sign);
});
// Get subcommand
......@@ -720,7 +728,9 @@ int main( int argc, char** argv ) {
if (abi->count()) {
contracts::setabi handler;
handler.account = account;
handler.abi = fc::json::from_file(abiPath).as<contracts::abi_def>();
try {
handler.abi = fc::json::from_file(abiPath).as<contracts::abi_def>();
} EOS_CAPTURE_AND_RETHROW(abi_type_exception, "Fail to parse ABI JSON")
actions.emplace_back( vector<chain::permission_level>{{account,"active"}}, handler);
}
......@@ -923,10 +933,15 @@ int main( int argc, char** argv ) {
add_standard_transaction_options(actionsSubcommand);
actionsSubcommand->set_callback([&] {
ilog("Converting argument to binary...");
fc::variant action_args_var;
try {
action_args_var = fc::json::from_string(data);
} EOS_CAPTURE_AND_RETHROW(action_type_exception, "Fail to parse action JSON")
auto arg= fc::mutable_variant_object
("code", contract)
("action", action)
("args", fc::json::from_string(data));
("args", action_args_var);
auto result = call(json_to_bin_func, arg);
auto accountPermissions = get_account_permissions(permissions);
......@@ -946,7 +961,11 @@ int main( int argc, char** argv ) {
auto trxSubcommand = push->add_subcommand("transaction", localized("Push an arbitrary JSON transaction"));
trxSubcommand->add_option("transaction", trxJson, localized("The JSON of the transaction to push"))->required();
trxSubcommand->set_callback([&] {
auto trx_result = call(push_txn_func, fc::json::from_string(trxJson));
fc::variant trx_var;
try {
trx_var = fc::json::from_string(trxJson);
} EOS_CAPTURE_AND_RETHROW(transaction_type_exception, "Fail to parse transaction JSON")
auto trx_result = call(push_txn_func, trx_var);
std::cout << fc::json::to_pretty_string(trx_result) << std::endl;
});
......@@ -955,7 +974,11 @@ int main( int argc, char** argv ) {
auto trxsSubcommand = push->add_subcommand("transactions", localized("Push an array of arbitrary JSON transactions"));
trxsSubcommand->add_option("transactions", trxsJson, localized("The JSON array of the transactions to push"))->required();
trxsSubcommand->set_callback([&] {
auto trxs_result = call(push_txn_func, fc::json::from_string(trxsJson));
fc::variant trx_var;
try {
trx_var = fc::json::from_string(trxJson);
} EOS_CAPTURE_AND_RETHROW(transaction_type_exception, "Fail to parse transaction JSON")
auto trxs_result = call(push_txn_func, trx_var);
std::cout << fc::json::to_pretty_string(trxs_result) << std::endl;
});
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册