未验证 提交 1f2a28ea 编写于 作者: D Daniel Larimer 提交者: GitHub

Merge pull request #2947 from EOSIO/2898-subjective-billing-2

Progress on subjective CPU billing 
...@@ -348,12 +348,12 @@ bytes apply_context::get_packed_transaction() { ...@@ -348,12 +348,12 @@ bytes apply_context::get_packed_transaction() {
} }
void apply_context::update_db_usage( const account_name& payer, int64_t delta ) { void apply_context::update_db_usage( const account_name& payer, int64_t delta ) {
if( (delta > 0) ) { if( delta > 0 ) {
if( !(privileged || payer == account_name(receiver)) ) { if( !(privileged || payer == account_name(receiver)) ) {
require_authorization( payer ); require_authorization( payer );
} }
trx_context.add_ram_usage(payer, delta);
} }
trx_context.add_ram_usage(payer, delta);
} }
......
...@@ -395,10 +395,11 @@ struct controller_impl { ...@@ -395,10 +395,11 @@ struct controller_impl {
etrx.set_reference_block( self.head_block_id() ); etrx.set_reference_block( self.head_block_id() );
transaction_context trx_context( self, etrx, etrx.id(), start ); transaction_context trx_context( self, etrx, etrx.id(), start );
trx_context.deadline = deadline;
trx_context.billed_cpu_time_us = billed_cpu_time_us; trx_context.billed_cpu_time_us = billed_cpu_time_us;
transaction_trace_ptr trace = trx_context.trace; transaction_trace_ptr trace = trx_context.trace;
try { try {
trx_context.init_for_implicit_trx( deadline, 0 ); trx_context.init_for_implicit_trx();
trx_context.published = gto.published; trx_context.published = gto.published;
trx_context.trace->action_traces.emplace_back(); trx_context.trace->action_traces.emplace_back();
trx_context.dispatch_action( trx_context.trace->action_traces.back(), etrx.actions.back(), gto.sender ); trx_context.dispatch_action( trx_context.trace->action_traces.back(), etrx.actions.back(), gto.sender );
...@@ -433,8 +434,10 @@ struct controller_impl { ...@@ -433,8 +434,10 @@ struct controller_impl {
bool failure_is_subjective( const fc::exception& e ) { bool failure_is_subjective( const fc::exception& e ) {
auto code = e.code(); auto code = e.code();
return (code == tx_soft_net_usage_exceeded::code_value) || return (code == block_net_usage_exceeded::code_value) ||
(code == tx_deadline_exceeded::code_value); (code == block_cpu_usage_exceeded::code_value) ||
(code == deadline_exception::code_value) ||
(code == leeway_deadline_exception::code_value);
} }
transaction_trace_ptr push_scheduled_transaction( const transaction_id_type& trxid, fc::time_point deadline, uint32_t billed_cpu_time_us ) { transaction_trace_ptr push_scheduled_transaction( const transaction_id_type& trxid, fc::time_point deadline, uint32_t billed_cpu_time_us ) {
...@@ -467,11 +470,12 @@ struct controller_impl { ...@@ -467,11 +470,12 @@ struct controller_impl {
fc::raw::unpack(ds,static_cast<transaction&>(dtrx) ); fc::raw::unpack(ds,static_cast<transaction&>(dtrx) );
transaction_context trx_context( self, dtrx, gto.trx_id ); transaction_context trx_context( self, dtrx, gto.trx_id );
trx_context.deadline = deadline;
trx_context.billed_cpu_time_us = billed_cpu_time_us; trx_context.billed_cpu_time_us = billed_cpu_time_us;
transaction_trace_ptr trace = trx_context.trace; transaction_trace_ptr trace = trx_context.trace;
flat_set<account_name> bill_to_accounts; flat_set<account_name> bill_to_accounts;
try { try {
trx_context.init_for_deferred_trx( deadline, gto.published ); trx_context.init_for_deferred_trx( gto.published );
bill_to_accounts = trx_context.bill_to_accounts; bill_to_accounts = trx_context.bill_to_accounts;
trx_context.exec(); trx_context.exec();
trx_context.finalize(); // Automatically rounds up network and CPU usage in trace and bills payers if successful trx_context.finalize(); // Automatically rounds up network and CPU usage in trace and bills payers if successful
...@@ -576,16 +580,16 @@ struct controller_impl { ...@@ -576,16 +580,16 @@ struct controller_impl {
transaction_trace_ptr trace; transaction_trace_ptr trace;
try { try {
transaction_context trx_context(self, trx->trx, trx->id); transaction_context trx_context(self, trx->trx, trx->id);
trx_context.deadline = deadline;
trx_context.billed_cpu_time_us = billed_cpu_time_us; trx_context.billed_cpu_time_us = billed_cpu_time_us;
trace = trx_context.trace; trace = trx_context.trace;
try { try {
if (implicit) { if (implicit) {
trx_context.init_for_implicit_trx(deadline); trx_context.init_for_implicit_trx();
} else { } else {
trx_context.init_for_input_trx(deadline, trx_context.init_for_input_trx( trx->packed_trx.get_unprunable_size(),
trx->packed_trx.get_unprunable_size(), trx->packed_trx.get_prunable_size(),
trx->packed_trx.get_prunable_size(), trx->trx.signatures.size() );
trx->trx.signatures.size());
} }
trx_context.delay = fc::seconds(trx->trx.delay_sec); trx_context.delay = fc::seconds(trx->trx.delay_sec);
...@@ -1063,13 +1067,11 @@ void controller::push_confirmation( const header_confirmation& c ) { ...@@ -1063,13 +1067,11 @@ void controller::push_confirmation( const header_confirmation& c ) {
} }
transaction_trace_ptr controller::push_transaction( const transaction_metadata_ptr& trx, fc::time_point deadline, uint32_t billed_cpu_time_us ) { transaction_trace_ptr controller::push_transaction( const transaction_metadata_ptr& trx, fc::time_point deadline, uint32_t billed_cpu_time_us ) {
wdump((deadline)(billed_cpu_time_us));
return my->push_transaction(trx, deadline, false, billed_cpu_time_us); return my->push_transaction(trx, deadline, false, billed_cpu_time_us);
} }
transaction_trace_ptr controller::push_scheduled_transaction( const transaction_id_type& trxid, fc::time_point deadline, uint32_t billed_cpu_time_us ) transaction_trace_ptr controller::push_scheduled_transaction( const transaction_id_type& trxid, fc::time_point deadline, uint32_t billed_cpu_time_us )
{ {
wdump((deadline)(billed_cpu_time_us));
return my->push_scheduled_transaction( trxid, deadline, billed_cpu_time_us ); return my->push_scheduled_transaction( trxid, deadline, billed_cpu_time_us );
} }
......
...@@ -92,7 +92,7 @@ const static uint32_t ram_usage_validation_overhead_per_account = 64 ...@@ -92,7 +92,7 @@ const static uint32_t ram_usage_validation_overhead_per_account = 64
const static uint32_t fixed_net_overhead_of_packed_trx = 16; // TODO: is this reasonable? const static uint32_t fixed_net_overhead_of_packed_trx = 16; // TODO: is this reasonable?
const static uint32_t fixed_overhead_shared_vector_ram_bytes = 16; ///< overhead accounts for fixed portion of size of shared_vector field const static uint32_t fixed_overhead_shared_vector_ram_bytes = 16; ///< overhead accounts for fixed portion of size of shared_vector field
const static uint32_t overhead_per_row_per_index_ram_bytes = 32; ///< overhead accounts for basic tracking structures in a row per index const static uint32_t overhead_per_row_per_index_ram_bytes = 32; ///< overhead accounts for basic tracking structures in a row per index
const static uint32_t overhead_per_account_ram_bytes = 2*1024; ///< overhead accounts for basic account storage and pre-pays features like account recovery const static uint32_t overhead_per_account_ram_bytes = 2*1024; ///< overhead accounts for basic account storage and pre-pays features like account recovery
const static uint32_t setcode_ram_bytes_multiplier = 10; ///< multiplier on contract size to account for multiple copies and cached compilation const static uint32_t setcode_ram_bytes_multiplier = 10; ///< multiplier on contract size to account for multiple copies and cached compilation
......
...@@ -203,16 +203,16 @@ namespace eosio { namespace chain { ...@@ -203,16 +203,16 @@ namespace eosio { namespace chain {
3080001, "account using more than allotted RAM usage" ) 3080001, "account using more than allotted RAM usage" )
FC_DECLARE_DERIVED_EXCEPTION( tx_net_usage_exceeded, resource_exhausted_exception, FC_DECLARE_DERIVED_EXCEPTION( tx_net_usage_exceeded, resource_exhausted_exception,
3080002, "transaction exceeded the current network usage limit imposed on the transaction" ) 3080002, "transaction exceeded the current network usage limit imposed on the transaction" )
FC_DECLARE_DERIVED_EXCEPTION( tx_soft_net_usage_exceeded, resource_exhausted_exception, FC_DECLARE_DERIVED_EXCEPTION( block_net_usage_exceeded, resource_exhausted_exception,
3080003, "transaction network usage is too much for the remaining allowable usage of the current block" ) 3080003, "transaction network usage is too much for the remaining allowable usage of the current block" )
FC_DECLARE_DERIVED_EXCEPTION( tx_cpu_usage_exceeded, resource_exhausted_exception, FC_DECLARE_DERIVED_EXCEPTION( tx_cpu_usage_exceeded, resource_exhausted_exception,
3080004, "transaction exceeded the current CPU usage limit imposed on the transaction" ) 3080004, "transaction exceeded the current CPU usage limit imposed on the transaction" )
FC_DECLARE_DERIVED_EXCEPTION( tx_soft_cpu_usage_exceeded, resource_exhausted_exception, FC_DECLARE_DERIVED_EXCEPTION( block_cpu_usage_exceeded, resource_exhausted_exception,
3080005, "transaction CPU usage is too much for the remaining allowable usage of the current block" ) 3080005, "transaction CPU usage is too much for the remaining allowable usage of the current block" )
FC_DECLARE_DERIVED_EXCEPTION( tx_deadline_exceeded, resource_exhausted_exception, FC_DECLARE_DERIVED_EXCEPTION( deadline_exception, resource_exhausted_exception,
3080006, "transaction took too long" ) 3080006, "transaction took too long" )
FC_DECLARE_DERIVED_EXCEPTION( action_cpu_usage_exceeded, resource_exhausted_exception, FC_DECLARE_DERIVED_EXCEPTION( leeway_deadline_exception, deadline_exception,
3080007, "action took too long" ) 3081001, "transaction reached the deadline set due to leeway on account CPU limits" )
FC_DECLARE_DERIVED_EXCEPTION( authorization_exception, chain_exception, FC_DECLARE_DERIVED_EXCEPTION( authorization_exception, chain_exception,
3090000, "Authorization exception" ) 3090000, "Authorization exception" )
......
...@@ -15,17 +15,13 @@ namespace eosio { namespace chain { ...@@ -15,17 +15,13 @@ namespace eosio { namespace chain {
const transaction_id_type& trx_id, const transaction_id_type& trx_id,
fc::time_point start = fc::time_point::now() ); fc::time_point start = fc::time_point::now() );
void init_for_implicit_trx( fc::time_point deadline, void init_for_implicit_trx( uint64_t initial_net_usage = 0 );
uint64_t initial_net_usage = 0
);
void init_for_input_trx( fc::time_point deadline, void init_for_input_trx( uint64_t packed_trx_unprunable_size,
uint64_t packed_trx_unprunable_size,
uint64_t packed_trx_prunable_size, uint64_t packed_trx_prunable_size,
uint32_t num_signatures ); uint32_t num_signatures );
void init_for_deferred_trx( fc::time_point deadline, void init_for_deferred_trx( fc::time_point published );
fc::time_point published );
void exec(); void exec();
void finalize(); void finalize();
...@@ -50,6 +46,8 @@ namespace eosio { namespace chain { ...@@ -50,6 +46,8 @@ namespace eosio { namespace chain {
void schedule_transaction(); void schedule_transaction();
void record_transaction( const transaction_id_type& id, fc::time_point_sec expire ); void record_transaction( const transaction_id_type& id, fc::time_point_sec expire );
void validate_cpu_usage_to_bill( int64_t u, bool check_minimum = true )const;
/// Fields: /// Fields:
public: public:
...@@ -61,16 +59,12 @@ namespace eosio { namespace chain { ...@@ -61,16 +59,12 @@ namespace eosio { namespace chain {
fc::time_point start; fc::time_point start;
fc::time_point published; fc::time_point published;
fc::time_point deadline = fc::time_point::maximum();
vector<action_receipt> executed; vector<action_receipt> executed;
flat_set<account_name> bill_to_accounts; flat_set<account_name> bill_to_accounts;
flat_set<account_name> validate_ram_usage; flat_set<account_name> validate_ram_usage;
/// the maximum number of network usage bytes the transaction can consume (ignoring what billable accounts can pay and ignoring the remaining usage available in the block)
uint64_t max_net = 0;
uint64_t eager_net_limit = 0;
/// the maximum number of virtual CPU instructions of the transaction that can be safely billed to the billable accounts /// the maximum number of virtual CPU instructions of the transaction that can be safely billed to the billable accounts
uint64_t initial_max_billable_cpu = 0; uint64_t initial_max_billable_cpu = 0;
...@@ -78,14 +72,22 @@ namespace eosio { namespace chain { ...@@ -78,14 +72,22 @@ namespace eosio { namespace chain {
bool is_input = false; bool is_input = false;
bool apply_context_free = true; bool apply_context_free = true;
uint32_t billed_cpu_time_us = 0; fc::time_point deadline = fc::time_point::maximum();
fc::microseconds leeway = fc::microseconds(1000);
int64_t billed_cpu_time_us = 0;
private: private:
bool is_initialized = false;
uint64_t net_limit = 0;
bool net_limit_due_to_block = true;
uint64_t eager_net_limit = 0;
uint64_t& net_usage; /// reference to trace->net_usage uint64_t& net_usage; /// reference to trace->net_usage
bool net_limit_due_to_block = false;
bool cpu_limit_due_to_block = false;
bool is_initialized = false;
fc::microseconds objective_duration_limit;
bool objective_duration_limit_due_to_block = true;
int64_t deadline_exception_code = block_cpu_usage_exceeded::code_value;
}; };
} } } }
...@@ -316,8 +316,12 @@ uint64_t resource_limits_manager::get_block_net_limit() const { ...@@ -316,8 +316,12 @@ uint64_t resource_limits_manager::get_block_net_limit() const {
int64_t resource_limits_manager::get_account_cpu_limit( const account_name& name ) const { int64_t resource_limits_manager::get_account_cpu_limit( const account_name& name ) const {
const auto& state = _db.get<resource_limits_state_object>(); const auto& state = _db.get<resource_limits_state_object>();
const auto& usage = _db.get<resource_usage_object, by_owner>(name); const auto& usage = _db.get<resource_usage_object, by_owner>(name);
const auto& limits = _db.get<resource_limits_object, by_owner>(boost::make_tuple(false, name));
if (limits.cpu_weight < 0) { int64_t x;
int64_t cpu_weight;
get_account_limits( name, x, x, cpu_weight );
if( cpu_weight < 0 ) {
return -1; return -1;
} }
...@@ -327,10 +331,9 @@ int64_t resource_limits_manager::get_account_cpu_limit( const account_name& name ...@@ -327,10 +331,9 @@ int64_t resource_limits_manager::get_account_cpu_limit( const account_name& name
uint128_t consumed_ex = (uint128_t)usage.cpu_usage.consumed * (uint128_t)config::rate_limiting_precision; uint128_t consumed_ex = (uint128_t)usage.cpu_usage.consumed * (uint128_t)config::rate_limiting_precision;
uint128_t virtual_capacity_ex = (uint128_t)state.virtual_cpu_limit * (uint128_t)config::rate_limiting_precision; uint128_t virtual_capacity_ex = (uint128_t)state.virtual_cpu_limit * (uint128_t)config::rate_limiting_precision;
uint128_t usable_capacity_ex = (uint128_t)(virtual_capacity_ex * limits.cpu_weight) / (uint128_t)total_cpu_weight; uint128_t usable_capacity_ex = (uint128_t)(virtual_capacity_ex * cpu_weight) / (uint128_t)total_cpu_weight;
//idump((virtual_capacity_ex)(total_cpu_weight)(limits.cpu_weight)(usable_capacity_ex)(consumed_ex)(config::rate_limiting_precision) ); if( usable_capacity_ex < consumed_ex ) {
if (usable_capacity_ex < consumed_ex) {
return 0; return 0;
} }
...@@ -341,8 +344,12 @@ account_resource_limit resource_limits_manager::get_account_cpu_limit_ex( const ...@@ -341,8 +344,12 @@ account_resource_limit resource_limits_manager::get_account_cpu_limit_ex( const
const auto& cfg = _db.get<resource_limits_config_object>(); const auto& cfg = _db.get<resource_limits_config_object>();
const auto& state = _db.get<resource_limits_state_object>(); const auto& state = _db.get<resource_limits_state_object>();
const auto& usage = _db.get<resource_usage_object, by_owner>(name); const auto& usage = _db.get<resource_usage_object, by_owner>(name);
const auto& limits = _db.get<resource_limits_object, by_owner>(boost::make_tuple(false, name));
if (limits.cpu_weight < 0) { int64_t x;
int64_t cpu_weight;
get_account_limits( name, x, x, cpu_weight );
if( cpu_weight < 0 ) {
return { -1, -1, -1 }; return { -1, -1, -1 };
} }
...@@ -352,15 +359,14 @@ account_resource_limit resource_limits_manager::get_account_cpu_limit_ex( const ...@@ -352,15 +359,14 @@ account_resource_limit resource_limits_manager::get_account_cpu_limit_ex( const
uint128_t consumed_ex = (uint128_t)usage.cpu_usage.consumed * (uint128_t)config::rate_limiting_precision; uint128_t consumed_ex = (uint128_t)usage.cpu_usage.consumed * (uint128_t)config::rate_limiting_precision;
uint128_t virtual_capacity_ex = (uint128_t)state.virtual_cpu_limit * (uint128_t)config::rate_limiting_precision; uint128_t virtual_capacity_ex = (uint128_t)state.virtual_cpu_limit * (uint128_t)config::rate_limiting_precision;
uint128_t usable_capacity_ex = (uint128_t)(virtual_capacity_ex * limits.cpu_weight) / (uint128_t)total_cpu_weight; uint128_t usable_capacity_ex = (uint128_t)(virtual_capacity_ex * cpu_weight) / (uint128_t)total_cpu_weight;
wdump((cfg.cpu_limit_parameters.target));
uint128_t real_capacity_ex = (uint128_t)cfg.cpu_limit_parameters.target * (uint128_t)config::rate_limiting_precision; uint128_t real_capacity_ex = (uint128_t)cfg.cpu_limit_parameters.target * (uint128_t)config::rate_limiting_precision;
uint128_t guaranteed_capacity_ex = (uint128_t)(real_capacity_ex * limits.cpu_weight) / (uint128_t)total_cpu_weight; uint128_t guaranteed_capacity_ex = (uint128_t)(real_capacity_ex * cpu_weight) / (uint128_t)total_cpu_weight;
uint128_t blocks_per_day = 86400 * 1000 / config::block_interval_ms; uint128_t blocks_per_day = 86400 * 1000 / config::block_interval_ms;
if (usable_capacity_ex < consumed_ex) { if( usable_capacity_ex < consumed_ex ) {
consumed_ex = usable_capacity_ex; consumed_ex = usable_capacity_ex;
} }
return { (int64_t)(std::min(usable_capacity_ex - consumed_ex, real_capacity_ex) / (uint128_t)config::rate_limiting_precision), return { (int64_t)(std::min(usable_capacity_ex - consumed_ex, real_capacity_ex) / (uint128_t)config::rate_limiting_precision),
...@@ -372,8 +378,12 @@ account_resource_limit resource_limits_manager::get_account_cpu_limit_ex( const ...@@ -372,8 +378,12 @@ account_resource_limit resource_limits_manager::get_account_cpu_limit_ex( const
int64_t resource_limits_manager::get_account_net_limit( const account_name& name ) const { int64_t resource_limits_manager::get_account_net_limit( const account_name& name ) const {
const auto& state = _db.get<resource_limits_state_object>(); const auto& state = _db.get<resource_limits_state_object>();
const auto& usage = _db.get<resource_usage_object, by_owner>(name); const auto& usage = _db.get<resource_usage_object, by_owner>(name);
const auto& limits = _db.get<resource_limits_object, by_owner>(boost::make_tuple(false, name));
if (limits.net_weight < 0) { int64_t x;
int64_t net_weight;
get_account_limits( name, x, net_weight, x );
if( net_weight < 0 ) {
return -1; return -1;
} }
...@@ -383,9 +393,9 @@ int64_t resource_limits_manager::get_account_net_limit( const account_name& name ...@@ -383,9 +393,9 @@ int64_t resource_limits_manager::get_account_net_limit( const account_name& name
auto total_net_weight = state.total_net_weight; auto total_net_weight = state.total_net_weight;
if( total_net_weight == 0 ) total_net_weight = 1; if( total_net_weight == 0 ) total_net_weight = 1;
uint128_t usable_capacity_ex = (uint128_t)(virtual_capacity_ex * limits.net_weight) / (uint128_t)total_net_weight; // max uint128_t usable_capacity_ex = (uint128_t)(virtual_capacity_ex * net_weight) / (uint128_t)total_net_weight; // max
if (usable_capacity_ex < consumed_ex) { if( usable_capacity_ex < consumed_ex ) {
return 0; return 0;
} }
...@@ -397,8 +407,12 @@ account_resource_limit resource_limits_manager::get_account_net_limit_ex( const ...@@ -397,8 +407,12 @@ account_resource_limit resource_limits_manager::get_account_net_limit_ex( const
const auto& cfg = _db.get<resource_limits_config_object>(); const auto& cfg = _db.get<resource_limits_config_object>();
const auto& state = _db.get<resource_limits_state_object>(); const auto& state = _db.get<resource_limits_state_object>();
const auto& usage = _db.get<resource_usage_object, by_owner>(name); const auto& usage = _db.get<resource_usage_object, by_owner>(name);
const auto& limits = _db.get<resource_limits_object, by_owner>(boost::make_tuple(false, name));
if (limits.net_weight < 0) { int64_t x;
int64_t net_weight;
get_account_limits( name, x, net_weight, x );
if( net_weight < 0 ) {
return { -1, -1, -1 }; return { -1, -1, -1 };
} }
...@@ -408,14 +422,14 @@ account_resource_limit resource_limits_manager::get_account_net_limit_ex( const ...@@ -408,14 +422,14 @@ account_resource_limit resource_limits_manager::get_account_net_limit_ex( const
uint128_t consumed_ex = (uint128_t)usage.net_usage.consumed * (uint128_t)config::rate_limiting_precision; uint128_t consumed_ex = (uint128_t)usage.net_usage.consumed * (uint128_t)config::rate_limiting_precision;
uint128_t virtual_capacity_ex = (uint128_t)state.virtual_net_limit * (uint128_t)config::rate_limiting_precision; uint128_t virtual_capacity_ex = (uint128_t)state.virtual_net_limit * (uint128_t)config::rate_limiting_precision;
uint128_t usable_capacity_ex = (uint128_t)(virtual_capacity_ex * limits.net_weight) / (uint128_t)total_net_weight; // max uint128_t usable_capacity_ex = (uint128_t)(virtual_capacity_ex * net_weight) / (uint128_t)total_net_weight; // max
uint128_t real_capacity_ex = (uint128_t)cfg.net_limit_parameters.target * (uint128_t)config::rate_limiting_precision; uint128_t real_capacity_ex = (uint128_t)cfg.net_limit_parameters.target * (uint128_t)config::rate_limiting_precision;
uint128_t guaranteed_capacity_ex = (uint128_t)(real_capacity_ex * limits.net_weight) / (uint128_t)total_net_weight; uint128_t guaranteed_capacity_ex = (uint128_t)(real_capacity_ex * net_weight) / (uint128_t)total_net_weight;
uint128_t blocks_per_day = 86400 * 1000 / config::block_interval_ms; uint128_t blocks_per_day = 86400 * 1000 / config::block_interval_ms;
if (usable_capacity_ex < consumed_ex) { if( usable_capacity_ex < consumed_ex ) {
consumed_ex = usable_capacity_ex; consumed_ex = usable_capacity_ex;
} }
return { (int64_t)(std::min(usable_capacity_ex - consumed_ex, real_capacity_ex) / (uint128_t)config::rate_limiting_precision), return { (int64_t)(std::min(usable_capacity_ex - consumed_ex, real_capacity_ex) / (uint128_t)config::rate_limiting_precision),
......
...@@ -29,99 +29,113 @@ namespace eosio { namespace chain { ...@@ -29,99 +29,113 @@ namespace eosio { namespace chain {
void transaction_context::init(uint64_t initial_net_usage ) void transaction_context::init(uint64_t initial_net_usage )
{ {
FC_ASSERT( !is_initialized, "cannot initialize twice" ); FC_ASSERT( !is_initialized, "cannot initialize twice" );
const static int64_t large_number_no_overflow = std::numeric_limits<int64_t>::max()/2;
auto original_deadline = deadline;
const auto& cfg = control.get_global_properties().configuration;
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;
// Check if deadline is limited by block deadline or caller-set deadline
if( original_deadline <= deadline ) {
deadline = original_deadline;
deadline_exception_code = deadline_exception::code_value;
}
// Possibly lower net_limit to the maximum net usage a transaction is allowed to be billed
if( cfg.max_transaction_net_usage <= net_limit ) {
net_limit = cfg.max_transaction_net_usage;
net_limit_due_to_block = false;
}
// Possibly lower net_limit to optional limit set in the transaction header
uint64_t trx_specified_net_usage_limit = static_cast<uint64_t>(trx.max_net_usage_words.value) * 8;
if( trx_specified_net_usage_limit > 0 && trx_specified_net_usage_limit <= net_limit ) {
net_limit = trx_specified_net_usage_limit;
net_limit_due_to_block = false;
}
// Possibly lower objective_duration_limit to optional limit set in transaction header
if( trx.max_cpu_usage_ms > 0 ) {
auto trx_specified_cpu_usage_limit = fc::milliseconds(trx.max_cpu_usage_ms);
if( trx_specified_cpu_usage_limit <= objective_duration_limit ) {
objective_duration_limit = trx_specified_cpu_usage_limit;
objective_duration_limit_due_to_block = false;
}
}
// Possibly limit deadline if objective_duration_limit is not due to the block and does not exceed current delta
if( !objective_duration_limit_due_to_block && objective_duration_limit <= (deadline - start) ) {
deadline = start + objective_duration_limit;
deadline_exception_code = tx_cpu_usage_exceeded::code_value;
}
if( billed_cpu_time_us > 0 )
validate_cpu_usage_to_bill( billed_cpu_time_us, false ); // Fail early if the amount to be billed is too high
// Record accounts to be billed for network and CPU usage // Record accounts to be billed for network and CPU usage
uint64_t determine_payers_cpu_cost = 0;
for( const auto& act : trx.actions ) { for( const auto& act : trx.actions ) {
for( const auto& auth : act.authorization ) { for( const auto& auth : act.authorization ) {
bill_to_accounts.insert( auth.actor ); bill_to_accounts.insert( auth.actor );
determine_payers_cpu_cost += config::determine_payers_cpu_overhead_per_authorization;
} }
} }
validate_ram_usage.reserve( bill_to_accounts.size() ); validate_ram_usage.reserve( bill_to_accounts.size() );
// Calculate network and CPU usage limits and initial usage:
// Start with limits set in dynamic configuration
const auto& cfg = control.get_global_properties().configuration;
max_net = cfg.max_transaction_net_usage;
// Potentially lower limits to what is optionally set in the transaction header
uint64_t trx_specified_net_usage_limit = static_cast<uint64_t>(trx.max_net_usage_words.value)*8;
if( trx_specified_net_usage_limit > 0 )
max_net = std::min( max_net, trx_specified_net_usage_limit );
eager_net_limit = max_net;
// Update usage values of accounts to reflect new time // Update usage values of accounts to reflect new time
auto& rl = control.get_mutable_resource_limits_manager();
rl.add_transaction_usage( bill_to_accounts, 0, 0, block_timestamp_type(control.pending_block_time()).slot ); rl.add_transaction_usage( bill_to_accounts, 0, 0, block_timestamp_type(control.pending_block_time()).slot );
uint64_t block_net_limit = rl.get_block_net_limit(); // Calculate the highest network usage and CPU time that all of the billed accounts can afford to be billed
uint64_t block_cpu_limit = rl.get_block_cpu_limit(); int64_t account_net_limit = large_number_no_overflow;
int64_t account_cpu_limit = large_number_no_overflow;
if( !billed_cpu_time_us ) { for( const auto& a : bill_to_accounts ) {
idump((block_cpu_limit)); auto net_limit = rl.get_account_net_limit(a);
auto potential_deadline = start + fc::microseconds(block_cpu_limit); if( net_limit >= 0 )
if( potential_deadline < deadline ) deadline = potential_deadline; account_net_limit = std::min( account_net_limit, net_limit );
auto cpu_limit = rl.get_account_cpu_limit(a);
if( cpu_limit >= 0 )
account_cpu_limit = std::min( account_cpu_limit, cpu_limit );
} }
if( block_net_limit < eager_net_limit ) { eager_net_limit = net_limit;
eager_net_limit = block_net_limit;
net_limit_due_to_block = true;
}
// Initial billing for network usage // Possible lower eager_net_limit to what the billed accounts can pay plus some (objective) leeway
if( initial_net_usage > 0 ) auto new_eager_net_limit = std::min( eager_net_limit, static_cast<uint64_t>(account_net_limit + cfg.net_usage_leeway) );
add_net_usage( initial_net_usage ); if( new_eager_net_limit < eager_net_limit ) {
eager_net_limit = new_eager_net_limit;
eager_net_limit = max_net; net_limit_due_to_block = false;
net_limit_due_to_block = false;
// Lower limits to what the billed accounts can afford to pay
if( !billed_cpu_time_us ) {
for( const auto& a : bill_to_accounts ) {
auto net_limit = rl.get_account_net_limit(a);
if( net_limit >= 0 )
eager_net_limit = std::min( eager_net_limit, static_cast<uint64_t>(net_limit) ); // reduce max_net to the amount the account is able to pay
auto cpu_limit = rl.get_account_cpu_limit(a);
if( cpu_limit > 0 ) {
auto potential_deadline = start + fc::microseconds(cpu_limit);
if( potential_deadline < deadline ) {
wdump((potential_deadline)(cpu_limit));
deadline = potential_deadline;
}
}
}
} }
eager_net_limit += cfg.net_usage_leeway; // Possibly limit deadline if the duration accounts can be billed for (+ a subjective leeway) does not exceed current delta
eager_net_limit = std::min(eager_net_limit, max_net); if( ( fc::microseconds(account_cpu_limit) + leeway ) <= (deadline - start) ) {
deadline = start + fc::microseconds(account_cpu_limit) + leeway;
if( block_net_limit < eager_net_limit ) { deadline_exception_code = leeway_deadline_exception::code_value;
eager_net_limit = block_net_limit;
net_limit_due_to_block = true;
} }
// Round down network and CPU usage limits so that comparison to actual usage is more efficient eager_net_limit = (eager_net_limit/8)*8; // Round down to nearest multiple of word size (8 bytes) so check_net_usage can be efficient
eager_net_limit = (eager_net_limit/8)*8; // Round down to nearest multiple of word size (8 bytes)
if( initial_net_usage > 0 ) if( initial_net_usage > 0 )
check_net_usage(); // Fail early if current net usage is already greater than the calculated limit add_net_usage( initial_net_usage ); // Fail early if current net usage is already greater than the calculated limit
if( billed_cpu_time_us > 0 )
deadline = original_deadline; // Only change deadline if billed_cpu_time_us is not set
check_time(); // Fail early if deadline has already been exceeded
is_initialized = true; is_initialized = true;
} }
void transaction_context::init_for_implicit_trx( fc::time_point d, uint64_t initial_net_usage ) void transaction_context::init_for_implicit_trx( uint64_t initial_net_usage )
{ {
published = control.pending_block_time(); published = control.pending_block_time();
deadline = d;
init( initial_net_usage ); init( initial_net_usage );
} }
void transaction_context::init_for_input_trx( fc::time_point d, void transaction_context::init_for_input_trx( uint64_t packed_trx_unprunable_size,
uint64_t packed_trx_unprunable_size,
uint64_t packed_trx_prunable_size, uint64_t packed_trx_prunable_size,
uint32_t num_signatures ) uint32_t num_signatures )
{ {
...@@ -148,7 +162,6 @@ namespace eosio { namespace chain { ...@@ -148,7 +162,6 @@ namespace eosio { namespace chain {
} }
published = control.pending_block_time(); published = control.pending_block_time();
deadline = d;
is_input = true; is_input = true;
control.validate_expiration( trx ); control.validate_expiration( trx );
control.validate_tapos( trx ); control.validate_tapos( trx );
...@@ -157,11 +170,9 @@ namespace eosio { namespace chain { ...@@ -157,11 +170,9 @@ namespace eosio { namespace chain {
record_transaction( id, trx.expiration ); /// checks for dupes record_transaction( id, trx.expiration ); /// checks for dupes
} }
void transaction_context::init_for_deferred_trx( fc::time_point d, void transaction_context::init_for_deferred_trx( fc::time_point p )
fc::time_point p )
{ {
published = p; published = p;
deadline = d;
trace->scheduled = true; trace->scheduled = true;
apply_context_free = false; apply_context_free = false;
init( 0 ); init( 0 );
...@@ -189,6 +200,7 @@ namespace eosio { namespace chain { ...@@ -189,6 +200,7 @@ namespace eosio { namespace chain {
void transaction_context::finalize() { void transaction_context::finalize() {
FC_ASSERT( is_initialized, "must first initialize" ); FC_ASSERT( is_initialized, "must first initialize" );
const static int64_t large_number_no_overflow = std::numeric_limits<int64_t>::max()/2;
if( is_input ) { if( is_input ) {
auto& am = control.get_mutable_authorization_manager(); auto& am = control.get_mutable_authorization_manager();
...@@ -204,27 +216,43 @@ namespace eosio { namespace chain { ...@@ -204,27 +216,43 @@ namespace eosio { namespace chain {
rl.verify_account_ram_usage( a ); rl.verify_account_ram_usage( a );
} }
eager_net_limit = max_net; // 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 = large_number_no_overflow;
net_limit_due_to_block = false; int64_t account_cpu_limit = large_number_no_overflow;
// Lower limits to what the billed accounts can afford to pay
for( const auto& a : bill_to_accounts ) { for( const auto& a : bill_to_accounts ) {
auto net_limit = rl.get_account_net_limit(a); auto net_limit = rl.get_account_net_limit(a);
if( net_limit >= 0 ) if( net_limit >= 0 )
eager_net_limit = std::min( eager_net_limit, static_cast<uint64_t>(net_limit) ); // reduce max_net to the amount the account is able to pay account_net_limit = std::min( account_net_limit, net_limit );
auto cpu_limit = rl.get_account_cpu_limit(a);
if( cpu_limit >= 0 )
account_cpu_limit = std::min( account_cpu_limit, cpu_limit );
}
// Possibly lower net_limit to what the billed accounts can pay
if( static_cast<uint64_t>(account_net_limit) <= net_limit ) {
net_limit = static_cast<uint64_t>(account_net_limit);
net_limit_due_to_block = false;
}
// Possibly lower objective_duration_limit to what the billed accounts can pay
if( account_cpu_limit <= objective_duration_limit.count() ) {
objective_duration_limit = fc::microseconds(account_cpu_limit);
objective_duration_limit_due_to_block = false;
} }
net_usage = ((net_usage + 7)/8)*8; // Round up to nearest multiple of word size (8 bytes) net_usage = ((net_usage + 7)/8)*8; // Round up to nearest multiple of word size (8 bytes)
eager_net_limit = net_limit;
check_net_usage(); check_net_usage();
trace->elapsed = fc::time_point::now() - start; trace->elapsed = fc::time_point::now() - start;
if( !billed_cpu_time_us ) if( billed_cpu_time_us == 0 )
billed_cpu_time_us = trace->elapsed.count(); billed_cpu_time_us = std::max( trace->elapsed.count(), static_cast<int64_t>(config::default_min_transaction_cpu_usage_us) );
validate_cpu_usage_to_bill( billed_cpu_time_us );
rl.add_transaction_usage( bill_to_accounts, billed_cpu_time_us, net_usage, 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 block_timestamp_type(control.pending_block_time()).slot ); // Should never fail
} }
...@@ -235,22 +263,60 @@ namespace eosio { namespace chain { ...@@ -235,22 +263,60 @@ namespace eosio { namespace chain {
void transaction_context::check_net_usage()const { void transaction_context::check_net_usage()const {
if( BOOST_UNLIKELY(net_usage > eager_net_limit) ) { if( BOOST_UNLIKELY(net_usage > eager_net_limit) ) {
if( BOOST_UNLIKELY( net_limit_due_to_block ) ) { if( net_limit_due_to_block ) {
EOS_THROW( tx_soft_net_usage_exceeded, EOS_THROW( block_net_usage_exceeded,
"not enough space left in block: ${actual_net_usage} > ${net_usage_limit}", "not enough space left in block: ${net_usage} > ${net_limit}",
("actual_net_usage", net_usage)("net_usage_limit", max_net) ); ("net_usage", net_usage)("net_limit", eager_net_limit) );
} else { } else {
EOS_THROW( tx_net_usage_exceeded, EOS_THROW( tx_net_usage_exceeded,
"net usage of transaction is too high: ${actual_net_usage} > ${net_usage_limit}", "net usage of transaction is too high: ${net_usage} > ${net_limit}",
("actual_net_usage", net_usage)("net_usage_limit", max_net) ); ("net_usage", net_usage)("net_limit", eager_net_limit) );
} }
} }
} }
void transaction_context::check_time()const { void transaction_context::check_time()const {
EOS_ASSERT( BOOST_LIKELY(fc::time_point::now() <= deadline), tx_deadline_exceeded, auto now = fc::time_point::now();
"deadline exceeded", if( BOOST_UNLIKELY( now > deadline ) ) {
("now",fc::time_point::now())("deadline",deadline)("start",start) ); if( billed_cpu_time_us > 0 || deadline_exception_code == deadline_exception::code_value ) {
EOS_THROW( deadline_exception, "deadline exceeded", ("now", now)("deadline", deadline)("start", start) );
} else if( deadline_exception_code == block_cpu_usage_exceeded::code_value ) {
EOS_THROW( block_cpu_usage_exceeded,
"not enough time left in block to complete executing transaction",
("now", now)("deadline", deadline)("start", start) );
} else if( deadline_exception_code == tx_cpu_usage_exceeded::code_value ) {
EOS_THROW( tx_cpu_usage_exceeded,
"transaction was executing for too long",
("now", now)("deadline", deadline)("start", start) );
} else if( deadline_exception_code == leeway_deadline_exception::code_value ) {
EOS_THROW( leeway_deadline_exception,
"the transaction was unable to complete by deadline, "
"but it is possible it could have succeeded if it were allow to run to completion",
("now", now)("deadline", deadline)("start", start) );
}
FC_ASSERT( false, "unexpected deadline exception code" );
}
}
void transaction_context::validate_cpu_usage_to_bill( int64_t billed_us, bool check_minimum )const {
#warning make min_transaction_cpu_us into a configuration parameter
EOS_ASSERT( !check_minimum || billed_us >= config::default_min_transaction_cpu_usage_us, transaction_exception,
"cannot bill CPU time less than the minimum of ${min_billable} us",
("min_billable", config::default_min_transaction_cpu_usage_us)("billed_cpu_time_us", billed_us)
);
if( objective_duration_limit_due_to_block ) {
EOS_ASSERT( billed_us <= objective_duration_limit.count(),
block_cpu_usage_exceeded,
"billed CPU time (${billed} us) is greater than the billable CPU time left in the block (${billable} us)",
("billed", billed_us)("billable", objective_duration_limit.count())
);
} else {
EOS_ASSERT( billed_us <= objective_duration_limit.count(),
tx_cpu_usage_exceeded,
"billed CPU time (${billed} us) is greater than the maximum billable CPU time for the transaction (${billable} us)",
("billed", billed_us)("billable", objective_duration_limit.count())
);
}
} }
void transaction_context::add_ram_usage( account_name account, int64_t ram_delta ) { void transaction_context::add_ram_usage( account_name account, int64_t ram_delta ) {
...@@ -268,9 +334,6 @@ namespace eosio { namespace chain { ...@@ -268,9 +334,6 @@ namespace eosio { namespace chain {
try { try {
acontext.exec(); acontext.exec();
} catch( const action_cpu_usage_exceeded& e ) {
trace = move(acontext.trace);
FC_ASSERT(false, "should not have reached here" );
} catch( ... ) { } catch( ... ) {
trace = move(acontext.trace); trace = move(acontext.trace);
throw; throw;
......
...@@ -87,8 +87,8 @@ namespace eosio { namespace testing { ...@@ -87,8 +87,8 @@ namespace eosio { namespace testing {
void produce_blocks_until_end_of_round(); void produce_blocks_until_end_of_round();
signed_block_ptr push_block(signed_block_ptr b); signed_block_ptr push_block(signed_block_ptr b);
transaction_trace_ptr push_transaction( packed_transaction& trx, uint32_t skip_flag = 0/*skip_nothing */, fc::time_point deadline = fc::time_point::maximum(), uint32_t billed_cpu_time_us = DEFAULT_BILLED_CPU_TIME_US ); 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 );
transaction_trace_ptr push_transaction( signed_transaction& trx, uint32_t skip_flag = 0/*skip_nothing*/, fc::time_point deadline = fc::time_point::maximum(), uint32_t billed_cpu_time_us = DEFAULT_BILLED_CPU_TIME_US ); transaction_trace_ptr push_transaction( signed_transaction& trx, fc::time_point deadline = fc::time_point::maximum(), uint32_t billed_cpu_time_us = DEFAULT_BILLED_CPU_TIME_US );
action_result push_action(action&& cert_act, uint64_t authorizer); // TODO/QUESTION: Is this needed? action_result push_action(action&& cert_act, uint64_t authorizer); // TODO/QUESTION: Is this needed?
transaction_trace_ptr push_action( const account_name& code, transaction_trace_ptr push_action( const account_name& code,
......
...@@ -243,12 +243,10 @@ namespace eosio { namespace testing { ...@@ -243,12 +243,10 @@ namespace eosio { namespace testing {
} }
transaction_trace_ptr base_tester::push_transaction( packed_transaction& trx, transaction_trace_ptr base_tester::push_transaction( packed_transaction& trx,
uint32_t skip_flag,
fc::time_point deadline, fc::time_point deadline,
uint32_t billed_cpu_time_us uint32_t billed_cpu_time_us
) )
{ try { { try {
wlog((deadline));
if( !control->pending_block_state() ) if( !control->pending_block_state() )
_start_block(control->head_block_time() + fc::microseconds(config::block_interval_us)); _start_block(control->head_block_time() + fc::microseconds(config::block_interval_us));
auto r = control->push_transaction( std::make_shared<transaction_metadata>(trx), deadline, billed_cpu_time_us ); auto r = control->push_transaction( std::make_shared<transaction_metadata>(trx), deadline, billed_cpu_time_us );
...@@ -258,12 +256,10 @@ namespace eosio { namespace testing { ...@@ -258,12 +256,10 @@ namespace eosio { namespace testing {
} FC_CAPTURE_AND_RETHROW( (transaction_header(trx.get_transaction())) ) } } FC_CAPTURE_AND_RETHROW( (transaction_header(trx.get_transaction())) ) }
transaction_trace_ptr base_tester::push_transaction( signed_transaction& trx, transaction_trace_ptr base_tester::push_transaction( signed_transaction& trx,
uint32_t skip_flag,
fc::time_point deadline, fc::time_point deadline,
uint32_t billed_cpu_time_us uint32_t billed_cpu_time_us
) )
{ try { { try {
wlog((deadline));
if( !control->pending_block_state() ) if( !control->pending_block_state() )
_start_block(control->head_block_time() + fc::microseconds(config::block_interval_us)); _start_block(control->head_block_time() + fc::microseconds(config::block_interval_us));
auto c = packed_transaction::none; auto c = packed_transaction::none;
......
...@@ -45,9 +45,10 @@ using namespace eosio::chain::plugin_interface; ...@@ -45,9 +45,10 @@ using namespace eosio::chain::plugin_interface;
namespace { namespace {
bool failure_is_subjective(const fc::exception& e, bool deadline_is_subjective) { bool failure_is_subjective(const fc::exception& e, bool deadline_is_subjective) {
auto code = e.code(); auto code = e.code();
return (code == tx_soft_cpu_usage_exceeded::code_value) || return (code == block_cpu_usage_exceeded::code_value) ||
(code == tx_soft_net_usage_exceeded::code_value) || (code == block_net_usage_exceeded::code_value) ||
(code == tx_deadline_exceeded::code_value && deadline_is_subjective); (code == deadline_exception::code_value && deadline_is_subjective) ||
(code == leeway_deadline_exception::code_value && deadline_is_subjective);
} }
} }
......
...@@ -33,12 +33,10 @@ add_dependencies(unit_test asserter test_api test_api_mem test_api_db test_api_m ...@@ -33,12 +33,10 @@ add_dependencies(unit_test asserter test_api test_api_mem test_api_db test_api_m
#To run unit_test with all log from blockchain displayed, put --verbose after --, i.e. unit_test -- --verbose #To run unit_test with all log from blockchain displayed, put --verbose after --, i.e. unit_test -- --verbose
add_test(NAME unit_test_binaryen COMMAND unit_test add_test(NAME unit_test_binaryen COMMAND unit_test
-t \!eosio_system_tests/* -t \!eosio_system_tests/*
-t \!resource_limits_test/enforce_block_limits_cpu
-t \!wasm_tests/weighted_cpu_limit_tests -t \!wasm_tests/weighted_cpu_limit_tests
--report_level=detailed --color_output -- --binaryen) --report_level=detailed --color_output -- --binaryen)
add_test(NAME unit_test_wavm COMMAND unit_test add_test(NAME unit_test_wavm COMMAND unit_test
-t \!eosio_system_tests/* -t \!eosio_system_tests/*
-t \!resource_limits_test/enforce_block_limits_cpu
-t \!wasm_tests/weighted_cpu_limit_tests -t \!wasm_tests/weighted_cpu_limit_tests
--report_level=detailed --color_output --catch_system_errors=no -- --wavm) --report_level=detailed --color_output --catch_system_errors=no -- --wavm)
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <eosio/chain/block_summary_object.hpp> #include <eosio/chain/block_summary_object.hpp>
#include <eosio/chain/global_property_object.hpp> #include <eosio/chain/global_property_object.hpp>
#include <eosio/chain/wasm_interface.hpp> #include <eosio/chain/wasm_interface.hpp>
#include <eosio/chain/resource_limits.hpp>
#include <fc/crypto/digest.hpp> #include <fc/crypto/digest.hpp>
#include <fc/crypto/sha256.hpp> #include <fc/crypto/sha256.hpp>
...@@ -207,8 +208,10 @@ bool is_page_memory_error(page_memory_error const &e) { return true; } ...@@ -207,8 +208,10 @@ bool is_page_memory_error(page_memory_error const &e) { return true; }
bool is_unsatisfied_authorization(unsatisfied_authorization const & e) { return true;} bool is_unsatisfied_authorization(unsatisfied_authorization const & e) { return true;}
bool is_wasm_execution_error(eosio::chain::wasm_execution_error const& e) {return true;} bool is_wasm_execution_error(eosio::chain::wasm_execution_error const& e) {return true;}
bool is_tx_net_usage_exceeded(const tx_net_usage_exceeded& e) { return true; } bool is_tx_net_usage_exceeded(const tx_net_usage_exceeded& e) { return true; }
bool is_block_net_usage_exceeded(const tx_cpu_usage_exceeded& e) { return true; }
bool is_tx_cpu_usage_exceeded(const tx_cpu_usage_exceeded& e) { return true; } bool is_tx_cpu_usage_exceeded(const tx_cpu_usage_exceeded& e) { return true; }
bool is_tx_deadline_exceeded(const tx_deadline_exceeded& e) { return true; } bool is_block_cpu_usage_exceeded(const tx_cpu_usage_exceeded& e) { return true; }
bool is_deadline_exception(const deadline_exception& e) { return true; }
/* /*
* register test suite `api_tests` * register test suite `api_tests`
...@@ -647,8 +650,6 @@ BOOST_FIXTURE_TEST_CASE(checktime_pass_tests, TESTER) { try { ...@@ -647,8 +650,6 @@ BOOST_FIXTURE_TEST_CASE(checktime_pass_tests, TESTER) { try {
BOOST_REQUIRE_EQUAL( validate(), true ); BOOST_REQUIRE_EQUAL( validate(), true );
} FC_LOG_AND_RETHROW() } } FC_LOG_AND_RETHROW() }
#if 0
BOOST_AUTO_TEST_CASE(checktime_fail_tests) { try { BOOST_AUTO_TEST_CASE(checktime_fail_tests) { try {
// TODO: This is an extremely fragile test. It needs improvements: // TODO: This is an extremely fragile test. It needs improvements:
// 1) compilation of the smart contract should probably not count towards the CPU time of a transaction that first uses it; // 1) compilation of the smart contract should probably not count towards the CPU time of a transaction that first uses it;
...@@ -664,7 +665,11 @@ BOOST_AUTO_TEST_CASE(checktime_fail_tests) { try { ...@@ -664,7 +665,11 @@ BOOST_AUTO_TEST_CASE(checktime_fail_tests) { try {
ilog( "produce block" ); ilog( "produce block" );
t.produce_blocks(1); t.produce_blocks(1);
auto call_test = [](TESTER& test, auto ac) { int64_t x; int64_t net; int64_t cpu;
t.control->get_resource_limits_manager().get_account_limits( N(testapi), x, net, cpu );
wdump((net)(cpu));
auto call_test = [](TESTER& test, auto ac, uint32_t billed_cpu_time_us, uint8_t max_cpu_usage_ms ) {
signed_transaction trx; signed_transaction trx;
auto pl = vector<permission_level>{{N(testapi), config::active_name}}; auto pl = vector<permission_level>{{N(testapi), config::active_name}};
...@@ -674,19 +679,29 @@ BOOST_AUTO_TEST_CASE(checktime_fail_tests) { try { ...@@ -674,19 +679,29 @@ BOOST_AUTO_TEST_CASE(checktime_fail_tests) { try {
trx.actions.push_back(act); trx.actions.push_back(act);
test.set_transaction_headers(trx); test.set_transaction_headers(trx);
trx.max_cpu_usage_ms = max_cpu_usage_ms;
auto sigs = trx.sign(test.get_private_key(N(testapi), "active"), chain_id_type()); auto sigs = trx.sign(test.get_private_key(N(testapi), "active"), chain_id_type());
trx.get_signature_keys(chain_id_type() ); trx.get_signature_keys(chain_id_type() );
auto res = test.push_transaction(trx); auto res = test.push_transaction( trx, fc::time_point::now() + fc::milliseconds(200), billed_cpu_time_us );
BOOST_CHECK_EQUAL(res->receipt->status, transaction_receipt::executed); BOOST_CHECK_EQUAL(res->receipt->status, transaction_receipt::executed);
test.produce_block(); test.produce_block();
}; };
BOOST_CHECK_EXCEPTION(call_test( t, test_api_action<TEST_METHOD("test_checktime", "checktime_failure")>{}), tx_deadline_exceeded, is_tx_cpu_usage_exceeded /*tx_deadline_exceeded, is_tx_deadline_exceeded*/); BOOST_CHECK_EXCEPTION( call_test( t, test_api_action<TEST_METHOD("test_checktime", "checktime_failure")>{},
5000, 0 ),
deadline_exception, is_deadline_exception );
BOOST_CHECK_EXCEPTION( call_test( t, test_api_action<TEST_METHOD("test_checktime", "checktime_failure")>{},
0, 50 ),
tx_cpu_usage_exceeded, is_tx_cpu_usage_exceeded );
BOOST_CHECK_EXCEPTION( call_test( t, test_api_action<TEST_METHOD("test_checktime", "checktime_failure")>{},
0, 0 ),
block_cpu_usage_exceeded, is_block_cpu_usage_exceeded ); // Because the onblock uses up some of the CPU
BOOST_REQUIRE_EQUAL( t.validate(), true ); BOOST_REQUIRE_EQUAL( t.validate(), true );
} FC_LOG_AND_RETHROW() } } FC_LOG_AND_RETHROW() }
#endif
/************************************************************************************* /*************************************************************************************
* compiler_builtins_tests test case * compiler_builtins_tests test case
...@@ -1017,7 +1032,6 @@ BOOST_FIXTURE_TEST_CASE(chain_tests, TESTER) { try { ...@@ -1017,7 +1032,6 @@ BOOST_FIXTURE_TEST_CASE(chain_tests, TESTER) { try {
vector<account_name> prods( control->active_producers().producers.size() ); vector<account_name> prods( control->active_producers().producers.size() );
for ( uint32_t i = 0; i < prods.size(); i++ ) { for ( uint32_t i = 0; i < prods.size(); i++ ) {
prods[i] = control->active_producers().producers[i].producer_name; prods[i] = control->active_producers().producers[i].producer_name;
produce_block();
} }
CALL_TEST_FUNCTION( *this, "test_chain", "test_activeprods", fc::raw::pack(prods) ); CALL_TEST_FUNCTION( *this, "test_chain", "test_activeprods", fc::raw::pack(prods) );
......
...@@ -225,9 +225,7 @@ BOOST_FIXTURE_TEST_CASE( bootseq_test, bootseq_tester ) { ...@@ -225,9 +225,7 @@ BOOST_FIXTURE_TEST_CASE( bootseq_test, bootseq_tester ) {
// Issue the genesis supply of 1 billion EOS tokens to eosio.system // Issue the genesis supply of 1 billion EOS tokens to eosio.system
// Issue the genesis supply of 1 billion EOS tokens to eosio.system // Issue the genesis supply of 1 billion EOS tokens to eosio.system
ilog(".");
issue(N(eosio.token), config::system_account_name, config::system_account_name, initial_supply); issue(N(eosio.token), config::system_account_name, config::system_account_name, initial_supply);
ilog(".");
auto actual = get_balance(config::system_account_name); auto actual = get_balance(config::system_account_name);
...@@ -247,9 +245,7 @@ BOOST_FIXTURE_TEST_CASE( bootseq_test, bootseq_tester ) { ...@@ -247,9 +245,7 @@ BOOST_FIXTURE_TEST_CASE( bootseq_test, bootseq_tester ) {
("memo", "" ) ); ("memo", "" ) );
*/ */
} }
ilog("set code....");
set_code_abi(N(eosio), eosio_system_wast, eosio_system_abi); //, &eosio_active_pk); set_code_abi(N(eosio), eosio_system_wast, eosio_system_abi); //, &eosio_active_pk);
produce_blocks(1);
for( const auto& a : test_genesis ) { for( const auto& a : test_genesis ) {
auto ib = a.initial_balance; auto ib = a.initial_balance;
...@@ -264,7 +260,6 @@ BOOST_FIXTURE_TEST_CASE( bootseq_test, bootseq_tester ) { ...@@ -264,7 +260,6 @@ BOOST_FIXTURE_TEST_CASE( bootseq_test, bootseq_tester ) {
); );
BOOST_REQUIRE( !r->except_ptr ); BOOST_REQUIRE( !r->except_ptr );
wdump((a.aname)(net)(cpu));
r = base_tester::push_action(N(eosio), N(delegatebw), N(eosio), mutable_variant_object() r = base_tester::push_action(N(eosio), N(delegatebw), N(eosio), mutable_variant_object()
("from", "eosio" ) ("from", "eosio" )
("receiver", name(a.aname)) ("receiver", name(a.aname))
...@@ -273,7 +268,6 @@ BOOST_FIXTURE_TEST_CASE( bootseq_test, bootseq_tester ) { ...@@ -273,7 +268,6 @@ BOOST_FIXTURE_TEST_CASE( bootseq_test, bootseq_tester ) {
("transfer", 1) ("transfer", 1)
); );
produce_blocks(1);
BOOST_REQUIRE( !r->except_ptr ); BOOST_REQUIRE( !r->except_ptr );
} }
......
...@@ -206,7 +206,7 @@ BOOST_AUTO_TEST_SUITE(resource_limits_test) ...@@ -206,7 +206,7 @@ BOOST_AUTO_TEST_SUITE(resource_limits_test)
process_account_limit_updates(); process_account_limit_updates();
const uint64_t increment = 1000; const uint64_t increment = 1000;
const uint64_t expected_iterations = (config::default_max_block_cpu_usage + increment - 1 ) / increment; const uint64_t expected_iterations = config::default_max_block_cpu_usage / increment;
for (int idx = 0; idx < expected_iterations; idx++) { for (int idx = 0; idx < expected_iterations; idx++) {
add_transaction_usage({account}, increment, 0, 0); add_transaction_usage({account}, increment, 0, 0);
...@@ -223,9 +223,9 @@ BOOST_AUTO_TEST_SUITE(resource_limits_test) ...@@ -223,9 +223,9 @@ BOOST_AUTO_TEST_SUITE(resource_limits_test)
process_account_limit_updates(); process_account_limit_updates();
const uint64_t increment = 1000; const uint64_t increment = 1000;
const uint64_t expected_iterations = (config::default_max_block_net_usage + increment - 1 ) / increment; const uint64_t expected_iterations = config::default_max_block_net_usage / increment;
for (int idx = 0; idx < expected_iterations - 1; idx++) { for (int idx = 0; idx < expected_iterations; idx++) {
add_transaction_usage({account}, 0, increment, 0); add_transaction_usage({account}, 0, increment, 0);
} }
......
...@@ -616,7 +616,7 @@ BOOST_FIXTURE_TEST_CASE(weighted_cpu_limit_tests, tester ) try { ...@@ -616,7 +616,7 @@ BOOST_FIXTURE_TEST_CASE(weighted_cpu_limit_tests, tester ) try {
while (count < 4) { while (count < 4) {
signed_transaction trx; signed_transaction trx;
for (int i = 0; i < 1000; ++i) { for (int i = 0; i < 10; ++i) {
action act; action act;
act.account = N(f_tests); act.account = N(f_tests);
act.name = N() + (i * 16); act.name = N() + (i * 16);
...@@ -628,12 +628,12 @@ BOOST_FIXTURE_TEST_CASE(weighted_cpu_limit_tests, tester ) try { ...@@ -628,12 +628,12 @@ BOOST_FIXTURE_TEST_CASE(weighted_cpu_limit_tests, tester ) try {
trx.sign(get_private_key( N(f_tests), "active" ), chain_id_type()); trx.sign(get_private_key( N(f_tests), "active" ), chain_id_type());
try { try {
push_transaction(trx); push_transaction(trx, fc::time_point::maximum(), 0);
produce_blocks(1); produce_blocks(1);
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id())); BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
pass = true; pass = true;
count++; count++;
} catch (eosio::chain::tx_deadline_exceeded &) { } catch( eosio::chain::leeway_deadline_exception& ) {
BOOST_REQUIRE_EQUAL(count, 3); BOOST_REQUIRE_EQUAL(count, 3);
break; break;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册