1
1
package tests
2
2
3
3
import (
4
+ "cmp"
4
5
"context"
5
6
"fmt"
6
7
"math/big"
8
+ "slices"
7
9
"testing"
8
10
"time"
9
11
@@ -16,6 +18,8 @@ import (
16
18
"github.com/Fantom-foundation/go-opera/opera/contracts/evmwriter"
17
19
"github.com/Fantom-foundation/go-opera/opera/contracts/netinit"
18
20
"github.com/Fantom-foundation/go-opera/opera/contracts/sfc"
21
+ "github.com/Fantom-foundation/go-opera/tests/contracts/counter_event_emitter"
22
+ "github.com/ethereum/go-ethereum"
19
23
"github.com/ethereum/go-ethereum/common"
20
24
"github.com/ethereum/go-ethereum/common/hexutil"
21
25
"github.com/ethereum/go-ethereum/core/types"
@@ -46,10 +50,13 @@ func testBlockHeadersOnNetwork(t *testing.T, net *IntegrationTestNet) {
46
50
const numBlocks = 10
47
51
require := require .New (t )
48
52
49
- // Produce a few blocks on the network.
53
+ // Produce a few blocks on the network. We use the counter contract since
54
+ // it is also producing events.
55
+ counter , _ , err := DeployContract (net , counter_event_emitter .DeployCounterEventEmitter )
56
+ require .NoError (err )
50
57
for range numBlocks {
51
- _ , err := net .EndowAccount (common. Address { 42 }, 100 )
52
- require .NoError (err , "failed to endow account " )
58
+ _ , err := net .Apply ( counter . Increment )
59
+ require .NoError (err , "failed to increment counter " )
53
60
}
54
61
55
62
client , err := net .GetClient ()
@@ -63,13 +70,12 @@ func testBlockHeadersOnNetwork(t *testing.T, net *IntegrationTestNet) {
63
70
originalHashes = append (originalHashes , header .Hash ())
64
71
}
65
72
66
- // Run twice - once before and once after a node restart.
67
73
runTests := func () {
68
74
headers , err := net .GetHeaders ()
69
75
require .NoError (err )
70
76
71
- t .Run ("CompareHeadersHashes " , func (t * testing.T ) {
72
- testHeaders_CompareHeadersHashes (t , originalHashes , headers )
77
+ t .Run ("CompareHeaderHashes " , func (t * testing.T ) {
78
+ testHeaders_CompareHeaderHashes (t , originalHashes , headers )
73
79
})
74
80
75
81
t .Run ("BlockNumberEqualsPositionInChain" , func (t * testing.T ) {
@@ -139,6 +145,14 @@ func testBlockHeadersOnNetwork(t *testing.T, net *IntegrationTestNet) {
139
145
t .Run ("SystemContractsHaveNonZeroNonce" , func (t * testing.T ) {
140
146
testHeaders_SystemContractsHaveNonZeroNonce (t , headers , client )
141
147
})
148
+
149
+ t .Run ("LogsReferenceTheirContext" , func (t * testing.T ) {
150
+ testHeaders_LogsReferenceTheirContext (t , headers , client )
151
+ })
152
+
153
+ t .Run ("CanRetrieveLogEvents" , func (t * testing.T ) {
154
+ testHeaders_CanRetrieveLogEvents (t , headers , client )
155
+ })
142
156
}
143
157
144
158
runTests ()
@@ -148,12 +162,12 @@ func testBlockHeadersOnNetwork(t *testing.T, net *IntegrationTestNet) {
148
162
runTests ()
149
163
}
150
164
151
- func testHeaders_CompareHeadersHashes (t * testing.T , hashes []common.Hash , newHeaders []* types.Header ) {
165
+ func testHeaders_CompareHeaderHashes (t * testing.T , hashes []common.Hash , newHeaders []* types.Header ) {
152
166
require := require .New (t )
153
167
154
168
require .GreaterOrEqual (len (newHeaders ), len (hashes ), "length mismatch" )
155
169
for i , hash := range hashes {
156
- require .Equal (hash , newHeaders [i ].Hash (), "hash mismatch" )
170
+ require .Equal (hash , newHeaders [i ].Hash (), "hash mismatch for block %d" , i )
157
171
}
158
172
}
159
173
@@ -470,3 +484,93 @@ func testHeaders_SystemContractsHaveNonZeroNonce(t *testing.T, headers []*types.
470
484
}
471
485
}
472
486
}
487
+
488
+ func testHeaders_LogsReferenceTheirContext (t * testing.T , headers []* types.Header , client * ethclient.Client ) {
489
+ require := require .New (t )
490
+
491
+ numLogs := 0
492
+ for _ , header := range headers {
493
+ blockHash := header .Hash ()
494
+ blockNumber := header .Number .Uint64 ()
495
+
496
+ receipts , err := client .BlockReceipts (context .Background (),
497
+ rpc .BlockNumberOrHashWithHash (blockHash , false ))
498
+ require .NoError (err , "failed to get block receipts" )
499
+
500
+ index := 0
501
+ for txIndex , receipt := range receipts {
502
+ for _ , log := range receipt .Logs {
503
+ numLogs ++
504
+ require .Equal (blockHash , log .BlockHash , "block hash mismatch" )
505
+ require .Equal (blockNumber , log .BlockNumber , "block number mismatch" )
506
+ require .Equal (receipt .TxHash , log .TxHash , "transaction hash mismatch" )
507
+ require .Equal (uint (txIndex ), log .TxIndex , "transaction index mismatch" )
508
+ require .Equal (uint (index ), log .Index , "log index mismatch" )
509
+ require .False (log .Removed , "log was removed" )
510
+ index ++
511
+ }
512
+ }
513
+ }
514
+
515
+ require .NotZero (numLogs , "no logs found in the chain" )
516
+ }
517
+
518
+ func testHeaders_CanRetrieveLogEvents (t * testing.T , headers []* types.Header , client * ethclient.Client ) {
519
+ require := require .New (t )
520
+
521
+ allLogs := []types.Log {}
522
+ for _ , header := range headers {
523
+ blockHash := header .Hash ()
524
+ receipts , err := client .BlockReceipts (context .Background (),
525
+ rpc .BlockNumberOrHashWithHash (blockHash , false ))
526
+ require .NoError (err , "failed to get block receipts" )
527
+
528
+ for _ , receipt := range receipts {
529
+ for _ , log := range receipt .Logs {
530
+ allLogs = append (allLogs , * log )
531
+
532
+ // Check that logs can be retrieved by specifically filtering
533
+ // for each individual log entry.
534
+ topicFilter := [][]common.Hash {}
535
+ for _ , topic := range log .Topics {
536
+ topicFilter = append (topicFilter , []common.Hash {topic })
537
+ }
538
+ logs , err := client .FilterLogs (
539
+ context .Background (),
540
+ ethereum.FilterQuery {
541
+ BlockHash : & blockHash ,
542
+ Addresses : []common.Address {log .Address },
543
+ Topics : topicFilter ,
544
+ },
545
+ )
546
+ require .NoError (err , "failed to get logs" )
547
+ require .Equal ([]types.Log {* log }, logs , "log mismatch" )
548
+ }
549
+ }
550
+ }
551
+
552
+ require .NotZero (len (allLogs ), "no logs found in the chain" )
553
+
554
+ // Fetch all logs from the chain in a single query and see that no extra
555
+ // log entries are returned.
556
+ logs , err := client .FilterLogs (
557
+ context .Background (),
558
+ ethereum.FilterQuery {
559
+ FromBlock : big .NewInt (0 ),
560
+ ToBlock : big .NewInt (int64 (len (headers ) - 1 )),
561
+ },
562
+ )
563
+ require .NoError (err , "failed to get logs" )
564
+
565
+ // Sort logs in chronological order to have a deterministic comparison.
566
+ logCompare := func (a , b types.Log ) int {
567
+ if res := cmp .Compare (a .BlockNumber , b .BlockNumber ); res != 0 {
568
+ return res
569
+ }
570
+ return cmp .Compare (a .Index , b .Index )
571
+ }
572
+
573
+ slices .SortFunc (logs , logCompare )
574
+ slices .SortFunc (allLogs , logCompare )
575
+ require .Equal (allLogs , logs , "log mismatch" )
576
+ }
0 commit comments