func dbIndexDisconnectBlock(dbTx database.Tx, indexer Indexer, block, parent *hcashutil.Block, view *blockchain.UtxoViewpoint) error {
	idxKey := indexer.Key()
	curTipHash, _, err := dbFetchIndexerTip(dbTx, idxKey)
	if err != nil {
		return err
	}
	if !curTipHash.IsEqual(block.Hash()) {
		return AssertError(fmt.Sprintf("dbIndexDisconnectBlock must "+
			"be called with the block at the current index tip "+
			"(%s, tip %s, block %s)", indexer.Name(),
			curTipHash, block.Hash()))
	}
	if err := indexer.DisconnectBlock(dbTx, block, parent, view); err != nil {
		return err
	}
	prevHash := &block.MsgBlock().Header.PrevBlock
	return dbPutIndexerTip(dbTx, idxKey, prevHash, int32(block.Height()-1))
}
dbIndexDisconnectBlock removes all of the index entries associated with the
given block using the provided indexer and updates the tip of the indexer
accordingly.  An error will be returned if the current tip for the indexer is
not the passed block.
package indexers
import (
	"bytes"
	"fmt"
	"github.com/HcashOrg/hcashd/blockchain"
	"github.com/HcashOrg/hcashd/blockchain/internal/progresslog"
	"github.com/HcashOrg/hcashd/blockchain/stake"
	"github.com/HcashOrg/hcashd/chaincfg"
	"github.com/HcashOrg/hcashd/chaincfg/chainhash"
	"github.com/HcashOrg/hcashd/database"
	"github.com/HcashOrg/hcashd/wire"
	"github.com/HcashOrg/hcashutil"
)
var (
	indexTipsBucketName = []byte("idxtips")
)
func dbPutIndexerTip(dbTx database.Tx, idxKey []byte, hash *chainhash.Hash, height int32) error {
	serialized := make([]byte, chainhash.HashSize+4)
	copy(serialized, hash[:])
	byteOrder.PutUint32(serialized[chainhash.HashSize:], uint32(height))
	indexesBucket := dbTx.Metadata().Bucket(indexTipsBucketName)
	return indexesBucket.Put(idxKey, serialized)
}
func dbFetchIndexerTip(dbTx database.Tx, idxKey []byte) (*chainhash.Hash, int32, error) {
	indexesBucket := dbTx.Metadata().Bucket(indexTipsBucketName)
	serialized := indexesBucket.Get(idxKey)
	if len(serialized) < chainhash.HashSize+4 {
		return nil, 0, database.Error{
			ErrorCode: database.ErrCorruption,
			Description: fmt.Sprintf("unexpected end of data for "+
				"index %q tip", string(idxKey)),
		}
	}
	var hash chainhash.Hash
	copy(hash[:], serialized[:chainhash.HashSize])
	height := int32(byteOrder.Uint32(serialized[chainhash.HashSize:]))
	return &hash, height, nil
}
func dbIndexConnectBlock(dbTx database.Tx, indexer Indexer, block, parent *hcashutil.Block, view *blockchain.UtxoViewpoint) error {
	idxKey := indexer.Key()
	curTipHash, _, err := dbFetchIndexerTip(dbTx, idxKey)
	if err != nil {
		return err
	}
	if !curTipHash.IsEqual(&block.MsgBlock().Header.PrevBlock) {
		return AssertError(fmt.Sprintf("dbIndexConnectBlock must be "+
			"called with a block that extends the current index "+
			"tip (%s, tip %s, block %s)", indexer.Name(),
			curTipHash, block.Hash()))
	}
	if err := indexer.ConnectBlock(dbTx, block, parent, view); err != nil {
		return err
	}
	return dbPutIndexerTip(dbTx, idxKey, block.Hash(), int32(block.Height()))
}