Commit graph

3433 commits

Author SHA1 Message Date
Dave Collins
9dec01adf4 txscript: Optimize ExtractPkScriptAddrs scripthash.
This begins the process of converting the ExtractPkScriptAddrs function
to use the optimized extraction functions recently introduced as part of
the typeOfScript conversion.

In order to ease the review process, the detection of each script type
will be converted in a separate commit such that the script is only
parsed as a fallback for the cases that are not already converted to
more efficient variants.

In particular, this converts the detection for pay-to-script-hash
scripts.
2022-05-23 21:46:21 -07:00
Dave Collins
e4c9d283b5 txscript: Add ExtractPkScriptAddrs benchmarks. 2022-05-23 21:46:21 -07:00
Dave Collins
96c8bc1e93 txscript: Optimize ExtractAtomicSwapDataPushes.
This converts the ExtractAtomicSwapDataPushes function to make use of
the new tokenizer instead of the far less efficient parseScript thereby
significantly optimizing the function.

The new implementation is designed such that it should be fairly easy to
move the function into the atomic swap tools where it more naturally
belongs now that the tokenizer makes it possible to analyze scripts
outside of the txscript module.  Consequently, this also deprecates the
function.

The following is a before and after comparison of attempting to extract
from both a typical atomic swap script and a very large non-atomic swap
script:

benchmark                                       old ns/op     new ns/op     delta
BenchmarkExtractAtomicSwapDataPushesLarge-8     61332         44.4          -99.93%
BenchmarkExtractAtomicSwapDataPushes-8          990           260           -73.74%

benchmark                                       old allocs     new allocs     delta
BenchmarkExtractAtomicSwapDataPushesLarge-8     1              0              -100.00%
BenchmarkExtractAtomicSwapDataPushes-8          2              1              -50.00%

benchmark                                       old bytes     new bytes     delta
BenchmarkExtractAtomicSwapDataPushesLarge-8     311299        0             -100.00%
BenchmarkExtractAtomicSwapDataPushes-8          3168          96            -96.97%
2022-05-23 21:46:21 -07:00
Conner Fromknecht
767dae7adf txscript/scriptnum: add maxscriptnum and maxcltvlength 2022-05-23 21:46:21 -07:00
Dave Collins
76fcfbaa1f txscript: Add ExtractAtomicSwapDataPushes benches. 2022-05-23 21:46:21 -07:00
Dave Collins
ef4e561119 txscript: Make canonicalPush accept raw opcode.
This renames the canonicalPush function to isCanonicalPush and converts
it to accept an opcode as a byte and the associate data as a byte slice
instead of the internal parse opcode data struct in order to make it
more flexible for raw script analysis.

It also updates all callers and tests accordingly.
2022-05-23 21:46:21 -07:00
Dave Collins
afb68c4ea2 txscript: Optimize PushedData.
This converts the PushedData function to make use of the new tokenizer
instead of the far less efficient parseScript thereby significantly
optimizing the function.

Also, the comment is modified to explicitly call out the script version
semantics.

The following is a before and after comparison of extracting the data
from a very large script:

benchmark                 old ns/op     new ns/op     delta
BenchmarkPushedData-8     64837         1790          -97.24%

benchmark                 old allocs     new allocs     delta
BenchmarkPushedData-8     7              6              -14.29%

benchmark                 old bytes     new bytes     delta
BenchmarkPushedData-8     312816        1520          -99.51%
2022-05-23 21:46:21 -07:00
Dave Collins
e063742295 txscript: Add benchmark for PushedData. 2022-05-23 21:46:21 -07:00
Dave Collins
e0cafeb4ca txscript: Optimize CalcMultiSigStats.
This converts the CalcMultiSigStats function to make use of the new
extractMultisigScriptDetails function instead of the far less efficient
parseScript thereby significantly optimizing the function.

The tests are also updated accordingly.

The following is a before and after comparison of analyzing a standard
multisig script:

benchmark                    old ns/op    new ns/op    delta
---------------------------------------------------------------
BenchmarkCalcMultiSigStats   972          79.5         -91.82%

