Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Commit

Permalink
Merge pull request #8856 from EOSIO/light-validation-net
Browse files Browse the repository at this point in the history
Use NET bill in transaction receipt during light validation mode
  • Loading branch information
arhag authored Mar 24, 2020
2 parents 0205953 + fba13d7 commit 4ddcee0
Show file tree
Hide file tree
Showing 6 changed files with 235 additions and 32 deletions.
26 changes: 19 additions & 7 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1418,7 +1418,8 @@ struct controller_impl {
transaction_trace_ptr push_transaction( const transaction_metadata_ptr& trx,
fc::time_point deadline,
uint32_t billed_cpu_time_us,
bool explicit_billed_cpu_time )
bool explicit_billed_cpu_time,
fc::optional<uint32_t> explicit_net_usage_words )
{
EOS_ASSERT(deadline != fc::time_point(), transaction_exception, "deadline cannot be uninitialized");

Expand Down Expand Up @@ -1450,13 +1451,18 @@ struct controller_impl {
trace = trx_context.trace;
try {
if( trx->implicit ) {
EOS_ASSERT( !explicit_net_usage_words.valid(), transaction_exception, "NET usage cannot be explicitly set for implicit transactions" );
trx_context.init_for_implicit_trx();
trx_context.enforce_whiteblacklist = false;
} else {
bool skip_recording = replay_head_time && (time_point(trn.expiration) <= *replay_head_time);
trx_context.init_for_input_trx( trx->packed_trx()->get_unprunable_size(),
trx->packed_trx()->get_prunable_size(),
skip_recording);
if( explicit_net_usage_words ) {
trx_context.init_for_input_trx_with_explicit_net( *explicit_net_usage_words, skip_recording );
} else {
trx_context.init_for_input_trx( trx->packed_trx()->get_unprunable_size(),
trx->packed_trx()->get_prunable_size(),
skip_recording );
}
}

trx_context.delay = fc::seconds(trn.delay_sec);
Expand Down Expand Up @@ -1658,7 +1664,7 @@ struct controller_impl {
in_trx_requiring_checks = old_value;
});
in_trx_requiring_checks = true;
push_transaction( onbtrx, fc::time_point::maximum(), gpo.configuration.min_transaction_cpu_usage, true );
push_transaction( onbtrx, fc::time_point::maximum(), gpo.configuration.min_transaction_cpu_usage, true, {} );
} catch( const std::bad_alloc& e ) {
elog( "on block transaction failed due to a std::bad_alloc" );
throw;
Expand Down Expand Up @@ -1890,6 +1896,8 @@ struct controller_impl {

transaction_trace_ptr trace;

bool explicit_net = self.skip_trx_checks();

size_t packed_idx = 0;
const auto& trx_receipts = pending->_block_stage.get<building_block>()._pending_trx_receipts;
for( const auto& receipt : b->transactions ) {
Expand All @@ -1899,7 +1907,11 @@ struct controller_impl {
: ( !!std::get<0>( trx_metas.at( packed_idx ) ) ?
std::get<0>( trx_metas.at( packed_idx ) )
: std::get<1>( trx_metas.at( packed_idx ) ).get() ) );
trace = push_transaction( trx_meta, fc::time_point::maximum(), receipt.cpu_usage_us, true );
fc::optional<uint32_t> explicit_net_usage_words;
if( explicit_net ) {
explicit_net_usage_words = receipt.net_usage_words.value;
}
trace = push_transaction( trx_meta, fc::time_point::maximum(), receipt.cpu_usage_us, true, explicit_net_usage_words );
++packed_idx;
} else if( receipt.trx.contains<transaction_id_type>() ) {
trace = push_scheduled_transaction( receipt.trx.get<transaction_id_type>(), fc::time_point::maximum(), receipt.cpu_usage_us, true );
Expand Down Expand Up @@ -2679,7 +2691,7 @@ transaction_trace_ptr controller::push_transaction( const transaction_metadata_p
validate_db_available_size();
EOS_ASSERT( get_read_mode() != db_read_mode::IRREVERSIBLE, transaction_type_exception, "push transaction not allowed in irreversible mode" );
EOS_ASSERT( trx && !trx->implicit && !trx->scheduled, transaction_type_exception, "Implicit/Scheduled transaction not allowed" );
return my->push_transaction(trx, deadline, billed_cpu_time_us, explicit_billed_cpu_time );
return my->push_transaction(trx, deadline, billed_cpu_time_us, explicit_billed_cpu_time, {} );
}

transaction_trace_ptr controller::push_scheduled_transaction( const transaction_id_type& trxid, fc::time_point deadline,
Expand Down
22 changes: 19 additions & 3 deletions libraries/chain/include/eosio/chain/transaction_context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ namespace eosio { namespace chain {

class transaction_context {
private:
void init( uint64_t initial_net_usage);
void init( uint64_t initial_net_usage );

void init_for_input_trx_common( uint64_t initial_net_usage, bool skip_recording );

public:

Expand All @@ -45,7 +47,10 @@ namespace eosio { namespace chain {

void init_for_input_trx( uint64_t packed_trx_unprunable_size,
uint64_t packed_trx_prunable_size,
bool skip_recording);
bool skip_recording );

void init_for_input_trx_with_explicit_net( uint32_t explicit_net_usage_words,
bool skip_recording );

void init_for_deferred_trx( fc::time_point published );

Expand All @@ -54,7 +59,17 @@ namespace eosio { namespace chain {
void squash();
void undo();

inline void add_net_usage( uint64_t u ) { net_usage += u; check_net_usage(); }
inline void add_net_usage( uint64_t u ) {
if( explicit_net_usage ) return;
net_usage += u;
check_net_usage();
}

inline void round_up_net_usage() {
if( explicit_net_usage ) return;
net_usage = ((net_usage + 7)/8)*8; // Round up to nearest multiple of word size (8 bytes)
check_net_usage();
}

void check_net_usage()const;

Expand Down Expand Up @@ -156,6 +171,7 @@ namespace eosio { namespace chain {
bool net_limit_due_to_greylist = false;
uint64_t eager_net_limit = 0;
uint64_t& net_usage; /// reference to trace->net_usage
bool explicit_net_usage = false;

bool cpu_limit_due_to_greylist = false;

Expand Down
58 changes: 37 additions & 21 deletions libraries/chain/transaction_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ namespace eosio { namespace chain {
}
}

void transaction_context::init(uint64_t initial_net_usage)
void transaction_context::init( uint64_t initial_net_usage )
{
EOS_ASSERT( !is_initialized, transaction_exception, "cannot initialize twice" );

Expand Down Expand Up @@ -197,7 +197,7 @@ namespace eosio { namespace chain {
}

published = control.pending_block_time();
init( initial_net_usage);
init( initial_net_usage );
}

void transaction_context::init_for_input_trx( uint64_t packed_trx_unprunable_size,
Expand Down Expand Up @@ -230,14 +230,32 @@ namespace eosio { namespace chain {
+ static_cast<uint64_t>(config::transaction_id_net_usage);
}

init_for_input_trx_common( initial_net_usage, skip_recording );
}

void transaction_context::init_for_input_trx_with_explicit_net( uint32_t explicit_net_usage_words,
bool skip_recording )
{
if( trx.transaction_extensions.size() > 0 ) {
disallow_transaction_extensions( "no transaction extensions supported yet for input transactions" );
}

explicit_net_usage = true;
net_usage = (static_cast<uint64_t>(explicit_net_usage_words) * 8);

init_for_input_trx_common( 0, skip_recording );
}

void transaction_context::init_for_input_trx_common( uint64_t initial_net_usage, bool skip_recording )
{
published = control.pending_block_time();
is_input = true;
if (!control.skip_trx_checks()) {
control.validate_expiration(trx);
control.validate_tapos(trx);
validate_referenced_accounts( trx, enforce_whiteblacklist && control.is_producing_block() );
}
init( initial_net_usage);
init( initial_net_usage );
if (!skip_recording)
record_transaction( id, trx.expiration ); /// checks for dupes
}
Expand Down Expand Up @@ -323,10 +341,10 @@ namespace eosio { namespace chain {
billing_timer_exception_code = tx_cpu_usage_exceeded::code_value;
}

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

round_up_net_usage(); // Round up to nearest multiple of word size (8 bytes).
check_net_usage(); // Check that NET usage satisfies limits (even when explicit_net_usage is true).

auto now = fc::time_point::now();
trace->elapsed = now - start;
Expand All @@ -348,21 +366,19 @@ namespace eosio { namespace chain {
}

void transaction_context::check_net_usage()const {
if (!control.skip_trx_checks()) {
if( BOOST_UNLIKELY(net_usage > eager_net_limit) ) {
if ( net_limit_due_to_block ) {
EOS_THROW( block_net_usage_exceeded,
"not enough space left in block: ${net_usage} > ${net_limit}",
("net_usage", net_usage)("net_limit", eager_net_limit) );
} else if (net_limit_due_to_greylist) {
EOS_THROW( greylist_net_usage_exceeded,
"greylisted transaction net usage is too high: ${net_usage} > ${net_limit}",
("net_usage", net_usage)("net_limit", eager_net_limit) );
} else {
EOS_THROW( tx_net_usage_exceeded,
"transaction net usage is too high: ${net_usage} > ${net_limit}",
("net_usage", net_usage)("net_limit", eager_net_limit) );
}
if( BOOST_UNLIKELY(net_usage > eager_net_limit) ) {
if ( net_limit_due_to_block ) {
EOS_THROW( block_net_usage_exceeded,
"not enough space left in block: ${net_usage} > ${net_limit}",
("net_usage", net_usage)("net_limit", eager_net_limit) );
} else if (net_limit_due_to_greylist) {
EOS_THROW( greylist_net_usage_exceeded,
"greylisted transaction net usage is too high: ${net_usage} > ${net_limit}",
("net_usage", net_usage)("net_limit", eager_net_limit) );
} else {
EOS_THROW( tx_net_usage_exceeded,
"transaction net usage is too high: ${net_usage} > ${net_limit}",
("net_usage", net_usage)("net_limit", eager_net_limit) );
}
}
}
Expand Down
12 changes: 12 additions & 0 deletions libraries/testing/include/eosio/testing/tester.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,18 @@ namespace eosio { namespace testing {
bool skip_validate = false;
};

/**
* Utility predicate to check whether an fc::exception code is equivalent to a given value
*/
struct fc_exception_code_is {
fc_exception_code_is( int64_t code )
: expected( code ) {}

bool operator()( const fc::exception& ex );

int64_t expected;
};

/**
* Utility predicate to check whether an fc::exception message is equivalent to a given string
*/
Expand Down
9 changes: 9 additions & 0 deletions libraries/testing/tester.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1153,6 +1153,15 @@ namespace eosio { namespace testing {
preactivate_protocol_features( preactivations );
}

bool fc_exception_code_is::operator()( const fc::exception& ex ) {
bool match = (ex.code() == expected);
if( !match ) {
auto message = ex.get_log().at( 0 ).get_message();
BOOST_TEST_MESSAGE( "LOG: expected code: " << expected << ", actual code: " << ex.code() << ", message: " << message );
}
return match;
}

bool fc_exception_message_is::operator()( const fc::exception& ex ) {
auto message = ex.get_log().at( 0 ).get_message();
bool match = (message == expected);
Expand Down
Loading

0 comments on commit 4ddcee0

Please sign in to comment.