Get head block number

- Allows us to refuse to sync past current head
- Creates the opportunity to add a flag for syncing all blocks
This commit is contained in:
Rob Mulholand 2018-05-03 16:58:45 -05:00
parent 5f6bf32ec1
commit 5a5e08bd13
7 changed files with 129 additions and 43 deletions

View File

@ -49,10 +49,6 @@ func init() {
} }
func coldImport() { func coldImport() {
if endingBlockNumber < startingBlockNumber {
log.Fatal("Ending block number must be greater than starting block number for cold import.")
}
// init eth db // init eth db
ethDBConfig := ethereum.CreateDatabaseConfig(ethereum.Level, levelDbPath) ethDBConfig := ethereum.CreateDatabaseConfig(ethereum.Level, levelDbPath)
ethDB, err := ethereum.CreateDatabase(ethDBConfig) ethDB, err := ethereum.CreateDatabase(ethDBConfig)
@ -60,6 +56,14 @@ func coldImport() {
log.Fatal("Error connecting to ethereum db: ", err) 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 // init pg db
genesisBlockHash := common.BytesToHash(ethDB.GetBlockHash(0)).String() genesisBlockHash := common.BytesToHash(ethDB.GetBlockHash(0)).String()
coldNode := core.Node{ coldNode := core.Node{

View File

@ -13,6 +13,7 @@ type Database interface {
GetBlock(hash []byte, blockNumber int64) *types.Block GetBlock(hash []byte, blockNumber int64) *types.Block
GetBlockHash(blockNumber int64) []byte GetBlockHash(blockNumber int64) []byte
GetBlockReceipts(blockHash []byte, blockNumber int64) types.Receipts GetBlockReceipts(blockHash []byte, blockNumber int64) types.Receipts
GetHeadBlockNumber() int64
} }
func CreateDatabase(config DatabaseConfig) (Database, error) { func CreateDatabase(config DatabaseConfig) (Database, error) {

View File

@ -32,3 +32,9 @@ func (l LevelDatabase) GetBlockReceipts(blockHash []byte, blockNumber int64) typ
h := common.BytesToHash(blockHash) h := common.BytesToHash(blockHash)
return l.reader.GetBlockReceipts(h, n) return l.reader.GetBlockReceipts(h, n)
} }
func (l LevelDatabase) GetHeadBlockNumber() int64 {
h := l.reader.GetHeadBlockHash()
n := l.reader.GetBlockNumber(h)
return int64(n)
}

View File

@ -8,26 +8,36 @@ import (
type Reader interface { type Reader interface {
GetBlock(hash common.Hash, number uint64) *types.Block GetBlock(hash common.Hash, number uint64) *types.Block
GetBlockNumber(hash common.Hash) uint64
GetBlockReceipts(hash common.Hash, number uint64) types.Receipts GetBlockReceipts(hash common.Hash, number uint64) types.Receipts
GetCanonicalHash(number uint64) common.Hash GetCanonicalHash(number uint64) common.Hash
GetHeadBlockHash() common.Hash
} }
type LevelDatabaseReader struct { type LevelDatabaseReader struct {
core.DatabaseReader reader core.DatabaseReader
} }
func NewLevelDatabaseReader(reader core.DatabaseReader) *LevelDatabaseReader { 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 { 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 { 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 { 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)
} }

View File

@ -3,24 +3,12 @@ package level_test
import ( import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/datastore/ethereum/level" "github.com/vulcanize/vulcanizedb/pkg/datastore/ethereum/level"
"github.com/vulcanize/vulcanizedb/pkg/fakes" "github.com/vulcanize/vulcanizedb/pkg/fakes"
) )
var _ = Describe("Level database", func() { 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() { Describe("Getting a block", func() {
It("converts block number to uint64 and hash to common.Hash to fetch block from reader", func() { It("converts block number to uint64 and hash to common.Hash to fetch block from reader", func() {
mockReader := fakes.NewMockLevelDatabaseReader() 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() { Describe("Getting a block's receipts", func() {
It("converts block number to uint64 and hash to common.Hash to fetch receipts from reader", func() { It("converts block number to uint64 and hash to common.Hash to fetch receipts from reader", func() {
mockReader := fakes.NewMockLevelDatabaseReader() mockReader := fakes.NewMockLevelDatabaseReader()
@ -50,4 +51,21 @@ var _ = Describe("Level database", func() {
mockReader.AssertGetBlockReceiptsCalledWith(expectedBlockHash, expectedBlockNumber) 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)))
})
})
}) })

View File

@ -18,6 +18,8 @@ type MockEthereumDatabase struct {
getBlockReceiptsPassedHash []byte getBlockReceiptsPassedHash []byte
getBlockReceiptsPassedNumber int64 getBlockReceiptsPassedNumber int64
getBlockReceiptsReturnReceipts types.Receipts getBlockReceiptsReturnReceipts types.Receipts
getHeadBlockNumberCalled bool
getHeadBlockNumberReturnVal int64
} }
func NewMockEthereumDatabase() *MockEthereumDatabase { func NewMockEthereumDatabase() *MockEthereumDatabase {
@ -33,6 +35,8 @@ func NewMockEthereumDatabase() *MockEthereumDatabase {
getBlockReceiptsPassedHash: nil, getBlockReceiptsPassedHash: nil,
getBlockReceiptsPassedNumber: 0, getBlockReceiptsPassedNumber: 0,
getBlockReceiptsReturnReceipts: nil, getBlockReceiptsReturnReceipts: nil,
getHeadBlockNumberCalled: false,
getHeadBlockNumberReturnVal: 0,
} }
} }
@ -68,6 +72,11 @@ func (med *MockEthereumDatabase) GetBlockReceipts(blockHash []byte, blockNumber
return med.getBlockReceiptsReturnReceipts return med.getBlockReceiptsReturnReceipts
} }
func (med *MockEthereumDatabase) GetHeadBlockNumber() int64 {
med.getHeadBlockNumberCalled = true
return med.getHeadBlockNumberReturnVal
}
func (med *MockEthereumDatabase) AssertGetBlockCalledWith(hash []byte, blockNumber int64) { func (med *MockEthereumDatabase) AssertGetBlockCalledWith(hash []byte, blockNumber int64) {
Expect(med.getBlockCalled).To(BeTrue()) Expect(med.getBlockCalled).To(BeTrue())
Expect(med.getBlockPassedHash).To(Equal(hash)) Expect(med.getBlockPassedHash).To(Equal(hash))

View File

@ -8,32 +8,42 @@ import (
type MockLevelDatabaseReader struct { type MockLevelDatabaseReader struct {
getBlockCalled bool getBlockCalled bool
getBlockReceiptsCalled bool getBlockNumberCalled bool
getCanonicalHashCalled bool getBlockNumberPassedHash common.Hash
passedHash common.Hash
getCanonicalHashPassedNumber uint64
getBlockPassedHash common.Hash getBlockPassedHash common.Hash
getBlockPassedNumber uint64 getBlockPassedNumber uint64
getBlockReceiptsCalled bool
getBlockReceiptsPassedHash common.Hash getBlockReceiptsPassedHash common.Hash
getBlockReceiptsPassedNumber uint64 getBlockReceiptsPassedNumber uint64
getCanonicalHashCalled bool
getCanonicalHashPassedNumber uint64
getCanonicalHashReturnHash common.Hash
getHeadBlockHashCalled bool
getHeadBlockHashReturnHash common.Hash
passedHash common.Hash
returnBlock *types.Block returnBlock *types.Block
returnHash common.Hash returnBlockNumber uint64
returnReceipts types.Receipts returnReceipts types.Receipts
} }
func NewMockLevelDatabaseReader() *MockLevelDatabaseReader { func NewMockLevelDatabaseReader() *MockLevelDatabaseReader {
return &MockLevelDatabaseReader{ return &MockLevelDatabaseReader{
getBlockCalled: false, getBlockCalled: false,
getBlockReceiptsCalled: false, getBlockNumberCalled: false,
getCanonicalHashCalled: false, getBlockNumberPassedHash: common.Hash{},
passedHash: common.Hash{},
getCanonicalHashPassedNumber: 0,
getBlockPassedHash: common.Hash{}, getBlockPassedHash: common.Hash{},
getBlockPassedNumber: 0, getBlockPassedNumber: 0,
getBlockReceiptsCalled: false,
getBlockReceiptsPassedHash: common.Hash{}, getBlockReceiptsPassedHash: common.Hash{},
getBlockReceiptsPassedNumber: 0, getBlockReceiptsPassedNumber: 0,
getCanonicalHashCalled: false,
getCanonicalHashPassedNumber: 0,
getCanonicalHashReturnHash: common.Hash{},
getHeadBlockHashCalled: false,
getHeadBlockHashReturnHash: common.Hash{},
passedHash: common.Hash{},
returnBlock: nil, returnBlock: nil,
returnHash: common.Hash{}, returnBlockNumber: 0,
returnReceipts: nil, returnReceipts: nil,
} }
} }
@ -42,20 +52,22 @@ func (mldr *MockLevelDatabaseReader) SetReturnBlock(block *types.Block) {
mldr.returnBlock = block mldr.returnBlock = block
} }
func (mldr *MockLevelDatabaseReader) SetReturnHash(hash common.Hash) { func (mldr *MockLevelDatabaseReader) SetReturnBlockNumber(n uint64) {
mldr.returnHash = hash 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) { func (mldr *MockLevelDatabaseReader) SetReturnReceipts(receipts types.Receipts) {
mldr.returnReceipts = 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 { func (mldr *MockLevelDatabaseReader) GetBlock(hash common.Hash, number uint64) *types.Block {
mldr.getBlockCalled = true mldr.getBlockCalled = true
mldr.getBlockPassedHash = hash mldr.getBlockPassedHash = hash
@ -70,9 +82,21 @@ func (mldr *MockLevelDatabaseReader) GetBlockReceipts(hash common.Hash, number u
return mldr.returnReceipts return mldr.returnReceipts
} }
func (mldr *MockLevelDatabaseReader) AssertGetCanonicalHashCalledWith(number uint64) { func (mldr *MockLevelDatabaseReader) GetBlockNumber(hash common.Hash) uint64 {
Expect(mldr.getCanonicalHashCalled).To(BeTrue()) mldr.getBlockNumberCalled = true
Expect(mldr.getCanonicalHashPassedNumber).To(Equal(number)) 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) { 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)) 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) { func (mldr *MockLevelDatabaseReader) AssertGetBlockReceiptsCalledWith(hash common.Hash, number uint64) {
Expect(mldr.getBlockReceiptsCalled).To(BeTrue()) Expect(mldr.getBlockReceiptsCalled).To(BeTrue())
Expect(mldr.getBlockReceiptsPassedHash).To(Equal(hash)) Expect(mldr.getBlockReceiptsPassedHash).To(Equal(hash))
Expect(mldr.getBlockReceiptsPassedNumber).To(Equal(number)) 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())
}