Skip to content

Commit 128328b

Browse files
authored
Merge pull request #1153 from AntelopeIO/GH-1145-replay-errors-main
[1.1.0 -> main] Fix deferred trx processing
2 parents 61a1d4b + 9ebc0ed commit 128328b

File tree

6 files changed

+23
-7
lines changed

6 files changed

+23
-7
lines changed

benchmark/bls.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ struct interface_in_benchmark {
7878
timer = std::make_unique<platform_timer>();
7979
trx_timer = std::make_unique<transaction_checktime_timer>(*timer);
8080
trx_ctx = std::make_unique<transaction_context>(*chain->control.get(), *ptrx, ptrx->id(), std::move(*trx_timer),
81-
action_digests_t::store_which_t::legacy);
81+
action_digests_t::store_which_t::legacy, fc::time_point::now(),
82+
transaction_metadata::trx_type::input);
8283
trx_ctx->max_transaction_time_subjective = fc::microseconds::maximum();
8384
trx_ctx->init_for_input_trx( ptrx->get_unprunable_size(), ptrx->get_prunable_size() );
8485
trx_ctx->exec(); // this is required to generate action traces to be used by apply_context constructor

libraries/chain/controller.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -2644,7 +2644,8 @@ struct controller_impl {
26442644

26452645
transaction_checktime_timer trx_timer(timer);
26462646
const packed_transaction trx( std::move( etrx ) );
2647-
transaction_context trx_context( self, trx, trx.id(), std::move(trx_timer), bb.action_receipt_digests().store_which(), start );
2647+
transaction_context trx_context( self, trx, trx.id(), std::move(trx_timer), bb.action_receipt_digests().store_which(),
2648+
start, transaction_metadata::trx_type::implicit );
26482649

26492650
if (auto dm_logger = get_deep_mind_logger(trx_context.is_transient())) {
26502651
dm_logger->on_onerror(etrx);
@@ -2690,6 +2691,8 @@ struct controller_impl {
26902691
} catch ( const boost::interprocess::bad_alloc& ) {
26912692
throw;
26922693
} catch( const fc::exception& e ) {
2694+
// apply_onerror for deferred trxs is implicit so interrupt oc not allowed
2695+
assert(e.code() != interrupt_oc_exception::code_value);
26932696
handle_exception(e);
26942697
} catch ( const std::exception& e ) {
26952698
auto wrapper = fc::std_exception_wrapper::from_current_exception(e);
@@ -2815,7 +2818,8 @@ struct controller_impl {
28152818
auto& bb = std::get<building_block>(pending->_block_stage);
28162819

28172820
transaction_checktime_timer trx_timer( timer );
2818-
transaction_context trx_context( self, *trx->packed_trx(), gtrx.trx_id, std::move(trx_timer), bb.action_receipt_digests().store_which() );
2821+
transaction_context trx_context( self, *trx->packed_trx(), gtrx.trx_id, std::move(trx_timer), bb.action_receipt_digests().store_which(),
2822+
start, transaction_metadata::trx_type::scheduled );
28192823
trx_context.leeway = fc::microseconds(0); // avoid stealing cpu resource
28202824
trx_context.block_deadline = block_deadline;
28212825
trx_context.max_transaction_time_subjective = max_transaction_time;

libraries/chain/include/eosio/chain/transaction_context.hpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ namespace eosio::chain {
114114
const transaction_id_type& trx_id, // trx_id diff than t.id() before replace_deferred
115115
transaction_checktime_timer&& timer,
116116
action_digests_t::store_which_t sad,
117-
fc::time_point start = fc::time_point::now(),
118-
transaction_metadata::trx_type type = transaction_metadata::trx_type::input);
117+
fc::time_point start,
118+
transaction_metadata::trx_type type);
119119
~transaction_context();
120120

121121
void init_for_implicit_trx();
@@ -162,6 +162,8 @@ namespace eosio::chain {
162162
bool is_dry_run()const { return trx_type == transaction_metadata::trx_type::dry_run; };
163163
bool is_read_only()const { return trx_type == transaction_metadata::trx_type::read_only; };
164164
bool is_transient()const { return trx_type == transaction_metadata::trx_type::read_only || trx_type == transaction_metadata::trx_type::dry_run; };
165+
bool is_implicit()const { return trx_type == transaction_metadata::trx_type::implicit; };
166+
bool is_scheduled()const { return trx_type == transaction_metadata::trx_type::scheduled; };
165167
bool has_undo()const;
166168

167169
int64_t set_proposed_producers(vector<producer_authority> producers);

libraries/chain/include/eosio/chain/wasm_interface_private.hpp

+8-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,14 @@ struct eosvmoc_tier {
164164
}
165165
}
166166
#endif
167-
const bool allow_oc_interrupt = attempt_tierup && context.is_applying_block() && context.trx_context.has_undo();
167+
// Do not allow oc interrupt if no undo as the transaction needs to be undone to restart it.
168+
// Do not allow oc interrupt if implicit or scheduled. There are two implicit trxs: onblock and onerror.
169+
// The onerror trx of deferred trxs is implicit. Interrupt needs to be disabled for deferred trxs because
170+
// they capture all exceptions, explicitly handle undo stack, and directly call trx_context.execute_action.
171+
// Not allowing interrupt for onblock seems rather harmless, so instead of distinguishing between onerror and
172+
// onblock, just disallow for all implicit.
173+
const bool allow_oc_interrupt = attempt_tierup && context.is_applying_block() &&
174+
context.trx_context.has_undo() && !context.trx_context.is_implicit() && !context.trx_context.is_scheduled();
168175
auto ex = fc::make_scoped_exit([&]() {
169176
if (allow_oc_interrupt) {
170177
eos_vm_oc_compile_interrupt = false;

libraries/chain/transaction_context.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ namespace eosio::chain {
5959
undo();
6060
*trace = transaction_trace{}; // reset trace
6161
initialize();
62+
transaction_timer.stop();
6263
resume_billing_timer(start);
6364

6465
auto sw = executed_action_receipts.store_which();

libraries/chain/webassembly/runtimes/eos-vm-oc/executor.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,6 @@ void executor::execute(const code_descriptor& code, memory& mem, apply_context&
231231
syscall(SYS_mprotect, self->code_mapping, self->code_mapping_size, PROT_NONE);
232232
self->mapping_is_executable = false;
233233
}, this);
234-
context.trx_context.checktime(); //catch any expiration that might have occurred before setting up callback
235234

236235
auto cleanup = fc::make_scoped_exit([cb, &tt=context.trx_context.transaction_timer, &mem=mem](){
237236
cb->is_running = false;
@@ -245,6 +244,8 @@ void executor::execute(const code_descriptor& code, memory& mem, apply_context&
245244
}
246245
});
247246

247+
context.trx_context.checktime(); //catch any expiration that might have occurred before setting up callback
248+
248249
void(*apply_func)(uint64_t, uint64_t, uint64_t) = (void(*)(uint64_t, uint64_t, uint64_t))(cb->running_code_base + code.apply_offset);
249250

250251
switch(sigsetjmp(*cb->jmp, 0)) {

0 commit comments

Comments
 (0)