Skip to content

Commit cee952b

Browse files
Check completeness of logs (#344)
1 parent 53fc1d1 commit cee952b

File tree

2 files changed

+117
-12
lines changed

2 files changed

+117
-12
lines changed

tests/block_header_test.go

+112-8
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package tests
22

33
import (
4+
"cmp"
45
"context"
56
"fmt"
67
"math/big"
8+
"slices"
79
"testing"
810
"time"
911

@@ -16,6 +18,8 @@ import (
1618
"github.com/Fantom-foundation/go-opera/opera/contracts/evmwriter"
1719
"github.com/Fantom-foundation/go-opera/opera/contracts/netinit"
1820
"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"
1923
"github.com/ethereum/go-ethereum/common"
2024
"github.com/ethereum/go-ethereum/common/hexutil"
2125
"github.com/ethereum/go-ethereum/core/types"
@@ -46,10 +50,13 @@ func testBlockHeadersOnNetwork(t *testing.T, net *IntegrationTestNet) {
4650
const numBlocks = 10
4751
require := require.New(t)
4852

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)
5057
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")
5360
}
5461

5562
client, err := net.GetClient()
@@ -63,13 +70,12 @@ func testBlockHeadersOnNetwork(t *testing.T, net *IntegrationTestNet) {
6370
originalHashes = append(originalHashes, header.Hash())
6471
}
6572

66-
// Run twice - once before and once after a node restart.
6773
runTests := func() {
6874
headers, err := net.GetHeaders()
6975
require.NoError(err)
7076

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)
7379
})
7480

7581
t.Run("BlockNumberEqualsPositionInChain", func(t *testing.T) {
@@ -139,6 +145,14 @@ func testBlockHeadersOnNetwork(t *testing.T, net *IntegrationTestNet) {
139145
t.Run("SystemContractsHaveNonZeroNonce", func(t *testing.T) {
140146
testHeaders_SystemContractsHaveNonZeroNonce(t, headers, client)
141147
})
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+
})
142156
}
143157

144158
runTests()
@@ -148,12 +162,12 @@ func testBlockHeadersOnNetwork(t *testing.T, net *IntegrationTestNet) {
148162
runTests()
149163
}
150164

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) {
152166
require := require.New(t)
153167

154168
require.GreaterOrEqual(len(newHeaders), len(hashes), "length mismatch")
155169
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)
157171
}
158172
}
159173

@@ -470,3 +484,93 @@ func testHeaders_SystemContractsHaveNonZeroNonce(t *testing.T, headers []*types.
470484
}
471485
}
472486
}
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+
}

tests/integration_test_net.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -410,10 +410,11 @@ func (n *IntegrationTestNet) RestartWithExportImport() error {
410410
originalArgs := os.Args
411411

412412
// export
413+
genesisFile := filepath.Join(n.directory, "testGenesis.g")
413414
os.Args = []string{
414415
"sonictool",
415416
"--datadir", n.stateDir(),
416-
"genesis", "export", n.directory + "/testGenesis.g",
417+
"genesis", "export", genesisFile,
417418
}
418419
err := sonictool.Run()
419420
if err != nil {
@@ -426,13 +427,13 @@ func (n *IntegrationTestNet) RestartWithExportImport() error {
426427
return err
427428
}
428429

429-
fmt.Println("Temp directory cleaned. Importing genesis file...")
430+
fmt.Println("State directory cleaned. Importing genesis file...")
430431

431432
// import genesis file
432433
os.Args = []string{
433434
"sonictool",
434435
"--datadir", n.stateDir(),
435-
"genesis", "--experimental", n.directory + "/testGenesis.g",
436+
"genesis", "--experimental", genesisFile,
436437
}
437438
err = sonictool.Run()
438439
if err != nil {
@@ -442,7 +443,7 @@ func (n *IntegrationTestNet) RestartWithExportImport() error {
442443
// restore original args
443444
os.Args = originalArgs
444445

445-
fmt.Println("Genesis file imported. Starting network...")
446+
fmt.Println("Genesis file imported. Restarting network...")
446447

447448
// start network again
448449
return n.start()

0 commit comments

Comments
 (0)