1 package txscript
2 3 import (
4 "math/rand"
5 "testing"
6 "time"
7 8 "github.com/davecgh/go-spew/spew"
9 10 "github.com/p9c/p9/pkg/wire"
11 )
12 13 // genTestTx creates a random transaction for uses within test cases.
14 func genTestTx() (*wire.MsgTx, error) {
15 tx := wire.NewMsgTx(2)
16 tx.Version = rand.Int31()
17 numTxins := rand.Intn(11)
18 for i := 0; i < numTxins; i++ {
19 randTxIn := wire.TxIn{
20 PreviousOutPoint: wire.OutPoint{
21 Index: uint32(rand.Int31()),
22 },
23 Sequence: uint32(rand.Int31()),
24 }
25 _, e := rand.Read(randTxIn.PreviousOutPoint.Hash[:])
26 if e != nil {
27 return nil, e
28 }
29 tx.TxIn = append(tx.TxIn, &randTxIn)
30 }
31 numTxouts := rand.Intn(11)
32 for i := 0; i < numTxouts; i++ {
33 randTxOut := wire.TxOut{
34 Value: rand.Int63(),
35 PkScript: make([]byte, rand.Intn(30)),
36 }
37 var e error
38 if _, e = rand.Read(randTxOut.PkScript); E.Chk(e) {
39 return nil, e
40 }
41 tx.TxOut = append(tx.TxOut, &randTxOut)
42 }
43 return tx, nil
44 }
45 46 // TestHashCacheAddContainsHashes tests that after items have been added to the hash cache, the ContainsHashes method
47 // returns true for all the items inserted. Conversely, ContainsHashes should return false for any items _not_ in the
48 // hash cache.
49 func TestHashCacheAddContainsHashes(t *testing.T) {
50 t.Parallel()
51 rand.Seed(time.Now().Unix())
52 cache := NewHashCache(10)
53 var e error
54 // First, we'll generate 10 random transactions for use within our tests.
55 const numTxns = 10
56 txns := make([]*wire.MsgTx, numTxns)
57 for i := 0; i < numTxns; i++ {
58 txns[i], e = genTestTx()
59 if e != nil {
60 t.Fatalf("unable to generate test tx: %v", e)
61 }
62 }
63 // With the transactions generated, we'll add each of them to the hash cache.
64 for _, tx := range txns {
65 cache.AddSigHashes(tx)
66 }
67 // Next, we'll ensure that each of the transactions inserted into the cache are properly located by the
68 // ContainsHashes method.
69 for _, tx := range txns {
70 txid := tx.TxHash()
71 if ok := cache.ContainsHashes(&txid); !ok {
72 t.Fatalf("txid %v not found in cache but should be: ",
73 txid,
74 )
75 }
76 }
77 randTx, e := genTestTx()
78 if e != nil {
79 t.Fatalf("unable to generate tx: %v", e)
80 }
81 // Finally, we'll assert that a transaction that wasn't added to the cache won't be reported as being present by the
82 // ContainsHashes method.
83 randTxid := randTx.TxHash()
84 if ok := cache.ContainsHashes(&randTxid); ok {
85 t.Fatalf("txid %v wasn't inserted into cache but was found",
86 randTxid,
87 )
88 }
89 }
90 91 // TestHashCacheAddGet tests that the sighashes for a particular transaction are properly retrieved by the GetSigHashes
92 // function.
93 func TestHashCacheAddGet(t *testing.T) {
94 t.Parallel()
95 rand.Seed(time.Now().Unix())
96 cache := NewHashCache(10)
97 // To start, we'll generate a random transaction and compute the set of sighashes for the transaction.
98 randTx, e := genTestTx()
99 if e != nil {
100 t.Fatalf("unable to generate tx: %v", e)
101 }
102 sigHashes := NewTxSigHashes(randTx)
103 // Next, add the transaction to the hash cache.
104 cache.AddSigHashes(randTx)
105 // The transaction inserted into the cache above should be found.
106 txid := randTx.TxHash()
107 cacheHashes, ok := cache.GetSigHashes(&txid)
108 if !ok {
109 t.Fatalf("tx %v wasn't found in cache", txid)
110 }
111 // Finally, the sighashes retrieved should exactly match the sighash originally inserted into the cache.
112 if *sigHashes != *cacheHashes {
113 t.Fatalf("sighashes don't match: expected %v, got %v",
114 spew.Sdump(sigHashes), spew.Sdump(cacheHashes),
115 )
116 }
117 }
118 119 // TestHashCachePurge tests that items are able to be properly removed from the hash cache.
120 func TestHashCachePurge(t *testing.T) {
121 t.Parallel()
122 rand.Seed(time.Now().Unix())
123 cache := NewHashCache(10)
124 var e error
125 // First we'll start by inserting numTxns transactions into the hash cache.
126 const numTxns = 10
127 txns := make([]*wire.MsgTx, numTxns)
128 for i := 0; i < numTxns; i++ {
129 txns[i], e = genTestTx()
130 if e != nil {
131 t.Fatalf("unable to generate test tx: %v", e)
132 }
133 }
134 for _, tx := range txns {
135 cache.AddSigHashes(tx)
136 }
137 // Once all the transactions have been inserted, we'll purge them from the hash cache.
138 for _, tx := range txns {
139 txid := tx.TxHash()
140 cache.PurgeSigHashes(&txid)
141 }
142 // At this point, none of the transactions inserted into the hash cache should be found within the cache.
143 for _, tx := range txns {
144 txid := tx.TxHash()
145 if ok := cache.ContainsHashes(&txid); ok {
146 t.Fatalf("tx %v found in cache but should have "+
147 "been purged: ", txid,
148 )
149 }
150 }
151 }
152