txscript: Optimize removeOpcodeRaw
This commit is contained in:
parent
30874ff76b
commit
a4720f30e5
2 changed files with 42 additions and 4 deletions
|
@ -269,6 +269,8 @@ func DisasmString(script []byte) (string, error) {
|
||||||
|
|
||||||
// removeOpcode will remove any opcode matching ``opcode'' from the opcode
|
// removeOpcode will remove any opcode matching ``opcode'' from the opcode
|
||||||
// stream in pkscript
|
// stream in pkscript
|
||||||
|
//
|
||||||
|
// DEPRECATED. Use removeOpcodeRaw instead.
|
||||||
func removeOpcode(pkscript []parsedOpcode, opcode byte) []parsedOpcode {
|
func removeOpcode(pkscript []parsedOpcode, opcode byte) []parsedOpcode {
|
||||||
retScript := make([]parsedOpcode, 0, len(pkscript))
|
retScript := make([]parsedOpcode, 0, len(pkscript))
|
||||||
for _, pop := range pkscript {
|
for _, pop := range pkscript {
|
||||||
|
@ -279,6 +281,43 @@ func removeOpcode(pkscript []parsedOpcode, opcode byte) []parsedOpcode {
|
||||||
return retScript
|
return retScript
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// removeOpcodeRaw will return the script after removing any opcodes that match
|
||||||
|
// `opcode`. If the opcode does not appear in script, the original script will
|
||||||
|
// be returned unmodified. Otherwise, a new script will be allocated to contain
|
||||||
|
// the filtered script. This metehod assumes that the script parses
|
||||||
|
// successfully.
|
||||||
|
//
|
||||||
|
// 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 removeOpcodeRaw(script []byte, opcode byte) []byte {
|
||||||
|
// Avoid work when possible.
|
||||||
|
if len(script) == 0 {
|
||||||
|
return script
|
||||||
|
}
|
||||||
|
|
||||||
|
const scriptVersion = 0
|
||||||
|
var result []byte
|
||||||
|
var prevOffset int32
|
||||||
|
|
||||||
|
tokenizer := MakeScriptTokenizer(scriptVersion, script)
|
||||||
|
for tokenizer.Next() {
|
||||||
|
if tokenizer.Opcode() == opcode {
|
||||||
|
if result == nil {
|
||||||
|
result = make([]byte, 0, len(script))
|
||||||
|
result = append(result, script[:prevOffset]...)
|
||||||
|
}
|
||||||
|
} else if result != nil {
|
||||||
|
result = append(result, script[prevOffset:tokenizer.ByteIndex()]...)
|
||||||
|
}
|
||||||
|
prevOffset = tokenizer.ByteIndex()
|
||||||
|
}
|
||||||
|
if result == nil {
|
||||||
|
return script
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// isCanonicalPush returns true if the opcode is either not a push instruction
|
// isCanonicalPush returns true if the opcode is either not a push instruction
|
||||||
// or the data associated with the push instruction uses the smallest
|
// or the data associated with the push instruction uses the smallest
|
||||||
// instruction to do the job. False otherwise.
|
// instruction to do the job. False otherwise.
|
||||||
|
|
|
@ -3981,13 +3981,12 @@ func TestRemoveOpcodes(t *testing.T) {
|
||||||
// tstRemoveOpcode is a convenience function to parse the provided
|
// tstRemoveOpcode is a convenience function to parse the provided
|
||||||
// raw script, remove the passed opcode, then unparse the result back
|
// raw script, remove the passed opcode, then unparse the result back
|
||||||
// into a raw script.
|
// into a raw script.
|
||||||
|
const scriptVersion = 0
|
||||||
tstRemoveOpcode := func(script []byte, opcode byte) ([]byte, error) {
|
tstRemoveOpcode := func(script []byte, opcode byte) ([]byte, error) {
|
||||||
pops, err := parseScript(script)
|
if err := checkScriptParses(scriptVersion, script); err != nil {
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
pops = removeOpcode(pops, opcode)
|
return removeOpcodeRaw(script, opcode), nil
|
||||||
return unparseScript(pops)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
|
Loading…
Reference in a new issue