Skip to content

Commit

Permalink
[Chore] Guard against nil buckets to prevent panics (#473)
Browse files Browse the repository at this point in the history
* Guard against nil buckets to prevent panics

* Remove txindex check
  • Loading branch information
zquestz authored May 24, 2021
1 parent 1061454 commit dc64324
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 6 deletions.
1 change: 0 additions & 1 deletion bchrpc/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2929,7 +2929,6 @@ func (s *GrpcServer) getSlpToken(hash *chainhash.Hash, vout uint32, scriptPubKey
// NOTE: this is launched as a goroutine and does not return errors!
//
func (s *GrpcServer) slpEventHandler() {

if s.slpIndex == nil {
return
}
Expand Down
9 changes: 9 additions & 0 deletions blockchain/indexers/addrindex.go
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,9 @@ func (idx *AddrIndex) ConnectBlock(dbTx database.Tx, block *bchutil.Block,

// Add all of the index entries for each address.
addrIdxBucket := dbTx.Metadata().Bucket(addrIndexKey)
if addrIdxBucket == nil {
return fmt.Errorf("bucket nil for key: %s", addrIndexKey)
}
for addrKey, txIdxs := range addrsToTxns {
for _, txIdx := range txIdxs {
err := dbPutAddrIndexEntry(addrIdxBucket, addrKey,
Expand Down Expand Up @@ -762,6 +765,9 @@ func (idx *AddrIndex) DisconnectBlock(dbTx database.Tx, block *bchutil.Block,

// Remove all of the index entries for each address.
bucket := dbTx.Metadata().Bucket(addrIndexKey)
if bucket == nil {
return fmt.Errorf("bucket nil for key: %s", addrIndexKey)
}
for addrKey, txIdxs := range addrsToTxns {
err := dbRemoveAddrIndexEntries(bucket, addrKey, len(txIdxs))
if err != nil {
Expand Down Expand Up @@ -801,6 +807,9 @@ func (idx *AddrIndex) TxRegionsForAddress(dbTx database.Tx, addr bchutil.Address

var err error
addrIdxBucket := dbTx.Metadata().Bucket(addrIndexKey)
if addrIdxBucket == nil {
return fmt.Errorf("bucket nil for key: %s", addrIndexKey)
}
regions, skipped, err = dbFetchAddrIndexEntries(addrIdxBucket,
addrKey, numToSkip, numRequested, reverse,
fetchBlockHash)
Expand Down
34 changes: 31 additions & 3 deletions blockchain/indexers/cfindex.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package indexers
import (
"encoding/binary"
"errors"
"fmt"

"github.com/gcash/bchd/blockchain"
"github.com/gcash/bchd/chaincfg"
Expand Down Expand Up @@ -66,25 +67,49 @@ var (
// dbFetchFilterIdxEntry retrieves a data blob from the filter index database.
// An entry's absence is not considered an error.
func dbFetchFilterIdxEntry(dbTx database.Tx, key []byte, h *chainhash.Hash) ([]byte, error) {
idx := dbTx.Metadata().Bucket(cfIndexParentBucketKey).Bucket(key)
parentIdx := dbTx.Metadata().Bucket(cfIndexParentBucketKey)
if parentIdx == nil {
return []byte{}, fmt.Errorf("bucket nil for key: %s", cfIndexParentBucketKey)
}
idx := parentIdx.Bucket(key)
if idx == nil {
return []byte{}, fmt.Errorf("bucket nil for key: %s", key)
}
return idx.Get(h[:]), nil
}

// dbStoreFilterIdxEntry stores a data blob in the filter index database.
func dbStoreFilterIdxEntry(dbTx database.Tx, key []byte, h *chainhash.Hash, f []byte) error {
idx := dbTx.Metadata().Bucket(cfIndexParentBucketKey).Bucket(key)
parentIdx := dbTx.Metadata().Bucket(cfIndexParentBucketKey)
if parentIdx == nil {
return fmt.Errorf("bucket nil for key: %s", cfIndexParentBucketKey)
}
idx := parentIdx.Bucket(key)
if idx == nil {
return fmt.Errorf("bucket nil for key: %s", key)
}
return idx.Put(h[:], f)
}

// dbDeleteFilterIdxEntry deletes a data blob from the filter index database.
func dbDeleteFilterIdxEntry(dbTx database.Tx, key []byte, h *chainhash.Hash) error {
idx := dbTx.Metadata().Bucket(cfIndexParentBucketKey).Bucket(key)
parentIdx := dbTx.Metadata().Bucket(cfIndexParentBucketKey)
if parentIdx == nil {
return fmt.Errorf("bucket nil for key: %s", cfIndexParentBucketKey)
}
idx := parentIdx.Bucket(key)
if idx == nil {
return fmt.Errorf("bucket nil for key: %s", key)
}
return idx.Delete(h[:])
}

// dbFetchMigrationVersion retrieves the migration version from the bucket.
func dbFetchMigrationVersion(dbTx database.Tx) (uint32, error) {
bucket := dbTx.Metadata().Bucket(cfIndexParentBucketKey)
if bucket == nil {
return 0, fmt.Errorf("bucket nil for key: %s", cfIndexParentBucketKey)
}
versionBytes := bucket.Get(cfIndexMigrationVersionKey)
version := uint32(0)
if len(versionBytes) == 4 {
Expand All @@ -96,6 +121,9 @@ func dbFetchMigrationVersion(dbTx database.Tx) (uint32, error) {
// dbStoreMigrationVersion stores the migration version in the bucket.
func dbStoreMigrationVersion(dbTx database.Tx, version uint32) error {
bucket := dbTx.Metadata().Bucket(cfIndexParentBucketKey)
if bucket == nil {
return fmt.Errorf("bucket nil for key: %s", cfIndexParentBucketKey)
}
versionBytes := make([]byte, 4)
binary.BigEndian.PutUint32(versionBytes, version)
return bucket.Put(cfIndexMigrationVersionKey, versionBytes)
Expand Down
22 changes: 20 additions & 2 deletions blockchain/indexers/slpindex.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,9 @@ func dbPutTokenIDIndexEntry(dbTx database.Tx, id uint32, metadata *TokenMetadata
// token id for the provided hash from the index.
func dbFetchTokenIDByHash(dbTx database.Tx, hash *chainhash.Hash) (uint32, error) {
hashIndex := dbTx.Metadata().Bucket(tokenIDByHashIndexBucketName)
if hashIndex == nil {
return 0, fmt.Errorf("bucket nil for key: %s", tokenIDByHashIndexBucketName)
}
serializedID := hashIndex.Get(hash[:])
if serializedID == nil {
return 0, errNoTokenIDHashEntry
Expand All @@ -177,6 +180,9 @@ func dbFetchTokenIDByHash(dbTx database.Tx, hash *chainhash.Hash) (uint32, error
// retrieve the hash for the provided serialized token id from the index.
func dbFetchTokenMetadataBySerializedID(dbTx database.Tx, serializedID []byte) (*TokenMetadata, error) {
idIndex := dbTx.Metadata().Bucket(tokenMetadataByIDIndexBucketName)
if idIndex == nil {
return nil, fmt.Errorf("bucket nil for key: %s", tokenMetadataByIDIndexBucketName)
}
serializedData := idIndex.Get(serializedID)
if serializedData == nil {
return nil, errNoTokenMetadataEntry
Expand Down Expand Up @@ -316,6 +322,9 @@ func dbPutSlpIndexEntry(idx *SlpIndex, dbTx database.Tx, entryInfo *dbSlpIndexEn
byteOrder.PutUint16(target[4:], uint16(entryInfo.slpMsg.TokenType()))
copy(target[6:], entryInfo.slpMsgPkScript)
slpIndex := dbTx.Metadata().Bucket(slpIndexKey)
if slpIndex == nil {
return fmt.Errorf("bucket nil for key: %s", slpIndexKey)
}
return slpIndex.Put(txHash[:], target)
}

Expand All @@ -332,8 +341,11 @@ type SlpTxEntry struct {
// nil will be returned for the both the entry and the error.
func dbFetchSlpIndexEntry(dbTx database.Tx, txHash *chainhash.Hash) (*SlpTxEntry, error) {
// Load the record from the database and return now if it doesn't exist.
SlpIndex := dbTx.Metadata().Bucket(slpIndexKey)
serializedData := SlpIndex.Get(txHash[:])
slpIndex := dbTx.Metadata().Bucket(slpIndexKey)
if slpIndex == nil {
return nil, fmt.Errorf("bucket nil for key: %s", slpIndexKey)
}
serializedData := slpIndex.Get(txHash[:])
if len(serializedData) == 0 {
return nil, fmt.Errorf("slp entry does not exist %v", txHash)
}
Expand Down Expand Up @@ -376,6 +388,9 @@ func dbRemoveSlpIndexEntries(dbTx database.Tx, block *bchutil.Block) error {
// this method should only be called after a topological sort
dbRemoveSlpIndexEntry := func(dbTx database.Tx, txHash *chainhash.Hash) error {
slpIndex := dbTx.Metadata().Bucket(slpIndexKey)
if slpIndex == nil {
return fmt.Errorf("bucket nil for key: %s", slpIndexKey)
}
serializedData := slpIndex.Get(txHash[:])
if len(serializedData) == 0 {
return nil
Expand Down Expand Up @@ -1154,6 +1169,9 @@ func (idx *SlpIndex) buildGraphSearchTokenMap() (*map[chainhash.Hash]*chainhash.

err := idx.db.View(func(dbTx database.Tx) error {
idxBucket := dbTx.Metadata().Bucket(slpIndexKey)
if idxBucket == nil {
return fmt.Errorf("bucket nil for key: %s", slpIndexKey)
}

// loop through all of the valid slp txn items stored in the db
err := idxBucket.ForEach(func(k []byte, v []byte) error {
Expand Down
15 changes: 15 additions & 0 deletions blockchain/indexers/txindex.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ func dbRemoveBlockIDIndexEntry(dbTx database.Tx, hash *chainhash.Hash) error {
// block id for the provided hash from the index.
func dbFetchBlockIDByHash(dbTx database.Tx, hash *chainhash.Hash) (uint32, error) {
hashIndex := dbTx.Metadata().Bucket(idByHashIndexBucketName)
if hashIndex == nil {
return 0, fmt.Errorf("bucket nil for key: %s", idByHashIndexBucketName)
}
serializedID := hashIndex.Get(hash[:])
if serializedID == nil {
return 0, errNoBlockIDEntry
Expand All @@ -146,6 +149,9 @@ func dbFetchBlockIDByHash(dbTx database.Tx, hash *chainhash.Hash) (uint32, error
// retrieve the hash for the provided serialized block id from the index.
func dbFetchBlockHashBySerializedID(dbTx database.Tx, serializedID []byte) (*chainhash.Hash, error) {
idIndex := dbTx.Metadata().Bucket(hashByIDIndexBucketName)
if idIndex == nil {
return nil, fmt.Errorf("bucket nil for key: %s", hashByIDIndexBucketName)
}
hashBytes := idIndex.Get(serializedID)
if hashBytes == nil {
return nil, errNoBlockIDEntry
Expand Down Expand Up @@ -179,6 +185,9 @@ func putTxIndexEntry(target []byte, blockID uint32, txLoc wire.TxLoc) {
// been serialized putTxIndexEntry.
func dbPutTxIndexEntry(dbTx database.Tx, txHash *chainhash.Hash, serializedData []byte) error {
txIndex := dbTx.Metadata().Bucket(txIndexKey)
if txIndex == nil {
return fmt.Errorf("bucket nil for key: %s", txIndexKey)
}
return txIndex.Put(txHash[:], serializedData)
}

Expand All @@ -189,6 +198,9 @@ func dbPutTxIndexEntry(dbTx database.Tx, txHash *chainhash.Hash, serializedData
func dbFetchTxIndexEntry(dbTx database.Tx, txHash *chainhash.Hash) (*database.BlockRegion, error) {
// Load the record from the database and return now if it doesn't exist.
txIndex := dbTx.Metadata().Bucket(txIndexKey)
if txIndex == nil {
return nil, fmt.Errorf("bucket nil for key: %s", txIndexKey)
}
serializedData := txIndex.Get(txHash[:])
if len(serializedData) == 0 {
return nil, nil
Expand Down Expand Up @@ -257,6 +269,9 @@ func dbAddTxIndexEntries(dbTx database.Tx, block *bchutil.Block, blockID uint32)
// recent transaction index entry for the given hash.
func dbRemoveTxIndexEntry(dbTx database.Tx, txHash *chainhash.Hash) error {
txIndex := dbTx.Metadata().Bucket(txIndexKey)
if txIndex == nil {
return fmt.Errorf("bucket nil for key: %s", txIndexKey)
}
serializedData := txIndex.Get(txHash[:])
if len(serializedData) == 0 {
return fmt.Errorf("can't remove non-existent transaction %s "+
Expand Down

0 comments on commit dc64324

Please sign in to comment.