github.com/btcsuite/btcd@v0.24.0/txscript/sigcache_test.go (about) 1 // Copyright (c) 2015-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 "crypto/rand" 9 "testing" 10 11 "github.com/btcsuite/btcd/btcec/v2" 12 "github.com/btcsuite/btcd/btcec/v2/ecdsa" 13 "github.com/btcsuite/btcd/chaincfg/chainhash" 14 ) 15 16 // genRandomSig returns a random message, a signature of the message under the 17 // public key and the public key. This function is used to generate randomized 18 // test data. 19 func genRandomSig() (*chainhash.Hash, *ecdsa.Signature, *btcec.PublicKey, error) { 20 privKey, err := btcec.NewPrivateKey() 21 if err != nil { 22 return nil, nil, nil, err 23 } 24 25 var msgHash chainhash.Hash 26 if _, err := rand.Read(msgHash[:]); err != nil { 27 return nil, nil, nil, err 28 } 29 30 sig := ecdsa.Sign(privKey, msgHash[:]) 31 32 return &msgHash, sig, privKey.PubKey(), nil 33 } 34 35 // TestSigCacheAddExists tests the ability to add, and later check the 36 // existence of a signature triplet in the signature cache. 37 func TestSigCacheAddExists(t *testing.T) { 38 sigCache := NewSigCache(200) 39 40 // Generate a random sigCache entry triplet. 41 msg1, sig1, key1, err := genRandomSig() 42 if err != nil { 43 t.Errorf("unable to generate random signature test data") 44 } 45 46 // Add the triplet to the signature cache. 47 sigCache.Add(*msg1, sig1.Serialize(), key1.SerializeCompressed()) 48 49 // The previously added triplet should now be found within the sigcache. 50 sig1Copy, _ := ecdsa.ParseSignature(sig1.Serialize()) 51 key1Copy, _ := btcec.ParsePubKey(key1.SerializeCompressed()) 52 if !sigCache.Exists(*msg1, sig1Copy.Serialize(), key1Copy.SerializeCompressed()) { 53 t.Errorf("previously added item not found in signature cache") 54 } 55 } 56 57 // TestSigCacheAddEvictEntry tests the eviction case where a new signature 58 // triplet is added to a full signature cache which should trigger randomized 59 // eviction, followed by adding the new element to the cache. 60 func TestSigCacheAddEvictEntry(t *testing.T) { 61 // Create a sigcache that can hold up to 100 entries. 62 sigCacheSize := uint(100) 63 sigCache := NewSigCache(sigCacheSize) 64 65 // Fill the sigcache up with some random sig triplets. 66 for i := uint(0); i < sigCacheSize; i++ { 67 msg, sig, key, err := genRandomSig() 68 if err != nil { 69 t.Fatalf("unable to generate random signature test data") 70 } 71 72 sigCache.Add(*msg, sig.Serialize(), key.SerializeCompressed()) 73 74 sigCopy, err := ecdsa.ParseSignature(sig.Serialize()) 75 if err != nil { 76 t.Fatalf("unable to parse sig: %v", err) 77 } 78 keyCopy, err := btcec.ParsePubKey(key.SerializeCompressed()) 79 if err != nil { 80 t.Fatalf("unable to parse key: %v", err) 81 } 82 if !sigCache.Exists(*msg, sigCopy.Serialize(), keyCopy.SerializeCompressed()) { 83 t.Errorf("previously added item not found in signature" + 84 "cache") 85 } 86 } 87 88 // The sigcache should now have sigCacheSize entries within it. 89 if uint(len(sigCache.validSigs)) != sigCacheSize { 90 t.Fatalf("sigcache should now have %v entries, instead it has %v", 91 sigCacheSize, len(sigCache.validSigs)) 92 } 93 94 // Add a new entry, this should cause eviction of a randomly chosen 95 // previous entry. 96 msgNew, sigNew, keyNew, err := genRandomSig() 97 if err != nil { 98 t.Fatalf("unable to generate random signature test data") 99 } 100 sigCache.Add(*msgNew, sigNew.Serialize(), keyNew.SerializeCompressed()) 101 102 // The sigcache should still have sigCache entries. 103 if uint(len(sigCache.validSigs)) != sigCacheSize { 104 t.Fatalf("sigcache should now have %v entries, instead it has %v", 105 sigCacheSize, len(sigCache.validSigs)) 106 } 107 108 // The entry added above should be found within the sigcache. 109 sigNewCopy, _ := ecdsa.ParseSignature(sigNew.Serialize()) 110 keyNewCopy, _ := btcec.ParsePubKey(keyNew.SerializeCompressed()) 111 if !sigCache.Exists(*msgNew, sigNewCopy.Serialize(), keyNewCopy.SerializeCompressed()) { 112 t.Fatalf("previously added item not found in signature cache") 113 } 114 } 115 116 // TestSigCacheAddMaxEntriesZeroOrNegative tests that if a sigCache is created 117 // with a max size <= 0, then no entries are added to the sigcache at all. 118 func TestSigCacheAddMaxEntriesZeroOrNegative(t *testing.T) { 119 // Create a sigcache that can hold up to 0 entries. 120 sigCache := NewSigCache(0) 121 122 // Generate a random sigCache entry triplet. 123 msg1, sig1, key1, err := genRandomSig() 124 if err != nil { 125 t.Errorf("unable to generate random signature test data") 126 } 127 128 // Add the triplet to the signature cache. 129 sigCache.Add(*msg1, sig1.Serialize(), key1.SerializeCompressed()) 130 131 // The generated triplet should not be found. 132 sig1Copy, _ := ecdsa.ParseSignature(sig1.Serialize()) 133 key1Copy, _ := btcec.ParsePubKey(key1.SerializeCompressed()) 134 if sigCache.Exists(*msg1, sig1Copy.Serialize(), key1Copy.SerializeCompressed()) { 135 t.Errorf("previously added signature found in sigcache, but" + 136 "shouldn't have been") 137 } 138 139 // There shouldn't be any entries in the sigCache. 140 if len(sigCache.validSigs) != 0 { 141 t.Errorf("%v items found in sigcache, no items should have"+ 142 "been added", len(sigCache.validSigs)) 143 } 144 }