Skip to content

Commit

Permalink
Merge pull request #558 from AntelopeIO/send_read_only_trx
Browse files Browse the repository at this point in the history
introduce new read-only transaction RPC end point
  • Loading branch information
linh2931 authored Mar 2, 2023
2 parents d42b860 + 2ae98cb commit 3c0e506
Show file tree
Hide file tree
Showing 41 changed files with 1,211 additions and 279 deletions.
80 changes: 48 additions & 32 deletions libraries/chain/apply_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ void apply_context::exec_one()
print_debug(receiver, trace);
}

if (auto dm_logger = control.get_deep_mind_logger())
if (auto dm_logger = control.get_deep_mind_logger(trx_context.is_transient()))
{
dm_logger->on_end_action();
}
Expand Down Expand Up @@ -289,7 +289,7 @@ void apply_context::require_recipient( account_name recipient ) {
schedule_action( action_ordinal, recipient, false )
);

if (auto dm_logger = control.get_deep_mind_logger()) {
if (auto dm_logger = control.get_deep_mind_logger(trx_context.is_transient())) {
dm_logger->on_require_recipient();
}
}
Expand Down Expand Up @@ -354,7 +354,7 @@ void apply_context::execute_inline( action&& a ) {
"inline action too big for nonprivileged account ${account}", ("account", a.account));
}
// No need to check authorization if replaying irreversible blocks or contract is privileged
if( !control.skip_auth_check() && !privileged ) {
if( !control.skip_auth_check() && !privileged && !trx_context.is_read_only() ) {
try {
control.get_authorization_manager()
.check_authorization( {a},
Expand All @@ -363,7 +363,7 @@ void apply_context::execute_inline( action&& a ) {
control.pending_block_time() - trx_context.published,
std::bind(&transaction_context::checktime, &this->trx_context),
false,
trx_context.is_dry_run(),
trx_context.is_dry_run(), // check_but_dont_fail
inherited_authorizations
);

Expand Down Expand Up @@ -394,7 +394,7 @@ void apply_context::execute_inline( action&& a ) {
schedule_action( std::move(a), inline_receiver, false )
);

if (auto dm_logger = control.get_deep_mind_logger()) {
if (auto dm_logger = control.get_deep_mind_logger(trx_context.is_transient())) {
dm_logger->on_send_inline();
}
}
Expand All @@ -419,13 +419,14 @@ void apply_context::execute_context_free_inline( action&& a ) {
schedule_action( std::move(a), inline_receiver, true )
);

if (auto dm_logger = control.get_deep_mind_logger()) {
if (auto dm_logger = control.get_deep_mind_logger(trx_context.is_transient())) {
dm_logger->on_send_context_free_inline();
}
}


void apply_context::schedule_deferred_transaction( const uint128_t& sender_id, account_name payer, transaction&& trx, bool replace_existing ) {
EOS_ASSERT( !trx_context.is_read_only(), transaction_exception, "cannot schedule a deferred transaction from within a readonly transaction" );
EOS_ASSERT( trx.context_free_actions.size() == 0, cfa_inside_generated_tx, "context free actions are not currently allowed in generated transactions" );

bool enforce_actor_whitelist_blacklist = trx_context.enforce_whiteblacklist && control.is_speculative_block()
Expand Down Expand Up @@ -557,7 +558,7 @@ void apply_context::schedule_deferred_transaction( const uint128_t& sender_id, a
subjective_block_production_exception,
"Replacing a deferred transaction is temporarily disabled." );

if (auto dm_logger = control.get_deep_mind_logger()) {
if (auto dm_logger = control.get_deep_mind_logger(trx_context.is_transient())) {
dm_logger->on_ram_trace(RAM_EVENT_ID("${id}", ("id", ptr->id)), "deferred_trx", "cancel", "deferred_trx_cancel");
}

Expand All @@ -575,7 +576,7 @@ void apply_context::schedule_deferred_transaction( const uint128_t& sender_id, a
trx_id_for_new_obj = ptr->trx_id;
}

if (auto dm_logger = control.get_deep_mind_logger()) {
if (auto dm_logger = control.get_deep_mind_logger(trx_context.is_transient())) {
dm_logger->on_cancel_deferred(deep_mind_handler::operation_qualifier::modify, *ptr);
}

Expand All @@ -592,7 +593,7 @@ void apply_context::schedule_deferred_transaction( const uint128_t& sender_id, a

trx_size = gtx.set( trx );

if (auto dm_logger = control.get_deep_mind_logger()) {
if (auto dm_logger = control.get_deep_mind_logger(trx_context.is_transient())) {
dm_logger->on_send_deferred(deep_mind_handler::operation_qualifier::modify, gtx);
dm_logger->on_ram_trace(RAM_EVENT_ID("${id}", ("id", gtx.id)), "deferred_trx", "update", "deferred_trx_add");
}
Expand All @@ -609,7 +610,7 @@ void apply_context::schedule_deferred_transaction( const uint128_t& sender_id, a

trx_size = gtx.set( trx );

if (auto dm_logger = control.get_deep_mind_logger()) {
if (auto dm_logger = control.get_deep_mind_logger(trx_context.is_transient())) {
dm_logger->on_send_deferred(deep_mind_handler::operation_qualifier::none, gtx);
dm_logger->on_ram_trace(RAM_EVENT_ID("${id}", ("id", gtx.id)), "deferred_trx", "add", "deferred_trx_add");
}
Expand All @@ -626,10 +627,11 @@ void apply_context::schedule_deferred_transaction( const uint128_t& sender_id, a
}

bool apply_context::cancel_deferred_transaction( const uint128_t& sender_id, account_name sender ) {
EOS_ASSERT( !trx_context.is_read_only(), transaction_exception, "cannot cancel a deferred transaction from within a readonly transaction" );
auto& generated_transaction_idx = db.get_mutable_index<generated_transaction_multi_index>();
const auto* gto = db.find<generated_transaction_object,by_sender_id>(boost::make_tuple(sender, sender_id));
if ( gto ) {
if (auto dm_logger = control.get_deep_mind_logger()) {
if (auto dm_logger = control.get_deep_mind_logger(trx_context.is_transient())) {
dm_logger->on_cancel_deferred(deep_mind_handler::operation_qualifier::none, *gto);
dm_logger->on_ram_trace(RAM_EVENT_ID("${id}", ("id", gto->id)), "deferred_trx", "cancel", "deferred_trx_cancel");
}
Expand Down Expand Up @@ -670,7 +672,7 @@ const table_id_object& apply_context::find_or_create_table( name code, name scop
return *existing_tid;
}

if (auto dm_logger = control.get_deep_mind_logger()) {
if (auto dm_logger = control.get_deep_mind_logger(trx_context.is_transient())) {
std::string event_id = RAM_EVENT_ID("${code}:${scope}:${table}",
("code", code)
("scope", scope)
Expand All @@ -687,14 +689,14 @@ const table_id_object& apply_context::find_or_create_table( name code, name scop
t_id.table = table;
t_id.payer = payer;

if (auto dm_logger = control.get_deep_mind_logger()) {
if (auto dm_logger = control.get_deep_mind_logger(trx_context.is_transient())) {
dm_logger->on_create_table(t_id);
}
});
}

void apply_context::remove_table( const table_id_object& tid ) {
if (auto dm_logger = control.get_deep_mind_logger()) {
if (auto dm_logger = control.get_deep_mind_logger(trx_context.is_transient())) {
std::string event_id = RAM_EVENT_ID("${code}:${scope}:${table}",
("code", tid.code)
("scope", tid.scope)
Expand All @@ -705,7 +707,7 @@ void apply_context::remove_table( const table_id_object& tid ) {

update_db_usage(tid.payer, - config::billable_size_v<table_id_object>);

if (auto dm_logger = control.get_deep_mind_logger()) {
if (auto dm_logger = control.get_deep_mind_logger(trx_context.is_transient())) {
dm_logger->on_remove_table(tid);
}

Expand Down Expand Up @@ -778,11 +780,13 @@ int apply_context::get_context_free_data( uint32_t index, char* buffer, size_t b
}

int apply_context::db_store_i64( name scope, name table, const account_name& payer, uint64_t id, const char* buffer, size_t buffer_size ) {
EOS_ASSERT( !trx_context.is_read_only(), table_operation_not_permitted, "cannot store a db record when executing a readonly transaction" );
return db_store_i64( receiver, scope, table, payer, id, buffer, buffer_size);
}

int apply_context::db_store_i64( name code, name scope, name table, const account_name& payer, uint64_t id, const char* buffer, size_t buffer_size ) {
// require_write_lock( scope );
EOS_ASSERT( !trx_context.is_read_only(), table_operation_not_permitted, "cannot store a db record when executing a readonly transaction" );
const auto& tab = find_or_create_table( code, scope, table, payer );
auto tableid = tab.id;

Expand All @@ -801,7 +805,7 @@ int apply_context::db_store_i64( name code, name scope, name table, const accoun

int64_t billable_size = (int64_t)(buffer_size + config::billable_size_v<key_value_object>);

if (auto dm_logger = control.get_deep_mind_logger()) {
if (auto dm_logger = control.get_deep_mind_logger(trx_context.is_transient())) {
std::string event_id = RAM_EVENT_ID("${table_code}:${scope}:${table_name}:${primkey}",
("table_code", tab.code)
("scope", tab.scope)
Expand All @@ -813,7 +817,7 @@ int apply_context::db_store_i64( name code, name scope, name table, const accoun

update_db_usage( payer, billable_size);

if (auto dm_logger = control.get_deep_mind_logger()) {
if (auto dm_logger = control.get_deep_mind_logger(trx_context.is_transient())) {
dm_logger->on_db_store_i64(tab, obj);
}

Expand All @@ -822,6 +826,7 @@ int apply_context::db_store_i64( name code, name scope, name table, const accoun
}

void apply_context::db_update_i64( int iterator, account_name payer, const char* buffer, size_t buffer_size ) {
EOS_ASSERT( !trx_context.is_read_only(), table_operation_not_permitted, "cannot update a db record when executing a readonly transaction" );
const key_value_object& obj = keyval_cache.get( iterator );

const auto& table_obj = keyval_cache.get_table( obj.t_id );
Expand All @@ -836,7 +841,7 @@ void apply_context::db_update_i64( int iterator, account_name payer, const char*
if( payer == account_name() ) payer = obj.payer;

std::string event_id;
if (control.get_deep_mind_logger() != nullptr) {
if (control.get_deep_mind_logger(trx_context.is_transient()) != nullptr) {
event_id = RAM_EVENT_ID("${table_code}:${scope}:${table_name}:${primkey}",
("table_code", table_obj.code)
("scope", table_obj.scope)
Expand All @@ -847,27 +852,27 @@ void apply_context::db_update_i64( int iterator, account_name payer, const char*

if( account_name(obj.payer) != payer ) {
// refund the existing payer
if (auto dm_logger = control.get_deep_mind_logger())
if (auto dm_logger = control.get_deep_mind_logger(trx_context.is_transient()))
{
dm_logger->on_ram_trace(std::string(event_id), "table_row", "remove", "primary_index_update_remove_old_payer");
}
update_db_usage( obj.payer, -(old_size) );
// charge the new payer
if (auto dm_logger = control.get_deep_mind_logger())
if (auto dm_logger = control.get_deep_mind_logger(trx_context.is_transient()))
{
dm_logger->on_ram_trace(std::move(event_id), "table_row", "add", "primary_index_update_add_new_payer");
}
update_db_usage( payer, (new_size));
} else if(old_size != new_size) {
// charge/refund the existing payer the difference
if (auto dm_logger = control.get_deep_mind_logger())
if (auto dm_logger = control.get_deep_mind_logger(trx_context.is_transient()))
{
dm_logger->on_ram_trace(std::move(event_id) , "table_row", "update", "primary_index_update");
}
update_db_usage( obj.payer, new_size - old_size);
}

if (auto dm_logger = control.get_deep_mind_logger()) {
if (auto dm_logger = control.get_deep_mind_logger(trx_context.is_transient())) {
dm_logger->on_db_update_i64(table_obj, obj, payer, buffer, buffer_size);
}

Expand All @@ -878,14 +883,15 @@ void apply_context::db_update_i64( int iterator, account_name payer, const char*
}

void apply_context::db_remove_i64( int iterator ) {
EOS_ASSERT( !trx_context.is_read_only(), table_operation_not_permitted, "cannot remove a db record when executing a readonly transaction" );
const key_value_object& obj = keyval_cache.get( iterator );

const auto& table_obj = keyval_cache.get_table( obj.t_id );
EOS_ASSERT( table_obj.code == receiver, table_access_violation, "db access violation" );

// require_write_lock( table_obj.scope );

if (auto dm_logger = control.get_deep_mind_logger()) {
if (auto dm_logger = control.get_deep_mind_logger(trx_context.is_transient())) {
std::string event_id = RAM_EVENT_ID("${table_code}:${scope}:${table_name}:${primkey}",
("table_code", table_obj.code)
("scope", table_obj.scope)
Expand All @@ -897,7 +903,7 @@ void apply_context::db_remove_i64( int iterator ) {

update_db_usage( obj.payer, -(obj.value.size() + config::billable_size_v<key_value_object>) );

if (auto dm_logger = control.get_deep_mind_logger()) {
if (auto dm_logger = control.get_deep_mind_logger(trx_context.is_transient())) {
dm_logger->on_db_remove_i64(table_obj, obj);
}

Expand Down Expand Up @@ -1029,17 +1035,27 @@ int apply_context::db_end_i64( name code, name scope, name table ) {

uint64_t apply_context::next_global_sequence() {
const auto& p = control.get_dynamic_global_properties();
db.modify( p, [&]( auto& dgp ) {
++dgp.global_action_sequence;
});
return p.global_action_sequence;
if ( trx_context.is_read_only() ) {
// To avoid confusion of duplicated global sequence number, hard code to be 0.
return 0;
} else {
db.modify( p, [&]( auto& dgp ) {
++dgp.global_action_sequence;
});
return p.global_action_sequence;
}
}

uint64_t apply_context::next_recv_sequence( const account_metadata_object& receiver_account ) {
db.modify( receiver_account, [&]( auto& ra ) {
++ra.recv_sequence;
});
return receiver_account.recv_sequence;
if ( trx_context.is_read_only() ) {
// To avoid confusion of duplicated receive sequence number, hard code to be 0.
return 0;
} else {
db.modify( receiver_account, [&]( auto& ra ) {
++ra.recv_sequence;
});
return receiver_account.recv_sequence;
}
}
uint64_t apply_context::next_auth_sequence( account_name actor ) {
const auto& amo = db.get<account_metadata_object,by_name>( actor );
Expand Down
16 changes: 9 additions & 7 deletions libraries/chain/authorization_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ namespace eosio { namespace chain {
permission_name name,
permission_id_type parent,
const authority& auth,
bool is_trx_transient,
time_point initial_creation_time
)
{
Expand All @@ -158,7 +159,7 @@ namespace eosio { namespace chain {
p.last_updated = creation_time;
p.auth = auth;

if (auto dm_logger = _control.get_deep_mind_logger()) {
if (auto dm_logger = _control.get_deep_mind_logger(is_trx_transient)) {
dm_logger->on_create_permission(p);
}
});
Expand All @@ -169,6 +170,7 @@ namespace eosio { namespace chain {
permission_name name,
permission_id_type parent,
authority&& auth,
bool is_trx_transient,
time_point initial_creation_time
)
{
Expand All @@ -193,20 +195,20 @@ namespace eosio { namespace chain {
p.last_updated = creation_time;
p.auth = std::move(auth);

if (auto dm_logger = _control.get_deep_mind_logger()) {
if (auto dm_logger = _control.get_deep_mind_logger(is_trx_transient)) {
dm_logger->on_create_permission(p);
}
});
return perm;
}

void authorization_manager::modify_permission( const permission_object& permission, const authority& auth ) {
void authorization_manager::modify_permission( const permission_object& permission, const authority& auth, bool is_trx_transient ) {
for(const key_weight& k: auth.keys)
EOS_ASSERT(k.key.which() < _db.get<protocol_state_object>().num_supported_key_types, unactivated_key_type,
"Unactivated key type used when modifying permission");

_db.modify( permission, [&](permission_object& po) {
auto dm_logger = _control.get_deep_mind_logger();
auto dm_logger = _control.get_deep_mind_logger(is_trx_transient);

std::optional<permission_object> old_permission;
if (dm_logger) {
Expand All @@ -216,21 +218,21 @@ namespace eosio { namespace chain {
po.auth = auth;
po.last_updated = _control.pending_block_time();

if (auto dm_logger = _control.get_deep_mind_logger()) {
if (auto dm_logger = _control.get_deep_mind_logger(is_trx_transient)) {
dm_logger->on_modify_permission(*old_permission, po);
}
});
}

void authorization_manager::remove_permission( const permission_object& permission ) {
void authorization_manager::remove_permission( const permission_object& permission, bool is_trx_transient ) {
const auto& index = _db.template get_index<permission_index, by_parent>();
auto range = index.equal_range(permission.id);
EOS_ASSERT( range.first == range.second, action_validate_exception,
"Cannot remove a permission which has children. Remove the children first.");

_db.get_mutable_index<permission_usage_index>().remove_object( permission.usage_id._id );

if (auto dm_logger = _control.get_deep_mind_logger()) {
if (auto dm_logger = _control.get_deep_mind_logger(is_trx_transient)) {
dm_logger->on_remove_permission(permission);
}

Expand Down
Loading

0 comments on commit 3c0e506

Please sign in to comment.