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