Add FetchBlockHeightBySha/FetchBlockHeaderBySha.
This commit introduces two new functions to the btcdb.Db interface named FetchBlockHeightBySha and FetchBlockHeaderBySha. The FetchBlockHeightBySha function is useful since previously it was only possible to get the height of block by fetching the entire block with FetchBlockBySha and pulling the height out of the returned btcutil.Block. The FetchBlockHeaderBySha function will ultimately make it much more efficient to fetch block headers. Currently, due to the database design in the ldb backend, the entire block has to be loaded anyways, so the only current benefit is to avoid the deserialize on all of the transactions. However, ultimately btcdb will gain a more efficient backend which can also avoid reading all of the extra transaction data altogether.
This commit is contained in:
parent
845aedf103
commit
d6c2492c7f
3 changed files with 77 additions and 0 deletions
7
db.go
7
db.go
|
@ -59,6 +59,13 @@ type Db interface {
|
||||||
// cache the underlying data if desired.
|
// cache the underlying data if desired.
|
||||||
FetchBlockBySha(sha *btcwire.ShaHash) (blk *btcutil.Block, err error)
|
FetchBlockBySha(sha *btcwire.ShaHash) (blk *btcutil.Block, err error)
|
||||||
|
|
||||||
|
// FetchBlockHeightBySha returns the block height for the given hash.
|
||||||
|
FetchBlockHeightBySha(sha *btcwire.ShaHash) (height int64, err error)
|
||||||
|
|
||||||
|
// FetchBlockHeaderBySha returns a btcwire.BlockHeader for the given
|
||||||
|
// sha. The implementation may cache the underlying data if desired.
|
||||||
|
FetchBlockHeaderBySha(sha *btcwire.ShaHash) (bh *btcwire.BlockHeader, err error)
|
||||||
|
|
||||||
// FetchBlockShaByHeight returns a block hash based on its height in the
|
// FetchBlockShaByHeight returns a block hash based on its height in the
|
||||||
// block chain.
|
// block chain.
|
||||||
FetchBlockShaByHeight(height int64) (sha *btcwire.ShaHash, err error)
|
FetchBlockShaByHeight(height int64) (sha *btcwire.ShaHash, err error)
|
||||||
|
|
32
ldb/block.go
32
ldb/block.go
|
@ -38,6 +38,38 @@ func (db *LevelDb) fetchBlockBySha(sha *btcwire.ShaHash) (blk *btcutil.Block, er
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FetchBlockHeightBySha returns the block height for the given hash. This is
|
||||||
|
// part of the btcdb.Db interface implementation.
|
||||||
|
func (db *LevelDb) FetchBlockHeightBySha(sha *btcwire.ShaHash) (int64, error) {
|
||||||
|
db.dbLock.Lock()
|
||||||
|
defer db.dbLock.Unlock()
|
||||||
|
|
||||||
|
return db.getBlkLoc(sha)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchBlockHeaderBySha - return a btcwire ShaHash
|
||||||
|
func (db *LevelDb) FetchBlockHeaderBySha(sha *btcwire.ShaHash) (bh *btcwire.BlockHeader, err error) {
|
||||||
|
db.dbLock.Lock()
|
||||||
|
defer db.dbLock.Unlock()
|
||||||
|
|
||||||
|
// Read the raw block from the database.
|
||||||
|
buf, _, err := db.fetchSha(sha)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only deserialize the header portion and ensure the transaction count
|
||||||
|
// is zero since this is a standalone header.
|
||||||
|
var blockHeader btcwire.BlockHeader
|
||||||
|
err = blockHeader.Deserialize(bytes.NewBuffer(buf))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
bh = &blockHeader
|
||||||
|
|
||||||
|
return bh, err
|
||||||
|
}
|
||||||
|
|
||||||
func (db *LevelDb) getBlkLoc(sha *btcwire.ShaHash) (int64, error) {
|
func (db *LevelDb) getBlkLoc(sha *btcwire.ShaHash) (int64, error) {
|
||||||
var blkHeight int64
|
var blkHeight int64
|
||||||
|
|
||||||
|
|
|
@ -230,6 +230,44 @@ func (db *MemDb) FetchBlockBySha(sha *btcwire.ShaHash) (*btcutil.Block, error) {
|
||||||
return nil, fmt.Errorf("block %v is not in database", sha)
|
return nil, fmt.Errorf("block %v is not in database", sha)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FetchBlockHeightBySha returns the block height for the given hash. This is
|
||||||
|
// part of the btcdb.Db interface implementation.
|
||||||
|
func (db *MemDb) FetchBlockHeightBySha(sha *btcwire.ShaHash) (int64, error) {
|
||||||
|
db.Lock()
|
||||||
|
defer db.Unlock()
|
||||||
|
|
||||||
|
if db.closed {
|
||||||
|
return 0, ErrDbClosed
|
||||||
|
}
|
||||||
|
|
||||||
|
if blockHeight, exists := db.blocksBySha[*sha]; exists {
|
||||||
|
return blockHeight, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, fmt.Errorf("block %v is not in database", sha)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchBlockHeaderBySha returns a btcwire.BlockHeader for the given sha. The
|
||||||
|
// implementation may cache the underlying data if desired. This is part of the
|
||||||
|
// btcdb.Db interface implementation.
|
||||||
|
//
|
||||||
|
// This implementation does not use any additional cache since the entire
|
||||||
|
// database is already in memory.
|
||||||
|
func (db *MemDb) FetchBlockHeaderBySha(sha *btcwire.ShaHash) (*btcwire.BlockHeader, error) {
|
||||||
|
db.Lock()
|
||||||
|
defer db.Unlock()
|
||||||
|
|
||||||
|
if db.closed {
|
||||||
|
return nil, ErrDbClosed
|
||||||
|
}
|
||||||
|
|
||||||
|
if blockHeight, exists := db.blocksBySha[*sha]; exists {
|
||||||
|
return &db.blocks[int(blockHeight)].Header, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("block header %v is not in database", sha)
|
||||||
|
}
|
||||||
|
|
||||||
// FetchBlockShaByHeight returns a block hash based on its height in the block
|
// FetchBlockShaByHeight returns a block hash based on its height in the block
|
||||||
// chain. This is part of the btcdb.Db interface implementation.
|
// chain. This is part of the btcdb.Db interface implementation.
|
||||||
func (db *MemDb) FetchBlockShaByHeight(height int64) (*btcwire.ShaHash, error) {
|
func (db *MemDb) FetchBlockShaByHeight(height int64) (*btcwire.ShaHash, error) {
|
||||||
|
|
Loading…
Reference in a new issue