Skip to content

Commit

Permalink
bandwith used for the providebw action is added to a payload actions …
Browse files Browse the repository at this point in the history
…bandwith #201
  • Loading branch information
e-schepachev committed Jan 28, 2019
1 parent 8a6051e commit 9e4274e
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 60 deletions.
35 changes: 20 additions & 15 deletions libraries/chain/controller.cpp
Expand Up @@ -1025,38 +1025,36 @@ struct controller_impl {
return push_scheduled_transaction( *itr, deadline, billed_cpu_time_us, explicit_billed_cpu_time );
}

std::map<account_name, provided_bandwith> call_approvebw_actions(vector<action>&& actions, fc::time_point deadline) {
signed_transaction call_provide_trx;
call_provide_trx.actions = std::move(actions);
void call_approvebw_actions(signed_transaction& call_provide_trx, transaction_context& trx_context) {
call_provide_trx.expiration = self.pending_block_time() + fc::microseconds(999'999); // Round up to avoid appearing expired
call_provide_trx.set_reference_block( self.head_block_id() );
transaction_context trx_context( self, call_provide_trx, call_provide_trx.id());
trx_context.deadline = deadline;

trx_context.init_for_implicit_trx();
trx_context.exec();
trx_context.finalize();
trx_context.validate_bw_usage();

auto restore = make_block_restore_point();
fc::move_append( pending->_actions, move(trx_context.executed) );
trx_context.squash();
restore.cancel();
return trx_context.get_provided_bandwith();
}

std::map<account_name, provided_bandwith> verify_bandwith_provided(const vector<action>& actions, fc::time_point deadline) {
std::vector<action> approve_actions;
bandwith_request_result get_provided_bandwith(const vector<action>& actions, fc::time_point deadline) {
signed_transaction call_provide_trx;
transaction_context trx_context( self, call_provide_trx, call_provide_trx.id());
for (const auto& action : actions) {
if (action.account == N(eosio) && action.name == N(requestbw)) {
const auto request_bw = action.data_as<requestbw>();
approve_actions.emplace_back(vector<permission_level>{{request_bw.provider, config::active_name}}, request_bw.provider, N(approvebw), fc::raw::pack(approvebw( request_bw.account)));
call_provide_trx.actions.emplace_back(vector<permission_level>{{request_bw.provider, config::active_name}}, request_bw.provider, N(approvebw), fc::raw::pack(approvebw( request_bw.account)));
}
}

if (!approve_actions.empty()) {
return call_approvebw_actions(std::move(approve_actions), deadline);
if (!call_provide_trx.actions.empty()) {
trx_context.deadline = deadline;
call_approvebw_actions(call_provide_trx, trx_context);
}
return {};

return {trx_context.get_provided_bandwith(), trx_context.get_net_usage(), trx_context.get_cpu_usage()};
}

transaction_trace_ptr push_scheduled_transaction( const generated_transaction_object& gto, fc::time_point deadline, uint32_t billed_cpu_time_us, bool explicit_billed_cpu_time = false )
Expand Down Expand Up @@ -1115,7 +1113,10 @@ struct controller_impl {
trx_context.billed_cpu_time_us = billed_cpu_time_us;
trace = trx_context.trace;
try {
trx_context.set_provided_bandwith(verify_bandwith_provided(trx->trx.actions, deadline));
auto bandwith_request_result = get_provided_bandwith(trx->trx.actions, deadline);
trx_context.set_provided_bandwith(std::move(bandwith_request_result.bandwith));
trx_context.add_cpu_usage(bandwith_request_result.used_cpu);
trx_context.add_net_usage(bandwith_request_result.used_net);

trx_context.init_for_deferred_trx( gtrx.published );
trx_context.exec();
Expand Down Expand Up @@ -1245,7 +1246,11 @@ struct controller_impl {
trx_context.billed_cpu_time_us = billed_cpu_time_us;
trace = trx_context.trace;
try {
trx_context.set_provided_bandwith(verify_bandwith_provided(trx->trx.actions, deadline));
auto bandwith_request_result = get_provided_bandwith(trx->trx.actions, deadline);

trx_context.set_provided_bandwith(std::move(bandwith_request_result.bandwith));
trx_context.add_cpu_usage(bandwith_request_result.used_cpu);
trx_context.add_net_usage(bandwith_request_result.used_net);

if( trx->implicit ) {
trx_context.init_for_implicit_trx();
Expand Down
2 changes: 1 addition & 1 deletion libraries/chain/include/eosio/chain/exceptions.hpp
Expand Up @@ -196,7 +196,7 @@ namespace eosio { namespace chain {
3040013, "Transaction is too big" )
FC_DECLARE_DERIVED_EXCEPTION( unknown_transaction_compression, transaction_exception,
3040014, "Unknown transaction compression" )
FC_DECLARE_DERIVED_EXCEPTION( bandwith_confirmed, transaction_exception,
FC_DECLARE_DERIVED_EXCEPTION( bandwith_already_confirmed, transaction_exception,
3040015, "Bandwith has been already confirmed" )


Expand Down
15 changes: 12 additions & 3 deletions libraries/chain/include/eosio/chain/transaction_context.hpp
Expand Up @@ -8,9 +8,6 @@ namespace eosio { namespace chain {
struct provided_bandwith {
provided_bandwith() = default;

// provided_bandwith(account_name account)
// : account_(account) {}

void confirm(account_name provider);

bool is_confirmed() const {return confirmed_;}
Expand All @@ -33,6 +30,13 @@ namespace eosio { namespace chain {
account_name provider_;
};


struct bandwith_request_result {
std::map<account_name, provided_bandwith> bandwith;
uint64_t used_net;
uint64_t used_cpu;
};

struct deadline_timer {
deadline_timer();
~deadline_timer();
Expand Down Expand Up @@ -70,8 +74,13 @@ namespace eosio { namespace chain {
void finalize();
void squash();
void undo();
void validate_bw_usage();

inline void add_net_usage( uint64_t u ) { net_usage += u; check_net_usage(); }
inline void add_cpu_usage( uint64_t u ) { billed_cpu_time_us += u;}

uint64_t get_net_usage() const {return net_usage;}
uint64_t get_cpu_usage() const {return billed_cpu_time_us;}

void check_net_usage()const;

Expand Down
86 changes: 45 additions & 41 deletions libraries/chain/transaction_context.cpp
Expand Up @@ -392,58 +392,62 @@ namespace bacc = boost::accumulators;
}

void transaction_context::finalize() {
EOS_ASSERT( is_initialized, transaction_exception, "must first initialize" );
validate_bw_usage();

if( is_input ) {
auto& am = control.get_mutable_authorization_manager();
for( const auto& act : trx.actions ) {
for( const auto& auth : act.authorization ) {
am.update_permission_usage( am.get_permission(auth) );
}
}
}
control.get_mutable_resource_limits_manager().add_transaction_usage( bill_to_accounts, static_cast<uint64_t>(billed_cpu_time_us), net_usage,
block_timestamp_type(control.pending_block_time()).slot ); // Should never fail
}

auto& rl = control.get_mutable_resource_limits_manager();
for( auto a : validate_ram_usage ) {
rl.verify_account_ram_usage( a );
}
void transaction_context::validate_bw_usage() {
EOS_ASSERT( is_initialized, transaction_exception, "must first initialize" );

// Calculate the new highest network usage and CPU time that all of the billed accounts can afford to be billed
int64_t account_net_limit = 0;
int64_t account_cpu_limit = 0;
bool greylisted_net = false, greylisted_cpu = false;
std::tie( account_net_limit, account_cpu_limit, greylisted_net, greylisted_cpu) = max_bandwidth_billed_accounts_can_pay();
net_limit_due_to_greylist |= greylisted_net;
cpu_limit_due_to_greylist |= greylisted_cpu;
if( is_input ) {
auto& am = control.get_mutable_authorization_manager();
for( const auto& act : trx.actions ) {
for( const auto& auth : act.authorization ) {
am.update_permission_usage( am.get_permission(auth) );
}
}
}

// Possibly lower net_limit to what the billed accounts can pay
if( static_cast<uint64_t>(account_net_limit) <= net_limit ) {
// NOTE: net_limit may possibly not be objective anymore due to net greylisting, but it should still be no greater than the truly objective net_limit
net_limit = static_cast<uint64_t>(account_net_limit);
net_limit_due_to_block = false;
}
auto& rl = control.get_mutable_resource_limits_manager();
for( auto a : validate_ram_usage ) {
rl.verify_account_ram_usage( a );
}

// Possibly lower objective_duration_limit to what the billed accounts can pay
if( account_cpu_limit <= objective_duration_limit.count() ) {
// NOTE: objective_duration_limit may possibly not be objective anymore due to cpu greylisting, but it should still be no greater than the truly objective objective_duration_limit
objective_duration_limit = fc::microseconds(account_cpu_limit);
billing_timer_exception_code = tx_cpu_usage_exceeded::code_value;
}
// Calculate the new highest network usage and CPU time that all of the billed accounts can afford to be billed
int64_t account_net_limit = 0;
int64_t account_cpu_limit = 0;
bool greylisted_net = false, greylisted_cpu = false;
std::tie( account_net_limit, account_cpu_limit, greylisted_net, greylisted_cpu) = max_bandwidth_billed_accounts_can_pay();
net_limit_due_to_greylist |= greylisted_net;
cpu_limit_due_to_greylist |= greylisted_cpu;

// Possibly lower net_limit to what the billed accounts can pay
if( static_cast<uint64_t>(account_net_limit) <= net_limit ) {
// NOTE: net_limit may possibly not be objective anymore due to net greylisting, but it should still be no greater than the truly objective net_limit
net_limit = static_cast<uint64_t>(account_net_limit);
net_limit_due_to_block = false;
}

net_usage = ((net_usage + 7)/8)*8; // Round up to nearest multiple of word size (8 bytes)
// Possibly lower objective_duration_limit to what the billed accounts can pay
if( account_cpu_limit <= objective_duration_limit.count() ) {
// NOTE: objective_duration_limit may possibly not be objective anymore due to cpu greylisting, but it should still be no greater than the truly objective objective_duration_limit
objective_duration_limit = fc::microseconds(account_cpu_limit);
billing_timer_exception_code = tx_cpu_usage_exceeded::code_value;
}

eager_net_limit = net_limit;
check_net_usage();
net_usage = ((net_usage + 7)/8)*8; // Round up to nearest multiple of word size (8 bytes)

auto now = fc::time_point::now();
trace->elapsed = now - start;
eager_net_limit = net_limit;
check_net_usage();

update_billed_cpu_time( now );
auto now = fc::time_point::now();
trace->elapsed = now - start;

validate_cpu_usage_to_bill( billed_cpu_time_us );
update_billed_cpu_time( now );

rl.add_transaction_usage( bill_to_accounts, static_cast<uint64_t>(billed_cpu_time_us), net_usage,
block_timestamp_type(control.pending_block_time()).slot ); // Should never fail
validate_cpu_usage_to_bill( billed_cpu_time_us );
}

void transaction_context::squash() {
Expand Down

0 comments on commit 9e4274e

Please sign in to comment.