Commit graph

143 commits

Author SHA1 Message Date
Dave Collins 8c68575331 txscript: Make asSmallInt accept raw opcode.
This converts the asSmallInt function to accept an opcode as a byte
instead of the internal opcode data struct in order to make it more
flexible for raw script analysis.

It also updates all callers accordingly.
2022-05-23 21:46:21 -07:00
Dave Collins 45de22d457 txscript: Make isSmallInt accept raw opcode.
This converts the isSmallInt function to accept an opcode as a byte
instead of the internal opcode data struct in order to make it more
flexible for raw script analysis.

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

Finally, it updates all callers accordingly.
2022-05-23 21:46:21 -07:00
Conner Fromknecht a02b71bcf9 txscript/reference_test: Convert sighash calc test
This converts the tests for calculating signature hashes to use the
exported function which handles the raw script versus the now deprecated
variant requiring parsed opcodes.

Backport of 06f769ef72e6042e7f2b5ff1c512ef1371d615e5
2022-05-23 21:46:21 -07:00
Dave Collins 18aa1a59df txscript: Optimize CalcSignatureHash.
This modifies the CalcSignatureHash function to make use of the new
signature hash calculation function that accepts raw scripts without
needing to first parse them.  Consequently, it also doubles as a slight
optimization to the execution time and a significant reduction in the
number of allocations.

In order to convert the CalcScriptHash function and keep the same
semantics, a new function named checkScriptParses is introduced which
will quickly determine if a script can be fully parsed without failure
and return the parse failure in the case it can't.

The following is a before and after comparison of analyzing a large
multiple input transaction:

benchmark                  old ns/op     new ns/op     delta
BenchmarkCalcSigHash-8     3627895       3619477       -0.23%

benchmark                  old allocs     new allocs     delta
BenchmarkCalcSigHash-8     1335           801            -40.00%

benchmark                  old bytes     new bytes     delta
BenchmarkCalcSigHash-8     1373812       1293354       -5.86%
2022-05-23 21:46:21 -07:00
Conner Fromknecht 07c1a9343d txscript: Introduce raw script sighash calc func.
This introduces a new function named calcSignatureHashRaw which accepts
the raw script bytes to calculate the script hash versus requiring the
parsed opcode only to unparse them later in order to make it more
flexible for working with raw scripts.

Since there are several places in the rest of the code that currently
only have access to the parsed opcodes, this modifies the existing
calcSignatureHash to first unparse the script before calling the new
function.

Backport of decred/dcrd:f306a72a16eaabfb7054a26f9d9f850b87b00279
2022-05-23 21:46:21 -07:00
Dave Collins ce08988514 txscript: Optimize script disasm.
This converts the DisasmString function to make use of the new
zero-allocation script tokenizer instead of the far less efficient
parseScript thereby significantly optimizing the function.

In order to facilitate this, the opcode disassembly functionality is
split into a separate function called disasmOpcode that accepts the
opcode struct and data independently as opposed to requiring a parsed
opcode.  The new function also accepts a pointer to a string builder so
the disassembly can be more efficiently be built.

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

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

benchmark                   old ns/op     new ns/op     delta
BenchmarkDisasmString-8     102902        40124         -61.01%

benchmark                   old allocs     new allocs     delta
BenchmarkDisasmString-8     46             51             +10.87%

benchmark                   old bytes     new bytes     delta
BenchmarkDisasmString-8     389324        130552        -66.47%
2022-05-23 21:46:20 -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
Jake Sylvestre d08785547a docs: update shields 2021-03-05 07:45:19 -05:00
Conner Fromknecht 5300a19d06
txscript/hashcache_test: call rand.Seed once in init
This resolves the more fundamental flake in the unit tests noted in the
prior commit.

Because multiple unit tests call rand.Seed in parallel, it's possible
they can be executed with the same unix timestamp (in seconds). If the
second call happens between generating the hash cache and checking that
the cache doesn't contain a random txn, the random transaction is in
fact a duplicate of one generated earlier since the RNG state was reset.

