Skip to content

Commit

Permalink
txscript: Optimize IsPayToWitnessScriptHash
Browse files Browse the repository at this point in the history
This converts the IsPayToWitnessScriptHash function to analyze the raw
script instead of using the far less efficient parseScript, thereby
significantly optimizing the function.

In order to accomplish this, it introduces two new functions. The first
one is named extractWitnessScriptHash and works with the raw script byte
to simultaneously deteremine if the script is a p2wsh script, and in the
case that is is, extract and return the hash. The second new function is
named isWitnessScriptHashScript and is defined in terms of the former.

The extract function approach was chosed because it is common for
callers to want to only extract relevant details from a script if the
script is of the specific type. Extracting those details requires
performing the exact same checks to ensure the script is of the correct
type, so it is more efficient to combine the two into one and define the
type determination in terms of the result, so long as the extraction
does not require allocations.

Finally, this also deprecates the isWitnessScriptHash function that
requires opcodes in favor of the new functions and modifies the comment
on IsPayToWitnessScriptHash to call out the script version semantics.

The following is a before and after comparison of executing
IsPayToWitnessScriptHash on a large script:

benchmark                          old ns/op     new ns/op     delta
BenchmarkIsWitnessScriptHash-8     62774         0.63          -100.00%

benchmark                          old allocs     new allocs     delta
BenchmarkIsWitnessScriptHash-8     1              0              -100.00%

benchmark                          old bytes     new bytes     delta
BenchmarkIsWitnessScriptHash-8     311299        0             -100.00%
  • Loading branch information
cfromknecht committed Feb 5, 2021
1 parent 58a2fa9 commit 5b69223
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 5 deletions.
6 changes: 1 addition & 5 deletions txscript/script.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,7 @@ func isWitnessScriptHash(pops []parsedOpcode) bool {
// IsPayToWitnessScriptHash returns true if the is in the standard
// pay-to-witness-script-hash (P2WSH) format, false otherwise.
func IsPayToWitnessScriptHash(script []byte) bool {
pops, err := parseScript(script)
if err != nil {
return false
}
return isWitnessScriptHash(pops)
return isWitnessScriptHashScript(script)
}

// IsPayToWitnessPubKeyHash returns true if the is in the standard
Expand Down
20 changes: 20 additions & 0 deletions txscript/standard.go
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,26 @@ func isWitnessPubKeyHashScript(script []byte) bool {
return extractWitnessPubKeyHash(script) != nil
}

// extractWitnessScriptHash extracts the witness script hash from the passed
// script if it is standard witness-script-hash script. It will return nil
// otherwise.
func extractWitnessScriptHash(script []byte) []byte {
if len(script) == 34 &&
script[0] == OP_0 &&
script[1] == OP_DATA_32 {

return script[2:34]
}

return nil
}

// isWitnessScriptHashScript returns whether or not the passed script is a
// standard witness-script-hash script.
func isWitnessScriptHashScript(script []byte) bool {
return extractWitnessScriptHash(script) != nil
}

// isNullData returns true if the passed script is a null data transaction,
// false otherwise.
func isNullData(pops []parsedOpcode) bool {
Expand Down

0 comments on commit 5b69223

Please sign in to comment.