txscript: Optimize IsPushOnlyScript.
This converts the IsPushOnlyScript function to make use of the new tokenizer instead of the far less efficient parseScript thereby significantly optimizing the function. It also deprecates the isPushOnly function that requires opcodes in favor of the new function and modifies the comment on IsPushOnlyScript to explicitly call out the script version semantics. The following is a before and after comparison of analyzing a large script: benchmark old ns/op new ns/op delta BenchmarkIsPushOnlyScript-8 62412 622 -99.00% benchmark old allocs new allocs delta BenchmarkIsPushOnlyScript-8 1 0 -100.00% benchmark old bytes new bytes delta BenchmarkIsPushOnlyScript-8 311299 0 -100.00%
This commit is contained in:
parent
ce1513df03
commit
2d5f7cf825
1 changed files with 20 additions and 6 deletions
|
@ -182,6 +182,8 @@ func ExtractWitnessProgramInfo(script []byte) (int, []byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// isPushOnly returns true if the script only pushes data, false otherwise.
|
// isPushOnly returns true if the script only pushes data, false otherwise.
|
||||||
|
//
|
||||||
|
// DEPRECATED. Use IsPushOnlyScript instead.
|
||||||
func isPushOnly(pops []parsedOpcode) bool {
|
func isPushOnly(pops []parsedOpcode) bool {
|
||||||
// NOTE: This function does NOT verify opcodes directly since it is
|
// NOTE: This function does NOT verify opcodes directly since it is
|
||||||
// internal and is only called with parsed opcodes for scripts that did
|
// internal and is only called with parsed opcodes for scripts that did
|
||||||
|
@ -199,15 +201,27 @@ func isPushOnly(pops []parsedOpcode) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsPushOnlyScript returns whether or not the passed script only pushes data.
|
// IsPushOnlyScript returns whether or not the passed script only pushes data
|
||||||
|
// according to the consensus definition of pushing data.
|
||||||
//
|
//
|
||||||
// False will be returned when the script does not parse.
|
// WARNING: This function always treats the passed script as version 0. Great
|
||||||
|
// care must be taken if introducing a new script version because it is used in
|
||||||
|
// consensus which, unfortunately as of the time of this writing, does not check
|
||||||
|
// script versions before checking if it is a push only script which means nodes
|
||||||
|
// on existing rules will treat new version scripts as if they were version 0.
|
||||||
func IsPushOnlyScript(script []byte) bool {
|
func IsPushOnlyScript(script []byte) bool {
|
||||||
pops, err := parseScript(script)
|
const scriptVersion = 0
|
||||||
if err != nil {
|
tokenizer := MakeScriptTokenizer(scriptVersion, script)
|
||||||
return false
|
for tokenizer.Next() {
|
||||||
|
// All opcodes up to OP_16 are data push instructions.
|
||||||
|
// NOTE: This does consider OP_RESERVED to be a data push instruction,
|
||||||
|
// but execution of OP_RESERVED will fail anyway and matches the
|
||||||
|
// behavior required by consensus.
|
||||||
|
if tokenizer.Opcode() > OP_16 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return isPushOnly(pops)
|
return tokenizer.Err() == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseScriptTemplate is the same as parseScript but allows the passing of the
|
// parseScriptTemplate is the same as parseScript but allows the passing of the
|
||||||
|
|
Loading…
Reference in a new issue