github.com/lbryio/lbcd@v0.22.119/txscript/script_test.go (about)

     1  // Copyright (c) 2013-2017 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  	"bytes"
     9  	"reflect"
    10  	"testing"
    11  
    12  	"github.com/lbryio/lbcd/wire"
    13  )
    14  
    15  // TestPushedData ensured the PushedData function extracts the expected data out
    16  // of various scripts.
    17  func TestPushedData(t *testing.T) {
    18  	t.Parallel()
    19  
    20  	var tests = []struct {
    21  		script string
    22  		out    [][]byte
    23  		valid  bool
    24  	}{
    25  		{
    26  			"0 IF 0 ELSE 2 ENDIF",
    27  			[][]byte{nil, nil},
    28  			true,
    29  		},
    30  		{
    31  			"16777216 10000000",
    32  			[][]byte{
    33  				{0x00, 0x00, 0x00, 0x01}, // 16777216
    34  				{0x80, 0x96, 0x98, 0x00}, // 10000000
    35  			},
    36  			true,
    37  		},
    38  		{
    39  			"DUP HASH160 '17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem' EQUALVERIFY CHECKSIG",
    40  			[][]byte{
    41  				// 17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem
    42  				{
    43  					0x31, 0x37, 0x56, 0x5a, 0x4e, 0x58, 0x31, 0x53, 0x4e, 0x35,
    44  					0x4e, 0x74, 0x4b, 0x61, 0x38, 0x55, 0x51, 0x46, 0x78, 0x77,
    45  					0x51, 0x62, 0x46, 0x65, 0x46, 0x63, 0x33, 0x69, 0x71, 0x52,
    46  					0x59, 0x68, 0x65, 0x6d,
    47  				},
    48  			},
    49  			true,
    50  		},
    51  		{
    52  			"PUSHDATA4 1000 EQUAL",
    53  			nil,
    54  			false,
    55  		},
    56  	}
    57  
    58  	for i, test := range tests {
    59  		script := mustParseShortForm(test.script)
    60  		data, err := PushedData(script)
    61  		if test.valid && err != nil {
    62  			t.Errorf("TestPushedData failed test #%d: %v\n", i, err)
    63  			continue
    64  		} else if !test.valid && err == nil {
    65  			t.Errorf("TestPushedData failed test #%d: test should "+
    66  				"be invalid\n", i)
    67  			continue
    68  		}
    69  		if !reflect.DeepEqual(data, test.out) {
    70  			t.Errorf("TestPushedData failed test #%d: want: %x "+
    71  				"got: %x\n", i, test.out, data)
    72  		}
    73  	}
    74  }
    75  
    76  // TestHasCanonicalPush ensures the isCanonicalPush function works as expected.
    77  func TestHasCanonicalPush(t *testing.T) {
    78  	t.Parallel()
    79  
    80  	const scriptVersion = 0
    81  	for i := 0; i < 65535; i++ {
    82  		script, err := NewScriptBuilder().AddInt64(int64(i)).Script()
    83  		if err != nil {
    84  			t.Errorf("Script: test #%d unexpected error: %v\n", i, err)
    85  			continue
    86  		}
    87  		if !IsPushOnlyScript(script) {
    88  			t.Errorf("IsPushOnlyScript: test #%d failed: %x\n", i, script)
    89  			continue
    90  		}
    91  		tokenizer := MakeScriptTokenizer(scriptVersion, script)
    92  		for tokenizer.Next() {
    93  			if !isCanonicalPush(tokenizer.Opcode(), tokenizer.Data()) {
    94  				t.Errorf("isCanonicalPush: test #%d failed: %x\n", i, script)
    95  				break
    96  			}
    97  		}
    98  	}
    99  	for i := 0; i <= MaxScriptElementSize; i++ {
   100  		builder := NewScriptBuilder()
   101  		builder.AddData(bytes.Repeat([]byte{0x49}, i))
   102  		script, err := builder.Script()
   103  		if err != nil {
   104  			t.Errorf("Script: test #%d unexpected error: %v\n", i, err)
   105  			continue
   106  		}
   107  		if !IsPushOnlyScript(script) {
   108  			t.Errorf("IsPushOnlyScript: test #%d failed: %x\n", i, script)
   109  			continue
   110  		}
   111  		tokenizer := MakeScriptTokenizer(scriptVersion, script)
   112  		for tokenizer.Next() {
   113  			if !isCanonicalPush(tokenizer.Opcode(), tokenizer.Data()) {
   114  				t.Errorf("isCanonicalPush: test #%d failed: %x\n", i, script)
   115  				break
   116  			}
   117  		}
   118  	}
   119  }
   120  
   121  // TestGetPreciseSigOps ensures the more precise signature operation counting
   122  // mechanism which includes signatures in P2SH scripts works as expected.
   123  func TestGetPreciseSigOps(t *testing.T) {
   124  	t.Parallel()
   125  
   126  	tests := []struct {
   127  		name      string
   128  		scriptSig []byte
   129  		nSigOps   int
   130  	}{
   131  		{
   132  			name:      "scriptSig doesn't parse",
   133  			scriptSig: mustParseShortForm("PUSHDATA1 0x02"),
   134  		},
   135  		{
   136  			name:      "scriptSig isn't push only",
   137  			scriptSig: mustParseShortForm("1 DUP"),
   138  			nSigOps:   0,
   139  		},
   140  		{
   141  			name:      "scriptSig length 0",
   142  			scriptSig: nil,
   143  			nSigOps:   0,
   144  		},
   145  		{
   146  			name: "No script at the end",
   147  			// No script at end but still push only.
   148  			scriptSig: mustParseShortForm("1 1"),
   149  			nSigOps:   0,
   150  		},
   151  		{
   152  			name:      "pushed script doesn't parse",
   153  			scriptSig: mustParseShortForm("DATA_2 PUSHDATA1 0x02"),
   154  		},
   155  	}
   156  
   157  	// The signature in the p2sh script is nonsensical for the tests since
   158  	// this script will never be executed.  What matters is that it matches
   159  	// the right pattern.
   160  	pkScript := mustParseShortForm("HASH160 DATA_20 0x433ec2ac1ffa1b7b7d0" +
   161  		"27f564529c57197f9ae88 EQUAL")
   162  	for _, test := range tests {
   163  		count := GetPreciseSigOpCount(test.scriptSig, pkScript, true)
   164  		if count != test.nSigOps {
   165  			t.Errorf("%s: expected count of %d, got %d", test.name,
   166  				test.nSigOps, count)
   167  
   168  		}
   169  	}
   170  }
   171  
   172  // TestGetWitnessSigOpCount tests that the sig op counting for p2wkh, p2wsh,
   173  // nested p2sh, and invalid variants are counted properly.
   174  func TestGetWitnessSigOpCount(t *testing.T) {
   175  	t.Parallel()
   176  	tests := []struct {
   177  		name string
   178  
   179  		sigScript []byte
   180  		pkScript  []byte
   181  		witness   wire.TxWitness
   182  
   183  		numSigOps int
   184  	}{
   185  		// A regualr p2wkh witness program. The output being spent
   186  		// should only have a single sig-op counted.
   187  		{
   188  			name: "p2wkh",
   189  			pkScript: mustParseShortForm("OP_0 DATA_20 " +
   190  				"0x365ab47888e150ff46f8d51bce36dcd680f1283f"),
   191  			witness: wire.TxWitness{
   192  				hexToBytes("3045022100ee9fe8f9487afa977" +
   193  					"6647ebcf0883ce0cd37454d7ce19889d34ba2c9" +
   194  					"9ce5a9f402200341cb469d0efd3955acb9e46" +
   195  					"f568d7e2cc10f9084aaff94ced6dc50a59134ad01"),
   196  				hexToBytes("03f0000d0639a22bfaf217e4c9428" +
   197  					"9c2b0cc7fa1036f7fd5d9f61a9d6ec153100e"),
   198  			},
   199  			numSigOps: 1,
   200  		},
   201  		// A p2wkh witness program nested within a p2sh output script.
   202  		// The pattern should be recognized properly and attribute only
   203  		// a single sig op.
   204  		{
   205  			name: "nested p2sh",
   206  			sigScript: hexToBytes("160014ad0ffa2e387f07" +
   207  				"e7ead14dc56d5a97dbd6ff5a23"),
   208  			pkScript: mustParseShortForm("HASH160 DATA_20 " +
   209  				"0xb3a84b564602a9d68b4c9f19c2ea61458ff7826c EQUAL"),
   210  			witness: wire.TxWitness{
   211  				hexToBytes("3045022100cb1c2ac1ff1d57d" +
   212  					"db98f7bdead905f8bf5bcc8641b029ce8eef25" +
   213  					"c75a9e22a4702203be621b5c86b771288706be5" +
   214  					"a7eee1db4fceabf9afb7583c1cc6ee3f8297b21201"),
   215  				hexToBytes("03f0000d0639a22bfaf217e4c9" +
   216  					"4289c2b0cc7fa1036f7fd5d9f61a9d6ec153100e"),
   217  			},
   218  			numSigOps: 1,
   219  		},
   220  		// A p2sh script that spends a 2-of-2 multi-sig output.
   221  		{
   222  			name:      "p2wsh multi-sig spend",
   223  			numSigOps: 2,
   224  			pkScript: hexToBytes("0020e112b88a0cd87ba387f" +
   225  				"449d443ee2596eb353beb1f0351ab2cba8909d875db23"),
   226  			witness: wire.TxWitness{
   227  				hexToBytes("522103b05faca7ceda92b493" +
   228  					"3f7acdf874a93de0dc7edc461832031cd69cbb1d1e" +
   229  					"6fae2102e39092e031c1621c902e3704424e8d8" +
   230  					"3ca481d4d4eeae1b7970f51c78231207e52ae"),
   231  			},
   232  		},
   233  		// A p2wsh witness program. However, the witness script fails
   234  		// to parse after the valid portion of the script. As a result,
   235  		// the valid portion of the script should still be counted.
   236  		{
   237  			name:      "witness script doesn't parse",
   238  			numSigOps: 1,
   239  			pkScript: hexToBytes("0020e112b88a0cd87ba387f44" +
   240  				"9d443ee2596eb353beb1f0351ab2cba8909d875db23"),
   241  			witness: wire.TxWitness{
   242  				mustParseShortForm("DUP HASH160 " +
   243  					"'17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem'" +
   244  					" EQUALVERIFY CHECKSIG DATA_20 0x91"),
   245  			},
   246  		},
   247  	}
   248  
   249  	for _, test := range tests {
   250  		count := GetWitnessSigOpCount(test.sigScript, test.pkScript,
   251  			test.witness)
   252  		if count != test.numSigOps {
   253  			t.Errorf("%s: expected count of %d, got %d", test.name,
   254  				test.numSigOps, count)
   255  
   256  		}
   257  	}
   258  }
   259  
   260  // TestRemoveOpcodes ensures that removing opcodes from scripts behaves as
   261  // expected.
   262  func TestRemoveOpcodes(t *testing.T) {
   263  	t.Parallel()
   264  
   265  	tests := []struct {
   266  		name   string
   267  		before string
   268  		remove byte
   269  		err    error
   270  		after  string
   271  	}{
   272  		{
   273  			// Nothing to remove.
   274  			name:   "nothing to remove",
   275  			before: "NOP",
   276  			remove: OP_CODESEPARATOR,
   277  			after:  "NOP",
   278  		},
   279  		{
   280  			// Test basic opcode removal.
   281  			name:   "codeseparator 1",
   282  			before: "NOP CODESEPARATOR TRUE",
   283  			remove: OP_CODESEPARATOR,
   284  			after:  "NOP TRUE",
   285  		},
   286  		{
   287  			// The opcode in question is actually part of the data
   288  			// in a previous opcode.
   289  			name:   "codeseparator by coincidence",
   290  			before: "NOP DATA_1 CODESEPARATOR TRUE",
   291  			remove: OP_CODESEPARATOR,
   292  			after:  "NOP DATA_1 CODESEPARATOR TRUE",
   293  		},
   294  		{
   295  			name:   "invalid opcode",
   296  			before: "CAT",
   297  			remove: OP_CODESEPARATOR,
   298  			after:  "CAT",
   299  		},
   300  		{
   301  			name:   "invalid length (instruction)",
   302  			before: "PUSHDATA1",
   303  			remove: OP_CODESEPARATOR,
   304  			err:    scriptError(ErrMalformedPush, ""),
   305  		},
   306  		{
   307  			name:   "invalid length (data)",
   308  			before: "PUSHDATA1 0xff 0xfe",
   309  			remove: OP_CODESEPARATOR,
   310  			err:    scriptError(ErrMalformedPush, ""),
   311  		},
   312  	}
   313  
   314  	// tstRemoveOpcode is a convenience function to parse the provided
   315  	// raw script, remove the passed opcode, then unparse the result back
   316  	// into a raw script.
   317  	const scriptVersion = 0
   318  	tstRemoveOpcode := func(script []byte, opcode byte) ([]byte, error) {
   319  		if err := checkScriptParses(scriptVersion, script); err != nil {
   320  			return nil, err
   321  		}
   322  		return removeOpcodeRaw(script, opcode), nil
   323  	}
   324  
   325  	for _, test := range tests {
   326  		before := mustParseShortForm(test.before)
   327  		after := mustParseShortForm(test.after)
   328  		result, err := tstRemoveOpcode(before, test.remove)
   329  		if e := tstCheckScriptError(err, test.err); e != nil {
   330  			t.Errorf("%s: %v", test.name, e)
   331  			continue
   332  		}
   333  
   334  		if !bytes.Equal(after, result) {
   335  			t.Errorf("%s: value does not equal expected: exp: %q"+
   336  				" got: %q", test.name, after, result)
   337  		}
   338  	}
   339  }
   340  
   341  // TestRemoveOpcodeByData ensures that removing data carrying opcodes based on
   342  // the data they contain works as expected.
   343  func TestRemoveOpcodeByData(t *testing.T) {
   344  	t.Parallel()
   345  
   346  	tests := []struct {
   347  		name   string
   348  		before []byte
   349  		remove []byte
   350  		err    error
   351  		after  []byte
   352  	}{
   353  		{
   354  			name:   "nothing to do",
   355  			before: []byte{OP_NOP},
   356  			remove: []byte{1, 2, 3, 4},
   357  			after:  []byte{OP_NOP},
   358  		},
   359  		{
   360  			name:   "simple case",
   361  			before: []byte{OP_DATA_4, 1, 2, 3, 4},
   362  			remove: []byte{1, 2, 3, 4},
   363  			after:  nil,
   364  		},
   365  		{
   366  			name:   "simple case (miss)",
   367  			before: []byte{OP_DATA_4, 1, 2, 3, 4},
   368  			remove: []byte{1, 2, 3, 5},
   369  			after:  []byte{OP_DATA_4, 1, 2, 3, 4},
   370  		},
   371  		{
   372  			// padded to keep it canonical.
   373  			name: "simple case (pushdata1)",
   374  			before: append(append([]byte{OP_PUSHDATA1, 76},
   375  				bytes.Repeat([]byte{0}, 72)...),
   376  				[]byte{1, 2, 3, 4}...),
   377  			remove: []byte{1, 2, 3, 4},
   378  			after:  nil,
   379  		},
   380  		{
   381  			name: "simple case (pushdata1 miss)",
   382  			before: append(append([]byte{OP_PUSHDATA1, 76},
   383  				bytes.Repeat([]byte{0}, 72)...),
   384  				[]byte{1, 2, 3, 4}...),
   385  			remove: []byte{1, 2, 3, 5},
   386  			after: append(append([]byte{OP_PUSHDATA1, 76},
   387  				bytes.Repeat([]byte{0}, 72)...),
   388  				[]byte{1, 2, 3, 4}...),
   389  		},
   390  		{
   391  			name:   "simple case (pushdata1 miss noncanonical)",
   392  			before: []byte{OP_PUSHDATA1, 4, 1, 2, 3, 4},
   393  			remove: []byte{1, 2, 3, 4},
   394  			after:  []byte{OP_PUSHDATA1, 4, 1, 2, 3, 4},
   395  		},
   396  		{
   397  			name: "simple case (pushdata2)",
   398  			before: append(append([]byte{OP_PUSHDATA2, 0, 1},
   399  				bytes.Repeat([]byte{0}, 252)...),
   400  				[]byte{1, 2, 3, 4}...),
   401  			remove: []byte{1, 2, 3, 4},
   402  			after:  nil,
   403  		},
   404  		{
   405  			name: "simple case (pushdata2 miss)",
   406  			before: append(append([]byte{OP_PUSHDATA2, 0, 1},
   407  				bytes.Repeat([]byte{0}, 252)...),
   408  				[]byte{1, 2, 3, 4}...),
   409  			remove: []byte{1, 2, 3, 4, 5},
   410  			after: append(append([]byte{OP_PUSHDATA2, 0, 1},
   411  				bytes.Repeat([]byte{0}, 252)...),
   412  				[]byte{1, 2, 3, 4}...),
   413  		},
   414  		{
   415  			name:   "simple case (pushdata2 miss noncanonical)",
   416  			before: []byte{OP_PUSHDATA2, 4, 0, 1, 2, 3, 4},
   417  			remove: []byte{1, 2, 3, 4},
   418  			after:  []byte{OP_PUSHDATA2, 4, 0, 1, 2, 3, 4},
   419  		},
   420  		{
   421  			// This is padded to make the push canonical.
   422  			name: "simple case (pushdata4)",
   423  			before: append(append([]byte{OP_PUSHDATA4, 0, 0, 1, 0},
   424  				bytes.Repeat([]byte{0}, 65532)...),
   425  				[]byte{1, 2, 3, 4}...),
   426  			remove: []byte{1, 2, 3, 4},
   427  			after:  nil,
   428  		},
   429  		{
   430  			name:   "simple case (pushdata4 miss noncanonical)",
   431  			before: []byte{OP_PUSHDATA4, 4, 0, 0, 0, 1, 2, 3, 4},
   432  			remove: []byte{1, 2, 3, 4},
   433  			after:  []byte{OP_PUSHDATA4, 4, 0, 0, 0, 1, 2, 3, 4},
   434  		},
   435  		{
   436  			// This is padded to make the push canonical.
   437  			name: "simple case (pushdata4 miss)",
   438  			before: append(append([]byte{OP_PUSHDATA4, 0, 0, 1, 0},
   439  				bytes.Repeat([]byte{0}, 65532)...), []byte{1, 2, 3, 4}...),
   440  			remove: []byte{1, 2, 3, 4, 5},
   441  			after: append(append([]byte{OP_PUSHDATA4, 0, 0, 1, 0},
   442  				bytes.Repeat([]byte{0}, 65532)...), []byte{1, 2, 3, 4}...),
   443  		},
   444  		{
   445  			name:   "invalid opcode ",
   446  			before: []byte{OP_UNKNOWN187},
   447  			remove: []byte{1, 2, 3, 4},
   448  			after:  []byte{OP_UNKNOWN187},
   449  		},
   450  		{
   451  			name:   "invalid length (instruction)",
   452  			before: []byte{OP_PUSHDATA1},
   453  			remove: []byte{1, 2, 3, 4},
   454  			err:    scriptError(ErrMalformedPush, ""),
   455  		},
   456  		{
   457  			name:   "invalid length (data)",
   458  			before: []byte{OP_PUSHDATA1, 255, 254},
   459  			remove: []byte{1, 2, 3, 4},
   460  			err:    scriptError(ErrMalformedPush, ""),
   461  		},
   462  	}
   463  
   464  	// tstRemoveOpcodeByData is a convenience function to ensure the provided
   465  	// script parses before attempting to remove the passed data.
   466  	const scriptVersion = 0
   467  	tstRemoveOpcodeByData := func(script []byte, data []byte) ([]byte, error) {
   468  		if err := checkScriptParses(scriptVersion, script); err != nil {
   469  			return nil, err
   470  		}
   471  
   472  		return removeOpcodeByData(script, data), nil
   473  	}
   474  
   475  	for _, test := range tests {
   476  		result, err := tstRemoveOpcodeByData(test.before, test.remove)
   477  		if e := tstCheckScriptError(err, test.err); e != nil {
   478  			t.Errorf("%s: %v", test.name, e)
   479  			continue
   480  		}
   481  
   482  		if !bytes.Equal(test.after, result) {
   483  			t.Errorf("%s: value does not equal expected: exp: %q"+
   484  				" got: %q", test.name, test.after, result)
   485  		}
   486  	}
   487  }
   488  
   489  // TestIsPayToScriptHash ensures the IsPayToScriptHash function returns the
   490  // expected results for all the scripts in scriptClassTests.
   491  func TestIsPayToScriptHash(t *testing.T) {
   492  	t.Parallel()
   493  
   494  	for _, test := range scriptClassTests {
   495  		script := mustParseShortForm(test.script)
   496  		shouldBe := (test.class == ScriptHashTy)
   497  		p2sh := IsPayToScriptHash(script)
   498  		if p2sh != shouldBe {
   499  			t.Errorf("%s: expected p2sh %v, got %v", test.name,
   500  				shouldBe, p2sh)
   501  		}
   502  	}
   503  }
   504  
   505  // TestIsPayToWitnessScriptHash ensures the IsPayToWitnessScriptHash function
   506  // returns the expected results for all the scripts in scriptClassTests.
   507  func TestIsPayToWitnessScriptHash(t *testing.T) {
   508  	t.Parallel()
   509  
   510  	for _, test := range scriptClassTests {
   511  		script := mustParseShortForm(test.script)
   512  		shouldBe := (test.class == WitnessV0ScriptHashTy)
   513  		p2wsh := IsPayToWitnessScriptHash(script)
   514  		if p2wsh != shouldBe {
   515  			t.Errorf("%s: expected p2wsh %v, got %v", test.name,
   516  				shouldBe, p2wsh)
   517  		}
   518  	}
   519  }
   520  
   521  // TestIsPayToWitnessPubKeyHash ensures the IsPayToWitnessPubKeyHash function
   522  // returns the expected results for all the scripts in scriptClassTests.
   523  func TestIsPayToWitnessPubKeyHash(t *testing.T) {
   524  	t.Parallel()
   525  
   526  	for _, test := range scriptClassTests {
   527  		script := mustParseShortForm(test.script)
   528  		shouldBe := (test.class == WitnessV0PubKeyHashTy)
   529  		p2wkh := IsPayToWitnessPubKeyHash(script)
   530  		if p2wkh != shouldBe {
   531  			t.Errorf("%s: expected p2wkh %v, got %v", test.name,
   532  				shouldBe, p2wkh)
   533  		}
   534  	}
   535  }
   536  
   537  // TestHasCanonicalPushes ensures the isCanonicalPush function properly
   538  // determines what is considered a canonical push for the purposes of
   539  // removeOpcodeByData.
   540  func TestHasCanonicalPushes(t *testing.T) {
   541  	t.Parallel()
   542  
   543  	const scriptVersion = 0
   544  	tests := []struct {
   545  		name     string
   546  		script   string
   547  		expected bool
   548  	}{
   549  		{
   550  			name: "does not parse",
   551  			script: "0x046708afdb0fe5548271967f1a67130b7105cd6a82" +
   552  				"8e03909a67962e0ea1f61d",
   553  			expected: false,
   554  		},
   555  		{
   556  			name:     "non-canonical push",
   557  			script:   "PUSHDATA1 0x04 0x01020304",
   558  			expected: false,
   559  		},
   560  	}
   561  
   562  	for _, test := range tests {
   563  		script := mustParseShortForm(test.script)
   564  		if err := checkScriptParses(scriptVersion, script); err != nil {
   565  			if test.expected {
   566  				t.Errorf("%q: script parse failed: %v", test.name, err)
   567  			}
   568  			continue
   569  		}
   570  		tokenizer := MakeScriptTokenizer(scriptVersion, script)
   571  		for tokenizer.Next() {
   572  			result := isCanonicalPush(tokenizer.Opcode(), tokenizer.Data())
   573  			if result != test.expected {
   574  				t.Errorf("%q: isCanonicalPush wrong result\ngot: %v\nwant: %v",
   575  					test.name, result, test.expected)
   576  				break
   577  			}
   578  		}
   579  	}
   580  }
   581  
   582  // TestIsPushOnlyScript ensures the IsPushOnlyScript function returns the
   583  // expected results.
   584  func TestIsPushOnlyScript(t *testing.T) {
   585  	t.Parallel()
   586  
   587  	test := struct {
   588  		name     string
   589  		script   []byte
   590  		expected bool
   591  	}{
   592  		name: "does not parse",
   593  		script: mustParseShortForm("0x046708afdb0fe5548271967f1a67130" +
   594  			"b7105cd6a828e03909a67962e0ea1f61d"),
   595  		expected: false,
   596  	}
   597  
   598  	if IsPushOnlyScript(test.script) != test.expected {
   599  		t.Errorf("IsPushOnlyScript (%s) wrong result\ngot: %v\nwant: "+
   600  			"%v", test.name, true, test.expected)
   601  	}
   602  }
   603  
   604  // TestIsUnspendable ensures the IsUnspendable function returns the expected
   605  // results.
   606  func TestIsUnspendable(t *testing.T) {
   607  	t.Parallel()
   608  
   609  	tests := []struct {
   610  		name     string
   611  		pkScript []byte
   612  		expected bool
   613  	}{
   614  		{
   615  			// Unspendable
   616  			pkScript: []byte{0x6a, 0x04, 0x74, 0x65, 0x73, 0x74},
   617  			expected: true,
   618  		},
   619  		{
   620  			// Spendable
   621  			pkScript: []byte{0x76, 0xa9, 0x14, 0x29, 0x95, 0xa0,
   622  				0xfe, 0x68, 0x43, 0xfa, 0x9b, 0x95, 0x45,
   623  				0x97, 0xf0, 0xdc, 0xa7, 0xa4, 0x4d, 0xf6,
   624  				0xfa, 0x0b, 0x5c, 0x88, 0xac},
   625  			expected: false,
   626  		},
   627  		{
   628  			// Spendable
   629  			pkScript: []byte{0xa9, 0x14, 0x82, 0x1d, 0xba, 0x94, 0xbc, 0xfb,
   630  				0xa2, 0x57, 0x36, 0xa3, 0x9e, 0x5d, 0x14, 0x5d, 0x69, 0x75,
   631  				0xba, 0x8c, 0x0b, 0x42, 0x87},
   632  			expected: false,
   633  		},
   634  		{
   635  			// Not Necessarily Unspendable
   636  			pkScript: []byte{},
   637  			expected: false,
   638  		},
   639  		{
   640  			// Spendable
   641  			pkScript: []byte{OP_TRUE},
   642  			expected: false,
   643  		},
   644  		{
   645  			// Unspendable
   646  			pkScript: []byte{OP_RETURN},
   647  			expected: true,
   648  		},
   649  	}
   650  
   651  	for i, test := range tests {
   652  		res := IsUnspendable(test.pkScript)
   653  		if res != test.expected {
   654  			t.Errorf("TestIsUnspendable #%d failed: got %v want %v",
   655  				i, res, test.expected)
   656  			continue
   657  		}
   658  	}
   659  }