txscript: Return witness version and program in one pass
This commit is contained in:
parent
6fb1c82fe5
commit
8b706344a1
1 changed files with 39 additions and 27 deletions
|
@ -387,6 +387,43 @@ func isWitnessScriptHashScript(script []byte) bool {
|
||||||
return extractWitnessScriptHash(script) != nil
|
return extractWitnessScriptHash(script) != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extractWitnessProgramInfo returns the version and program if the passed
|
||||||
|
// script constitutes a valid witness program. The alst return value indicates
|
||||||
|
// whether or not the script is a valid witness program.
|
||||||
|
func extractWitnessProgramInfo(script []byte) (int, []byte, bool) {
|
||||||
|
// Skip parsing if we know the program is invalid based on size.
|
||||||
|
if len(script) < 4 || len(script) > 42 {
|
||||||
|
return 0, nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
const scriptVersion = 0
|
||||||
|
tokenizer := MakeScriptTokenizer(scriptVersion, script)
|
||||||
|
|
||||||
|
// The first opcode must be a small int.
|
||||||
|
if !tokenizer.Next() ||
|
||||||
|
!isSmallInt(tokenizer.Opcode()) {
|
||||||
|
|
||||||
|
return 0, nil, false
|
||||||
|
}
|
||||||
|
version := asSmallInt(tokenizer.Opcode())
|
||||||
|
|
||||||
|
// 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 0, nil, false
|
||||||
|
}
|
||||||
|
program := tokenizer.Data()
|
||||||
|
|
||||||
|
// The witness program is valid if there are no more opcodes, and we
|
||||||
|
// terminated without a parsing error.
|
||||||
|
valid := tokenizer.Done() && tokenizer.Err() == nil
|
||||||
|
|
||||||
|
return version, program, valid
|
||||||
|
}
|
||||||
|
|
||||||
// isWitnessProgramScript returns true if the passed script is a witness
|
// isWitnessProgramScript returns true if the passed script is a witness
|
||||||
// program, and false otherwise. A witness program MUST adhere to the following
|
// program, and false otherwise. A witness program MUST adhere to the following
|
||||||
// constraints: there must be exactly two pops (program version and the program
|
// constraints: there must be exactly two pops (program version and the program
|
||||||
|
@ -403,33 +440,8 @@ func isWitnessScriptHashScript(script []byte) bool {
|
||||||
// does not accept a script version, the results are undefined for other script
|
// does not accept a script version, the results are undefined for other script
|
||||||
// versions.
|
// versions.
|
||||||
func isWitnessProgramScript(script []byte) bool {
|
func isWitnessProgramScript(script []byte) bool {
|
||||||
// Skip parsing if we know the program is invalid based on size.
|
_, _, valid := extractWitnessProgramInfo(script)
|
||||||
if len(script) < 4 || len(script) > 42 {
|
return valid
|
||||||
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
|
// isNullDataScript returns whether or not the passed script is a standard
|
||||||
|
|
Loading…
Reference in a new issue