func (cs *ChainState) prunePayments(ctx context.Context, height uint32) error {
	toDelete, err := cs.cfg.db.fetchPaymentsAtHeight(height)
	if err != nil {
		return err
	}
	for _, payment := range toDelete {
		hash, err := chainhash.NewHashFromStr(payment.Source.BlockHash)
		if err != nil {
			return err
		}
		confs, err := cs.cfg.GetBlockConfirmations(ctx, hash)
		if err != nil {
			return err
		}
		if confs <= 0 {
			err = cs.cfg.db.deletePayment(payment.UUID)
			if err != nil {
				return err
			}
		}
	}
	return nil
}
prunePayments removes all spendable payments sourcing from
orphaned blocks at the provided height.
package pool
import (
	"context"
	"errors"
	"sync"
	"sync/atomic"
	"time"
	"github.com/decred/dcrd/blockchain/standalone/v2"
	"github.com/decred/dcrd/chaincfg/chainhash"
	"github.com/decred/dcrd/dcrutil/v3"
	"github.com/decred/dcrd/wire"
	errs "github.com/decred/dcrpool/errors"
)
const (
	bufferSize = 128
)
type ChainStateConfig struct {
	db Database
	SoloPool bool
	ProcessPayments func(msg *paymentMsg)
	GeneratePayments func(uint32, *PaymentSource, dcrutil.Amount, int64) error
	GetBlock func(context.Context, *chainhash.Hash) (*wire.MsgBlock, error)
	GetBlockConfirmations func(context.Context, *chainhash.Hash) (int64, error)
	Cancel context.CancelFunc
	SignalCache func(event CacheUpdateEvent)
	HubWg *sync.WaitGroup
}
type blockNotification struct {
	Header []byte
	Done   chan bool
}
type ChainState struct {
	lastWorkHeight uint32  
	cfg            *ChainStateConfig
	connCh         chan *blockNotification
	discCh         chan *blockNotification
	currentWork    string
	currentWorkMtx sync.RWMutex
}
func NewChainState(sCfg *ChainStateConfig) *ChainState {
	return &ChainState{
		cfg:    sCfg,
		connCh: make(chan *blockNotification, bufferSize),
		discCh: make(chan *blockNotification, bufferSize),
	}
}
func (cs *ChainState) fetchLastWorkHeight() uint32 {
	return atomic.LoadUint32(&cs.lastWorkHeight)
}
func (cs *ChainState) setLastWorkHeight(height uint32) {
	atomic.StoreUint32(&cs.lastWorkHeight, height)
}
func (cs *ChainState) setCurrentWork(headerE string) {
	cs.currentWorkMtx.Lock()
	cs.currentWork = headerE
	cs.currentWorkMtx.Unlock()
}
func (cs *ChainState) fetchCurrentWork() string {
	cs.currentWorkMtx.RLock()
	work := cs.currentWork
	cs.currentWorkMtx.RUnlock()
	return work
}
func (cs *ChainState) pruneAcceptedWork(ctx context.Context, height uint32) error {
	toDelete, err := cs.cfg.db.fetchUnconfirmedWork(height)
	if err != nil {
		return err
	}
	for _, work := range toDelete {
		hash, err := chainhash.NewHashFromStr(work.BlockHash)
		if err != nil {
			return err
		}
		confs, err := cs.cfg.GetBlockConfirmations(ctx, hash)
		if err != nil {
			if !errors.Is(err, errs.BlockNotFound) {
				return err
			}
		}
		if confs <= 0 {
			err = cs.cfg.db.deleteAcceptedWork(work.UUID)
			if err != nil {
				return err
			}
			continue
		}
		work.Confirmed = true
		err = cs.cfg.db.updateAcceptedWork(work)
		if err != nil {
			return err
		}
	}
	return nil
}