OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / btcsuite / btcd / txscript / hashcache.go
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/btcsuite/btcd/chaincfg/chainhash"
11         "github.com/btcsuite/btcd/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 }