Commit Graph

357 Commits

Author SHA1 Message Date
Dave Collins
c598f59151
txscript: Rename removeOpcodeByDataRaw func.
This renames the removeOpcodeByDataRaw to removeOpcodeByData now that
the old version has been removed.
2019-03-26 14:55:41 -05:00
Dave Collins
bd040aea02
txscript: Remove unused removeOpcodeByData func. 2019-03-26 14:55:40 -05:00
Dave Collins
75c48ea8c7
txscript: Refactor engine to use raw scripts.
This refactors the script engine to store and step through raw scripts
by making using of the new zero-allocation script tokenizer as opposed
to the less efficient method of storing and stepping through parsed
opcodes.  It also improves several aspects while refactoring such as
optimizing the disassembly trace, showing all scripts in the trace in
the case of execution failure, and providing additional comments
describing the purpose of each field in the engine.

It should be noted that this is a step towards removing the parsed
opcode struct and associated supporting code altogether, however, in
order to ease the review process, this retains the struct and all
function signatures for opcode execution which make use of an individual
parsed opcode.  Those will be updated in future commits.

The following is an overview of the changes:

- Modify internal engine scripts slice to use raw scripts instead of
  parsed opcodes
- Introduce a tokenizer to the engine to track the current script
- Remove no longer needed script offset parameter from the engine since
  that is tracked by the tokenizer
- Add an opcode index counter for disassembly purposes to the engine
- Update check for valid program counter to only consider the script
  index
  - Update tests for bad program counter accordingly
- Rework the NewEngine function
  - Store the raw scripts
  - Setup the initial tokenizer
  - Explicitly check against version 0 instead of DefaultScriptVersion
    which would break consensus if changed
  - Check the scripts parse according to version 0 semantics to retain
    current consensus rules
  - Improve comments throughout
- Rework the Step function
  - Use the tokenizer and raw scripts
  - Create a parsed opcode on the fly for now to retain existing
    opcode execution function signatures
  - Improve comments throughout
- Update the Execute function
  - Explicitly check against version 0 instead of DefaultScriptVersion
    which would break consensus if changed
  - Improve the disassembly tracing in the case of error
- Update the CheckErrorCondition function
  - Modify clean stack error message to make sense in all cases
  - Improve the comments
- Update the DisasmPC and DisasmScript functions on the engine
  - Use the tokenizer
  - Optimize construction via the use of strings.Builder
- Modify the subScript function to return the raw script bytes since the
  parsed opcodes are no longer stored
- Update the various signature checking opcodes to use the raw opcode
  data removal and signature hash calculation functions since the
  subscript is now a raw script
  - opcodeCheckSig
  - opcodeCheckMultiSig
  - opcodeCheckSigAlt
2019-03-26 14:55:39 -05:00
Dave Collins
280c062930
txscript: Convert to use non-parsed opcode disasm.
This converts the engine's current program counter disasembly to make
use of the standalone disassembly function to remove the dependency on
the parsed opcode struct.

It also updates the tests accordingly.
2019-03-26 14:55:38 -05:00
Dave Collins
e915598b76
txscript: Make min push accept raw opcode and data.
This converts the checkMinimalDataPush function defined on a parsed
opcode to a standalone function which accepts an opcode and data slice
instead in order to make it more flexible for raw script analysis.

It also updates all callers accordingly.
2019-03-26 14:55:38 -05:00
Dave Collins
cfd3753756
txscript: Make isConditional accept raw opcode.
This converts the isConditional function defined on a parsed opcode to a
standalone function named isOpcodeConditional which accepts an opcode as
a byte instead in order to make it more flexible for raw script
analysis.

It also updates all callers accordingly.
2019-03-26 14:55:37 -05:00
Dave Collins
b62655222c
txscript: Make alwaysIllegal accept raw opcode.
This converts the alwaysIllegal function defined on a parsed opcode to a
standalone function named isOpcodeAlwaysIllegal which accepts an opcode
as a byte instead in order to make it more flexible for raw script
analysis.

It also updates all callers accordingly.
2019-03-26 14:55:36 -05:00
Dave Collins
d3518fc150
txscript: Make isDisabled accept raw opcode.
This converts the isDisabled function defined on a parsed opcode to a
standalone function which accepts an opcode as a byte instead in order
to make it more flexible for raw script analysis.

It also updates all callers accordingly.
2019-03-26 14:55:36 -05:00
Dave Collins
f93c1de13f
txscript: Implement efficient opcode data removal.
This introduces a new function named removeOpcodeByDataRaw which accepts
the raw scripts and data to remove versus requiring the parsed opcodes
to both significantly optimize it as well as make it more flexible for
working with raw scripts.

