From 9ac8abd5199f23db0db271474e4e909fc933799e Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:33 -0500 Subject: [PATCH] txscript: Make typeOfScript accept raw script. This converts the typeOfScript function to accept a script version and raw script instead of an array of internal parsed opcodes in order to make it more flexible for raw script analysis. Also, this adds a comment to CalcScriptInfo to call out the specific version semantics and deprecates the function since nothing currently uses it, and the relevant information can now be obtained by callers more directly through the use of the new script tokenizer. All other callers are updated accordingly. --- txscript/standard.go | 46 ++++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index 9825f61b..54c04318 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -498,7 +498,19 @@ func isNullDataScript(scriptVersion uint16, script []byte) bool { // scriptType returns the type of the script being inspected from the known // standard types. -func typeOfScript(pops []parsedOpcode) ScriptClass { +// +// NOTE: All scripts that are not version 0 are currently considered non +// standard. +func typeOfScript(scriptVersion uint16, script []byte) ScriptClass { + if scriptVersion != 0 { + return NonStandardTy + } + + pops, err := parseScript(script) + if err != nil { + return NonStandardTy + } + if isPubkey(pops) { return PubKeyTy } else if isPubkeyHash(pops) { @@ -521,11 +533,8 @@ func typeOfScript(pops []parsedOpcode) ScriptClass { // // NonStandardTy will be returned when the script does not parse. func GetScriptClass(script []byte) ScriptClass { - pops, err := parseScript(script) - if err != nil { - return NonStandardTy - } - return typeOfScript(pops) + const scriptVersion = 0 + return typeOfScript(scriptVersion, script) } // NewScriptClass returns the ScriptClass corresponding to the string name @@ -608,9 +617,17 @@ type ScriptInfo struct { // pair. It will error if the pair is in someway invalid such that they can not // be analysed, i.e. if they do not parse or the pkScript is not a push-only // script +// +// NOTE: This function is only valid for version 0 scripts. Since the function +// does not accept a script version, the results are undefined for other script +// versions. +// +// DEPRECATED. This will be removed in the next major version bump. func CalcScriptInfo(sigScript, pkScript []byte, witness wire.TxWitness, bip16, segwit bool) (*ScriptInfo, error) { + const scriptVersion = 0 + sigPops, err := parseScript(sigScript) if err != nil { return nil, err @@ -621,9 +638,8 @@ func CalcScriptInfo(sigScript, pkScript []byte, witness wire.TxWitness, return nil, err } - // Push only sigScript makes little sense. si := new(ScriptInfo) - si.PkScriptClass = typeOfScript(pkPops) + si.PkScriptClass = typeOfScript(scriptVersion, pkScript) // Can't have a signature script that doesn't just push data. if !isPushOnly(sigPops) { @@ -644,7 +660,8 @@ func CalcScriptInfo(sigScript, pkScript []byte, witness wire.TxWitness, return nil, err } - shInputs := expectedInputs(shPops, typeOfScript(shPops)) + redeemClass := typeOfScript(scriptVersion, script) + shInputs := expectedInputs(shPops, redeemClass) if shInputs == -1 { si.ExpectedInputs = -1 } else { @@ -671,7 +688,9 @@ func CalcScriptInfo(sigScript, pkScript []byte, witness wire.TxWitness, // Extract the pushed witness program from the sigScript so we // can determine the number of expected inputs. pkPops, _ := parseScript(sigScript[1:]) - shInputs := expectedInputs(pkPops, typeOfScript(pkPops)) + + redeemClass := typeOfScript(scriptVersion, sigScript[1:]) + shInputs := expectedInputs(pkPops, redeemClass) if shInputs == -1 { si.ExpectedInputs = -1 } else { @@ -691,7 +710,8 @@ func CalcScriptInfo(sigScript, pkScript []byte, witness wire.TxWitness, witnessScript := witness[len(witness)-1] pops, _ := parseScript(witnessScript) - shInputs := expectedInputs(pops, typeOfScript(pops)) + redeemClass := typeOfScript(scriptVersion, witnessScript) + shInputs := expectedInputs(pops, redeemClass) if shInputs == -1 { si.ExpectedInputs = -1 } else { @@ -888,7 +908,9 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (Script return NonStandardTy, nil, 0, err } - scriptClass := typeOfScript(pops) + const scriptVersion = 0 + scriptClass := typeOfScript(scriptVersion, pkScript) + switch scriptClass { case PubKeyHashTy: // A pay-to-pubkey-hash script is of the form: