2021-10-21 17:06:06 +00:00
|
|
|
package cmd
|
|
|
|
|
|
|
|
import (
|
2021-11-13 00:45:08 +00:00
|
|
|
"context"
|
2023-08-25 07:57:33 +00:00
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
2021-10-25 19:06:05 +00:00
|
|
|
|
2023-08-31 13:00:12 +00:00
|
|
|
statediff "github.com/cerc-io/plugeth-statediff"
|
2023-08-25 07:57:33 +00:00
|
|
|
"github.com/cerc-io/plugeth-statediff/indexer"
|
|
|
|
"github.com/cerc-io/plugeth-statediff/indexer/node"
|
|
|
|
"github.com/cerc-io/plugeth-statediff/indexer/shared"
|
|
|
|
"github.com/cerc-io/plugeth-statediff/utils/log"
|
2021-10-25 19:06:05 +00:00
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
|
|
"github.com/ethereum/go-ethereum/params"
|
2021-10-21 17:06:06 +00:00
|
|
|
"github.com/ethereum/go-ethereum/trie"
|
|
|
|
"github.com/spf13/viper"
|
|
|
|
|
2023-08-25 07:57:33 +00:00
|
|
|
pkg "github.com/cerc-io/eth-statediff-service/pkg"
|
2022-09-20 18:00:10 +00:00
|
|
|
"github.com/cerc-io/eth-statediff-service/pkg/prom"
|
2021-10-21 17:06:06 +00:00
|
|
|
)
|
|
|
|
|
2021-10-25 19:06:05 +00:00
|
|
|
type blockRange [2]uint64
|
|
|
|
|
2023-08-25 07:57:33 +00:00
|
|
|
func createStateDiffService(lvlDBReader pkg.Reader, chainConf *params.ChainConfig, nodeInfo node.Info) (*pkg.Service, error) {
|
2021-10-21 17:06:06 +00:00
|
|
|
// create statediff service
|
2023-08-31 13:00:12 +00:00
|
|
|
logWithCommand.Debug("Setting up database")
|
2021-11-13 00:45:08 +00:00
|
|
|
conf, err := getConfig(nodeInfo)
|
2021-10-21 17:06:06 +00:00
|
|
|
if err != nil {
|
|
|
|
logWithCommand.Fatal(err)
|
|
|
|
}
|
2022-07-19 09:30:01 +00:00
|
|
|
|
2023-08-31 13:00:12 +00:00
|
|
|
logWithCommand.Debug("Creating statediff indexer")
|
2023-08-25 07:57:33 +00:00
|
|
|
db, indexer, err := indexer.NewStateDiffIndexer(context.Background(), chainConf, nodeInfo, conf)
|
2021-10-21 17:06:06 +00:00
|
|
|
if err != nil {
|
|
|
|
logWithCommand.Fatal(err)
|
|
|
|
}
|
2022-07-19 09:30:01 +00:00
|
|
|
if conf.Type() == shared.POSTGRES && viper.GetBool("prom.dbStats") {
|
|
|
|
prom.RegisterDBCollector(viper.GetString("database.name"), db)
|
|
|
|
}
|
|
|
|
|
2023-08-31 13:00:12 +00:00
|
|
|
logWithCommand.Debug("Creating statediff service")
|
2023-08-25 07:57:33 +00:00
|
|
|
sdConf := pkg.ServiceConfig{
|
2021-10-25 19:06:05 +00:00
|
|
|
ServiceWorkers: viper.GetUint("statediff.serviceWorkers"),
|
|
|
|
TrieWorkers: viper.GetUint("statediff.trieWorkers"),
|
|
|
|
WorkerQueueSize: viper.GetUint("statediff.workerQueueSize"),
|
|
|
|
PreRuns: setupPreRunRanges(),
|
|
|
|
}
|
2023-08-25 07:57:33 +00:00
|
|
|
return pkg.NewStateDiffService(lvlDBReader, indexer, sdConf), nil
|
2021-10-21 17:06:06 +00:00
|
|
|
}
|
|
|
|
|
2023-08-25 07:57:33 +00:00
|
|
|
func setupPreRunRanges() []pkg.RangeRequest {
|
2021-10-25 19:06:05 +00:00
|
|
|
if !viper.GetBool("statediff.prerun") {
|
|
|
|
return nil
|
|
|
|
}
|
2022-07-19 09:30:01 +00:00
|
|
|
preRunParams := statediff.Params{
|
2023-08-25 07:57:33 +00:00
|
|
|
IncludeBlock: viper.GetBool("prerun.params.includeBlock"),
|
|
|
|
IncludeReceipts: viper.GetBool("prerun.params.includeReceipts"),
|
|
|
|
IncludeTD: viper.GetBool("prerun.params.includeTD"),
|
|
|
|
IncludeCode: viper.GetBool("prerun.params.includeCode"),
|
2021-10-25 19:06:05 +00:00
|
|
|
}
|
|
|
|
var addrStrs []string
|
|
|
|
viper.UnmarshalKey("prerun.params.watchedAddresses", &addrStrs)
|
|
|
|
addrs := make([]common.Address, len(addrStrs))
|
|
|
|
for i, addrStr := range addrStrs {
|
|
|
|
addrs[i] = common.HexToAddress(addrStr)
|
|
|
|
}
|
|
|
|
preRunParams.WatchedAddresses = addrs
|
|
|
|
var rawRanges []blockRange
|
|
|
|
viper.UnmarshalKey("prerun.ranges", &rawRanges)
|
2023-08-25 07:57:33 +00:00
|
|
|
blockRanges := make([]pkg.RangeRequest, len(rawRanges))
|
2021-10-25 19:06:05 +00:00
|
|
|
for i, rawRange := range rawRanges {
|
2023-08-25 07:57:33 +00:00
|
|
|
blockRanges[i] = pkg.RangeRequest{
|
2021-10-25 19:06:05 +00:00
|
|
|
Start: rawRange[0],
|
|
|
|
Stop: rawRange[1],
|
|
|
|
Params: preRunParams,
|
|
|
|
}
|
|
|
|
}
|
2021-10-27 15:40:08 +00:00
|
|
|
if viper.IsSet("prerun.start") && viper.IsSet("prerun.stop") {
|
|
|
|
hardStart := viper.GetInt("prerun.start")
|
|
|
|
hardStop := viper.GetInt("prerun.stop")
|
2023-08-25 07:57:33 +00:00
|
|
|
blockRanges = append(blockRanges, pkg.RangeRequest{
|
2021-10-27 15:40:08 +00:00
|
|
|
Start: uint64(hardStart),
|
|
|
|
Stop: uint64(hardStop),
|
|
|
|
Params: preRunParams,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-10-25 19:06:05 +00:00
|
|
|
return blockRanges
|
|
|
|
}
|
2022-10-10 18:38:55 +00:00
|
|
|
|
2023-08-25 07:57:33 +00:00
|
|
|
// LoadConfig loads chain config from json file
|
|
|
|
func LoadConfig(chainConfigPath string) (*params.ChainConfig, error) {
|
|
|
|
file, err := os.Open(chainConfigPath)
|
|
|
|
if err != nil {
|
2023-08-31 13:00:12 +00:00
|
|
|
log.Error("Failed to read chain config file", "error", err)
|
2023-08-25 07:57:33 +00:00
|
|
|
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer file.Close()
|
|
|
|
|
|
|
|
chainConfig := new(params.ChainConfig)
|
|
|
|
if err := json.NewDecoder(file).Decode(chainConfig); err != nil {
|
2023-08-31 13:00:12 +00:00
|
|
|
log.Error("invalid chain config file", "error", err)
|
2023-08-25 07:57:33 +00:00
|
|
|
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2023-08-31 13:00:12 +00:00
|
|
|
log.Debug(fmt.Sprintf("Using chain config from '%s'. Content: %+v", chainConfigPath, chainConfig))
|
2023-08-25 07:57:33 +00:00
|
|
|
|
|
|
|
return chainConfig, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func instantiateLevelDBReader() (pkg.Reader, *params.ChainConfig, node.Info) {
|
2022-10-10 18:38:55 +00:00
|
|
|
// load some necessary params
|
2023-08-31 13:00:12 +00:00
|
|
|
logWithCommand.Debug("Loading statediff service parameters")
|
2022-10-10 18:38:55 +00:00
|
|
|
mode := viper.GetString("leveldb.mode")
|
|
|
|
path := viper.GetString("leveldb.path")
|
|
|
|
ancientPath := viper.GetString("leveldb.ancient")
|
|
|
|
url := viper.GetString("leveldb.url")
|
|
|
|
|
|
|
|
if mode == "local" {
|
|
|
|
if path == "" || ancientPath == "" {
|
|
|
|
logWithCommand.Fatal("Require a valid eth LevelDB primary datastore path and ancient datastore path")
|
|
|
|
}
|
|
|
|
} else if mode == "remote" {
|
|
|
|
if url == "" {
|
|
|
|
logWithCommand.Fatal("Require a valid RPC url for accessing LevelDB")
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
logWithCommand.Fatal("Invalid mode provided for LevelDB access")
|
|
|
|
}
|
|
|
|
|
|
|
|
nodeInfo := getEthNodeInfo()
|
|
|
|
|
|
|
|
chainConfigPath := viper.GetString("ethereum.chainConfig")
|
2023-08-25 07:57:33 +00:00
|
|
|
chainConf, err := LoadConfig(chainConfigPath)
|
2022-10-10 18:38:55 +00:00
|
|
|
if err != nil {
|
2023-08-25 07:57:33 +00:00
|
|
|
logWithCommand.Fatalf("Unable to instantiate chain config: %s", err)
|
2022-10-10 18:38:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// create LevelDB reader
|
2023-08-31 13:00:12 +00:00
|
|
|
logWithCommand.Debug("Creating LevelDB reader")
|
2023-08-25 07:57:33 +00:00
|
|
|
readerConf := pkg.LvLDBReaderConfig{
|
2022-10-10 18:38:55 +00:00
|
|
|
TrieConfig: &trie.Config{
|
|
|
|
Cache: viper.GetInt("cache.trie"),
|
|
|
|
Journal: "",
|
|
|
|
Preimages: false,
|
|
|
|
},
|
|
|
|
ChainConfig: chainConf,
|
|
|
|
Mode: mode,
|
|
|
|
Path: path,
|
|
|
|
AncientPath: ancientPath,
|
|
|
|
Url: url,
|
|
|
|
DBCacheSize: viper.GetInt("cache.database"),
|
|
|
|
}
|
2023-08-25 07:57:33 +00:00
|
|
|
reader, err := pkg.NewLvlDBReader(readerConf)
|
2022-10-10 18:38:55 +00:00
|
|
|
if err != nil {
|
2023-08-25 07:57:33 +00:00
|
|
|
logWithCommand.Fatalf("Unable to instantiate levelDB reader: %s", err)
|
2022-10-10 18:38:55 +00:00
|
|
|
}
|
|
|
|
return reader, chainConf, nodeInfo
|
|
|
|
}
|
2023-08-31 13:00:12 +00:00
|
|
|
|
|
|
|
// report latest block info
|
|
|
|
func reportLatestBlock(reader pkg.Reader) {
|
|
|
|
header, err := reader.GetLatestHeader()
|
|
|
|
if err != nil {
|
|
|
|
logWithCommand.Fatalf("Unable to determine latest header height and hash: %s", err.Error())
|
|
|
|
}
|
|
|
|
if header.Number == nil {
|
|
|
|
logWithCommand.Fatal("Latest header found in levelDB has a nil block height")
|
|
|
|
}
|
|
|
|
logWithCommand.
|
|
|
|
WithField("height", header.Number).
|
|
|
|
WithField("hash", header.Hash()).
|
|
|
|
Info("Latest block found in levelDB")
|
|
|
|
}
|