diff --git a/cmd/coldImport.go b/cmd/coldImport.go index ec1a7ad5..0b2aa61c 100644 --- a/cmd/coldImport.go +++ b/cmd/coldImport.go @@ -49,10 +49,6 @@ func init() { } func coldImport() { - if endingBlockNumber < startingBlockNumber { - log.Fatal("Ending block number must be greater than starting block number for cold import.") - } - // init eth db ethDBConfig := ethereum.CreateDatabaseConfig(ethereum.Level, levelDbPath) ethDB, err := ethereum.CreateDatabase(ethDBConfig) @@ -60,6 +56,14 @@ func coldImport() { log.Fatal("Error connecting to ethereum db: ", err) } + if endingBlockNumber < startingBlockNumber { + log.Fatal("Ending block number must be greater than starting block number for cold import.") + } + mostRecentBlockNumberInDb := ethDB.GetHeadBlockNumber() + if endingBlockNumber > mostRecentBlockNumberInDb { + log.Fatal("Ending block number is greater than most recent block in db: ", mostRecentBlockNumberInDb) + } + // init pg db genesisBlockHash := common.BytesToHash(ethDB.GetBlockHash(0)).String() coldNode := core.Node{ diff --git a/pkg/datastore/ethereum/database.go b/pkg/datastore/ethereum/database.go index e74082a7..c0676c41 100644 --- a/pkg/datastore/ethereum/database.go +++ b/pkg/datastore/ethereum/database.go @@ -13,6 +13,7 @@ type Database interface { GetBlock(hash []byte, blockNumber int64) *types.Block GetBlockHash(blockNumber int64) []byte GetBlockReceipts(blockHash []byte, blockNumber int64) types.Receipts + GetHeadBlockNumber() int64 } func CreateDatabase(config DatabaseConfig) (Database, error) { diff --git a/pkg/datastore/ethereum/level/database.go b/pkg/datastore/ethereum/level/database.go index 29c4fb76..1d32ae8b 100644 --- a/pkg/datastore/ethereum/level/database.go +++ b/pkg/datastore/ethereum/level/database.go @@ -32,3 +32,9 @@ func (l LevelDatabase) GetBlockReceipts(blockHash []byte, blockNumber int64) typ h := common.BytesToHash(blockHash) return l.reader.GetBlockReceipts(h, n) } + +func (l LevelDatabase) GetHeadBlockNumber() int64 { + h := l.reader.GetHeadBlockHash() + n := l.reader.GetBlockNumber(h) + return int64(n) +} diff --git a/pkg/datastore/ethereum/level/database_reader.go b/pkg/datastore/ethereum/level/database_reader.go index d4360b70..05b1e278 100644 --- a/pkg/datastore/ethereum/level/database_reader.go +++ b/pkg/datastore/ethereum/level/database_reader.go @@ -8,26 +8,36 @@ import ( type Reader interface { GetBlock(hash common.Hash, number uint64) *types.Block + GetBlockNumber(hash common.Hash) uint64 GetBlockReceipts(hash common.Hash, number uint64) types.Receipts GetCanonicalHash(number uint64) common.Hash + GetHeadBlockHash() common.Hash } type LevelDatabaseReader struct { - core.DatabaseReader + reader core.DatabaseReader } func NewLevelDatabaseReader(reader core.DatabaseReader) *LevelDatabaseReader { - return &LevelDatabaseReader{DatabaseReader: reader} + return &LevelDatabaseReader{reader: reader} } func (ldbr *LevelDatabaseReader) GetBlock(hash common.Hash, number uint64) *types.Block { - return core.GetBlock(ldbr.DatabaseReader, hash, number) + return core.GetBlock(ldbr.reader, hash, number) +} + +func (ldbr *LevelDatabaseReader) GetBlockNumber(hash common.Hash) uint64 { + return core.GetBlockNumber(ldbr.reader, hash) } func (ldbr *LevelDatabaseReader) GetBlockReceipts(hash common.Hash, number uint64) types.Receipts { - return core.GetBlockReceipts(ldbr.DatabaseReader, hash, number) + return core.GetBlockReceipts(ldbr.reader, hash, number) } func (ldbr *LevelDatabaseReader) GetCanonicalHash(number uint64) common.Hash { - return core.GetCanonicalHash(ldbr.DatabaseReader, number) + return core.GetCanonicalHash(ldbr.reader, number) +} + +func (ldbr *LevelDatabaseReader) GetHeadBlockHash() common.Hash { + return core.GetHeadBlockHash(ldbr.reader) } diff --git a/pkg/datastore/ethereum/level/database_test.go b/pkg/datastore/ethereum/level/database_test.go index 4342e24a..4d2018da 100644 --- a/pkg/datastore/ethereum/level/database_test.go +++ b/pkg/datastore/ethereum/level/database_test.go @@ -3,24 +3,12 @@ package level_test import ( "github.com/ethereum/go-ethereum/common" . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" "github.com/vulcanize/vulcanizedb/pkg/datastore/ethereum/level" "github.com/vulcanize/vulcanizedb/pkg/fakes" ) var _ = Describe("Level database", func() { - Describe("Getting a block hash", func() { - It("converts block number to uint64 to fetch hash from reader", func() { - mockReader := fakes.NewMockLevelDatabaseReader() - ldb := level.NewLevelDatabase(mockReader) - blockNumber := int64(12345) - - ldb.GetBlockHash(blockNumber) - - expectedBlockNumber := uint64(blockNumber) - mockReader.AssertGetCanonicalHashCalledWith(expectedBlockNumber) - }) - }) - Describe("Getting a block", func() { It("converts block number to uint64 and hash to common.Hash to fetch block from reader", func() { mockReader := fakes.NewMockLevelDatabaseReader() @@ -36,6 +24,19 @@ var _ = Describe("Level database", func() { }) }) + Describe("Getting a block hash", func() { + It("converts block number to uint64 to fetch hash from reader", func() { + mockReader := fakes.NewMockLevelDatabaseReader() + ldb := level.NewLevelDatabase(mockReader) + blockNumber := int64(12345) + + ldb.GetBlockHash(blockNumber) + + expectedBlockNumber := uint64(blockNumber) + mockReader.AssertGetCanonicalHashCalledWith(expectedBlockNumber) + }) + }) + Describe("Getting a block's receipts", func() { It("converts block number to uint64 and hash to common.Hash to fetch receipts from reader", func() { mockReader := fakes.NewMockLevelDatabaseReader() @@ -50,4 +51,21 @@ var _ = Describe("Level database", func() { mockReader.AssertGetBlockReceiptsCalledWith(expectedBlockHash, expectedBlockNumber) }) }) + + Describe("Getting the latest block number", func() { + It("invokes the database reader to get the latest block number by hash and converts result to int64", func() { + mockReader := fakes.NewMockLevelDatabaseReader() + fakeHash := common.BytesToHash([]byte{1, 2, 3, 4, 5}) + mockReader.SetHeadBlockHashReturnHash(fakeHash) + fakeBlockNumber := uint64(123456789) + mockReader.SetReturnBlockNumber(fakeBlockNumber) + ldb := level.NewLevelDatabase(mockReader) + + result := ldb.GetHeadBlockNumber() + + mockReader.AssertGetHeadBlockHashCalled() + mockReader.AssertGetBlockNumberCalledWith(fakeHash) + Expect(result).To(Equal(int64(fakeBlockNumber))) + }) + }) }) diff --git a/pkg/fakes/mock_ethereum_database.go b/pkg/fakes/mock_ethereum_database.go index f0026e74..a25d2b5c 100644 --- a/pkg/fakes/mock_ethereum_database.go +++ b/pkg/fakes/mock_ethereum_database.go @@ -18,6 +18,8 @@ type MockEthereumDatabase struct { getBlockReceiptsPassedHash []byte getBlockReceiptsPassedNumber int64 getBlockReceiptsReturnReceipts types.Receipts + getHeadBlockNumberCalled bool + getHeadBlockNumberReturnVal int64 } func NewMockEthereumDatabase() *MockEthereumDatabase { @@ -33,6 +35,8 @@ func NewMockEthereumDatabase() *MockEthereumDatabase { getBlockReceiptsPassedHash: nil, getBlockReceiptsPassedNumber: 0, getBlockReceiptsReturnReceipts: nil, + getHeadBlockNumberCalled: false, + getHeadBlockNumberReturnVal: 0, } } @@ -68,6 +72,11 @@ func (med *MockEthereumDatabase) GetBlockReceipts(blockHash []byte, blockNumber return med.getBlockReceiptsReturnReceipts } +func (med *MockEthereumDatabase) GetHeadBlockNumber() int64 { + med.getHeadBlockNumberCalled = true + return med.getHeadBlockNumberReturnVal +} + func (med *MockEthereumDatabase) AssertGetBlockCalledWith(hash []byte, blockNumber int64) { Expect(med.getBlockCalled).To(BeTrue()) Expect(med.getBlockPassedHash).To(Equal(hash)) diff --git a/pkg/fakes/mock_level_database_reader.go b/pkg/fakes/mock_level_database_reader.go index c4af4d22..4e2bb118 100644 --- a/pkg/fakes/mock_level_database_reader.go +++ b/pkg/fakes/mock_level_database_reader.go @@ -8,32 +8,42 @@ import ( type MockLevelDatabaseReader struct { getBlockCalled bool - getBlockReceiptsCalled bool - getCanonicalHashCalled bool - passedHash common.Hash - getCanonicalHashPassedNumber uint64 + getBlockNumberCalled bool + getBlockNumberPassedHash common.Hash getBlockPassedHash common.Hash getBlockPassedNumber uint64 + getBlockReceiptsCalled bool getBlockReceiptsPassedHash common.Hash getBlockReceiptsPassedNumber uint64 + getCanonicalHashCalled bool + getCanonicalHashPassedNumber uint64 + getCanonicalHashReturnHash common.Hash + getHeadBlockHashCalled bool + getHeadBlockHashReturnHash common.Hash + passedHash common.Hash returnBlock *types.Block - returnHash common.Hash + returnBlockNumber uint64 returnReceipts types.Receipts } func NewMockLevelDatabaseReader() *MockLevelDatabaseReader { return &MockLevelDatabaseReader{ getBlockCalled: false, - getBlockReceiptsCalled: false, - getCanonicalHashCalled: false, - passedHash: common.Hash{}, - getCanonicalHashPassedNumber: 0, + getBlockNumberCalled: false, + getBlockNumberPassedHash: common.Hash{}, getBlockPassedHash: common.Hash{}, getBlockPassedNumber: 0, + getBlockReceiptsCalled: false, getBlockReceiptsPassedHash: common.Hash{}, getBlockReceiptsPassedNumber: 0, + getCanonicalHashCalled: false, + getCanonicalHashPassedNumber: 0, + getCanonicalHashReturnHash: common.Hash{}, + getHeadBlockHashCalled: false, + getHeadBlockHashReturnHash: common.Hash{}, + passedHash: common.Hash{}, returnBlock: nil, - returnHash: common.Hash{}, + returnBlockNumber: 0, returnReceipts: nil, } } @@ -42,20 +52,22 @@ func (mldr *MockLevelDatabaseReader) SetReturnBlock(block *types.Block) { mldr.returnBlock = block } -func (mldr *MockLevelDatabaseReader) SetReturnHash(hash common.Hash) { - mldr.returnHash = hash +func (mldr *MockLevelDatabaseReader) SetReturnBlockNumber(n uint64) { + mldr.returnBlockNumber = n +} + +func (mldr *MockLevelDatabaseReader) SetGetCanonicalHashReturnHash(hash common.Hash) { + mldr.getCanonicalHashReturnHash = hash +} + +func (mldr *MockLevelDatabaseReader) SetHeadBlockHashReturnHash(hash common.Hash) { + mldr.getHeadBlockHashReturnHash = hash } func (mldr *MockLevelDatabaseReader) SetReturnReceipts(receipts types.Receipts) { mldr.returnReceipts = receipts } -func (mldr *MockLevelDatabaseReader) GetCanonicalHash(number uint64) common.Hash { - mldr.getCanonicalHashCalled = true - mldr.getCanonicalHashPassedNumber = number - return mldr.returnHash -} - func (mldr *MockLevelDatabaseReader) GetBlock(hash common.Hash, number uint64) *types.Block { mldr.getBlockCalled = true mldr.getBlockPassedHash = hash @@ -70,9 +82,21 @@ func (mldr *MockLevelDatabaseReader) GetBlockReceipts(hash common.Hash, number u return mldr.returnReceipts } -func (mldr *MockLevelDatabaseReader) AssertGetCanonicalHashCalledWith(number uint64) { - Expect(mldr.getCanonicalHashCalled).To(BeTrue()) - Expect(mldr.getCanonicalHashPassedNumber).To(Equal(number)) +func (mldr *MockLevelDatabaseReader) GetBlockNumber(hash common.Hash) uint64 { + mldr.getBlockNumberCalled = true + mldr.getBlockNumberPassedHash = hash + return mldr.returnBlockNumber +} + +func (mldr *MockLevelDatabaseReader) GetCanonicalHash(number uint64) common.Hash { + mldr.getCanonicalHashCalled = true + mldr.getCanonicalHashPassedNumber = number + return mldr.getCanonicalHashReturnHash +} + +func (mldr *MockLevelDatabaseReader) GetHeadBlockHash() common.Hash { + mldr.getHeadBlockHashCalled = true + return mldr.getHeadBlockHashReturnHash } func (mldr *MockLevelDatabaseReader) AssertGetBlockCalledWith(hash common.Hash, number uint64) { @@ -81,8 +105,22 @@ func (mldr *MockLevelDatabaseReader) AssertGetBlockCalledWith(hash common.Hash, Expect(mldr.getBlockPassedNumber).To(Equal(number)) } +func (mldr *MockLevelDatabaseReader) AssertGetBlockNumberCalledWith(hash common.Hash) { + Expect(mldr.getBlockNumberCalled).To(BeTrue()) + Expect(mldr.getBlockNumberPassedHash).To(Equal(hash)) +} + func (mldr *MockLevelDatabaseReader) AssertGetBlockReceiptsCalledWith(hash common.Hash, number uint64) { Expect(mldr.getBlockReceiptsCalled).To(BeTrue()) Expect(mldr.getBlockReceiptsPassedHash).To(Equal(hash)) Expect(mldr.getBlockReceiptsPassedNumber).To(Equal(number)) } + +func (mldr *MockLevelDatabaseReader) AssertGetCanonicalHashCalledWith(number uint64) { + Expect(mldr.getCanonicalHashCalled).To(BeTrue()) + Expect(mldr.getCanonicalHashPassedNumber).To(Equal(number)) +} + +func (mldr *MockLevelDatabaseReader) AssertGetHeadBlockHashCalled() { + Expect(mldr.getHeadBlockHashCalled).To(BeTrue()) +}