benchmark                    old allocs   new allocs   delta
---------------------------------------------------------------
BenchmarkCalcMultiSigStats   1            0            -100.00%

benchmark                    old bytes    new bytes    delta
---------------------------------------------------------------
BenchmarkCalcMultiSigStats   2304         0            -100.00%
2022-05-23 21:46:21 -07:00
Dave Collins
ea7b0e3816 txscript: Remove unused getSigOpCount function. 2022-05-23 21:46:21 -07:00
Dave Collins
e9a777d84e txscript: Remove unused isPushOnly function. 2022-05-23 21:46:21 -07:00
Dave Collins
ded9b8c506 txscript: Convert CalcScriptInfo.
This converts CalcScriptInfo and dependent expectedInputs to make use of
the new script tokenizer as well as several of the other recently added
raw script analysis functions in order to remove the reliance on parsed
opcodes as a step towards utlimately removing them altogether.

It is worth noting that this has the side effect of significantly
optimizing the function as well, however, since it is deprecated, no
benchmarks are provided.
2022-05-23 21:46:21 -07:00
Conner Fromknecht
0edfee87d6 txscript: Remove unused isWitnessScriptHash 2022-05-23 21:46:21 -07:00
Conner Fromknecht
6e0abb61bd txscript: Optimize typeOfScript for witness-script-hash
This concludes the process of converting the typeOfScript function to
use a combination of raw script analysis and the new tokenizer instead
of the far less efficient parsed opcodes.

In particular, it converts the detection of witness script hash scripts
to use raw script analysis and the new tokenizer.

With all of the limbs now useing optimized variants, the following is a
before an after comparison of calling GetScriptClass on a large script:

benchmark                     old ns/op     new ns/op     delta
BenchmarkGetScriptClass-8     61515         15.3          -99.98%

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

benchmark                     old bytes     new bytes     delta
BenchmarkGetScriptClass-8     311299        0             -100.00%
2022-05-23 21:46:21 -07:00
Conner Fromknecht
918278a251 txscript: Optimize typeOfScript witness-pubkey-hash
This continues the process of converting the typeOfScript function to
use a combination of raw script analysis and the new tokenizer instead
of the far less efficient parsed opcodes.

In particular, it converts the detection of witness pubkey hash scripts
to use raw script analysis and the new tokenizer.

The following is a before and after comparison of analyzing a large
script:

benchmark                          old ns/op     new ns/op     delta
BenchmarkIsWitnessPubKeyHash-8     61688         62839         +1.87%

benchmark                          old allocs     new allocs     delta
BenchmarkIsWitnessPubKeyHash-8     1              1              +0.00%

benchmark                          old bytes     new bytes     delta
BenchmarkIsWitnessPubKeyHash-8     311299        311299        +0.00%
2022-05-23 21:46:21 -07:00
Dave Collins
9cfaf49024 txscript: Remove unused isNullData function. 2022-05-23 21:46:21 -07:00
Conner Fromknecht
b5e58f4a8d txscript: Optimize typeOfScript for null data scripts
This continues the process of converting the typeOfScript function to
use a combination of raw script analysize and the tokenizer instead of
parsed opcode, with the intent of significanty optimizing the function.

In particular, it converts the detection of null data scripts to use raw
script analysis.
2022-05-23 21:46:21 -07:00
Dave Collins
461335437a txscript: Remove unused isPubkeyHash function. 2022-05-23 21:46:21 -07:00
Dave Collins
c52f41a5af txscript: Optimize typeOfScript pay-to-pubkey-hash.
This continues the process of converting the typeOfScript function to
use a combination of raw script analysis and the new tokenizer instead
of the far less efficient parsed opcodes.

In particular, it converts the detection of pay-to-pubkey-hash scripts
to use raw script analysis.
2022-05-23 21:46:21 -07:00
Dave Collins
cb4018a1d4 txscript: Remove unused isPubkey function. 2022-05-23 21:46:21 -07:00
Conner Fromknecht
b1544cd4a9 txscript: Optimze typeOfScript pay-to-pubkey
This continues the process of converting the typeOfScript function to
use a combination of raw script analysis and the new tokenizer instead
of the face less efficient parsed opcodes, with the intent of
significantly optimizing the function.

