Skip to content

Commit

Permalink
Merge pull request #663 from eosnetworkfoundation/cleos_activate_subc…
Browse files Browse the repository at this point in the history
…ommand

[3.2] cleos: add get supported_protocol_features and system activate subcommands
  • Loading branch information
linh2931 authored Jul 19, 2022
2 parents c31f87a + c9dba88 commit d6c3e25
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 0 deletions.
3 changes: 3 additions & 0 deletions programs/cleos/httpc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,5 +135,8 @@ namespace eosio { namespace client { namespace http {
const string wallet_sign_trx = wallet_func_base + "/sign_transaction";
const string keosd_stop = "/v1/" + string(client::config::key_store_executable_name) + "/stop";

const string producer_func_base = "/v1/producer";
const string producer_get_supported_protocol_features_func = producer_func_base + "/get_supported_protocol_features";

FC_DECLARE_EXCEPTION( connection_exception, 1100000, "Connection Exception" );
}}}
124 changes: 124 additions & 0 deletions programs/cleos/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ Usage: ./cleos create account [OPTIONS] creator name OwnerKey ActiveKey
#include <vector>
#include <regex>
#include <iostream>
#include <locale>
#include <unordered_map>
#include <fc/crypto/hex.hpp>
#include <fc/variant.hpp>
#include <fc/io/datastream.hpp>
Expand Down Expand Up @@ -2247,6 +2249,120 @@ struct closerex_subcommand {
}
};

struct protocol_features_t {
std::string names;
std::unordered_map<std::string, std::string> digests {}; // from name to digest
};

protocol_features_t get_supported_protocol_features() {
protocol_features_t results;

auto prot_features = call(producer_get_supported_protocol_features_func, fc::mutable_variant_object("exclude_disabled", true)
("exclude_unactivatable", true)
);

if ( !prot_features.is_array() ) {
std::cerr << "protocol features not an array" << endl;
return {};
}
fc::variants& feature_variants = prot_features.get_array();

for( auto& feature_v : feature_variants ) {
if( !feature_v.is_object() ) {
std::cerr << "feature_v not an object" << endl;
return {};
}
fc::variant_object& feature_vo = feature_v.get_object();
if( !feature_vo.contains( "feature_digest" ) ) {
std::cerr << "feature_digest is missing" << std::endl;
return {};
}
if( !feature_vo["feature_digest"].is_string() ) {
std::cerr << "feature_digest not a string" << std::endl;
return {};
}
auto digest = feature_vo["feature_digest"].as_string();

if( !feature_vo.contains( "specification" ) ) {
std::cerr << "specification is missing" << std::endl;
return {};
}
if( !feature_vo["specification"].is_array() ) {
std::cerr << "specification not an array" << std::endl;
return {};
}
const fc::variants& spec_variants = feature_vo["specification"].get_array();
if ( spec_variants.size() != 1 ) {
std::cerr << "specification array size " << spec_variants.size() << " not 1 " << std::endl;
return {};
}
if ( !spec_variants[0].is_object() ) {
std::cerr << "spec_variants[0] not an object" << endl;
return {};
}
const fc::variant_object& spec_vo = spec_variants[0].get_object();
if ( !spec_vo.contains( "value" ) ) {
std::cerr << "value is missing" << endl;
return {};
}
if ( !spec_vo["value"].is_string() ) {
std::cerr << "value not a string" << std::endl;
return {};
}
auto name = spec_vo["value"].as_string();

if ( spec_vo["value"].as_string() == "PREACTIVATE_FEATURE" )
{
// PREACTIVATE_FEATURE must be activated by schedule_protocol_feature_activations RPC,
// not by activate action
continue;
}

results.names += name;
results.names += "\n";
results.digests.emplace(name, digest);
}

return results;
};

struct activate_subcommand {
string feature_name_str;
std::string account_str = "eosio";
std::string permission_str = "eosio";

activate_subcommand(CLI::App* actionRoot) {
auto activate = actionRoot->add_subcommand("activate", localized("Activate protocol feature by name"));
activate->add_option("feature", feature_name_str, localized("The name, can be found from \"cleos get supported_protoctol_features\" command"))->required();
activate->add_option("-a,--account", account_str, localized("The contract account name, default is eosio"));
activate->add_option("-p,--permission", permission_str, localized("The permission level to authorize, default is eosio"));
activate->fallthrough(false);

activate->callback([this] {
string action="activate";
string data;
std::locale loc;
vector<std::string> permissions = { permission_str };
for(auto & c : feature_name_str) c = std::toupper(c, loc);
protocol_features_t supported_features;
supported_features = get_supported_protocol_features();
if( supported_features.digests.find(feature_name_str) != supported_features.digests.end() ){
std::string digest = supported_features.digests[feature_name_str];
data = "[\"" + digest + "\"]";
} else {
std::cerr << feature_name_str << " is unknown. Following protocol features are supported" << std::endl << std::endl;
std::cerr << supported_features.names << std::endl;
return;
}
fc::variant action_args_var;
action_args_var = json_from_file_or_string(data, fc::json::parse_type::relaxed_parser);
auto accountPermissions = get_account_permissions(permissions);
send_actions({chain::action{accountPermissions, name(account_str), name(action),
variant_to_bin( name(account_str), name(action), action_args_var ) }}, signing_keys_opt.get_keys());
});
}
};

void get_account( const string& accountName, const string& coresym, bool json_format ) {
fc::variant json;
if (coresym.empty()) {
Expand Down Expand Up @@ -3179,6 +3295,13 @@ int main( int argc, char** argv ) {
get_schedule_subcommand{get};
auto getTransactionId = get_transaction_id_subcommand{get};

// get supported_protocol_features
get->add_subcommand("supported_protocol_features", localized("Get supported protocol features"))->callback([] {
protocol_features_t supported_features;
supported_features = get_supported_protocol_features();
std::cout << supported_features.names << std::endl;
});

// set subcommand
auto setSubcommand = app.add_subcommand("set", localized("Set or update blockchain state"));
setSubcommand->require_subcommand();
Expand Down Expand Up @@ -4225,6 +4348,7 @@ int main( int argc, char** argv ) {
auto unregProxy = unregproxy_subcommand(system);

auto cancelDelay = canceldelay_subcommand(system);
auto activate = activate_subcommand(system);

auto rex = system->add_subcommand("rex", localized("Actions related to REX (the resource exchange)"));
rex->require_subcommand();
Expand Down

0 comments on commit d6c3e25

Please sign in to comment.