github.com/palcoin-project/palcd@v1.0.0/txscript/standard.go (about) 1 // Copyright (c) 2013-2020 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 "fmt" 9 10 "github.com/palcoin-project/palcd/chaincfg" 11 "github.com/palcoin-project/palcd/wire" 12 "github.com/palcoin-project/palcutil" 13 ) 14 15 const ( 16 // MaxDataCarrierSize is the maximum number of bytes allowed in pushed 17 // data to be considered a nulldata transaction 18 MaxDataCarrierSize = 80 19 20 // StandardVerifyFlags are the script flags which are used when 21 // executing transaction scripts to enforce additional checks which 22 // are required for the script to be considered standard. These checks 23 // help reduce issues related to transaction malleability as well as 24 // allow pay-to-script hash transactions. Note these flags are 25 // different than what is required for the consensus rules in that they 26 // are more strict. 27 // 28 // TODO: This definition does not belong here. It belongs in a policy 29 // package. 30 StandardVerifyFlags = ScriptBip16 | 31 ScriptVerifyDERSignatures | 32 ScriptVerifyStrictEncoding | 33 ScriptVerifyMinimalData | 34 ScriptStrictMultiSig | 35 ScriptDiscourageUpgradableNops | 36 ScriptVerifyCleanStack | 37 ScriptVerifyNullFail | 38 ScriptVerifyCheckLockTimeVerify | 39 ScriptVerifyCheckSequenceVerify | 40 ScriptVerifyLowS | 41 ScriptStrictMultiSig | 42 ScriptVerifyWitness | 43 ScriptVerifyDiscourageUpgradeableWitnessProgram | 44 ScriptVerifyMinimalIf | 45 ScriptVerifyWitnessPubKeyType 46 ) 47 48 // ScriptClass is an enumeration for the list of standard types of script. 49 type ScriptClass byte 50 51 // Classes of script payment known about in the blockchain. 52 const ( 53 NonStandardTy ScriptClass = iota // None of the recognized forms. 54 PubKeyTy // Pay pubkey. 55 PubKeyHashTy // Pay pubkey hash. 56 WitnessV0PubKeyHashTy // Pay witness pubkey hash. 57 ScriptHashTy // Pay to script hash. 58 WitnessV0ScriptHashTy // Pay to witness script hash. 59 MultiSigTy // Multi signature. 60 NullDataTy // Empty data-only (provably prunable). 61 WitnessUnknownTy // Witness unknown 62 ) 63 64 // scriptClassToName houses the human-readable strings which describe each 65 // script class. 66 var scriptClassToName = []string{ 67 NonStandardTy: "nonstandard", 68 PubKeyTy: "pubkey", 69 PubKeyHashTy: "pubkeyhash", 70 WitnessV0PubKeyHashTy: "witness_v0_keyhash", 71 ScriptHashTy: "scripthash", 72 WitnessV0ScriptHashTy: "witness_v0_scripthash", 73 MultiSigTy: "multisig", 74 NullDataTy: "nulldata", 75 WitnessUnknownTy: "witness_unknown", 76 } 77 78 // String implements the Stringer interface by returning the name of 79 // the enum script class. If the enum is invalid then "Invalid" will be 80 // returned. 81 func (t ScriptClass) String() string { 82 if int(t) > len(scriptClassToName) || int(t) < 0 { 83 return "Invalid" 84 } 85 return scriptClassToName[t] 86 } 87 88 // isPubkey returns true if the script passed is a pay-to-pubkey transaction, 89 // false otherwise. 90 func isPubkey(pops []parsedOpcode) bool { 91 // Valid pubkeys are either 33 or 65 bytes. 92 return len(pops) == 2 && 93 (len(pops[0].data) == 33 || len(pops[0].data) == 65) && 94 pops[1].opcode.value == OP_CHECKSIG 95 } 96 97 // isPubkeyHash returns true if the script passed is a pay-to-pubkey-hash 98 // transaction, false otherwise. 99 func isPubkeyHash(pops []parsedOpcode) bool { 100 return len(pops) == 5 && 101 pops[0].opcode.value == OP_DUP && 102 pops[1].opcode.value == OP_HASH160 && 103 pops[2].opcode.value == OP_DATA_20 && 104 pops[3].opcode.value == OP_EQUALVERIFY && 105 pops[4].opcode.value == OP_CHECKSIG 106 107 } 108 109 // isMultiSig returns true if the passed script is a multisig transaction, false 110 // otherwise. 111 func isMultiSig(pops []parsedOpcode) bool { 112 // The absolute minimum is 1 pubkey: 113 // OP_0/OP_1-16 <pubkey> OP_1 OP_CHECKMULTISIG 114 l := len(pops) 115 if l < 4 { 116 return false 117 } 118 if !isSmallInt(pops[0].opcode) { 119 return false 120 } 121 if !isSmallInt(pops[l-2].opcode) { 122 return false 123 } 124 if pops[l-1].opcode.value != OP_CHECKMULTISIG { 125 return false 126 } 127 128 // Verify the number of pubkeys specified matches the actual number 129 // of pubkeys provided. 130 if l-2-1 != asSmallInt(pops[l-2].opcode) { 131 return false 132 } 133 134 for _, pop := range pops[1 : l-2] { 135 // Valid pubkeys are either 33 or 65 bytes. 136 if len(pop.data) != 33 && len(pop.data) != 65 { 137 return false 138 } 139 } 140 return true 141 } 142 143 // isNullData returns true if the passed script is a null data transaction, 144 // false otherwise. 145 func isNullData(pops []parsedOpcode) bool { 146 // A nulldata transaction is either a single OP_RETURN or an 147 // OP_RETURN SMALLDATA (where SMALLDATA is a data push up to 148 // MaxDataCarrierSize bytes). 149 l := len(pops) 150 if l == 1 && pops[0].opcode.value == OP_RETURN { 151 return true 152 } 153 154 return l == 2 && 155 pops[0].opcode.value == OP_RETURN && 156 (isSmallInt(pops[1].opcode) || pops[1].opcode.value <= 157 OP_PUSHDATA4) && 158 len(pops[1].data) <= MaxDataCarrierSize 159 } 160 161 // scriptType returns the type of the script being inspected from the known 162 // standard types. 163 func typeOfScript(pops []parsedOpcode) ScriptClass { 164 if isPubkey(pops) { 165 return PubKeyTy 166 } else if isPubkeyHash(pops) { 167 return PubKeyHashTy 168 } else if isWitnessPubKeyHash(pops) { 169 return WitnessV0PubKeyHashTy 170 } else if isScriptHash(pops) { 171 return ScriptHashTy 172 } else if isWitnessScriptHash(pops) { 173 return WitnessV0ScriptHashTy 174 } else if isMultiSig(pops) { 175 return MultiSigTy 176 } else if isNullData(pops) { 177 return NullDataTy 178 } 179 return NonStandardTy 180 } 181 182 // GetScriptClass returns the class of the script passed. 183 // 184 // NonStandardTy will be returned when the script does not parse. 185 func GetScriptClass(script []byte) ScriptClass { 186 pops, err := parseScript(script) 187 if err != nil { 188 return NonStandardTy 189 } 190 return typeOfScript(pops) 191 } 192 193 // NewScriptClass returns the ScriptClass corresponding to the string name 194 // provided as argument. ErrUnsupportedScriptType error is returned if the 195 // name doesn't correspond to any known ScriptClass. 196 // 197 // Not to be confused with GetScriptClass. 198 func NewScriptClass(name string) (*ScriptClass, error) { 199 for i, n := range scriptClassToName { 200 if n == name { 201 value := ScriptClass(i) 202 return &value, nil 203 } 204 } 205 206 return nil, fmt.Errorf("%w: %s", ErrUnsupportedScriptType, name) 207 } 208 209 // expectedInputs returns the number of arguments required by a script. 210 // If the script is of unknown type such that the number can not be determined 211 // then -1 is returned. We are an internal function and thus assume that class 212 // is the real class of pops (and we can thus assume things that were determined 213 // while finding out the type). 214 func expectedInputs(pops []parsedOpcode, class ScriptClass) int { 215 switch class { 216 case PubKeyTy: 217 return 1 218 219 case PubKeyHashTy: 220 return 2 221 222 case WitnessV0PubKeyHashTy: 223 return 2 224 225 case ScriptHashTy: 226 // Not including script. That is handled by the caller. 227 return 1 228 229 case WitnessV0ScriptHashTy: 230 // Not including script. That is handled by the caller. 231 return 1 232 233 case MultiSigTy: 234 // Standard multisig has a push a small number for the number 235 // of sigs and number of keys. Check the first push instruction 236 // to see how many arguments are expected. typeOfScript already 237 // checked this so we know it'll be a small int. Also, due to 238 // the original bitcoind bug where OP_CHECKMULTISIG pops an 239 // additional item from the stack, add an extra expected input 240 // for the extra push that is required to compensate. 241 return asSmallInt(pops[0].opcode) + 1 242 243 case NullDataTy: 244 fallthrough 245 default: 246 return -1 247 } 248 } 249 250 // ScriptInfo houses information about a script pair that is determined by 251 // CalcScriptInfo. 252 type ScriptInfo struct { 253 // PkScriptClass is the class of the public key script and is equivalent 254 // to calling GetScriptClass on it. 255 PkScriptClass ScriptClass 256 257 // NumInputs is the number of inputs provided by the public key script. 258 NumInputs int 259 260 // ExpectedInputs is the number of outputs required by the signature 261 // script and any pay-to-script-hash scripts. The number will be -1 if 262 // unknown. 263 ExpectedInputs int 264 265 // SigOps is the number of signature operations in the script pair. 266 SigOps int 267 } 268 269 // CalcScriptInfo returns a structure providing data about the provided script 270 // pair. It will error if the pair is in someway invalid such that they can not 271 // be analysed, i.e. if they do not parse or the pkScript is not a push-only 272 // script 273 func CalcScriptInfo(sigScript, pkScript []byte, witness wire.TxWitness, 274 bip16, segwit bool) (*ScriptInfo, error) { 275 276 sigPops, err := parseScript(sigScript) 277 if err != nil { 278 return nil, err 279 } 280 281 pkPops, err := parseScript(pkScript) 282 if err != nil { 283 return nil, err 284 } 285 286 // Push only sigScript makes little sense. 287 si := new(ScriptInfo) 288 si.PkScriptClass = typeOfScript(pkPops) 289 290 // Can't have a signature script that doesn't just push data. 291 if !isPushOnly(sigPops) { 292 return nil, scriptError(ErrNotPushOnly, 293 "signature script is not push only") 294 } 295 296 si.ExpectedInputs = expectedInputs(pkPops, si.PkScriptClass) 297 298 switch { 299 // Count sigops taking into account pay-to-script-hash. 300 case si.PkScriptClass == ScriptHashTy && bip16 && !segwit: 301 // The pay-to-hash-script is the final data push of the 302 // signature script. 303 script := sigPops[len(sigPops)-1].data 304 shPops, err := parseScript(script) 305 if err != nil { 306 return nil, err 307 } 308 309 shInputs := expectedInputs(shPops, typeOfScript(shPops)) 310 if shInputs == -1 { 311 si.ExpectedInputs = -1 312 } else { 313 si.ExpectedInputs += shInputs 314 } 315 si.SigOps = getSigOpCount(shPops, true) 316 317 // All entries pushed to stack (or are OP_RESERVED and exec 318 // will fail). 319 si.NumInputs = len(sigPops) 320 321 // If segwit is active, and this is a regular p2wkh output, then we'll 322 // treat the script as a p2pkh output in essence. 323 case si.PkScriptClass == WitnessV0PubKeyHashTy && segwit: 324 325 si.SigOps = GetWitnessSigOpCount(sigScript, pkScript, witness) 326 si.NumInputs = len(witness) 327 328 // We'll attempt to detect the nested p2sh case so we can accurately 329 // count the signature operations involved. 330 case si.PkScriptClass == ScriptHashTy && 331 IsWitnessProgram(sigScript[1:]) && bip16 && segwit: 332 333 // Extract the pushed witness program from the sigScript so we 334 // can determine the number of expected inputs. 335 pkPops, _ := parseScript(sigScript[1:]) 336 shInputs := expectedInputs(pkPops, typeOfScript(pkPops)) 337 if shInputs == -1 { 338 si.ExpectedInputs = -1 339 } else { 340 si.ExpectedInputs += shInputs 341 } 342 343 si.SigOps = GetWitnessSigOpCount(sigScript, pkScript, witness) 344 345 si.NumInputs = len(witness) 346 si.NumInputs += len(sigPops) 347 348 // If segwit is active, and this is a p2wsh output, then we'll need to 349 // examine the witness script to generate accurate script info. 350 case si.PkScriptClass == WitnessV0ScriptHashTy && segwit: 351 // The witness script is the final element of the witness 352 // stack. 353 witnessScript := witness[len(witness)-1] 354 pops, _ := parseScript(witnessScript) 355 356 shInputs := expectedInputs(pops, typeOfScript(pops)) 357 if shInputs == -1 { 358 si.ExpectedInputs = -1 359 } else { 360 si.ExpectedInputs += shInputs 361 } 362 363 si.SigOps = GetWitnessSigOpCount(sigScript, pkScript, witness) 364 si.NumInputs = len(witness) 365 366 default: 367 si.SigOps = getSigOpCount(pkPops, true) 368 369 // All entries pushed to stack (or are OP_RESERVED and exec 370 // will fail). 371 si.NumInputs = len(sigPops) 372 } 373 374 return si, nil 375 } 376 377 // CalcMultiSigStats returns the number of public keys and signatures from 378 // a multi-signature transaction script. The passed script MUST already be 379 // known to be a multi-signature script. 380 func CalcMultiSigStats(script []byte) (int, int, error) { 381 pops, err := parseScript(script) 382 if err != nil { 383 return 0, 0, err 384 } 385 386 // A multi-signature script is of the pattern: 387 // NUM_SIGS PUBKEY PUBKEY PUBKEY... NUM_PUBKEYS OP_CHECKMULTISIG 388 // Therefore the number of signatures is the oldest item on the stack 389 // and the number of pubkeys is the 2nd to last. Also, the absolute 390 // minimum for a multi-signature script is 1 pubkey, so at least 4 391 // items must be on the stack per: 392 // OP_1 PUBKEY OP_1 OP_CHECKMULTISIG 393 if len(pops) < 4 { 394 str := fmt.Sprintf("script %x is not a multisig script", script) 395 return 0, 0, scriptError(ErrNotMultisigScript, str) 396 } 397 398 numSigs := asSmallInt(pops[0].opcode) 399 numPubKeys := asSmallInt(pops[len(pops)-2].opcode) 400 return numPubKeys, numSigs, nil 401 } 402 403 // payToPubKeyHashScript creates a new script to pay a transaction 404 // output to a 20-byte pubkey hash. It is expected that the input is a valid 405 // hash. 406 func payToPubKeyHashScript(pubKeyHash []byte) ([]byte, error) { 407 return NewScriptBuilder().AddOp(OP_DUP).AddOp(OP_HASH160). 408 AddData(pubKeyHash).AddOp(OP_EQUALVERIFY).AddOp(OP_CHECKSIG). 409 Script() 410 } 411 412 // payToWitnessPubKeyHashScript creates a new script to pay to a version 0 413 // pubkey hash witness program. The passed hash is expected to be valid. 414 func payToWitnessPubKeyHashScript(pubKeyHash []byte) ([]byte, error) { 415 return NewScriptBuilder().AddOp(OP_0).AddData(pubKeyHash).Script() 416 } 417 418 // payToScriptHashScript creates a new script to pay a transaction output to a 419 // script hash. It is expected that the input is a valid hash. 420 func payToScriptHashScript(scriptHash []byte) ([]byte, error) { 421 return NewScriptBuilder().AddOp(OP_HASH160).AddData(scriptHash). 422 AddOp(OP_EQUAL).Script() 423 } 424 425 // payToWitnessPubKeyHashScript creates a new script to pay to a version 0 426 // script hash witness program. The passed hash is expected to be valid. 427 func payToWitnessScriptHashScript(scriptHash []byte) ([]byte, error) { 428 return NewScriptBuilder().AddOp(OP_0).AddData(scriptHash).Script() 429 } 430 431 // payToPubkeyScript creates a new script to pay a transaction output to a 432 // public key. It is expected that the input is a valid pubkey. 433 func payToPubKeyScript(serializedPubKey []byte) ([]byte, error) { 434 return NewScriptBuilder().AddData(serializedPubKey). 435 AddOp(OP_CHECKSIG).Script() 436 } 437 438 // PayToAddrScript creates a new script to pay a transaction output to a the 439 // specified address. 440 func PayToAddrScript(addr palcutil.Address) ([]byte, error) { 441 const nilAddrErrStr = "unable to generate payment script for nil address" 442 443 switch addr := addr.(type) { 444 case *palcutil.AddressPubKeyHash: 445 if addr == nil { 446 return nil, scriptError(ErrUnsupportedAddress, 447 nilAddrErrStr) 448 } 449 return payToPubKeyHashScript(addr.ScriptAddress()) 450 451 case *palcutil.AddressScriptHash: 452 if addr == nil { 453 return nil, scriptError(ErrUnsupportedAddress, 454 nilAddrErrStr) 455 } 456 return payToScriptHashScript(addr.ScriptAddress()) 457 458 case *palcutil.AddressPubKey: 459 if addr == nil { 460 return nil, scriptError(ErrUnsupportedAddress, 461 nilAddrErrStr) 462 } 463 return payToPubKeyScript(addr.ScriptAddress()) 464 465 case *palcutil.AddressWitnessPubKeyHash: 466 if addr == nil { 467 return nil, scriptError(ErrUnsupportedAddress, 468 nilAddrErrStr) 469 } 470 return payToWitnessPubKeyHashScript(addr.ScriptAddress()) 471 case *palcutil.AddressWitnessScriptHash: 472 if addr == nil { 473 return nil, scriptError(ErrUnsupportedAddress, 474 nilAddrErrStr) 475 } 476 return payToWitnessScriptHashScript(addr.ScriptAddress()) 477 } 478 479 str := fmt.Sprintf("unable to generate payment script for unsupported "+ 480 "address type %T", addr) 481 return nil, scriptError(ErrUnsupportedAddress, str) 482 } 483 484 // NullDataScript creates a provably-prunable script containing OP_RETURN 485 // followed by the passed data. An Error with the error code ErrTooMuchNullData 486 // will be returned if the length of the passed data exceeds MaxDataCarrierSize. 487 func NullDataScript(data []byte) ([]byte, error) { 488 if len(data) > MaxDataCarrierSize { 489 str := fmt.Sprintf("data size %d is larger than max "+ 490 "allowed size %d", len(data), MaxDataCarrierSize) 491 return nil, scriptError(ErrTooMuchNullData, str) 492 } 493 494 return NewScriptBuilder().AddOp(OP_RETURN).AddData(data).Script() 495 } 496 497 // MultiSigScript returns a valid script for a multisignature redemption where 498 // nrequired of the keys in pubkeys are required to have signed the transaction 499 // for success. An Error with the error code ErrTooManyRequiredSigs will be 500 // returned if nrequired is larger than the number of keys provided. 501 func MultiSigScript(pubkeys []*palcutil.AddressPubKey, nrequired int) ([]byte, error) { 502 if len(pubkeys) < nrequired { 503 str := fmt.Sprintf("unable to generate multisig script with "+ 504 "%d required signatures when there are only %d public "+ 505 "keys available", nrequired, len(pubkeys)) 506 return nil, scriptError(ErrTooManyRequiredSigs, str) 507 } 508 509 builder := NewScriptBuilder().AddInt64(int64(nrequired)) 510 for _, key := range pubkeys { 511 builder.AddData(key.ScriptAddress()) 512 } 513 builder.AddInt64(int64(len(pubkeys))) 514 builder.AddOp(OP_CHECKMULTISIG) 515 516 return builder.Script() 517 } 518 519 // PushedData returns an array of byte slices containing any pushed data found 520 // in the passed script. This includes OP_0, but not OP_1 - OP_16. 521 func PushedData(script []byte) ([][]byte, error) { 522 pops, err := parseScript(script) 523 if err != nil { 524 return nil, err 525 } 526 527 var data [][]byte 528 for _, pop := range pops { 529 if pop.data != nil { 530 data = append(data, pop.data) 531 } else if pop.opcode.value == OP_0 { 532 data = append(data, nil) 533 } 534 } 535 return data, nil 536 } 537 538 // ExtractPkScriptAddrs returns the type of script, addresses and required 539 // signatures associated with the passed PkScript. Note that it only works for 540 // 'standard' transaction script types. Any data such as public keys which are 541 // invalid are omitted from the results. 542 func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (ScriptClass, []palcutil.Address, int, error) { 543 var addrs []palcutil.Address 544 var requiredSigs int 545 546 // No valid addresses or required signatures if the script doesn't 547 // parse. 548 pops, err := parseScript(pkScript) 549 if err != nil { 550 return NonStandardTy, nil, 0, err 551 } 552 553 scriptClass := typeOfScript(pops) 554 switch scriptClass { 555 case PubKeyHashTy: 556 // A pay-to-pubkey-hash script is of the form: 557 // OP_DUP OP_HASH160 <hash> OP_EQUALVERIFY OP_CHECKSIG 558 // Therefore the pubkey hash is the 3rd item on the stack. 559 // Skip the pubkey hash if it's invalid for some reason. 560 requiredSigs = 1 561 addr, err := palcutil.NewAddressPubKeyHash(pops[2].data, 562 chainParams) 563 if err == nil { 564 addrs = append(addrs, addr) 565 } 566 567 case WitnessV0PubKeyHashTy: 568 // A pay-to-witness-pubkey-hash script is of thw form: 569 // OP_0 <20-byte hash> 570 // Therefore, the pubkey hash is the second item on the stack. 571 // Skip the pubkey hash if it's invalid for some reason. 572 requiredSigs = 1 573 addr, err := palcutil.NewAddressWitnessPubKeyHash(pops[1].data, 574 chainParams) 575 if err == nil { 576 addrs = append(addrs, addr) 577 } 578 579 case PubKeyTy: 580 // A pay-to-pubkey script is of the form: 581 // <pubkey> OP_CHECKSIG 582 // Therefore the pubkey is the first item on the stack. 583 // Skip the pubkey if it's invalid for some reason. 584 requiredSigs = 1 585 addr, err := palcutil.NewAddressPubKey(pops[0].data, chainParams) 586 if err == nil { 587 addrs = append(addrs, addr) 588 } 589 590 case ScriptHashTy: 591 // A pay-to-script-hash script is of the form: 592 // OP_HASH160 <scripthash> OP_EQUAL 593 // Therefore the script hash is the 2nd item on the stack. 594 // Skip the script hash if it's invalid for some reason. 595 requiredSigs = 1 596 addr, err := palcutil.NewAddressScriptHashFromHash(pops[1].data, 597 chainParams) 598 if err == nil { 599 addrs = append(addrs, addr) 600 } 601 602 case WitnessV0ScriptHashTy: 603 // A pay-to-witness-script-hash script is of the form: 604 // OP_0 <32-byte hash> 605 // Therefore, the script hash is the second item on the stack. 606 // Skip the script hash if it's invalid for some reason. 607 requiredSigs = 1 608 addr, err := palcutil.NewAddressWitnessScriptHash(pops[1].data, 609 chainParams) 610 if err == nil { 611 addrs = append(addrs, addr) 612 } 613 614 case MultiSigTy: 615 // A multi-signature script is of the form: 616 // <numsigs> <pubkey> <pubkey> <pubkey>... <numpubkeys> OP_CHECKMULTISIG 617 // Therefore the number of required signatures is the 1st item 618 // on the stack and the number of public keys is the 2nd to last 619 // item on the stack. 620 requiredSigs = asSmallInt(pops[0].opcode) 621 numPubKeys := asSmallInt(pops[len(pops)-2].opcode) 622 623 // Extract the public keys while skipping any that are invalid. 624 addrs = make([]palcutil.Address, 0, numPubKeys) 625 for i := 0; i < numPubKeys; i++ { 626 addr, err := palcutil.NewAddressPubKey(pops[i+1].data, 627 chainParams) 628 if err == nil { 629 addrs = append(addrs, addr) 630 } 631 } 632 633 case NullDataTy: 634 // Null data transactions have no addresses or required 635 // signatures. 636 637 case NonStandardTy: 638 // Don't attempt to extract addresses or required signatures for 639 // nonstandard transactions. 640 } 641 642 return scriptClass, addrs, requiredSigs, nil 643 } 644 645 // AtomicSwapDataPushes houses the data pushes found in atomic swap contracts. 646 type AtomicSwapDataPushes struct { 647 RecipientHash160 [20]byte 648 RefundHash160 [20]byte 649 SecretHash [32]byte 650 SecretSize int64 651 LockTime int64 652 } 653 654 // ExtractAtomicSwapDataPushes returns the data pushes from an atomic swap 655 // contract. If the script is not an atomic swap contract, 656 // ExtractAtomicSwapDataPushes returns (nil, nil). Non-nil errors are returned 657 // for unparsable scripts. 658 // 659 // NOTE: Atomic swaps are not considered standard script types by the dcrd 660 // mempool policy and should be used with P2SH. The atomic swap format is also 661 // expected to change to use a more secure hash function in the future. 662 // 663 // This function is only defined in the txscript package due to API limitations 664 // which prevent callers using txscript to parse nonstandard scripts. 665 func ExtractAtomicSwapDataPushes(version uint16, pkScript []byte) (*AtomicSwapDataPushes, error) { 666 pops, err := parseScript(pkScript) 667 if err != nil { 668 return nil, err 669 } 670 671 if len(pops) != 20 { 672 return nil, nil 673 } 674 isAtomicSwap := pops[0].opcode.value == OP_IF && 675 pops[1].opcode.value == OP_SIZE && 676 canonicalPush(pops[2]) && 677 pops[3].opcode.value == OP_EQUALVERIFY && 678 pops[4].opcode.value == OP_SHA256 && 679 pops[5].opcode.value == OP_DATA_32 && 680 pops[6].opcode.value == OP_EQUALVERIFY && 681 pops[7].opcode.value == OP_DUP && 682 pops[8].opcode.value == OP_HASH160 && 683 pops[9].opcode.value == OP_DATA_20 && 684 pops[10].opcode.value == OP_ELSE && 685 canonicalPush(pops[11]) && 686 pops[12].opcode.value == OP_CHECKLOCKTIMEVERIFY && 687 pops[13].opcode.value == OP_DROP && 688 pops[14].opcode.value == OP_DUP && 689 pops[15].opcode.value == OP_HASH160 && 690 pops[16].opcode.value == OP_DATA_20 && 691 pops[17].opcode.value == OP_ENDIF && 692 pops[18].opcode.value == OP_EQUALVERIFY && 693 pops[19].opcode.value == OP_CHECKSIG 694 if !isAtomicSwap { 695 return nil, nil 696 } 697 698 pushes := new(AtomicSwapDataPushes) 699 copy(pushes.SecretHash[:], pops[5].data) 700 copy(pushes.RecipientHash160[:], pops[9].data) 701 copy(pushes.RefundHash160[:], pops[16].data) 702 if pops[2].data != nil { 703 locktime, err := makeScriptNum(pops[2].data, true, 5) 704 if err != nil { 705 return nil, nil 706 } 707 pushes.SecretSize = int64(locktime) 708 } else if op := pops[2].opcode; isSmallInt(op) { 709 pushes.SecretSize = int64(asSmallInt(op)) 710 } else { 711 return nil, nil 712 } 713 if pops[11].data != nil { 714 locktime, err := makeScriptNum(pops[11].data, true, 5) 715 if err != nil { 716 return nil, nil 717 } 718 pushes.LockTime = int64(locktime) 719 } else if op := pops[11].opcode; isSmallInt(op) { 720 pushes.LockTime = int64(asSmallInt(op)) 721 } else { 722 return nil, nil 723 } 724 return pushes, nil 725 }