There are several places in the rest of the code that currently only
have access to the parsed opcodes, so this only introduces the function
for use in the future and deprecates the existing one.

Note that, in practice, the script will never actually contain the data
that is intended to be removed since the function is only used during
signature verification to remove the signature itself which would
require some incredibly non-standard code to create.

Thus, as an optimization, it avoids allocating a new script unless there
is actually a match that needs to be removed.

Finally, it updates the tests to use the new function.
2019-03-26 14:55:35 -05:00
Dave Collins
85c7a9ba8e
txscript: Use raw scripts in SignTxOutput.
This converts SignTxOutput and supporting funcs, namely sign,
mergeScripts and mergeMultiSig, to make use of the new tokenizer as well
as some recently added funcs that deal with raw scripts in order to
remove the reliance on parsed opcodes as a step towards utlimately
removing them altogether and updates the comments to explicitly call out
the script version semantics.

It is worth noting that this has the side effect of optimizing the
function as well, however, since this change is not focused on the
optimization aspects, no benchmarks are provided.
2019-03-26 14:52:02 -05:00
Dave Collins
d8d561d4b6
txscript: Correct p2pkSignatureScriptAlt comment. 2019-03-26 14:52:01 -05:00
Dave Collins
706b3a1fcd
txscript: Use raw scripts in RawTxInSignatureAlt.
This converts RawTxInSignatureAlt to make use of the recently converted
CalcSignatureHash function that works with raw scripts in order to
remove the reliance on parsed opcodes as a step towards utlimately
removing them altogether and updates the comment to explicitly call out
the script version semantics.

It is worth noting that this has the side effect of optimizing the
function as well, however, since this change is not focused on the
optimization aspects, no benchmarks are provided.
2019-03-26 14:52:01 -05:00
Dave Collins
7cf42b0a70
txscript: Use raw scripts in RawTxInSignature.
This converts RawTxInSignature to make use of the recently converted
CalcSignatureHash function that works with raw scripts in order to
remove the reliance on parsed opcodes as a step towards utlimately
removing them altogether and updates the comment to explicitly call out
the script version semantics.

It is worth noting that this has the side effect of optimizing the
function as well, however, since this change is not focused on the
optimization aspects, no benchmarks are provided.
2019-03-26 14:52:00 -05:00
Dave Collins
251c9be0a1
txscript: mergeMultiSig function def order cleanup.
This moves the function definition for mergeMultiSig so it is more
consistent with the preferred order used through the codebase.  In
particular, the functions are defined before they're first used and
generally as close as possible to the first use when they're defined in
the same file.
2019-03-26 14:51:59 -05:00
Dave Collins
a247a5207c
txscript: Remove unused isOneByteMaxDataPush func. 2019-03-26 14:51:59 -05:00
Dave Collins
9e3269ec2d
txscript: Remove unused isPubkeyHashAlt function. 2019-03-26 14:51:58 -05:00
Dave Collins
b19b6cbb40
txscript: Remove unused isPubkeyAlt function. 2019-03-26 14:51:57 -05:00
Dave Collins
007264ec21
txscript: Remove unused extractOneBytePush func. 2019-03-26 14:51:57 -05:00
Dave Collins
2fd1dcbbff
txscript: Optimize ExtractPkScriptAltSigType.
This converts the ExtractPkScriptAltSigType function to use the
optimized extraction functions recently introduced as part of the
typeOfScript conversion.

It is important to note that this new implementation intentionally has
the same semantic differences from the existing implementation as
discussed in the relevant commits that introduced the extraction
functions.

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

benchmark                    old ns/op    new ns/op    delta
---------------------------------------------------------------
BenchmarkExtractAltSigType   497          12.8         -97.42%

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

benchmark                    old bytes    new bytes    delta
---------------------------------------------------------------
BenchmarkExtractAltSigType   896          0            -100.00%
2019-03-26 14:51:56 -05:00
Dave Collins
aaebc79459
txscript: Add ExtractPkScriptAltSigType benchmark. 2019-03-26 14:51:55 -05:00
Dave Collins
d1944a942e
txscript: Optimize ExtractPkScriptAddrs nulldata.
This completes the process of converting the ExtractPkScriptAddrs
function to use the optimized extraction functions recently introduced
as part of the typeOfScript conversion.

In particular, this converts the detection for nulldata scripts, removes
the slow path fallback code since it is the final case, and modifies the
comment to call out the script version semantics.

The following is a before and after comparison of analyzing both a
typical standard script and a very large non-standard script:

benchmark                            old ns/op    new ns/op    delta
-----------------------------------------------------------------------
BenchmarkExtractPkScriptAddrsLarge   132400       44.4         -99.97%
BenchmarkExtractPkScriptAddrs        1265         231          -81.74%

