github.com/btcsuite/btcd@v0.24.0/blockchain/utxoviewpoint.go (about)

     1  // Copyright (c) 2015-2016 The btcsuite developers
     2  // Use of this source code is governed by an ISC
     3  // license that can be found in the LICENSE file.
     4  
     5  package blockchain
     6  
     7  import (
     8  	"fmt"
     9  
    10  	"github.com/btcsuite/btcd/btcutil"
    11  	"github.com/btcsuite/btcd/chaincfg/chainhash"
    12  	"github.com/btcsuite/btcd/database"
    13  	"github.com/btcsuite/btcd/txscript"
    14  	"github.com/btcsuite/btcd/wire"
    15  )
    16  
    17  // txoFlags is a bitmask defining additional information and state for a
    18  // transaction output in a utxo view.
    19  type txoFlags uint8
    20  
    21  const (
    22  	// tfCoinBase indicates that a txout was contained in a coinbase tx.
    23  	tfCoinBase txoFlags = 1 << iota
    24  
    25  	// tfSpent indicates that a txout is spent.
    26  	tfSpent
    27  
    28  	// tfModified indicates that a txout has been modified since it was
    29  	// loaded.
    30  	tfModified
    31  
    32  	// tfFresh indicates that the entry is fresh.  This means that the parent
    33  	// view never saw this entry.  Note that tfFresh is a performance
    34  	// optimization with which we can erase entries that are fully spent if we
    35  	// know we do not need to commit them.  It is always safe to not mark
    36  	// tfFresh if that condition is not guaranteed.
    37  	tfFresh
    38  )
    39  
    40  // UtxoEntry houses details about an individual transaction output in a utxo
    41  // view such as whether or not it was contained in a coinbase tx, the height of
    42  // the block that contains the tx, whether or not it is spent, its public key
    43  // script, and how much it pays.
    44  type UtxoEntry struct {
    45  	// NOTE: Additions, deletions, or modifications to the order of the
    46  	// definitions in this struct should not be changed without considering
    47  	// how it affects alignment on 64-bit platforms.  The current order is
    48  	// specifically crafted to result in minimal padding.  There will be a
    49  	// lot of these in memory, so a few extra bytes of padding adds up.
    50  
    51  	amount      int64
    52  	pkScript    []byte // The public key script for the output.
    53  	blockHeight int32  // Height of block containing tx.
    54  
    55  	// packedFlags contains additional info about output such as whether it
    56  	// is a coinbase, whether it is spent, and whether it has been modified
    57  	// since it was loaded.  This approach is used in order to reduce memory
    58  	// usage since there will be a lot of these in memory.
    59  	packedFlags txoFlags
    60  }
    61  
    62  // isModified returns whether or not the output has been modified since it was
    63  // loaded.
    64  func (entry *UtxoEntry) isModified() bool {
    65  	return entry.packedFlags&tfModified == tfModified
    66  }
    67  
    68  // isFresh returns whether or not it's certain the output has never previously
    69  // been stored in the database.
    70  func (entry *UtxoEntry) isFresh() bool {
    71  	return entry.packedFlags&tfFresh == tfFresh
    72  }
    73  
    74  // memoryUsage returns the memory usage in bytes of for the utxo entry.
    75  // It returns 0 for a nil entry.
    76  func (entry *UtxoEntry) memoryUsage() uint64 {
    77  	if entry == nil {
    78  		return 0
    79  	}
    80  
    81  	return baseEntrySize + uint64(cap(entry.pkScript))
    82  }
    83  
    84  // IsCoinBase returns whether or not the output was contained in a coinbase
    85  // transaction.
    86  func (entry *UtxoEntry) IsCoinBase() bool {
    87  	return entry.packedFlags&tfCoinBase == tfCoinBase
    88  }
    89  
    90  // BlockHeight returns the height of the block containing the output.
    91  func (entry *UtxoEntry) BlockHeight() int32 {
    92  	return entry.blockHeight
    93  }
    94  
    95  // IsSpent returns whether or not the output has been spent based upon the
    96  // current state of the unspent transaction output view it was obtained from.
    97  func (entry *UtxoEntry) IsSpent() bool {
    98  	return entry.packedFlags&tfSpent == tfSpent
    99  }
   100  
   101  // Spend marks the output as spent.  Spending an output that is already spent
   102  // has no effect.
   103  func (entry *UtxoEntry) Spend() {
   104  	// Nothing to do if the output is already spent.
   105  	if entry.IsSpent() {
   106  		return
   107  	}
   108  
   109  	// Mark the output as spent and modified.
   110  	entry.packedFlags |= tfSpent | tfModified
   111  }
   112  
   113  // Amount returns the amount of the output.
   114  func (entry *UtxoEntry) Amount() int64 {
   115  	return entry.amount
   116  }
   117  
   118  // PkScript returns the public key script for the output.
   119  func (entry *UtxoEntry) PkScript() []byte {
   120  	return entry.pkScript
   121  }
   122  
   123  // Clone returns a shallow copy of the utxo entry.
   124  func (entry *UtxoEntry) Clone() *UtxoEntry {
   125  	if entry == nil {
   126  		return nil
   127  	}
   128  
   129  	return &UtxoEntry{
   130  		amount:      entry.amount,
   131  		pkScript:    entry.pkScript,
   132  		blockHeight: entry.blockHeight,
   133  		packedFlags: entry.packedFlags,
   134  	}
   135  }
   136  
   137  // NewUtxoEntry returns a new UtxoEntry built from the arguments.
   138  func NewUtxoEntry(
   139  	txOut *wire.TxOut, blockHeight int32, isCoinbase bool) *UtxoEntry {
   140  	var cbFlag txoFlags
   141  	if isCoinbase {
   142  		cbFlag |= tfCoinBase
   143  	}
   144  
   145  	return &UtxoEntry{
   146  		amount:      txOut.Value,
   147  		pkScript:    txOut.PkScript,
   148  		blockHeight: blockHeight,
   149  		packedFlags: cbFlag,
   150  	}
   151  }
   152  
   153  // UtxoViewpoint represents a view into the set of unspent transaction outputs
   154  // from a specific point of view in the chain.  For example, it could be for
   155  // the end of the main chain, some point in the history of the main chain, or
   156  // down a side chain.
   157  //
   158  // The unspent outputs are needed by other transactions for things such as
   159  // script validation and double spend prevention.
   160  type UtxoViewpoint struct {
   161  	entries  map[wire.OutPoint]*UtxoEntry
   162  	bestHash chainhash.Hash
   163  }
   164  
   165  // BestHash returns the hash of the best block in the chain the view currently
   166  // respresents.
   167  func (view *UtxoViewpoint) BestHash() *chainhash.Hash {
   168  	return &view.bestHash
   169  }
   170  
   171  // SetBestHash sets the hash of the best block in the chain the view currently
   172  // respresents.
   173  func (view *UtxoViewpoint) SetBestHash(hash *chainhash.Hash) {
   174  	view.bestHash = *hash
   175  }
   176  
   177  // LookupEntry returns information about a given transaction output according to
   178  // the current state of the view.  It will return nil if the passed output does
   179  // not exist in the view or is otherwise not available such as when it has been
   180  // disconnected during a reorg.
   181  func (view *UtxoViewpoint) LookupEntry(outpoint wire.OutPoint) *UtxoEntry {
   182  	return view.entries[outpoint]
   183  }
   184  
   185  // FetchPrevOutput fetches the previous output referenced by the passed
   186  // outpoint. This is identical to the LookupEntry method, but it returns a
   187  // wire.TxOut instead.
   188  //
   189  // NOTE: This is an implementation of the txscript.PrevOutputFetcher interface.
   190  func (view *UtxoViewpoint) FetchPrevOutput(op wire.OutPoint) *wire.TxOut {
   191  	prevOut := view.entries[op]
   192  	if prevOut == nil {
   193  		return nil
   194  	}
   195  
   196  	return &wire.TxOut{
   197  		Value:    prevOut.amount,
   198  		PkScript: prevOut.PkScript(),
   199  	}
   200  }
   201  
   202  // addTxOut adds the specified output to the view if it is not provably
   203  // unspendable.  When the view already has an entry for the output, it will be
   204  // marked unspent.  All fields will be updated for existing entries since it's
   205  // possible it has changed during a reorg.
   206  func (view *UtxoViewpoint) addTxOut(outpoint wire.OutPoint, txOut *wire.TxOut, isCoinBase bool, blockHeight int32) {
   207  	// Don't add provably unspendable outputs.
   208  	if txscript.IsUnspendable(txOut.PkScript) {
   209  		return
   210  	}
   211  
   212  	// Update existing entries.  All fields are updated because it's
   213  	// possible (although extremely unlikely) that the existing entry is
   214  	// being replaced by a different transaction with the same hash.  This
   215  	// is allowed so long as the previous transaction is fully spent.
   216  	entry := view.LookupEntry(outpoint)
   217  	if entry == nil {
   218  		entry = new(UtxoEntry)
   219  		view.entries[outpoint] = entry
   220  	}
   221  
   222  	entry.amount = txOut.Value
   223  	entry.pkScript = txOut.PkScript
   224  	entry.blockHeight = blockHeight
   225  	entry.packedFlags = tfFresh | tfModified
   226  	if isCoinBase {
   227  		entry.packedFlags |= tfCoinBase
   228  	}
   229  }
   230  
   231  // AddTxOut adds the specified output of the passed transaction to the view if
   232  // it exists and is not provably unspendable.  When the view already has an
   233  // entry for the output, it will be marked unspent.  All fields will be updated
   234  // for existing entries since it's possible it has changed during a reorg.
   235  func (view *UtxoViewpoint) AddTxOut(tx *btcutil.Tx, txOutIdx uint32, blockHeight int32) {
   236  	// Can't add an output for an out of bounds index.
   237  	if txOutIdx >= uint32(len(tx.MsgTx().TxOut)) {
   238  		return
   239  	}
   240  
   241  	// Update existing entries.  All fields are updated because it's
   242  	// possible (although extremely unlikely) that the existing entry is
   243  	// being replaced by a different transaction with the same hash.  This
   244  	// is allowed so long as the previous transaction is fully spent.
   245  	prevOut := wire.OutPoint{Hash: *tx.Hash(), Index: txOutIdx}
   246  	txOut := tx.MsgTx().TxOut[txOutIdx]
   247  	view.addTxOut(prevOut, txOut, IsCoinBase(tx), blockHeight)
   248  }
   249  
   250  // AddTxOuts adds all outputs in the passed transaction which are not provably
   251  // unspendable to the view.  When the view already has entries for any of the
   252  // outputs, they are simply marked unspent.  All fields will be updated for
   253  // existing entries since it's possible it has changed during a reorg.
   254  func (view *UtxoViewpoint) AddTxOuts(tx *btcutil.Tx, blockHeight int32) {
   255  	// Loop all of the transaction outputs and add those which are not
   256  	// provably unspendable.
   257  	isCoinBase := IsCoinBase(tx)
   258  	prevOut := wire.OutPoint{Hash: *tx.Hash()}
   259  	for txOutIdx, txOut := range tx.MsgTx().TxOut {
   260  		// Update existing entries.  All fields are updated because it's
   261  		// possible (although extremely unlikely) that the existing
   262  		// entry is being replaced by a different transaction with the
   263  		// same hash.  This is allowed so long as the previous
   264  		// transaction is fully spent.
   265  		prevOut.Index = uint32(txOutIdx)
   266  		view.addTxOut(prevOut, txOut, isCoinBase, blockHeight)
   267  	}
   268  }
   269  
   270  // connectTransaction updates the view by adding all new utxos created by the
   271  // passed transaction and marking all utxos that the transactions spend as
   272  // spent.  In addition, when the 'stxos' argument is not nil, it will be updated
   273  // to append an entry for each spent txout.  An error will be returned if the
   274  // view does not contain the required utxos.
   275  func (view *UtxoViewpoint) connectTransaction(tx *btcutil.Tx, blockHeight int32, stxos *[]SpentTxOut) error {
   276  	// Coinbase transactions don't have any inputs to spend.
   277  	if IsCoinBase(tx) {
   278  		// Add the transaction's outputs as available utxos.
   279  		view.AddTxOuts(tx, blockHeight)
   280  		return nil
   281  	}
   282  
   283  	// Spend the referenced utxos by marking them spent in the view and,
   284  	// if a slice was provided for the spent txout details, append an entry
   285  	// to it.
   286  	for _, txIn := range tx.MsgTx().TxIn {
   287  		// Ensure the referenced utxo exists in the view.  This should
   288  		// never happen unless there is a bug is introduced in the code.
   289  		entry := view.entries[txIn.PreviousOutPoint]
   290  		if entry == nil {
   291  			return AssertError(fmt.Sprintf("view missing input %v",
   292  				txIn.PreviousOutPoint))
   293  		}
   294  
   295  		// Only create the stxo details if requested.
   296  		if stxos != nil {
   297  			// Populate the stxo details using the utxo entry.
   298  			var stxo = SpentTxOut{
   299  				Amount:     entry.Amount(),
   300  				PkScript:   entry.PkScript(),
   301  				Height:     entry.BlockHeight(),
   302  				IsCoinBase: entry.IsCoinBase(),
   303  			}
   304  			*stxos = append(*stxos, stxo)
   305  		}
   306  
   307  		// Mark the entry as spent.  This is not done until after the
   308  		// relevant details have been accessed since spending it might
   309  		// clear the fields from memory in the future.
   310  		entry.Spend()
   311  	}
   312  
   313  	// Add the transaction's outputs as available utxos.
   314  	view.AddTxOuts(tx, blockHeight)
   315  	return nil
   316  }
   317  
   318  // connectTransactions updates the view by adding all new utxos created by all
   319  // of the transactions in the passed block, marking all utxos the transactions
   320  // spend as spent, and setting the best hash for the view to the passed block.
   321  // In addition, when the 'stxos' argument is not nil, it will be updated to
   322  // append an entry for each spent txout.
   323  func (view *UtxoViewpoint) connectTransactions(block *btcutil.Block, stxos *[]SpentTxOut) error {
   324  	for _, tx := range block.Transactions() {
   325  		err := view.connectTransaction(tx, block.Height(), stxos)
   326  		if err != nil {
   327  			return err
   328  		}
   329  	}
   330  
   331  	// Update the best hash for view to include this block since all of its
   332  	// transactions have been connected.
   333  	view.SetBestHash(block.Hash())
   334  	return nil
   335  }
   336  
   337  // fetchEntryByHash attempts to find any available utxo for the given hash by
   338  // searching the entire set of possible outputs for the given hash.  It checks
   339  // the view first and then falls back to the database if needed.
   340  func (view *UtxoViewpoint) fetchEntryByHash(db database.DB, hash *chainhash.Hash) (*UtxoEntry, error) {
   341  	// First attempt to find a utxo with the provided hash in the view.
   342  	prevOut := wire.OutPoint{Hash: *hash}
   343  	for idx := uint32(0); idx < MaxOutputsPerBlock; idx++ {
   344  		prevOut.Index = idx
   345  		entry := view.LookupEntry(prevOut)
   346  		if entry != nil {
   347  			return entry, nil
   348  		}
   349  	}
   350  
   351  	// Check the database since it doesn't exist in the view.  This will
   352  	// often by the case since only specifically referenced utxos are loaded
   353  	// into the view.
   354  	var entry *UtxoEntry
   355  	err := db.View(func(dbTx database.Tx) error {
   356  		var err error
   357  		entry, err = dbFetchUtxoEntryByHash(dbTx, hash)
   358  		return err
   359  	})
   360  	return entry, err
   361  }
   362  
   363  // disconnectTransactions updates the view by removing all of the transactions
   364  // created by the passed block, restoring all utxos the transactions spent by
   365  // using the provided spent txo information, and setting the best hash for the
   366  // view to the block before the passed block.
   367  func (view *UtxoViewpoint) disconnectTransactions(db database.DB, block *btcutil.Block, stxos []SpentTxOut) error {
   368  	// Sanity check the correct number of stxos are provided.
   369  	if len(stxos) != countSpentOutputs(block) {
   370  		return AssertError("disconnectTransactions called with bad " +
   371  			"spent transaction out information")
   372  	}
   373  
   374  	// Loop backwards through all transactions so everything is unspent in
   375  	// reverse order.  This is necessary since transactions later in a block
   376  	// can spend from previous ones.
   377  	stxoIdx := len(stxos) - 1
   378  	transactions := block.Transactions()
   379  	for txIdx := len(transactions) - 1; txIdx > -1; txIdx-- {
   380  		tx := transactions[txIdx]
   381  
   382  		// All entries will need to potentially be marked as a coinbase.
   383  		var packedFlags txoFlags
   384  		isCoinBase := txIdx == 0
   385  		if isCoinBase {
   386  			packedFlags |= tfCoinBase
   387  		}
   388  
   389  		// Mark all of the spendable outputs originally created by the
   390  		// transaction as spent.  It is instructive to note that while
   391  		// the outputs aren't actually being spent here, rather they no
   392  		// longer exist, since a pruned utxo set is used, there is no
   393  		// practical difference between a utxo that does not exist and
   394  		// one that has been spent.
   395  		//
   396  		// When the utxo does not already exist in the view, add an
   397  		// entry for it and then mark it spent.  This is done because
   398  		// the code relies on its existence in the view in order to
   399  		// signal modifications have happened.
   400  		txHash := tx.Hash()
   401  		prevOut := wire.OutPoint{Hash: *txHash}
   402  		for txOutIdx, txOut := range tx.MsgTx().TxOut {
   403  			if txscript.IsUnspendable(txOut.PkScript) {
   404  				continue
   405  			}
   406  
   407  			prevOut.Index = uint32(txOutIdx)
   408  			entry := view.entries[prevOut]
   409  			if entry == nil {
   410  				entry = &UtxoEntry{
   411  					amount:      txOut.Value,
   412  					pkScript:    txOut.PkScript,
   413  					blockHeight: block.Height(),
   414  					packedFlags: packedFlags,
   415  				}
   416  
   417  				view.entries[prevOut] = entry
   418  			}
   419  
   420  			entry.Spend()
   421  		}
   422  
   423  		// Loop backwards through all of the transaction inputs (except
   424  		// for the coinbase which has no inputs) and unspend the
   425  		// referenced txos.  This is necessary to match the order of the
   426  		// spent txout entries.
   427  		if isCoinBase {
   428  			continue
   429  		}
   430  		for txInIdx := len(tx.MsgTx().TxIn) - 1; txInIdx > -1; txInIdx-- {
   431  			// Ensure the spent txout index is decremented to stay
   432  			// in sync with the transaction input.
   433  			stxo := &stxos[stxoIdx]
   434  			stxoIdx--
   435  
   436  			// When there is not already an entry for the referenced
   437  			// output in the view, it means it was previously spent,
   438  			// so create a new utxo entry in order to resurrect it.
   439  			originOut := &tx.MsgTx().TxIn[txInIdx].PreviousOutPoint
   440  			entry := view.entries[*originOut]
   441  			if entry == nil {
   442  				entry = new(UtxoEntry)
   443  				view.entries[*originOut] = entry
   444  			}
   445  
   446  			// The legacy v1 spend journal format only stored the
   447  			// coinbase flag and height when the output was the last
   448  			// unspent output of the transaction.  As a result, when
   449  			// the information is missing, search for it by scanning
   450  			// all possible outputs of the transaction since it must
   451  			// be in one of them.
   452  			//
   453  			// It should be noted that this is quite inefficient,
   454  			// but it realistically will almost never run since all
   455  			// new entries include the information for all outputs
   456  			// and thus the only way this will be hit is if a long
   457  			// enough reorg happens such that a block with the old
   458  			// spend data is being disconnected.  The probability of
   459  			// that in practice is extremely low to begin with and
   460  			// becomes vanishingly small the more new blocks are
   461  			// connected.  In the case of a fresh database that has
   462  			// only ever run with the new v2 format, this code path
   463  			// will never run.
   464  			if stxo.Height == 0 {
   465  				utxo, err := view.fetchEntryByHash(db, txHash)
   466  				if err != nil {
   467  					return err
   468  				}
   469  				if utxo == nil {
   470  					return AssertError(fmt.Sprintf("unable "+
   471  						"to resurrect legacy stxo %v",
   472  						*originOut))
   473  				}
   474  
   475  				stxo.Height = utxo.BlockHeight()
   476  				stxo.IsCoinBase = utxo.IsCoinBase()
   477  			}
   478  
   479  			// Restore the utxo using the stxo data from the spend
   480  			// journal and mark it as modified.
   481  			entry.amount = stxo.Amount
   482  			entry.pkScript = stxo.PkScript
   483  			entry.blockHeight = stxo.Height
   484  			entry.packedFlags = tfModified
   485  			if stxo.IsCoinBase {
   486  				entry.packedFlags |= tfCoinBase
   487  			}
   488  		}
   489  	}
   490  
   491  	// Update the best hash for view to the previous block since all of the
   492  	// transactions for the current block have been disconnected.
   493  	view.SetBestHash(&block.MsgBlock().Header.PrevBlock)
   494  	return nil
   495  }
   496  
   497  // RemoveEntry removes the given transaction output from the current state of
   498  // the view.  It will have no effect if the passed output does not exist in the
   499  // view.
   500  func (view *UtxoViewpoint) RemoveEntry(outpoint wire.OutPoint) {
   501  	delete(view.entries, outpoint)
   502  }
   503  
   504  // Entries returns the underlying map that stores of all the utxo entries.
   505  func (view *UtxoViewpoint) Entries() map[wire.OutPoint]*UtxoEntry {
   506  	return view.entries
   507  }
   508  
   509  // commit prunes all entries marked modified that are now fully spent and marks
   510  // all entries as unmodified.
   511  func (view *UtxoViewpoint) commit() {
   512  	for outpoint, entry := range view.entries {
   513  		if entry == nil || (entry.isModified() && entry.IsSpent()) {
   514  			delete(view.entries, outpoint)
   515  			continue
   516  		}
   517  
   518  		entry.packedFlags ^= tfModified
   519  	}
   520  }
   521  
   522  // fetchUtxosMain fetches unspent transaction output data about the provided
   523  // set of outpoints from the point of view of the end of the main chain at the
   524  // time of the call.
   525  //
   526  // Upon completion of this function, the view will contain an entry for each
   527  // requested outpoint.  Spent outputs, or those which otherwise don't exist,
   528  // will result in a nil entry in the view.
   529  func (view *UtxoViewpoint) fetchUtxosMain(db database.DB, outpoints []wire.OutPoint) error {
   530  	// Nothing to do if there are no requested outputs.
   531  	if len(outpoints) == 0 {
   532  		return nil
   533  	}
   534  
   535  	// Load the requested set of unspent transaction outputs from the point
   536  	// of view of the end of the main chain.
   537  	//
   538  	// NOTE: Missing entries are not considered an error here and instead
   539  	// will result in nil entries in the view.  This is intentionally done
   540  	// so other code can use the presence of an entry in the store as a way
   541  	// to unnecessarily avoid attempting to reload it from the database.
   542  	return db.View(func(dbTx database.Tx) error {
   543  		utxoBucket := dbTx.Metadata().Bucket(utxoSetBucketName)
   544  		for i := range outpoints {
   545  			entry, err := dbFetchUtxoEntry(dbTx, utxoBucket, outpoints[i])
   546  			if err != nil {
   547  				return err
   548  			}
   549  
   550  			view.entries[outpoints[i]] = entry
   551  		}
   552  
   553  		return nil
   554  	})
   555  }
   556  
   557  // fetchUtxosFromCache fetches unspent transaction output data about the provided
   558  // set of outpoints from the point of view of the end of the main chain at the
   559  // time of the call.  It attempts to fetch them from the cache and whatever entries
   560  // that were not in the cache will be attempted to be fetched from the database and
   561  // it'll be cached.
   562  //
   563  // Upon completion of this function, the view will contain an entry for each
   564  // requested outpoint.  Spent outputs, or those which otherwise don't exist,
   565  // will result in a nil entry in the view.
   566  func (view *UtxoViewpoint) fetchUtxosFromCache(cache *utxoCache, outpoints []wire.OutPoint) error {
   567  	// Nothing to do if there are no requested outputs.
   568  	if len(outpoints) == 0 {
   569  		return nil
   570  	}
   571  
   572  	// Load the requested set of unspent transaction outputs from the point
   573  	// of view of the end of the main chain.  Any missing entries will be
   574  	// fetched from the database and be cached.
   575  	//
   576  	// NOTE: Missing entries are not considered an error here and instead
   577  	// will result in nil entries in the view.  This is intentionally done
   578  	// so other code can use the presence of an entry in the store as a way
   579  	// to unnecessarily avoid attempting to reload it from the database.
   580  	entries, err := cache.fetchEntries(outpoints)
   581  	if err != nil {
   582  		return err
   583  	}
   584  	for i, entry := range entries {
   585  		view.entries[outpoints[i]] = entry.Clone()
   586  	}
   587  	return nil
   588  }
   589  
   590  // fetchUtxos loads the unspent transaction outputs for the provided set of
   591  // outputs into the view from the database as needed unless they already exist
   592  // in the view in which case they are ignored.
   593  func (view *UtxoViewpoint) fetchUtxos(cache *utxoCache, outpoints []wire.OutPoint) error {
   594  	// Nothing to do if there are no requested outputs.
   595  	if len(outpoints) == 0 {
   596  		return nil
   597  	}
   598  
   599  	// Filter entries that are already in the view.
   600  	needed := make([]wire.OutPoint, 0, len(outpoints))
   601  	for i := range outpoints {
   602  		// Already loaded into the current view.
   603  		if _, ok := view.entries[outpoints[i]]; ok {
   604  			continue
   605  		}
   606  
   607  		needed = append(needed, outpoints[i])
   608  	}
   609  
   610  	// Request the input utxos from the database.
   611  	return view.fetchUtxosFromCache(cache, needed)
   612  }
   613  
   614  // findInputsToFetch goes through all the blocks and returns all the outpoints of
   615  // the entries that need to be fetched in order to validate the block.  Outpoints
   616  // for the entries that are already in the block are not included in the returned
   617  // outpoints.
   618  func (view *UtxoViewpoint) findInputsToFetch(block *btcutil.Block) []wire.OutPoint {
   619  	// Build a map of in-flight transactions because some of the inputs in
   620  	// this block could be referencing other transactions earlier in this
   621  	// block which are not yet in the chain.
   622  	txInFlight := map[chainhash.Hash]int{}
   623  	transactions := block.Transactions()
   624  	for i, tx := range transactions {
   625  		txInFlight[*tx.Hash()] = i
   626  	}
   627  
   628  	// Loop through all of the transaction inputs (except for the coinbase
   629  	// which has no inputs) collecting them into sets of what is needed and
   630  	// what is already known (in-flight).
   631  	needed := make([]wire.OutPoint, 0, len(transactions))
   632  	for i, tx := range transactions[1:] {
   633  		for _, txIn := range tx.MsgTx().TxIn {
   634  			// It is acceptable for a transaction input to reference
   635  			// the output of another transaction in this block only
   636  			// if the referenced transaction comes before the
   637  			// current one in this block.  Add the outputs of the
   638  			// referenced transaction as available utxos when this
   639  			// is the case.  Otherwise, the utxo details are still
   640  			// needed.
   641  			//
   642  			// NOTE: The >= is correct here because i is one less
   643  			// than the actual position of the transaction within
   644  			// the block due to skipping the coinbase.
   645  			originHash := &txIn.PreviousOutPoint.Hash
   646  			if inFlightIndex, ok := txInFlight[*originHash]; ok &&
   647  				i >= inFlightIndex {
   648  
   649  				originTx := transactions[inFlightIndex]
   650  				view.AddTxOuts(originTx, block.Height())
   651  				continue
   652  			}
   653  
   654  			// Don't request entries that are already in the view
   655  			// from the database.
   656  			if _, ok := view.entries[txIn.PreviousOutPoint]; ok {
   657  				continue
   658  			}
   659  
   660  			needed = append(needed, txIn.PreviousOutPoint)
   661  		}
   662  	}
   663  
   664  	return needed
   665  }
   666  
   667  // fetchInputUtxos loads the unspent transaction outputs for the inputs
   668  // referenced by the transactions in the given block into the view from the
   669  // database or the cache as needed.  In particular, referenced entries that
   670  // are earlier in the block are added to the view and entries that are already
   671  // in the view are not modified.
   672  func (view *UtxoViewpoint) fetchInputUtxos(db database.DB, cache *utxoCache, block *btcutil.Block) error {
   673  	if cache != nil {
   674  		return view.fetchUtxosFromCache(cache, view.findInputsToFetch(block))
   675  	}
   676  	// Request the input utxos from the cache.
   677  	return view.fetchUtxosMain(db, view.findInputsToFetch(block))
   678  }
   679  
   680  // NewUtxoViewpoint returns a new empty unspent transaction output view.
   681  func NewUtxoViewpoint() *UtxoViewpoint {
   682  	return &UtxoViewpoint{
   683  		entries: make(map[wire.OutPoint]*UtxoEntry),
   684  	}
   685  }
   686  
   687  // FetchUtxoView loads unspent transaction outputs for the inputs referenced by
   688  // the passed transaction from the point of view of the end of the main chain.
   689  // It also attempts to fetch the utxos for the outputs of the transaction itself
   690  // so the returned view can be examined for duplicate transactions.
   691  //
   692  // This function is safe for concurrent access however the returned view is NOT.
   693  func (b *BlockChain) FetchUtxoView(tx *btcutil.Tx) (*UtxoViewpoint, error) {
   694  	// Create a set of needed outputs based on those referenced by the
   695  	// inputs of the passed transaction and the outputs of the transaction
   696  	// itself.
   697  	neededLen := len(tx.MsgTx().TxOut)
   698  	if !IsCoinBase(tx) {
   699  		neededLen += len(tx.MsgTx().TxIn)
   700  	}
   701  	needed := make([]wire.OutPoint, 0, neededLen)
   702  	prevOut := wire.OutPoint{Hash: *tx.Hash()}
   703  	for txOutIdx := range tx.MsgTx().TxOut {
   704  		prevOut.Index = uint32(txOutIdx)
   705  		needed = append(needed, prevOut)
   706  	}
   707  	if !IsCoinBase(tx) {
   708  		for _, txIn := range tx.MsgTx().TxIn {
   709  			needed = append(needed, txIn.PreviousOutPoint)
   710  		}
   711  	}
   712  
   713  	// Request the utxos from the point of view of the end of the main
   714  	// chain.
   715  	view := NewUtxoViewpoint()
   716  	b.chainLock.RLock()
   717  	err := view.fetchUtxosFromCache(b.utxoCache, needed)
   718  	b.chainLock.RUnlock()
   719  	return view, err
   720  }
   721  
   722  // FetchUtxoEntry loads and returns the requested unspent transaction output
   723  // from the point of view of the end of the main chain.
   724  //
   725  // NOTE: Requesting an output for which there is no data will NOT return an
   726  // error.  Instead both the entry and the error will be nil.  This is done to
   727  // allow pruning of spent transaction outputs.  In practice this means the
   728  // caller must check if the returned entry is nil before invoking methods on it.
   729  //
   730  // This function is safe for concurrent access however the returned entry (if
   731  // any) is NOT.
   732  func (b *BlockChain) FetchUtxoEntry(outpoint wire.OutPoint) (*UtxoEntry, error) {
   733  	b.chainLock.RLock()
   734  	defer b.chainLock.RUnlock()
   735  
   736  	entries, err := b.utxoCache.fetchEntries([]wire.OutPoint{outpoint})
   737  	if err != nil {
   738  		return nil, err
   739  	}
   740  
   741  	return entries[0], nil
   742  }