Skip to content

Commit df020d6

Browse files
committed
add return_value to action traces
1 parent 98c3f84 commit df020d6

16 files changed

Lines changed: 1239 additions & 334 deletions

plugins/trace_api_plugin/abi_data_handler.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@ namespace eosio::trace_api {
99
std::make_shared<chain::abi_serializer>(abi, chain::abi_serializer::create_yield_function(fc::microseconds::maximum())));
1010
}
1111

12-
fc::variant abi_data_handler::process_data(const action_trace_v0& action, const yield_function& yield ) {
13-
if (abi_serializer_by_account.count(action.account) > 0) {
14-
const auto& serializer_p = abi_serializer_by_account.at(action.account);
15-
auto type_name = serializer_p->get_action_type(action.action);
12+
std::tuple<fc::variant, std::optional<fc::variant>> abi_data_handler::serialize_to_variant(const std::variant<action_trace_v0, action_trace_v1> & action, const yield_function& yield ) {
13+
auto account = std::visit([](auto &&action) -> auto { return action.account; }, action);
14+
15+
if (abi_serializer_by_account.count(account) > 0) {
16+
const auto &serializer_p = abi_serializer_by_account.at(account);
17+
auto action_name = std::visit([](auto &&action) -> auto { return action.action; }, action);
18+
auto type_name = serializer_p->get_action_type(action_name);
1619

1720
if (!type_name.empty()) {
1821
try {
@@ -22,7 +25,15 @@ namespace eosio::trace_api {
2225
EOS_ASSERT( recursion_depth < chain::abi_serializer::max_recursion_depth, chain::abi_recursion_depth_exception,
2326
"exceeded max_recursion_depth ${r} ", ("r", chain::abi_serializer::max_recursion_depth) );
2427
};
25-
return serializer_p->binary_to_variant(type_name, action.data, abi_yield);
28+
return std::visit([&](auto &&action) -> std::tuple<fc::variant, std::optional<fc::variant>> {
29+
using T = std::decay_t<decltype(action)>;
30+
if constexpr (std::is_same_v<T, action_trace_v0>) {
31+
return {serializer_p->binary_to_variant(type_name, action.data, abi_yield), {}};
32+
} else {
33+
return {serializer_p->binary_to_variant(type_name, action.data, abi_yield),
34+
{serializer_p->binary_to_variant(type_name, action.return_value, abi_yield)}};
35+
}
36+
}, action);
2637
} catch (...) {
2738
except_handler(MAKE_EXCEPTION_WITH_CONTEXT(std::current_exception()));
2839
}

plugins/trace_api_plugin/include/eosio/trace_api/abi_data_handler.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@ namespace eosio {
3131
void add_abi( const chain::name& name, const chain::abi_def& abi );
3232

3333
/**
34-
* Given an action trace, produce a variant that represents the `data` field in the trace
34+
* Given an action trace, produce a tuple representing the `data` and `return_value` fields in the trace
3535
*
3636
* @param action - trace of the action including metadata necessary for finding the ABI
3737
* @param yield - a yield function to allow cooperation during long running tasks
38-
* @return variant representing the `data` field of the action interpreted by known ABIs OR an empty variant
38+
* @return tuple with the first element is a variant representing the `data` field of the action interpreted by known ABIs OR an empty variant, the second element representing the `return_value` field of the trace.
3939
*/
40-
fc::variant process_data( const action_trace_v0& action, const yield_function& yield );
40+
std::tuple<fc::variant, std::optional<fc::variant>> serialize_to_variant(const std::variant<action_trace_v0, action_trace_v1> & action, const yield_function& yield );
4141

4242
/**
4343
* Utility class that allows mulitple request_handlers to share the same abi_data_handler
@@ -48,8 +48,8 @@ namespace eosio {
4848
:handler(handler)
4949
{}
5050

51-
fc::variant process_data( const action_trace_v0& action, const yield_function& yield ) {
52-
return handler->process_data(action, yield);
51+
std::tuple<fc::variant, std::optional<fc::variant>> serialize_to_variant( const std::variant<action_trace_v0, action_trace_v1> & action, const yield_function& yield ) {
52+
return handler->serialize_to_variant(action, yield);
5353
}
5454

5555
std::shared_ptr<abi_data_handler> handler;

plugins/trace_api_plugin/include/eosio/trace_api/chain_extraction.hpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,15 @@ class chain_extraction_impl_type {
8181

8282
void store_block_trace( const chain::block_state_ptr& block_state ) {
8383
try {
84-
block_trace_v1 bt = create_block_trace_v1( block_state );
84+
using block_trace_t = block_trace_v2;
85+
using transaction_trace_t = transaction_trace_v2;
8586

86-
std::vector<transaction_trace_v1>& traces = bt.transactions_v1;
87+
block_trace_t bt = create_block_trace<block_trace_t>( block_state );
88+
89+
std::vector<transaction_trace_t>& traces = std::get<std::vector<transaction_trace_t>>(bt.transactions);
8790
traces.reserve( block_state->block->transactions.size() + 1 );
8891
if( onblock_trace )
89-
traces.emplace_back( to_transaction_trace_v1( *onblock_trace ));
92+
traces.emplace_back( to_transaction_trace<transaction_trace_t>( *onblock_trace ));
9093
for( const auto& r : block_state->block->transactions ) {
9194
transaction_id_type id;
9295
if( std::holds_alternative<transaction_id_type>(r.trx)) {
@@ -96,7 +99,7 @@ class chain_extraction_impl_type {
9699
}
97100
const auto it = cached_traces.find( id );
98101
if( it != cached_traces.end() ) {
99-
traces.emplace_back( to_transaction_trace_v1( it->second ));
102+
traces.emplace_back( to_transaction_trace<transaction_trace_t>( it->second ));
100103
}
101104
}
102105
clear_caches();

plugins/trace_api_plugin/include/eosio/trace_api/data_log.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ namespace eosio { namespace trace_api {
88

99
using data_log_entry = std::variant<
1010
block_trace_v0,
11-
block_trace_v1
11+
block_trace_v1,
12+
block_trace_v2
1213
>;
1314

1415
}}

plugins/trace_api_plugin/include/eosio/trace_api/extract_util.hpp

Lines changed: 41 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@
55

66
namespace eosio { namespace trace_api {
77

8-
/// Used by to_transaction_trace_v0 for creation of action_trace_v0
9-
inline action_trace_v0 to_action_trace_v0( const chain::action_trace& at ) {
10-
action_trace_v0 r;
8+
/// Used by to_transaction_trace for creation of action_trace_v0 or action_trace_v1
9+
template<typename ActionTrace>
10+
inline ActionTrace to_action_trace( const chain::action_trace& at ) {
11+
ActionTrace r;
1112
r.receiver = at.receiver;
1213
r.account = at.act.account;
1314
r.action = at.act.name;
1415
r.data = at.act.data;
16+
if constexpr(std::is_same_v<ActionTrace, action_trace_v1>){
17+
r.return_value = at.return_value;
18+
}
1519
if( at.receipt ) {
1620
r.global_sequence = at.receipt->global_sequence;
1721
}
@@ -22,70 +26,54 @@ inline action_trace_v0 to_action_trace_v0( const chain::action_trace& at ) {
2226
return r;
2327
}
2428

25-
/// @return transaction_trace_v0 with populated action_trace_v0
26-
inline transaction_trace_v0 to_transaction_trace_v0( const chain::transaction_trace_ptr& t ) {
27-
transaction_trace_v0 r;
28-
if( !t->failed_dtrx_trace ) {
29-
r.id = t->id;
29+
template<typename TransactionTrace>
30+
inline TransactionTrace to_transaction_trace( const cache_trace& t ) {
31+
TransactionTrace r;
32+
if( !t.trace->failed_dtrx_trace ) {
33+
r.id = t.trace->id;
3034
} else {
31-
r.id = t->failed_dtrx_trace->id; // report the failed trx id since that is the id known to user
35+
r.id = t.trace->failed_dtrx_trace->id; // report the failed trx id since that is the id known to user
36+
}
37+
38+
if constexpr(std::is_same_v<TransactionTrace, transaction_trace_v1> || std::is_same_v<TransactionTrace, transaction_trace_v2>){
39+
if (t.trace->receipt) {
40+
r.status = t.trace->receipt->status;
41+
r.cpu_usage_us = t.trace->receipt->cpu_usage_us;
42+
r.net_usage_words = t.trace->receipt->net_usage_words;
43+
}
44+
auto sigs = t.trx->get_signatures();
45+
if( sigs ) r.signatures = *sigs;
46+
r.trx_header = static_cast<const chain::transaction_header&>( t.trx->get_transaction() );
3247
}
33-
r.actions.reserve( t->action_traces.size());
34-
for( const auto& at : t->action_traces ) {
48+
49+
using action_trace_t = std::conditional_t<std::is_same_v<TransactionTrace, transaction_trace_v2>, action_trace_v1, action_trace_v0>;
50+
51+
r.actions = std::vector<action_trace_t>();
52+
std::get<std::vector<action_trace_t>>(r.actions).reserve( t.trace->action_traces.size());
53+
for( const auto& at : t.trace->action_traces ) {
3554
if( !at.context_free ) { // not including CFA at this time
36-
r.actions.emplace_back( to_action_trace_v0( at ));
55+
std::get<std::vector<action_trace_t>>(r.actions).emplace_back( to_action_trace<action_trace_t>(at) );
3756
}
3857
}
39-
return r;
40-
}
4158

42-
inline transaction_trace_v1 to_transaction_trace_v1( const cache_trace& t ) {
43-
transaction_trace_v1 r;
44-
if( !t.trace->failed_dtrx_trace ) {
45-
r.id = t.trace->id;
46-
} else {
47-
r.id = t.trace->failed_dtrx_trace->id; // report the failed trx id since that is the id known to user
48-
}
49-
if (t.trace->receipt) {
50-
r.status = t.trace->receipt->status;
51-
r.cpu_usage_us = t.trace->receipt->cpu_usage_us;
52-
r.net_usage_words = t.trace->receipt->net_usage_words;
53-
}
54-
auto sigs = t.trx->get_signatures();
55-
if( sigs ) r.signatures = *sigs;
56-
r.trx_header = static_cast<const chain::transaction_header&>( t.trx->get_transaction() );
57-
r.actions.reserve( t.trace->action_traces.size());
58-
for( const auto& at : t.trace->action_traces ) {
59-
if( !at.context_free ) { // not including CFA at this time
60-
r.actions.emplace_back( to_action_trace_v0( at ));
61-
}
62-
}
63-
return r;
59+
return r;
6460
}
6561

66-
/// @return block_trace_v0 without any transaction_trace_v0
67-
inline block_trace_v0 create_block_trace_v0( const chain::block_state_ptr& bsp ) {
68-
block_trace_v0 r;
62+
template<typename BlockTrace>
63+
inline BlockTrace create_block_trace( const chain::block_state_ptr& bsp ) {
64+
BlockTrace r;
6965
r.id = bsp->id;
7066
r.number = bsp->block_num;
7167
r.previous_id = bsp->block->previous;
7268
r.timestamp = bsp->block->timestamp;
7369
r.producer = bsp->block->producer;
70+
if constexpr(std::is_same_v<BlockTrace, block_trace_v1> || std::is_same_v<BlockTrace, block_trace_v2>)
71+
{
72+
r.schedule_version = bsp->block->schedule_version;
73+
r.transaction_mroot = bsp->block->transaction_mroot;
74+
r.action_mroot = bsp->block->action_mroot;
75+
}
7476
return r;
7577
}
7678

77-
/// @return block_trace_v1 without any transaction_trace_v1
78-
inline block_trace_v1 create_block_trace_v1( const chain::block_state_ptr& bsp ) {
79-
block_trace_v1 r;
80-
r.id = bsp->id;
81-
r.number = bsp->block_num;
82-
r.previous_id = bsp->block->previous;
83-
r.timestamp = bsp->block->timestamp;
84-
r.producer = bsp->block->producer;
85-
r.schedule_version = bsp->block->schedule_version;
86-
r.transaction_mroot = bsp->block->transaction_mroot;
87-
r.action_mroot = bsp->block->action_mroot;
88-
return r;
89-
}
90-
9179
} }

plugins/trace_api_plugin/include/eosio/trace_api/request_handler.hpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#include <eosio/trace_api/common.hpp>
77

88
namespace eosio::trace_api {
9-
using data_handler_function = std::function<fc::variant(const action_trace_v0&, const yield_function&)>;
9+
using data_handler_function = std::function<std::tuple<fc::variant, std::optional<fc::variant>>( const std::variant<action_trace_v0, action_trace_v1> & action_trace_t, const yield_function&)>;
1010

1111
namespace detail {
1212
class response_formatter {
@@ -43,8 +43,10 @@ namespace eosio::trace_api {
4343

4444
yield();
4545

46-
auto data_handler = [this](const action_trace_v0& action, const yield_function& yield) -> fc::variant {
47-
return data_handler_provider.process_data(action, yield);
46+
auto data_handler = [this](const auto& action, const yield_function& yield) -> std::tuple<fc::variant, std::optional<fc::variant>> {
47+
return std::visit([&](const auto& action_trace_t) {
48+
return data_handler_provider.serialize_to_variant(action_trace_t, yield);
49+
}, action);
4850
};
4951

5052
return detail::response_formatter::process_block(std::get<0>(*data), std::get<1>(*data), data_handler, yield);

plugins/trace_api_plugin/include/eosio/trace_api/store_provider.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,8 @@ namespace eosio::trace_api {
246246
store_provider(const boost::filesystem::path& slice_dir, uint32_t stride_width, std::optional<uint32_t> minimum_irreversible_history_blocks,
247247
std::optional<uint32_t> minimum_uncompressed_irreversible_history_blocks, size_t compression_seek_point_stride);
248248

249-
void append(const block_trace_v1& bt);
249+
template<typename BlockTrace>
250+
void append(const BlockTrace& bt);
250251
void append_lib(uint32_t lib);
251252

252253
/**

plugins/trace_api_plugin/include/eosio/trace_api/trace.hpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ namespace eosio { namespace trace_api {
2121
chain::bytes data = {};
2222
};
2323

24+
struct action_trace_v1 : public action_trace_v0 {
25+
chain::bytes return_value = {};
26+
};
27+
2428
struct transaction_trace_v0 {
2529
using status_type = chain::transaction_receipt_header::status_enum;
2630

@@ -36,6 +40,18 @@ namespace eosio { namespace trace_api {
3640
chain::transaction_header trx_header = {};
3741
};
3842

43+
struct transaction_trace_v2 {
44+
using status_type = chain::transaction_receipt_header::status_enum;
45+
46+
chain::transaction_id_type id = {};
47+
std::variant<std::vector<action_trace_v0>, std::vector<action_trace_v1>> actions = {};
48+
fc::enum_type<uint8_t,status_type> status = {};
49+
uint32_t cpu_usage_us = 0;
50+
fc::unsigned_int net_usage_words;
51+
std::vector<chain::signature_type> signatures = {};
52+
chain::transaction_header trx_header = {};
53+
};
54+
3955
struct block_trace_v0 {
4056
chain::block_id_type id = {};
4157
uint32_t number = {};
@@ -52,6 +68,18 @@ namespace eosio { namespace trace_api {
5268
std::vector<transaction_trace_v1> transactions_v1 = {};
5369
};
5470

71+
struct block_trace_v2 {
72+
chain::block_id_type id = {};
73+
uint32_t number = {};
74+
chain::block_id_type previous_id = {};
75+
chain::block_timestamp_type timestamp = chain::block_timestamp_type(0);
76+
chain::name producer = {};
77+
chain::checksum256_type transaction_mroot = {};
78+
chain::checksum256_type action_mroot = {};
79+
uint32_t schedule_version = {};
80+
std::variant<std::vector<transaction_trace_v2>> transactions = {};
81+
};
82+
5583
struct cache_trace {
5684
chain::transaction_trace_ptr trace;
5785
chain::packed_transaction_ptr trx;
@@ -61,7 +89,10 @@ namespace eosio { namespace trace_api {
6189

6290
FC_REFLECT(eosio::trace_api::authorization_trace_v0, (account)(permission))
6391
FC_REFLECT(eosio::trace_api::action_trace_v0, (global_sequence)(receiver)(account)(action)(authorization)(data))
92+
FC_REFLECT_DERIVED(eosio::trace_api::action_trace_v1, (eosio::trace_api::action_trace_v0),(return_value))
6493
FC_REFLECT(eosio::trace_api::transaction_trace_v0, (id)(actions))
6594
FC_REFLECT_DERIVED(eosio::trace_api::transaction_trace_v1, (eosio::trace_api::transaction_trace_v0), (status)(cpu_usage_us)(net_usage_words)(signatures)(trx_header))
95+
FC_REFLECT(eosio::trace_api::transaction_trace_v2, (id)(actions)(status)(cpu_usage_us)(net_usage_words)(signatures)(trx_header))
6696
FC_REFLECT(eosio::trace_api::block_trace_v0, (id)(number)(previous_id)(timestamp)(producer)(transactions))
6797
FC_REFLECT_DERIVED(eosio::trace_api::block_trace_v1, (eosio::trace_api::block_trace_v0), (transaction_mroot)(action_mroot)(schedule_version)(transactions_v1))
98+
FC_REFLECT(eosio::trace_api::block_trace_v2, (id)(number)(previous_id)(timestamp)(producer)(transaction_mroot)(action_mroot)(schedule_version)(transactions))

0 commit comments

Comments
 (0)