Skip to content

Commit

Permalink
txscript: Optimize IsPayToWitnessPubKeyHash
Browse files Browse the repository at this point in the history
This converts the IsPayToWitnessPubKeyHash function to analyze the raw
script instead of 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 extractWitnessPubKeyHash and works with the raw script
bytes to simultaneously deteremine if the script is a p2wkh, and in case
it is, extract and return the hash. The second new function is name
isWitnessPubKeyHashScript which is defined in terms of the former.

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

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

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

benchmark                          old ns/op     new ns/op     delta
BenchmarkIsWitnessPubKeyHash-8     68927         0.53          -100.00%

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

benchmark                          old bytes     new bytes     delta
BenchmarkIsWitnessPubKeyHash-8     311299        0             -100.00%
  • Loading branch information
cfromknecht committed Feb 5, 2021
1 parent c1d1b0e commit 344636f
Show file tree
Hide file tree
Showing 2 changed files with 20 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 @@ -110,11 +110,7 @@ func IsPayToWitnessScriptHash(script []byte) bool {
// IsPayToWitnessPubKeyHash returns true if the is in the standard
// pay-to-witness-pubkey-hash (P2WKH) format, false otherwise.
func IsPayToWitnessPubKeyHash(script []byte) bool {
pops, err := parseScript(script)
if err != nil {
return false
}
return isWitnessPubKeyHash(pops)
return isWitnessPubKeyHashScript(script)
}

// isWitnessPubKeyHash returns true if the passed script is a
Expand Down
19 changes: 19 additions & 0 deletions txscript/standard.go
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,25 @@ func IsMultisigSigScript(script []byte) bool {
return isMultisigScript(scriptVersion, possibleRedeemScript)
}

// extractWitnessPubKeyHash extracts the witness public key hash from the passed
// script if it is a standard witness-pay-to-pubkey-hash script. It will return
// nil otherwise.
func extractWitnessPubKeyHash(script []byte) []byte {
if len(script) == 22 &&
script[0] == OP_0 &&
script[1] == OP_DATA_20 {

return script[2:22]
}
return nil
}

// isWitnessPubKeyHashScript returns whether or not the passed script is a
// standard witness-pay-to-pubkey-hash script.
func isWitnessPubKeyHashScript(script []byte) bool {
return extractWitnessPubKeyHash(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 344636f

Please sign in to comment.