Skip to content

Commit b96c26f

Browse files
committed
cleanup; more unit tests
1 parent 898e64b commit b96c26f

File tree

14 files changed

+873
-280
lines changed

14 files changed

+873
-280
lines changed

statediff/indexer/database/file/config.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,15 @@ type Config struct {
3131
func (c Config) Type() shared.DBType {
3232
return shared.FILE
3333
}
34+
35+
// TestConfig config for unit tests
36+
var TestConfig = Config{
37+
FilePath: "./statediffing_test_file.sql",
38+
NodeInfo: node.Info{
39+
GenesisBlock: "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3",
40+
NetworkID: "1",
41+
ChainID: 1,
42+
ID: "mockNodeID",
43+
ClientName: "go-ethereum",
44+
},
45+
}

statediff/indexer/database/file/indexer.go

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ var (
5353

5454
// StateDiffIndexer satisfies the indexer.StateDiffIndexer interface for ethereum statediff objects on top of a void
5555
type StateDiffIndexer struct {
56-
writer *SQLWriter
56+
fileWriter *SQLWriter
5757
chainConfig *params.ChainConfig
5858
nodeID string
5959
wg *sync.WaitGroup
@@ -79,7 +79,7 @@ func NewStateDiffIndexer(ctx context.Context, chainConfig *params.ChainConfig, c
7979
w.upsertNode(config.NodeInfo)
8080
w.upsertIPLDDirect(shared.RemovedNodeMhKey, []byte{})
8181
return &StateDiffIndexer{
82-
writer: w,
82+
fileWriter: w,
8383
chainConfig: chainConfig,
8484
nodeID: config.NodeInfo.ID,
8585
wg: wg,
@@ -133,7 +133,7 @@ func (sdi *StateDiffIndexer) PushBlock(block *types.Block, receipts types.Receip
133133
indexerMetrics.tStateStoreCodeProcessing.Update(tDiff)
134134
traceMsg += fmt.Sprintf("state, storage, and code storage processing time: %s\r\n", tDiff.String())
135135
t = time.Now()
136-
sdi.writer.Flush()
136+
sdi.fileWriter.Flush()
137137
tDiff = time.Since(t)
138138
indexerMetrics.tPostgresCommit.Update(tDiff)
139139
traceMsg += fmt.Sprintf("postgres transaction commit duration: %s\r\n", tDiff.String())
@@ -189,15 +189,15 @@ func (sdi *StateDiffIndexer) PushBlock(block *types.Block, receipts types.Receip
189189
// processHeader write a header IPLD insert SQL stmt to a file
190190
// it returns the headerID
191191
func (sdi *StateDiffIndexer) processHeader(header *types.Header, headerNode node.Node, reward, td *big.Int) string {
192-
sdi.writer.upsertIPLDNode(headerNode)
192+
sdi.fileWriter.upsertIPLDNode(headerNode)
193193

194194
var baseFee *int64
195195
if header.BaseFee != nil {
196196
baseFee = new(int64)
197197
*baseFee = header.BaseFee.Int64()
198198
}
199199
headerID := header.Hash().String()
200-
sdi.writer.upsertHeaderCID(models.HeaderModel{
200+
sdi.fileWriter.upsertHeaderCID(models.HeaderModel{
201201
NodeID: sdi.nodeID,
202202
CID: headerNode.Cid().String(),
203203
MhKey: shared.MultihashKeyFromCID(headerNode.Cid()),
@@ -221,15 +221,15 @@ func (sdi *StateDiffIndexer) processHeader(header *types.Header, headerNode node
221221
func (sdi *StateDiffIndexer) processUncles(headerID string, blockNumber uint64, uncleNodes []*ipld2.EthHeader) {
222222
// publish and index uncles
223223
for _, uncleNode := range uncleNodes {
224-
sdi.writer.upsertIPLDNode(uncleNode)
224+
sdi.fileWriter.upsertIPLDNode(uncleNode)
225225
var uncleReward *big.Int
226226
// in PoA networks uncle reward is 0
227227
if sdi.chainConfig.Clique != nil {
228228
uncleReward = big.NewInt(0)
229229
} else {
230230
uncleReward = shared.CalcUncleMinerReward(blockNumber, uncleNode.Number.Uint64())
231231
}
232-
sdi.writer.upsertUncleCID(models.UncleModel{
232+
sdi.fileWriter.upsertUncleCID(models.UncleModel{
233233
HeaderID: headerID,
234234
CID: uncleNode.Cid().String(),
235235
MhKey: shared.MultihashKeyFromCID(uncleNode.Cid()),
@@ -261,10 +261,10 @@ func (sdi *StateDiffIndexer) processReceiptsAndTxs(args processArgs) error {
261261
signer := types.MakeSigner(sdi.chainConfig, args.blockNumber)
262262
for i, receipt := range args.receipts {
263263
for _, logTrieNode := range args.logTrieNodes[i] {
264-
sdi.writer.upsertIPLDNode(logTrieNode)
264+
sdi.fileWriter.upsertIPLDNode(logTrieNode)
265265
}
266266
txNode := args.txNodes[i]
267-
sdi.writer.upsertIPLDNode(txNode)
267+
sdi.fileWriter.upsertIPLDNode(txNode)
268268

269269
// index tx
270270
trx := args.txs[i]
@@ -285,7 +285,7 @@ func (sdi *StateDiffIndexer) processReceiptsAndTxs(args processArgs) error {
285285
MhKey: shared.MultihashKeyFromCID(txNode.Cid()),
286286
Type: trx.Type(),
287287
}
288-
sdi.writer.upsertTransactionCID(txModel)
288+
sdi.fileWriter.upsertTransactionCID(txModel)
289289

290290
// index access list if this is one
291291
for j, accessListElement := range trx.AccessList() {
@@ -299,7 +299,7 @@ func (sdi *StateDiffIndexer) processReceiptsAndTxs(args processArgs) error {
299299
Address: accessListElement.Address.Hex(),
300300
StorageKeys: storageKeys,
301301
}
302-
sdi.writer.upsertAccessListElement(accessListElementModel)
302+
sdi.fileWriter.upsertAccessListElement(accessListElementModel)
303303
}
304304

305305
// this is the contract address if this receipt is for a contract creation tx
@@ -327,7 +327,7 @@ func (sdi *StateDiffIndexer) processReceiptsAndTxs(args processArgs) error {
327327
} else {
328328
rctModel.PostState = common.Bytes2Hex(receipt.PostState)
329329
}
330-
sdi.writer.upsertReceiptCID(rctModel)
330+
sdi.fileWriter.upsertReceiptCID(rctModel)
331331

332332
// index logs
333333
logDataSet := make([]*models.LogsModel, len(receipt.Logs))
@@ -354,13 +354,13 @@ func (sdi *StateDiffIndexer) processReceiptsAndTxs(args processArgs) error {
354354
Topic3: topicSet[3],
355355
}
356356
}
357-
sdi.writer.upsertLogCID(logDataSet)
357+
sdi.fileWriter.upsertLogCID(logDataSet)
358358
}
359359

360360
// publish trie nodes, these aren't indexed directly
361361
for i, n := range args.txTrieNodes {
362-
sdi.writer.upsertIPLDNode(n)
363-
sdi.writer.upsertIPLDNode(args.rctTrieNodes[i])
362+
sdi.fileWriter.upsertIPLDNode(n)
363+
sdi.fileWriter.upsertIPLDNode(args.rctTrieNodes[i])
364364
}
365365

366366
return nil
@@ -380,10 +380,10 @@ func (sdi *StateDiffIndexer) PushStateNode(batch interfaces.Batch, stateNode sdt
380380
MhKey: shared.RemovedNodeMhKey,
381381
NodeType: stateNode.NodeType.Int(),
382382
}
383-
sdi.writer.upsertStateCID(stateModel)
383+
sdi.fileWriter.upsertStateCID(stateModel)
384384
return nil
385385
}
386-
stateCIDStr, stateMhKey, err := sdi.writer.upsertIPLDRaw(ipld2.MEthStateTrie, multihash.KECCAK_256, stateNode.NodeValue)
386+
stateCIDStr, stateMhKey, err := sdi.fileWriter.upsertIPLDRaw(ipld2.MEthStateTrie, multihash.KECCAK_256, stateNode.NodeValue)
387387
if err != nil {
388388
return fmt.Errorf("error generating and cacheing state node IPLD: %v", err)
389389
}
@@ -396,7 +396,7 @@ func (sdi *StateDiffIndexer) PushStateNode(batch interfaces.Batch, stateNode sdt
396396
NodeType: stateNode.NodeType.Int(),
397397
}
398398
// index the state node
399-
sdi.writer.upsertStateCID(stateModel)
399+
sdi.fileWriter.upsertStateCID(stateModel)
400400
// if we have a leaf, decode and index the account data
401401
if stateNode.NodeType == sdtypes.Leaf {
402402
var i []interface{}
@@ -418,7 +418,7 @@ func (sdi *StateDiffIndexer) PushStateNode(batch interfaces.Batch, stateNode sdt
418418
CodeHash: account.CodeHash,
419419
StorageRoot: account.Root.String(),
420420
}
421-
sdi.writer.upsertStateAccount(accountModel)
421+
sdi.fileWriter.upsertStateAccount(accountModel)
422422
}
423423
// if there are any storage nodes associated with this node, publish and index them
424424
for _, storageNode := range stateNode.StorageNodes {
@@ -434,10 +434,10 @@ func (sdi *StateDiffIndexer) PushStateNode(batch interfaces.Batch, stateNode sdt
434434
MhKey: shared.RemovedNodeMhKey,
435435
NodeType: storageNode.NodeType.Int(),
436436
}
437-
sdi.writer.upsertStorageCID(storageModel)
437+
sdi.fileWriter.upsertStorageCID(storageModel)
438438
continue
439439
}
440-
storageCIDStr, storageMhKey, err := sdi.writer.upsertIPLDRaw(ipld2.MEthStorageTrie, multihash.KECCAK_256, storageNode.NodeValue)
440+
storageCIDStr, storageMhKey, err := sdi.fileWriter.upsertIPLDRaw(ipld2.MEthStorageTrie, multihash.KECCAK_256, storageNode.NodeValue)
441441
if err != nil {
442442
return fmt.Errorf("error generating and cacheing storage node IPLD: %v", err)
443443
}
@@ -450,7 +450,7 @@ func (sdi *StateDiffIndexer) PushStateNode(batch interfaces.Batch, stateNode sdt
450450
MhKey: storageMhKey,
451451
NodeType: storageNode.NodeType.Int(),
452452
}
453-
sdi.writer.upsertStorageCID(storageModel)
453+
sdi.fileWriter.upsertStorageCID(storageModel)
454454
}
455455

456456
return nil
@@ -463,11 +463,11 @@ func (sdi *StateDiffIndexer) PushCodeAndCodeHash(batch interfaces.Batch, codeAnd
463463
if err != nil {
464464
return fmt.Errorf("error deriving multihash key from codehash: %v", err)
465465
}
466-
sdi.writer.upsertIPLDDirect(mhKey, codeAndCodeHash.Code)
466+
sdi.fileWriter.upsertIPLDDirect(mhKey, codeAndCodeHash.Code)
467467
return nil
468468
}
469469

470470
// Close satisfies io.Closer
471471
func (sdi *StateDiffIndexer) Close() error {
472-
return sdi.writer.Close()
472+
return sdi.fileWriter.Close()
473473
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
// VulcanizeDB
2+
// Copyright © 2019 Vulcanize
3+
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Affero General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Affero General Public License for more details.
13+
14+
// You should have received a copy of the GNU Affero General Public License
15+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
17+
package file_test
18+
19+
import (
20+
"context"
21+
"os"
22+
"testing"
23+
24+
"github.com/ethereum/go-ethereum/core/types"
25+
"github.com/ethereum/go-ethereum/statediff/indexer/database/file"
26+
"github.com/ethereum/go-ethereum/statediff/indexer/mocks"
27+
"github.com/ipfs/go-cid"
28+
"github.com/jmoiron/sqlx"
29+
30+
"github.com/multiformats/go-multihash"
31+
"github.com/stretchr/testify/require"
32+
33+
"github.com/ethereum/go-ethereum/statediff/indexer/database/sql"
34+
"github.com/ethereum/go-ethereum/statediff/indexer/database/sql/postgres"
35+
"github.com/ethereum/go-ethereum/statediff/indexer/interfaces"
36+
"github.com/ethereum/go-ethereum/statediff/indexer/ipld"
37+
"github.com/ethereum/go-ethereum/statediff/indexer/test_helpers"
38+
)
39+
40+
var (
41+
legacyData = mocks.NewLegacyData()
42+
mockLegacyBlock *types.Block
43+
legacyHeaderCID cid.Cid
44+
)
45+
46+
func setupLegacy(t *testing.T) {
47+
mockLegacyBlock = legacyData.MockBlock
48+
legacyHeaderCID, _ = ipld.RawdataToCid(ipld.MEthHeader, legacyData.MockHeaderRlp, multihash.KECCAK_256)
49+
50+
ind, err := file.NewStateDiffIndexer(context.Background(), legacyData.Config, file.TestConfig)
51+
require.NoError(t, err)
52+
var tx interfaces.Batch
53+
tx, err = ind.PushBlock(
54+
mockLegacyBlock,
55+
legacyData.MockReceipts,
56+
legacyData.MockBlock.Difficulty())
57+
require.NoError(t, err)
58+
59+
defer func() {
60+
if err := tx.Submit(err); err != nil {
61+
t.Fatal(err)
62+
}
63+
if err := ind.Close(); err != nil {
64+
t.Fatal(err)
65+
}
66+
}()
67+
for _, node := range legacyData.StateDiffs {
68+
err = ind.PushStateNode(tx, node, legacyData.MockBlock.Hash().String())
69+
require.NoError(t, err)
70+
}
71+
72+
test_helpers.ExpectEqual(t, tx.(*sql.BatchTx).BlockNumber, legacyData.BlockNumber.Uint64())
73+
74+
connStr := postgres.DefaultConfig.DbConnectionString()
75+
76+
sqlxdb, err = sqlx.Connect("postgres", connStr)
77+
if err != nil {
78+
t.Fatalf("failed to connect to db with connection string: %s err: %v", connStr, err)
79+
}
80+
}
81+
82+
func dumpData(t *testing.T) {
83+
sqlFileBytes, err := os.ReadFile(file.TestConfig.FilePath)
84+
require.NoError(t, err)
85+
86+
_, err = sqlxdb.Exec(string(sqlFileBytes))
87+
require.NoError(t, err)
88+
}
89+
90+
func tearDown(t *testing.T) {
91+
err := os.Remove(file.TestConfig.FilePath)
92+
require.NoError(t, err)
93+
err = sqlxdb.Close()
94+
require.NoError(t, err)
95+
}
96+
97+
func expectTrue(t *testing.T, value bool) {
98+
if !value {
99+
t.Fatalf("Assertion failed")
100+
}
101+
}
102+
103+
func TestFIleIndexerLegacy(t *testing.T) {
104+
t.Run("Publish and index header IPLDs in a legacy tx", func(t *testing.T) {
105+
setupLegacy(t)
106+
dumpData(t)
107+
defer tearDown(t)
108+
pgStr := `SELECT cid, cast(td AS TEXT), cast(reward AS TEXT), block_hash, base_fee
109+
FROM eth.header_cids
110+
WHERE block_number = $1`
111+
// check header was properly indexed
112+
type res struct {
113+
CID string
114+
TD string
115+
Reward string
116+
BlockHash string `db:"block_hash"`
117+
BaseFee *int64 `db:"base_fee"`
118+
}
119+
header := new(res)
120+
121+
err = sqlxdb.QueryRow(pgStr, legacyData.BlockNumber.Uint64()).Scan(
122+
&header.CID, &header.TD, &header.Reward, &header.BlockHash, &header.BaseFee)
123+
require.NoError(t, err)
124+
125+
test_helpers.ExpectEqual(t, header.CID, legacyHeaderCID.String())
126+
test_helpers.ExpectEqual(t, header.TD, legacyData.MockBlock.Difficulty().String())
127+
test_helpers.ExpectEqual(t, header.Reward, "5000000000000011250")
128+
require.Nil(t, legacyData.MockHeader.BaseFee)
129+
require.Nil(t, header.BaseFee)
130+
})
131+
}

0 commit comments

Comments
 (0)