github.com/palcoin-project/palcd@v1.0.0/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/palcoin-project/palcd/chaincfg/chainhash" 11 "github.com/palcoin-project/palcd/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 }