In particular, it converts the detection of pay-to-pubkey scripts to use
raw script analysis.
2022-05-23 21:46:21 -07:00
Dave Collins
1f25921172 txscript: Remove unused isMultiSig function. 2022-05-23 21:46:21 -07:00
Dave Collins
cfb6bc9399 txscript: Optimize typeOfScript multisig.
This continues the process of converting the typeOfScript function to
use a combination of raw script analysis and the new tokenizer instead
of the far less efficient parsed opcodes.

In particular, for this commit, since the ability to detect multisig
scripts via the new tokenizer is now available, the function is simply
updated to make use of it.
2022-05-23 21:46:21 -07:00
Dave Collins
c85458bc7c txscript: Remove unused isScriptHash function. 2022-05-23 21:46:21 -07:00
Dave Collins
603c2e3b2b txscript: Optimize typeOfScript pay-to-script-hash.
This begins the process of converting the typeOfScript function to use a
combination of raw script analysis and the new tokenizer instead of the
far less efficient parsed opcodes with the intent of significantly
optimizing the function.

In order to ease the review process, each script type will be converted
in a separate commit and the typeOfScript function will be updated such
that the script is only parsed as a fallback for the cases that are not
already converted to more efficient raw script variants.

In particular, for this commit, since the ability to detect
pay-to-script-hash via raw script analysis is now available, the
function is simply updated to make use of it.
2022-05-23 21:46:21 -07:00
Dave Collins
9ac8abd519 txscript: Make typeOfScript accept raw script.
This converts the typeOfScript function to accept a script version and
raw script instead of an array of internal parsed opcodes in order to
make it more flexible for raw script analysis.

Also, this adds a comment to CalcScriptInfo to call out the specific
version semantics and deprecates the function since nothing currently
uses it, and the relevant information can now be obtained by callers
more directly through the use of the new script tokenizer.

All other callers are updated accordingly.
2022-05-23 21:46:21 -07:00
Dave Collins
aa5a1d1648 txscript: Add benchmark for GetScriptClass. 2022-05-23 21:46:21 -07:00
Conner Fromknecht
43e2a2acb2 txscript: Optimize GetWitnessSigOpCount
This converts the GetWitnessSigOpCount function to use a combination of
raw script analysis and the new tokenizer instead of the far less
efficeint parseScript, thereby significantly optimizing the funciton.

In particular, it use the recently added countSigOpsv0 in precise mode
to avoid calling paseScript.
2022-05-23 21:46:21 -07:00
Conner Fromknecht
83442d60bf txscript: add GetWitnessSigOpCountBenchmarks 2022-05-23 21:46:21 -07:00
Dave Collins
b607be0852 txscript: Optimize GetPreciseSigOpCount.
This converts the GetPreciseSigOpCount function to use a combination of
raw script analysis and the new tokenizer instead of the far less
efficient parseScript thereby significantly optimizing the function.

In particular it uses the recently converted isScriptHashScript,
IsPushOnlyScript, and countSigOpsV0 functions along with the recently
added finalOpcodeData functions.

It also modifies the comment 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
BenchmarkGetPreciseSigOpCount-8     130223        742           -99.43%

benchmark                           old allocs     new allocs     delta
BenchmarkGetPreciseSigOpCount-8     3              0              -100.00%

benchmark                           old bytes     new bytes     delta
BenchmarkGetPreciseSigOpCount-8     623367        0             -100.00%
2022-05-23 21:46:21 -07:00
Dave Collins
8de1bc3ecc txscript: Add benchmark for GetPreciseSigOpCount. 2022-05-23 21:46:21 -07:00
Dave Collins
873339c5bc txscript: Optimize GetSigOpCount.
This converts the GetSigOpCount function to make use of the new
tokenizer instead of the far less efficient parseScript thereby
significantly optimizing the function.

