forked from cerc-io/ipld-eth-server
76 lines
2.6 KiB
Go
76 lines
2.6 KiB
Go
package db
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/core/types"
|
|
"github.com/ethereum/go-ethereum/ethdb"
|
|
"github.com/vulcanize/eth-block-extractor/pkg/db/level"
|
|
"github.com/vulcanize/eth-block-extractor/pkg/wrappers/core"
|
|
"github.com/vulcanize/eth-block-extractor/pkg/wrappers/core/rawdb"
|
|
"github.com/vulcanize/eth-block-extractor/pkg/wrappers/core/state"
|
|
"github.com/vulcanize/eth-block-extractor/pkg/wrappers/rlp"
|
|
)
|
|
|
|
var ErrNoSuchDb = errors.New("no such database")
|
|
|
|
type ReadError struct {
|
|
msg string
|
|
err error
|
|
}
|
|
|
|
func (re ReadError) Error() string {
|
|
return fmt.Sprintf("%s: %s", re.msg, re.err.Error())
|
|
}
|
|
|
|
type Database interface {
|
|
ComputeBlockStateTrie(currentBlock *types.Block, parentBlock *types.Block) (common.Hash, error)
|
|
GetBlockByBlockNumber(blockNumber int64) *types.Block
|
|
GetBlockBodyByBlockNumber(blockNumber int64) *types.Body
|
|
GetBlockHeaderByBlockNumber(blockNumber int64) *types.Header
|
|
GetRawBlockHeaderByBlockNumber(blockNumber int64) []byte
|
|
GetBlockReceipts(blockNumber int64) types.Receipts
|
|
GetStateAndStorageTrieNodes(root common.Hash) (stateTrieNodes, storageTrieNodes [][]byte, err error)
|
|
}
|
|
|
|
func CreateDatabase(config DatabaseConfig) (Database, error) {
|
|
switch config.Type {
|
|
case Level:
|
|
levelDBConnection, err := ethdb.NewLDBDatabase(config.Path, 128, 1024)
|
|
if err != nil {
|
|
return nil, ReadError{msg: "Failed to connect to LevelDB", err: err}
|
|
}
|
|
stateDatabase := state.NewDatabase(levelDBConnection)
|
|
stateTrieReader := createStateTrieReader(stateDatabase)
|
|
levelDBReader := rawdb.NewAccessorsChain(levelDBConnection)
|
|
stateComputer, err := createStateComputer(levelDBConnection, stateDatabase)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
levelDB := level.NewLevelDatabase(levelDBReader, stateComputer, stateTrieReader)
|
|
return levelDB, nil
|
|
default:
|
|
return nil, ReadError{msg: "Unknown database not implemented", err: ErrNoSuchDb}
|
|
}
|
|
}
|
|
|
|
func createStateTrieReader(stateDatabase state.GethStateDatabase) level.IStateTrieReader {
|
|
decoder := rlp.RlpDecoder{}
|
|
storageTrieReader := level.NewStorageTrieReader(stateDatabase, decoder)
|
|
return level.NewStateTrieReader(stateDatabase, storageTrieReader)
|
|
}
|
|
|
|
func createStateComputer(databaseConnection ethdb.Database, stateDatabase state.GethStateDatabase) (level.IStateComputer, error) {
|
|
blockChain, err := core.NewBlockChain(databaseConnection)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
processor := core.NewStateProcessor(*blockChain)
|
|
trieFactory := state.NewStateDBFactory()
|
|
validator := core.NewBlockValidator(*blockChain)
|
|
computer := level.NewStateComputer(blockChain, stateDatabase, processor, trieFactory, validator)
|
|
return computer, nil
|
|
}
|