benchmark                            old allocs   new allocs   delta
-----------------------------------------------------------------------
BenchmarkExtractPkScriptAddrsLarge   1            0            -100.00%
BenchmarkExtractPkScriptAddrs        5            2            -60.00%

benchmark                            old bytes    new bytes    delta
-----------------------------------------------------------------------
BenchmarkExtractPkScriptAddrsLarge   466944       0            -100.00%
BenchmarkExtractPkScriptAddrs        1600         48           -97.00%
2019-03-26 14:51:55 -05:00
Dave Collins
c9bce2a0fb
txscript: Optimize ExtractPkScriptAddrs stakechange.
This continues the process of converting the ExtractPkScriptAddrs
function to use the optimized extraction functions recently introduced
as part of the typeOfScript conversion.

In particular, this converts the detection for stake-change-tagged
pay-to-pubkey-hash and pay-to-script-hash scripts.
2019-03-26 14:51:54 -05:00
Dave Collins
a754af9145
txscript: Optimize ExtractPkScriptAddrs stakerev.
This continues the process of converting the ExtractPkScriptAddrs
function to use the optimized extraction functions recently introduced
as part of the typeOfScript conversion.

In particular, this converts the detection for stake-revocation-tagged
pay-to-pubkey-hash and pay-to-script-hash scripts.
2019-03-26 14:51:53 -05:00
Dave Collins
8c763f198a
txscript: Optimize ExtractPkScriptAddrs stakegen.
This continues the process of converting the ExtractPkScriptAddrs
function to use the optimized extraction functions recently introduced
as part of the typeOfScript conversion.

In particular, this converts the detection for stake-generation-tagged
pay-to-pubkey-hash and pay-to-script-hash scripts.
2019-03-26 14:51:53 -05:00
Dave Collins
57219fc17e
txscript: Optimize ExtractPkScriptAddrs stakesub.
This continues the process of converting the ExtractPkScriptAddrs
function to use the optimized extraction functions recently introduced
as part of the typeOfScript conversion.

In particular, this converts the detection for stake-submission-tagged
pay-to-pubkey-hash and pay-to-script-hash scripts.
2019-03-26 14:51:52 -05:00
Dave Collins
6c1c2d1075
txscript: Optimize ExtractPkScriptAddrs multisig.
This continues the process of converting the ExtractPkScriptAddrs
function to use the optimized extraction functions recently introduced
as part of the typeOfScript conversion.

In particular, this converts the detection for multisig scripts.

Also, since the remaining slow path cases are all recursive calls,
the parsed opcodes are no longer used, so parsing is removed.
2019-03-26 14:51:51 -05:00
Dave Collins
8280e50849
txscript: Optimize ExtractPkScriptAddrs altpubkey.
This continues the process of converting the ExtractPkScriptAddrs
function to use the optimized extraction functions recently introduced
as part of the typeOfScript conversion.

In particular, this converts the detection for pay-to-alt-pubkey
scripts.
2019-03-26 14:51:51 -05:00
Dave Collins
9e5744d4ed
txscript: Optimize ExtractPkScriptAddrs pubkey.
This continues the process of converting the ExtractPkScriptAddrs
function to use the optimized extraction functions recently introduced
as part of the typeOfScript conversion.

In particular, this converts the detection for pay-to-pubkey scripts.
2019-03-26 14:51:50 -05:00
Dave Collins
bbca815a71
txscript: Optimize ExtractPkScriptAddrs altpubkeyhash.
This continues the process of converting the ExtractPkScriptAddrs
function to use the optimized extraction functions recently introduced
as part of the typeOfScript conversion.

In particular, this converts the detection for pay-to-alt-pubkey-hash
scripts.
2019-03-26 14:51:49 -05:00
Dave Collins
bdd98b15ba
txscript: Optimize ExtractPkScriptAddrs pubkeyhash.
This continues the process of converting the ExtractPkScriptAddrs
function to use the optimized extraction functions recently introduced
as part of the typeOfScript conversion.

In particular, this converts the detection for pay-to-pubkey-hash
scripts.
2019-03-26 14:51:49 -05:00
Dave Collins
49b3f9f61a
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.
2019-03-26 14:51:48 -05:00
Dave Collins
5e90e59cf5
txscript: Add ExtractPkScriptAddrs benchmarks. 2019-03-26 14:51:47 -05:00
Dave Collins
4774fda89a
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
------------------------------------------------------------------------------
BenchmarkExtractAtomicSwapDataPushes        1330         410          -69.17%
BenchmarkExtractAtomicSwapDataPushesLarge   136819       69.3         -99.95%

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

