1515package org .hyperledger .besu .services ;
1616
1717import static org .assertj .core .api .Assertions .assertThat ;
18+ import static org .assertj .core .api .Assertions .fail ;
19+ import static org .mockito .ArgumentMatchers .any ;
20+ import static org .mockito .ArgumentMatchers .anyBoolean ;
21+ import static org .mockito .ArgumentMatchers .anyLong ;
22+ import static org .mockito .ArgumentMatchers .eq ;
23+ import static org .mockito .Mockito .mock ;
24+ import static org .mockito .Mockito .verify ;
1825
1926import org .hyperledger .besu .datatypes .Address ;
27+ import org .hyperledger .besu .datatypes .Hash ;
2028import org .hyperledger .besu .datatypes .Transaction ;
2129import org .hyperledger .besu .datatypes .Wei ;
2230import org .hyperledger .besu .ethereum .api .query .BlockchainQueries ;
2331import org .hyperledger .besu .ethereum .chain .MutableBlockchain ;
32+ import org .hyperledger .besu .ethereum .core .Block ;
2433import org .hyperledger .besu .ethereum .core .BlockchainSetupUtil ;
2534import org .hyperledger .besu .ethereum .worldstate .DataStorageFormat ;
2635import org .hyperledger .besu .ethereum .worldstate .WorldStateArchive ;
2736import org .hyperledger .besu .evm .log .Log ;
2837import org .hyperledger .besu .evm .worldstate .WorldView ;
38+ import org .hyperledger .besu .plugin .data .BlockBody ;
39+ import org .hyperledger .besu .plugin .data .BlockHeader ;
2940import org .hyperledger .besu .plugin .data .BlockTraceResult ;
3041import org .hyperledger .besu .plugin .data .TransactionTraceResult ;
3142import org .hyperledger .besu .plugin .services .TraceService ;
3243import org .hyperledger .besu .plugin .services .tracer .BlockAwareOperationTracer ;
3344
45+ import java .util .HashSet ;
3446import java .util .List ;
47+ import java .util .Optional ;
48+ import java .util .Set ;
49+ import java .util .stream .LongStream ;
3550
3651import org .apache .tuweni .bytes .Bytes ;
3752import org .junit .jupiter .api .BeforeEach ;
3853import org .junit .jupiter .api .Test ;
39- import org .junit .runner . RunWith ;
40- import org .mockito .junit .MockitoJUnitRunner ;
54+ import org .junit .jupiter . api . extension . ExtendWith ;
55+ import org .mockito .junit .jupiter . MockitoExtension ;
4156
42- @ RunWith ( MockitoJUnitRunner .class )
57+ @ ExtendWith ( MockitoExtension .class )
4358class TraceServiceImplTest {
4459
4560 TraceService traceService ;
@@ -73,19 +88,40 @@ void shouldRetrieveStateUpdatePostTracingForOneBlock() {
7388 final long persistedNonceForAccount =
7489 worldStateArchive .getMutable ().get (addressToVerify ).getNonce ();
7590
91+ final long blockNumber = 2 ;
92+
93+ final BlockAwareOperationTracer opTracer = mock (BlockAwareOperationTracer .class );
94+
7695 traceService .trace (
77- 2 ,
78- 2 ,
96+ blockNumber ,
97+ blockNumber ,
7998 worldState -> {
8099 assertThat (worldState .get (addressToVerify ).getNonce ()).isEqualTo (1 );
81100 },
82101 worldState -> {
83102 assertThat (worldState .get (addressToVerify ).getNonce ()).isEqualTo (2 );
84103 },
85- BlockAwareOperationTracer . NO_TRACING );
104+ opTracer );
86105
87106 assertThat (worldStateArchive .getMutable ().get (addressToVerify ).getNonce ())
88107 .isEqualTo (persistedNonceForAccount );
108+
109+ final Block tracedBlock = blockchain .getBlockByNumber (blockNumber ).get ();
110+
111+ verify (opTracer ).traceStartBlock (tracedBlock .getHeader (), tracedBlock .getBody ());
112+
113+ tracedBlock
114+ .getBody ()
115+ .getTransactions ()
116+ .forEach (
117+ tx -> {
118+ verify (opTracer ).traceStartTransaction (any (), eq (tx ));
119+ verify (opTracer )
120+ .traceEndTransaction (
121+ any (), eq (tx ), anyBoolean (), any (), any (), anyLong (), anyLong ());
122+ });
123+
124+ verify (opTracer ).traceEndBlock (tracedBlock .getHeader (), tracedBlock .getBody ());
89125 }
90126
91127 @ Test
@@ -96,20 +132,44 @@ void shouldRetrieveStateUpdatePostTracingForAllBlocks() {
96132 final long persistedNonceForAccount =
97133 worldStateArchive .getMutable ().get (addressToVerify ).getNonce ();
98134
135+ final long startBlock = 1 ;
136+ final long endBlock = 32 ;
137+ final BlockAwareOperationTracer opTracer = mock (BlockAwareOperationTracer .class );
138+
99139 traceService .trace (
100- 0 ,
101- 32 ,
140+ startBlock ,
141+ endBlock ,
102142 worldState -> {
103143 assertThat (worldState .get (addressToVerify ).getNonce ()).isEqualTo (0 );
104144 },
105145 worldState -> {
106146 assertThat (worldState .get (addressToVerify ).getNonce ())
107147 .isEqualTo (persistedNonceForAccount );
108148 },
109- BlockAwareOperationTracer . NO_TRACING );
149+ opTracer );
110150
111151 assertThat (worldStateArchive .getMutable ().get (addressToVerify ).getNonce ())
112152 .isEqualTo (persistedNonceForAccount );
153+
154+ LongStream .rangeClosed (startBlock , endBlock )
155+ .mapToObj (blockchain ::getBlockByNumber )
156+ .map (Optional ::get )
157+ .forEach (
158+ tracedBlock -> {
159+ verify (opTracer ).traceStartBlock (tracedBlock .getHeader (), tracedBlock .getBody ());
160+ tracedBlock
161+ .getBody ()
162+ .getTransactions ()
163+ .forEach (
164+ tx -> {
165+ verify (opTracer ).traceStartTransaction (any (), eq (tx ));
166+ verify (opTracer )
167+ .traceEndTransaction (
168+ any (), eq (tx ), anyBoolean (), any (), any (), anyLong (), anyLong ());
169+ });
170+
171+ verify (opTracer ).traceEndBlock (tracedBlock .getHeader (), tracedBlock .getBody ());
172+ });
113173 }
114174
115175 @ Test
@@ -197,8 +257,16 @@ private static class TxStartEndTracer implements BlockAwareOperationTracer {
197257 public long txEndGasUsed ;
198258 public Long txEndTimeNs ;
199259
260+ private final Set <Transaction > traceStartTxCalled = new HashSet <>();
261+ private final Set <Transaction > traceEndTxCalled = new HashSet <>();
262+ private final Set <Hash > traceStartBlockCalled = new HashSet <>();
263+ private final Set <Hash > traceEndBlockCalled = new HashSet <>();
264+
200265 @ Override
201266 public void traceStartTransaction (final WorldView worldView , final Transaction transaction ) {
267+ if (!traceStartTxCalled .add (transaction )) {
268+ fail ("traceStartTransaction already called for tx " + transaction );
269+ }
202270 txStartWorldView = worldView ;
203271 txStartTransaction = transaction ;
204272 }
@@ -212,6 +280,9 @@ public void traceEndTransaction(
212280 final List <Log > logs ,
213281 final long gasUsed ,
214282 final long timeNs ) {
283+ if (!traceEndTxCalled .add (transaction )) {
284+ fail ("traceEndTransaction already called for tx " + transaction );
285+ }
215286 txEndWorldView = worldView ;
216287 txEndTransaction = transaction ;
217288 txEndStatus = status ;
@@ -220,5 +291,19 @@ public void traceEndTransaction(
220291 txEndGasUsed = gasUsed ;
221292 txEndTimeNs = timeNs ;
222293 }
294+
295+ @ Override
296+ public void traceStartBlock (final BlockHeader blockHeader , final BlockBody blockBody ) {
297+ if (!traceStartBlockCalled .add (blockHeader .getBlockHash ())) {
298+ fail ("traceStartBlock already called for block " + blockHeader );
299+ }
300+ }
301+
302+ @ Override
303+ public void traceEndBlock (final BlockHeader blockHeader , final BlockBody blockBody ) {
304+ if (!traceEndBlockCalled .add (blockHeader .getBlockHash ())) {
305+ fail ("traceEndBlock already called for block " + blockHeader );
306+ }
307+ }
223308 }
224309}
0 commit comments