update dependencies to work with update eth-block-extractor

This commit is contained in:
Ian Norden
2019-12-02 13:24:49 -06:00
parent 31a9017c4f
commit d702cb720c
3000 changed files with 433987 additions and 182448 deletions
-19
View File
@@ -1,19 +0,0 @@
package db
type DatabaseType int
const (
Level DatabaseType = iota
)
type DatabaseConfig struct {
Type DatabaseType
Path string
}
func CreateDatabaseConfig(dbType DatabaseType, path string) DatabaseConfig {
return DatabaseConfig{
Type: dbType,
Path: path,
}
}
-75
View File
@@ -1,75 +0,0 @@
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
}
@@ -1,59 +0,0 @@
package level
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/vulcanize/eth-block-extractor/pkg/wrappers/core/rawdb"
)
type Database struct {
accessorsChain rawdb.IAccessorsChain
stateComputer IStateComputer
stateTrieReader IStateTrieReader
}
func NewLevelDatabase(accessorsChain rawdb.IAccessorsChain, stateComputer IStateComputer, stateTrieReader IStateTrieReader) *Database {
return &Database{
accessorsChain: accessorsChain,
stateComputer: stateComputer,
stateTrieReader: stateTrieReader,
}
}
func (db Database) ComputeBlockStateTrie(currentBlock *types.Block, parentBlock *types.Block) (common.Hash, error) {
return db.stateComputer.ComputeBlockStateTrie(currentBlock, parentBlock)
}
func (db Database) GetBlockBodyByBlockNumber(blockNumber int64) *types.Body {
n := uint64(blockNumber)
h := db.accessorsChain.GetCanonicalHash(n)
return db.accessorsChain.GetBody(h, n)
}
func (db Database) GetBlockByBlockNumber(blockNumber int64) *types.Block {
n := uint64(blockNumber)
h := db.accessorsChain.GetCanonicalHash(n)
return db.accessorsChain.GetBlock(h, n)
}
func (db Database) GetBlockHeaderByBlockNumber(blockNumber int64) *types.Header {
n := uint64(blockNumber)
h := db.accessorsChain.GetCanonicalHash(n)
return db.accessorsChain.GetHeader(h, n)
}
func (db Database) GetRawBlockHeaderByBlockNumber(blockNumber int64) []byte {
n := uint64(blockNumber)
h := db.accessorsChain.GetCanonicalHash(n)
return db.accessorsChain.GetHeaderRLP(h, n)
}
func (db Database) GetBlockReceipts(blockNumber int64) types.Receipts {
n := uint64(blockNumber)
h := db.accessorsChain.GetCanonicalHash(n)
return db.accessorsChain.GetBlockReceipts(h, n)
}
func (db Database) GetStateAndStorageTrieNodes(root common.Hash) (stateTrieNodes, storageTrieNodes [][]byte, err error) {
return db.stateTrieReader.GetStateAndStorageTrieNodes(root)
}
@@ -1,168 +0,0 @@
package level_test
import (
"github.com/ethereum/go-ethereum/common"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/ethereum/go-ethereum/core/types"
"github.com/vulcanize/eth-block-extractor/pkg/db/level"
"github.com/vulcanize/eth-block-extractor/test_helpers"
level_wrapper "github.com/vulcanize/eth-block-extractor/test_helpers/mocks/db/level"
"github.com/vulcanize/eth-block-extractor/test_helpers/mocks/wrappers/core/rawdb"
)
var _ = Describe("Database", func() {
Describe("Computing state trie nodes", func() {
It("invokes state computer to build historical state", func() {
mockStateComputer := level_wrapper.NewMockStateComputer()
db := level.NewLevelDatabase(rawdb.NewMockAccessorsChain(), mockStateComputer, level_wrapper.NewMockStateTrieReader())
currentBlock := &types.Block{}
parentBlock := &types.Block{}
_, err := db.ComputeBlockStateTrie(currentBlock, parentBlock)
Expect(err).NotTo(HaveOccurred())
mockStateComputer.AssertComputeBlockStateTrieCalledWith(currentBlock, parentBlock)
})
It("returns err if state computer returns err", func() {
mockStateComputer := level_wrapper.NewMockStateComputer()
mockStateComputer.SetComputeBlockStateTrieReturnErr(test_helpers.FakeError)
db := level.NewLevelDatabase(rawdb.NewMockAccessorsChain(), mockStateComputer, level_wrapper.NewMockStateTrieReader())
_, err := db.ComputeBlockStateTrie(&types.Block{}, &types.Block{})
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(test_helpers.FakeError))
})
})
Describe("Getting block body data", func() {
It("invokes the chain accessor to query for block hash by block number", func() {
mockAccessorsChain := rawdb.NewMockAccessorsChain()
db := level.NewLevelDatabase(mockAccessorsChain, level_wrapper.NewMockStateComputer(), level_wrapper.NewMockStateTrieReader())
num := int64(123456)
db.GetBlockBodyByBlockNumber(num)
mockAccessorsChain.AssertGetCanonicalHashCalledWith(uint64(num))
})
It("invokes the chain accessor to query for block body data", func() {
mockAccessorsChain := rawdb.NewMockAccessorsChain()
mockAccessorsChain.SetGetCanonicalHashReturnHash(test_helpers.FakeHash)
db := level.NewLevelDatabase(mockAccessorsChain, level_wrapper.NewMockStateComputer(), level_wrapper.NewMockStateTrieReader())
num := int64(123456)
db.GetBlockBodyByBlockNumber(num)
mockAccessorsChain.AssertGetBodyRLPCalledWith(test_helpers.FakeHash, uint64(num))
})
})
Describe("Getting block", func() {
It("invokes the chain accessor to query for block hash by block number", func() {
mockAccessorsChain := rawdb.NewMockAccessorsChain()
db := level.NewLevelDatabase(mockAccessorsChain, level_wrapper.NewMockStateComputer(), level_wrapper.NewMockStateTrieReader())
num := int64(123456)
db.GetBlockByBlockNumber(num)
mockAccessorsChain.AssertGetCanonicalHashCalledWith(uint64(num))
})
It("invokes the chain accessor to query for block", func() {
mockAccessorsChain := rawdb.NewMockAccessorsChain()
mockAccessorsChain.SetGetCanonicalHashReturnHash(test_helpers.FakeHash)
db := level.NewLevelDatabase(mockAccessorsChain, level_wrapper.NewMockStateComputer(), level_wrapper.NewMockStateTrieReader())
num := int64(123456)
db.GetBlockByBlockNumber(num)
mockAccessorsChain.AssertGetBlockCalledWith(test_helpers.FakeHash, uint64(num))
})
})
Describe("Getting block header", func() {
It("invokes the chain accessor to query for block hash by block number", func() {
mockAccessorsChain := rawdb.NewMockAccessorsChain()
db := level.NewLevelDatabase(mockAccessorsChain, level_wrapper.NewMockStateComputer(), level_wrapper.NewMockStateTrieReader())
num := int64(123456)
db.GetBlockHeaderByBlockNumber(num)
mockAccessorsChain.AssertGetCanonicalHashCalledWith(uint64(num))
})
It("invokes the chain accessor to query for block header", func() {
mockAccessorsChain := rawdb.NewMockAccessorsChain()
mockAccessorsChain.SetGetCanonicalHashReturnHash(test_helpers.FakeHash)
db := level.NewLevelDatabase(mockAccessorsChain, level_wrapper.NewMockStateComputer(), level_wrapper.NewMockStateTrieReader())
num := int64(123456)
db.GetBlockHeaderByBlockNumber(num)
mockAccessorsChain.AssertGetHeaderCalledWith(test_helpers.FakeHash, uint64(num))
})
})
Describe("Getting raw block header data", func() {
It("invokes the chain accessor to query for block hash by block number", func() {
mockAccessorsChain := rawdb.NewMockAccessorsChain()
db := level.NewLevelDatabase(mockAccessorsChain, level_wrapper.NewMockStateComputer(), level_wrapper.NewMockStateTrieReader())
num := int64(123456)
db.GetRawBlockHeaderByBlockNumber(num)
mockAccessorsChain.AssertGetCanonicalHashCalledWith(uint64(num))
})
It("invokes the chain accessor to query for block header data", func() {
mockAccessorsChain := rawdb.NewMockAccessorsChain()
mockAccessorsChain.SetGetCanonicalHashReturnHash(test_helpers.FakeHash)
db := level.NewLevelDatabase(mockAccessorsChain, level_wrapper.NewMockStateComputer(), level_wrapper.NewMockStateTrieReader())
num := int64(123456)
db.GetRawBlockHeaderByBlockNumber(num)
mockAccessorsChain.AssertGetHeaderRLPCalledWith(test_helpers.FakeHash, uint64(num))
})
})
Describe("Getting block receipts", func() {
It("invokes the chain accessor to query for block hash by block number", func() {
mockAccessorsChain := rawdb.NewMockAccessorsChain()
db := level.NewLevelDatabase(mockAccessorsChain, level_wrapper.NewMockStateComputer(), level_wrapper.NewMockStateTrieReader())
num := int64(123456)
db.GetBlockReceipts(num)
mockAccessorsChain.AssertGetCanonicalHashCalledWith(uint64(num))
})
It("invokes the chain accessor to query for block receipts", func() {
mockAccessorsChain := rawdb.NewMockAccessorsChain()
mockAccessorsChain.SetGetCanonicalHashReturnHash(test_helpers.FakeHash)
db := level.NewLevelDatabase(mockAccessorsChain, level_wrapper.NewMockStateComputer(), level_wrapper.NewMockStateTrieReader())
num := int64(123456)
db.GetBlockReceipts(num)
mockAccessorsChain.AssertGetBlockReceiptsCalledWith(test_helpers.FakeHash, uint64(num))
})
})
Describe("Getting state trie nodes", func() {
It("invokes the chain accessor to query for state trie data", func() {
mockStateTrieReader := level_wrapper.NewMockStateTrieReader()
db := level.NewLevelDatabase(rawdb.NewMockAccessorsChain(), level_wrapper.NewMockStateComputer(), mockStateTrieReader)
root := common.HexToHash("abcde")
_, _, err := db.GetStateAndStorageTrieNodes(root)
Expect(err).NotTo(HaveOccurred())
mockStateTrieReader.AssertGetStateAndStorageTrieNodesCalledWith(root)
})
})
})
@@ -1,13 +0,0 @@
package level_test
import (
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
func TestLevel(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Level Suite")
}
@@ -1,50 +0,0 @@
package level
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/vulcanize/eth-block-extractor/pkg/wrappers/core"
"github.com/vulcanize/eth-block-extractor/pkg/wrappers/core/state"
)
type IStateComputer interface {
ComputeBlockStateTrie(currentBlock *types.Block, parentBlock *types.Block) (root common.Hash, err error)
}
type StateComputer struct {
blockChain core.GethCoreBlockChain
db state.GethStateDatabase
processor core.GethStateProcessor
stateDBFactory state.GethStateDBFactory
validator core.GethBlockValidator
}
func NewStateComputer(blockChain core.GethCoreBlockChain, db state.GethStateDatabase, processor core.GethStateProcessor, stateDBFactory state.GethStateDBFactory, validator core.GethBlockValidator) *StateComputer {
return &StateComputer{
blockChain: blockChain,
db: db,
processor: processor,
stateDBFactory: stateDBFactory,
validator: validator,
}
}
func (sc *StateComputer) ComputeBlockStateTrie(block, parent *types.Block) (root common.Hash, err error) {
stateTrie, err := sc.stateDBFactory.NewStateDB(parent.Root(), sc.db.Database())
if err != nil {
return root, err
}
return sc.createStateTrieForBlock(block, parent, stateTrie)
}
func (sc *StateComputer) createStateTrieForBlock(block, parent *types.Block, stateTrie state.GethStateDB) (root common.Hash, err error) {
receipts, _, usedGas, err := sc.processor.Process(block, stateTrie.StateDB())
if err != nil {
return root, err
}
err = sc.validator.ValidateState(block, parent, stateTrie.StateDB(), receipts, usedGas)
if err != nil {
return root, err
}
return stateTrie.Commit(sc.blockChain.Config().IsEIP158(block.Number()))
}
@@ -1,176 +0,0 @@
package level_test
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/eth-block-extractor/pkg/db/level"
"github.com/vulcanize/eth-block-extractor/test_helpers"
"github.com/vulcanize/eth-block-extractor/test_helpers/mocks/wrappers/core"
state_wrapper "github.com/vulcanize/eth-block-extractor/test_helpers/mocks/wrappers/core/state"
"github.com/vulcanize/eth-block-extractor/test_helpers/mocks/wrappers/trie"
)
var _ = Describe("", func() {
It("initializes state trie at parent block's root", func() {
chain, db, processor, trieFactory, validator := getMocks()
fakeDB := db.CreateFakeUnderlyingDatabase()
db.SetReturnDatabase(fakeDB)
computer := level.NewStateComputer(chain, db, processor, trieFactory, validator)
currentBlock, parentBlock := getFakeBlocks()
_, err := computer.ComputeBlockStateTrie(currentBlock, parentBlock)
Expect(err).NotTo(HaveOccurred())
trieFactory.AssertNewStateTrieCalledWith(parentBlock.Root(), fakeDB)
})
It("returns error if state trie initialization fails", func() {
chain, db, processor, trieFactory, validator := getMocks()
trieFactory.SetReturnErr(test_helpers.FakeError)
computer := level.NewStateComputer(chain, db, processor, trieFactory, validator)
currentBlock, parentBlock := getFakeBlocks()
_, err := computer.ComputeBlockStateTrie(currentBlock, parentBlock)
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(test_helpers.FakeError))
})
It("processes the block to build the state trie", func() {
chain, db, processor, trieFactory, validator := getMocks()
computer := level.NewStateComputer(chain, db, processor, trieFactory, validator)
stateTrie := state_wrapper.NewMockStateDB()
fakeStateDB := &state.StateDB{}
stateTrie.SetStateDB(fakeStateDB)
trieFactory.SetStateDB(stateTrie)
currentBlock, parentBlock := getFakeBlocks()
_, err := computer.ComputeBlockStateTrie(currentBlock, parentBlock)
Expect(err).NotTo(HaveOccurred())
processor.AssertProcessCalledWith(currentBlock, fakeStateDB)
})
It("returns error if processing block fails", func() {
chain, db, processor, trieFactory, validator := getMocks()
processor.SetReturnErr(test_helpers.FakeError)
computer := level.NewStateComputer(chain, db, processor, trieFactory, validator)
currentBlock, parentBlock := getFakeBlocks()
_, err := computer.ComputeBlockStateTrie(currentBlock, parentBlock)
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(test_helpers.FakeError))
})
It("validates state computed by processing blocks", func() {
chain, db, processor, trieFactory, validator := getMocks()
fakeReceipts := types.Receipts{}
processor.SetReturnReceipts(fakeReceipts)
fakeUsedGas := uint64(1234)
processor.SetReturnUsedGas(fakeUsedGas)
computer := level.NewStateComputer(chain, db, processor, trieFactory, validator)
stateTrie := state_wrapper.NewMockStateDB()
fakeStateDB := &state.StateDB{}
stateTrie.SetStateDB(fakeStateDB)
trieFactory.SetStateDB(stateTrie)
currentBlock, parentBlock := getFakeBlocks()
_, err := computer.ComputeBlockStateTrie(currentBlock, parentBlock)
Expect(err).NotTo(HaveOccurred())
validator.AssertValidateStateCalledWith(currentBlock, parentBlock, fakeStateDB, fakeReceipts, fakeUsedGas)
})
It("returns error if validating state fails", func() {
chain, db, processor, trieFactory, validator := getMocks()
validator.SetReturnErr(test_helpers.FakeError)
computer := level.NewStateComputer(chain, db, processor, trieFactory, validator)
currentBlock, parentBlock := getFakeBlocks()
_, err := computer.ComputeBlockStateTrie(currentBlock, parentBlock)
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(test_helpers.FakeError))
})
It("commits validated state to memory database", func() {
chain, db, processor, trieFactory, validator := getMocks()
computer := level.NewStateComputer(chain, db, processor, trieFactory, validator)
stateTrie := state_wrapper.NewMockStateDB()
trieFactory.SetStateDB(stateTrie)
currentBlock, parentBlock := getFakeBlocks()
_, err := computer.ComputeBlockStateTrie(currentBlock, parentBlock)
Expect(err).NotTo(HaveOccurred())
stateTrie.AssertCommitCalled()
})
It("returns error if committing state fails", func() {
chain, db, processor, trieFactory, validator := getMocks()
computer := level.NewStateComputer(chain, db, processor, trieFactory, validator)
stateTrie := state_wrapper.NewMockStateDB()
stateTrie.SetReturnErr(test_helpers.FakeError)
trieFactory.SetStateDB(stateTrie)
currentBlock, parentBlock := getFakeBlocks()
_, err := computer.ComputeBlockStateTrie(currentBlock, parentBlock)
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(test_helpers.FakeError))
})
It("returns computed state trie root", func() {
chain, db, processor, trieFactory, validator := getMocks()
computer := level.NewStateComputer(chain, db, processor, trieFactory, validator)
fakeIterator := trie.NewMockIterator(2)
fakeIterator.SetReturnHash(test_helpers.FakeHash)
fakeTrie := state_wrapper.NewMockTrie()
fakeTrie.SetReturnIterator(fakeIterator)
db.SetReturnTrie(fakeTrie)
currentBlock, parentBlock := getFakeBlocks()
stateRoot, err := computer.ComputeBlockStateTrie(currentBlock, parentBlock)
Expect(err).NotTo(HaveOccurred())
Expect(stateRoot).To(Equal(test_helpers.FakeHash))
})
})
func getMocks() (*core.MockBlockChain, *state_wrapper.MockStateDatabase, *core.MockProcessor, *state_wrapper.MockStateDBFactory, *core.MockValidator) {
chain := core.NewMockBlockChain()
db := state_wrapper.NewMockStateDatabase()
fakeDB := db.CreateFakeUnderlyingDatabase()
db.SetReturnDatabase(fakeDB)
fakeIterator := trie.NewMockIterator(1)
fakeTrie := state_wrapper.NewMockTrie()
fakeTrie.SetReturnIterator(fakeIterator)
db.SetReturnTrie(fakeTrie)
processor := core.NewMockProcessor()
trieFactory := state_wrapper.NewMockStateDBFactory()
stateTrie := state_wrapper.NewMockStateDB()
trieFactory.SetStateDB(stateTrie)
validator := core.NewMockValidator()
return chain, db, processor, trieFactory, validator
}
func getFakeBlocks() (*types.Block, *types.Block) {
currentBlockHeader := &types.Header{
Root: test_helpers.FakeHash,
Number: big.NewInt(456),
}
currentBlock := types.NewBlockWithHeader(currentBlockHeader)
parentBlockHeader := &types.Header{
Root: common.HexToHash("0x789"),
Number: big.NewInt(457),
}
parentBlock := types.NewBlockWithHeader(parentBlockHeader)
return currentBlock, parentBlock
}
@@ -1,59 +0,0 @@
package level
import (
"github.com/ethereum/go-ethereum/common"
"github.com/vulcanize/eth-block-extractor/pkg/wrappers/core/state"
)
type IStateTrieReader interface {
GetStateAndStorageTrieNodes(stateRoot common.Hash) (stateTrieNodes, storageTrieNodes [][]byte, err error)
}
type StateTrieReader struct {
db state.GethStateDatabase
storageTrieReader IStorageTrieReader
}
func NewStateTrieReader(db state.GethStateDatabase, storageTrieReader IStorageTrieReader) *StateTrieReader {
return &StateTrieReader{
db: db,
storageTrieReader: storageTrieReader,
}
}
func (str *StateTrieReader) GetStateAndStorageTrieNodes(stateRoot common.Hash) (stateTrieNodes, storageTrieNodes [][]byte, err error) {
trieDb := str.db.TrieDB()
// fetch and append state root node
stateRootNode, err := trieDb.Node(stateRoot)
if err != nil {
return stateTrieNodes, storageTrieNodes, err
}
stateTrieNodes = append(stateTrieNodes, stateRootNode)
// fetch and append remaining nodes in the state trie
stateTrie, err := str.db.OpenTrie(stateRoot)
if err != nil {
return stateTrieNodes, storageTrieNodes, err
}
stateTrieIterator := stateTrie.NodeIterator(nil)
for stateTrieIterator.Next(true) {
if stateTrieIterator.Leaf() {
node := stateTrieIterator.LeafBlob()
stateTrieNodes = append(stateTrieNodes, node)
// fetch and append storage trie nodes for state trie leaf (account snapshot)
accountStorageTrieNodes, err := str.storageTrieReader.GetStorageTrie(node)
if err != nil {
return stateTrieNodes, storageTrieNodes, err
}
storageTrieNodes = append(storageTrieNodes, accountStorageTrieNodes...)
} else {
nodeKey := stateTrieIterator.Hash()
node, err := str.db.TrieDB().Node(nodeKey)
if err != nil {
return stateTrieNodes, storageTrieNodes, err
}
stateTrieNodes = append(stateTrieNodes, node)
}
}
return stateTrieNodes, storageTrieNodes, nil
}
@@ -1,66 +0,0 @@
package level_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/eth-block-extractor/pkg/db/level"
"github.com/vulcanize/eth-block-extractor/test_helpers"
level_wrapper "github.com/vulcanize/eth-block-extractor/test_helpers/mocks/db/level"
"github.com/vulcanize/eth-block-extractor/test_helpers/mocks/wrappers/core/state"
"github.com/vulcanize/eth-block-extractor/test_helpers/mocks/wrappers/trie"
)
var _ = Describe("State trie reader", func() {
It("fetches node associated with state root", func() {
db := state.NewMockStateDatabase()
trieDB := db.CreateFakeUnderlyingDatabase()
db.SetReturnDatabase(trieDB)
mockIteratror := trie.NewMockIterator(0)
mockTrie := state.NewMockTrie()
mockTrie.SetReturnIterator(mockIteratror)
db.SetReturnTrie(mockTrie)
mockStorageTrieReader := level_wrapper.NewMockStorageTrieReader()
reader := level.NewStateTrieReader(db, mockStorageTrieReader)
stateTrieNodes, _, err := reader.GetStateAndStorageTrieNodes(test_helpers.FakeHash)
Expect(err).NotTo(HaveOccurred())
Expect(stateTrieNodes).To(ContainElement(test_helpers.FakeTrieNode))
})
It("returns nodes found traversing state trie", func() {
db := state.NewMockStateDatabase()
trieDB := db.CreateFakeUnderlyingDatabase()
db.SetReturnDatabase(trieDB)
mockIteratror := trie.NewMockIterator(2)
mockTrie := state.NewMockTrie()
mockTrie.SetReturnIterator(mockIteratror)
db.SetReturnTrie(mockTrie)
mockStorageTrieReader := level_wrapper.NewMockStorageTrieReader()
reader := level.NewStateTrieReader(db, mockStorageTrieReader)
stateTrieNodes, storageTrieNodes, err := reader.GetStateAndStorageTrieNodes(test_helpers.FakeHash)
Expect(err).NotTo(HaveOccurred())
Expect(len(stateTrieNodes)).To(Equal(3))
Expect(len(storageTrieNodes)).To(BeZero())
})
It("invokes storage trie reader for state trie leaf nodes", func() {
db := state.NewMockStateDatabase()
trieDB := db.CreateFakeUnderlyingDatabase()
db.SetReturnDatabase(trieDB)
mockIteratror := trie.NewMockIterator(1)
mockIteratror.SetIncludeLeaf()
mockTrie := state.NewMockTrie()
mockTrie.SetReturnIterator(mockIteratror)
db.SetReturnTrie(mockTrie)
mockStorageTrieReader := level_wrapper.NewMockStorageTrieReader()
reader := level.NewStateTrieReader(db, mockStorageTrieReader)
_, _, err := reader.GetStateAndStorageTrieNodes(test_helpers.FakeHash)
Expect(err).NotTo(HaveOccurred())
mockStorageTrieReader.AssertGetStorageTrieCalled()
})
})
@@ -1,63 +0,0 @@
package level
import (
"bytes"
"github.com/ethereum/go-ethereum/core/state"
state_wrapper "github.com/vulcanize/eth-block-extractor/pkg/wrappers/core/state"
"github.com/vulcanize/eth-block-extractor/pkg/wrappers/rlp"
)
var EmptyStorageTrieRoot = []byte{86, 232, 31, 23, 27, 204, 85, 166, 255, 131, 69, 230, 146, 192, 248, 110, 91, 72, 224, 27, 153, 108, 173, 192, 1, 98, 47, 181, 227, 99, 180, 33}
type IStorageTrieReader interface {
GetStorageTrie(stateTrieLeafNode []byte) (storageTrieResults [][]byte, err error)
}
type StorageTrieReader struct {
db state_wrapper.GethStateDatabase
decoder rlp.Decoder
}
func NewStorageTrieReader(db state_wrapper.GethStateDatabase, decoder rlp.Decoder) *StorageTrieReader {
return &StorageTrieReader{
db: db,
decoder: decoder,
}
}
func (stc *StorageTrieReader) GetStorageTrie(stateTrieLeafNode []byte) (storageTrieResults [][]byte, err error) {
trieDb := stc.db.TrieDB()
var account state.Account
err = stc.decoder.Decode(stateTrieLeafNode, &account)
if err != nil {
return storageTrieResults, err
}
// if storage trie root corresponds to empty storage trie, continue to next iteration in state trie
if bytes.Equal(EmptyStorageTrieRoot, account.Root.Bytes()) {
return storageTrieResults, err
}
// if storage trie root not empty, fetch and append root node
storageRootNode, err := trieDb.Node(account.Root)
if err != nil {
return storageTrieResults, err
}
storageTrieResults = append(storageTrieResults, storageRootNode)
storageTrie, err := stc.db.OpenTrie(account.Root)
if err != nil {
return storageTrieResults, err
}
storageTrieIterator := storageTrie.NodeIterator(account.Root.Bytes())
for storageTrieIterator.Next(true) {
if storageTrieIterator.Leaf() {
storageTrieResults = append(storageTrieResults, storageTrieIterator.LeafBlob())
} else {
nextStorageHash := storageTrieIterator.Hash()
nextStorageNode, err := trieDb.Node(nextStorageHash)
if err != nil {
return storageTrieResults, err
}
storageTrieResults = append(storageTrieResults, nextStorageNode)
}
}
return storageTrieResults, err
}
@@ -1,71 +0,0 @@
package level_test
import (
"github.com/ethereum/go-ethereum/core/state"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/eth-block-extractor/pkg/db/level"
"github.com/vulcanize/eth-block-extractor/test_helpers"
state_wrapper "github.com/vulcanize/eth-block-extractor/test_helpers/mocks/wrappers/core/state"
"github.com/vulcanize/eth-block-extractor/test_helpers/mocks/wrappers/rlp"
"github.com/vulcanize/eth-block-extractor/test_helpers/mocks/wrappers/trie"
)
var _ = Describe("Storage trie reader", func() {
It("decodes passed state trie leaf node into account", func() {
db := state_wrapper.NewMockStateDatabase()
trieDb := db.CreateFakeUnderlyingDatabase()
db.SetReturnDatabase(trieDb)
mockIteratror := trie.NewMockIterator(1)
mockIteratror.SetIncludeLeaf()
mockTrie := state_wrapper.NewMockTrie()
mockTrie.SetReturnIterator(mockIteratror)
db.SetReturnTrie(mockTrie)
decoder := rlp.NewMockDecoder()
decoder.SetReturnOut(&state.Account{})
reader := level.NewStorageTrieReader(db, decoder)
_, err := reader.GetStorageTrie(test_helpers.FakeTrieNode)
Expect(err).NotTo(HaveOccurred())
decoder.AssertDecodeCalledWith(test_helpers.FakeTrieNode, &state.Account{})
})
It("fetches node associated with storage root", func() {
db := state_wrapper.NewMockStateDatabase()
trieDb := db.CreateFakeUnderlyingDatabase()
db.SetReturnDatabase(trieDb)
mockIteratror := trie.NewMockIterator(0)
mockTrie := state_wrapper.NewMockTrie()
mockTrie.SetReturnIterator(mockIteratror)
db.SetReturnTrie(mockTrie)
decoder := rlp.NewMockDecoder()
decoder.SetReturnOut(&state.Account{})
reader := level.NewStorageTrieReader(db, decoder)
storageTrieNodes, err := reader.GetStorageTrie(test_helpers.FakeTrieNode)
Expect(err).NotTo(HaveOccurred())
Expect(len(storageTrieNodes)).To(Equal(1))
})
It("returns nodes found traversing storage trie", func() {
db := state_wrapper.NewMockStateDatabase()
trieDb := db.CreateFakeUnderlyingDatabase()
db.SetReturnDatabase(trieDb)
mockIteratror := trie.NewMockIterator(1)
mockIteratror.SetIncludeLeaf()
mockTrie := state_wrapper.NewMockTrie()
mockTrie.SetReturnIterator(mockIteratror)
db.SetReturnTrie(mockTrie)
decoder := rlp.NewMockDecoder()
decoder.SetReturnOut(&state.Account{})
reader := level.NewStorageTrieReader(db, decoder)
storageTrieNodes, err := reader.GetStorageTrie(test_helpers.FakeTrieNode)
Expect(err).NotTo(HaveOccurred())
Expect(len(storageTrieNodes)).To(Equal(2))
})
})
+1 -1
View File
@@ -1,6 +1,6 @@
package ipfs
import ipld "gx/ipfs/QmWi2BYBL5gJ3CiAiQchg6rn1A8iBsrWy51EYxvHVjFvLb/go-ipld-format"
import ipld "github.com/ipfs/go-ipld-format"
type Adder interface {
Add(node ipld.Node) error
@@ -2,7 +2,7 @@ package eth_block_header
import (
"github.com/ethereum/go-ethereum/core/types"
ipld "gx/ipfs/QmWi2BYBL5gJ3CiAiQchg6rn1A8iBsrWy51EYxvHVjFvLb/go-ipld-format"
ipld "github.com/ipfs/go-ipld-format"
"github.com/vulcanize/eth-block-extractor/pkg/ipfs"
"github.com/vulcanize/eth-block-extractor/pkg/ipfs/util"
@@ -1,64 +0,0 @@
package eth_block_header_test
import (
"github.com/ethereum/go-ethereum/core/types"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/eth-block-extractor/pkg/ipfs/eth_block_header"
"github.com/vulcanize/eth-block-extractor/test_helpers"
"github.com/vulcanize/eth-block-extractor/test_helpers/mocks/ipfs"
"github.com/vulcanize/eth-block-extractor/test_helpers/mocks/wrappers/rlp"
)
var _ = Describe("Creating an IPLD for a block header", func() {
It("decodes passed bytes into ethereum block header", func() {
mockDecoder := rlp.NewMockDecoder()
mockDecoder.SetReturnOut(&types.Header{})
dagPutter := eth_block_header.NewBlockHeaderDagPutter(ipfs.NewMockAdder(), mockDecoder)
fakeBytes := []byte{1, 2, 3, 4, 5}
_, err := dagPutter.DagPut(fakeBytes)
Expect(err).NotTo(HaveOccurred())
mockDecoder.AssertDecodeCalledWith(fakeBytes, &types.Header{})
})
It("returns error if decoding fails", func() {
mockDecoder := rlp.NewMockDecoder()
mockDecoder.SetReturnOut(&types.Header{})
mockDecoder.SetError(test_helpers.FakeError)
dagPutter := eth_block_header.NewBlockHeaderDagPutter(ipfs.NewMockAdder(), mockDecoder)
_, err := dagPutter.DagPut([]byte{1, 2, 3, 4, 5})
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(test_helpers.FakeError))
})
It("adds ethereum block header to ipfs", func() {
mockAdder := ipfs.NewMockAdder()
mockDecoder := rlp.NewMockDecoder()
mockDecoder.SetReturnOut(&types.Header{})
dagPutter := eth_block_header.NewBlockHeaderDagPutter(mockAdder, mockDecoder)
fakeBytes := []byte{1, 2, 3, 4, 5}
_, err := dagPutter.DagPut(fakeBytes)
Expect(err).NotTo(HaveOccurred())
mockAdder.AssertAddCalled(1, &eth_block_header.EthBlockHeaderNode{})
})
It("returns error if adding to ipfs fails", func() {
mockAdder := ipfs.NewMockAdder()
mockAdder.SetError(test_helpers.FakeError)
mockDecoder := rlp.NewMockDecoder()
mockDecoder.SetReturnOut(&types.Header{})
dagPutter := eth_block_header.NewBlockHeaderDagPutter(mockAdder, mockDecoder)
_, err := dagPutter.DagPut([]byte{1, 2, 3, 4, 5})
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(test_helpers.FakeError))
})
})
@@ -1,13 +0,0 @@
package eth_block_header_test
import (
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
func TestEthBlockHeader(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "EthBlockHeader Suite")
}
@@ -3,14 +3,14 @@ package eth_block_header
import (
"github.com/ethereum/go-ethereum/core/types"
"gx/ipfs/QmWi2BYBL5gJ3CiAiQchg6rn1A8iBsrWy51EYxvHVjFvLb/go-ipld-format"
"gx/ipfs/QmapdYm1b22Frv3k17fqrBYTFRxwiaVJkB299Mfn33edeB/go-cid"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-ipld-format"
)
type EthBlockHeaderNode struct {
*types.Header
cid *cid.Cid
cid cid.Cid
rawdata []byte
}
@@ -18,7 +18,7 @@ func (ebh *EthBlockHeaderNode) RawData() []byte {
return ebh.rawdata
}
func (ebh *EthBlockHeaderNode) Cid() *cid.Cid {
func (ebh *EthBlockHeaderNode) Cid() cid.Cid {
return ebh.cid
}
@@ -4,7 +4,7 @@ import (
"bytes"
"github.com/ethereum/go-ethereum/core/types"
"gx/ipfs/QmapdYm1b22Frv3k17fqrBYTFRxwiaVJkB299Mfn33edeB/go-cid"
"github.com/ipfs/go-cid"
"github.com/vulcanize/eth-block-extractor/pkg/ipfs"
"github.com/vulcanize/eth-block-extractor/pkg/ipfs/util"
@@ -1,42 +0,0 @@
package eth_block_receipts_test
import (
"github.com/ethereum/go-ethereum/core/types"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/eth-block-extractor/pkg/ipfs/eth_block_receipts"
"github.com/vulcanize/eth-block-extractor/test_helpers"
"github.com/vulcanize/eth-block-extractor/test_helpers/mocks/ipfs"
)
var _ = Describe("Eth block receipts dag putter", func() {
It("adds a node for each receipt", func() {
mockAdder := ipfs.NewMockAdder()
dagPutter := eth_block_receipts.NewEthBlockReceiptDagPutter(mockAdder)
fakeReceipts := types.Receipts{
&types.Receipt{},
&types.Receipt{},
}
_, err := dagPutter.DagPut(fakeReceipts)
Expect(err).NotTo(HaveOccurred())
mockAdder.AssertAddCalled(2, &eth_block_receipts.EthReceiptNode{})
})
It("returns error if adding node fails", func() {
mockAdder := ipfs.NewMockAdder()
mockAdder.SetError(test_helpers.FakeError)
dagPutter := eth_block_receipts.NewEthBlockReceiptDagPutter(mockAdder)
fakeReceipts := types.Receipts{
&types.Receipt{},
&types.Receipt{},
}
_, err := dagPutter.DagPut(fakeReceipts)
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(test_helpers.FakeError))
})
})
@@ -1,13 +0,0 @@
package eth_block_receipts_test
import (
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
func TestEthBlockReceipts(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "EthBlockReceipts Suite")
}
@@ -1,20 +1,20 @@
package eth_block_receipts
import (
"gx/ipfs/QmWi2BYBL5gJ3CiAiQchg6rn1A8iBsrWy51EYxvHVjFvLb/go-ipld-format"
"gx/ipfs/QmapdYm1b22Frv3k17fqrBYTFRxwiaVJkB299Mfn33edeB/go-cid"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-ipld-format"
)
type EthReceiptNode struct {
raw []byte
cid *cid.Cid
cid cid.Cid
}
func (node *EthReceiptNode) RawData() []byte {
return node.raw
}
func (node *EthReceiptNode) Cid() *cid.Cid {
func (node *EthReceiptNode) Cid() cid.Cid {
return node.cid
}
@@ -1,40 +0,0 @@
package eth_block_transactions_test
import (
"github.com/ethereum/go-ethereum/core/types"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/eth-block-extractor/pkg/ipfs/eth_block_transactions"
"github.com/vulcanize/eth-block-extractor/test_helpers"
"github.com/vulcanize/eth-block-extractor/test_helpers/mocks/ipfs"
)
var _ = Describe("Eth block transactions dag putter", func() {
It("adds a node for each transaction on the block", func() {
mockAdder := ipfs.NewMockAdder()
fakeTransactionOne := &types.Transaction{}
fakeTransactionTwo := &types.Transaction{}
fakeBlockBody := &types.Body{
Transactions: types.Transactions{fakeTransactionOne, fakeTransactionTwo},
Uncles: nil,
}
dagPutter := eth_block_transactions.NewBlockTransactionsDagPutter(mockAdder)
_, err := dagPutter.DagPut(fakeBlockBody)
Expect(err).NotTo(HaveOccurred())
mockAdder.AssertAddCalled(2, &eth_block_transactions.EthTransactionNode{})
})
It("returns error if adding node fails", func() {
mockAdder := ipfs.NewMockAdder()
mockAdder.SetError(test_helpers.FakeError)
dagPutter := eth_block_transactions.NewBlockTransactionsDagPutter(mockAdder)
_, err := dagPutter.DagPut(&types.Body{Transactions: types.Transactions{{}}})
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(test_helpers.FakeError))
})
})
@@ -1,13 +0,0 @@
package eth_block_transactions_test
import (
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
func TestEthBlockTransactions(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "EthBlockTransactions Suite")
}
@@ -2,14 +2,14 @@ package eth_block_transactions
import (
"github.com/ethereum/go-ethereum/core/types"
"gx/ipfs/QmWi2BYBL5gJ3CiAiQchg6rn1A8iBsrWy51EYxvHVjFvLb/go-ipld-format"
"gx/ipfs/QmapdYm1b22Frv3k17fqrBYTFRxwiaVJkB299Mfn33edeB/go-cid"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-ipld-format"
)
type EthTransactionNode struct {
*types.Transaction
cid *cid.Cid
cid cid.Cid
rawdata []byte
}
@@ -17,7 +17,7 @@ func (etn *EthTransactionNode) RawData() []byte {
return etn.rawdata
}
func (etn *EthTransactionNode) Cid() *cid.Cid {
func (etn *EthTransactionNode) Cid() cid.Cid {
return etn.cid
}
@@ -1,33 +0,0 @@
package eth_state_trie_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/eth-block-extractor/pkg/ipfs/eth_state_trie"
"github.com/vulcanize/eth-block-extractor/test_helpers"
"github.com/vulcanize/eth-block-extractor/test_helpers/mocks/ipfs"
)
var _ = Describe("Ethereum state trie node dag putter", func() {
It("adds passed state trie node to ipfs", func() {
mockAdder := ipfs.NewMockAdder()
dagPutter := eth_state_trie.NewStateTrieDagPutter(mockAdder)
_, err := dagPutter.DagPut([]byte{1, 2, 3, 4, 5})
Expect(err).NotTo(HaveOccurred())
mockAdder.AssertAddCalled(1, &eth_state_trie.EthStateTrieNode{})
})
It("returns error if adding to ipfs fails", func() {
mockAdder := ipfs.NewMockAdder()
mockAdder.SetError(test_helpers.FakeError)
dagPutter := eth_state_trie.NewStateTrieDagPutter(mockAdder)
_, err := dagPutter.DagPut([]byte{1, 2, 3, 4, 5})
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(test_helpers.FakeError))
})
})
@@ -1,13 +0,0 @@
package eth_state_trie_test
import (
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
func TestEthStateTrie(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "EthStateTrie Suite")
}
@@ -1,12 +1,12 @@
package eth_state_trie
import (
"gx/ipfs/QmWi2BYBL5gJ3CiAiQchg6rn1A8iBsrWy51EYxvHVjFvLb/go-ipld-format"
"gx/ipfs/QmapdYm1b22Frv3k17fqrBYTFRxwiaVJkB299Mfn33edeB/go-cid"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-ipld-format"
)
type EthStateTrieNode struct {
cid *cid.Cid
cid cid.Cid
rawdata []byte
}
@@ -14,7 +14,7 @@ func (estn EthStateTrieNode) RawData() []byte {
return estn.rawdata
}
func (estn EthStateTrieNode) Cid() *cid.Cid {
func (estn EthStateTrieNode) Cid() cid.Cid {
return estn.cid
}
@@ -1,32 +0,0 @@
package eth_storage_trie_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/eth-block-extractor/pkg/ipfs/eth_storage_trie"
"github.com/vulcanize/eth-block-extractor/test_helpers"
"github.com/vulcanize/eth-block-extractor/test_helpers/mocks/ipfs"
)
var _ = Describe("Ethereum storage trie node dag putter", func() {
It("adds passed storage trie node to ipfs", func() {
mockAdder := ipfs.NewMockAdder()
dagPutter := eth_storage_trie.NewStorageTrieDagPutter(mockAdder)
_, err := dagPutter.DagPut([]byte{1, 2, 3, 4, 5})
Expect(err).NotTo(HaveOccurred())
mockAdder.AssertAddCalled(1, &eth_storage_trie.EthStorageTrieNode{})
})
It("returns error if adding to ipfs fails", func() {
mockAdder := ipfs.NewMockAdder()
mockAdder.SetError(test_helpers.FakeError)
dagPutter := eth_storage_trie.NewStorageTrieDagPutter(mockAdder)
_, err := dagPutter.DagPut([]byte{1, 2, 3, 4, 5})
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(test_helpers.FakeError))
})
})
@@ -1,13 +0,0 @@
package eth_storage_trie_test
import (
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
func TestEthStorageTrie(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "EthStorageTrie Suite")
}
@@ -1,12 +1,12 @@
package eth_storage_trie
import (
"gx/ipfs/QmWi2BYBL5gJ3CiAiQchg6rn1A8iBsrWy51EYxvHVjFvLb/go-ipld-format"
"gx/ipfs/QmapdYm1b22Frv3k17fqrBYTFRxwiaVJkB299Mfn33edeB/go-cid"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-ipld-format"
)
type EthStorageTrieNode struct {
cid *cid.Cid
cid cid.Cid
rawdata []byte
}
@@ -14,7 +14,7 @@ func (estn *EthStorageTrieNode) RawData() []byte {
return estn.rawdata
}
func (estn *EthStorageTrieNode) Cid() *cid.Cid {
func (estn *EthStorageTrieNode) Cid() cid.Cid {
return estn.cid
}
@@ -1,13 +0,0 @@
package ipfs_test
import (
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
func TestIpfs(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Ipfs Suite")
}
+1 -1
View File
@@ -6,7 +6,7 @@ import (
"github.com/ipfs/go-ipfs/core"
"github.com/ipfs/go-ipfs/repo/fsrepo"
ipld "gx/ipfs/QmWi2BYBL5gJ3CiAiQchg6rn1A8iBsrWy51EYxvHVjFvLb/go-ipld-format"
ipld "github.com/ipfs/go-ipld-format"
)
type IPFS struct {
@@ -1,34 +0,0 @@
package ipfs_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/eth-block-extractor/pkg/ipfs"
"github.com/vulcanize/eth-block-extractor/test_helpers"
ipfs_wrapper "github.com/vulcanize/eth-block-extractor/test_helpers/mocks/ipfs"
)
var _ = Describe("IPFS publisher", func() {
It("calls dag put with the passed data", func() {
mockDagPutter := ipfs_wrapper.NewMockDagPutter()
publisher := ipfs.NewIpfsPublisher(mockDagPutter)
fakeBytes := []byte{1, 2, 3, 4, 5}
_, err := publisher.DagPut(fakeBytes)
Expect(err).NotTo(HaveOccurred())
Expect(mockDagPutter.Called).To(BeTrue())
Expect(mockDagPutter.PassedInterface).To(Equal(fakeBytes))
})
It("returns error if dag put fails", func() {
mockDagPutter := ipfs_wrapper.NewMockDagPutter()
mockDagPutter.SetError(test_helpers.FakeError)
publisher := ipfs.NewIpfsPublisher(mockDagPutter)
_, err := publisher.DagPut([]byte{1, 2, 3, 4, 5})
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(test_helpers.FakeError))
})
})
+4 -4
View File
@@ -1,11 +1,11 @@
package util
import (
mh "gx/ipfs/QmZyZDi491cCNTLfAhwcaDii2Kg4pwKRkhqQzURGDvY6ua/go-multihash"
"gx/ipfs/QmapdYm1b22Frv3k17fqrBYTFRxwiaVJkB299Mfn33edeB/go-cid"
"github.com/ipfs/go-cid"
mh "github.com/multiformats/go-multihash"
)
func RawToCid(codec uint64, raw []byte) (*cid.Cid, error) {
func RawToCid(codec uint64, raw []byte) (cid.Cid, error) {
c, err := cid.Prefix{
Codec: codec,
Version: 1,
@@ -13,7 +13,7 @@ func RawToCid(codec uint64, raw []byte) (*cid.Cid, error) {
MhLength: -1,
}.Sum(raw)
if err != nil {
return nil, err
return cid.Cid{}, err
}
return c, nil
}
@@ -1,95 +0,0 @@
package transformers
import (
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/vulcanize/eth-block-extractor/pkg/db"
"github.com/vulcanize/eth-block-extractor/pkg/ipfs"
"log"
)
const (
GenesisBlockNumber = int64(0)
FirstBlockToCompute = int64(1)
)
type ComputeEthStateTrieTransformer struct {
database db.Database
stateTriePublisher ipfs.Publisher
storageTriePublisher ipfs.Publisher
}
func NewComputeEthStateTrieTransformer(database db.Database, stateTriePublisher, storageTriePublisher ipfs.Publisher) *ComputeEthStateTrieTransformer {
return &ComputeEthStateTrieTransformer{
database: database,
stateTriePublisher: stateTriePublisher,
storageTriePublisher: storageTriePublisher,
}
}
func (t ComputeEthStateTrieTransformer) Execute(endingBlockNumber int64) error {
root, err := t.getStateRootForBlock(GenesisBlockNumber)
if err != nil {
return err
}
// ignore storage trie node return val for genesis block
stateTrieNodes, _, err := t.database.GetStateAndStorageTrieNodes(root)
if err != nil {
return fmt.Errorf("Error fetching state trie for genesis block: %s\n", err)
}
err = t.writeStateTrieNodesToIpfs(stateTrieNodes)
if err != nil {
return err
}
for n := FirstBlockToCompute; n <= endingBlockNumber; n++ {
currentBlock := t.database.GetBlockByBlockNumber(n)
parentBlock := t.database.GetBlockByBlockNumber(n - 1)
stateRoot, err := t.database.ComputeBlockStateTrie(currentBlock, parentBlock)
if err != nil {
return err
}
nextStateTrieNodes, nextStorageTrieNodes, err := t.database.GetStateAndStorageTrieNodes(stateRoot)
if err != nil {
return err
}
err = t.writeStateTrieNodesToIpfs(nextStateTrieNodes)
if err != nil {
return err
}
err = t.writeStorageTrieNodesToIpfs(nextStorageTrieNodes)
if err != nil {
return err
}
}
return nil
}
func (t ComputeEthStateTrieTransformer) getStateRootForBlock(blockNumber int64) (root common.Hash, err error) {
header := t.database.GetBlockHeaderByBlockNumber(blockNumber)
if err != nil {
return root, err
}
return header.Root, err
}
func (t ComputeEthStateTrieTransformer) writeStateTrieNodesToIpfs(stateTrieNodes [][]byte) error {
for _, node := range stateTrieNodes {
output, err := t.stateTriePublisher.Write(node)
if err != nil {
return fmt.Errorf("Error writing state trie node to ipfs: %s\n", err)
}
log.Println("Created ipld: ", output)
}
return nil
}
func (t ComputeEthStateTrieTransformer) writeStorageTrieNodesToIpfs(storageTrieNodes [][]byte) error {
for _, node := range storageTrieNodes {
output, err := t.storageTriePublisher.Write(node)
if err != nil {
return fmt.Errorf("Error writing storage trie node to ipfs: %s\n", err.Error())
}
log.Println("Created ipld: ", output)
}
return nil
}
@@ -1,177 +0,0 @@
package transformers_test
import (
"io/ioutil"
"log"
"github.com/ethereum/go-ethereum/core/types"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/eth-block-extractor/pkg/transformers"
"github.com/vulcanize/eth-block-extractor/test_helpers"
"github.com/vulcanize/eth-block-extractor/test_helpers/mocks/db"
"github.com/vulcanize/eth-block-extractor/test_helpers/mocks/ipfs"
)
var _ = Describe("Compute eth state trie transformer", func() {
BeforeEach(func() {
log.SetOutput(ioutil.Discard)
})
Describe("publishing the state trie for the genesis block", func() {
It("fetches state trie root for genesis block", func() {
mockDB := db.NewMockDatabase()
mockDB.SetGetBlockHeaderByBlockNumberReturnHeader(&types.Header{})
transformer := transformers.NewComputeEthStateTrieTransformer(mockDB, ipfs.NewMockPublisher(), ipfs.NewMockPublisher())
err := transformer.Execute(0)
Expect(err).NotTo(HaveOccurred())
mockDB.AssertGetBlockHeaderByBlockNumberCalledWith([]int64{0})
})
It("fetches state and storage trie nodes for genesis block with block state root", func() {
mockDB := db.NewMockDatabase()
mockDB.SetGetBlockHeaderByBlockNumberReturnHeader(&types.Header{Root: test_helpers.FakeHash})
storageTriePublisher := ipfs.NewMockPublisher()
transformer := transformers.NewComputeEthStateTrieTransformer(mockDB, ipfs.NewMockPublisher(), storageTriePublisher)
err := transformer.Execute(0)
Expect(err).NotTo(HaveOccurred())
mockDB.AssertGetStateTrieNodesCalledWith(test_helpers.FakeHash)
})
It("returns error if fetching state trie nodes fails", func() {
mockDB := db.NewMockDatabase()
mockDB.SetGetBlockHeaderByBlockNumberReturnHeader(&types.Header{})
mockDB.SetGetStateAndStorageTrieNodesError(test_helpers.FakeError)
transformer := transformers.NewComputeEthStateTrieTransformer(mockDB, ipfs.NewMockPublisher(), ipfs.NewMockPublisher())
err := transformer.Execute(0)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring(test_helpers.FakeError.Error()))
})
It("publishes state trie nodes for genesis block to IPFS", func() {
mockDB := db.NewMockDatabase()
mockDB.SetGetBlockHeaderByBlockNumberReturnHeader(&types.Header{})
fakeStateTrieNodes := [][]byte{{6, 7, 8, 9, 0}}
mockDB.SetGetStateAndStorageTrieNodesReturnStateTrieBytes(fakeStateTrieNodes)
stateTriePublisher := ipfs.NewMockPublisher()
transformer := transformers.NewComputeEthStateTrieTransformer(mockDB, stateTriePublisher, ipfs.NewMockPublisher())
err := transformer.Execute(0)
Expect(err).NotTo(HaveOccurred())
stateTriePublisher.AssertWriteCalledWithBytes(fakeStateTrieNodes)
})
It("returns error if publishing state trie nodes fails", func() {
mockDB := db.NewMockDatabase()
mockDB.SetGetBlockHeaderByBlockNumberReturnHeader(&types.Header{})
fakeStateTrieNodes := [][]byte{{6, 7, 8, 9, 0}}
mockDB.SetGetStateAndStorageTrieNodesReturnStateTrieBytes(fakeStateTrieNodes)
stateTriePublisher := ipfs.NewMockPublisher()
stateTriePublisher.SetError(test_helpers.FakeError)
transformer := transformers.NewComputeEthStateTrieTransformer(mockDB, stateTriePublisher, ipfs.NewMockPublisher())
err := transformer.Execute(0)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring(test_helpers.FakeError.Error()))
})
})
Describe("computing and publishing the state trie for subsequent blocks", func() {
It("fetches the current and parent block", func() {
mockDB := db.NewMockDatabase()
mockDB.SetGetBlockHeaderByBlockNumberReturnHeader(&types.Header{})
mockDB.SetGetStateAndStorageTrieNodesReturnStateTrieBytes([][]byte{{6, 7, 8, 9, 0}})
transformer := transformers.NewComputeEthStateTrieTransformer(mockDB, ipfs.NewMockPublisher(), ipfs.NewMockPublisher())
err := transformer.Execute(4)
Expect(err).NotTo(HaveOccurred())
mockDB.AssertGetBlockByBlockNumberCalledwith([]int64{0, 1, 2, 3, 4})
})
It("computes state and storage trie nodes for current block", func() {
mockDB := db.NewMockDatabase()
mockDB.SetGetBlockHeaderByBlockNumberReturnHeader(&types.Header{})
mockDB.SetGetStateAndStorageTrieNodesReturnStateTrieBytes([][]byte{{6, 7, 8, 9, 0}})
fakeBlock := &types.Block{}
mockDB.SetGetBlockByBlockNumberReturnBlock(fakeBlock)
transformer := transformers.NewComputeEthStateTrieTransformer(mockDB, ipfs.NewMockPublisher(), ipfs.NewMockPublisher())
err := transformer.Execute(1)
Expect(err).NotTo(HaveOccurred())
mockDB.AssertComputeBlockStateTrieCalledWith(fakeBlock, fakeBlock)
})
It("publishes state trie nodes to IPFS", func() {
mockDB := db.NewMockDatabase()
mockDB.SetGetBlockHeaderByBlockNumberReturnHeader(&types.Header{})
fakeStateTrieNodes := [][]byte{{0, 0, 0, 0, 0}, {1, 1, 1, 1, 1}}
mockDB.SetGetStateAndStorageTrieNodesReturnStateTrieBytes(fakeStateTrieNodes)
mockDB.SetComputeBlockStateTrieReturnHash(test_helpers.FakeHash)
stateTriePublisher := ipfs.NewMockPublisher()
transformer := transformers.NewComputeEthStateTrieTransformer(mockDB, stateTriePublisher, ipfs.NewMockPublisher())
err := transformer.Execute(1)
Expect(err).NotTo(HaveOccurred())
stateTriePublisher.AssertWriteCalledWithBytes(fakeStateTrieNodes)
})
It("returns error if publishing state trie nodes fails", func() {
mockDB := db.NewMockDatabase()
mockDB.SetGetBlockHeaderByBlockNumberReturnHeader(&types.Header{})
mockDB.SetGetStateAndStorageTrieNodesReturnStateTrieBytes([][]byte{{6, 7, 8, 9, 0}})
mockDB.SetComputeBlockStateTrieReturnHash(test_helpers.FakeHash)
stateTriePublisher := ipfs.NewMockPublisher()
stateTriePublisher.SetError(test_helpers.FakeError)
transformer := transformers.NewComputeEthStateTrieTransformer(mockDB, stateTriePublisher, ipfs.NewMockPublisher())
err := transformer.Execute(1)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring(test_helpers.FakeError.Error()))
})
It("publishes storage trie nodes to IPFS", func() {
mockDB := db.NewMockDatabase()
mockDB.SetGetBlockHeaderByBlockNumberReturnHeader(&types.Header{})
mockDB.SetGetStateAndStorageTrieNodesReturnStateTrieBytes(test_helpers.FakeTrieNodes)
fakeStorageTrieNodes := [][]byte{{2, 2, 2, 2, 2}}
mockDB.SetGetStateAndStorageTrieNodesReturnStorageTrieBytes(fakeStorageTrieNodes)
mockDB.SetComputeBlockStateTrieReturnHash(test_helpers.FakeHash)
storageTriePublisher := ipfs.NewMockPublisher()
transformer := transformers.NewComputeEthStateTrieTransformer(mockDB, ipfs.NewMockPublisher(), storageTriePublisher)
err := transformer.Execute(1)
Expect(err).NotTo(HaveOccurred())
storageTriePublisher.AssertWriteCalledWithBytes(fakeStorageTrieNodes)
})
It("returns error if publishing storage trie nodes fails", func() {
mockDB := db.NewMockDatabase()
mockDB.SetGetBlockHeaderByBlockNumberReturnHeader(&types.Header{})
mockDB.SetGetStateAndStorageTrieNodesReturnStateTrieBytes(test_helpers.FakeTrieNodes)
mockDB.SetGetStateAndStorageTrieNodesReturnStorageTrieBytes(test_helpers.FakeTrieNodes)
mockDB.SetComputeBlockStateTrieReturnHash(test_helpers.FakeHash)
storageTriePublisher := ipfs.NewMockPublisher()
storageTriePublisher.SetError(test_helpers.FakeError)
transformer := transformers.NewComputeEthStateTrieTransformer(mockDB, ipfs.NewMockPublisher(), storageTriePublisher)
err := transformer.Execute(1)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring(test_helpers.FakeError.Error()))
})
})
})
@@ -1,26 +0,0 @@
package transformers
import (
"errors"
"fmt"
)
const (
GetBlockRlpErr = "Error fetching block RLP data"
PutIpldErr = "Error writing to IPFS"
)
var ErrInvalidRange = errors.New("ending block number must be greater than or equal to starting block number")
type ExecuteError struct {
msg string
err error
}
func NewExecuteError(msg string, err error) *ExecuteError {
return &ExecuteError{msg: msg, err: err}
}
func (ee ExecuteError) Error() string {
return fmt.Sprintf("%s: %s", ee.msg, ee.err.Error())
}
@@ -1,32 +0,0 @@
package transformers
import (
"log"
"github.com/vulcanize/eth-block-extractor/pkg/db"
"github.com/vulcanize/eth-block-extractor/pkg/ipfs"
)
type EthBlockHeaderTransformer struct {
database db.Database
publisher ipfs.Publisher
}
func NewEthBlockHeaderTransformer(ethDB db.Database, publisher ipfs.Publisher) *EthBlockHeaderTransformer {
return &EthBlockHeaderTransformer{database: ethDB, publisher: publisher}
}
func (t EthBlockHeaderTransformer) Execute(startingBlockNumber int64, endingBlockNumber int64) error {
if endingBlockNumber < startingBlockNumber {
return ErrInvalidRange
}
for i := startingBlockNumber; i <= endingBlockNumber; i++ {
blockData := t.database.GetRawBlockHeaderByBlockNumber(i)
output, err := t.publisher.Write(blockData)
if err != nil {
return NewExecuteError(PutIpldErr, err)
}
log.Printf("Created IPLD: %s", output)
}
return nil
}
@@ -1,110 +0,0 @@
package transformers_test
import (
"io/ioutil"
"log"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/eth-block-extractor/pkg/transformers"
"github.com/vulcanize/eth-block-extractor/test_helpers"
"github.com/vulcanize/eth-block-extractor/test_helpers/mocks/db"
"github.com/vulcanize/eth-block-extractor/test_helpers/mocks/ipfs"
)
var _ = Describe("Eth block header transformer", func() {
var mockDB *db.MockDatabase
var mockPublisher *ipfs.MockPublisher
Describe("Fetching one block header", func() {
var fakeBytes []byte
var blockNumber int64
BeforeEach(func() {
mockDB = db.NewMockDatabase()
mockPublisher = ipfs.NewMockPublisher()
blockNumber = 54321
fakeBytes = []byte{6, 7, 8, 9, 0}
mockDB.SetGetRawBlockHeaderByBlockNumberReturnBytes([][]byte{fakeBytes})
mockPublisher.SetReturnStrings([][]string{{"cid_one", "cid_two"}})
log.SetOutput(ioutil.Discard)
})
It("returns error if ending block number is less than starting block number", func() {
transformer := transformers.NewEthBlockHeaderTransformer(mockDB, mockPublisher)
err := transformer.Execute(1, 0)
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(transformers.ErrInvalidRange))
})
It("Fetches RLP data from ethereum db", func() {
transformer := transformers.NewEthBlockHeaderTransformer(mockDB, mockPublisher)
err := transformer.Execute(blockNumber, blockNumber)
Expect(err).NotTo(HaveOccurred())
mockDB.AssertGetRawBlockHeaderByBlockNumberCalledWith([]int64{blockNumber})
})
It("Persists block RLP data to IPFS", func() {
transformer := transformers.NewEthBlockHeaderTransformer(mockDB, mockPublisher)
err := transformer.Execute(blockNumber, blockNumber)
Expect(err).NotTo(HaveOccurred())
mockPublisher.AssertWriteCalledWithBytes([][]byte{fakeBytes})
})
It("Returns err if persisting block RLP data to IPFS fails", func() {
mockPublisher.SetError(test_helpers.FakeError)
transformer := transformers.NewEthBlockHeaderTransformer(mockDB, mockPublisher)
err := transformer.Execute(blockNumber, blockNumber)
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(transformers.NewExecuteError(transformers.PutIpldErr, test_helpers.FakeError)))
mockDB.AssertGetRawBlockHeaderByBlockNumberCalledWith([]int64{blockNumber})
mockPublisher.AssertWriteCalledWithBytes([][]byte{fakeBytes})
})
})
Describe("Fetching multiple blocks", func() {
var fakeRlpBytes []byte
var startingBlockNumber int64
var endingBlockNumber int64
BeforeEach(func() {
mockDB = db.NewMockDatabase()
mockPublisher = ipfs.NewMockPublisher()
startingBlockNumber = 54321
endingBlockNumber = 54322
fakeRlpBytes = []byte{6, 7, 8, 9, 0}
mockDB.SetGetRawBlockHeaderByBlockNumberReturnBytes([][]byte{fakeRlpBytes, fakeRlpBytes})
fakeOutputString := []string{"cid_one", "cid_two"}
mockPublisher.SetReturnStrings([][]string{fakeOutputString, fakeOutputString})
log.SetOutput(ioutil.Discard)
})
It("Fetches block RLP data from ethereum db for every block in range", func() {
transformer := transformers.NewEthBlockHeaderTransformer(mockDB, mockPublisher)
err := transformer.Execute(startingBlockNumber, endingBlockNumber)
Expect(err).NotTo(HaveOccurred())
mockDB.AssertGetRawBlockHeaderByBlockNumberCalledWith([]int64{startingBlockNumber, endingBlockNumber})
})
It("Persists block RLP data to IPFS for every block in range", func() {
transformer := transformers.NewEthBlockHeaderTransformer(mockDB, mockPublisher)
err := transformer.Execute(startingBlockNumber, endingBlockNumber)
Expect(err).NotTo(HaveOccurred())
mockPublisher.AssertWriteCalledWithBytes([][]byte{fakeRlpBytes, fakeRlpBytes})
})
})
})
@@ -1,34 +0,0 @@
package transformers
import (
"github.com/vulcanize/eth-block-extractor/pkg/db"
"github.com/vulcanize/eth-block-extractor/pkg/ipfs"
"log"
)
type EthBlockReceiptTransformer struct {
database db.Database
publisher ipfs.Publisher
}
func NewEthBlockReceiptTransformer(database db.Database, publisher ipfs.Publisher) *EthBlockReceiptTransformer {
return &EthBlockReceiptTransformer{
database: database,
publisher: publisher,
}
}
func (transformer EthBlockReceiptTransformer) Execute(startingBlockNumber int64, endingBlockNumber int64) error {
if endingBlockNumber < startingBlockNumber {
return ErrInvalidRange
}
for i := startingBlockNumber; i <= endingBlockNumber; i++ {
receipts := transformer.database.GetBlockReceipts(i)
cids, err := transformer.publisher.Write(receipts)
if err != nil {
return err
}
log.Println("Generated IPLDs: ", cids)
}
return nil
}
@@ -1,71 +0,0 @@
package transformers_test
import (
"github.com/ethereum/go-ethereum/core/types"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/eth-block-extractor/pkg/transformers"
"github.com/vulcanize/eth-block-extractor/test_helpers"
"github.com/vulcanize/eth-block-extractor/test_helpers/mocks/db"
"github.com/vulcanize/eth-block-extractor/test_helpers/mocks/ipfs"
"io/ioutil"
"log"
)
var _ = Describe("Eth block receipts transformer", func() {
BeforeEach(func() {
log.SetOutput(ioutil.Discard)
})
It("returns error if ending block number is less than starting block number", func() {
transformer := transformers.NewEthBlockReceiptTransformer(db.NewMockDatabase(), ipfs.NewMockPublisher())
err := transformer.Execute(1, 0)
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(transformers.ErrInvalidRange))
})
It("fetches blocks' receipts from database", func() {
mockDatabase := db.NewMockDatabase()
transformer := transformers.NewEthBlockReceiptTransformer(mockDatabase, ipfs.NewMockPublisher())
err := transformer.Execute(0, 1)
Expect(err).NotTo(HaveOccurred())
mockDatabase.AssertGetBlockReceiptsCalledWith([]int64{0, 1})
})
It("publishes block receipts", func() {
mockDatabase := db.NewMockDatabase()
fakeReceipts := types.Receipts{
&types.Receipt{},
&types.Receipt{},
}
mockDatabase.SetGetBlockReceiptsReturnReceipts(fakeReceipts)
mockPublisher := ipfs.NewMockPublisher()
transformer := transformers.NewEthBlockReceiptTransformer(mockDatabase, mockPublisher)
err := transformer.Execute(0, 0)
Expect(err).NotTo(HaveOccurred())
mockPublisher.AssertWriteCalledWithInterfaces([]interface{}{fakeReceipts})
})
It("returns error if publishing block receipts fails", func() {
mockDatabase := db.NewMockDatabase()
fakeReceipts := types.Receipts{
&types.Receipt{},
&types.Receipt{},
}
mockDatabase.SetGetBlockReceiptsReturnReceipts(fakeReceipts)
mockPublisher := ipfs.NewMockPublisher()
mockPublisher.SetError(test_helpers.FakeError)
transformer := transformers.NewEthBlockReceiptTransformer(mockDatabase, mockPublisher)
err := transformer.Execute(0, 0)
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(test_helpers.FakeError))
})
})
@@ -1,31 +0,0 @@
package transformers
import (
"github.com/vulcanize/eth-block-extractor/pkg/db"
"github.com/vulcanize/eth-block-extractor/pkg/ipfs"
"log"
)
type EthBlockTransactionsTransformer struct {
database db.Database
publisher ipfs.Publisher
}
func NewEthBlockTransactionsTransformer(db db.Database, publisher ipfs.Publisher) *EthBlockTransactionsTransformer {
return &EthBlockTransactionsTransformer{database: db, publisher: publisher}
}
func (t EthBlockTransactionsTransformer) Execute(startingBlockNumber int64, endingBlockNumber int64) error {
if endingBlockNumber < startingBlockNumber {
return ErrInvalidRange
}
for i := startingBlockNumber; i <= endingBlockNumber; i++ {
body := t.database.GetBlockBodyByBlockNumber(i)
res, err := t.publisher.Write(body)
if err != nil {
return NewExecuteError(PutIpldErr, err)
}
log.Println("Created CIDs: ", res)
}
return nil
}
@@ -1,109 +0,0 @@
package transformers_test
import (
"io/ioutil"
"log"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/ethereum/go-ethereum/core/types"
"github.com/vulcanize/eth-block-extractor/pkg/transformers"
"github.com/vulcanize/eth-block-extractor/test_helpers"
"github.com/vulcanize/eth-block-extractor/test_helpers/mocks/db"
"github.com/vulcanize/eth-block-extractor/test_helpers/mocks/ipfs"
)
var _ = Describe("Eth block transactions transformer", func() {
Describe("executing on a single block", func() {
BeforeEach(func() {
log.SetOutput(ioutil.Discard)
})
It("returns error if ending block number is less than starting block number", func() {
transformer := transformers.NewEthBlockTransactionsTransformer(db.NewMockDatabase(), ipfs.NewMockPublisher())
err := transformer.Execute(1, 0)
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(transformers.ErrInvalidRange))
})
It("fetches rlp data for block body", func() {
mockDB := db.NewMockDatabase()
mockDB.SetGetBlockBodyByBlockNumberReturnBody([]*types.Body{{}})
mockPublisher := ipfs.NewMockPublisher()
mockPublisher.SetReturnStrings([][]string{{"cid"}})
transformer := transformers.NewEthBlockTransactionsTransformer(mockDB, mockPublisher)
blockNumber := int64(1234567)
err := transformer.Execute(blockNumber, blockNumber)
Expect(err).NotTo(HaveOccurred())
mockDB.AssertGetBlockBodyByBlockNumberCalledWith([]int64{blockNumber})
})
It("publishes block body data to IPFS", func() {
mockDB := db.NewMockDatabase()
fakeRawData := []*types.Body{{}}
mockDB.SetGetBlockBodyByBlockNumberReturnBody(fakeRawData)
mockPublisher := ipfs.NewMockPublisher()
mockPublisher.SetReturnStrings([][]string{{"cid"}})
transformer := transformers.NewEthBlockTransactionsTransformer(mockDB, mockPublisher)
blockNumber := int64(1234567)
err := transformer.Execute(blockNumber, blockNumber)
Expect(err).NotTo(HaveOccurred())
mockPublisher.AssertWriteCalledWithBodies(fakeRawData)
})
It("returns error if publishing data returns error", func() {
mockDB := db.NewMockDatabase()
fakeRawData := []*types.Body{{}}
mockDB.SetGetBlockBodyByBlockNumberReturnBody(fakeRawData)
mockPublisher := ipfs.NewMockPublisher()
mockPublisher.SetError(test_helpers.FakeError)
transformer := transformers.NewEthBlockTransactionsTransformer(mockDB, mockPublisher)
blockNumber := int64(1234567)
err := transformer.Execute(blockNumber, blockNumber)
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(transformers.NewExecuteError(transformers.PutIpldErr, test_helpers.FakeError)))
})
})
Describe("executing on a range of blocks", func() {
It("fetches rlp data for every block's body", func() {
mockDatabase := db.NewMockDatabase()
mockDatabase.SetGetBlockBodyByBlockNumberReturnBody([]*types.Body{{}, {}})
mockPublisher := ipfs.NewMockPublisher()
mockPublisher.SetReturnStrings([][]string{{"cid_one"}, {"cid_two"}})
transformer := transformers.NewEthBlockTransactionsTransformer(mockDatabase, mockPublisher)
startingBlockNumber := int64(1234567)
endingBlockNumber := int64(1234568)
err := transformer.Execute(startingBlockNumber, endingBlockNumber)
Expect(err).NotTo(HaveOccurred())
mockDatabase.AssertGetBlockBodyByBlockNumberCalledWith([]int64{startingBlockNumber, endingBlockNumber})
})
It("publishes every block body's data to IPFS", func() {
mockDatabase := db.NewMockDatabase()
fakeRawData := []*types.Body{{}, {}}
mockDatabase.SetGetBlockBodyByBlockNumberReturnBody(fakeRawData)
mockPublisher := ipfs.NewMockPublisher()
mockPublisher.SetReturnStrings([][]string{{"cid_one"}, {"cid_two"}})
transformer := transformers.NewEthBlockTransactionsTransformer(mockDatabase, mockPublisher)
startingBlockNumber := int64(1234567)
endingBlockNumber := int64(1234568)
err := transformer.Execute(startingBlockNumber, endingBlockNumber)
Expect(err).NotTo(HaveOccurred())
mockPublisher.AssertWriteCalledWithBodies(fakeRawData)
})
})
})
@@ -1,82 +0,0 @@
package transformers
import (
"fmt"
"log"
"github.com/ethereum/go-ethereum/common"
"github.com/vulcanize/eth-block-extractor/pkg/db"
"github.com/vulcanize/eth-block-extractor/pkg/ipfs"
)
type EthStateTrieTransformer struct {
database db.Database
stateTriePublisher ipfs.Publisher
storageTriePublisher ipfs.Publisher
}
func NewEthStateTrieTransformer(database db.Database, stateTriePublisher, storageTriePublisher ipfs.Publisher) *EthStateTrieTransformer {
return &EthStateTrieTransformer{
database: database,
stateTriePublisher: stateTriePublisher,
storageTriePublisher: storageTriePublisher,
}
}
func (t EthStateTrieTransformer) Execute(startingBlockNumber int64, endingBlockNumber int64) error {
if endingBlockNumber < startingBlockNumber {
return ErrInvalidRange
}
for i := startingBlockNumber; i <= endingBlockNumber; i++ {
root, err := t.getStateRootForBlock(i)
if err != nil {
return err
}
stateTrieNodes, storageTrieNodes, err := t.database.GetStateAndStorageTrieNodes(root)
if err != nil {
return fmt.Errorf("Error fetching state trie for block %d: %s\n", i, err)
}
err = t.writeStateTrieNodesToIpfs(stateTrieNodes)
if err != nil {
return err
}
err = t.writeStorageTrieNodesToIpfs(storageTrieNodes)
if err != nil {
return err
}
}
return nil
}
func (t EthStateTrieTransformer) getStateRootForBlock(blockNumber int64) (root common.Hash, err error) {
header := t.database.GetBlockHeaderByBlockNumber(blockNumber)
if err != nil {
return root, err
}
return header.Root, nil
}
func (t EthStateTrieTransformer) writeStateTrieNodesToIpfs(stateTrieNodes [][]byte) error {
for _, node := range stateTrieNodes {
output, err := t.stateTriePublisher.Write(node)
if err != nil {
return fmt.Errorf("Error writing state trie node to ipfs: %s\n", err.Error())
}
log.Println("Created ipld: ", output)
}
return nil
}
func (t EthStateTrieTransformer) writeStorageTrieNodesToIpfs(storageTrieNodes [][]byte) error {
for _, node := range storageTrieNodes {
output, err := t.storageTriePublisher.Write(node)
if err != nil {
return fmt.Errorf("Error writing storage trie node to ipfs: %s\n", err.Error())
}
log.Println("Created ipld: ", output)
}
return nil
}
@@ -1,99 +0,0 @@
package transformers_test
import (
"io/ioutil"
"log"
"github.com/ethereum/go-ethereum/core/types"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/eth-block-extractor/pkg/transformers"
"github.com/vulcanize/eth-block-extractor/test_helpers"
"github.com/vulcanize/eth-block-extractor/test_helpers/mocks/db"
"github.com/vulcanize/eth-block-extractor/test_helpers/mocks/ipfs"
"github.com/vulcanize/eth-block-extractor/test_helpers/mocks/wrappers/rlp"
)
var _ = Describe("Eth state trie transformer", func() {
BeforeEach(func() {
log.SetOutput(ioutil.Discard)
})
It("returns error if ending block number is less than starting block number", func() {
transformer := transformers.NewEthStateTrieTransformer(db.NewMockDatabase(), ipfs.NewMockPublisher(), ipfs.NewMockPublisher())
err := transformer.Execute(1, 0)
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(transformers.ErrInvalidRange))
})
It("fetches block header for block", func() {
mockDB := db.NewMockDatabase()
mockDB.SetGetBlockHeaderByBlockNumberReturnHeader(&types.Header{})
transformer := transformers.NewEthStateTrieTransformer(mockDB, ipfs.NewMockPublisher(), ipfs.NewMockPublisher())
err := transformer.Execute(0, 0)
Expect(err).NotTo(HaveOccurred())
mockDB.AssertGetBlockHeaderByBlockNumberCalledWith([]int64{0})
})
It("fetches state and storage trie nodes with state root from decoded block header", func() {
mockDB := db.NewMockDatabase()
mockDB.SetGetBlockHeaderByBlockNumberReturnHeader(&types.Header{Root: test_helpers.FakeHash})
transformer := transformers.NewEthStateTrieTransformer(mockDB, ipfs.NewMockPublisher(), ipfs.NewMockPublisher())
err := transformer.Execute(0, 0)
Expect(err).NotTo(HaveOccurred())
mockDB.AssertGetStateTrieNodesCalledWith(test_helpers.FakeHash)
})
It("returns err if fetching state trie returns err", func() {
mockDB := db.NewMockDatabase()
mockDB.SetGetBlockHeaderByBlockNumberReturnHeader(&types.Header{})
mockDB.SetGetStateAndStorageTrieNodesError(test_helpers.FakeError)
transformer := transformers.NewEthStateTrieTransformer(mockDB, ipfs.NewMockPublisher(), ipfs.NewMockPublisher())
err := transformer.Execute(0, 0)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring(test_helpers.FakeError.Error()))
})
It("writes state trie nodes to ipfs", func() {
mockDB := db.NewMockDatabase()
mockDB.SetGetBlockHeaderByBlockNumberReturnHeader(&types.Header{})
fakeStateTrieNodes := [][]byte{{1, 2, 3, 4, 5}, {6, 7, 8, 9, 0}}
mockDB.SetGetStateAndStorageTrieNodesReturnStateTrieBytes(fakeStateTrieNodes)
mockDecoder := rlp.NewMockDecoder()
mockDecoder.SetReturnOut(&types.Header{})
mockStateTriePublisher := ipfs.NewMockPublisher()
mockStateTriePublisher.SetReturnStrings([][]string{{"one"}, {"two"}})
transformer := transformers.NewEthStateTrieTransformer(mockDB, mockStateTriePublisher, ipfs.NewMockPublisher())
err := transformer.Execute(0, 0)
Expect(err).NotTo(HaveOccurred())
mockStateTriePublisher.AssertWriteCalledWithBytes(fakeStateTrieNodes)
})
It("writes storage trie nodes to ipfs", func() {
mockDB := db.NewMockDatabase()
mockDB.SetGetBlockHeaderByBlockNumberReturnHeader(&types.Header{})
fakeStateTrieNodes := [][]byte{{1, 2, 3, 4, 5}, {6, 7, 8, 9, 0}}
mockDB.SetGetStateAndStorageTrieNodesReturnStorageTrieBytes(fakeStateTrieNodes)
mockDecoder := rlp.NewMockDecoder()
mockDecoder.SetReturnOut(&types.Header{})
mockStorageTriePublisher := ipfs.NewMockPublisher()
mockStorageTriePublisher.SetReturnStrings([][]string{{"one"}, {"two"}})
transformer := transformers.NewEthStateTrieTransformer(mockDB, ipfs.NewMockPublisher(), mockStorageTriePublisher)
err := transformer.Execute(0, 0)
Expect(err).NotTo(HaveOccurred())
mockStorageTriePublisher.AssertWriteCalledWithBytes(fakeStateTrieNodes)
})
})
@@ -1,13 +0,0 @@
package transformers_test
import (
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
func TestTransformers(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Transformers Suite")
}
@@ -1,24 +0,0 @@
package core
import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
)
type GethBlockValidator interface {
ValidateState(block, parent *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64) error
}
type BlockValidator struct {
validator core.Validator
}
func NewBlockValidator(blockChain BlockChain) *BlockValidator {
validator := core.NewBlockValidator(blockChain.Config(), blockChain.BlockChain(), blockChain.Engine())
return &BlockValidator{validator: validator}
}
func (sv *BlockValidator) ValidateState(block, parent *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64) error {
return sv.validator.ValidateState(block, parent, state, receipts, usedGas)
}
@@ -1,40 +0,0 @@
package core
import (
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
)
type GethCoreBlockChain interface {
BlockChain() *core.BlockChain
Config() *params.ChainConfig
Engine() consensus.Engine
}
type BlockChain struct {
blockChain *core.BlockChain
}
func NewBlockChain(databaseConnection ethdb.Database) (*BlockChain, error) {
blockchain, err := core.NewBlockChain(databaseConnection, nil, params.MainnetChainConfig, ethash.NewFaker(), vm.Config{})
if err != nil {
return nil, err
}
return &BlockChain{blockChain: blockchain}, nil
}
func (sb *BlockChain) BlockChain() *core.BlockChain {
return sb.blockChain
}
func (sb *BlockChain) Config() *params.ChainConfig {
return sb.blockChain.Config()
}
func (sb *BlockChain) Engine() consensus.Engine {
return sb.blockChain.Engine()
}
@@ -1,50 +0,0 @@
package rawdb
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/rlp"
)
type IAccessorsChain interface {
GetBlock(hash common.Hash, number uint64) *types.Block
GetBlockReceipts(hash common.Hash, number uint64) types.Receipts
GetBody(hash common.Hash, number uint64) *types.Body
GetCanonicalHash(number uint64) common.Hash
GetHeader(hash common.Hash, number uint64) *types.Header
GetHeaderRLP(hash common.Hash, number uint64) rlp.RawValue
}
type AccessorsChain struct {
ethDbConnection ethdb.Database
}
func NewAccessorsChain(databaseConnection ethdb.Database) *AccessorsChain {
return &AccessorsChain{ethDbConnection: databaseConnection}
}
func (accessor *AccessorsChain) GetBlock(hash common.Hash, number uint64) *types.Block {
return rawdb.ReadBlock(accessor.ethDbConnection, hash, number)
}
func (accessor *AccessorsChain) GetBlockReceipts(hash common.Hash, number uint64) types.Receipts {
return rawdb.ReadReceipts(accessor.ethDbConnection, hash, number)
}
func (accessor *AccessorsChain) GetBody(hash common.Hash, number uint64) *types.Body {
return rawdb.ReadBody(accessor.ethDbConnection, hash, number)
}
func (accessor *AccessorsChain) GetCanonicalHash(number uint64) common.Hash {
return rawdb.ReadCanonicalHash(accessor.ethDbConnection, number)
}
func (accessor *AccessorsChain) GetHeader(hash common.Hash, number uint64) *types.Header {
return rawdb.ReadHeader(accessor.ethDbConnection, hash, number)
}
func (accessor *AccessorsChain) GetHeaderRLP(hash common.Hash, number uint64) rlp.RawValue {
return rawdb.ReadHeaderRLP(accessor.ethDbConnection, hash, number)
}
@@ -1,41 +0,0 @@
package state
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/vulcanize/eth-block-extractor/pkg/wrappers/trie"
)
type GethStateDatabase interface {
Database() state.Database
OpenTrie(root common.Hash) (GethTrie, error)
TrieDB() trie.GethTrieDatabase
}
type Database struct {
db state.Database
trieDB trie.GethTrieDatabase
}
func NewDatabase(databaseConnection ethdb.Database) *Database {
db := state.NewDatabase(databaseConnection)
trieDB := trie.NewTrieDatabase(db.TrieDB())
return &Database{db: db, trieDB: trieDB}
}
func (db Database) Database() state.Database {
return db.db
}
func (db Database) OpenTrie(root common.Hash) (GethTrie, error) {
stateTrie, err := db.db.OpenTrie(root)
if err != nil {
return nil, err
}
return NewTrie(stateTrie), nil
}
func (db Database) TrieDB() trie.GethTrieDatabase {
return db.trieDB
}
@@ -1,23 +0,0 @@
package state
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
)
type GethStateDB interface {
Commit(deleteEmptyObjects bool) (common.Hash, error)
StateDB() *state.StateDB
}
type StateDB struct {
db *state.StateDB
}
func (st *StateDB) StateDB() *state.StateDB {
return st.db
}
func (st *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
return st.db.Commit(deleteEmptyObjects)
}
@@ -1,25 +0,0 @@
package state
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
)
type GethStateDBFactory interface {
NewStateDB(root common.Hash, db state.Database) (GethStateDB, error)
}
type StateDBFactory struct {
}
func NewStateDBFactory() *StateDBFactory {
return &StateDBFactory{}
}
func (stf *StateDBFactory) NewStateDB(root common.Hash, db state.Database) (GethStateDB, error) {
stateDb, err := state.New(root, db)
if err != nil {
return nil, err
}
return &StateDB{db: stateDb}, nil
}
@@ -1,23 +0,0 @@
package state
import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/vulcanize/eth-block-extractor/pkg/wrappers/trie"
)
type GethTrie interface {
NodeIterator(startKey []byte) trie.GethTrieNodeIterator
}
type Trie struct {
trie state.Trie
}
func NewTrie(trie state.Trie) GethTrie {
return &Trie{trie: trie}
}
func (t *Trie) NodeIterator(startKey []byte) trie.GethTrieNodeIterator {
iterator := t.trie.NodeIterator(startKey)
return trie.NewNodeIterator(iterator)
}
@@ -1,27 +0,0 @@
package core
import (
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
)
type GethStateProcessor interface {
Process(block *types.Block, statedb *state.StateDB) (types.Receipts, []*types.Log, uint64, error)
}
type StateProcessor struct {
processor *core.StateProcessor
}
func NewStateProcessor(blockChain BlockChain) *StateProcessor {
processor := core.NewStateProcessor(params.MainnetChainConfig, blockChain.BlockChain(), ethash.NewFaker())
return &StateProcessor{processor: processor}
}
func (sp *StateProcessor) Process(block *types.Block, statedb *state.StateDB) (types.Receipts, []*types.Log, uint64, error) {
return sp.processor.Process(block, statedb, vm.Config{})
}
@@ -1,22 +0,0 @@
package trie
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/trie"
)
type GethTrieDatabase interface {
Node(hash common.Hash) ([]byte, error)
}
type Database struct {
db *trie.Database
}
func NewTrieDatabase(db *trie.Database) *Database {
return &Database{db: db}
}
func (td *Database) Node(hash common.Hash) ([]byte, error) {
return td.db.Node(hash)
}
@@ -1,37 +0,0 @@
package trie
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/trie"
)
type GethTrieNodeIterator interface {
Hash() common.Hash
Leaf() bool
LeafBlob() []byte
Next(bool) bool
}
type NodeIterator struct {
iterator trie.NodeIterator
}
func NewNodeIterator(nodeIterator trie.NodeIterator) *NodeIterator {
return &NodeIterator{iterator: nodeIterator}
}
func (ni *NodeIterator) Hash() common.Hash {
return ni.iterator.Hash()
}
func (ni *NodeIterator) Leaf() bool {
return ni.iterator.Leaf()
}
func (ni *NodeIterator) LeafBlob() []byte {
return ni.iterator.LeafBlob()
}
func (ni *NodeIterator) Next(b bool) bool {
return ni.iterator.Next(b)
}