hashcache.go 2.8 KB

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