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  }