1
+ use std:: fmt:: Debug ;
1
2
#[ cfg( feature = "concurrency" ) ]
2
3
use std:: panic:: { self , catch_unwind, AssertUnwindSafe } ;
3
4
#[ cfg( feature = "concurrency" ) ]
@@ -18,6 +19,7 @@ use crate::context::BlockContext;
18
19
use crate :: state:: cached_state:: { CachedState , CommitmentStateDiff , TransactionalState } ;
19
20
use crate :: state:: errors:: StateError ;
20
21
use crate :: state:: state_api:: StateReader ;
22
+ use crate :: state:: visited_pcs:: VisitedPcs ;
21
23
use crate :: transaction:: errors:: TransactionExecutionError ;
22
24
use crate :: transaction:: objects:: TransactionExecutionInfo ;
23
25
use crate :: transaction:: transaction_execution:: Transaction ;
@@ -43,7 +45,7 @@ pub type TransactionExecutorResult<T> = Result<T, TransactionExecutorError>;
43
45
pub type VisitedSegmentsMapping = Vec < ( ClassHash , Vec < usize > ) > ;
44
46
45
47
// TODO(Gilad): make this hold TransactionContext instead of BlockContext.
46
- pub struct TransactionExecutor < S : StateReader > {
48
+ pub struct TransactionExecutor < S : StateReader , V : VisitedPcs > {
47
49
pub block_context : BlockContext ,
48
50
pub bouncer : Bouncer ,
49
51
// Note: this config must not affect the execution result (e.g. state diff and traces).
@@ -54,12 +56,12 @@ pub struct TransactionExecutor<S: StateReader> {
54
56
// block state to the worker executor - operating at the chunk level - and gets it back after
55
57
// committing the chunk. The block state is wrapped with an Option<_> to allow setting it to
56
58
// `None` while it is moved to the worker executor.
57
- pub block_state : Option < CachedState < S > > ,
59
+ pub block_state : Option < CachedState < S , V > > ,
58
60
}
59
61
60
- impl < S : StateReader > TransactionExecutor < S > {
62
+ impl < S : StateReader , V : VisitedPcs > TransactionExecutor < S , V > {
61
63
pub fn new (
62
- block_state : CachedState < S > ,
64
+ block_state : CachedState < S , V > ,
63
65
block_context : BlockContext ,
64
66
config : TransactionExecutorConfig ,
65
67
) -> Self {
@@ -85,9 +87,10 @@ impl<S: StateReader> TransactionExecutor<S> {
85
87
& mut self ,
86
88
tx : & Transaction ,
87
89
) -> TransactionExecutorResult < TransactionExecutionInfo > {
88
- let mut transactional_state = TransactionalState :: create_transactional (
89
- self . block_state . as_mut ( ) . expect ( BLOCK_STATE_ACCESS_ERR ) ,
90
- ) ;
90
+ let mut transactional_state: TransactionalState < ' _ , _ , V > =
91
+ TransactionalState :: create_transactional (
92
+ self . block_state . as_mut ( ) . expect ( BLOCK_STATE_ACCESS_ERR ) ,
93
+ ) ;
91
94
// Executing a single transaction cannot be done in a concurrent mode.
92
95
let execution_flags =
93
96
ExecutionFlags { charge_fee : true , validate : true , concurrency_mode : false } ;
@@ -157,7 +160,8 @@ impl<S: StateReader> TransactionExecutor<S> {
157
160
. as_ref ( )
158
161
. expect ( BLOCK_STATE_ACCESS_ERR )
159
162
. get_compiled_contract_class ( * class_hash) ?;
160
- Ok ( ( * class_hash, contract_class. get_visited_segments ( class_visited_pcs) ?) )
163
+ let class_visited_pcs = V :: to_set ( class_visited_pcs. clone ( ) ) ;
164
+ Ok ( ( * class_hash, contract_class. get_visited_segments ( & class_visited_pcs) ?) )
161
165
} )
162
166
. collect :: < TransactionExecutorResult < _ > > ( ) ?;
163
167
@@ -170,7 +174,7 @@ impl<S: StateReader> TransactionExecutor<S> {
170
174
}
171
175
}
172
176
173
- impl < S : StateReader + Send + Sync > TransactionExecutor < S > {
177
+ impl < S : StateReader + Send + Sync , V : VisitedPcs + Send + Sync > TransactionExecutor < S , V > {
174
178
/// Executes the given transactions on the state maintained by the executor.
175
179
/// Stops if and when there is no more room in the block, and returns the executed transactions'
176
180
/// results.
@@ -219,7 +223,7 @@ impl<S: StateReader + Send + Sync> TransactionExecutor<S> {
219
223
chunk : & [ Transaction ] ,
220
224
) -> Vec < TransactionExecutorResult < TransactionExecutionInfo > > {
221
225
use crate :: concurrency:: utils:: AbortIfPanic ;
222
- use crate :: state :: cached_state :: VisitedPcs ;
226
+ use crate :: concurrency :: worker_logic :: ExecutionTaskOutput ;
223
227
224
228
let block_state = self . block_state . take ( ) . expect ( "The block state should be `Some`." ) ;
225
229
@@ -263,20 +267,20 @@ impl<S: StateReader + Send + Sync> TransactionExecutor<S> {
263
267
264
268
let n_committed_txs = worker_executor. scheduler . get_n_committed_txs ( ) ;
265
269
let mut tx_execution_results = Vec :: new ( ) ;
266
- let mut visited_pcs: VisitedPcs = VisitedPcs :: new ( ) ;
270
+ let mut visited_pcs: V = V :: new ( ) ;
267
271
for execution_output in worker_executor. execution_outputs . iter ( ) {
268
272
if tx_execution_results. len ( ) >= n_committed_txs {
269
273
break ;
270
274
}
271
- let locked_execution_output = execution_output
275
+ let locked_execution_output: ExecutionTaskOutput < V > = execution_output
272
276
. lock ( )
273
277
. expect ( "Failed to lock execution output." )
274
278
. take ( )
275
279
. expect ( "Output must be ready." ) ;
276
280
tx_execution_results
277
281
. push ( locked_execution_output. result . map_err ( TransactionExecutorError :: from) ) ;
278
- for ( class_hash, class_visited_pcs) in locked_execution_output. visited_pcs {
279
- visited_pcs. entry ( class_hash ) . or_default ( ) . extend ( class_visited_pcs) ;
282
+ for ( class_hash, class_visited_pcs) in locked_execution_output. visited_pcs . iter ( ) {
283
+ visited_pcs. extend ( class_hash , class_visited_pcs) ;
280
284
}
281
285
}
282
286
0 commit comments