ipld-eth-server/vendor/github.com/vulcanize/eth-block-extractor/pkg/db/database.go
2019-12-02 13:24:46 -06:00

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
}