github.com/decred/dcrd/blockchain@v1.2.1/compress_test.go (about)

     1  // Copyright (c) 2015-2016 The Decred 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 blockchain
     6  
     7  import (
     8  	"bytes"
     9  	"encoding/hex"
    10  	"testing"
    11  )
    12  
    13  // hexToBytes converts the passed hex string into bytes and will panic if there
    14  // is an error.  This is only provided for the hard-coded constants so errors in
    15  // the source code can be detected. It will only (and must only) be called with
    16  // hard-coded values.
    17  func hexToBytes(s string) []byte {
    18  	b, err := hex.DecodeString(s)
    19  	if err != nil {
    20  		panic("invalid hex in source file: " + s)
    21  	}
    22  	return b
    23  }
    24  
    25  // TestVLQ ensures the variable length quantity serialization, deserialization,
    26  // and size calculation works as expected.
    27  func TestVLQ(t *testing.T) {
    28  	t.Parallel()
    29  
    30  	tests := []struct {
    31  		val        uint64
    32  		serialized []byte
    33  	}{
    34  		{0, hexToBytes("00")},
    35  		{1, hexToBytes("01")},
    36  		{127, hexToBytes("7f")},
    37  		{128, hexToBytes("8000")},
    38  		{129, hexToBytes("8001")},
    39  		{255, hexToBytes("807f")},
    40  		{256, hexToBytes("8100")},
    41  		{16383, hexToBytes("fe7f")},
    42  		{16384, hexToBytes("ff00")},
    43  		{16511, hexToBytes("ff7f")}, // Max 2-byte value
    44  		{16512, hexToBytes("808000")},
    45  		{16513, hexToBytes("808001")},
    46  		{16639, hexToBytes("80807f")},
    47  		{32895, hexToBytes("80ff7f")},
    48  		{2113663, hexToBytes("ffff7f")}, // Max 3-byte value
    49  		{2113664, hexToBytes("80808000")},
    50  		{270549119, hexToBytes("ffffff7f")}, // Max 4-byte value
    51  		{270549120, hexToBytes("8080808000")},
    52  		{2147483647, hexToBytes("86fefefe7f")},
    53  		{2147483648, hexToBytes("86fefeff00")},
    54  		{4294967295, hexToBytes("8efefefe7f")}, // Max uint32, 5 bytes
    55  	}
    56  
    57  	for _, test := range tests {
    58  		// Ensure the function to calculate the serialized size without
    59  		// actually serializing the value is calculated properly.
    60  		gotSize := serializeSizeVLQ(test.val)
    61  		if gotSize != len(test.serialized) {
    62  			t.Errorf("serializeSizeVLQ: did not get expected size "+
    63  				"for %d - got %d, want %d", test.val, gotSize,
    64  				len(test.serialized))
    65  			continue
    66  		}
    67  
    68  		// Ensure the value serializes to the expected bytes.
    69  		gotBytes := make([]byte, gotSize)
    70  		gotBytesWritten := putVLQ(gotBytes, test.val)
    71  		if !bytes.Equal(gotBytes, test.serialized) {
    72  			t.Errorf("putVLQUnchecked: did not get expected bytes "+
    73  				"for %d - got %x, want %x", test.val, gotBytes,
    74  				test.serialized)
    75  			continue
    76  		}
    77  		if gotBytesWritten != len(test.serialized) {
    78  			t.Errorf("putVLQUnchecked: did not get expected number "+
    79  				"of bytes written for %d - got %d, want %d",
    80  				test.val, gotBytesWritten, len(test.serialized))
    81  			continue
    82  		}
    83  
    84  		// Ensure the serialized bytes deserialize to the expected
    85  		// value.
    86  		gotVal, gotBytesRead := deserializeVLQ(test.serialized)
    87  		if gotVal != test.val {
    88  			t.Errorf("deserializeVLQ: did not get expected value "+
    89  				"for %x - got %d, want %d", test.serialized,
    90  				gotVal, test.val)
    91  			continue
    92  		}
    93  		if gotBytesRead != len(test.serialized) {
    94  			t.Errorf("deserializeVLQ: did not get expected number "+
    95  				"of bytes read for %d - got %d, want %d",
    96  				test.serialized, gotBytesRead,
    97  				len(test.serialized))
    98  			continue
    99  		}
   100  	}
   101  }
   102  
   103  // TestScriptCompression ensures the domain-specific script compression and
   104  // decompression works as expected.
   105  func TestScriptCompression(t *testing.T) {
   106  	t.Parallel()
   107  
   108  	tests := []struct {
   109  		name          string
   110  		version       uint32
   111  		scriptVersion uint16
   112  		uncompressed  []byte
   113  		compressed    []byte
   114  	}{
   115  		{
   116  			name:          "nil",
   117  			version:       1,
   118  			scriptVersion: 0,
   119  			uncompressed:  nil,
   120  			compressed:    hexToBytes("40"),
   121  		},
   122  		{
   123  			name:          "pay-to-pubkey-hash 1",
   124  			version:       1,
   125  			scriptVersion: 0,
   126  			uncompressed:  hexToBytes("76a9141018853670f9f3b0582c5b9ee8ce93764ac32b9388ac"),
   127  			compressed:    hexToBytes("001018853670f9f3b0582c5b9ee8ce93764ac32b93"),
   128  		},
   129  		{
   130  			name:          "pay-to-pubkey-hash 2",
   131  			version:       1,
   132  			scriptVersion: 0,
   133  			uncompressed:  hexToBytes("76a914e34cce70c86373273efcc54ce7d2a491bb4a0e8488ac"),
   134  			compressed:    hexToBytes("00e34cce70c86373273efcc54ce7d2a491bb4a0e84"),
   135  		},
   136  		{
   137  			name:          "pay-to-script-hash 1",
   138  			version:       1,
   139  			scriptVersion: 0,
   140  			uncompressed:  hexToBytes("a914da1745e9b549bd0bfa1a569971c77eba30cd5a4b87"),
   141  			compressed:    hexToBytes("01da1745e9b549bd0bfa1a569971c77eba30cd5a4b"),
   142  		},
   143  		{
   144  			name:          "pay-to-script-hash 2",
   145  			version:       1,
   146  			scriptVersion: 0,
   147  			uncompressed:  hexToBytes("a914f815b036d9bbbce5e9f2a00abd1bf3dc91e9551087"),
   148  			compressed:    hexToBytes("01f815b036d9bbbce5e9f2a00abd1bf3dc91e95510"),
   149  		},
   150  		{
   151  			name:          "pay-to-pubkey compressed 0x02",
   152  			version:       1,
   153  			scriptVersion: 0,
   154  			uncompressed:  hexToBytes("2102192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4ac"),
   155  			compressed:    hexToBytes("02192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4"),
   156  		},
   157  		{
   158  			name:          "pay-to-pubkey compressed 0x03",
   159  			version:       1,
   160  			scriptVersion: 0,
   161  			uncompressed:  hexToBytes("2103b0bd634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e65ac"),
   162  			compressed:    hexToBytes("03b0bd634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e65"),
   163  		},
   164  		{
   165  			name:          "pay-to-pubkey uncompressed 0x04 even",
   166  			version:       1,
   167  			scriptVersion: 0,
   168  			uncompressed:  hexToBytes("4104192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b40d45264838c0bd96852662ce6a847b197376830160c6d2eb5e6a4c44d33f453eac"),
   169  			compressed:    hexToBytes("04192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4"),
   170  		},
   171  		{
   172  			name:          "pay-to-pubkey uncompressed 0x04 odd",
   173  			version:       1,
   174  			scriptVersion: 0,
   175  			uncompressed:  hexToBytes("410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac"),
   176  			compressed:    hexToBytes("0511db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c"),
   177  		},
   178  		{
   179  			name:          "pay-to-pubkey invalid pubkey",
   180  			version:       1,
   181  			scriptVersion: 0,
   182  			uncompressed:  hexToBytes("3302aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac"),
   183  			compressed:    hexToBytes("633302aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac"),
   184  		},
   185  		{
   186  			name:          "null data",
   187  			version:       1,
   188  			scriptVersion: 0,
   189  			uncompressed:  hexToBytes("6a200102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"),
   190  			compressed:    hexToBytes("626a200102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"),
   191  		},
   192  		{
   193  			name:          "requires 2 size bytes - data push 200 bytes",
   194  			version:       1,
   195  			scriptVersion: 0,
   196  			uncompressed:  append(hexToBytes("4cc8"), bytes.Repeat([]byte{0x00}, 200)...),
   197  			// [0x80, 0x50] = 208 as a variable length quantity
   198  			// [0x4c, 0xc8] = OP_PUSHDATA1 200
   199  			compressed: append(hexToBytes("810a4cc8"), bytes.Repeat([]byte{0x00}, 200)...),
   200  		},
   201  	}
   202  
   203  	for _, test := range tests {
   204  		// Ensure the function to calculate the serialized size without
   205  		// actually serializing the value is calculated properly.
   206  		gotSize := compressedScriptSize(test.scriptVersion, test.uncompressed,
   207  			test.version)
   208  		if gotSize != len(test.compressed) {
   209  			t.Errorf("compressedScriptSize (%s): did not get "+
   210  				"expected size - got %d, want %d", test.name,
   211  				gotSize, len(test.compressed))
   212  			continue
   213  		}
   214  
   215  		// Ensure the script compresses to the expected bytes.
   216  		gotCompressed := make([]byte, gotSize)
   217  		gotBytesWritten := putCompressedScript(gotCompressed, test.scriptVersion,
   218  			test.uncompressed, test.version)
   219  		if !bytes.Equal(gotCompressed, test.compressed) {
   220  			t.Errorf("putCompressedScript (%s): did not get "+
   221  				"expected bytes - got %x, want %x", test.name,
   222  				gotCompressed, test.compressed)
   223  			continue
   224  		}
   225  		if gotBytesWritten != len(test.compressed) {
   226  			t.Errorf("putCompressedScript (%s): did not get "+
   227  				"expected number of bytes written - got %d, "+
   228  				"want %d", test.name, gotBytesWritten,
   229  				len(test.compressed))
   230  			continue
   231  		}
   232  
   233  		// Ensure the compressed script size is properly decoded from
   234  		// the compressed script.
   235  		gotDecodedSize := decodeCompressedScriptSize(test.compressed,
   236  			test.version)
   237  		if gotDecodedSize != len(test.compressed) {
   238  			t.Errorf("decodeCompressedScriptSize (%s): did not get "+
   239  				"expected size - got %d, want %d", test.name,
   240  				gotDecodedSize, len(test.compressed))
   241  			continue
   242  		}
   243  
   244  		// Ensure the script decompresses to the expected bytes.
   245  		gotDecompressed := decompressScript(test.compressed, test.version)
   246  		if !bytes.Equal(gotDecompressed, test.uncompressed) {
   247  			t.Errorf("decompressScript (%s): did not get expected "+
   248  				"bytes - got %x, want %x", test.name,
   249  				gotDecompressed, test.uncompressed)
   250  			continue
   251  		}
   252  	}
   253  }
   254  
   255  // TestScriptCompressionErrors ensures calling various functions related to
   256  // script compression with incorrect data returns the expected results.
   257  func TestScriptCompressionErrors(t *testing.T) {
   258  	t.Parallel()
   259  
   260  	// A nil script must result in a decoded size of 0.
   261  	if gotSize := decodeCompressedScriptSize(nil, 1); gotSize != 0 {
   262  		t.Fatalf("decodeCompressedScriptSize with nil script did not "+
   263  			"return 0 - got %d", gotSize)
   264  	}
   265  
   266  	// A nil script must result in a nil decompressed script.
   267  	if gotScript := decompressScript(nil, 1); gotScript != nil {
   268  		t.Fatalf("decompressScript with nil script did not return nil "+
   269  			"decompressed script - got %x", gotScript)
   270  	}
   271  
   272  	// A compressed script for a pay-to-pubkey (uncompressed) that results
   273  	// in an invalid pubkey must result in a nil decompressed script.
   274  	compressedScript := hexToBytes("04012d74d0cb94344c9569c2e77901573d8d" +
   275  		"7903c3ebec3a957724895dca52c6b4")
   276  	if gotScript := decompressScript(compressedScript, 1); gotScript != nil {
   277  		t.Fatalf("decompressScript with compressed pay-to-"+
   278  			"uncompressed-pubkey that is invalid did not return "+
   279  			"nil decompressed script - got %x", gotScript)
   280  	}
   281  }
   282  
   283  // TestAmountCompression ensures the domain-specific transaction output amount
   284  // compression and decompression works as expected.
   285  func TestAmountCompression(t *testing.T) {
   286  	t.Parallel()
   287  
   288  	tests := []struct {
   289  		name         string
   290  		uncompressed uint64
   291  		compressed   uint64
   292  	}{
   293  		{
   294  			name:         "0 DCR (sometimes used in nulldata)",
   295  			uncompressed: 0,
   296  			compressed:   0,
   297  		},
   298  		{
   299  			name:         "546 atoms (current network dust value)",
   300  			uncompressed: 546,
   301  			compressed:   4911,
   302  		},
   303  		{
   304  			name:         "0.00001 DCR (typical transaction fee)",
   305  			uncompressed: 1000,
   306  			compressed:   4,
   307  		},
   308  		{
   309  			name:         "0.0001 DCR (typical transaction fee)",
   310  			uncompressed: 10000,
   311  			compressed:   5,
   312  		},
   313  		{
   314  			name:         "0.12345678 DCR",
   315  			uncompressed: 12345678,
   316  			compressed:   111111101,
   317  		},
   318  		{
   319  			name:         "0.5 DCR",
   320  			uncompressed: 50000000,
   321  			compressed:   48,
   322  		},
   323  		{
   324  			name:         "1 DCR",
   325  			uncompressed: 100000000,
   326  			compressed:   9,
   327  		},
   328  		{
   329  			name:         "5 DCR",
   330  			uncompressed: 500000000,
   331  			compressed:   49,
   332  		},
   333  		{
   334  			name:         "21000000 DCR (max minted coins)",
   335  			uncompressed: 2100000000000000,
   336  			compressed:   21000000,
   337  		},
   338  	}
   339  
   340  	for _, test := range tests {
   341  		// Ensure the amount compresses to the expected value.
   342  		gotCompressed := compressTxOutAmount(test.uncompressed)
   343  		if gotCompressed != test.compressed {
   344  			t.Errorf("compressTxOutAmount (%s): did not get "+
   345  				"expected value - got %d, want %d", test.name,
   346  				gotCompressed, test.compressed)
   347  			continue
   348  		}
   349  
   350  		// Ensure the value decompresses to the expected value.
   351  		gotDecompressed := decompressTxOutAmount(test.compressed)
   352  		if gotDecompressed != test.uncompressed {
   353  			t.Errorf("decompressTxOutAmount (%s): did not get "+
   354  				"expected value - got %d, want %d", test.name,
   355  				gotDecompressed, test.uncompressed)
   356  			continue
   357  		}
   358  	}
   359  }
   360  
   361  // TestCompressedTxOut ensures the transaction output serialization and
   362  // deserialization works as expected.
   363  func TestCompressedTxOut(t *testing.T) {
   364  	t.Parallel()
   365  
   366  	tests := []struct {
   367  		name          string
   368  		amount        uint64
   369  		scriptVersion uint16
   370  		pkScript      []byte
   371  		compPkScript  []byte
   372  		version       uint32
   373  		compressed    []byte
   374  		hasAmount     bool
   375  		isCompressed  bool
   376  	}{
   377  		{
   378  			name:          "nulldata with 0 DCR",
   379  			amount:        0,
   380  			scriptVersion: 0,
   381  			pkScript:      hexToBytes("6a200102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"),
   382  			compPkScript:  hexToBytes("626a200102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"),
   383  			version:       1,
   384  			compressed:    hexToBytes("00626a200102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"),
   385  			hasAmount:     false,
   386  			isCompressed:  false,
   387  		},
   388  		{
   389  			name:          "pay-to-pubkey-hash dust, no amount",
   390  			amount:        0,
   391  			scriptVersion: 0,
   392  			pkScript:      hexToBytes("76a9141018853670f9f3b0582c5b9ee8ce93764ac32b9388ac"),
   393  			compPkScript:  hexToBytes("001018853670f9f3b0582c5b9ee8ce93764ac32b93"),
   394  			version:       1,
   395  			compressed:    hexToBytes("00001018853670f9f3b0582c5b9ee8ce93764ac32b93"),
   396  			hasAmount:     false,
   397  			isCompressed:  false,
   398  		},
   399  		{
   400  			name:          "pay-to-pubkey-hash dust, no amount, precompressed",
   401  			amount:        0,
   402  			scriptVersion: 0,
   403  			pkScript:      hexToBytes("001018853670f9f3b0582c5b9ee8ce93764ac32b93"),
   404  			compPkScript:  hexToBytes("001018853670f9f3b0582c5b9ee8ce93764ac32b93"),
   405  			version:       1,
   406  			compressed:    hexToBytes("00001018853670f9f3b0582c5b9ee8ce93764ac32b93"),
   407  			hasAmount:     false,
   408  			isCompressed:  true,
   409  		},
   410  		{
   411  			name:          "pay-to-pubkey-hash dust, amount",
   412  			amount:        546,
   413  			scriptVersion: 0,
   414  			pkScript:      hexToBytes("76a9141018853670f9f3b0582c5b9ee8ce93764ac32b9388ac"),
   415  			compPkScript:  hexToBytes("001018853670f9f3b0582c5b9ee8ce93764ac32b93"),
   416  			version:       1,
   417  			compressed:    hexToBytes("a52f00001018853670f9f3b0582c5b9ee8ce93764ac32b93"),
   418  			hasAmount:     true,
   419  			isCompressed:  false,
   420  		},
   421  		{
   422  			name:          "pay-to-pubkey-hash dust, amount, precompressed",
   423  			amount:        546,
   424  			scriptVersion: 0,
   425  			pkScript:      hexToBytes("001018853670f9f3b0582c5b9ee8ce93764ac32b93"),
   426  			compPkScript:  hexToBytes("001018853670f9f3b0582c5b9ee8ce93764ac32b93"),
   427  			version:       1,
   428  			compressed:    hexToBytes("a52f00001018853670f9f3b0582c5b9ee8ce93764ac32b93"),
   429  			hasAmount:     true,
   430  			isCompressed:  true,
   431  		},
   432  		{
   433  			name:          "pay-to-pubkey uncompressed, no amount",
   434  			amount:        0,
   435  			scriptVersion: 0,
   436  			pkScript:      hexToBytes("4104192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b40d45264838c0bd96852662ce6a847b197376830160c6d2eb5e6a4c44d33f453eac"),
   437  			compPkScript:  hexToBytes("04192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4"),
   438  			version:       1,
   439  			compressed:    hexToBytes("0004192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4"),
   440  			hasAmount:     false,
   441  			isCompressed:  false,
   442  		},
   443  		{
   444  			name:          "pay-to-pubkey uncompressed 1 DCR, amount present",
   445  			amount:        100000000,
   446  			scriptVersion: 0,
   447  			pkScript:      hexToBytes("4104192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b40d45264838c0bd96852662ce6a847b197376830160c6d2eb5e6a4c44d33f453eac"),
   448  			compPkScript:  hexToBytes("04192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4"),
   449  			version:       1,
   450  			compressed:    hexToBytes("090004192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4"),
   451  			hasAmount:     true,
   452  			isCompressed:  false,
   453  		},
   454  	}
   455  
   456  	for _, test := range tests {
   457  		targetSz := compressedTxOutSize(0, test.scriptVersion, test.pkScript, currentCompressionVersion, test.isCompressed, test.hasAmount) - 1
   458  		target := make([]byte, targetSz)
   459  		putCompressedScript(target, test.scriptVersion, test.pkScript, currentCompressionVersion)
   460  
   461  		// Ensure the function to calculate the serialized size without
   462  		// actually serializing the txout is calculated properly.
   463  		gotSize := compressedTxOutSize(test.amount, test.scriptVersion,
   464  			test.pkScript, test.version, test.isCompressed, test.hasAmount)
   465  		if gotSize != len(test.compressed) {
   466  			t.Errorf("compressedTxOutSize (%s): did not get "+
   467  				"expected size - got %d, want %d", test.name,
   468  				gotSize, len(test.compressed))
   469  			continue
   470  		}
   471  
   472  		// Ensure the txout compresses to the expected value.
   473  		gotCompressed := make([]byte, gotSize)
   474  		gotBytesWritten := putCompressedTxOut(gotCompressed,
   475  			test.amount, test.scriptVersion, test.pkScript,
   476  			test.version, test.isCompressed, test.hasAmount)
   477  		if !bytes.Equal(gotCompressed, test.compressed) {
   478  			t.Errorf("compressTxOut (%s): did not get expected "+
   479  				"bytes - got %x, want %x", test.name,
   480  				gotCompressed, test.compressed)
   481  			continue
   482  		}
   483  		if gotBytesWritten != len(test.compressed) {
   484  			t.Errorf("compressTxOut (%s): did not get expected "+
   485  				"number of bytes written - got %d, want %d",
   486  				test.name, gotBytesWritten,
   487  				len(test.compressed))
   488  			continue
   489  		}
   490  
   491  		// Ensure the serialized bytes are decoded back to the expected
   492  		// compressed values.
   493  		gotAmount, gotScrVersion, gotScript, gotBytesRead, err :=
   494  			decodeCompressedTxOut(test.compressed, test.version,
   495  				test.hasAmount)
   496  		if err != nil {
   497  			t.Errorf("decodeCompressedTxOut (%s): unexpected "+
   498  				"error: %v", test.name, err)
   499  			continue
   500  		}
   501  		if gotAmount != int64(test.amount) {
   502  			t.Errorf("decodeCompressedTxOut (%s): did not get "+
   503  				"expected amount - got %d, want %d",
   504  				test.name, gotAmount, test.amount)
   505  			continue
   506  		}
   507  		if gotScrVersion != test.scriptVersion {
   508  			t.Errorf("decodeCompressedTxOut (%s): did not get "+
   509  				"expected script version - got %d, want %d",
   510  				test.name, gotScrVersion, test.scriptVersion)
   511  			continue
   512  		}
   513  		if !bytes.Equal(gotScript, test.compPkScript) {
   514  			t.Errorf("decodeCompressedTxOut (%s): did not get "+
   515  				"expected script - got %x, want %x",
   516  				test.name, gotScript, test.compPkScript)
   517  			continue
   518  		}
   519  		if gotBytesRead != len(test.compressed) {
   520  			t.Errorf("decodeCompressedTxOut (%s): did not get "+
   521  				"expected number of bytes read - got %d, want %d",
   522  				test.name, gotBytesRead, len(test.compressed))
   523  			continue
   524  		}
   525  
   526  		// Ensure the compressed values decompress to the expected
   527  		// txout.
   528  		gotScript = decompressScript(gotScript, test.version)
   529  		localScript := make([]byte, len(test.pkScript))
   530  		copy(localScript, test.pkScript)
   531  		if test.isCompressed {
   532  			localScript = decompressScript(localScript, test.version)
   533  		}
   534  		if !bytes.Equal(gotScript, localScript) {
   535  			t.Errorf("decompressTxOut (%s): did not get expected "+
   536  				"script - got %x, want %x", test.name,
   537  				gotScript, test.pkScript)
   538  			continue
   539  		}
   540  	}
   541  }
   542  
   543  // TestTxOutCompressionErrors ensures calling various functions related to
   544  // txout compression with incorrect data returns the expected results.
   545  func TestTxOutCompressionErrors(t *testing.T) {
   546  	t.Parallel()
   547  
   548  	// A compressed txout with a value and missing compressed script must error.
   549  	compressedTxOut := hexToBytes("00")
   550  	_, _, _, _, err := decodeCompressedTxOut(compressedTxOut, 1, true)
   551  	if !isDeserializeErr(err) {
   552  		t.Fatalf("decodeCompressedTxOut with value and missing "+
   553  			"compressed script did not return expected error type "+
   554  			"- got %T, want errDeserialize", err)
   555  	}
   556  
   557  	// A compressed txout without a value and with an empty compressed
   558  	// script returns empty but is valid.
   559  	compressedTxOut = hexToBytes("00")
   560  	_, _, _, _, err = decodeCompressedTxOut(compressedTxOut, 1, false)
   561  	if err != nil {
   562  		t.Fatalf("decodeCompressedTxOut with missing compressed script "+
   563  			"did not return expected error type - got %T, want "+
   564  			"errDeserialize", err)
   565  	}
   566  
   567  	// A compressed txout with short compressed script must error.
   568  	compressedTxOut = hexToBytes("0010")
   569  	_, _, _, _, err = decodeCompressedTxOut(compressedTxOut, 1, false)
   570  	if !isDeserializeErr(err) {
   571  		t.Fatalf("decodeCompressedTxOut with short compressed script "+
   572  			"did not return expected error type - got %T, want "+
   573  			"errDeserialize", err)
   574  	}
   575  }