To remedy, we initialize rand.Seed once in the init function.
2021-02-02 13:31:47 -08:00
Conner Fromknecht 1dd693480c
txscript/hashcache_test: always add inputs during getTxn
TestHashCacheAddContainsHashes flakes fairly regularly when rebasing
PR #1684 with:
    txid <txid> wasn't inserted into cache but was found.

With probabilty 1/10^2 there will be no inputs on the transaction. This
reduces the entropy in the txid, and I belive is the primary cause of
the flake.
2021-02-02 12:44:22 -08:00
Dan Cline 77fd96753c txscript: add benchmark for IsUnspendable
- create benchmarks to measure allocations
 - add test for benchmark input
 - create a low alloc parseScriptTemplate
 - refactor parsing logic for a single opcode
2021-02-02 09:20:31 -05:00
Anirudha Bose ac3f235eb9 rpcclient: implement getaddressinfo command
Fields such as label, and labelspurpose are not included, since they
are deprecated, and will be removed in Bitcoin Core 0.21.
2020-09-21 09:47:58 -04:00
David Hill f7399e6157 build: clean linter warnings 2020-05-13 08:58:39 -04:00
David Hill a505b99ba3 build: replace travis-ci with github actions.
test go 1.14
use golangci-lint
2020-05-13 08:52:05 -04:00
Tyler Chambers 1d0bfca5b0 fix error message 2020-03-05 16:51:41 -05:00
Wilmer Paulino 5328af0b63
txscript: refactor ComputePkScript 2019-06-03 13:55:28 -07:00
Wilmer Paulino 545bc5d474
txscript: handle variable length P2PKH signatures in ComputePkScript
Since P2PKH signatures have variable lengths, we would attempt to parse
P2PKH scripts as P2SH if they didn't fit the previous length
constraints.
2019-06-03 13:55:24 -07:00
Wilmer Paulino 0cec774a75
txscript: add support to re-derive output's PkScript from input
In this commit, we extend the txscript package to support re-deriving
the PkScript of an output by looking at the input's signature
script/witness attempting to spend it. As of this commit, the only
supported types are P2SH, v0 P2WSH, and v0 P2WPKH.

This will serve useful to detect when a particular script has been spent
on-chain.

A set of test vectors has also been added for the supported script types
to ensure its correctness.
2019-01-11 18:30:42 -08:00
Dave Collins 07edce81b0
txscript: Cleanup strict signature enforcement.
This cleans up the code for handling the checksig and checkmultisig
opcode strict signatures to explicitly call out any semantics that are
likely not obvious and improve readability.

It also introduce new distinct errors for each condition which can
result in a signature being rejected due to not following the strict
encoding requirements and updates reference test adaptor accordingly.
2018-08-23 11:56:28 -05:00
Olaoluwa Osuntokun b72e16f0d6 multi: correct all import paths 2018-05-23 16:46:15 -07:00
Olaoluwa Osuntokun 3d1caa2f83 multi: update to point to roasbeef forks 2018-05-23 16:46:15 -07:00
Olaoluwa Osuntokun 4a6dc67067 txscript: add exported sighash calc func 2018-05-23 16:46:15 -07:00
Josh Rickmar 1cd648d784 Require atomic swap contracts to specify the secret size.
This allows redeeming parties to audit the secret size and ensure it
will be usable once revealed.
2018-02-16 16:18:43 -05:00
Nicola 'tekNico' Larosa 11fcd83963 btcd/multi: fix a number of typos in comments. 2018-01-25 23:23:59 -06:00
Marko Bencun 16dbb2602a txscript: export calcSignatureHash
This is a useful function for users of this library, and deserves to
be public.
2018-01-25 23:14:55 -06:00
Shuai Qi b6afec5e51 txscript: Fix comment typo. 2018-01-25 22:37:50 -06:00
Josh Rickmar 2e60448ffc txscript: Require SHA256 secret hashes for atomic swaps 2017-11-28 10:07:13 -05:00
Janus Troelsen 8cea3866d0 Update script_test.go
Typo fix
2017-10-26 14:26:30 +02:00
Josh Rickmar 4803a8291c txscript: Add API to parse atomic swap contracts. 2017-09-20 12:44:35 -05:00
Alex Bosworth 63d1550d42 txscript: Trivial typo fixes. 2017-09-08 12:56:38 -05:00
Dave Collins 6b802379ec
txscript: Shallow tx copy for signature hash calc.
This modifies calcSignatureHash to use a shallow copy of the transaction
versus a deep copy since the actual scripts themselves are not modified
and therefore don't need to be copied.

