/
indexer_cmd.go
133 lines (121 loc) · 4.18 KB
/
indexer_cmd.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright 2022 Evmos Foundation
// This file is part of the Evmos Network packages.
//
// Evmos is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The Evmos packages are distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the Evmos packages. If not, see https://github.com/evmos/evmos/blob/main/LICENSE
package server
import (
"fmt"
"github.com/spf13/cobra"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/server"
"github.com/evmos/evmos/v12/indexer"
tmnode "github.com/tendermint/tendermint/node"
sm "github.com/tendermint/tendermint/state"
tmstore "github.com/tendermint/tendermint/store"
)
func NewIndexTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "index-eth-tx [backward|forward]",
Short: "Index historical eth txs",
Long: `Index historical eth txs, it only support two traverse direction to avoid creating gaps in the indexer db if using arbitrary block ranges:
- backward: index the blocks from the first indexed block to the earliest block in the chain, if indexer db is empty, start from the latest block.
- forward: index the blocks from the latest indexed block to latest block in the chain.
When start the node, the indexer start from the latest indexed block to avoid creating gap.
Backward mode should be used most of the time, so the latest indexed block is always up-to-date.
`,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
serverCtx := server.GetServerContextFromCmd(cmd)
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
direction := args[0]
if direction != "backward" && direction != "forward" {
return fmt.Errorf("unknown index direction, expect: backward|forward, got: %s", direction)
}
cfg := serverCtx.Config
home := cfg.RootDir
logger := serverCtx.Logger
idxDB, err := OpenIndexerDB(home, server.GetAppDBBackend(serverCtx.Viper))
if err != nil {
logger.Error("failed to open evm indexer DB", "error", err.Error())
return err
}
idxer := indexer.NewKVIndexer(idxDB, logger.With("module", "evmindex"), clientCtx)
// open local tendermint db, because the local rpc won't be available.
tmdb, err := tmnode.DefaultDBProvider(&tmnode.DBContext{ID: "blockstore", Config: cfg})
if err != nil {
return err
}
blockStore := tmstore.NewBlockStore(tmdb)
stateDB, err := tmnode.DefaultDBProvider(&tmnode.DBContext{ID: "state", Config: cfg})
if err != nil {
return err
}
stateStore := sm.NewStore(stateDB, sm.StoreOptions{
DiscardABCIResponses: cfg.Storage.DiscardABCIResponses,
})
indexBlock := func(height int64) error {
blk := blockStore.LoadBlock(height)
if blk == nil {
return fmt.Errorf("block not found %d", height)
}
resBlk, err := stateStore.LoadABCIResponses(height)
if err != nil {
return err
}
if err := idxer.IndexBlock(blk, resBlk.DeliverTxs); err != nil {
return err
}
fmt.Println(height)
return nil
}
switch args[0] {
case "backward":
first, err := idxer.FirstIndexedBlock()
if err != nil {
return err
}
if first == -1 {
// start from the latest block if indexer db is empty
first = blockStore.Height()
}
for i := first - 1; i > 0; i-- {
if err := indexBlock(i); err != nil {
return err
}
}
case "forward":
latest, err := idxer.LastIndexedBlock()
if err != nil {
return err
}
if latest == -1 {
// start from genesis if empty
latest = 0
}
for i := latest + 1; i <= blockStore.Height(); i++ {
if err := indexBlock(i); err != nil {
return err
}
}
default:
return fmt.Errorf("unknown direction %s", args[0])
}
return nil
},
}
return cmd
}