Commit graph

15 commits

Author SHA1 Message Date
Dave Collins 90e7a42585 txscript: Add benchmark for IsUnspendable. 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 b3dd941a77 txscript: Add benchmark for IsPayToWitnessScriptHash 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 2b5edd2b5e txscript: Add benchmark for IsPushOnlyScript. 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 a6244b516d txscript: Add benchmarks for IsMutlsigScript. 2022-05-23 21:46:21 -07:00
Dave Collins e7228a2e5f txscript: Add benchmark for IsPayToScriptHash. 2022-05-23 21:46:21 -07:00
Conner Fromknecht c4da180d4f txscript: Add benchmark for IsPayToPubKeyHash 2022-05-23 21:46:21 -07:00
Dave Collins 28eaf3492d txscript: Add benchmark for IsPayToPubKey 2022-05-23 21:46:21 -07:00
Dave Collins 94bb41664b txscript: Add benchmark for DisasmString. 2022-05-23 21:46:20 -07:00
Dave Collins ac002d6422 txscript: Introduce zero-alloc script tokenizer.
This implements an efficient and zero-allocation script tokenizer that
is exported to both provide a new capability to tokenize scripts to
external consumers of the API as well as to serve as a base for
refactoring the existing highly inefficient internal code.

It is important to note that this tokenizer is intended to be used in
consensus critical code in the future, so it must exactly follow the
existing semantics.

The current script parsing mechanism used throughout the txscript module
is to fully tokenize the scripts into an array of internal parsed
opcodes which are then examined and passed around in order to implement
virtually everything related to scripts.

While that approach does simplify the analysis of certain scripts and
thus provide some nice properties in that regard, it is both extremely
inefficient in many cases, and makes it impossible for external
consumers of the API to implement any form of custom script analysis
without manually implementing a bunch of error prone tokenizing code or,
alternatively, the script engine exposing internal structures.

For example, as shown by profiling the total memory allocations of an
initial sync, the existing script parsing code allocates a total of
around 295.12GB, which equates to around 50% of all allocations
performed.  The zero-alloc tokenizer this introduces will allow that to
be reduced to virtually zero.

The following is a before and after comparison of tokenizing a large
script with a high opcode count using the existing code versus the
tokenizer this introduces for both speed and memory allocations:

benchmark                    old ns/op     new ns/op     delta
BenchmarkScriptParsing-8     63464         677           -98.93%

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

benchmark                    old bytes     new bytes     delta
BenchmarkScriptParsing-8     311299        0             -100.00%

The following is an overview of the changes:

- Introduce new error code ErrUnsupportedScriptVersion
- Implement zero-allocation script tokenizer
- Add a full suite of tests to ensure the tokenizer works as intended
  and follows the required consensus semantics
- Add an example of using the new tokenizer to count the number of
  opcodes in a script
- Update README.md to include the new example
- Update script parsing benchmark to use the new tokenizer
2022-05-23 21:46:20 -07:00
Dave Collins fc5b1a817c txscript: Add benchmark for script parsing. 2022-05-23 21:46:20 -07:00
Conner Fromknecht b2784102f4 txscript: Add benchmark for CalcWitnessSigHash 2022-05-23 21:46:20 -07:00
Dave Collins 42f4b4025c txscript: Add benchmark for CalcSignatureHash 2022-05-23 21:46:20 -07:00