This is being done because profiling the most overall allocated space
shows that the deep copy performed in calcSignatureHash accounts for
nearly 20% of all allocations on a synced running instance.  Also,
copying all of the additional data makes it more time consuming as well.

With this change, that figure drops from ~20% to ~5% of all allocations.

The following benchmark shows the relative speedups and allocation
reduction as a result of the optimization on my system.  In particular,
the changes result in approximately a 15% speedup and a whopping 99.89%
reduction in allocations when using a large transaction with thousands
of inputs which was the worst case scenario.

benchmark                        old allocs    new allocs    delta
--------------------------------------------------------------------
BenchmarkCalcSignatureHash       11151         12            -99.89%

benchmark                        old ns/op     new ns/op     delta
--------------------------------------------------------------------
BenchmarkCalcSignatureHash       3599845       3056359       -15.10%
2017-08-24 12:48:11 -05:00
Olaoluwa Osuntokun 3b4b4e7942 txscript: update reference tests to include new segwit related cases 2017-08-13 23:17:40 -05:00
Olaoluwa Osuntokun ff6cb25e89 txscript: convert all new segwit error types to ErrorCode's 2017-08-13 23:17:40 -05:00
Olaoluwa Osuntokun 80dd96ac5d txscript: add new post segwit policies to standard script flags 2017-08-13 23:17:40 -05:00
Olaoluwa Osuntokun 0a7bbda6dd txscript: add verification of the post-segwit pub key type constraint
This commit adds verification of the post-segwit standardness
requirement that all pubkeys involved in checks operations MUST be
serialized as compressed public keys. A new ScriptFlag has been added
to guard this behavior when executing scripts.
2017-08-13 23:17:40 -05:00
Olaoluwa Osuntokun 9367aedfd7 txscript: add verification of the post-segwit minimal if policy
This commit modifies the op-code execution for OP_IF and OP_NOTIF to
enforce the additional “minimal if” constraints which require the
top-stack item when the op codes are encountered to be either an empty
vector, or exactly [0x01].
2017-08-13 23:17:40 -05:00
Olaoluwa Osuntokun 9054ef8354 BIP 147: enforce NULLDUMMY w/ segwit verification
This commit implements the flag activation portion of BIP 0147. The
verification behavior triggered by the NULLDUMMY script verification
flag has been present within btcd for some time, however it wasn’t
activated by default.

With this commit, once segwit has activated, the ScriptStrictMultiSig
will also be activated within the Script VM. Additionally, the
ScriptStrictMultiSig is now a standard script verification flag which
is used unconditionally within the mempool.
2017-08-13 23:17:40 -05:00
Olaoluwa Osuntokun aaf187427e BIP0141+txscript: implement witness program validation
This commit implements full witness program validation for the
currently defined version 0 witness programs. This includes validation
logic for nested p2sh, p2wsh, and p2wkh. Additionally, when in witness
validation mode, an additional set of constrains are enforced such as
using the new sighash digest algorithm and enforcing clean stack
behavior within witness programs.
2017-08-13 23:17:40 -05:00
Olaoluwa Osuntokun b564111aff txscript: fix off-by-one error due to new OP_CODESEPARATOR behavior in segwit
This commit fixes an off-by-one error which is only manifested by the
new behavior of OP_CODESEPARATOR within sig hashes triggered by the
segwit behavior. The current behavior within the Script VM
(txscript.Engine) is known to be fully correct to the extent that it has
been verified. However, once segwit activates a consensus divergence
would emerge due to *when* the program counter was incremented in the
previous code (pre-this-commit).

Currently (pre-segwit) when calculating the pre-image to a transaction
sighash for signature verification, *all* instances of OP_CODESEPARATOR
are removed from the subScript being signed before generating the final
sighash. SegWit has additional nerfed the behavior of OP_CODESEPARATOR
by no longer removing them (and starting after the last instance), but
instead simply starting the subScript to be directly *after* the last
instance of an OP_CODESEPARATOR within the pkScript.