A new function named countSigOpsV0 which accepts the raw script is
introduced to perform the bulk of the work so it can be reused for
precise signature operation counting as well in a later commit.  It
retains the same semantics in terms of counting the number of signature
operations either up to the first parse error or the end of the script
in the case it parses successfully as required by consensus.

Finally, this also deprecates the getSigOpCount function that requires
opcodes in favor of the new function and modifies the comment on
GetSigOpCount 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
BenchmarkGetSigOpCount-8     61051         677           -98.89%

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

benchmark                    old bytes     new bytes     delta
BenchmarkGetSigOpCount-8     311299        0             -100.00%
2022-05-23 21:46:21 -07:00
Dave Collins
c7218b2622 txscript: Add benchmark for GetSigOpCount. 2022-05-23 21:46:21 -07:00
Conner Fromknecht
f1ab6cc7cb txscript/engine: Check ps2h push before parsing script
This moves the check for non push-only pay-to-script-hash signature
scripts before the script parsing logic when creating a new engine
instance to avoid the extra overhead in the error case.
2022-05-23 21:46:21 -07:00
Conner Fromknecht
2674b2926b txscript/engine: Use optimized isScriptHashScript 2022-05-23 21:46:21 -07:00
Conner Fromknecht
c0b2b10241 txscript/engine: Use optimized IsPushOnlyScript 2022-05-23 21:46:21 -07:00
Conner Fromknecht
1814b48565 txscript/engine: Optimize new engine push only script
This modifies the check for whether or not a pay-to-script-hash
signature script is a push only script to make use of the new and more
efficient raw script function.

Also, since the script will have already been checked further above when
the ScriptVerifySigPushOnly flags is set, avoid checking it again in
that case.

Backport of af67951b9a66df3aac1bf3d6376af0730287bbf2
2022-05-23 21:46:21 -07:00
Dave Collins
814f0bae89 txscript: Optimize IsUnspendable.
This converts the IsUnspendable function to make use of a combination of
raw script analysis and the new tokenizer instead of the far less
efficient parseScript thereby significantly optimizing the function.

It is important to note that this new implementation intentionally has a
semantic difference from the existing implementation in that it will now
report scripts that are larger than the max allowed script size are
unspendable as well.

Finally, the comment is modified to explicitly call out the script
version semantics.

Note: this function was recently optimized in master, so the gains here
are less noticable than other optimizations.

The following is a before and after comparison of analyzing a large
script:

benchmark                    old ns/op     new ns/op     delta
BenchmarkIsUnspendable-8     656           584           -10.98%

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

benchmark                    old bytes     new bytes     delta
BenchmarkIsUnspendable-8     1             0             -100.00%
2022-05-23 21:46:21 -07:00
Dave Collins
90e7a42585 txscript: Add benchmark for IsUnspendable. 2022-05-23 21:46:21 -07:00
Conner Fromknecht
b4f144ad8c txscript: Optimize IsNullData
This converts the IsNullData function to analyze the raw script instead
of using the far less efficient parseScript, thereby significantly
optimizing the function.

The following is a before and after comparison of analyzing a large
script:

benchmark                       old ns/op     new ns/op     delta
BenchmarkIsNullDataScript-8     62495         2.65          -100.00%

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

benchmark                       old bytes     new bytes     delta
BenchmarkIsNullDataScript-8     311299        0             -100.00%
2022-05-23 21:46:21 -07:00
Dave Collins
4878db49cf txscript: Add benchmark for IsNullData 2022-05-23 21:46:21 -07:00
Conner Fromknecht
44c6be3d4e txscript: Optimize IsPayToWitnessScriptHash
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%
2022-05-23 21:46:21 -07:00
Conner Fromknecht
b3dd941a77 txscript: Add benchmark for IsPayToWitnessScriptHash 2022-05-23 21:46:21 -07:00
Conner Fromknecht
4d8edfe6d9 txscript: Optimize IsPayToWitnessPubKeyHash
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%
2022-05-23 21:46:21 -07:00
Conner Fromknecht
38ade2c48f txscript: Add benchmark IsPayToWitnessPubkeyHash 2022-05-23 21:46:21 -07:00
Dave Collins
02ddaf29fd 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%
2022-05-23 21:46:21 -07:00
Dave Collins
2b5edd2b5e txscript: Add benchmark for IsPushOnlyScript. 2022-05-23 21:46:21 -07:00
Dave Collins
6be04a8e43 txscript: Optimize IsMultisigSigScript.
This converts the IsMultisigSigScript function to analyze the raw script
and make use of the new tokenizer instead of the far less efficient
parseScript thereby significantly optimizing the function.

