txscript: Optimize IsWitnessProgram

This commit is contained in:
Conner Fromknecht 2019-04-19 18:58:28 -07:00 committed by Roy Lee
parent 67168099d3
commit 1936f28d33
2 changed files with 48 additions and 14 deletions

View file

@ -103,20 +103,7 @@ func isWitnessPubKeyHash(pops []parsedOpcode) bool {
// witness program must be a small integer (from 0-16), followed by 2-40 bytes
// of pushed data.
func IsWitnessProgram(script []byte) bool {
// The length of the script must be between 4 and 42 bytes. The
// smallest program is the witness version, followed by a data push of
// 2 bytes. The largest allowed witness program has a data push of
// 40-bytes.
if len(script) < 4 || len(script) > 42 {
return false
}
pops, err := parseScript(script)
if err != nil {
return false
}
return isWitnessProgram(pops)
return isWitnessProgramScript(script)
}
// isWitnessProgram returns true if the passed script is a witness program, and
@ -125,6 +112,8 @@ func IsWitnessProgram(script []byte) bool {
// first opcode MUST be a small integer (0-16), the push data MUST be
// canonical, and finally the size of the push data must be between 2 and 40
// bytes.
//
// DEPRECATED: Use isWitnessProgramScript instead.
func isWitnessProgram(pops []parsedOpcode) bool {
return len(pops) == 2 &&
isSmallInt(pops[0].opcode.value) &&

View file

@ -387,6 +387,51 @@ func isWitnessScriptHashScript(script []byte) bool {
return extractWitnessScriptHash(script) != nil
}
// isWitnessProgramScript returns true if the passed script is a witness
// program, and false otherwise. A witness program MUST adhere to the following
// constraints: there must be exactly two pops (program version and the program
// itself), the first opcode MUST be a small integer (0-16), the push data MUST
// be canonical, and finally the size of the push data must be between 2 and 40
// bytes.
//
// The length of the script must be between 4 and 42 bytes. The
// smallest program is the witness version, followed by a data push of
// 2 bytes. The largest allowed witness program has a data push of
// 40-bytes.
//
// 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.
func isWitnessProgramScript(script []byte) bool {
// Skip parsing if we know the program is invalid based on size.
if len(script) < 4 || len(script) > 42 {
return false
}
const scriptVersion = 0
tokenizer := MakeScriptTokenizer(scriptVersion, script)
// The first opcode must be a small int.
if !tokenizer.Next() ||
!isSmallInt(tokenizer.Opcode()) {
return false
}
// The second opcode must be a canonical data push, the length of the
// data push is bounded to 40 by the initial check on overall script
// length.
if !tokenizer.Next() ||
!isCanonicalPush(tokenizer.Opcode(), tokenizer.Data()) {
return false
}
// The witness program is valid if there are no more opcodes, and we
// terminated without a parsing error.
return tokenizer.Done() && tokenizer.Err() == nil
}
// isNullDataScript returns whether or not the passed script is a standard
// null data script.
//