github.com/lbryio/lbcd@v0.22.119/txscript/hashcache.go (about)

     1  // Copyright (c) 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 txscript
     6  
     7  import (
     8  	"sync"
     9  
    10  	"github.com/lbryio/lbcd/chaincfg/chainhash"
    11  	"github.com/lbryio/lbcd/wire"
    12  )
    13  
    14  // TxSigHashes houses the partial set of sighashes introduced within BIP0143.
    15  // This partial set of sighashes may be re-used within each input across a
    16  // transaction when validating all inputs. As a result, validation complexity
    17  // for SigHashAll can be reduced by a polynomial factor.
    18  type TxSigHashes struct {
    19  	HashPrevOuts chainhash.Hash
    20  	HashSequence chainhash.Hash
    21  	HashOutputs  chainhash.Hash
    22  }
    23  
    24  // NewTxSigHashes computes, and returns the cached sighashes of the given
    25  // transaction.
    26  func NewTxSigHashes(tx *wire.MsgTx) *TxSigHashes {
    27  	return &TxSigHashes{
    28  		HashPrevOuts: calcHashPrevOuts(tx),
    29  		HashSequence: calcHashSequence(tx),
    30  		HashOutputs:  calcHashOutputs(tx),
    31  	}
    32  }
    33  
    34  // HashCache houses a set of partial sighashes keyed by txid. The set of partial
    35  // sighashes are those introduced within BIP0143 by the new more efficient
    36  // sighash digest calculation algorithm. Using this threadsafe shared cache,
    37  // multiple goroutines can safely re-use the pre-computed partial sighashes
    38  // speeding up validation time amongst all inputs found within a block.
    39  type HashCache struct {
    40  	sigHashes map[chainhash.Hash]*TxSigHashes
    41  
    42  	sync.RWMutex
    43  }
    44  
    45  // NewHashCache returns a new instance of the HashCache given a maximum number
    46  // of entries which may exist within it at anytime.
    47  func NewHashCache(maxSize uint) *HashCache {
    48  	return &HashCache{
    49  		sigHashes: make(map[chainhash.Hash]*TxSigHashes, maxSize),
    50  	}
    51  }
    52  
    53  // AddSigHashes computes, then adds the partial sighashes for the passed
    54  // transaction.
    55  func (h *HashCache) AddSigHashes(tx *wire.MsgTx) {
    56  	h.Lock()
    57  	h.sigHashes[tx.TxHash()] = NewTxSigHashes(tx)
    58  	h.Unlock()
    59  }
    60  
    61  // ContainsHashes returns true if the partial sighashes for the passed
    62  // transaction currently exist within the HashCache, and false otherwise.
    63  func (h *HashCache) ContainsHashes(txid *chainhash.Hash) bool {
    64  	h.RLock()
    65  	_, found := h.sigHashes[*txid]
    66  	h.RUnlock()
    67  
    68  	return found
    69  }
    70  
    71  // GetSigHashes possibly returns the previously cached partial sighashes for
    72  // the passed transaction. This function also returns an additional boolean
    73  // value indicating if the sighashes for the passed transaction were found to
    74  // be present within the HashCache.
    75  func (h *HashCache) GetSigHashes(txid *chainhash.Hash) (*TxSigHashes, bool) {
    76  	h.RLock()
    77  	item, found := h.sigHashes[*txid]
    78  	h.RUnlock()
    79  
    80  	return item, found
    81  }
    82  
    83  // PurgeSigHashes removes all partial sighashes from the HashCache belonging to
    84  // the passed transaction.
    85  func (h *HashCache) PurgeSigHashes(txid *chainhash.Hash) {
    86  	h.Lock()
    87  	delete(h.sigHashes, *txid)
    88  	h.Unlock()
    89  }