Skip to content

Commit

Permalink
added set_bw_limits and confirm_bw intrinsics. #201
Browse files Browse the repository at this point in the history
Also get bw_limits functions return limits by actor, not summary.
Several requestbw actions supported in one transaction.
  • Loading branch information
e-schepachev committed Jan 24, 2019
1 parent 523ad17 commit 17bb1cb
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 42 deletions.
29 changes: 15 additions & 14 deletions libraries/chain/controller.cpp
Expand Up @@ -1010,36 +1010,38 @@ struct controller_impl {
return push_scheduled_transaction( *itr, deadline, billed_cpu_time_us, explicit_billed_cpu_time );
}


void call_approvebw_action(const action& action, fc::time_point deadline) {
const auto request_bw = action.data_as<requestbw>();

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.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 = std::move(actions);
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;
transaction_trace_ptr trace = trx_context.trace;

trx_context.init_for_implicit_trx();
trx_context.trace->action_traces.emplace_back();
trx_context.dispatch_action( trx_context.trace->action_traces.back(), call_provide_trx.actions.back(), request_bw.provider );
trx_context.exec();
trx_context.finalize();

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();
}

void verify_approvebw_required(const vector<action>& actions, fc::time_point deadline) {
for (const auto& action : actions) {
std::map<account_name, provided_bandwith> verify_bandwith_provided(const vector<action>& actions, fc::time_point deadline) {
std::vector<action> approve_actions;
for (const auto& action : actions) {
if (action.account == N(eosio) && action.name == N(requestbw)) {
call_approvebw_action(action, deadline);
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)));
}
}

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

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 @@ -1098,7 +1100,7 @@ struct controller_impl {
trx_context.billed_cpu_time_us = billed_cpu_time_us;
trace = trx_context.trace;
try {
verify_approvebw_required(trx->trx.actions, deadline);
trx_context.set_provided_bandwith(verify_bandwith_provided(trx->trx.actions, deadline));

trx_context.init_for_deferred_trx( gtrx.published );
trx_context.exec();
Expand Down Expand Up @@ -1228,7 +1230,7 @@ struct controller_impl {
trx_context.billed_cpu_time_us = billed_cpu_time_us;
trace = trx_context.trace;
try {
verify_approvebw_required(trx->trx.actions, deadline);
trx_context.set_provided_bandwith(verify_bandwith_provided(trx->trx.actions, deadline));

if( trx->implicit ) {
trx_context.init_for_implicit_trx();
Expand All @@ -1245,7 +1247,6 @@ struct controller_impl {
check_actor_list( trx_context.bill_to_accounts ); // Assumes bill_to_accounts is the set of actors authorizing the transaction
}


trx_context.delay = fc::seconds(trx->trx.delay_sec);

if( !self.skip_auth_check() && !trx->implicit ) {
Expand Down
3 changes: 2 additions & 1 deletion libraries/chain/include/eosio/chain/exceptions.hpp
Expand Up @@ -196,6 +196,8 @@ 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,
3040015, "Bandwith has been already confirmed" )


FC_DECLARE_DERIVED_EXCEPTION( action_validate_exception, chain_exception,
Expand Down Expand Up @@ -257,7 +259,6 @@ namespace eosio { namespace chain {
FC_DECLARE_DERIVED_EXCEPTION( binaryen_exception, wasm_exception,
3070005, "binaryen exception" )


FC_DECLARE_DERIVED_EXCEPTION( resource_exhausted_exception, chain_exception,
3080000, "Resource exhausted exception" )

Expand Down
46 changes: 37 additions & 9 deletions libraries/chain/include/eosio/chain/transaction_context.hpp
Expand Up @@ -6,12 +6,31 @@
namespace eosio { namespace chain {

struct provided_bandwith {
provided_bandwith(uint64_t net_limit, uint64_t cpu_limit)
: net_limit(net_limit),
cpu_limit(cpu_limit) {}
provided_bandwith() = default;

uint64_t net_limit;
uint64_t cpu_limit;
// provided_bandwith(account_name account)
// : account_(account) {}

void confirm(account_name provider);

bool is_confirmed() const {return confirmed_;}

int64_t get_net_limit() const {return net_limit_;}
int64_t get_cpu_limit() const {return cpu_limit_;}

void set_net_limit(int64_t net_limit);
void set_cpu_limit(int64_t cpu_limit);

account_name get_provider() const {return provider_;}

private:

void verify_limits_not_confirmed();

int64_t net_limit_ = 0;
int64_t cpu_limit_ = 0;
bool confirmed_ = false;
account_name provider_;
};

struct deadline_timer {
Expand Down Expand Up @@ -65,9 +84,19 @@ namespace eosio { namespace chain {

std::tuple<int64_t, int64_t, bool, bool> max_bandwidth_billed_accounts_can_pay( bool force_elastic_limits = false )const;

uint64_t get_provided_net_limit() const {return provided_bandwith_.net_limit;}
uint64_t get_provided_net_limit(account_name account) const;

uint64_t get_provided_cpu_limit(account_name account) const;

std::map<account_name, provided_bandwith> get_provided_bandwith() const {return provided_bandwith_;}

bool is_provided_bandwith_confirmed(account_name account) const;

void set_provided_bandwith(std::map<account_name, provided_bandwith>&& bandwith);

void set_provided_bandwith_limits(account_name account, uint64_t net_limit, uint64_t cpu_limit);

uint64_t get_provided_cpu_limit() const {return provided_bandwith_.cpu_limit;}
void confirm_provided_bandwith_limits(account_name account, account_name provider);

private:

Expand All @@ -85,7 +114,6 @@ namespace eosio { namespace chain {

void validate_cpu_usage_to_bill( int64_t u, bool check_minimum = true )const;

provided_bandwith get_provided_bandwith() const;
/// Fields:
public:

Expand Down Expand Up @@ -141,7 +169,7 @@ namespace eosio { namespace chain {

deadline_timer _deadline_timer;

provided_bandwith provided_bandwith_;
std::map<account_name, provided_bandwith> provided_bandwith_;
};

} }
90 changes: 78 additions & 12 deletions libraries/chain/transaction_context.cpp
Expand Up @@ -85,6 +85,28 @@ namespace bacc = boost::accumulators;
volatile sig_atomic_t deadline_timer_verify::hit;
static deadline_timer_verify deadline_timer_verification;

void provided_bandwith::confirm(account_name provider) {
verify_limits_not_confirmed();
confirmed_ = true;
provider_ = provider;
}

void provided_bandwith::set_net_limit(int64_t net_limit) {
verify_limits_not_confirmed();
this->net_limit_ = net_limit;
}

void provided_bandwith::set_cpu_limit(int64_t cpu_limit) {
verify_limits_not_confirmed();
this->cpu_limit_ = cpu_limit;
}

void provided_bandwith::verify_limits_not_confirmed() {
if (confirmed_) {
EOS_THROW( bandwith_confirmed, "bandwith has been already confirmed. No changes could be done");
}
}

deadline_timer::deadline_timer() {
if(initialized)
return;
Expand Down Expand Up @@ -161,7 +183,6 @@ namespace bacc = boost::accumulators;
,start(s)
,net_usage(trace->net_usage)
,pseudo_start(s)
,provided_bandwith_(get_provided_bandwith())
{
if (!c.skip_db_sessions()) {
// TODO: removed by CyberWay
Expand All @@ -185,8 +206,8 @@ namespace bacc = boost::accumulators;
auto& rl = control.get_mutable_resource_limits_manager();

net_limit = rl.get_block_net_limit();

objective_duration_limit = fc::microseconds( rl.get_block_cpu_limit() );

_deadline = start + objective_duration_limit;

// Possibly lower net_limit to the maximum net usage a transaction is allowed to be billed
Expand Down Expand Up @@ -232,7 +253,12 @@ namespace bacc = boost::accumulators;
provided_accounts.insert(args.account);
}
for( const auto& auth : act.authorization ) {
bill_to_accounts.insert( auth.actor );
const auto provided_bw_it = provided_bandwith_.find(auth.actor);
if(provided_bw_it != provided_bandwith_.end()) {
bill_to_accounts.insert( provided_bw_it->second.get_provider() );
} else {
bill_to_accounts.insert( auth.actor );
}
}
}
validate_ram_usage.reserve( bill_to_accounts.size() );
Expand Down Expand Up @@ -560,11 +586,6 @@ namespace bacc = boost::accumulators;
return static_cast<uint32_t>(billed_cpu_time_us);
}

provided_bandwith transaction_context::get_provided_bandwith() const {
const auto max_bandwith = max_bandwidth_billed_accounts_can_pay();
return {static_cast<uint64_t>(std::get<0>(max_bandwith)), static_cast<uint64_t>(std::get<1>(max_bandwith))};
}

std::tuple<int64_t, int64_t, bool, bool> transaction_context::max_bandwidth_billed_accounts_can_pay( bool force_elastic_limits ) const{
// Assumes rl.update_account_usage( bill_to_accounts, block_timestamp_type(control.pending_block_time()).slot ) was already called prior

Expand All @@ -577,12 +598,14 @@ namespace bacc = boost::accumulators;
bool greylisted_cpu = false;
for( const auto& a : bill_to_accounts ) {
bool elastic = force_elastic_limits || !(control.is_producing_block() && control.is_resource_greylisted(a));
auto net_limit = rl.get_account_net_limit(a, elastic);
const auto provided_bw_it = provided_bandwith_.find(a);
const auto is_bw_provided = provided_bw_it != provided_bandwith_.end() && provided_bw_it->second.is_confirmed();
auto net_limit = is_bw_provided ? provided_bw_it->second.get_net_limit() : rl.get_account_net_limit(a, elastic);
if( net_limit >= 0 ) {
account_net_limit = std::min( account_net_limit, net_limit );
if (!elastic) greylisted_net = true;
}
auto cpu_limit = rl.get_account_cpu_limit(a, elastic);
auto cpu_limit = is_bw_provided ? provided_bw_it->second.get_cpu_limit() : rl.get_account_cpu_limit(a, elastic);
if( cpu_limit >= 0 ) {
account_cpu_limit = std::min( account_cpu_limit, cpu_limit );
if (!elastic) greylisted_cpu = true;
Expand All @@ -592,6 +615,49 @@ namespace bacc = boost::accumulators;
return std::make_tuple(account_net_limit, account_cpu_limit, greylisted_net, greylisted_cpu);
}

uint64_t transaction_context::get_provided_net_limit(account_name account) const {
const auto provided_bw_it = provided_bandwith_.find(account);

if (provided_bw_it == provided_bandwith_.end()) {
return 0;
}

return provided_bw_it->second.get_net_limit();
}

uint64_t transaction_context::get_provided_cpu_limit(account_name account) const {
const auto provided_bw_it = provided_bandwith_.find(account);

if (provided_bw_it == provided_bandwith_.end()) {
return 0;
}

return provided_bw_it->second.get_cpu_limit();
}

bool transaction_context::is_provided_bandwith_confirmed(account_name account) const {
const auto provided_bw_it = provided_bandwith_.find(account);

if (provided_bw_it == provided_bandwith_.end()) {
return 0;
}

return provided_bw_it->second.is_confirmed();
}

void transaction_context::set_provided_bandwith(std::map<account_name, provided_bandwith>&& bandwith) {
provided_bandwith_ = std::move(bandwith);
}

void transaction_context::set_provided_bandwith_limits(account_name account, uint64_t net_limit, uint64_t cpu_limit) {
provided_bandwith_[account].set_net_limit(net_limit);
provided_bandwith_[account].set_cpu_limit(cpu_limit);
}

void transaction_context::confirm_provided_bandwith_limits(account_name account, account_name provider) {
provided_bandwith_[account].confirm(provider);
}

void transaction_context::dispatch_action( action_trace& trace, const action& a, account_name receiver, bool context_free, uint32_t recurse_depth ) {
apply_context acontext( control, *this, a, recurse_depth );
acontext.context_free = context_free;
Expand Down Expand Up @@ -634,7 +700,7 @@ namespace bacc = boost::accumulators;
transaction.trx_id = id;
transaction.expiration = expire;
});
} /// record_transaction

}

/// record_transaction
} } /// eosio::chain
27 changes: 21 additions & 6 deletions libraries/chain/wasm_interface.cpp
Expand Up @@ -1134,12 +1134,24 @@ class bandwith_api : public context_aware_api {
bandwith_api( apply_context& ctx )
: context_aware_api(ctx,true) {}

int64_t get_bw_cpu_limit() const {
return context.trx_context.get_provided_cpu_limit();
int64_t get_bw_cpu_limit(account_name account) const {
return context.trx_context.get_provided_cpu_limit(account);
}

int64_t get_bw_net_limit() const {
return context.trx_context.get_provided_net_limit();
int64_t get_bw_net_limit(account_name account) const {
return context.trx_context.get_provided_net_limit(account);
}

bool is_provided_bw_confirmed(account_name account) const {
return context.trx_context.is_provided_bandwith_confirmed(account);
}

void set_bw_limits(account_name account, int64_t net_limit, int64_t cpu_limit) {
context.trx_context.set_provided_bandwith_limits(account, net_limit, cpu_limit);
}

void confirm_bw_limits(account_name account) {
context.trx_context.confirm_provided_bandwith_limits(account, context.receiver);
}
};

Expand Down Expand Up @@ -1873,8 +1885,11 @@ REGISTER_INTRINSICS(console_api,


REGISTER_INTRINSICS(bandwith_api,
(get_bw_cpu_limit, int64_t())
(get_bw_net_limit, int64_t())
(get_bw_cpu_limit, int64_t(int64_t))
(get_bw_net_limit, int64_t(int64_t ))
(is_provided_bw_confirmed, int(int64_t))
(set_bw_limits, void(int64_t, int64_t, int64_t))
(confirm_bw_limits, void(int64_t))
);


Expand Down

0 comments on commit 17bb1cb

Please sign in to comment.