Skip to content

Commit

Permalink
Merge pull request EOSIO#126 from enumivo/staging
Browse files Browse the repository at this point in the history
merge from eosio master
  • Loading branch information
Enumivo authored May 17, 2018
2 parents 1b485cf + b3370c8 commit 2ce1657
Show file tree
Hide file tree
Showing 10 changed files with 408 additions and 331 deletions.
2 changes: 1 addition & 1 deletion libraries/chain/block_header_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ namespace enumivo { namespace chain {

auto itr = producer_to_last_produced.find(h.producer);
if( itr != producer_to_last_produced.end() ) {
FC_ASSERT( itr->second <= result.block_num - h.confirmed, "producer double-confirming known range" );
FC_ASSERT( itr->second < result.block_num - h.confirmed, "producer double-confirming known range" );
}

// FC_ASSERT( result.header.block_mroot == h.block_mroot, "mismatch block merkle root" );
Expand Down
3 changes: 3 additions & 0 deletions libraries/testing/include/enumivo/testing/tester.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ namespace enumivo { namespace testing {
virtual signed_block_ptr produce_empty_block( fc::microseconds skip_time = fc::milliseconds(config::block_interval_ms), uint32_t skip_flag = 0/*skip_missed_block_penalty*/ ) = 0;
void produce_blocks( uint32_t n = 1, bool empty = false );
void produce_blocks_until_end_of_round();
void produce_blocks_for_n_rounds(const uint32_t num_of_rounds = 1);
// Produce minimal number of blocks as possible to spend the given time without having any producer become inactive
void produce_min_num_of_blocks_to_spend_time_wo_inactive_prod(const fc::microseconds target_elapsed_time = fc::microseconds());
signed_block_ptr push_block(signed_block_ptr b);

transaction_trace_ptr push_transaction( packed_transaction& trx, fc::time_point deadline = fc::time_point::maximum(), uint32_t billed_cpu_time_us = DEFAULT_BILLED_CPU_TIME_US );
Expand Down
29 changes: 27 additions & 2 deletions libraries/testing/tester.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ namespace enumivo { namespace testing {
auto last_produced_block_num = control->last_irreversible_block_num();
auto itr = last_produced_block.find(producer.producer_name);
if (itr != last_produced_block.end()) {
last_produced_block_num = block_header::num_from_id(itr->second);
last_produced_block_num = std::max(control->last_irreversible_block_num(), block_header::num_from_id(itr->second));
}

control->abort_block();
Expand All @@ -180,11 +180,36 @@ namespace enumivo { namespace testing {


void base_tester::produce_blocks_until_end_of_round() {
while( control->pending_block_state()->has_pending_producers() ) {
uint64_t blocks_per_round;
while(true) {
blocks_per_round = control->active_producers().producers.size() * config::producer_repetitions;
produce_block();
if (control->head_block_num() % blocks_per_round == (blocks_per_round - 1)) break;
}
}

void base_tester::produce_blocks_for_n_rounds(const uint32_t num_of_rounds) {
for(uint32_t i = 0; i < num_of_rounds; i++) {
produce_blocks_until_end_of_round();
}
}

void base_tester::produce_min_num_of_blocks_to_spend_time_wo_inactive_prod(const fc::microseconds target_elapsed_time) {
fc::microseconds elapsed_time;
while (elapsed_time < target_elapsed_time) {
for(uint32_t i = 0; i < control->head_block_state()->active_schedule.producers.size(); i++) {
const auto time_to_skip = fc::milliseconds(config::producer_repetitions * config::block_interval_ms);
produce_block(time_to_skip);
elapsed_time += time_to_skip;
}
// if it is more than 24 hours, producer will be marked as inactive
const auto time_to_skip = fc::seconds(23 * 60 * 60);
produce_block(time_to_skip);
elapsed_time += time_to_skip;
}

}


void base_tester::set_transaction_headers( signed_transaction& trx, uint32_t expiration, uint32_t delay_sec ) const {
trx.expiration = control->head_block_time() + fc::seconds(expiration);
Expand Down
1 change: 1 addition & 0 deletions plugins/chain_api_plugin/chain_api_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ void chain_api_plugin::plugin_startup() {
CHAIN_RO_CALL(get_table_rows, 200),
CHAIN_RO_CALL(get_currency_balance, 200),
CHAIN_RO_CALL(get_currency_stats, 200),
CHAIN_RO_CALL(get_producers, 200),
CHAIN_RO_CALL(abi_json_to_bin, 200),
CHAIN_RO_CALL(abi_bin_to_json, 200),
CHAIN_RO_CALL(get_required_keys, 200),
Expand Down
54 changes: 54 additions & 0 deletions plugins/chain_plugin/chain_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,60 @@ fc::variant read_only::get_currency_stats( const read_only::get_currency_stats_p
return results;
}

// TODO: move this and similar functions to a header. Copied from wasm_interface.cpp.
// TODO: fix strict aliasing violation
static float64_t to_softfloat64( double d ) {
return *reinterpret_cast<float64_t*>(&d);
}

read_only::get_producers_result read_only::get_producers( const read_only::get_producers_params& p ) const {
const abi_def abi = get_abi(db, N(enumivo));
const auto table_type = get_table_type(abi, N(producers));
const abi_serializer abis{ abi };
ENU_ASSERT(table_type == KEYi64, chain::contract_table_query_exception, "Invalid table type ${type}", ("type",table_type));

const auto& d = db.db();
const auto lower = name{p.lower_bound};

static const uint8_t secondary_index_num = 0;
const auto* const table_id = d.find<chain::table_id_object, chain::by_code_scope_table>(boost::make_tuple(N(enumivo), N(enumivo), N(producers)));
const auto* const secondary_table_id = d.find<chain::table_id_object, chain::by_code_scope_table>(boost::make_tuple(N(enumivo), N(enumivo), N(producers) | secondary_index_num));
ENU_ASSERT(table_id && secondary_table_id, chain::contract_table_query_exception, "Missing producers table");

const auto& kv_index = d.get_index<key_value_index, by_scope_primary>();
const auto& secondary_index = d.get_index<index_double_index>().indices();
const auto& secondary_index_by_primary = secondary_index.get<by_primary>();
const auto& secondary_index_by_secondary = secondary_index.get<by_secondary>();

read_only::get_producers_result result;
const auto stopTime = fc::time_point::now() + fc::microseconds(1000 * 10); // 10ms
vector<char> data;

auto it = [&]{
if(lower.value == 0)
return secondary_index_by_secondary.lower_bound(
boost::make_tuple(secondary_table_id->id, to_softfloat64(std::numeric_limits<double>::lowest()), 0));
else
return secondary_index.project<by_secondary>(
secondary_index_by_primary.lower_bound(
boost::make_tuple(secondary_table_id->id, lower.value)));
}();

for( ; it != secondary_index_by_secondary.end() && it->t_id == secondary_table_id->id; ++it ) {
if (result.rows.size() >= p.limit || fc::time_point::now() > stopTime) {
result.more = name{it->primary_key}.to_string();
break;
}
copy_inline_row(*kv_index.find(boost::make_tuple(table_id->id, it->primary_key)), data);
if (p.json)
result.rows.emplace_back(abis.binary_to_variant(abis.get_table_type(N(producers)), data));
else
result.rows.emplace_back(fc::variant(data));
}

return result;
}

template<typename Api>
struct resolver_factory {
static auto make(const Api *api) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,19 @@ class read_only {

fc::variant get_currency_stats( const get_currency_stats_params& params )const;

struct get_producers_params {
bool json = false;
string lower_bound;
uint32_t limit = 50;
};

struct get_producers_result {
vector<fc::variant> rows; ///< one row per item, either encoded as hex string or JSON object
string more; ///< fill lower_bound with this value to fetch more rows
};

get_producers_result get_producers( const get_producers_params& params )const;

static void copy_inline_row(const chain::key_value_object& obj, vector<char>& data) {
data.resize( obj.value.size() );
memcpy( data.data(), obj.value.data(), obj.value.size() );
Expand Down Expand Up @@ -372,7 +385,7 @@ FC_REFLECT( enumivo::chain_apis::permission, (perm_name)(parent)(required_auth)
FC_REFLECT(enumivo::chain_apis::empty, )
FC_REFLECT(enumivo::chain_apis::read_only::get_info_results,
(server_version)(head_block_num)(last_irreversible_block_num)(last_irreversible_block_id)(head_block_id)(head_block_time)(head_block_producer)(virtual_block_cpu_limit)(virtual_block_net_limit)(block_cpu_limit)(block_net_limit) )
FC_REFLECT(enumivo::chain_apis::read_only::get_block_params, (block_num_or_id))
FC_REFLECT( enumivo::chain_apis::read_only::get_block_params, (block_num_or_id))

FC_REFLECT( enumivo::chain_apis::read_write::push_transaction_results, (transaction_id)(processed) )

Expand All @@ -383,6 +396,9 @@ FC_REFLECT( enumivo::chain_apis::read_only::get_currency_balance_params, (code)(
FC_REFLECT( enumivo::chain_apis::read_only::get_currency_stats_params, (code)(symbol));
FC_REFLECT( enumivo::chain_apis::read_only::get_currency_stats_result, (supply)(max_supply)(issuer));

FC_REFLECT( enumivo::chain_apis::read_only::get_producers_params, (json)(lower_bound)(limit) )
FC_REFLECT( enumivo::chain_apis::read_only::get_producers_result, (rows)(more) );

FC_REFLECT( enumivo::chain_apis::read_only::get_account_results, (account_name)(privileged)(last_code_update)(created)(ram_quota)(net_weight)(cpu_weight)(net_limit)(cpu_limit)(ram_usage)(permissions)(total_resources)(delegated_bandwidth)(voter_info) )
FC_REFLECT( enumivo::chain_apis::read_only::get_code_results, (account_name)(code_hash)(wast)(abi) )
FC_REFLECT( enumivo::chain_apis::read_only::get_account_params, (account_name) )
Expand Down
1 change: 1 addition & 0 deletions programs/enucli/httpc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ namespace enumivo { namespace client { namespace http {
const string get_code_func = chain_func_base + "/get_code";
const string get_currency_balance_func = chain_func_base + "/get_currency_balance";
const string get_currency_stats_func = chain_func_base + "/get_currency_stats";
const string get_producers_func = chain_func_base + "/get_producers";
const string get_required_keys = chain_func_base + "/get_required_keys";


Expand Down
68 changes: 25 additions & 43 deletions programs/enucli/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1011,54 +1011,36 @@ struct unapprove_producer_subcommand {

struct list_producers_subcommand {
bool print_json = false;
bool sort_names = false;
uint32_t limit = 50;
std::string lower;

list_producers_subcommand(CLI::App* actionRoot) {
auto list_producers = actionRoot->add_subcommand("listproducers", localized("List producers"));
list_producers->add_flag("--json,-j", print_json, localized("Output in JSON format") );
list_producers->add_flag("--sort-account-names,-n", sort_names, localized("Sort by account names (default order is by votes)") );
list_producers->add_flag("--json,-j", print_json, localized("Output in JSON format"));
list_producers->add_option("-l,--limit", limit, localized("The maximum number of rows to return"));
list_producers->add_option("-L,--lower", lower, localized("lower bound value of key, defaults to first"));
list_producers->set_callback([this] {
auto result = call(get_table_func, fc::mutable_variant_object("json", true)
("code", name(config::system_account_name).to_string())
("scope", name(config::system_account_name).to_string())
("table", "producers")
);

if ( !print_json ) {
auto res = result.as<enumivo::chain_apis::read_only::get_table_rows_result>();
std::vector<std::tuple<std::string, std::string, std::string, std::string>> v;
for ( auto& row : res.rows ) {
auto& r = row.get_object();
v.emplace_back( r["owner"].as_string(), r["total_votes"].as_string(), r["producer_key"].as_string(), r["url"].as_string() );

}
if ( !v.empty() ) {
if ( sort_names ) {
std::sort( v.begin(), v.end(), [](auto a, auto b) { return std::get<0>(a) < std::get<0>(b); } );
} else {
std::sort( v.begin(), v.end(), [](auto a, auto b) {
return std::get<1>(a) < std::get<1>(b) || (std::get<1>(a) == std::get<1>(b) && std::get<0>(a) < std::get<0>(b)); }
);
}

std::cout << std::left << std::setw(14) << "Producer" << std::setw(55) << "Producer key"
<< std::setw(50) << "Url" << "Total votes" << std::endl;
for ( auto& x : v ) {
std::cout << std::left << std::setw(14) << std::get<0>(x) << std::setw(55) << std::get<2>(x)
<< std::setw(50) << std::get<3>(x) << std::get<1>(x) << std::endl;
}
} else {
std::cout << "No producers found" << std::endl;
}
} else {
if ( sort_names ) {
FC_THROW("Sorting producers is not supported for JSON format");
}
std::cout << fc::json::to_pretty_string(result)
<< std::endl;
}
auto rawResult = call(get_producers_func, fc::mutable_variant_object
("json", true)("lower_bound", lower)("limit", limit));
if ( print_json ) {
std::cout << fc::json::to_pretty_string(rawResult) << std::endl;
return;
}
);
auto result = rawResult.as<enumivo::chain_apis::read_only::get_producers_result>();
if ( result.rows.empty() ) {
std::cout << "No producers found" << std::endl;
return;
}
printf("%-13s %-54s %-59s %s\n", "Producer", "Producer key", "Url", "Total votes");
for ( auto& row : result.rows )
printf("%-13.13s %-54.54s %-59.59s %040f\n",
row["owner"].as_string().c_str(),
row["producer_key"].as_string().c_str(),
row["url"].as_string().c_str(),
row["total_votes"].as_double());
if ( !result.more.empty() )
std::cout << "-L " << result.more << " for more" << std::endl;
});
}
};

Expand Down
Loading

0 comments on commit 2ce1657

Please sign in to comment.