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

Commit

Permalink
initial attempt at restructuring transaction traces #6897
Browse files Browse the repository at this point in the history
  • Loading branch information
arhag committed Mar 30, 2019
1 parent c8d8271 commit 50635a6
Show file tree
Hide file tree
Showing 11 changed files with 214 additions and 115 deletions.
2 changes: 1 addition & 1 deletion libraries/chain/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ add_library( eosio_chain
#
# contracts/chain_initializer.cpp


trace.cpp
transaction_metadata.cpp
protocol_state_object.cpp
protocol_feature_activation.cpp
Expand Down
47 changes: 23 additions & 24 deletions libraries/chain/apply_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,6 @@ void apply_context::exec_one( action_trace& trace )
r.receiver = receiver;
r.act_digest = digest_type::hash(act);

trace.trx_id = trx_context.id;
trace.block_num = control.head_block_num() + 1;
trace.block_time = control.pending_block_time();
trace.producer_block_id = control.pending_producer_block_id();
trace.act = act;
trace.context_free = context_free;

const auto& cfg = control.get_global_properties().configuration;
try {
try {
Expand Down Expand Up @@ -71,7 +64,6 @@ void apply_context::exec_one( action_trace& trace )
}
} FC_RETHROW_EXCEPTIONS( warn, "pending console output: ${console}", ("console", _pending_console_output) )
} catch( fc::exception& e ) {
trace.receipt = r; // fill with known data
trace.except = e;
finalize_trace( trace, start );
throw;
Expand All @@ -90,7 +82,7 @@ void apply_context::exec_one( action_trace& trace )

trace.receipt = r;

trx_context.executed.emplace_back( move(r) );
trx_context.executed.emplace_back( std::move(r) );

finalize_trace( trace, start );

Expand All @@ -112,27 +104,24 @@ void apply_context::finalize_trace( action_trace& trace, const fc::time_point& s

void apply_context::exec( action_trace& trace )
{
_notified.push_back(receiver);
_notified.emplace_back( receiver, action_ordinal );
exec_one( trace );
for( uint32_t i = 1; i < _notified.size(); ++i ) {
receiver = _notified[i];
trace.inline_traces.emplace_back( );
exec_one( trace.inline_traces.back() );
std::tie( receiver, action_ordinal ) = _notified[i];
exec_one( trx_context.get_action_trace( action_ordinal ) );
}

if( _cfa_inline_actions.size() > 0 || _inline_actions.size() > 0 ) {
EOS_ASSERT( recurse_depth < control.get_global_properties().configuration.max_inline_action_depth,
transaction_exception, "max inline action depth per transaction reached" );
}

for( const auto& inline_action : _cfa_inline_actions ) {
trace.inline_traces.emplace_back();
trx_context.dispatch_action( trace.inline_traces.back(), inline_action, inline_action.account, true, recurse_depth + 1 );
for( int32_t ordinal : _cfa_inline_actions ) {
trx_context.execute_action( ordinal, recurse_depth + 1 );
}

for( const auto& inline_action : _inline_actions ) {
trace.inline_traces.emplace_back();
trx_context.dispatch_action( trace.inline_traces.back(), inline_action, inline_action.account, false, recurse_depth + 1 );
for( int32_t ordinal : _inline_actions ) {
trx_context.execute_action( ordinal, recurse_depth + 1 );
}

} /// exec()
Expand Down Expand Up @@ -172,15 +161,18 @@ void apply_context::require_authorization(const account_name& account,
}

bool apply_context::has_recipient( account_name code )const {
for( auto a : _notified )
if( a == code )
for( const auto& p : _notified )
if( p.first == code )
return true;
return false;
}

void apply_context::require_recipient( account_name recipient ) {
if( !has_recipient(recipient) ) {
_notified.push_back(recipient);
_notified.emplace_back(
recipient,
trx_context.schedule_action( act, recipient, false, action_ordinal, first_receiver_action_ordinal )
);
}
}

Expand Down Expand Up @@ -271,7 +263,10 @@ void apply_context::execute_inline( action&& a ) {
}
}

_inline_actions.emplace_back( move(a) );
auto inline_receiver = a.account;
_inline_actions.emplace_back(
trx_context.schedule_action( std::move(a), inline_receiver, false, action_ordinal, first_receiver_action_ordinal )
);
}

void apply_context::execute_context_free_inline( action&& a ) {
Expand All @@ -282,7 +277,11 @@ void apply_context::execute_context_free_inline( action&& a ) {
EOS_ASSERT( a.authorization.size() == 0, action_validate_exception,
"context-free actions cannot have authorizations" );

_cfa_inline_actions.emplace_back( move(a) );

auto inline_receiver = a.account;
_cfa_inline_actions.emplace_back(
trx_context.schedule_action( std::move(a), inline_receiver, true, action_ordinal, first_receiver_action_ordinal )
);
}


Expand Down
19 changes: 11 additions & 8 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -966,8 +966,7 @@ struct controller_impl {
try {
trx_context.init_for_implicit_trx();
trx_context.published = gtrx.published;
trx_context.trace->action_traces.emplace_back();
trx_context.dispatch_action( trx_context.trace->action_traces.back(), etrx.actions.back(), gtrx.sender );
trx_context.execute_action( trx_context.schedule_action( etrx.actions.back(), gtrx.sender ) );
trx_context.finalize(); // Automatically rounds up network and CPU usage in trace and bills payers if successful

auto restore = make_block_restore_point();
Expand All @@ -988,14 +987,13 @@ struct controller_impl {
return trace;
}

void remove_scheduled_transaction( const generated_transaction_object& gto ) {
resource_limits.add_pending_ram_usage(
gto.payer,
-(config::billable_size_v<generated_transaction_object> + gto.packed_trx.size())
);
int64_t remove_scheduled_transaction( const generated_transaction_object& gto ) {
int64_t ram_delta = -(config::billable_size_v<generated_transaction_object> + gto.packed_trx.size());
resource_limits.add_pending_ram_usage( gto.payer, ram_delta );
// No need to verify_account_ram_usage since we are only reducing memory

db.remove( gto );
return ram_delta;
}

bool failure_is_subjective( const fc::exception& e ) const {
Expand Down Expand Up @@ -1042,7 +1040,7 @@ struct controller_impl {
//
// IF the transaction FAILs in a subjective way, `undo_session` should expire without being squashed
// resulting in the GTO being restored and available for a future block to retire.
remove_scheduled_transaction(gto);
int64_t trx_removal_ram_delta = remove_scheduled_transaction(gto);

fc::datastream<const char*> ds( gtrx.packed_trx.data(), gtrx.packed_trx.size() );

Expand All @@ -1064,6 +1062,7 @@ struct controller_impl {
trace->producer_block_id = self.pending_producer_block_id();
trace->scheduled = true;
trace->receipt = push_receipt( gtrx.trx_id, transaction_receipt::expired, billed_cpu_time_us, 0 ); // expire the transaction
trace->account_ram_delta = account_delta( gtrx.payer, trx_removal_ram_delta );
emit( self.accepted_transaction, trx );
emit( self.applied_transaction, trace );
undo_session.squash();
Expand Down Expand Up @@ -1103,6 +1102,8 @@ struct controller_impl {

fc::move_append( pending->_block_stage.get<building_block>()._actions, move(trx_context.executed) );

trace->account_ram_delta = account_delta( gtrx.payer, trx_removal_ram_delta );

emit( self.accepted_transaction, trx );
emit( self.applied_transaction, trace );

Expand Down Expand Up @@ -1133,6 +1134,7 @@ struct controller_impl {
error_trace->failed_dtrx_trace = trace;
trace = error_trace;
if( !trace->except_ptr ) {
trace->account_ram_delta = account_delta( gtrx.payer, trx_removal_ram_delta );
emit( self.accepted_transaction, trx );
emit( self.applied_transaction, trace );
undo_session.squash();
Expand Down Expand Up @@ -1169,6 +1171,7 @@ struct controller_impl {
block_timestamp_type(self.pending_block_time()).slot ); // Should never fail

trace->receipt = push_receipt(gtrx.trx_id, transaction_receipt::hard_fail, cpu_time_to_bill_us, 0);
trace->account_ram_delta = account_delta( gtrx.payer, trx_removal_ram_delta );

emit( self.accepted_transaction, trx );
emit( self.applied_transaction, trace );
Expand Down
1 change: 0 additions & 1 deletion libraries/chain/include/eosio/chain/abi_serializer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,6 @@ namespace impl {
std::is_same<T, packed_transaction>::value ||
std::is_same<T, transaction_trace>::value ||
std::is_same<T, transaction_receipt>::value ||
std::is_same<T, base_action_trace>::value ||
std::is_same<T, action_trace>::value ||
std::is_same<T, signed_transaction>::value ||
std::is_same<T, signed_block>::value ||
Expand Down
8 changes: 5 additions & 3 deletions libraries/chain/include/eosio/chain/apply_context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,8 @@ class apply_context {
account_name receiver; ///< the code that is currently running
vector<bool> used_authorizations; ///< Parallel to act.authorization; tracks which permissions have been used while processing the message
uint32_t recurse_depth; ///< how deep inline actions can recurse
int32_t first_receiver_action_ordinal = -1;
int32_t action_ordinal = -1;
bool privileged = false;
bool context_free = false;
bool used_context_free_api = false;
Expand All @@ -583,9 +585,9 @@ class apply_context {
private:

iterator_cache<key_value_object> keyval_cache;
vector<account_name> _notified; ///< keeps track of new accounts to be notifed of current message
vector<action> _inline_actions; ///< queued inline messages
vector<action> _cfa_inline_actions; ///< queued inline messages
vector< std::pair<account_name, int32_t> > _notified; ///< keeps track of new accounts to be notifed of current message
vector<int32_t> _inline_actions; ///< action_ordinals of queued inline actions
vector<int32_t> _cfa_inline_actions; ///< action_ordinals of queued inline context-free actions
std::string _pending_console_output;
flat_set<account_delta> _account_ram_deltas; ///< flat_set of account_delta so json is an array of objects

Expand Down
58 changes: 29 additions & 29 deletions libraries/chain/include/eosio/chain/trace.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,34 @@ namespace eosio { namespace chain {
friend bool operator<( const account_delta& lhs, const account_delta& rhs ) { return lhs.account < rhs.account; }
};

struct base_action_trace {
base_action_trace( const action_receipt& r ):receipt(r){}
base_action_trace(){}

action_receipt receipt;
action act;
bool context_free = false;
fc::microseconds elapsed;
string console;
struct transaction_trace;
using transaction_trace_ptr = std::shared_ptr<transaction_trace>;

transaction_id_type trx_id; ///< the transaction that generated this action
uint32_t block_num = 0;
block_timestamp_type block_time;
struct action_trace {
action_trace( const transaction_trace& trace, const action& act, account_name receiver, bool context_free,
int32_t action_ordinal, int32_t creator_action_ordinal, int32_t parent_action_ordinal );
action_trace( const transaction_trace& trace, action&& act, account_name receiver, bool context_free,
int32_t action_ordinal, int32_t creator_action_ordinal, int32_t parent_action_ordinal );
//action_trace( const action_receipt& r ):receipt(r){}
action_trace(){}

int32_t action_ordinal = 0;
int32_t creator_action_ordinal = -1;
int32_t parent_action_ordinal = -1;
fc::optional<action_receipt> receipt;
action_name receiver;
action act;
bool context_free = false;
fc::microseconds elapsed;
string console;
transaction_id_type trx_id; ///< the transaction that generated this action
uint32_t block_num = 0;
block_timestamp_type block_time;
fc::optional<block_id_type> producer_block_id;
flat_set<account_delta> account_ram_deltas;
fc::optional<fc::exception> except;
};

struct action_trace : public base_action_trace {
using base_action_trace::base_action_trace;

vector<action_trace> inline_traces;
};

struct transaction_trace;
using transaction_trace_ptr = std::shared_ptr<transaction_trace>;

struct transaction_trace {
transaction_id_type id;
uint32_t block_num = 0;
Expand All @@ -56,7 +57,8 @@ namespace eosio { namespace chain {
fc::microseconds elapsed;
uint64_t net_usage = 0;
bool scheduled = false;
vector<action_trace> action_traces; ///< disposable
vector<action_trace> action_traces;
fc::optional<account_delta> account_ram_delta;

transaction_trace_ptr failed_dtrx_trace;
fc::optional<fc::exception> except;
Expand All @@ -68,13 +70,11 @@ namespace eosio { namespace chain {
FC_REFLECT( eosio::chain::account_delta,
(account)(delta) )

FC_REFLECT( eosio::chain::base_action_trace,
(receipt)(act)(context_free)(elapsed)(console)(trx_id)
(block_num)(block_time)(producer_block_id)(account_ram_deltas)(except) )

FC_REFLECT_DERIVED( eosio::chain::action_trace,
(eosio::chain::base_action_trace), (inline_traces) )
FC_REFLECT( eosio::chain::action_trace,
(action_ordinal)(creator_action_ordinal)(parent_action_ordinal)(receipt)
(receiver)(act)(context_free)(elapsed)(console)(trx_id)(block_num)(block_time)
(producer_block_id)(account_ram_deltas)(except) )

FC_REFLECT( eosio::chain::transaction_trace, (id)(block_num)(block_time)(producer_block_id)
(receipt)(elapsed)(net_usage)(scheduled)
(action_traces)(failed_dtrx_trace)(except) )
(action_traces)(account_ram_delta)(failed_dtrx_trace)(except) )
18 changes: 14 additions & 4 deletions libraries/chain/include/eosio/chain/transaction_context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,20 @@ namespace eosio { namespace chain {

void add_ram_usage( account_name account, int64_t ram_delta );

void dispatch_action( action_trace& trace, const action& a, account_name receiver, bool context_free = false, uint32_t recurse_depth = 0 );
inline void dispatch_action( action_trace& trace, const action& a, bool context_free = false ) {
dispatch_action(trace, a, a.account, context_free);
};
int32_t schedule_action( const action& act, account_name receiver, bool context_free = false,
int32_t creator_action_ordinal = -1, int32_t parent_action_ordinal = -1 );

int32_t schedule_action( action&& act, account_name receiver, bool context_free = false,
int32_t creator_action_ordinal = -1, int32_t parent_action_ordinal = -1 );

action_trace& get_action_trace( int32_t action_ordinal );
const action_trace& get_action_trace( int32_t action_ordinal )const;

void execute_action( action_trace& act_trace, uint32_t recurse_depth );
inline void execute_action( int32_t action_ordinal, uint32_t recurse_depth = 0 ) {
execute_action( get_action_trace( action_ordinal ), recurse_depth );
}

void schedule_transaction();
void record_transaction( const transaction_id_type& id, fc::time_point_sec expire );

Expand Down
41 changes: 41 additions & 0 deletions libraries/chain/trace.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* @file
* @copyright defined in eos/LICENSE
*/
#include <eosio/chain/trace.hpp>

namespace eosio { namespace chain {

action_trace::action_trace(
const transaction_trace& trace, const action& act, account_name receiver, bool context_free,
int32_t action_ordinal, int32_t creator_action_ordinal, int32_t parent_action_ordinal
)
:action_ordinal( action_ordinal )
,creator_action_ordinal( creator_action_ordinal )
,parent_action_ordinal( parent_action_ordinal )
,receiver( receiver )
,act( act )
,context_free( context_free )
,trx_id( trace.id )
,block_num( trace.block_num )
,block_time( trace.block_time )
,producer_block_id( trace.producer_block_id )
{}

action_trace::action_trace(
const transaction_trace& trace, action&& act, account_name receiver, bool context_free,
int32_t action_ordinal, int32_t creator_action_ordinal, int32_t parent_action_ordinal
)
:action_ordinal( action_ordinal )
,creator_action_ordinal( creator_action_ordinal )
,parent_action_ordinal( parent_action_ordinal )
,receiver( receiver )
,act( std::move(act) )
,context_free( context_free )
,trx_id( trace.id )
,block_num( trace.block_num )
,block_time( trace.block_time )
,producer_block_id( trace.producer_block_id )
{}

} } // eosio::chain
Loading

0 comments on commit 50635a6

Please sign in to comment.