Skip to content

Commit ac6ef33

Browse files
authored
Merge pull request #156 from vulcanize/schema_updates
Schema updates
2 parents 898e64b + b9a82f6 commit ac6ef33

20 files changed

+961
-326
lines changed

statediff/indexer/database/dump/indexer.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,10 @@ func (sdi *StateDiffIndexer) PushBlock(block *types.Block, receipts types.Receip
184184
func (sdi *StateDiffIndexer) processHeader(tx *BatchTx, header *types.Header, headerNode node.Node, reward, td *big.Int) (string, error) {
185185
tx.cacheIPLD(headerNode)
186186

187-
var baseFee *int64
187+
var baseFee *string
188188
if header.BaseFee != nil {
189-
baseFee = new(int64)
190-
*baseFee = header.BaseFee.Int64()
189+
baseFee = new(string)
190+
*baseFee = header.BaseFee.String()
191191
}
192192

193193
headerID := header.Hash().String()

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: 27 additions & 27 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

194-
var baseFee *int64
194+
var baseFee *string
195195
if header.BaseFee != nil {
196-
baseFee = new(int64)
197-
*baseFee = header.BaseFee.Int64()
196+
baseFee = new(string)
197+
*baseFee = header.BaseFee.String()
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: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
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+
"errors"
22+
"os"
23+
"testing"
24+
25+
"github.com/ipfs/go-cid"
26+
"github.com/jmoiron/sqlx"
27+
"github.com/multiformats/go-multihash"
28+
"github.com/stretchr/testify/require"
29+
30+
"github.com/ethereum/go-ethereum/core/types"
31+
"github.com/ethereum/go-ethereum/statediff/indexer/database/file"
32+
"github.com/ethereum/go-ethereum/statediff/indexer/database/sql/postgres"
33+
"github.com/ethereum/go-ethereum/statediff/indexer/interfaces"
34+
"github.com/ethereum/go-ethereum/statediff/indexer/ipld"
35+
"github.com/ethereum/go-ethereum/statediff/indexer/mocks"
36+
"github.com/ethereum/go-ethereum/statediff/indexer/test_helpers"
37+
)
38+
39+
var (
40+
legacyData = mocks.NewLegacyData()
41+
mockLegacyBlock *types.Block
42+
legacyHeaderCID cid.Cid
43+
)
44+
45+
func setupLegacy(t *testing.T) {
46+
mockLegacyBlock = legacyData.MockBlock
47+
legacyHeaderCID, _ = ipld.RawdataToCid(ipld.MEthHeader, legacyData.MockHeaderRlp, multihash.KECCAK_256)
48+
if _, err := os.Stat(file.TestConfig.FilePath); !errors.Is(err, os.ErrNotExist) {
49+
err := os.Remove(file.TestConfig.FilePath)
50+
require.NoError(t, err)
51+
}
52+
ind, err := file.NewStateDiffIndexer(context.Background(), legacyData.Config, file.TestConfig)
53+
require.NoError(t, err)
54+
var tx interfaces.Batch
55+
tx, err = ind.PushBlock(
56+
mockLegacyBlock,
57+
legacyData.MockReceipts,
58+
legacyData.MockBlock.Difficulty())
59+
require.NoError(t, err)
60+
61+
defer func() {
62+
if err := tx.Submit(err); err != nil {
63+
t.Fatal(err)
64+
}
65+
if err := ind.Close(); err != nil {
66+
t.Fatal(err)
67+
}
68+
}()
69+
for _, node := range legacyData.StateDiffs {
70+
err = ind.PushStateNode(tx, node, legacyData.MockBlock.Hash().String())
71+
require.NoError(t, err)
72+
}
73+
74+
test_helpers.ExpectEqual(t, tx.(*file.BatchTx).BlockNumber, legacyData.BlockNumber.Uint64())
75+
76+
connStr := postgres.DefaultConfig.DbConnectionString()
77+
78+
sqlxdb, err = sqlx.Connect("postgres", connStr)
79+
if err != nil {
80+
t.Fatalf("failed to connect to db with connection string: %s err: %v", connStr, err)
81+
}
82+
}
83+
84+
func dumpData(t *testing.T) {
85+
sqlFileBytes, err := os.ReadFile(file.TestConfig.FilePath)
86+
require.NoError(t, err)
87+
88+
_, err = sqlxdb.Exec(string(sqlFileBytes))
89+
require.NoError(t, err)
90+
}
91+
92+
func tearDown(t *testing.T) {
93+
file.TearDownDB(t, sqlxdb)
94+
err := os.Remove(file.TestConfig.FilePath)
95+
require.NoError(t, err)
96+
err = sqlxdb.Close()
97+
require.NoError(t, err)
98+
}
99+
100+
func expectTrue(t *testing.T, value bool) {
101+
if !value {
102+
t.Fatalf("Assertion failed")
103+
}
104+
}
105+
106+
func TestFileIndexerLegacy(t *testing.T) {
107+
t.Run("Publish and index header IPLDs", func(t *testing.T) {
108+
setupLegacy(t)
109+
dumpData(t)
110+
defer tearDown(t)
111+
pgStr := `SELECT cid, td, reward, block_hash, base_fee
112+
FROM eth.header_cids
113+
WHERE block_number = $1`
114+
// check header was properly indexed
115+
type res struct {
116+
CID string
117+
TD string
118+
Reward string
119+
BlockHash string `db:"block_hash"`
120+
BaseFee *string `db:"base_fee"`
121+
}
122+
header := new(res)
123+
err = sqlxdb.QueryRowx(pgStr, legacyData.BlockNumber.Uint64()).StructScan(header)
124+
require.NoError(t, err)
125+
126+
test_helpers.ExpectEqual(t, header.CID, legacyHeaderCID.String())
127+
test_helpers.ExpectEqual(t, header.TD, legacyData.MockBlock.Difficulty().String())
128+
test_helpers.ExpectEqual(t, header.Reward, "5000000000000011250")
129+
require.Nil(t, legacyData.MockHeader.BaseFee)
130+
require.Nil(t, header.BaseFee)
131+
})
132+
}

0 commit comments

Comments
 (0)