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 }