In order to accomplish this, it first rejects scripts that can't
possibly fit the bill due to the final byte of what would be the redeem
script not being the appropriate opcode or the overall script not having
enough bytes.  Then, it uses a new function that is introduced named
finalOpcodeData that uses the tokenizer to return any data associated
with the final opcode in the signature script (which will be nil for
non-push opcodes or if the script fails to parse) and analyzes it as if
it were a redeem script when it is non nil.

It is also worth noting that this new implementation intentionally has
the same semantic difference from the existing implementation as the
updated IsMultisigScript function in regards to allowing zero pubkeys
whereas previously it incorrectly required at least one pubkey.

Finally, the comment is modified to explicitly call out the script
version semantics.

The following is a before and after comparison of analyzing a large
script that is not a multisig script and both a 1-of-2 multisig public
key script (which should be false) and a signature script comprised of a
pay-to-script-hash 1-of-2 multisig redeem script (which should be true):

benchmark                               old ns/op     new ns/op     delta
BenchmarkIsMultisigSigScriptLarge-8     69328         2.93          -100.00%
BenchmarkIsMultisigSigScript-8          2375          146           -93.85%

benchmark                               old allocs     new allocs     delta
BenchmarkIsMultisigSigScriptLarge-8     5              0              -100.00%
BenchmarkIsMultisigSigScript-8          3              0              -100.00%

benchmark                               old bytes     new bytes     delta
BenchmarkIsMultisigSigScriptLarge-8     330035        0             -100.00%
BenchmarkIsMultisigSigScript-8          9472          0             -100.00%
2022-05-23 21:46:21 -07:00
Dave Collins
3bdeaa46bf txscript: Add benchmarks for IsMutlsigSigScript. 2022-05-23 21:46:21 -07:00
Dave Collins
67e2cbe374 txscript: Optimize IsMultisigScript.
This converts the IsMultisigScript function to make use of the new
tokenizer 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 extractMultisigScriptDetails and works with the raw script
bytes to simultaneously determine if the script is a multisignature
script, and in the case it is, extract and return the relevant details.
The second new function is named isMultisigScript and is defined in
terms of the former.

The extract function accepts the script version, raw script bytes, and a
flag to determine whether or not the public keys should also be
extracted.  The flag is provided because extracting pubkeys results in
an allocation that the caller might wish to avoid.

The extract function approach was chosen 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.

It is important to note that this new implementation intentionally has a
semantic difference from the existing implementation in that it will now
correctly identify a multisig script with zero pubkeys whereas
previously it incorrectly required at least one pubkey.  This change is
acceptable because the function only deals with standardness rather than
consensus rules.

Finally, this also deprecates the isMultiSig function that requires
opcodes in favor of the new functions and deprecates the error return on
the export IsMultisigScript function since it really does not make sense
given the purpose of the function.

The following is a before and after comparison of analyzing both a large
script that is not a multisig script and a 1-of-2 multisig public key
script:

benchmark                            old ns/op     new ns/op     delta
BenchmarkIsMultisigScriptLarge-8     64166         5.52          -99.99%
BenchmarkIsMultisigScript-8          630           59.4          -90.57%

benchmark                            old allocs     new allocs     delta
BenchmarkIsMultisigScriptLarge-8     1              0              -100.00%
BenchmarkIsMultisigScript-8          1              0              -100.00%

benchmark                            old bytes     new bytes     delta
BenchmarkIsMultisigScriptLarge-8     311299        0             -100.00%
BenchmarkIsMultisigScript-8          2304          0             -100.00%
2022-05-23 21:46:21 -07:00