func (view *UtxoViewpoint) connectTransactions(block *cashutil.Block, stxos *[]SpentTxOut) error {
	for _, tx := range block.Transactions() {
		err := view.connectTransaction(tx, block.Height(), stxos)
		if err != nil {
			return err
		}
	}
	view.SetBestHash(block.Hash())
	return nil
}
connectTransactions updates the view by adding all new utxos created by all
of the transactions in the passed block, marking all utxos the transactions
spend as spent, and setting the best hash for the view to the passed block.
In addition, when the 'stxos' argument is not nil, it will be updated to
append an entry for each spent txout.
package blockchain
import (
	"fmt"
	"github.com/bcext/cashutil"
	"github.com/bcext/gcash/chaincfg/chainhash"
	"github.com/bcext/gcash/database"
	"github.com/bcext/gcash/txscript"
	"github.com/bcext/gcash/wire"
)
type txoFlags uint8
const (
	tfCoinBase txoFlags = 1 << iota
	tfSpent
	tfModified
)
type UtxoEntry struct {
	amount      int64
	pkScript    []byte  
	blockHeight int32   
	packedFlags txoFlags
}
func (entry *UtxoEntry) isModified() bool {
	return entry.packedFlags&tfModified == tfModified
}
func (entry *UtxoEntry) IsCoinBase() bool {
	return entry.packedFlags&tfCoinBase == tfCoinBase
}
func (entry *UtxoEntry) BlockHeight() int32 {
	return entry.blockHeight
}
func (entry *UtxoEntry) IsSpent() bool {
	return entry.packedFlags&tfSpent == tfSpent
}
func (entry *UtxoEntry) Spend() {
	if entry.IsSpent() {
		return
	}
	entry.packedFlags |= tfSpent | tfModified
}
func (entry *UtxoEntry) Amount() int64 {
	return entry.amount
}
func (entry *UtxoEntry) PkScript() []byte {
	return entry.pkScript
}
func (entry *UtxoEntry) Clone() *UtxoEntry {
	if entry == nil {
		return nil
	}
	return &UtxoEntry{
		amount:      entry.amount,
		pkScript:    entry.pkScript,
		blockHeight: entry.blockHeight,
		packedFlags: entry.packedFlags,
	}
}
type UtxoViewpoint struct {
	entries  map[wire.OutPoint]*UtxoEntry
	bestHash chainhash.Hash
}
func (view *UtxoViewpoint) BestHash() *chainhash.Hash {
	return &view.bestHash
}
func (view *UtxoViewpoint) SetBestHash(hash *chainhash.Hash) {
	view.bestHash = *hash
}
func (view *UtxoViewpoint) LookupEntry(outpoint wire.OutPoint) *UtxoEntry {
	return view.entries[outpoint]
}
func (view *UtxoViewpoint) addTxOut(outpoint wire.OutPoint, txOut *wire.TxOut, isCoinBase bool, blockHeight int32) {
	if txscript.IsUnspendable(txOut.PkScript) {
		return
	}
	entry := view.LookupEntry(outpoint)
	if entry == nil {
		entry = new(UtxoEntry)
		view.entries[outpoint] = entry
	}
	entry.amount = txOut.Value
	entry.pkScript = txOut.PkScript
	entry.blockHeight = blockHeight
	entry.packedFlags = tfModified
	if isCoinBase {
		entry.packedFlags |= tfCoinBase
	}
}
func (view *UtxoViewpoint) AddTxOut(tx *cashutil.Tx, txOutIdx uint32, blockHeight int32) {
	if txOutIdx >= uint32(len(tx.MsgTx().TxOut)) {
		return
	}
	prevOut := wire.OutPoint{Hash: *tx.Hash(), Index: txOutIdx}
	txOut := tx.MsgTx().TxOut[txOutIdx]
	view.addTxOut(prevOut, txOut, IsCoinBase(tx), blockHeight)
}
func (view *UtxoViewpoint) AddTxOuts(tx *cashutil.Tx, blockHeight int32) {
	isCoinBase := IsCoinBase(tx)
	prevOut := wire.OutPoint{Hash: *tx.Hash()}
	for txOutIdx, txOut := range tx.MsgTx().TxOut {
		prevOut.Index = uint32(txOutIdx)
		view.addTxOut(prevOut, txOut, isCoinBase, blockHeight)
	}
}
func (view *UtxoViewpoint) connectTransaction(tx *cashutil.Tx, blockHeight int32, stxos *[]SpentTxOut) error {
	if IsCoinBase(tx) {
		view.AddTxOuts(tx, blockHeight)
		return nil
	}
	for _, txIn := range tx.MsgTx().TxIn {
		entry := view.entries[txIn.PreviousOutPoint]
		if entry == nil {
			return AssertError(fmt.Sprintf("view missing input %v",
				txIn.PreviousOutPoint))
		}
		if stxos != nil {
			var stxo = SpentTxOut{
				Amount:     entry.Amount(),
				PkScript:   entry.PkScript(),
				Height:     entry.BlockHeight(),
				IsCoinBase: entry.IsCoinBase(),
			}
			*stxos = append(*stxos, stxo)
		}
		entry.Spend()
	}
	view.AddTxOuts(tx, blockHeight)
	return nil
}