txscript: refactor ComputePkScript

This commit is contained in:
Wilmer Paulino 2019-05-30 12:41:25 -07:00
parent 545bc5d474
commit 5328af0b63
No known key found for this signature in database
GPG key ID: 6DF57B9F9514972F

View file

@ -156,28 +156,29 @@ func (s PkScript) String() string {
return str return str
} }
// ComputePkScript computes the pkScript of an transaction output by looking at // ComputePkScript computes the script of an output by looking at the spending
// the transaction input's signature script or witness. // input's signature script or witness.
// //
// NOTE: Only P2PKH, P2SH, P2WSH, and P2WPKH redeem scripts are supported. // NOTE: Only P2PKH, P2SH, P2WSH, and P2WPKH redeem scripts are supported.
func ComputePkScript(sigScript []byte, witness wire.TxWitness) (PkScript, error) { func ComputePkScript(sigScript []byte, witness wire.TxWitness) (PkScript, error) {
var pkScript PkScript
// Ensure that either an input's signature script or a witness was
// provided.
if len(sigScript) == 0 && len(witness) == 0 {
return pkScript, ErrUnsupportedScriptType
}
// We'll start by checking the input's signature script, if provided.
switch { switch {
case len(sigScript) == 0: case len(sigScript) > 0:
break return computeNonWitnessPkScript(sigScript)
case len(witness) > 0:
return computeWitnessPkScript(witness)
default:
return PkScript{}, ErrUnsupportedScriptType
}
}
// computeNonWitnessPkScript computes the script of an output by looking at the
// spending input's signature script.
func computeNonWitnessPkScript(sigScript []byte) (PkScript, error) {
switch {
// Since we only support P2PKH and P2SH scripts as the only non-witness // Since we only support P2PKH and P2SH scripts as the only non-witness
// script types, we should expect to see a push only script. // script types, we should expect to see a push only script.
case !IsPushOnlyScript(sigScript): case !IsPushOnlyScript(sigScript):
return pkScript, ErrUnsupportedScriptType return PkScript{}, ErrUnsupportedScriptType
// If a signature script is provided with a length long enough to // If a signature script is provided with a length long enough to
// represent a P2PKH script, then we'll attempt to parse the compressed // represent a P2PKH script, then we'll attempt to parse the compressed
@ -193,10 +194,10 @@ func ComputePkScript(sigScript []byte, witness wire.TxWitness) (PkScript, error)
pubKeyHash := hash160(pubKey) pubKeyHash := hash160(pubKey)
script, err := payToPubKeyHashScript(pubKeyHash) script, err := payToPubKeyHashScript(pubKeyHash)
if err != nil { if err != nil {
return pkScript, err return PkScript{}, err
} }
pkScript.class = PubKeyHashTy pkScript := PkScript{class: PubKeyHashTy}
copy(pkScript.script[:], script) copy(pkScript.script[:], script)
return pkScript, nil return pkScript, nil
} }
@ -212,25 +213,30 @@ func ComputePkScript(sigScript []byte, witness wire.TxWitness) (PkScript, error)
// obtain it. // obtain it.
parsedOpcodes, err := parseScript(sigScript) parsedOpcodes, err := parseScript(sigScript)
if err != nil { if err != nil {
return pkScript, err return PkScript{}, err
} }
redeemScript := parsedOpcodes[len(parsedOpcodes)-1].data redeemScript := parsedOpcodes[len(parsedOpcodes)-1].data
scriptHash := hash160(redeemScript) scriptHash := hash160(redeemScript)
script, err := payToScriptHashScript(scriptHash) script, err := payToScriptHashScript(scriptHash)
if err != nil { if err != nil {
return pkScript, err return PkScript{}, err
} }
pkScript.class = ScriptHashTy pkScript := PkScript{class: ScriptHashTy}
copy(pkScript.script[:], script) copy(pkScript.script[:], script)
return pkScript, nil return pkScript, nil
} }
}
// If a witness was provided instead, we'll use the last item of the // computeWitnessPkScript computes the script of an output by looking at the
// witness stack to determine the proper witness type. // spending input's witness.
func computeWitnessPkScript(witness wire.TxWitness) (PkScript, error) {
// We'll use the last item of the witness stack to determine the proper
// witness type.
lastWitnessItem := witness[len(witness)-1] lastWitnessItem := witness[len(witness)-1]
var pkScript PkScript
switch { switch {
// If the witness stack has a size of 2 and its last item is a // If the witness stack has a size of 2 and its last item is a
// compressed public key, then this is a P2WPKH witness. // compressed public key, then this is a P2WPKH witness.
@ -243,7 +249,6 @@ func ComputePkScript(sigScript []byte, witness wire.TxWitness) (PkScript, error)
pkScript.class = WitnessV0PubKeyHashTy pkScript.class = WitnessV0PubKeyHashTy
copy(pkScript.script[:], script) copy(pkScript.script[:], script)
return pkScript, nil
// For any other witnesses, we'll assume it's a P2WSH witness. // For any other witnesses, we'll assume it's a P2WSH witness.
default: default:
@ -255,8 +260,9 @@ func ComputePkScript(sigScript []byte, witness wire.TxWitness) (PkScript, error)
pkScript.class = WitnessV0ScriptHashTy pkScript.class = WitnessV0ScriptHashTy
copy(pkScript.script[:], script) copy(pkScript.script[:], script)
return pkScript, nil
} }
return pkScript, nil
} }
// hash160 returns the RIPEMD160 hash of the SHA-256 HASH of the given data. // hash160 returns the RIPEMD160 hash of the SHA-256 HASH of the given data.