Due to this new behavior, without this commit, an off-by-one error
(which only matters post-segwit), would cause txscript to generate an
incorrect subScript since the instance of OP_CODESEPARATOR would remain
as part of the subScript instead of being sliced off as the new behavior
dictates. The off-by-one error itself is manifested due to a slight
divergence in txscript.Engine’s logic compared to Bitcoin Core.  In
Bitcoin Core script verification is as follows: first the next op-code
is fetched, then program counter is incremented, and finally the op-code
itself is executed. Before this commit, btcd flipped the order
of the last two steps, executing the op-code *before* the program
counter was incremented.

This commit fixes the post-segwit consensus divergence by incrementing
the program-counter *before* the next op-code is executed. It is
important to note that this divergence is only significant post-segwit,
meaning that txscript.Engine is still consensus compliant independent of
this commit.
2017-08-13 23:17:40 -05:00
Olaoluwa Osuntokun 653459c810 BIP0141+txscript: implement signature operation cost calculations 2017-08-13 23:17:40 -05:00
Olaoluwa Osuntokun 469e53ca27 BIP0141+txscript: awareness of new standard script templates, add helper funcs
This commit introduces a series of internal and external helper
functions which enable the txscript package to be aware of the new
standard script templates introduced as part of BIP0141. The two new
standard script templates recognized are pay-to-witness-key-hash
(P2WKH) and pay-to-witness-script-hash (P2WSH).
2017-08-13 23:17:40 -05:00
Olaoluwa Osuntokun 98cae74275 BIP0143+txscript: add segwit sighash, signing, and HashCache integration
This commit implements most of BIP0143 by adding logic to implement the
new sighash calculation, signing, and additionally introduces the
HashCache optimization which eliminates the O(N^2) computational
complexity for the SIGHASH_ALL sighash type.

The HashCache struct is the equivalent to the existing SigCache struct,
but for caching the reusable midstate for transactions which are
spending segwitty outputs.
2017-08-13 23:17:40 -05:00
Josh Rickmar a6965d493f all: Remove seelog logger.
The btclog package has been changed to defining its own logging
interface (rather than seelog's) and provides a default implementation
for callers to use.

There are two primary advantages to the new logger implementation.

First, all log messages are created before the call returns.  Compared
to seelog, this prevents data races when mutable variables are logged.

Second, the new logger does not implement any kind of artifical rate
limiting (what seelog refers to as "adaptive logging").  Log messages
are outputted as soon as possible and the application will appear to
perform much better when watching standard output.

Because log rotation is not a feature of the btclog logging
implementation, it is handled by the main package by importing a file
rotation package that provides an io.Reader interface for creating
output to a rotating file output.  The rotator has been configured
with the same defaults that btcd previously used in the seelog config
(10MB file limits with maximum of 3 rolls) but now compresses newly
created roll files.  Due to the high compressibility of log text, the
compressed files typically reduce to around 15-30% of the original
10MB file.
2017-06-19 16:46:50 -04:00
Steven Roose bf43e56f2f Fix warnings from ineffassign
I left one at the end of fullblocktest, since I suspected the unused
variable assignments there were set for the possibility of extending the
tests.
2017-06-07 17:59:33 -05:00
Dave Collins 9918e2a561
multi: Update markdown files for GFM changes.
The github markdown interpreter has been changed such that it no longer
allows spaces in between the brackets and parenthesis of links and now
requires a newline in between anchors and other formatting.  This
updates all of the markdown files accordingly.

While here, it also corrects a couple of inconsistencies in some of the
README.md files.
2017-05-25 12:06:16 -05:00
Dave Collins 0ea4a6ebd4
multi: Switch to upstream golang.org/x/crypto.
Now that glide is used for version management and a specific commit of
the upstream repository can be locked it is no longer necessary to
maintain a fork of the package specifically to keep a stable dependency.

While here, update the glide dependency for btcutil as well since it was
switched to use the upstream path as well.
2017-05-09 11:35:01 -05:00