github.com/decred/dcrlnd@v0.7.6/channeldb/witness_cache_test.go (about)

     1  package channeldb
     2  
     3  import (
     4  	"crypto/sha256"
     5  	"testing"
     6  
     7  	"github.com/decred/dcrlnd/lntypes"
     8  )
     9  
    10  // TestWitnessCacheSha256Retrieval tests that we're able to add and lookup new
    11  // sha256 preimages to the witness cache.
    12  func TestWitnessCacheSha256Retrieval(t *testing.T) {
    13  	t.Parallel()
    14  
    15  	cdb, cleanUp, err := MakeTestDB()
    16  	if err != nil {
    17  		t.Fatalf("unable to make test database: %v", err)
    18  	}
    19  	defer cleanUp()
    20  
    21  	wCache := cdb.NewWitnessCache()
    22  
    23  	// We'll be attempting to add then lookup two simple sha256 preimages
    24  	// within this test.
    25  	preimage1 := lntypes.Preimage(rev)
    26  	preimage2 := lntypes.Preimage(key)
    27  
    28  	preimages := []lntypes.Preimage{preimage1, preimage2}
    29  	hashes := []lntypes.Hash{preimage1.Hash(), preimage2.Hash()}
    30  
    31  	// First, we'll attempt to add the preimages to the database.
    32  	err = wCache.AddSha256Witnesses(preimages...)
    33  	if err != nil {
    34  		t.Fatalf("unable to add witness: %v", err)
    35  	}
    36  
    37  	// With the preimages stored, we'll now attempt to look them up.
    38  	for i, hash := range hashes {
    39  		preimage := preimages[i]
    40  
    41  		// We should get back the *exact* same preimage as we originally
    42  		// stored.
    43  		dbPreimage, err := wCache.LookupSha256Witness(hash)
    44  		if err != nil {
    45  			t.Fatalf("unable to look up witness: %v", err)
    46  		}
    47  
    48  		if preimage != dbPreimage {
    49  			t.Fatalf("witnesses don't match: expected %x, got %x",
    50  				preimage[:], dbPreimage[:])
    51  		}
    52  	}
    53  }
    54  
    55  // TestWitnessCacheSha256Deletion tests that we're able to delete a single
    56  // sha256 preimage, and also a class of witnesses from the cache.
    57  func TestWitnessCacheSha256Deletion(t *testing.T) {
    58  	t.Parallel()
    59  
    60  	cdb, cleanUp, err := MakeTestDB()
    61  	if err != nil {
    62  		t.Fatalf("unable to make test database: %v", err)
    63  	}
    64  	defer cleanUp()
    65  
    66  	wCache := cdb.NewWitnessCache()
    67  
    68  	// We'll start by adding two preimages to the cache.
    69  	preimage1 := lntypes.Preimage(key)
    70  	hash1 := preimage1.Hash()
    71  
    72  	preimage2 := lntypes.Preimage(rev)
    73  	hash2 := preimage2.Hash()
    74  
    75  	if err := wCache.AddSha256Witnesses(preimage1); err != nil {
    76  		t.Fatalf("unable to add witness: %v", err)
    77  	}
    78  
    79  	if err := wCache.AddSha256Witnesses(preimage2); err != nil {
    80  		t.Fatalf("unable to add witness: %v", err)
    81  	}
    82  
    83  	// We'll now delete the first preimage. If we attempt to look it up, we
    84  	// should get ErrNoWitnesses.
    85  	err = wCache.DeleteSha256Witness(hash1)
    86  	if err != nil {
    87  		t.Fatalf("unable to delete witness: %v", err)
    88  	}
    89  	_, err = wCache.LookupSha256Witness(hash1)
    90  	if err != ErrNoWitnesses {
    91  		t.Fatalf("expected ErrNoWitnesses instead got: %v", err)
    92  	}
    93  
    94  	// Next, we'll attempt to delete the entire witness class itself. When
    95  	// we try to lookup the second preimage, we should again get
    96  	// ErrNoWitnesses.
    97  	if err := wCache.DeleteWitnessClass(Sha256HashWitness); err != nil {
    98  		t.Fatalf("unable to delete witness class: %v", err)
    99  	}
   100  	_, err = wCache.LookupSha256Witness(hash2)
   101  	if err != ErrNoWitnesses {
   102  		t.Fatalf("expected ErrNoWitnesses instead got: %v", err)
   103  	}
   104  }
   105  
   106  // TestWitnessCacheUnknownWitness tests that we get an error if we attempt to
   107  // query/add/delete an unknown witness.
   108  func TestWitnessCacheUnknownWitness(t *testing.T) {
   109  	t.Parallel()
   110  
   111  	cdb, cleanUp, err := MakeTestDB()
   112  	if err != nil {
   113  		t.Fatalf("unable to make test database: %v", err)
   114  	}
   115  	defer cleanUp()
   116  
   117  	wCache := cdb.NewWitnessCache()
   118  
   119  	// We'll attempt to add a new, undefined witness type to the database.
   120  	// We should get an error.
   121  	err = wCache.legacyAddWitnesses(234, key[:])
   122  	if err != ErrUnknownWitnessType {
   123  		t.Fatalf("expected ErrUnknownWitnessType, got %v", err)
   124  	}
   125  }
   126  
   127  // TestAddSha256Witnesses tests that insertion using AddSha256Witnesses behaves
   128  // identically to the insertion via the generalized interface.
   129  func TestAddSha256Witnesses(t *testing.T) {
   130  	cdb, cleanUp, err := MakeTestDB()
   131  	if err != nil {
   132  		t.Fatalf("unable to make test database: %v", err)
   133  	}
   134  	defer cleanUp()
   135  
   136  	wCache := cdb.NewWitnessCache()
   137  
   138  	// We'll start by adding a witnesses to the cache using the generic
   139  	// AddWitnesses method.
   140  	witness1 := rev[:]
   141  	preimage1 := lntypes.Preimage(rev)
   142  	hash1 := preimage1.Hash()
   143  
   144  	witness2 := key[:]
   145  	preimage2 := lntypes.Preimage(key)
   146  	hash2 := preimage2.Hash()
   147  
   148  	var (
   149  		witnesses = [][]byte{witness1, witness2}
   150  		preimages = []lntypes.Preimage{preimage1, preimage2}
   151  		hashes    = []lntypes.Hash{hash1, hash2}
   152  	)
   153  
   154  	err = wCache.legacyAddWitnesses(Sha256HashWitness, witnesses...)
   155  	if err != nil {
   156  		t.Fatalf("unable to add witness: %v", err)
   157  	}
   158  
   159  	for i, hash := range hashes {
   160  		preimage := preimages[i]
   161  
   162  		dbPreimage, err := wCache.LookupSha256Witness(hash)
   163  		if err != nil {
   164  			t.Fatalf("unable to lookup witness: %v", err)
   165  		}
   166  
   167  		// Assert that the retrieved witness matches the original.
   168  		if dbPreimage != preimage {
   169  			t.Fatalf("retrieved witness mismatch, want: %x, "+
   170  				"got: %x", preimage, dbPreimage)
   171  		}
   172  
   173  		// We'll now delete the witness, as we'll be reinserting it
   174  		// using the specialized AddSha256Witnesses method.
   175  		err = wCache.DeleteSha256Witness(hash)
   176  		if err != nil {
   177  			t.Fatalf("unable to delete witness: %v", err)
   178  		}
   179  	}
   180  
   181  	// Now, add the same witnesses using the type-safe interface for
   182  	// lntypes.Preimages..
   183  	err = wCache.AddSha256Witnesses(preimages...)
   184  	if err != nil {
   185  		t.Fatalf("unable to add chainhash preimage: %v", err)
   186  	}
   187  
   188  	// Finally, iterate over the keys and assert that the returned witnesses
   189  	// match the original witnesses. This asserts that the specialized
   190  	// insertion method behaves identically to the generalized interface.
   191  	for i, hash := range hashes {
   192  		preimage := preimages[i]
   193  
   194  		dbPreimage, err := wCache.LookupSha256Witness(hash)
   195  		if err != nil {
   196  			t.Fatalf("unable to lookup witness: %v", err)
   197  		}
   198  
   199  		// Assert that the retrieved witness matches the original.
   200  		if dbPreimage != preimage {
   201  			t.Fatalf("retrieved witness mismatch, want: %x, "+
   202  				"got: %x", preimage, dbPreimage)
   203  		}
   204  	}
   205  }
   206  
   207  // legacyAddWitnesses adds a batch of new witnesses of wType to the witness
   208  // cache. The type of the witness will be used to map each witness to the key
   209  // that will be used to look it up. All witnesses should be of the same
   210  // WitnessType.
   211  //
   212  // NOTE: Previously this method exposed a generic interface for adding
   213  // witnesses, which has since been deprecated in favor of a strongly typed
   214  // interface for each witness class. We keep this method around to assert the
   215  // correctness of specialized witness adding methods.
   216  func (w *WitnessCache) legacyAddWitnesses(wType WitnessType,
   217  	witnesses ...[]byte) error {
   218  
   219  	// Optimistically compute the witness keys before attempting to start
   220  	// the db transaction.
   221  	entries := make([]witnessEntry, 0, len(witnesses))
   222  	for _, witness := range witnesses {
   223  		// Map each witness to its key by applying the appropriate
   224  		// transformation for the given witness type.
   225  		switch wType {
   226  		case Sha256HashWitness:
   227  			key := sha256.Sum256(witness)
   228  			entries = append(entries, witnessEntry{
   229  				key:     key[:],
   230  				witness: witness,
   231  			})
   232  		default:
   233  			return ErrUnknownWitnessType
   234  		}
   235  	}
   236  
   237  	return w.addWitnessEntries(wType, entries)
   238  }