| 513 | } |
| 514 | |
| 515 | func (s *Script) IsStandardScriptPubKey() (pubKeyType int, pubKeys [][]byte, isStandard bool) { |
| 516 | //p2sh scriptPubKey |
| 517 | |
| 518 | // Shortcut for pay-to-script-hash, which are more constrained than the |
| 519 | // other types: |
| 520 | // it is always OP_HASH160 20 [20 byte hash] OP_EQUAL |
| 521 | if s.IsPayToScriptHash() { |
| 522 | return ScriptHash, [][]byte{s.ParsedOpCodes[1].Data}, true |
| 523 | } |
| 524 | |
| 525 | // Provably prunable, data-carrying output |
| 526 | // |
| 527 | // So long as script passes the IsUnspendable() test and all but the first |
| 528 | // byte passes the IsPushOnly() test we don't care what exactly is in the |
| 529 | // script. |
| 530 | |
| 531 | // OP_RETURN or OP_RETURN + DATA |
| 532 | opCodesLen := len(s.ParsedOpCodes) |
| 533 | if opCodesLen == 0 { |
| 534 | return ScriptNonStandard, nil, false |
| 535 | } |
| 536 | parsedOpCode0 := s.ParsedOpCodes[0] |
| 537 | opValue0 := parsedOpCode0.OpValue |
| 538 | |
| 539 | if opCodesLen >= 1 && parsedOpCode0.OpValue == opcodes.OP_RETURN { |
| 540 | temp := NewScriptOps(s.ParsedOpCodes[1:]) |
| 541 | if temp.IsPushOnly() { |
| 542 | return ScriptNullData, nil, true |
| 543 | } |
| 544 | return ScriptNonStandard, nil, false |
| 545 | } |
| 546 | |
| 547 | // Standard tx, sender provides pubkkey, receiver adds signature. |
| 548 | // PUBKEY << OP_CHECKSIG |
| 549 | if opCodesLen == 2 { |
| 550 | if opValue0 > opcodes.OP_PUSHDATA4 || parsedOpCode0.Length < 33 || |
| 551 | parsedOpCode0.Length > 65 || s.ParsedOpCodes[1].OpValue != opcodes.OP_CHECKSIG { |
| 552 | return ScriptNonStandard, nil, false |
| 553 | } |
| 554 | pubKeyType = ScriptPubkey |
| 555 | pubKeys = make([][]byte, 0, 1) |
| 556 | data := parsedOpCode0.Data |
| 557 | pubKeys = append(pubKeys, data) |
| 558 | isStandard = true |
| 559 | return |
| 560 | } |
| 561 | |
| 562 | // Bitcoin address tx, sender provides hash of pubkey, reciver provides signature and pubkey. |
| 563 | // OP_DUP << OP_HASH160 << PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG |
| 564 | if opValue0 == opcodes.OP_DUP { |
| 565 | if opCodesLen != 5 { |
| 566 | return ScriptNonStandard, nil, false |
| 567 | } |
| 568 | if s.ParsedOpCodes[1].OpValue != opcodes.OP_HASH160 || |
| 569 | s.ParsedOpCodes[2].Length != 20 || |
| 570 | s.ParsedOpCodes[3].OpValue != opcodes.OP_EQUALVERIFY || |
| 571 | s.ParsedOpCodes[4].OpValue != opcodes.OP_CHECKSIG { |
| 572 | return ScriptNonStandard, nil, false |