github.com/palcoin-project/palcd@v1.0.0/txscript/engine_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  	"testing"
     9  
    10  	"github.com/palcoin-project/palcd/chaincfg/chainhash"
    11  	"github.com/palcoin-project/palcd/wire"
    12  )
    13  
    14  // TestBadPC sets the pc to a deliberately bad result then confirms that Step()
    15  // and Disasm fail correctly.
    16  func TestBadPC(t *testing.T) {
    17  	t.Parallel()
    18  
    19  	tests := []struct {
    20  		script, off int
    21  	}{
    22  		{script: 2, off: 0},
    23  		{script: 0, off: 2},
    24  	}
    25  
    26  	// tx with almost empty scripts.
    27  	tx := &wire.MsgTx{
    28  		Version: 1,
    29  		TxIn: []*wire.TxIn{
    30  			{
    31  				PreviousOutPoint: wire.OutPoint{
    32  					Hash: chainhash.Hash([32]byte{
    33  						0xc9, 0x97, 0xa5, 0xe5,
    34  						0x6e, 0x10, 0x41, 0x02,
    35  						0xfa, 0x20, 0x9c, 0x6a,
    36  						0x85, 0x2d, 0xd9, 0x06,
    37  						0x60, 0xa2, 0x0b, 0x2d,
    38  						0x9c, 0x35, 0x24, 0x23,
    39  						0xed, 0xce, 0x25, 0x85,
    40  						0x7f, 0xcd, 0x37, 0x04,
    41  					}),
    42  					Index: 0,
    43  				},
    44  				SignatureScript: mustParseShortForm("NOP"),
    45  				Sequence:        4294967295,
    46  			},
    47  		},
    48  		TxOut: []*wire.TxOut{{
    49  			Value:    1000000000,
    50  			PkScript: nil,
    51  		}},
    52  		LockTime: 0,
    53  	}
    54  	pkScript := mustParseShortForm("NOP")
    55  
    56  	for _, test := range tests {
    57  		vm, err := NewEngine(pkScript, tx, 0, 0, nil, nil, -1)
    58  		if err != nil {
    59  			t.Errorf("Failed to create script: %v", err)
    60  		}
    61  
    62  		// set to after all scripts
    63  		vm.scriptIdx = test.script
    64  		vm.scriptOff = test.off
    65  
    66  		_, err = vm.Step()
    67  		if err == nil {
    68  			t.Errorf("Step with invalid pc (%v) succeeds!", test)
    69  			continue
    70  		}
    71  
    72  		_, err = vm.DisasmPC()
    73  		if err == nil {
    74  			t.Errorf("DisasmPC with invalid pc (%v) succeeds!",
    75  				test)
    76  		}
    77  	}
    78  }
    79  
    80  // TestCheckErrorCondition tests the execute early test in CheckErrorCondition()
    81  // since most code paths are tested elsewhere.
    82  func TestCheckErrorCondition(t *testing.T) {
    83  	t.Parallel()
    84  
    85  	// tx with almost empty scripts.
    86  	tx := &wire.MsgTx{
    87  		Version: 1,
    88  		TxIn: []*wire.TxIn{{
    89  			PreviousOutPoint: wire.OutPoint{
    90  				Hash: chainhash.Hash([32]byte{
    91  					0xc9, 0x97, 0xa5, 0xe5,
    92  					0x6e, 0x10, 0x41, 0x02,
    93  					0xfa, 0x20, 0x9c, 0x6a,
    94  					0x85, 0x2d, 0xd9, 0x06,
    95  					0x60, 0xa2, 0x0b, 0x2d,
    96  					0x9c, 0x35, 0x24, 0x23,
    97  					0xed, 0xce, 0x25, 0x85,
    98  					0x7f, 0xcd, 0x37, 0x04,
    99  				}),
   100  				Index: 0,
   101  			},
   102  			SignatureScript: nil,
   103  			Sequence:        4294967295,
   104  		}},
   105  		TxOut: []*wire.TxOut{{
   106  			Value:    1000000000,
   107  			PkScript: nil,
   108  		}},
   109  		LockTime: 0,
   110  	}
   111  	pkScript := mustParseShortForm("NOP NOP NOP NOP NOP NOP NOP NOP NOP" +
   112  		" NOP TRUE")
   113  
   114  	vm, err := NewEngine(pkScript, tx, 0, 0, nil, nil, 0)
   115  	if err != nil {
   116  		t.Errorf("failed to create script: %v", err)
   117  	}
   118  
   119  	for i := 0; i < len(pkScript)-1; i++ {
   120  		done, err := vm.Step()
   121  		if err != nil {
   122  			t.Fatalf("failed to step %dth time: %v", i, err)
   123  		}
   124  		if done {
   125  			t.Fatalf("finshed early on %dth time", i)
   126  		}
   127  
   128  		err = vm.CheckErrorCondition(false)
   129  		if !IsErrorCode(err, ErrScriptUnfinished) {
   130  			t.Fatalf("got unexepected error %v on %dth iteration",
   131  				err, i)
   132  		}
   133  	}
   134  	done, err := vm.Step()
   135  	if err != nil {
   136  		t.Fatalf("final step failed %v", err)
   137  	}
   138  	if !done {
   139  		t.Fatalf("final step isn't done!")
   140  	}
   141  
   142  	err = vm.CheckErrorCondition(false)
   143  	if err != nil {
   144  		t.Errorf("unexpected error %v on final check", err)
   145  	}
   146  }
   147  
   148  // TestInvalidFlagCombinations ensures the script engine returns the expected
   149  // error when disallowed flag combinations are specified.
   150  func TestInvalidFlagCombinations(t *testing.T) {
   151  	t.Parallel()
   152  
   153  	tests := []ScriptFlags{
   154  		ScriptVerifyCleanStack,
   155  	}
   156  
   157  	// tx with almost empty scripts.
   158  	tx := &wire.MsgTx{
   159  		Version: 1,
   160  		TxIn: []*wire.TxIn{
   161  			{
   162  				PreviousOutPoint: wire.OutPoint{
   163  					Hash: chainhash.Hash([32]byte{
   164  						0xc9, 0x97, 0xa5, 0xe5,
   165  						0x6e, 0x10, 0x41, 0x02,
   166  						0xfa, 0x20, 0x9c, 0x6a,
   167  						0x85, 0x2d, 0xd9, 0x06,
   168  						0x60, 0xa2, 0x0b, 0x2d,
   169  						0x9c, 0x35, 0x24, 0x23,
   170  						0xed, 0xce, 0x25, 0x85,
   171  						0x7f, 0xcd, 0x37, 0x04,
   172  					}),
   173  					Index: 0,
   174  				},
   175  				SignatureScript: []uint8{OP_NOP},
   176  				Sequence:        4294967295,
   177  			},
   178  		},
   179  		TxOut: []*wire.TxOut{
   180  			{
   181  				Value:    1000000000,
   182  				PkScript: nil,
   183  			},
   184  		},
   185  		LockTime: 0,
   186  	}
   187  	pkScript := []byte{OP_NOP}
   188  
   189  	for i, test := range tests {
   190  		_, err := NewEngine(pkScript, tx, 0, test, nil, nil, -1)
   191  		if !IsErrorCode(err, ErrInvalidFlags) {
   192  			t.Fatalf("TestInvalidFlagCombinations #%d unexpected "+
   193  				"error: %v", i, err)
   194  		}
   195  	}
   196  }
   197  
   198  // TestCheckPubKeyEncoding ensures the internal checkPubKeyEncoding function
   199  // works as expected.
   200  func TestCheckPubKeyEncoding(t *testing.T) {
   201  	t.Parallel()
   202  
   203  	tests := []struct {
   204  		name    string
   205  		key     []byte
   206  		isValid bool
   207  	}{
   208  		{
   209  			name: "uncompressed ok",
   210  			key: hexToBytes("0411db93e1dcdb8a016b49840f8c53bc1eb68" +
   211  				"a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf" +
   212  				"9744464f82e160bfa9b8b64f9d4c03f999b8643f656b" +
   213  				"412a3"),
   214  			isValid: true,
   215  		},
   216  		{
   217  			name: "compressed ok",
   218  			key: hexToBytes("02ce0b14fb842b1ba549fdd675c98075f12e9" +
   219  				"c510f8ef52bd021a9a1f4809d3b4d"),
   220  			isValid: true,
   221  		},
   222  		{
   223  			name: "compressed ok",
   224  			key: hexToBytes("032689c7c2dab13309fb143e0e8fe39634252" +
   225  				"1887e976690b6b47f5b2a4b7d448e"),
   226  			isValid: true,
   227  		},
   228  		{
   229  			name: "hybrid",
   230  			key: hexToBytes("0679be667ef9dcbbac55a06295ce870b07029" +
   231  				"bfcdb2dce28d959f2815b16f81798483ada7726a3c46" +
   232  				"55da4fbfc0e1108a8fd17b448a68554199c47d08ffb1" +
   233  				"0d4b8"),
   234  			isValid: false,
   235  		},
   236  		{
   237  			name:    "empty",
   238  			key:     nil,
   239  			isValid: false,
   240  		},
   241  	}
   242  
   243  	vm := Engine{flags: ScriptVerifyStrictEncoding}
   244  	for _, test := range tests {
   245  		err := vm.checkPubKeyEncoding(test.key)
   246  		if err != nil && test.isValid {
   247  			t.Errorf("checkSignatureEncoding test '%s' failed "+
   248  				"when it should have succeeded: %v", test.name,
   249  				err)
   250  		} else if err == nil && !test.isValid {
   251  			t.Errorf("checkSignatureEncooding test '%s' succeeded "+
   252  				"when it should have failed", test.name)
   253  		}
   254  	}
   255  
   256  }
   257  
   258  // TestCheckSignatureEncoding ensures the internal checkSignatureEncoding
   259  // function works as expected.
   260  func TestCheckSignatureEncoding(t *testing.T) {
   261  	t.Parallel()
   262  
   263  	tests := []struct {
   264  		name    string
   265  		sig     []byte
   266  		isValid bool
   267  	}{
   268  		{
   269  			name: "valid signature",
   270  			sig: hexToBytes("304402204e45e16932b8af514961a1d3a1a25" +
   271  				"fdf3f4f7732e9d624c6c61548ab5fb8cd41022018152" +
   272  				"2ec8eca07de4860a4acdd12909d831cc56cbbac46220" +
   273  				"82221a8768d1d09"),
   274  			isValid: true,
   275  		},
   276  		{
   277  			name:    "empty.",
   278  			sig:     nil,
   279  			isValid: false,
   280  		},
   281  		{
   282  			name: "bad magic",
   283  			sig: hexToBytes("314402204e45e16932b8af514961a1d3a1a25" +
   284  				"fdf3f4f7732e9d624c6c61548ab5fb8cd41022018152" +
   285  				"2ec8eca07de4860a4acdd12909d831cc56cbbac46220" +
   286  				"82221a8768d1d09"),
   287  			isValid: false,
   288  		},
   289  		{
   290  			name: "bad 1st int marker magic",
   291  			sig: hexToBytes("304403204e45e16932b8af514961a1d3a1a25" +
   292  				"fdf3f4f7732e9d624c6c61548ab5fb8cd41022018152" +
   293  				"2ec8eca07de4860a4acdd12909d831cc56cbbac46220" +
   294  				"82221a8768d1d09"),
   295  			isValid: false,
   296  		},
   297  		{
   298  			name: "bad 2nd int marker",
   299  			sig: hexToBytes("304402204e45e16932b8af514961a1d3a1a25" +
   300  				"fdf3f4f7732e9d624c6c61548ab5fb8cd41032018152" +
   301  				"2ec8eca07de4860a4acdd12909d831cc56cbbac46220" +
   302  				"82221a8768d1d09"),
   303  			isValid: false,
   304  		},
   305  		{
   306  			name: "short len",
   307  			sig: hexToBytes("304302204e45e16932b8af514961a1d3a1a25" +
   308  				"fdf3f4f7732e9d624c6c61548ab5fb8cd41022018152" +
   309  				"2ec8eca07de4860a4acdd12909d831cc56cbbac46220" +
   310  				"82221a8768d1d09"),
   311  			isValid: false,
   312  		},
   313  		{
   314  			name: "long len",
   315  			sig: hexToBytes("304502204e45e16932b8af514961a1d3a1a25" +
   316  				"fdf3f4f7732e9d624c6c61548ab5fb8cd41022018152" +
   317  				"2ec8eca07de4860a4acdd12909d831cc56cbbac46220" +
   318  				"82221a8768d1d09"),
   319  			isValid: false,
   320  		},
   321  		{
   322  			name: "long X",
   323  			sig: hexToBytes("304402424e45e16932b8af514961a1d3a1a25" +
   324  				"fdf3f4f7732e9d624c6c61548ab5fb8cd41022018152" +
   325  				"2ec8eca07de4860a4acdd12909d831cc56cbbac46220" +
   326  				"82221a8768d1d09"),
   327  			isValid: false,
   328  		},
   329  		{
   330  			name: "long Y",
   331  			sig: hexToBytes("304402204e45e16932b8af514961a1d3a1a25" +
   332  				"fdf3f4f7732e9d624c6c61548ab5fb8cd41022118152" +
   333  				"2ec8eca07de4860a4acdd12909d831cc56cbbac46220" +
   334  				"82221a8768d1d09"),
   335  			isValid: false,
   336  		},
   337  		{
   338  			name: "short Y",
   339  			sig: hexToBytes("304402204e45e16932b8af514961a1d3a1a25" +
   340  				"fdf3f4f7732e9d624c6c61548ab5fb8cd41021918152" +
   341  				"2ec8eca07de4860a4acdd12909d831cc56cbbac46220" +
   342  				"82221a8768d1d09"),
   343  			isValid: false,
   344  		},
   345  		{
   346  			name: "trailing crap",
   347  			sig: hexToBytes("304402204e45e16932b8af514961a1d3a1a25" +
   348  				"fdf3f4f7732e9d624c6c61548ab5fb8cd41022018152" +
   349  				"2ec8eca07de4860a4acdd12909d831cc56cbbac46220" +
   350  				"82221a8768d1d0901"),
   351  			isValid: false,
   352  		},
   353  		{
   354  			name: "X == N ",
   355  			sig: hexToBytes("30440220fffffffffffffffffffffffffffff" +
   356  				"ffebaaedce6af48a03bbfd25e8cd0364141022018152" +
   357  				"2ec8eca07de4860a4acdd12909d831cc56cbbac46220" +
   358  				"82221a8768d1d09"),
   359  			isValid: false,
   360  		},
   361  		{
   362  			name: "X == N ",
   363  			sig: hexToBytes("30440220fffffffffffffffffffffffffffff" +
   364  				"ffebaaedce6af48a03bbfd25e8cd0364142022018152" +
   365  				"2ec8eca07de4860a4acdd12909d831cc56cbbac46220" +
   366  				"82221a8768d1d09"),
   367  			isValid: false,
   368  		},
   369  		{
   370  			name: "Y == N",
   371  			sig: hexToBytes("304402204e45e16932b8af514961a1d3a1a25" +
   372  				"fdf3f4f7732e9d624c6c61548ab5fb8cd410220fffff" +
   373  				"ffffffffffffffffffffffffffebaaedce6af48a03bb" +
   374  				"fd25e8cd0364141"),
   375  			isValid: false,
   376  		},
   377  		{
   378  			name: "Y > N",
   379  			sig: hexToBytes("304402204e45e16932b8af514961a1d3a1a25" +
   380  				"fdf3f4f7732e9d624c6c61548ab5fb8cd410220fffff" +
   381  				"ffffffffffffffffffffffffffebaaedce6af48a03bb" +
   382  				"fd25e8cd0364142"),
   383  			isValid: false,
   384  		},
   385  		{
   386  			name: "0 len X",
   387  			sig: hexToBytes("302402000220181522ec8eca07de4860a4acd" +
   388  				"d12909d831cc56cbbac4622082221a8768d1d09"),
   389  			isValid: false,
   390  		},
   391  		{
   392  			name: "0 len Y",
   393  			sig: hexToBytes("302402204e45e16932b8af514961a1d3a1a25" +
   394  				"fdf3f4f7732e9d624c6c61548ab5fb8cd410200"),
   395  			isValid: false,
   396  		},
   397  		{
   398  			name: "extra R padding",
   399  			sig: hexToBytes("30450221004e45e16932b8af514961a1d3a1a" +
   400  				"25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181" +
   401  				"522ec8eca07de4860a4acdd12909d831cc56cbbac462" +
   402  				"2082221a8768d1d09"),
   403  			isValid: false,
   404  		},
   405  		{
   406  			name: "extra S padding",
   407  			sig: hexToBytes("304502204e45e16932b8af514961a1d3a1a25" +
   408  				"fdf3f4f7732e9d624c6c61548ab5fb8cd41022100181" +
   409  				"522ec8eca07de4860a4acdd12909d831cc56cbbac462" +
   410  				"2082221a8768d1d09"),
   411  			isValid: false,
   412  		},
   413  	}
   414  
   415  	vm := Engine{flags: ScriptVerifyStrictEncoding}
   416  	for _, test := range tests {
   417  		err := vm.checkSignatureEncoding(test.sig)
   418  		if err != nil && test.isValid {
   419  			t.Errorf("checkSignatureEncoding test '%s' failed "+
   420  				"when it should have succeeded: %v", test.name,
   421  				err)
   422  		} else if err == nil && !test.isValid {
   423  			t.Errorf("checkSignatureEncooding test '%s' succeeded "+
   424  				"when it should have failed", test.name)
   425  		}
   426  	}
   427  }