github.com/mit-dci/lit@v0.0.0-20221102210550-8c3d3b49f2ce/btcutil/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/mit-dci/lit/btcutil/chaincfg/chainhash" 11 "github.com/mit-dci/lit/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 a 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 defer h.Unlock() 58 59 sigHashes := NewTxSigHashes(tx) 60 61 txid := tx.TxHash() 62 h.sigHashes[txid] = sigHashes 63 64 return 65 } 66 67 // ContainsHashes returns true if the partial sighashes for the passed 68 // transaction currently exist within the HashCache, and false otherwise. 69 func (h *HashCache) ContainsHashes(txid *chainhash.Hash) bool { 70 h.RLock() 71 defer h.RUnlock() 72 73 _, found := h.sigHashes[*txid] 74 return found 75 } 76 77 // GetSigHashes possibly returns the previously cached partial sighashes for 78 // the passed transaction. This function also returns an additional boolean 79 // value indicating if the sighashes for the passed transaction were found to 80 // be present within the HashCache. 81 func (h *HashCache) GetSigHashes(txid *chainhash.Hash) (*TxSigHashes, bool) { 82 h.RLock() 83 defer h.RUnlock() 84 85 item, found := h.sigHashes[*txid] 86 return item, found 87 } 88 89 // PurgeSigHashes removes all partial sighashes from the HashCache belonging to 90 // the passed transaction. 91 func (h *HashCache) PurgeSigHashes(txid *chainhash.Hash) { 92 h.Lock() 93 defer h.Unlock() 94 95 delete(h.sigHashes, *txid) 96 }