benchmark                                   old bytes    new bytes    delta
------------------------------------------------------------------------------
BenchmarkExtractAtomicSwapDataPushes        3168         96           -96.97%
BenchmarkExtractAtomicSwapDataPushesLarge   466944       0            -100.00%
2019-03-26 14:51:47 -05:00
Dave Collins
605a9a419e
txscript: Add ExtractAtomicSwapDataPushes benches. 2019-03-26 14:51:46 -05:00
Dave Collins
ceb1f7244a
txscript: Add tests for atomic swap extraction.
This adds a fairly comprehensive set of tests to ensure the standard
atomic swap script detection and extraction function works as intended.
2019-03-26 14:51:45 -05:00
Dave Collins
67d73853b2
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.
2019-03-26 14:51:45 -05:00
Dave Collins
bb365f221f
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.

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

benchmark                old ns/op    new ns/op    delta
-----------------------------------------------------------
BenchmarkIsUnspendable   149899       860          -99.43%

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

benchmark                old bytes    new bytes    delta
-----------------------------------------------------------
BenchmarkIsUnspendable   466945       0            -100.00%
2019-03-26 14:51:44 -05:00
Dave Collins
a1da017271
txscript: Add benchmark for IsUnspendable. 2019-03-26 14:51:43 -05:00
Dave Collins
9e7de33d6b
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   132400       1619         -98.78%

benchmark             old allocs   new allocs   delta
-------------------------------------------------------
BenchmarkPushedData   5            4            -20.00%

benchmark             old bytes    new bytes    delta
-------------------------------------------------------
BenchmarkPushedData   467320       368          -99.92%
2019-03-26 14:51:42 -05:00
Dave Collins
9b74ada724
txscript: Add benchmark for PushedData. 2019-03-26 14:51:42 -05:00
Dave Collins
d82dfb76dd
txscript: Convert GetScriptHashFromP2SHScript.
This converts GetScriptHashFromP2SHScript to make use of the new script
tokenizer in order to remove the reliance on parsed opcodes as a step
towards utlimately removing them altogether.

It also deprecates the function since the current semantics are not
really ideal in that they simply return the data push just after the
first HASH160 opcode which is only valid in the case the script is
already known to be of the correct form and the task can be done more
efficiently via raw script analysis such as how it is done in the
recently added extractScriptHash function.

Finally, it modifies the comment to explicitly call out the script
version semantics as well as the aforemention precondition.

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.
2019-03-26 14:51:41 -05:00
Dave Collins
1466a2a72d
txscript: Optimize multi sig redeem script func.
This converts the MultisigRedeemScriptFromScriptSig function to make use
of the new finalOpcodeData function instead of the far less efficient
parseScript thereby significantly optimizing the function.

It also deprecates the error return since it really does not make sense
given the preconditions of the function.

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

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

benchmark                       old ns/op    new ns/op    delta
------------------------------------------------------------------
BenchmarkMultisigRedeemScript   153623       1830         -98.81%

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

benchmark                       old bytes    new bytes    delta
------------------------------------------------------------------
BenchmarkMultisigRedeemScript   466944       0            -100.00%
2019-03-26 14:51:40 -05:00
Dave Collins
b0f5561776
txscript: Add multisig redeem script extract bench. 2019-03-26 14:51:40 -05:00
Dave Collins
c596826688
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%
2019-03-26 14:51:39 -05:00
Dave Collins
04e70a1150
txscript: Add CalcMultiSigStats benchmark. 2019-03-26 14:51:38 -05:00
Dave Collins
5a4d9c9b5a
txscript: Remove unused getSigOpCount function. 2019-03-26 14:51:37 -05:00
Dave Collins
7d8ce2d27b
txscript: Remove unused isPushOnly function. 2019-03-26 14:51:37 -05:00
Dave Collins
8f442764f4
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.
2019-03-26 14:51:36 -05:00
Dave Collins
6a0a77fd81
txscript: Optimize ExtractCoinbaseNullData.
This converts the ExtractCoinbaseNullData function to make use of the
new tokenizer instead of the far less efficient parseScript thereby
significantly optimizing the function.

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

benchmark                        old ns/op    new ns/op    delta
-------------------------------------------------------------------
BenchmarkExactCoinbaseNullData   227          31.0         -86.34%

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

benchmark                        old bytes    new bytes    delta
-------------------------------------------------------------------
BenchmarkExactCoinbaseNullData   448          0            -100.00%
2019-03-26 14:51:35 -05:00
Dave Collins
ccd0a92bc1
txscript: Add benchmark for ExtractCoinbaseNullData. 2019-03-26 14:51:35 -05:00