diff --git a/contrib/rpm/README.md b/contrib/rpm/README.md index e1fd0b317b..4ab2f35680 100644 --- a/contrib/rpm/README.md +++ b/contrib/rpm/README.md @@ -1,185 +1,185 @@ RPM Spec File Notes ------------------- The RPM spec file provided here is for Bitcoin-Core 0.12.0 and builds on CentOS 7 with either the CentOS provided OpenSSL library or with LibreSSL as packaged at [LibreLAMP.com](https://librelamp.com/). It should hopefully not be too difficult to port the RPM spec file to most RPM based Linux distributions. When porting the spec file to build for a particular distribution, there are some important notes. ## Sources It is considered good form for all sources to reference a URL where the source can be downloaded. Sources 0-9 should be reserved for source code tarballs. `Source0` should reference the release tarball available from https://bitcoin.org/bin/ and `Source1` should reference the BerkeleyDB source. Sources 10-99 are for source files that are maintained in the [Bitcoin git repository](https://github.com/bitcoin/bitcoin) but are not part of the release tarball. Most of these will reside in the `contrib` sub-directory. Sources 10-19 should be reserved for miscellaneous configuration files. Currently only `Source10` is used, for the example `bitcoin.conf` file. Sources 20-29 should be reserved for man pages. Currently only `Source20` through `Source23` are used. Sources 30-39 should be reserved for SELinux related files. Currently only `Source30` through `Source32` are used. Until those files are in a tagged release, the full URL specified in the RPM spec file will not work. You can get them from the git repository where you retrieved this file. Sources 100+ are for files that are not source tarballs and are not maintained in the bitcoin git repository. At present only an SVG version of the Bitcoin icon is used. ## Patches In general, patches should be avoided. When a packager feels a patch is necessary, the packager should bring the problem to the attention of the bitcoin developers so that an official fix to the issue can make it into the next release. ### Patch0 bitcoin-0.12.0-libressl.patch This patch is only needed if building against LibreSSL. LibreSSL is not the standard TLS library on most Linux distributions. The patch will likely not be needed when 0.12.1 is released, a proper fix is already in the Bitcoin git master branch. ## BuildRequires The packages specified in the `BuildRequires` are specified according to the package naming convention currently used in CentOS 7 and EPEL for CentOS 7. You may need to change some of the package names for other distributions. This is most likely to be the case with the Qt packages. ## BerkeleyDB The `build-unix.md` file recommends building against BerkeleyDB 4.8.30. Even if that is the version your Linux distribution ships with, it probably is a good idea to build Bitcoin Core against a static version of that library compiled according to the instructions in the `build-unix.md` file so that any changes the distribution may make in the future will not result in a problem for users. The problem that can exist, clients built against different versions of BerkeleyDB may not be able read each other's `wallet.dat` file which can make it difficult for a user to recover from backup in the event of a system failure. ## Graphical User Interface and Qt Version The RPM spec file will by default build the GUI client linked against the Qt5 libraries. If you wish instead to link against the Qt4 libraries you need to pass the switch `-D '_use_qt4 1'` at build time to the `rpmbuild` or `mock` command used to build the packages. If you would prefer not to build the GUI at all, you can pass the switch `-D '_no_gui 1'` to the `rpmbuild` or `mock` build command. ## Desktop and KDE Files The desktop and KDE meta files are created in the spec file itself with the `cat` command. This is done to allow easy distribution specific changes without needing to use any patches. A specific time stamp is given to the files so that it does not they do not appear to have been updated every time the package is built. If you do make changes to them, you probably should update time stamp assigned to them in the `touch` command that specifies the time stamp. ## SVG, PNG, and XPM Icons The `bitcoin.svg` file is from the source listed as `Source100`. It is used as the source for the PNG and XPM files. The generated PNG and XPM files are given the same time stamp as the source SVG file as a means of indicating they are derived from it. ## Systemd This spec file assumes the target distribution uses systemd. That really only matters for the `bitcoin-server` package. At this point, most RPM based distributions that still receive vendor updates do in fact use systemd. The files to control the service are created in the RPM spec file itself using the `cat` command. This is done to make it easy to modify for other distributions that may implement things differently without needing to patch source. A specific time stamp is given to the files so that they do not appear to have been updated every time the package is built. If you do make changes to them, you probably should update the time stamp assigned to them in the `touch` command that specifies the time stamp. ## SELinux The `bitcoin-server` package should have SELinux support. How to properly do that *may* vary by distribution and version of distribution. The SELinux stuff in this RPM spec file *should* be correct for CentOS, RHEL, and Fedora but it would be a good idea to review it before building the package on other distributions. ## Tests The `%check` section takes a very long time to run. If your build system has a time limit for package build, you may need to make an exception for this package. On CentOS 7 the `%check` section completes successfully with both OpenSSL and LibreSSL, a failure really does mean something is wrong. ## LibreSSL Build Notes To build against LibreSSL you will need to pass the switch `-D '_use_libressl 1'` to the `rpmbuild` or `mock` command or the spec file will want the OpenSSL development files. ### LibreSSL and Boost LibreSSL (and some newer builds of OpenSSL) do not have support for SSLv3. This can cause issues with the Boost package if the Boost package has not been patched accordingly. On those distributions, you will either need to build Bitcoin-Core against OpenSSL or use a patched version of Boost in the build system. As SSLv3 is no longer safe, distributions that have not patched Boost to work with TLS libraries that do not support SSLv3 should have bug reports filed against the Boost package. This bug report has already been filed for RHEL 7 but it may need to be filed for other distributions. A patch for Boost: https://github.com/boostorg/asio/pull/23/files ## ZeroMQ At this time, this RPM spec file does not support the ZeroMQ build options. A suitable version of ZeroMQ is not available for the platform this spec file was developed on (CentOS 7). ## Legacy Credit This RPM spec file is largely based upon the work of Michael Hampton at [Ringing Liberty](https://www.ringingliberty.com/bitcoin/). He has been packaging Bitcoin for Fedora at least since 2012. Most of the differences between his packaging and this package are stylistic in nature. The major differences: 1. He builds from a github tagged release rather than a release tarball. This should not result in different source code. 2. He does not build BerkeleyDB but instead uses the BerkeleyDB provided by the Linux distribution. For the distributions he packages for, they currently all use the same version of BerkeleyDB so that difference is *probably* just academic. 3. As of his 10.11.2 package he did not allow for building against LibreSSL, specifying a build without the Qt GUI, or specifying which version of the Qt libraries to use. 4. I renamed the `bitcoin` package that contains the Qt GUI to `bitcoin-core` as that appears to be how the general population refers to it, in contrast to `bitcoin-xt` or `bitcoin-classic`. I wanted to make sure the general population knows what they are getting when installing the GUI package. As far as minor differences, I generally prefer to assign the file permissions in the `%files` portion of an RPM spec file rather than specifying the -permissions of a file during `%install` and other minor things like that that +permissions of a file during `%install` and other minor things like that are largely just cosmetic. diff --git a/contrib/rpm/bitcoin.if b/contrib/rpm/bitcoin.if index 2b096c24dc..b206866cc5 100644 --- a/contrib/rpm/bitcoin.if +++ b/contrib/rpm/bitcoin.if @@ -1,157 +1,157 @@ ## policy for bitcoin ######################################## ## ## Transition to bitcoin. ## ## ## ## Domain allowed to transition. ## ## # interface(`bitcoin_domtrans',` gen_require(` type bitcoin_t, bitcoin_exec_t; ') corecmd_search_bin($1) domtrans_pattern($1, bitcoin_exec_t, bitcoin_t) ') ######################################## ## ## Execute bitcoin server in the bitcoin domain. ## ## ## ## Domain allowed access. ## ## # interface(`bitcoin_initrc_domtrans',` gen_require(` type bitcoin_initrc_exec_t; ') init_labeled_script_domtrans($1, bitcoin_initrc_exec_t) ') ######################################## ## ## Search bitcoin lib directories. ## ## ## ## Domain allowed access. ## ## # interface(`bitcoin_search_lib',` gen_require(` type bitcoin_var_lib_t; ') allow $1 bitcoin_var_lib_t:dir search_dir_perms; files_search_var_lib($1) ') ######################################## ## ## Read bitcoin lib files. ## ## ## ## Domain allowed access. ## ## # interface(`bitcoin_read_lib_files',` gen_require(` type bitcoin_var_lib_t; ') files_search_var_lib($1) read_files_pattern($1, bitcoin_var_lib_t, bitcoin_var_lib_t) ') ######################################## ## ## Manage bitcoin lib files. ## ## ## ## Domain allowed access. ## ## # interface(`bitcoin_manage_lib_files',` gen_require(` type bitcoin_var_lib_t; ') files_search_var_lib($1) manage_files_pattern($1, bitcoin_var_lib_t, bitcoin_var_lib_t) ') ######################################## ## ## Manage bitcoin lib directories. ## ## ## ## Domain allowed access. ## ## # interface(`bitcoin_manage_lib_dirs',` gen_require(` type bitcoin_var_lib_t; ') files_search_var_lib($1) manage_dirs_pattern($1, bitcoin_var_lib_t, bitcoin_var_lib_t) ') ######################################## ## ## All of the rules required to administrate -## an bitcoin environment +## a bitcoin environment ## ## ## ## Domain allowed access. ## ## ## ## ## Role allowed access. ## ## ## # interface(`bitcoin_admin',` gen_require(` type bitcoin_t; type bitcoin_initrc_exec_t; type bitcoin_var_lib_t; ') allow $1 bitcoin_t:process { ptrace signal_perms }; ps_process_pattern($1, bitcoin_t) bitcoin_initrc_domtrans($1) domain_system_change_exemption($1) role_transition $2 bitcoin_initrc_exec_t system_r; allow $2 system_r; files_search_var_lib($1) admin_pattern($1, bitcoin_var_lib_t) ') diff --git a/doc/developer-notes.md b/doc/developer-notes.md index f83e54cf9b..83eee83a00 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -1,711 +1,711 @@ Developer Notes =============== Various coding styles have been used during the history of the codebase, and the result is not very consistent. However, we're now trying to converge to a single style, so please use it in new code. Old code will be converted gradually and you are encouraged to use the provided [clang-format-diff script](/contrib/devtools/README.md#clang-format-diffpy) to clean up the patch automatically before submitting a pull request. - Basic rules specified in [src/.clang-format](/src/.clang-format). - Braces on new lines for namespaces, classes, functions, methods. - Braces on the same line for everything else. - 4 space indentation (no tabs) for every block except namespaces. - No indentation for `public`/`protected`/`private` or for `namespace`. - No extra spaces inside parenthesis; don't do ( this ) - No space after function names; one space after `if`, `for` and `while`. - Always add braces for block statements (e.g. `if`, `for`, `while`). - `++i` is preferred over `i++`. - `static_assert` is preferred over `assert` where possible. Generally; compile-time checking is preferred over run-time checking. - Use CamelCase for functions/methods, and lowerCamelCase for variables. - GLOBAL_CONSTANTS should use UPPER_SNAKE_CASE. - namespaces should use lower_snake_case. - Function names should generally start with an English command-form verb (e.g. `ValidateTransaction`, `AddTransactionToMempool`, `ConnectBlock`) - Variable names should generally be nouns or past/future tense verbs. (e.g. `canDoThing`, `signatureOperations`, `didThing`) - Avoid using globals, remove existing globals whenever possible. - Class member variable names should be prepended with `m_` - DO choose easily readable identifier names. - DO favor readability over brevity. - DO NOT use Hungarian notation. - DO NOT use abbreviations or contractions within identifiers. - WRONG: mempool - RIGHT: MemoryPool - WRONG: ChangeDir - RIGHT: ChangeDirectory - DO NOT use obscure acronyms, DO uppercase any acronyms. - FINALLY, do not migrate existing code unless refactoring. It makes forwarding-porting from Bitcoin Core more difficult. The naming convention roughly mirrors [Microsoft Naming Conventions](https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/general-naming-conventions) C++ Coding Standards should strive to follow the [LLVM Coding Standards](https://llvm.org/docs/CodingStandards.html) Code style example: ```c++ // namespaces should be lower_snake_case namespace foo_bar_bob { /** * Class is used for doing classy things. All classes should * have a doxygen comment describing their PURPOSE. That is to say, * why they exist. Functional details can be determined from the code. * @see PerformTask() */ class Class { private: //! memberVariable's name should be lowerCamelCase, and be a noun. int m_memberVariable; public: /** * The documentation before a function or class method should follow Doxygen * spec. The name of the function should start with an english verb which * indicates the intended purpose of this code. * * The function name should be should be CamelCase. * * @param[in] s A description * @param[in] n Another argument description * @pre Precondition for function... */ bool PerformTask(const std::string& s, int n) { // Use lowerChamelCase for local variables. bool didMore = false; // Comment summarizing the intended purpose of this section of code for (int i = 0; i < n; ++i) { if (!DidSomethingFail()) { return false; } ... if (IsSomethingElse()) { DoMore(); didMore = true; } else { DoLess(); } } return didMore; } } } ``` Doxygen comments ----------------- To facilitate the generation of documentation, use doxygen-compatible comment blocks for functions, methods and fields. For example, to describe a function use: ```c++ /** * ... text ... * @param[in] arg1 A description * @param[in] arg2 Another argument description * @pre Precondition for function... */ bool function(int arg1, const char *arg2) ``` A complete list of `@xxx` commands can be found at http://www.stack.nl/~dimitri/doxygen/manual/commands.html. As Doxygen recognizes the comments by the delimiters (`/**` and `*/` in this case), you don't *need* to provide any commands for a comment to be valid; just a description text is fine. To describe a class use the same construct above the class definition: ```c++ /** * Alerts are for notifying old versions if they become too obsolete and * need to upgrade. The message is displayed in the status bar. * @see GetWarnings() */ class CAlert { ``` To describe a member or variable use: ```c++ int var; //!< Detailed description after the member ``` or ```cpp //! Description before the member int var; ``` Also OK: ```c++ /// /// ... text ... /// bool function2(int arg1, const char *arg2) ``` Not OK (used plenty in the current source, but not picked up): ```c++ // // ... text ... // ``` A full list of comment syntaxes picked up by doxygen can be found at http://www.stack.nl/~dimitri/doxygen/manual/docblocks.html, but if possible use one of the above styles. To build doxygen locally to test changes to the Doxyfile or visualize your comments before landing changes: ``` # at the project root, call: doxygen doc/Doxyfile # output goes to doc/doxygen/html/ ``` Development tips and tricks --------------------------- **compiling for debugging** Run configure with the --enable-debug option, then make. Or run configure with CXXFLAGS="-g -ggdb -O0" or whatever debug flags you need. **debug.log** If the code is behaving strangely, take a look in the debug.log file in the data directory; error and debugging messages are written there. The -debug=... command-line option controls debugging; running with just -debug or -debug=1 will turn on all categories (and give you a very large debug.log file). The Qt code routes qDebug() output to debug.log under category "qt": run with -debug=qt to see it. **writing tests** For details on unit tests, see `unit-tests.md` For details on functional tests, see `functional-tests.md` **writing script integration tests** Script integration tests are built using `src/test/script_tests.cpp`: 1. Uncomment the line with `#define UPDATE_JSON_TESTS` 2. Add a new TestBuilder to the `script_build` test to cover your test case. 3. `make && ./src/test/test_bitcoin --run_test=script_tests` 4. Copy your newly generated test JSON from `/src/script_tests.json.gen` to `src/test/data/script_tests.json`. Please commit your TestBuilder along with your generated test JSON and cleanup the uncommented #define before code review. **testnet and regtest modes** Run with the -testnet option to run with "play bitcoins" on the test network, if you are testing multi-machine code that needs to operate across the internet. If you are testing something that can run on one machine, run with the -regtest option. In regression test mode, blocks can be created on-demand; see test/functional/ for tests that run in -regtest mode. **DEBUG_LOCKORDER** Bitcoin Core is a multithreaded application, and deadlocks or other multithreading bugs can be very difficult to track down. Compiling with -DDEBUG_LOCKORDER (configure CXXFLAGS="-DDEBUG_LOCKORDER -g") inserts run-time checks to keep track of which locks are held, and adds warnings to the debug.log file if inconsistencies are detected. **Sanitizers** Bitcoin can be compiled with various "sanitizers" enabled, which add instrumentation for issues regarding things like memory safety, thread race conditions, or undefined behavior. This is controlled with the `--with-sanitizers` configure flag, which should be a comma separated list of sanitizers to enable. The sanitizer list should correspond to supported `-fsanitize=` options in your compiler. These sanitizers have runtime overhead, so they are most useful when testing changes or producing debugging builds. Some examples: ```bash # Enable both the address sanitizer and the undefined behavior sanitizer ./configure --with-sanitizers=address,undefined # Enable the thread sanitizer ./configure --with-sanitizers=thread ``` If you are compiling with GCC you will typically need to install corresponding "san" libraries to actually compile with these flags, e.g. libasan for the address sanitizer, libtsan for the thread sanitizer, and libubsan for the undefined sanitizer. If you are missing required libraries, the configure script will fail with a linker error when testing the sanitizer flags. The test suite should pass cleanly with the `thread` and `undefined` sanitizers, but there are a number of known problems when using the `address` sanitizer. The address sanitizer is known to fail in [sha256_sse4::Transform](/src/crypto/sha256_sse4.cpp) which makes it unusable unless you also use `--disable-asm` when running configure. We would like to fix sanitizer issues, so please send pull requests if you can fix any errors found by the address sanitizer (or any other sanitizer). Not all sanitizer options can be enabled at the same time, e.g. trying to build with `--with-sanitizers=address,thread` will fail in the configure script as these sanitizers are mutually incompatible. Refer to your compiler manual to learn more about these options and which sanitizers are supported by your compiler. Additional resources: * [AddressSanitizer](https://clang.llvm.org/docs/AddressSanitizer.html) * [LeakSanitizer](https://clang.llvm.org/docs/LeakSanitizer.html) * [MemorySanitizer](https://clang.llvm.org/docs/MemorySanitizer.html) * [ThreadSanitizer](https://clang.llvm.org/docs/ThreadSanitizer.html) * [UndefinedBehaviorSanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) * [GCC Instrumentation Options](https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html) * [Google Sanitizers Wiki](https://github.com/google/sanitizers/wiki) * [Issue #12691: Enable -fsanitize flags in Travis](https://github.com/bitcoin/bitcoin/issues/12691) Locking/mutex usage notes ------------------------- The code is multi-threaded, and uses mutexes and the LOCK/TRY_LOCK macros to protect data structures. Deadlocks due to inconsistent lock ordering (thread 1 locks cs_main and then cs_wallet, while thread 2 locks them in the opposite order: result, deadlock as each waits for the other to release its lock) are a problem. Compile with -DDEBUG_LOCKORDER to get lock order inconsistencies reported in the debug.log file. Re-architecting the core code so there are better-defined interfaces between the various components is a goal, with any necessary locking done by the components (e.g. see the self-contained CKeyStore class and its cs_KeyStore lock for example). Threads ------- - ThreadScriptCheck : Verifies block scripts. - ThreadImport : Loads blocks from blk*.dat files or bootstrap.dat. - StartNode : Starts other threads. - ThreadDNSAddressSeed : Loads addresses of peers from the DNS. - ThreadMapPort : Universal plug-and-play startup/shutdown - ThreadSocketHandler : Sends/Receives data from peers on port 8333. - ThreadOpenAddedConnections : Opens network connections to added nodes. - ThreadOpenConnections : Initiates new connections to peers. - ThreadMessageHandler : Higher-level message handling (sending and receiving). - DumpAddresses : Dumps IP addresses of nodes to peers.dat. - ThreadFlushWalletDB : Close the wallet.dat file if it hasn't been used in 500ms. - ThreadRPCServer : Remote procedure call handler, listens on port 8332 for connections and services them. - BitcoinMiner : Generates bitcoins (if wallet is enabled). - Shutdown : Does an orderly shutdown of everything. Ignoring IDE/editor files -------------------------- In closed-source environments in which everyone uses the same IDE it is common to add temporary files it produces to the project-wide `.gitignore` file. However, in open source software such as Bitcoin Core, where everyone uses their own editors/IDE/tools, it is less common. Only you know what files your editor produces and this may change from version to version. The canonical way to do this is thus to create your local gitignore. Add this to `~/.gitconfig`: ``` [core] excludesfile = /home/.../.gitignore_global ``` (alternatively, type the command `git config --global core.excludesfile ~/.gitignore_global` on a terminal) Then put your favourite tool's temporary filenames in that file, e.g. ``` # NetBeans nbproject/ ``` Another option is to create a per-repository excludes file `.git/info/exclude`. These are not committed but apply only to one repository. If a set of tools is used by the build system or scripts the repository (for example, lcov) it is perfectly acceptable to add its files to `.gitignore` and commit them. Development guidelines ============================ A few non-style-related recommendations for developers, as well as points to pay attention to for reviewers of Bitcoin Core code. Wallet ------- - Make sure that no crashes happen with run-time option `-disablewallet`. - *Rationale*: In RPC code that conditionally uses the wallet (such as `validateaddress`) it is easy to forget that global pointer `pwalletMain` can be NULL. See `test/functional/disablewallet.py` for functional tests exercising the API with `-disablewallet` - Include `db_cxx.h` (BerkeleyDB header) only when `ENABLE_WALLET` is set - *Rationale*: Otherwise compilation of the disable-wallet build will fail in environments without BerkeleyDB General C++ ------------- - Assertions should not have side-effects - - *Rationale*: Even though the source code is set to to refuse to compile + - *Rationale*: Even though the source code is set to refuse to compile with assertions disabled, having side-effects in assertions is unexpected and makes the code harder to understand - If you use the `.h`, you must link the `.cpp` - *Rationale*: Include files define the interface for the code in implementation files. Including one but not linking the other is confusing. Please avoid that. Moving functions from the `.h` to the `.cpp` should not result in build errors - Use the RAII (Resource Acquisition Is Initialization) paradigm where possible. For example by using `unique_ptr` for allocations in a function. - *Rationale*: This avoids memory and resource leaks, and ensures exception safety C++ data structures -------------------- - Never use the `std::map []` syntax when reading from a map, but instead use `.find()` - *Rationale*: `[]` does an insert (of the default element) if the item doesn't exist in the map yet. This has resulted in memory leaks in the past, as well as race conditions (expecting read-read behavior). Using `[]` is fine for *writing* to a map - Do not compare an iterator from one data structure with an iterator of another data structure (even if of the same type) - *Rationale*: Behavior is undefined. In C++ parlor this means "may reformat the universe", in practice this has resulted in at least one hard-to-debug crash bug - Watch out for out-of-bounds vector access. `&vch[vch.size()]` is illegal, including `&vch[0]` for an empty vector. Use `vch.data()` and `vch.data() + vch.size()` instead. - Vector bounds checking is only enabled in debug mode. Do not rely on it - Make sure that constructors initialize all fields. If this is skipped for a good reason (i.e., optimization on the critical path), add an explicit comment about this - *Rationale*: Ensure determinism by avoiding accidental use of uninitialized values. Also, static analyzers balk about this. - Use explicitly signed or unsigned `char`s, or even better `uint8_t` and `int8_t`. Do not use bare `char` unless it is to pass to a third-party API. This type can be signed or unsigned depending on the architecture, which can lead to interoperability problems or dangerous conditions such as out-of-bounds array accesses - Prefer explicit constructions over implicit ones that rely on 'magical' C++ behavior - *Rationale*: Easier to understand what is happening, thus easier to spot mistakes, even for those that are not language lawyers Strings and formatting ------------------------ - Use `std::string`, avoid C string manipulation functions - *Rationale*: C++ string handling is marginally safer, less scope for buffer overflows and surprises with `\0` characters. Also some C string manipulations tend to act differently depending on platform, or even the user locale - Use `ParseInt32`, `ParseInt64`, `ParseUInt32`, `ParseUInt64`, `ParseDouble` from `utilstrencodings.h` for number parsing - *Rationale*: These functions do overflow checking, and avoid pesky locale issues Variable names -------------- The shadowing warning (`-Wshadow`) is enabled by default. It prevents issues rising from using a different variable with the same name. Please name variables so that their names do not shadow variables defined in the source code. Threads and synchronization ---------------------------- - Build and run tests with `-DDEBUG_LOCKORDER` to verify that no potential deadlocks are introduced. As of 0.12, this is defined by default when configuring with `--enable-debug` - When using `LOCK`/`TRY_LOCK` be aware that the lock exists in the context of the current scope, so surround the statement and the code that needs the lock with braces OK: ```c++ { TRY_LOCK(cs_vNodes, lockNodes); ... } ``` Wrong: ```c++ TRY_LOCK(cs_vNodes, lockNodes); { ... } ``` Source code organization -------------------------- - Implementation code should go into the `.cpp` file and not the `.h`, unless necessary due to template usage or when performance due to inlining is critical - *Rationale*: Shorter and simpler header files are easier to read, and reduce compile time - Don't import anything into the global namespace (`using namespace ...`). Use fully specified types such as `std::string`. - *Rationale*: Avoids symbol conflicts Header Inclusions ----------------- - Header inclusions should use angle brackets (`#include <>`). The include path should be relative to the `src` folder. e.g.: `#include ` - Native C++ headers should be preferred over C compatibility headers. e.g.: use `` instead of `` - In order to make the code consistent, header files should be included in the following order, with each section separated by a newline: 1. In a .cpp file, the associated .h is in first position. In a test source, this is the header file under test. 2. The project headers. 3. The test headers. 4. The 3rd party libraries headers. Different libraries should be in different sections. 5. The system libraries. All headers should be lexically ordered inside their block. GUI ----- - Do not display or manipulate dialogs in model code (classes `*Model`) - *Rationale*: Model classes pass through events and data from the core, they should not interact with the user. That's where View classes come in. The converse also holds: try to not directly access core data structures from Views. - Avoid adding slow or blocking code in the GUI thread. In particular do not add new `interface::Node` and `interface::Wallet` method calls, even if they may be fast now, in case they are changed to lock or communicate across processes in the future. Prefer to offload work from the GUI thread to worker threads (see `RPCExecutor` in console code as an example) or take other steps (see https://doc.qt.io/archives/qq/qq27-responsive-guis.html) to keep the GUI responsive. - *Rationale*: Blocking the GUI thread can increase latency, and lead to hangs and deadlocks. Unit Tests ----------- - Test suite naming convention: The Boost test suite in file `src/test/foo_tests.cpp` should be named `foo_tests`. Test suite names must be unique. Subtrees ---------- Several parts of the repository are subtrees of software maintained elsewhere. Some of these are maintained by active developers of Bitcoin Core, in which case changes should probably go directly upstream without being PRed directly against the project. They will be merged back in the next subtree merge. Others are external projects without a tight relationship with our project. Changes to these should also be sent upstream but bugfixes may also be prudent to PR against Bitcoin Core so that they can be integrated quickly. Cosmetic changes should be purely taken upstream. There is a tool in contrib/devtools/git-subtree-check.sh to check a subtree directory for consistency with its upstream repository. Current subtrees include: - src/leveldb - Upstream at https://github.com/google/leveldb ; Maintained by Google, but open important PRs to Core to avoid delay - src/libsecp256k1 - Upstream at https://github.com/bitcoin-core/secp256k1/ ; actively maintaned by Core contributors. - src/crypto/ctaes - Upstream at https://github.com/bitcoin-core/ctaes ; actively maintained by Core contributors. - src/univalue - Upstream at https://github.com/jgarzik/univalue ; report important PRs to Core to avoid delay. Git and GitHub tips --------------------- - Github is not typically the source of truth for pull requests. See CONTRIBUTING.md for instructions on setting up your repo correctly. - Similarly, your git remote origin should be set to: `ssh://vcs@reviews.bitcoinabc.org:2221/source/bitcoin-abc.git` instead of github.com. See CONTRIBUTING.md for details. - For resolving merge/rebase conflicts, it can be useful to enable diff3 style using `git config merge.conflictstyle diff3`. Instead of <<< yours === theirs >>> you will see <<< yours ||| original === theirs >>> This may make it much clearer what caused the conflict. In this style, you can often just look at what changed between *original* and *theirs*, and mechanically apply that to *yours* (or the other way around). - When reviewing patches which change indentation in C++ files, use `git diff -w` and `git show -w`. This makes the diff algorithm ignore whitespace changes. This feature is also available on github.com, by adding `?w=1` at the end of any URL which shows a diff. - When reviewing patches that change symbol names in many places, use `git diff --word-diff`. This will instead of showing the patch as deleted/added *lines*, show deleted/added *words*. - When reviewing patches that move code around, try using `git diff --patience commit~:old/file.cpp commit:new/file/name.cpp`, and ignoring everything except the moved body of code which should show up as neither `+` or `-` lines. In case it was not a pure move, this may even work when combined with the `-w` or `--word-diff` options described above. - When looking at other's pull requests, it may make sense to add the following section to your `.git/config` file: [remote "upstream-pull"] fetch = +refs/pull/*:refs/remotes/upstream-pull/* url = git@github.com:bitcoin/bitcoin.git This will add an `upstream-pull` remote to your git repository, which can be fetched using `git fetch --all` or `git fetch upstream-pull`. Afterwards, you can use `upstream-pull/NUMBER/head` in arguments to `git show`, `git checkout` and anywhere a commit id would be acceptable to see the changes from pull request NUMBER. RPC interface guidelines -------------------------- A few guidelines for introducing and reviewing new RPC interfaces: - Method naming: use consecutive lower-case names such as `getrawtransaction` and `submitblock` - *Rationale*: Consistency with existing interface. - Argument naming: use snake case `fee_delta` (and not, e.g. camel case `feeDelta`) - *Rationale*: Consistency with existing interface. - Use the JSON parser for parsing, don't manually parse integers or strings from arguments unless absolutely necessary. - *Rationale*: Introduces hand-rolled string manipulation code at both the caller and callee sites, which is error prone, and it is easy to get things such as escaping wrong. JSON already supports nested data structures, no need to re-invent the wheel. - *Exception*: AmountFromValue can parse amounts as string. This was introduced because many JSON parsers and formatters hard-code handling decimal numbers as floating point values, resulting in potential loss of precision. This is unacceptable for monetary values. **Always** use `AmountFromValue` and `ValueFromAmount` when inputting or outputting monetary values. The only exceptions to this are `prioritisetransaction` and `getblocktemplate` because their interface is specified as-is in BIP22. - Missing arguments and 'null' should be treated the same: as default values. If there is no default value, both cases should fail in the same way. The easiest way to follow this guideline is detect unspecified arguments with `params[x].isNull()` instead of `params.size() <= x`. The former returns true if the argument is either null or missing, while the latter returns true if is missing, and false if it is null. - *Rationale*: Avoids surprises when switching to name-based arguments. Missing name-based arguments are passed as 'null'. - Try not to overload methods on argument type. E.g. don't make `getblock(true)` and `getblock("hash")` do different things. - *Rationale*: This is impossible to use with `bitcoin-cli`, and can be surprising to users. - *Exception*: Some RPC calls can take both an `int` and `bool`, most notably when a bool was switched to a multi-value, or due to other historical reasons. **Always** have false map to 0 and true to 1 in this case. - Don't forget to fill in the argument names correctly in the RPC command table. - *Rationale*: If not, the call can not be used with name-based arguments. - Set okSafeMode in the RPC command table to a sensible value: safe mode is when the blockchain is regarded to be in a confused state, and the client deems it unsafe to do anything irreversible such as send. Anything that just queries should be permitted. - *Rationale*: Troubleshooting a node in safe mode is difficult if half the RPCs don't work. - Add every non-string RPC argument `(method, idx, name)` to the table `vRPCConvertParams` in `rpc/client.cpp`. - *Rationale*: `bitcoin-cli` and the GUI debug console use this table to determine how to convert a plaintext command line to JSON. If the types don't match, the method can be unusable from there. - A RPC method must either be a wallet method or a non-wallet method. Do not introduce new methods such as `signrawtransaction` that differ in behavior based on presence of a wallet. - *Rationale*: as well as complicating the implementation and interfering with the introduction of multi-wallet, wallet and non-wallet code should be separated to avoid introducing circular dependencies between code units. - Try to make the RPC response a JSON object. - *Rationale*: If a RPC response is not a JSON object then it is harder to avoid API breakage if new data in the response is needed. - Wallet RPCs call BlockUntilSyncedToCurrentChain to maintain consistency with `getblockchaininfo`'s state immediately prior to the call's execution. Wallet RPCs whose behavior does *not* depend on the current chainstate may omit this call. - *Rationale*: In previous versions of Bitcoin Core, the wallet was always in-sync with the chainstate (by virtue of them all being updated in the same cs_main lock). In order to maintain the behavior that wallet RPCs return results as of at least the highest best-known block an RPC client may be aware of prior to entering a wallet RPC call, we must block until the wallet is caught up to the chainstate as of the RPC call's entry. This also makes the API much easier for RPC clients to reason about. diff --git a/src/chain.cpp b/src/chain.cpp index 6eba2cd035..46d0d892ba 100644 --- a/src/chain.cpp +++ b/src/chain.cpp @@ -1,193 +1,193 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include /** * CChain implementation */ void CChain::SetTip(CBlockIndex *pindex) { if (pindex == nullptr) { vChain.clear(); return; } vChain.resize(pindex->nHeight + 1); while (pindex && vChain[pindex->nHeight] != pindex) { vChain[pindex->nHeight] = pindex; pindex = pindex->pprev; } } CBlockLocator CChain::GetLocator(const CBlockIndex *pindex) const { int nStep = 1; std::vector vHave; vHave.reserve(32); if (!pindex) { pindex = Tip(); } while (pindex) { vHave.push_back(pindex->GetBlockHash()); // Stop when we have added the genesis block. if (pindex->nHeight == 0) { break; } // Exponentially larger steps back, plus the genesis block. int nHeight = std::max(pindex->nHeight - nStep, 0); if (Contains(pindex)) { // Use O(1) CChain index if possible. pindex = (*this)[nHeight]; } else { // Otherwise, use O(log n) skiplist. pindex = pindex->GetAncestor(nHeight); } if (vHave.size() > 10) { nStep *= 2; } } return CBlockLocator(vHave); } const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const { if (pindex == nullptr) { return nullptr; } if (pindex->nHeight > Height()) { pindex = pindex->GetAncestor(Height()); } while (pindex && !Contains(pindex)) { pindex = pindex->pprev; } return pindex; } CBlockIndex *CChain::FindEarliestAtLeast(int64_t nTime) const { std::vector::const_iterator lower = std::lower_bound(vChain.begin(), vChain.end(), nTime, [](CBlockIndex *pBlock, const int64_t &time) -> bool { return pBlock->GetBlockTimeMax() < time; }); return (lower == vChain.end() ? nullptr : *lower); } /** Turn the lowest '1' bit in the binary representation of a number into a '0'. */ static inline int InvertLowestOne(int n) { return n & (n - 1); } /** Compute what height to jump back to with the CBlockIndex::pskip pointer. */ static inline int GetSkipHeight(int height) { if (height < 2) { return 0; } // Determine which height to jump back to. Any number strictly lower than // height is acceptable, but the following expression seems to perform well // in simulations (max 110 steps to go back up to 2**18 blocks). return (height & 1) ? InvertLowestOne(InvertLowestOne(height - 1)) + 1 : InvertLowestOne(height); } CBlockIndex *CBlockIndex::GetAncestor(int height) { if (height > nHeight || height < 0) { return nullptr; } CBlockIndex *pindexWalk = this; int heightWalk = nHeight; while (heightWalk > height) { int heightSkip = GetSkipHeight(heightWalk); int heightSkipPrev = GetSkipHeight(heightWalk - 1); if (pindexWalk->pskip != nullptr && (heightSkip == height || (heightSkip > height && !(heightSkipPrev < heightSkip - 2 && heightSkipPrev >= height)))) { // Only follow pskip if pprev->pskip isn't better than pskip->pprev. pindexWalk = pindexWalk->pskip; heightWalk = heightSkip; } else { assert(pindexWalk->pprev); pindexWalk = pindexWalk->pprev; heightWalk--; } } return pindexWalk; } const CBlockIndex *CBlockIndex::GetAncestor(int height) const { return const_cast(this)->GetAncestor(height); } void CBlockIndex::BuildSkip() { if (pprev) { pskip = pprev->GetAncestor(GetSkipHeight(nHeight)); } } arith_uint256 GetBlockProof(const CBlockIndex &block) { arith_uint256 bnTarget; bool fNegative; bool fOverflow; bnTarget.SetCompact(block.nBits, &fNegative, &fOverflow); if (fNegative || fOverflow || bnTarget == 0) { return 0; } // We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256 - // as it's too large for a arith_uint256. However, as 2**256 is at least as + // as it's too large for an arith_uint256. However, as 2**256 is at least as // large as bnTarget+1, it is equal to ((2**256 - bnTarget - 1) / // (bnTarget+1)) + 1, or ~bnTarget / (nTarget+1) + 1. return (~bnTarget / (bnTarget + 1)) + 1; } int64_t GetBlockProofEquivalentTime(const CBlockIndex &to, const CBlockIndex &from, const CBlockIndex &tip, const Consensus::Params ¶ms) { arith_uint256 r; int sign = 1; if (to.nChainWork > from.nChainWork) { r = to.nChainWork - from.nChainWork; } else { r = from.nChainWork - to.nChainWork; sign = -1; } r = r * arith_uint256(params.nPowTargetSpacing) / GetBlockProof(tip); if (r.bits() > 63) { return sign * std::numeric_limits::max(); } return sign * r.GetLow64(); } /** * Find the last common ancestor two blocks have. * Both pa and pb must be non null. */ const CBlockIndex *LastCommonAncestor(const CBlockIndex *pa, const CBlockIndex *pb) { if (pa->nHeight > pb->nHeight) { pa = pa->GetAncestor(pb->nHeight); } else if (pb->nHeight > pa->nHeight) { pb = pb->GetAncestor(pa->nHeight); } while (pa != pb && pa && pb) { pa = pa->pprev; pb = pb->pprev; } // Eventually all chain branches meet at the genesis block. assert(pa == pb); return pa; } bool AreOnTheSameFork(const CBlockIndex *pa, const CBlockIndex *pb) { // The common ancestor needs to be either pa (pb is a child of pa) or pb (pa // is a child of pb). const CBlockIndex *pindexCommon = LastCommonAncestor(pa, pb); return pindexCommon == pa || pindexCommon == pb; } diff --git a/src/cuckoocache.h b/src/cuckoocache.h index cbd93557b9..e8da673c95 100644 --- a/src/cuckoocache.h +++ b/src/cuckoocache.h @@ -1,461 +1,461 @@ // Copyright (c) 2016 Jeremy Rubin // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_CUCKOOCACHE_H #define BITCOIN_CUCKOOCACHE_H #include #include #include #include #include #include #include /** namespace CuckooCache provides high performance cache primitives * * Summary: * * 1) bit_packed_atomic_flags is bit-packed atomic flags for garbage collection * * 2) cache is a cache which is performant in memory usage and lookup speed. It * is lockfree for erase operations. Elements are lazily erased on the next * insert. */ namespace CuckooCache { /** * bit_packed_atomic_flags implements a container for garbage collection flags * that is only thread unsafe on calls to setup. This class bit-packs collection * flags for memory efficiency. * * All operations are std::memory_order_relaxed so external mechanisms must * ensure that writes and reads are properly synchronized. * * On setup(n), all bits up to n are marked as collected. * * Under the hood, because it is an 8-bit type, it makes sense to use a multiple * of 8 for setup, but it will be safe if that is not the case as well. */ class bit_packed_atomic_flags { std::unique_ptr[]> mem; public: /** No default constructor as there must be some size */ bit_packed_atomic_flags() = delete; /** * bit_packed_atomic_flags constructor creates memory to sufficiently keep * track of garbage collection information for size entries. * * @param size the number of elements to allocate space for * * @post bit_set, bit_unset, and bit_is_set function properly forall x. x < * size * @post All calls to bit_is_set (without subsequent bit_unset) will return * true. */ explicit bit_packed_atomic_flags(uint32_t size) { // pad out the size if needed size = (size + 7) / 8; mem.reset(new std::atomic[size]); for (uint32_t i = 0; i < size; ++i) mem[i].store(0xFF); }; /** * setup marks all entries and ensures that bit_packed_atomic_flags can * store at least size entries * * @param b the number of elements to allocate space for * @post bit_set, bit_unset, and bit_is_set function properly forall x. x < * b * @post All calls to bit_is_set (without subsequent bit_unset) will return * true. */ inline void setup(uint32_t b) { bit_packed_atomic_flags d(b); std::swap(mem, d.mem); } /** * bit_set sets an entry as discardable. * * @param s the index of the entry to bit_set. * @post immediately subsequent call (assuming proper external memory * ordering) to bit_is_set(s) == true. */ inline void bit_set(uint32_t s) { mem[s >> 3].fetch_or(1 << (s & 7), std::memory_order_relaxed); } /** * bit_unset marks an entry as something that should not be overwritten * * @param s the index of the entry to bit_unset. * @post immediately subsequent call (assuming proper external memory * ordering) to bit_is_set(s) == false. */ inline void bit_unset(uint32_t s) { mem[s >> 3].fetch_and(~(1 << (s & 7)), std::memory_order_relaxed); } /** * bit_is_set queries the table for discardability at s * * @param s the index of the entry to read. * @returns if the bit at index s was set. * */ inline bool bit_is_set(uint32_t s) const { return (1 << (s & 7)) & mem[s >> 3].load(std::memory_order_relaxed); } }; /** * cache implements a cache with properties similar to a cuckoo-set * * The cache is able to hold up to (~(uint32_t)0) - 1 elements. * * Read Operations: * - contains(*, false) * * Read+Erase Operations: * - contains(*, true) * * Erase Operations: * - allow_erase() * * Write Operations: * - setup() * - setup_bytes() * - insert() * - please_keep() * * Synchronization Free Operations: * - invalid() * - compute_hashes() * * User Must Guarantee: * * 1) Write Requires synchronized access (e.g., a lock) * 2) Read Requires no concurrent Write, synchronized with the last insert. * 3) Erase requires no concurrent Write, synchronized with last insert. * 4) An Erase caller must release all memory before allowing a new Writer. * * * Note on function names: * - The name "allow_erase" is used because the real discard happens later. * - The name "please_keep" is used because elements may be erased anyways on * insert. * * @tparam Element should be a movable and copyable type * @tparam Hash should be a function/callable which takes a template parameter * hash_select and an Element and extracts a hash from it. Should return * high-entropy hashes for `Hash h; h<0>(e) ... h<7>(e)`. */ template class cache { private: /** table stores all the elements */ std::vector table; /** size stores the total available slots in the hash table */ uint32_t size; /** * The bit_packed_atomic_flags array is marked mutable because we want * garbage collection to be allowed to occur from const methods. */ mutable bit_packed_atomic_flags collection_flags; /** * epoch_flags tracks how recently an element was inserted into the cache. * true denotes recent, false denotes not-recent. See insert() method for * full semantics. */ mutable std::vector epoch_flags; /** - * epoch_heuristic_counter is used to determine when a epoch might be aged & - * an expensive scan should be done. epoch_heuristic_counter is decremented - * on insert and reset to the new number of inserts which would cause the - * epoch to reach epoch_size when it reaches zero. + * epoch_heuristic_counter is used to determine when an epoch might be aged + * & an expensive scan should be done. epoch_heuristic_counter is + * decremented on insert and reset to the new number of inserts which would + * cause the epoch to reach epoch_size when it reaches zero. */ uint32_t epoch_heuristic_counter; /** * epoch_size is set to be the number of elements supposed to be in a epoch. - * When the number of non-erased elements in a epoch exceeds epoch_size, a + * When the number of non-erased elements in an epoch exceeds epoch_size, a * new epoch should be started and all current entries demoted. epoch_size * is set to be 45% of size because we want to keep load around 90%, and we * support 3 epochs at once -- one "dead" which has been erased, one "dying" * which has been marked to be erased next, and one "living" which new * inserts add to. */ uint32_t epoch_size; /** * hash_mask should be set to appropriately mask out a hash such that every * masked hash is [0,size), eg, if floor(log2(size)) == 20, then hash_mask * should be (1<<20)-1 */ uint32_t hash_mask; /** * depth_limit determines how many elements insert should try to replace. * Should be set to log2(n) */ uint8_t depth_limit; /** * hash_function is a const instance of the hash function. It cannot be * static or initialized at call time as it may have internal state (such as * a nonce). */ const Hash hash_function; /** * compute_hashes is convenience for not having to write out this expression * everywhere we use the hash values of an Element. * * @param e the element whose hashes will be returned * @returns std::array of deterministic hashes derived from e */ inline std::array compute_hashes(const Element &e) const { return {{hash_function.template operator()<0>(e) & hash_mask, hash_function.template operator()<1>(e) & hash_mask, hash_function.template operator()<2>(e) & hash_mask, hash_function.template operator()<3>(e) & hash_mask, hash_function.template operator()<4>(e) & hash_mask, hash_function.template operator()<5>(e) & hash_mask, hash_function.template operator()<6>(e) & hash_mask, hash_function.template operator()<7>(e) & hash_mask}}; } /* end * @returns a constexpr index that can never be inserted to */ constexpr uint32_t invalid() const { return ~(uint32_t)0; } /** * allow_erase marks the element at index n as discardable. * Threadsafe without any concurrent insert. * @param n the index to allow erasure of */ inline void allow_erase(uint32_t n) const { collection_flags.bit_set(n); } /** * please_keep marks the element at index n as an entry that should be kept. * Threadsafe without any concurrent insert. * @param n the index to prioritize keeping */ inline void please_keep(uint32_t n) const { collection_flags.bit_unset(n); } /** * epoch_check handles the changing of epochs for elements stored in the * cache. epoch_check should be run before every insert. * * First, epoch_check decrements and checks the cheap heuristic, and then * does a more expensive scan if the cheap heuristic runs out. If the * expensive scan succeeds, the epochs are aged and old elements are * allow_erased. The cheap heuristic is reset to retrigger after the worst * case growth of the current epoch's elements would exceed the epoch_size. */ void epoch_check() { if (epoch_heuristic_counter != 0) { --epoch_heuristic_counter; return; } // count the number of elements from the latest epoch which have not // been erased. uint32_t epoch_unused_count = 0; for (uint32_t i = 0; i < size; ++i) epoch_unused_count += epoch_flags[i] && !collection_flags.bit_is_set(i); // If there are more non-deleted entries in the current epoch than the // epoch size, then allow_erase on all elements in the old epoch (marked // false) and move all elements in the current epoch to the old epoch // but do not call allow_erase on their indices. if (epoch_unused_count >= epoch_size) { for (uint32_t i = 0; i < size; ++i) if (epoch_flags[i]) epoch_flags[i] = false; else allow_erase(i); epoch_heuristic_counter = epoch_size; } else { // reset the epoch_heuristic_counter to next do a scan when worst // case behavior (no intermittent erases) would exceed epoch size, // with a reasonable minimum scan size. Ordinarily, we would have to // sanity check std::min(epoch_size, epoch_unused_count), but we // already know that `epoch_unused_count < epoch_size` in this // branch epoch_heuristic_counter = std::max( 1u, std::max(epoch_size / 16, epoch_size - epoch_unused_count)); } } public: /** * You must always construct a cache with some elements via a subsequent * call to setup or setup_bytes, otherwise operations may segfault. */ cache() : table(), size(), collection_flags(0), epoch_flags(), epoch_heuristic_counter(), epoch_size(), depth_limit(0), hash_function() {} /** * setup initializes the container to store no more than new_size elements. * setup rounds down to a power of two size. * * setup should only be called once. * * @param new_size the desired number of elements to store * @returns the maximum number of elements storable */ uint32_t setup(uint32_t new_size) { // depth_limit must be at least one otherwise errors can occur. depth_limit = static_cast( std::log2(static_cast(std::max((uint32_t)2, new_size)))); size = 1 << depth_limit; hash_mask = size - 1; table.resize(size); collection_flags.setup(size); epoch_flags.resize(size); // Set to 45% as described above epoch_size = std::max((uint32_t)1, (45 * size) / 100); // Initially set to wait for a whole epoch epoch_heuristic_counter = epoch_size; return size; } /** * setup_bytes is a convenience function which accounts for internal memory * usage when deciding how many elements to store. It isn't perfect because * it doesn't account for any overhead (struct size, MallocUsage, collection * and epoch flags). This was done to simplify selecting a power of two * size. In the expected use case, an extra two bits per entry should be * negligible compared to the size of the elements. * * @param bytes the approximate number of bytes to use for this data * structure. * @returns the maximum number of elements storable (see setup() * documentation for more detail) */ uint32_t setup_bytes(size_t bytes) { return setup(bytes / sizeof(Element)); } /** * insert loops at most depth_limit times trying to insert a hash at various * locations in the table via a variant of the Cuckoo Algorithm with eight * hash locations. * * It drops the last tried element if it runs out of depth before * encountering an open slot. * * Thus * * insert(x); * return contains(x, false); * * is not guaranteed to return true. * * @param e the element to insert * @post one of the following: All previously inserted elements and e are * now in the table, one previously inserted element is evicted from the * table, the entry attempted to be inserted is evicted. */ inline void insert(Element e) { epoch_check(); uint32_t last_loc = invalid(); bool last_epoch = true; std::array locs = compute_hashes(e); // Make sure we have not already inserted this element. // If we have, make sure that it does not get deleted. for (uint32_t loc : locs) if (table[loc] == e) { please_keep(loc); epoch_flags[loc] = last_epoch; return; } for (uint8_t depth = 0; depth < depth_limit; ++depth) { // First try to insert to an empty slot, if one exists for (uint32_t loc : locs) { if (!collection_flags.bit_is_set(loc)) continue; table[loc] = std::move(e); please_keep(loc); epoch_flags[loc] = last_epoch; return; } /** * Swap with the element at the location that was not the last one * looked at. Example: * * 1) On first iteration, last_loc == invalid(), find returns last, * so last_loc defaults to locs[0]. * 2) On further iterations, where last_loc == locs[k], last_loc * will go to locs[k+1 % 8], i.e., next of the 8 indices wrapping * around to 0 if needed. * * This prevents moving the element we just put in. * * The swap is not a move -- we must switch onto the evicted element * for the next iteration. */ last_loc = locs[(1 + (std::find(locs.begin(), locs.end(), last_loc) - locs.begin())) & 7]; std::swap(table[last_loc], e); // Can't std::swap a std::vector::reference and a bool&. bool epoch = last_epoch; last_epoch = epoch_flags[last_loc]; epoch_flags[last_loc] = epoch; // Recompute the locs -- unfortunately happens one too many times! locs = compute_hashes(e); } } /** * contains iterates through the hash locations for a given element and * checks to see if it is present. * * contains does not check garbage collected state (in other words, garbage * is only collected when the space is needed), so: * * insert(x); * if (contains(x, true)) * return contains(x, false); * else * return true; * * executed on a single thread will always return true! * * This is a great property for re-org performance for example. * * contains returns a bool set true if the element was found. * * @param e the element to check * @param erase * * @post if erase is true and the element is found, then the garbage collect * flag is set * @returns true if the element is found, false otherwise */ inline bool contains(const Element &e, const bool erase) const { std::array locs = compute_hashes(e); for (uint32_t loc : locs) { if (table[loc] == e) { if (erase) { allow_erase(loc); } return true; } } return false; } }; } // namespace CuckooCache #endif // BITCOIN_CUCKOOCACHE_H diff --git a/src/httpserver.h b/src/httpserver.h index 9d37ac12bd..60fb919418 100644 --- a/src/httpserver.h +++ b/src/httpserver.h @@ -1,159 +1,159 @@ // Copyright (c) 2015-2016 The Bitcoin Core developers // Copyright (c) 2018 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_HTTPSERVER_H #define BITCOIN_HTTPSERVER_H #include #include #include static const int DEFAULT_HTTP_THREADS = 4; static const int DEFAULT_HTTP_WORKQUEUE = 16; static const int DEFAULT_HTTP_SERVER_TIMEOUT = 30; struct evhttp_request; struct event_base; class Config; class CService; class HTTPRequest; /** * Initialize HTTP server. * Call this before RegisterHTTPHandler or EventBase(). */ bool InitHTTPServer(Config &config); /** * Start HTTP server. * This is separate from InitHTTPServer to give users race-condition-free time * to register their handlers between InitHTTPServer and StartHTTPServer. */ bool StartHTTPServer(); /** Interrupt HTTP server threads */ void InterruptHTTPServer(); /** Stop HTTP server */ void StopHTTPServer(); /** Handler for requests to a certain HTTP path */ typedef std::function HTTPRequestHandler; /** * Register handler for prefix. * If multiple handlers match a prefix, the first-registered one will * be invoked. */ void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPRequestHandler &handler); /** Unregister handler for prefix */ void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch); /** * Return evhttp event base. This can be used by submodules to * queue timers or custom events. */ struct event_base *EventBase(); /** * In-flight HTTP request. * Thin C++ wrapper around evhttp_request. */ class HTTPRequest { private: struct evhttp_request *req; bool replySent; public: explicit HTTPRequest(struct evhttp_request *req); ~HTTPRequest(); enum RequestMethod { UNKNOWN, GET, POST, HEAD, PUT, OPTIONS }; /** Get requested URI */ std::string GetURI(); /** Get CService (address:ip) for the origin of the http request */ CService GetPeer(); /** Get request method */ RequestMethod GetRequestMethod(); /** * Get the request header specified by hdr, or an empty string. - * Return an pair (isPresent,string). + * Return a pair (isPresent,string). */ std::pair GetHeader(const std::string &hdr); /** * Read request body. * * @note As this consumes the underlying buffer, call this only once. * Repeated calls will return an empty string. */ std::string ReadBody(); /** * Write output header. * * @note call this before calling WriteErrorReply or Reply. */ void WriteHeader(const std::string &hdr, const std::string &value); /** * Write HTTP reply. * nStatus is the HTTP status code to send. * strReply is the body of the reply. Keep it empty to send a standard * message. * * @note Can be called only once. As this will give the request back to the * main thread, do not call any other HTTPRequest methods after calling * this. */ void WriteReply(int nStatus, const std::string &strReply = ""); }; /** Event handler closure */ class HTTPClosure { public: virtual void operator()() = 0; virtual ~HTTPClosure() {} }; /** - * Event class. This can be used either as an cross-thread trigger or as a + * Event class. This can be used either as a cross-thread trigger or as a * timer. */ class HTTPEvent { public: /** * Create a new event. * deleteWhenTriggered deletes this event object after the event is * triggered (and the handler called) * handler is the handler to call when the event is triggered. */ HTTPEvent(struct event_base *base, bool deleteWhenTriggered, const std::function &handler); ~HTTPEvent(); /** * Trigger the event. If tv is 0, trigger it immediately. Otherwise trigger * it after the given time has elapsed. */ void trigger(struct timeval *tv); bool deleteWhenTriggered; std::function handler; private: struct event *ev; }; #endif // BITCOIN_HTTPSERVER_H diff --git a/src/leveldb/db/version_set.h b/src/leveldb/db/version_set.h index c4e7ac360b..7935a965a7 100644 --- a/src/leveldb/db/version_set.h +++ b/src/leveldb/db/version_set.h @@ -1,398 +1,398 @@ // Copyright (c) 2011 The LevelDB Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. See the AUTHORS file for names of contributors. // // The representation of a DBImpl consists of a set of Versions. The // newest version is called "current". Older versions may be kept // around to provide a consistent view to live iterators. // // Each Version keeps track of a set of Table files per level. The // entire set of versions is maintained in a VersionSet. // // Version,VersionSet are thread-compatible, but require external // synchronization on all accesses. #ifndef STORAGE_LEVELDB_DB_VERSION_SET_H_ #define STORAGE_LEVELDB_DB_VERSION_SET_H_ #include #include #include #include "db/dbformat.h" #include "db/version_edit.h" #include "port/port.h" #include "port/thread_annotations.h" namespace leveldb { namespace log { class Writer; } class Compaction; class Iterator; class MemTable; class TableBuilder; class TableCache; class Version; class VersionSet; class WritableFile; // Return the smallest index i such that files[i]->largest >= key. // Return files.size() if there is no such file. // REQUIRES: "files" contains a sorted list of non-overlapping files. extern int FindFile(const InternalKeyComparator& icmp, const std::vector& files, const Slice& key); // Returns true iff some file in "files" overlaps the user key range // [*smallest,*largest]. // smallest==NULL represents a key smaller than all keys in the DB. // largest==NULL represents a key largest than all keys in the DB. // REQUIRES: If disjoint_sorted_files, files[] contains disjoint ranges // in sorted order. extern bool SomeFileOverlapsRange( const InternalKeyComparator& icmp, bool disjoint_sorted_files, const std::vector& files, const Slice* smallest_user_key, const Slice* largest_user_key); class Version { public: // Append to *iters a sequence of iterators that will // yield the contents of this Version when merged together. // REQUIRES: This version has been saved (see VersionSet::SaveTo) void AddIterators(const ReadOptions&, std::vector* iters); // Lookup the value for key. If found, store it in *val and // return OK. Else return a non-OK status. Fills *stats. // REQUIRES: lock is not held struct GetStats { FileMetaData* seek_file; int seek_file_level; }; Status Get(const ReadOptions&, const LookupKey& key, std::string* val, GetStats* stats); // Adds "stats" into the current state. Returns true if a new // compaction may need to be triggered, false otherwise. // REQUIRES: lock is held bool UpdateStats(const GetStats& stats); // Record a sample of bytes read at the specified internal key. // Samples are taken approximately once every config::kReadBytesPeriod // bytes. Returns true if a new compaction may need to be triggered. // REQUIRES: lock is held bool RecordReadSample(Slice key); // Reference count management (so Versions do not disappear out from // under live iterators) void Ref(); void Unref(); void GetOverlappingInputs( int level, const InternalKey* begin, // NULL means before all keys const InternalKey* end, // NULL means after all keys std::vector* inputs); // Returns true iff some file in the specified level overlaps // some part of [*smallest_user_key,*largest_user_key]. // smallest_user_key==NULL represents a key smaller than all keys in the DB. // largest_user_key==NULL represents a key largest than all keys in the DB. bool OverlapInLevel(int level, const Slice* smallest_user_key, const Slice* largest_user_key); // Return the level at which we should place a new memtable compaction // result that covers the range [smallest_user_key,largest_user_key]. int PickLevelForMemTableOutput(const Slice& smallest_user_key, const Slice& largest_user_key); int NumFiles(int level) const { return files_[level].size(); } // Return a human readable string that describes this version's contents. std::string DebugString() const; private: friend class Compaction; friend class VersionSet; class LevelFileNumIterator; Iterator* NewConcatenatingIterator(const ReadOptions&, int level) const; // Call func(arg, level, f) for every file that overlaps user_key in // order from newest to oldest. If an invocation of func returns // false, makes no more calls. // // REQUIRES: user portion of internal_key == user_key. void ForEachOverlapping(Slice user_key, Slice internal_key, void* arg, bool (*func)(void*, int, FileMetaData*)); VersionSet* vset_; // VersionSet to which this Version belongs Version* next_; // Next version in linked list Version* prev_; // Previous version in linked list int refs_; // Number of live refs to this version // List of files per level std::vector files_[config::kNumLevels]; // Next file to compact based on seek stats. FileMetaData* file_to_compact_; int file_to_compact_level_; // Level that should be compacted next and its compaction score. // Score < 1 means compaction is not strictly needed. These fields // are initialized by Finalize(). double compaction_score_; int compaction_level_; explicit Version(VersionSet* vset) : vset_(vset), next_(this), prev_(this), refs_(0), file_to_compact_(NULL), file_to_compact_level_(-1), compaction_score_(-1), compaction_level_(-1) { } ~Version(); // No copying allowed Version(const Version&); void operator=(const Version&); }; class VersionSet { public: VersionSet(const std::string& dbname, const Options* options, TableCache* table_cache, const InternalKeyComparator*); ~VersionSet(); // Apply *edit to the current version to form a new descriptor that // is both saved to persistent state and installed as the new // current version. Will release *mu while actually writing to the file. // REQUIRES: *mu is held on entry. // REQUIRES: no other thread concurrently calls LogAndApply() Status LogAndApply(VersionEdit* edit, port::Mutex* mu) EXCLUSIVE_LOCKS_REQUIRED(mu); // Recover the last saved descriptor from persistent storage. Status Recover(bool *save_manifest); // Return the current version. Version* current() const { return current_; } // Return the current manifest file number uint64_t ManifestFileNumber() const { return manifest_file_number_; } // Allocate and return a new file number uint64_t NewFileNumber() { return next_file_number_++; } // Arrange to reuse "file_number" unless a newer file number has // already been allocated. // REQUIRES: "file_number" was returned by a call to NewFileNumber(). void ReuseFileNumber(uint64_t file_number) { if (next_file_number_ == file_number + 1) { next_file_number_ = file_number; } } // Return the number of Table files at the specified level. int NumLevelFiles(int level) const; // Return the combined file size of all files at the specified level. int64_t NumLevelBytes(int level) const; // Return the last sequence number. uint64_t LastSequence() const { return last_sequence_; } // Set the last sequence number to s. void SetLastSequence(uint64_t s) { assert(s >= last_sequence_); last_sequence_ = s; } // Mark the specified file number as used. void MarkFileNumberUsed(uint64_t number); // Return the current log file number. uint64_t LogNumber() const { return log_number_; } // Return the log file number for the log file that is currently // being compacted, or zero if there is no such log file. uint64_t PrevLogNumber() const { return prev_log_number_; } // Pick level and inputs for a new compaction. // Returns NULL if there is no compaction to be done. // Otherwise returns a pointer to a heap-allocated object that // describes the compaction. Caller should delete the result. Compaction* PickCompaction(); // Return a compaction object for compacting the range [begin,end] in // the specified level. Returns NULL if there is nothing in that // level that overlaps the specified range. Caller should delete // the result. Compaction* CompactRange( int level, const InternalKey* begin, const InternalKey* end); // Return the maximum overlapping data (in bytes) at next level for any // file at a level >= 1. int64_t MaxNextLevelOverlappingBytes(); // Create an iterator that reads over the compaction inputs for "*c". // The caller should delete the iterator when no longer needed. Iterator* MakeInputIterator(Compaction* c); // Returns true iff some level needs a compaction. bool NeedsCompaction() const { Version* v = current_; return (v->compaction_score_ >= 1) || (v->file_to_compact_ != NULL); } // Add all files listed in any live version to *live. // May also mutate some internal state. void AddLiveFiles(std::set* live); // Return the approximate offset in the database of the data for // "key" as of version "v". uint64_t ApproximateOffsetOf(Version* v, const InternalKey& key); // Return a human-readable short (single-line) summary of the number // of files per level. Uses *scratch as backing store. struct LevelSummaryStorage { char buffer[100]; }; const char* LevelSummary(LevelSummaryStorage* scratch) const; private: class Builder; friend class Compaction; friend class Version; bool ReuseManifest(const std::string& dscname, const std::string& dscbase); void Finalize(Version* v); void GetRange(const std::vector& inputs, InternalKey* smallest, InternalKey* largest); void GetRange2(const std::vector& inputs1, const std::vector& inputs2, InternalKey* smallest, InternalKey* largest); void SetupOtherInputs(Compaction* c); // Save current contents to *log Status WriteSnapshot(log::Writer* log); void AppendVersion(Version* v); Env* const env_; const std::string dbname_; const Options* const options_; TableCache* const table_cache_; const InternalKeyComparator icmp_; uint64_t next_file_number_; uint64_t manifest_file_number_; uint64_t last_sequence_; uint64_t log_number_; uint64_t prev_log_number_; // 0 or backing store for memtable being compacted // Opened lazily WritableFile* descriptor_file_; log::Writer* descriptor_log_; Version dummy_versions_; // Head of circular doubly-linked list of versions. Version* current_; // == dummy_versions_.prev_ // Per-level key at which the next compaction at that level should start. // Either an empty string, or a valid InternalKey. std::string compact_pointer_[config::kNumLevels]; // No copying allowed VersionSet(const VersionSet&); void operator=(const VersionSet&); }; // A Compaction encapsulates information about a compaction. class Compaction { public: ~Compaction(); // Return the level that is being compacted. Inputs from "level" // and "level+1" will be merged to produce a set of "level+1" files. int level() const { return level_; } // Return the object that holds the edits to the descriptor done // by this compaction. VersionEdit* edit() { return &edit_; } // "which" must be either 0 or 1 int num_input_files(int which) const { return inputs_[which].size(); } // Return the ith input file at "level()+which" ("which" must be 0 or 1). FileMetaData* input(int which, int i) const { return inputs_[which][i]; } // Maximum size of files to build during this compaction. uint64_t MaxOutputFileSize() const { return max_output_file_size_; } // Is this a trivial compaction that can be implemented by just // moving a single input file to the next level (no merging or splitting) bool IsTrivialMove() const; // Add all inputs to this compaction as delete operations to *edit. void AddInputDeletions(VersionEdit* edit); // Returns true if the information we have available guarantees that // the compaction is producing data in "level+1" for which no data exists // in levels greater than "level+1". bool IsBaseLevelForKey(const Slice& user_key); // Returns true iff we should stop building the current output // before processing "internal_key". bool ShouldStopBefore(const Slice& internal_key); // Release the input version for the compaction, once the compaction // is successful. void ReleaseInputs(); private: friend class Version; friend class VersionSet; Compaction(const Options* options, int level); int level_; uint64_t max_output_file_size_; Version* input_version_; VersionEdit edit_; // Each compaction reads inputs from "level_" and "level_+1" std::vector inputs_[2]; // The two sets of inputs - // State used to check for number of of overlapping grandparent files + // State used to check for number of overlapping grandparent files // (parent == level_ + 1, grandparent == level_ + 2) std::vector grandparents_; size_t grandparent_index_; // Index in grandparent_starts_ bool seen_key_; // Some output key has been seen int64_t overlapped_bytes_; // Bytes of overlap between current output // and grandparent files // State for implementing IsBaseLevelForKey // level_ptrs_ holds indices into input_version_->levels_: our state // is that we are positioned at one of the file ranges for each // higher level than the ones involved in this compaction (i.e. for // all L >= level_ + 2). size_t level_ptrs_[config::kNumLevels]; }; } // namespace leveldb #endif // STORAGE_LEVELDB_DB_VERSION_SET_H_ diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 6243098e2b..ad1e5d047b 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -1,262 +1,262 @@ // Copyright (c) 2011-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class CBlockIndex; static int64_t nLastHeaderTipUpdateNotification = 0; static int64_t nLastBlockTipUpdateNotification = 0; ClientModel::ClientModel(interfaces::Node &node, OptionsModel *_optionsModel, QObject *parent) : QObject(parent), m_node(node), optionsModel(_optionsModel), peerTableModel(0), banTableModel(0), pollTimer(0) { cachedBestHeaderHeight = -1; cachedBestHeaderTime = -1; peerTableModel = new PeerTableModel(m_node, this); banTableModel = new BanTableModel(m_node, this); pollTimer = new QTimer(this); connect(pollTimer, SIGNAL(timeout()), this, SLOT(updateTimer())); pollTimer->start(MODEL_UPDATE_DELAY); subscribeToCoreSignals(); } ClientModel::~ClientModel() { unsubscribeFromCoreSignals(); } int ClientModel::getNumConnections(unsigned int flags) const { CConnman::NumConnections connections = CConnman::CONNECTIONS_NONE; if (flags == CONNECTIONS_IN) { connections = CConnman::CONNECTIONS_IN; } else if (flags == CONNECTIONS_OUT) { connections = CConnman::CONNECTIONS_OUT; } else if (flags == CONNECTIONS_ALL) { connections = CConnman::CONNECTIONS_ALL; } return m_node.getNodeCount(connections); } int ClientModel::getHeaderTipHeight() const { if (cachedBestHeaderHeight == -1) { // make sure we initially populate the cache via a cs_main lock // otherwise we need to wait for a tip update int height; int64_t blockTime; if (m_node.getHeaderTip(height, blockTime)) { cachedBestHeaderHeight = height; cachedBestHeaderTime = blockTime; } } return cachedBestHeaderHeight; } int64_t ClientModel::getHeaderTipTime() const { if (cachedBestHeaderTime == -1) { int height; int64_t blockTime; if (m_node.getHeaderTip(height, blockTime)) { cachedBestHeaderHeight = height; cachedBestHeaderTime = blockTime; } } return cachedBestHeaderTime; } void ClientModel::updateTimer() { // no locking required at this point // the following calls will acquire the required lock Q_EMIT mempoolSizeChanged(m_node.getMempoolSize(), m_node.getMempoolDynamicUsage()); Q_EMIT bytesChanged(m_node.getTotalBytesRecv(), m_node.getTotalBytesSent()); } void ClientModel::updateNumConnections(int numConnections) { Q_EMIT numConnectionsChanged(numConnections); } void ClientModel::updateNetworkActive(bool networkActive) { Q_EMIT networkActiveChanged(networkActive); } void ClientModel::updateAlert() { Q_EMIT alertsChanged(getStatusBarWarnings()); } enum BlockSource ClientModel::getBlockSource() const { if (m_node.getReindex()) { return BlockSource::REINDEX; } else if (m_node.getImporting()) { return BlockSource::DISK; } else if (getNumConnections() > 0) { return BlockSource::NETWORK; } return BlockSource::NONE; } QString ClientModel::getStatusBarWarnings() const { return QString::fromStdString(m_node.getWarnings("gui")); } OptionsModel *ClientModel::getOptionsModel() { return optionsModel; } PeerTableModel *ClientModel::getPeerTableModel() { return peerTableModel; } BanTableModel *ClientModel::getBanTableModel() { return banTableModel; } QString ClientModel::formatFullVersion() const { return QString::fromStdString(FormatFullVersion()); } QString ClientModel::formatSubVersion() const { return QString::fromStdString(userAgent(GetConfig())); } bool ClientModel::isReleaseVersion() const { return CLIENT_VERSION_IS_RELEASE; } QString ClientModel::formatClientStartupTime() const { return QDateTime::fromTime_t(GetStartupTime()).toString(); } QString ClientModel::dataDir() const { return GUIUtil::boostPathToQString(GetDataDir()); } void ClientModel::updateBanlist() { banTableModel->refresh(); } // Handlers for core signals static void ShowProgress(ClientModel *clientmodel, const std::string &title, int nProgress) { // emits signal "showProgress" QMetaObject::invokeMethod(clientmodel, "showProgress", Qt::QueuedConnection, Q_ARG(QString, QString::fromStdString(title)), Q_ARG(int, nProgress)); } static void NotifyNumConnectionsChanged(ClientModel *clientmodel, int newNumConnections) { // Too noisy: qDebug() << "NotifyNumConnectionsChanged: " + // QString::number(newNumConnections); QMetaObject::invokeMethod(clientmodel, "updateNumConnections", Qt::QueuedConnection, Q_ARG(int, newNumConnections)); } static void NotifyNetworkActiveChanged(ClientModel *clientmodel, bool networkActive) { QMetaObject::invokeMethod(clientmodel, "updateNetworkActive", Qt::QueuedConnection, Q_ARG(bool, networkActive)); } static void NotifyAlertChanged(ClientModel *clientmodel) { qDebug() << "NotifyAlertChanged"; QMetaObject::invokeMethod(clientmodel, "updateAlert", Qt::QueuedConnection); } static void BannedListChanged(ClientModel *clientmodel) { qDebug() << QString("%1: Requesting update for peer banlist").arg(__func__); QMetaObject::invokeMethod(clientmodel, "updateBanlist", Qt::QueuedConnection); } static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, int height, int64_t blockTime, double verificationProgress, bool fHeader) { // lock free async UI updates in case we have a new block tip // during initial sync, only update the UI if the last update // was > 250ms (MODEL_UPDATE_DELAY) ago int64_t now = 0; if (initialSync) { now = GetTimeMillis(); } int64_t &nLastUpdateNotification = fHeader ? nLastHeaderTipUpdateNotification : nLastBlockTipUpdateNotification; if (fHeader) { // cache best headers time and height to reduce future cs_main locks clientmodel->cachedBestHeaderHeight = height; clientmodel->cachedBestHeaderTime = blockTime; } // if we are in-sync, update the UI regardless of last update time if (!initialSync || now - nLastUpdateNotification > MODEL_UPDATE_DELAY) { - // pass a async signal to the UI thread + // pass an async signal to the UI thread QMetaObject::invokeMethod( clientmodel, "numBlocksChanged", Qt::QueuedConnection, Q_ARG(int, height), Q_ARG(QDateTime, QDateTime::fromTime_t(blockTime)), Q_ARG(double, verificationProgress), Q_ARG(bool, fHeader)); nLastUpdateNotification = now; } } void ClientModel::subscribeToCoreSignals() { // Connect signals to client m_handler_show_progress = m_node.handleShowProgress(boost::bind(ShowProgress, this, _1, _2)); m_handler_notify_num_connections_changed = m_node.handleNotifyNumConnectionsChanged( boost::bind(NotifyNumConnectionsChanged, this, _1)); m_handler_notify_network_active_changed = m_node.handleNotifyNetworkActiveChanged( boost::bind(NotifyNetworkActiveChanged, this, _1)); m_handler_notify_alert_changed = m_node.handleNotifyAlertChanged(boost::bind(NotifyAlertChanged, this)); m_handler_banned_list_changed = m_node.handleBannedListChanged(boost::bind(BannedListChanged, this)); m_handler_notify_block_tip = m_node.handleNotifyBlockTip( boost::bind(BlockTipChanged, this, _1, _2, _3, _4, false)); m_handler_notify_header_tip = m_node.handleNotifyHeaderTip( boost::bind(BlockTipChanged, this, _1, _2, _3, _4, true)); } void ClientModel::unsubscribeFromCoreSignals() { // Disconnect signals from client m_handler_show_progress->disconnect(); m_handler_notify_num_connections_changed->disconnect(); m_handler_notify_network_active_changed->disconnect(); m_handler_notify_alert_changed->disconnect(); m_handler_banned_list_changed->disconnect(); m_handler_notify_block_tip->disconnect(); m_handler_notify_header_tip->disconnect(); } diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui index 4a76454c75..890ab7370a 100644 --- a/src/qt/forms/optionsdialog.ui +++ b/src/qt/forms/optionsdialog.ui @@ -1,799 +1,799 @@ OptionsDialog 0 0 560 440 Options true 0 &Main Automatically start %1 after logging in to the system. &Start %1 on system login Size of &database cache Qt::PlainText databaseCache MB Qt::PlainText Qt::Horizontal 40 20 Number of script &verification threads Qt::PlainText threadsScriptVerif (0 = auto, <0 = leave that many cores free) Qt::Horizontal 40 20 Qt::Vertical 20 40 W&allet Expert Whether to show coin control features or not. Enable coin &control features If you disable the spending of unconfirmed change, the change from a transaction cannot be used until that transaction has at least one confirmation. This also affects how your balance is computed. &Spend unconfirmed change Qt::Vertical 20 40 &Network Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled. Map port using &UPnP Accept connections from outside Allow incoming connections Connect to the Bitcoin network through a SOCKS5 proxy. &Connect through SOCKS5 proxy (default proxy): Proxy &IP: Qt::PlainText proxyIp 140 0 140 16777215 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) &Port: Qt::PlainText proxyPort 55 0 55 16777215 Port of the proxy (e.g. 9050) Qt::Horizontal 40 20 Used for reaching peers via: Qt::PlainText false - Shows, if the supplied default SOCKS5 proxy is used to reach peers via this network type. + Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type. IPv4 Qt::PlainText false - Shows, if the supplied default SOCKS5 proxy is used to reach peers via this network type. + Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type. IPv6 Qt::PlainText false - Shows, if the supplied default SOCKS5 proxy is used to reach peers via this network type. + Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type. Tor Qt::PlainText Qt::Horizontal 40 20 Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services. Use separate SOCKS5 proxy to reach peers via Tor hidden services: Proxy &IP: Qt::PlainText proxyIpTor 140 0 140 16777215 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) &Port: Qt::PlainText proxyPortTor 55 0 55 16777215 Port of the proxy (e.g. 9050) Qt::Horizontal 40 20 Qt::Vertical 20 40 &Window &Hide the icon from the system tray. Hide tray icon Show only a tray icon after minimizing the window. &Minimize to the tray instead of the taskbar Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu. M&inimize on close Qt::Vertical 20 40 &Display User Interface &language: Qt::PlainText lang The user interface language can be set here. This setting will take effect after restarting %1. &Unit to show amounts in: Qt::PlainText unit Choose the default subdivision unit to show in the interface and when sending coins. Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. Third party transaction URLs thirdPartyTxUrls Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. Qt::Vertical 20 40 Active command-line options that override above options: Qt::PlainText Qt::Horizontal 40 20 Qt::PlainText true Reset all client options to default. &Reset Options false Qt::Horizontal 40 48 200 0 75 true Qt::PlainText true Qt::Horizontal 40 48 &OK false true &Cancel false QValidatedLineEdit QLineEdit
qt/qvalidatedlineedit.h
QValueComboBox QComboBox
qt/qvaluecombobox.h
diff --git a/src/qt/modaloverlay.cpp b/src/qt/modaloverlay.cpp index e1a44801b1..e840d3dfeb 100644 --- a/src/qt/modaloverlay.cpp +++ b/src/qt/modaloverlay.cpp @@ -1,165 +1,165 @@ // Copyright (c) 2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include #include #include #include #include ModalOverlay::ModalOverlay(QWidget *parent) : QWidget(parent), ui(new Ui::ModalOverlay), bestHeaderHeight(0), bestHeaderDate(QDateTime()), layerIsVisible(false), userClosed(false) { ui->setupUi(this); connect(ui->closeButton, SIGNAL(clicked()), this, SLOT(closeClicked())); if (parent) { parent->installEventFilter(this); raise(); } blockProcessTime.clear(); setVisible(false); } ModalOverlay::~ModalOverlay() { delete ui; } bool ModalOverlay::eventFilter(QObject *obj, QEvent *ev) { if (obj == parent()) { if (ev->type() == QEvent::Resize) { QResizeEvent *rev = static_cast(ev); resize(rev->size()); if (!layerIsVisible) setGeometry(0, height(), width(), height()); } else if (ev->type() == QEvent::ChildAdded) { raise(); } } return QWidget::eventFilter(obj, ev); } //! Tracks parent widget changes bool ModalOverlay::event(QEvent *ev) { if (ev->type() == QEvent::ParentAboutToChange) { if (parent()) parent()->removeEventFilter(this); } else if (ev->type() == QEvent::ParentChange) { if (parent()) { parent()->installEventFilter(this); raise(); } } return QWidget::event(ev); } void ModalOverlay::setKnownBestHeight(int count, const QDateTime &blockDate) { if (count > bestHeaderHeight) { bestHeaderHeight = count; bestHeaderDate = blockDate; } } void ModalOverlay::tipUpdate(int count, const QDateTime &blockDate, double nVerificationProgress) { QDateTime currentDate = QDateTime::currentDateTime(); // keep a vector of samples of verification progress at height blockProcessTime.push_front( qMakePair(currentDate.toMSecsSinceEpoch(), nVerificationProgress)); // show progress speed if we have more then one sample if (blockProcessTime.size() >= 2) { double progressStart = blockProcessTime[0].second; double progressDelta = 0; double progressPerHour = 0; qint64 timeDelta = 0; qint64 remainingMSecs = 0; double remainingProgress = 1.0 - nVerificationProgress; for (int i = 1; i < blockProcessTime.size(); i++) { QPair sample = blockProcessTime[i]; // take first sample after 500 seconds or last available one if (sample.first < (currentDate.toMSecsSinceEpoch() - 500 * 1000) || i == blockProcessTime.size() - 1) { progressDelta = progressStart - sample.second; timeDelta = blockProcessTime[0].first - sample.first; progressPerHour = progressDelta / (double)timeDelta * 1000 * 3600; remainingMSecs = remainingProgress / progressDelta * timeDelta; break; } } // show progress increase per hour ui->progressIncreasePerH->setText( QString::number(progressPerHour * 100, 'f', 2) + "%"); // show expected remaining time ui->expectedTimeLeft->setText( GUIUtil::formatNiceTimeOffset(remainingMSecs / 1000.0)); static const int MAX_SAMPLES = 5000; if (blockProcessTime.count() > MAX_SAMPLES) blockProcessTime.remove(MAX_SAMPLES, blockProcessTime.count() - MAX_SAMPLES); } // show the last block date ui->newestBlockDate->setText(blockDate.toString()); // show the percentage done according to nVerificationProgress ui->percentageProgress->setText( QString::number(nVerificationProgress * 100, 'f', 2) + "%"); ui->progressBar->setValue(nVerificationProgress * 100); if (!bestHeaderDate.isValid()) // not syncing return; // estimate the number of headers left based on nPowTargetSpacing - // and check if the gui is not aware of the the best header (happens rarely) + // and check if the gui is not aware of the best header (happens rarely) int estimateNumHeadersLeft = bestHeaderDate.secsTo(currentDate) / Params().GetConsensus().nPowTargetSpacing; bool hasBestHeader = bestHeaderHeight >= count; // show remaining number of blocks if (estimateNumHeadersLeft < HEADER_HEIGHT_DELTA_SYNC && hasBestHeader) { ui->numberOfBlocksLeft->setText( QString::number(bestHeaderHeight - count)); } else { ui->numberOfBlocksLeft->setText( tr("Unknown. Syncing Headers (%1)...").arg(bestHeaderHeight)); ui->expectedTimeLeft->setText(tr("Unknown...")); } } void ModalOverlay::toggleVisibility() { showHide(layerIsVisible, true); if (!layerIsVisible) userClosed = true; } void ModalOverlay::showHide(bool hide, bool userRequested) { if ((layerIsVisible && !hide) || (!layerIsVisible && hide) || (!hide && userClosed && !userRequested)) return; if (!isVisible() && !hide) setVisible(true); setGeometry(0, hide ? 0 : height(), width(), height()); QPropertyAnimation *animation = new QPropertyAnimation(this, "pos"); animation->setDuration(300); animation->setStartValue(QPoint(0, hide ? 0 : this->height())); animation->setEndValue(QPoint(0, hide ? this->height() : 0)); animation->setEasingCurve(QEasingCurve::OutQuad); animation->start(QAbstractAnimation::DeleteWhenStopped); layerIsVisible = !hide; } void ModalOverlay::closeClicked() { showHide(true); userClosed = true; } diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index a5b872d426..c47c16421e 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -1,1435 +1,1435 @@ // Copyright (c) 2011-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef ENABLE_WALLET #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include // TODO: add a scrollback limit, as there is currently none // TODO: make it possible to filter out categories (esp debug messages when // implemented) // TODO: receive errors and debug messages through ClientModel const int CONSOLE_HISTORY = 50; const int INITIAL_TRAFFIC_GRAPH_MINS = 30; const QSize FONT_RANGE(4, 40); const char fontSizeSettingsKey[] = "consoleFontSize"; const struct { const char *url; const char *source; } ICON_MAPPING[] = {{"cmd-request", ":/icons/tx_input"}, {"cmd-reply", ":/icons/tx_output"}, {"cmd-error", ":/icons/tx_output"}, {"misc", ":/icons/tx_inout"}, {nullptr, nullptr}}; namespace { // don't add private key handling cmd's to the history const QStringList historyFilter = QStringList() << "importprivkey" << "importmulti" << "signmessagewithprivkey" << "signrawtransaction" << "signrawtransactionwithkey" << "walletpassphrase" << "walletpassphrasechange" << "encryptwallet"; } // namespace /* Object for executing console RPC commands in a separate thread. */ class RPCExecutor : public QObject { Q_OBJECT public: RPCExecutor(interfaces::Node &node) : m_node(node) {} public Q_SLOTS: void request(const QString &command, const QString &walletID); Q_SIGNALS: void reply(int category, const QString &command); private: interfaces::Node &m_node; }; /** Class for handling RPC timers * (used for e.g. re-locking the wallet after a timeout) */ class QtRPCTimerBase : public QObject, public RPCTimerBase { Q_OBJECT public: QtRPCTimerBase(std::function &_func, int64_t millis) : func(_func) { timer.setSingleShot(true); connect(&timer, SIGNAL(timeout()), this, SLOT(timeout())); timer.start(millis); } ~QtRPCTimerBase() {} private Q_SLOTS: void timeout() { func(); } private: QTimer timer; std::function func; }; class QtRPCTimerInterface : public RPCTimerInterface { public: ~QtRPCTimerInterface() {} const char *Name() override { return "Qt"; } RPCTimerBase *NewTimer(std::function &func, int64_t millis) override { return new QtRPCTimerBase(func, millis); } }; #include /** * Split shell command line into a list of arguments and optionally execute the * command(s). * Aims to emulate \c bash and friends. * * - Command nesting is possible with parenthesis; for example: * validateaddress(getnewaddress()) * - Arguments are delimited with whitespace or comma * - Extra whitespace at the beginning and end and between arguments will be * ignored * - Text can be "double" or 'single' quoted * - The backslash \c \ is used as escape character * - Outside quotes, any character can be escaped * - Within double quotes, only escape \c " and backslashes before a \c " or * another backslash * - Within single quotes, no escaping is possible and no special * interpretation takes place * * @param[in] node optional node to execute command on * @param[out] result stringified Result from the executed command(chain) * @param[in] strCommand Command line to split * @param[in] fExecute set true if you want the command to be executed * @param[out] pstrFilteredOut Command line, filtered to remove any sensitive * data */ bool RPCConsole::RPCParseCommandLine(interfaces::Node *node, std::string &strResult, const std::string &strCommand, const bool fExecute, std::string *const pstrFilteredOut, const std::string *walletID) { std::vector> stack; stack.push_back(std::vector()); enum CmdParseState { STATE_EATING_SPACES, STATE_EATING_SPACES_IN_ARG, STATE_EATING_SPACES_IN_BRACKETS, STATE_ARGUMENT, STATE_SINGLEQUOTED, STATE_DOUBLEQUOTED, STATE_ESCAPE_OUTER, STATE_ESCAPE_DOUBLEQUOTED, STATE_COMMAND_EXECUTED, STATE_COMMAND_EXECUTED_INNER } state = STATE_EATING_SPACES; std::string curarg; UniValue lastResult; unsigned nDepthInsideSensitive = 0; size_t filter_begin_pos = 0, chpos; std::vector> filter_ranges; auto add_to_current_stack = [&](const std::string &strArg) { if (stack.back().empty() && (!nDepthInsideSensitive) && historyFilter.contains(QString::fromStdString(strArg), Qt::CaseInsensitive)) { nDepthInsideSensitive = 1; filter_begin_pos = chpos; } // Make sure stack is not empty before adding something if (stack.empty()) { stack.push_back(std::vector()); } stack.back().push_back(strArg); }; auto close_out_params = [&]() { if (nDepthInsideSensitive) { if (!--nDepthInsideSensitive) { assert(filter_begin_pos); filter_ranges.push_back( std::make_pair(filter_begin_pos, chpos)); filter_begin_pos = 0; } } stack.pop_back(); }; std::string strCommandTerminated = strCommand; if (strCommandTerminated.back() != '\n') strCommandTerminated += "\n"; for (chpos = 0; chpos < strCommandTerminated.size(); ++chpos) { char ch = strCommandTerminated[chpos]; switch (state) { case STATE_COMMAND_EXECUTED_INNER: case STATE_COMMAND_EXECUTED: { bool breakParsing = true; switch (ch) { case '[': curarg.clear(); state = STATE_COMMAND_EXECUTED_INNER; break; default: if (state == STATE_COMMAND_EXECUTED_INNER) { if (ch != ']') { // append char to the current argument (which is // also used for the query command) curarg += ch; break; } if (curarg.size() && fExecute) { // if we have a value query, query arrays with // index and objects with a string key UniValue subelement; if (lastResult.isArray()) { for (char argch : curarg) { if (!std::isdigit(argch)) { throw std::runtime_error( "Invalid result query"); } } subelement = lastResult[atoi(curarg.c_str())]; } else if (lastResult.isObject()) { subelement = find_value(lastResult, curarg); } else { // no array or object: abort throw std::runtime_error( "Invalid result query"); } lastResult = subelement; } state = STATE_COMMAND_EXECUTED; break; } // don't break parsing when the char is required for the // next argument breakParsing = false; // pop the stack and return the result to the current // command arguments close_out_params(); // don't stringify the json in case of a string to avoid // doublequotes if (lastResult.isStr()) { curarg = lastResult.get_str(); } else { curarg = lastResult.write(2); } // if we have a non empty result, use it as stack // argument otherwise as general result if (curarg.size()) { if (stack.size()) { add_to_current_stack(curarg); } else { strResult = curarg; } } curarg.clear(); // assume eating space state state = STATE_EATING_SPACES; } if (breakParsing) { break; } } // FALLTHROUGH case STATE_ARGUMENT: // In or after argument case STATE_EATING_SPACES_IN_ARG: case STATE_EATING_SPACES_IN_BRACKETS: case STATE_EATING_SPACES: // Handle runs of whitespace switch (ch) { case '"': state = STATE_DOUBLEQUOTED; break; case '\'': state = STATE_SINGLEQUOTED; break; case '\\': state = STATE_ESCAPE_OUTER; break; case '(': case ')': case '\n': if (state == STATE_EATING_SPACES_IN_ARG) { throw std::runtime_error("Invalid Syntax"); } if (state == STATE_ARGUMENT) { if (ch == '(' && stack.size() && stack.back().size() > 0) { if (nDepthInsideSensitive) { ++nDepthInsideSensitive; } stack.push_back(std::vector()); } // don't allow commands after executed commands on // baselevel if (!stack.size()) { throw std::runtime_error("Invalid Syntax"); } add_to_current_stack(curarg); curarg.clear(); state = STATE_EATING_SPACES_IN_BRACKETS; } if ((ch == ')' || ch == '\n') && stack.size() > 0) { if (fExecute) { // Convert argument list to JSON objects in // method-dependent way, and pass it along with // the method name to the dispatcher. UniValue params = RPCConvertValues( stack.back()[0], std::vector( stack.back().begin() + 1, stack.back().end())); std::string method = stack.back()[0]; std::string uri; #ifdef ENABLE_WALLET if (walletID && !walletID->empty()) { QByteArray encodedName = QUrl::toPercentEncoding( QString::fromStdString(*walletID)); uri = "/wallet/" + std::string(encodedName.constData(), encodedName.length()); } #endif GlobalConfig config; assert(node); lastResult = node->executeRpc(config, method, params, uri); } state = STATE_COMMAND_EXECUTED; curarg.clear(); } break; case ' ': case ',': case '\t': if (state == STATE_EATING_SPACES_IN_ARG && curarg.empty() && ch == ',') { throw std::runtime_error("Invalid Syntax"); } else if (state == STATE_ARGUMENT) { // Space ends argument add_to_current_stack(curarg); curarg.clear(); } if ((state == STATE_EATING_SPACES_IN_BRACKETS || state == STATE_ARGUMENT) && ch == ',') { state = STATE_EATING_SPACES_IN_ARG; break; } state = STATE_EATING_SPACES; break; default: curarg += ch; state = STATE_ARGUMENT; } break; case STATE_SINGLEQUOTED: // Single-quoted string switch (ch) { case '\'': state = STATE_ARGUMENT; break; default: curarg += ch; } break; case STATE_DOUBLEQUOTED: // Double-quoted string switch (ch) { case '"': state = STATE_ARGUMENT; break; case '\\': state = STATE_ESCAPE_DOUBLEQUOTED; break; default: curarg += ch; } break; case STATE_ESCAPE_OUTER: // '\' outside quotes curarg += ch; state = STATE_ARGUMENT; break; case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text if (ch != '"' && ch != '\\') { // keep '\' for everything but the quote and '\' itself curarg += '\\'; } curarg += ch; state = STATE_DOUBLEQUOTED; break; } } if (pstrFilteredOut) { if (STATE_COMMAND_EXECUTED == state) { assert(!stack.empty()); close_out_params(); } *pstrFilteredOut = strCommand; for (auto i = filter_ranges.rbegin(); i != filter_ranges.rend(); ++i) { pstrFilteredOut->replace(i->first, i->second - i->first, "(…)"); } } // final state switch (state) { case STATE_COMMAND_EXECUTED: if (lastResult.isStr()) { strResult = lastResult.get_str(); } else { strResult = lastResult.write(2); } // FALLTHROUGH case STATE_ARGUMENT: case STATE_EATING_SPACES: return true; default: // ERROR to end in one of the other states return false; } } void RPCExecutor::request(const QString &command, const QString &walletID) { try { std::string result; std::string executableCommand = command.toStdString() + "\n"; // Catch the console-only-help command before RPC call is executed and // reply with help text as-if a RPC reply. if (executableCommand == "help-console\n") { Q_EMIT reply( RPCConsole::CMD_REPLY, QString(("\n" "This console accepts RPC commands using the standard " "syntax.\n" " example: getblockhash 0\n\n" "This console can also accept RPC commands using " "parenthesized syntax.\n" " example: getblockhash(0)\n\n" "Commands may be nested when specified with the " "parenthesized syntax.\n" " example: getblock(getblockhash(0) 1)\n\n" "A space or a comma can be used to delimit arguments " "for either syntax.\n" " example: getblockhash 0\n" " getblockhash,0\n\n" "Named results can be queried with a non-quoted key " "string in brackets.\n" " example: getblock(getblockhash(0) true)[tx]\n\n" "Results without keys can be queried using an integer " "in brackets.\n" " example: " "getblock(getblockhash(0),true)[tx][0]\n\n"))); return; } std::string wallet_id = walletID.toStdString(); if (!RPCConsole::RPCExecuteCommandLine( m_node, result, executableCommand, nullptr, &wallet_id)) { Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \"")); return; } Q_EMIT reply(RPCConsole::CMD_REPLY, QString::fromStdString(result)); } catch (UniValue &objError) { // Nice formatting for standard-format error try { int code = find_value(objError, "code").get_int(); std::string message = find_value(objError, "message").get_str(); Q_EMIT reply(RPCConsole::CMD_ERROR, QString::fromStdString(message) + " (code " + QString::number(code) + ")"); } catch (const std::runtime_error &) { // raised when converting to invalid type, i.e. missing code or // message. Show raw JSON object. Q_EMIT reply(RPCConsole::CMD_ERROR, QString::fromStdString(objError.write())); } } catch (const std::exception &e) { Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what())); } } RPCConsole::RPCConsole(interfaces::Node &node, const PlatformStyle *_platformStyle, QWidget *parent) : QWidget(parent), m_node(node), ui(new Ui::RPCConsole), clientModel(0), historyPtr(0), platformStyle(_platformStyle), peersTableContextMenu(0), banTableContextMenu(0), consoleFontSize(0) { ui->setupUi(this); QSettings settings; if (!restoreGeometry( settings.value("RPCConsoleWindowGeometry").toByteArray())) { // Restore failed (perhaps missing setting), center the window move(QApplication::desktop()->availableGeometry().center() - frameGeometry().center()); } ui->openDebugLogfileButton->setToolTip( ui->openDebugLogfileButton->toolTip().arg(tr(PACKAGE_NAME))); if (platformStyle->getImagesOnButtons()) { ui->openDebugLogfileButton->setIcon( platformStyle->SingleColorIcon(":/icons/export")); } ui->clearButton->setIcon(platformStyle->SingleColorIcon(":/icons/remove")); ui->fontBiggerButton->setIcon( platformStyle->SingleColorIcon(":/icons/fontbigger")); ui->fontSmallerButton->setIcon( platformStyle->SingleColorIcon(":/icons/fontsmaller")); // Install event filter for up and down arrow ui->lineEdit->installEventFilter(this); ui->messagesWidget->installEventFilter(this); connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear())); connect(ui->fontBiggerButton, SIGNAL(clicked()), this, SLOT(fontBigger())); connect(ui->fontSmallerButton, SIGNAL(clicked()), this, SLOT(fontSmaller())); connect(ui->btnClearTrafficGraph, SIGNAL(clicked()), ui->trafficGraph, SLOT(clear())); // disable the wallet selector by default ui->WalletSelector->setVisible(false); ui->WalletSelectorLabel->setVisible(false); // set library version labels #ifdef ENABLE_WALLET ui->berkeleyDBVersion->setText(DbEnv::version(0, 0, 0)); #else ui->label_berkeleyDBVersion->hide(); ui->berkeleyDBVersion->hide(); #endif // Register RPC timer interface rpcTimerInterface = new QtRPCTimerInterface(); // avoid accidentally overwriting an existing, non QTThread // based timer interface m_node.rpcSetTimerInterfaceIfUnset(rpcTimerInterface); setTrafficGraphRange(INITIAL_TRAFFIC_GRAPH_MINS); ui->detailWidget->hide(); ui->peerHeading->setText(tr("Select a peer to view detailed information.")); consoleFontSize = settings.value(fontSizeSettingsKey, QFontInfo(QFont()).pointSize()) .toInt(); clear(); } RPCConsole::~RPCConsole() { QSettings settings; settings.setValue("RPCConsoleWindowGeometry", saveGeometry()); m_node.rpcUnsetTimerInterface(rpcTimerInterface); delete rpcTimerInterface; delete ui; } bool RPCConsole::eventFilter(QObject *obj, QEvent *event) { // Special key handling if (event->type() == QEvent::KeyPress) { QKeyEvent *keyevt = static_cast(event); int key = keyevt->key(); Qt::KeyboardModifiers mod = keyevt->modifiers(); switch (key) { case Qt::Key_Up: if (obj == ui->lineEdit) { browseHistory(-1); return true; } break; case Qt::Key_Down: if (obj == ui->lineEdit) { browseHistory(1); return true; } break; case Qt::Key_PageUp: /* pass paging keys to messages widget */ case Qt::Key_PageDown: if (obj == ui->lineEdit) { QApplication::postEvent(ui->messagesWidget, new QKeyEvent(*keyevt)); return true; } break; case Qt::Key_Return: case Qt::Key_Enter: // forward these events to lineEdit if (obj == autoCompleter->popup()) { QApplication::postEvent(ui->lineEdit, new QKeyEvent(*keyevt)); return true; } break; default: // Typing in messages widget brings focus to line edit, and // redirects key there. Exclude most combinations and keys that // emit no text, except paste shortcuts. if (obj == ui->messagesWidget && ((!mod && !keyevt->text().isEmpty() && key != Qt::Key_Tab) || ((mod & Qt::ControlModifier) && key == Qt::Key_V) || ((mod & Qt::ShiftModifier) && key == Qt::Key_Insert))) { ui->lineEdit->setFocus(); QApplication::postEvent(ui->lineEdit, new QKeyEvent(*keyevt)); return true; } } } return QWidget::eventFilter(obj, event); } void RPCConsole::setClientModel(ClientModel *model) { clientModel = model; ui->trafficGraph->setClientModel(model); if (model && clientModel->getPeerTableModel() && clientModel->getBanTableModel()) { // Keep up to date with client setNumConnections(model->getNumConnections()); connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); interfaces::Node &node = clientModel->node(); setNumBlocks(node.getNumBlocks(), QDateTime::fromTime_t(node.getLastBlockTime()), node.getVerificationProgress(), false); connect(model, SIGNAL(numBlocksChanged(int, QDateTime, double, bool)), this, SLOT(setNumBlocks(int, QDateTime, double, bool))); updateNetworkState(); connect(model, SIGNAL(networkActiveChanged(bool)), this, SLOT(setNetworkActive(bool))); updateTrafficStats(node.getTotalBytesRecv(), node.getTotalBytesSent()); connect(model, SIGNAL(bytesChanged(quint64, quint64)), this, SLOT(updateTrafficStats(quint64, quint64))); connect(model, SIGNAL(mempoolSizeChanged(long, size_t)), this, SLOT(setMempoolSize(long, size_t))); // set up peer table ui->peerWidget->setModel(model->getPeerTableModel()); ui->peerWidget->verticalHeader()->hide(); ui->peerWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); ui->peerWidget->setSelectionBehavior(QAbstractItemView::SelectRows); ui->peerWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); ui->peerWidget->setContextMenuPolicy(Qt::CustomContextMenu); ui->peerWidget->setColumnWidth(PeerTableModel::Address, ADDRESS_COLUMN_WIDTH); ui->peerWidget->setColumnWidth(PeerTableModel::Subversion, SUBVERSION_COLUMN_WIDTH); ui->peerWidget->setColumnWidth(PeerTableModel::Ping, PING_COLUMN_WIDTH); ui->peerWidget->horizontalHeader()->setStretchLastSection(true); // create peer table context menu actions QAction *disconnectAction = new QAction(tr("&Disconnect"), this); QAction *banAction1h = new QAction(tr("Ban for") + " " + tr("1 &hour"), this); QAction *banAction24h = new QAction(tr("Ban for") + " " + tr("1 &day"), this); QAction *banAction7d = new QAction(tr("Ban for") + " " + tr("1 &week"), this); QAction *banAction365d = new QAction(tr("Ban for") + " " + tr("1 &year"), this); // create peer table context menu peersTableContextMenu = new QMenu(this); peersTableContextMenu->addAction(disconnectAction); peersTableContextMenu->addAction(banAction1h); peersTableContextMenu->addAction(banAction24h); peersTableContextMenu->addAction(banAction7d); peersTableContextMenu->addAction(banAction365d); // Add a signal mapping to allow dynamic context menu arguments. We need // to use int (instead of int64_t), because signal mapper only supports // int or objects, which is okay because max bantime (1 year) is < // int_max. QSignalMapper *signalMapper = new QSignalMapper(this); signalMapper->setMapping(banAction1h, 60 * 60); signalMapper->setMapping(banAction24h, 60 * 60 * 24); signalMapper->setMapping(banAction7d, 60 * 60 * 24 * 7); signalMapper->setMapping(banAction365d, 60 * 60 * 24 * 365); connect(banAction1h, SIGNAL(triggered()), signalMapper, SLOT(map())); connect(banAction24h, SIGNAL(triggered()), signalMapper, SLOT(map())); connect(banAction7d, SIGNAL(triggered()), signalMapper, SLOT(map())); connect(banAction365d, SIGNAL(triggered()), signalMapper, SLOT(map())); connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(banSelectedNode(int))); // peer table context menu signals connect(ui->peerWidget, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(showPeersTableContextMenu(const QPoint &))); connect(disconnectAction, SIGNAL(triggered()), this, SLOT(disconnectSelectedNode())); // peer table signal handling - update peer details when selecting new // node connect( ui->peerWidget->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), this, SLOT(peerSelected(const QItemSelection &, const QItemSelection &))); // peer table signal handling - update peer details when new nodes are // added to the model connect(model->getPeerTableModel(), SIGNAL(layoutChanged()), this, SLOT(peerLayoutChanged())); // peer table signal handling - cache selected node ids connect(model->getPeerTableModel(), SIGNAL(layoutAboutToBeChanged()), this, SLOT(peerLayoutAboutToChange())); // set up ban table ui->banlistWidget->setModel(model->getBanTableModel()); ui->banlistWidget->verticalHeader()->hide(); ui->banlistWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); ui->banlistWidget->setSelectionBehavior(QAbstractItemView::SelectRows); ui->banlistWidget->setSelectionMode(QAbstractItemView::SingleSelection); ui->banlistWidget->setContextMenuPolicy(Qt::CustomContextMenu); ui->banlistWidget->setColumnWidth(BanTableModel::Address, BANSUBNET_COLUMN_WIDTH); ui->banlistWidget->setColumnWidth(BanTableModel::Bantime, BANTIME_COLUMN_WIDTH); ui->banlistWidget->horizontalHeader()->setStretchLastSection(true); // create ban table context menu action QAction *unbanAction = new QAction(tr("&Unban"), this); // create ban table context menu banTableContextMenu = new QMenu(this); banTableContextMenu->addAction(unbanAction); // ban table context menu signals connect(ui->banlistWidget, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(showBanTableContextMenu(const QPoint &))); connect(unbanAction, SIGNAL(triggered()), this, SLOT(unbanSelectedNode())); // ban table signal handling - clear peer details when clicking a peer // in the ban table connect(ui->banlistWidget, SIGNAL(clicked(const QModelIndex &)), this, SLOT(clearSelectedNode())); // ban table signal handling - ensure ban table is shown or hidden (if // empty) connect(model->getBanTableModel(), SIGNAL(layoutChanged()), this, SLOT(showOrHideBanTableIfRequired())); showOrHideBanTableIfRequired(); // Provide initial values ui->clientVersion->setText(model->formatFullVersion()); ui->clientUserAgent->setText(model->formatSubVersion()); ui->dataDir->setText(model->dataDir()); ui->startupTime->setText(model->formatClientStartupTime()); ui->networkName->setText( QString::fromStdString(Params().NetworkIDString())); // Setup autocomplete and attach it QStringList wordList; std::vector commandList = m_node.listRpcCommands(); for (size_t i = 0; i < commandList.size(); ++i) { wordList << commandList[i].c_str(); wordList << ("help " + commandList[i]).c_str(); } wordList << "help-console"; wordList.sort(); autoCompleter = new QCompleter(wordList, this); autoCompleter->setModelSorting(QCompleter::CaseSensitivelySortedModel); ui->lineEdit->setCompleter(autoCompleter); autoCompleter->popup()->installEventFilter(this); // Start thread to execute RPC commands. startExecutor(); } if (!model) { // Client model is being set to 0, this means shutdown() is about to be // called. Make sure we clean up the executor thread Q_EMIT stopExecutor(); thread.wait(); } } #ifdef ENABLE_WALLET void RPCConsole::addWallet(WalletModel *const walletModel) { const QString name = walletModel->getWalletName(); // use name for text and internal data object (to allow to move to a wallet // id later) ui->WalletSelector->addItem(name, name); if (ui->WalletSelector->count() == 2 && !isVisible()) { // First wallet added, set to default so long as the window isn't // presently visible (and potentially in use) ui->WalletSelector->setCurrentIndex(1); } if (ui->WalletSelector->count() > 2) { ui->WalletSelector->setVisible(true); ui->WalletSelectorLabel->setVisible(true); } } #endif static QString categoryClass(int category) { switch (category) { case RPCConsole::CMD_REQUEST: return "cmd-request"; break; case RPCConsole::CMD_REPLY: return "cmd-reply"; break; case RPCConsole::CMD_ERROR: return "cmd-error"; break; default: return "misc"; } } void RPCConsole::fontBigger() { setFontSize(consoleFontSize + 1); } void RPCConsole::fontSmaller() { setFontSize(consoleFontSize - 1); } void RPCConsole::setFontSize(int newSize) { QSettings settings; - // don't allow a insane font size + // don't allow an insane font size if (newSize < FONT_RANGE.width() || newSize > FONT_RANGE.height()) return; // temp. store the console content QString str = ui->messagesWidget->toHtml(); // replace font tags size in current content str.replace(QString("font-size:%1pt").arg(consoleFontSize), QString("font-size:%1pt").arg(newSize)); // store the new font size consoleFontSize = newSize; settings.setValue(fontSizeSettingsKey, consoleFontSize); // clear console (reset icon sizes, default stylesheet) and re-add the // content float oldPosFactor = 1.0 / ui->messagesWidget->verticalScrollBar()->maximum() * ui->messagesWidget->verticalScrollBar()->value(); clear(false); ui->messagesWidget->setHtml(str); ui->messagesWidget->verticalScrollBar()->setValue( oldPosFactor * ui->messagesWidget->verticalScrollBar()->maximum()); } void RPCConsole::clear(bool clearHistory) { ui->messagesWidget->clear(); if (clearHistory) { history.clear(); historyPtr = 0; } ui->lineEdit->clear(); ui->lineEdit->setFocus(); // Add smoothly scaled icon images. // (when using width/height on an img, Qt uses nearest instead of linear // interpolation) for (int i = 0; ICON_MAPPING[i].url; ++i) { ui->messagesWidget->document()->addResource( QTextDocument::ImageResource, QUrl(ICON_MAPPING[i].url), platformStyle->SingleColorImage(ICON_MAPPING[i].source) .scaled(QSize(consoleFontSize * 2, consoleFontSize * 2), Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); } // Set default style sheet QFontInfo fixedFontInfo(GUIUtil::fixedPitchFont()); ui->messagesWidget->document()->setDefaultStyleSheet( QString("table { }" "td.time { color: #808080; font-size: %2; padding-top: 3px; } " "td.message { font-family: %1; font-size: %2; " "white-space:pre-wrap; } " "td.cmd-request { color: #006060; } " "td.cmd-error { color: red; } " ".secwarning { color: red; }" "b { color: #006060; } ") .arg(fixedFontInfo.family(), QString("%1pt").arg(consoleFontSize))); #ifdef Q_OS_MAC QString clsKey = "(⌘)-L"; #else QString clsKey = "Ctrl-L"; #endif message(CMD_REPLY, (tr("Welcome to the %1 RPC console.").arg(tr(PACKAGE_NAME)) + "
" + tr("Use up and down arrows to navigate history, and " "%1 to clear screen.") .arg("" + clsKey + "") + "
" + tr("Type %1 for an overview of available commands.") .arg("help") + "
" + tr("For more information on using this console type %1.") .arg("help-console") + "

" + tr("WARNING: Scammers have been active, telling users to type " "commands here, stealing their wallet contents. Do not use " - "this console without fully understanding the ramification " + "this console without fully understanding the ramifications " "of a command.") + "
"), true); } void RPCConsole::keyPressEvent(QKeyEvent *event) { if (windowType() != Qt::Widget && event->key() == Qt::Key_Escape) { close(); } } void RPCConsole::message(int category, const QString &message, bool html) { QTime time = QTime::currentTime(); QString timeString = time.toString(); QString out; out += ""; out += ""; out += "
" + timeString + ""; if (html) { out += message; } else { out += GUIUtil::HtmlEscape(message, false); } out += "
"; ui->messagesWidget->append(out); } void RPCConsole::updateNetworkState() { QString connections = QString::number(clientModel->getNumConnections()) + " ("; connections += tr("In:") + " " + QString::number(clientModel->getNumConnections(CONNECTIONS_IN)) + " / "; connections += tr("Out:") + " " + QString::number(clientModel->getNumConnections(CONNECTIONS_OUT)) + ")"; if (!clientModel->node().getNetworkActive()) { connections += " (" + tr("Network activity disabled") + ")"; } ui->numberOfConnections->setText(connections); } void RPCConsole::setNumConnections(int count) { if (!clientModel) { return; } updateNetworkState(); } void RPCConsole::setNetworkActive(bool networkActive) { updateNetworkState(); } void RPCConsole::setNumBlocks(int count, const QDateTime &blockDate, double nVerificationProgress, bool headers) { if (!headers) { ui->numberOfBlocks->setText(QString::number(count)); ui->lastBlockTime->setText(blockDate.toString()); } } void RPCConsole::setMempoolSize(long numberOfTxs, size_t dynUsage) { ui->mempoolNumberTxs->setText(QString::number(numberOfTxs)); if (dynUsage < 1000000) { ui->mempoolSize->setText(QString::number(dynUsage / 1000.0, 'f', 2) + " KB"); } else { ui->mempoolSize->setText(QString::number(dynUsage / 1000000.0, 'f', 2) + " MB"); } } void RPCConsole::on_lineEdit_returnPressed() { QString cmd = ui->lineEdit->text(); if (!cmd.isEmpty()) { std::string strFilteredCmd; try { std::string dummy; if (!RPCParseCommandLine(nullptr, dummy, cmd.toStdString(), false, &strFilteredCmd)) { // Failed to parse command, so we cannot even filter it for the // history throw std::runtime_error("Invalid command line"); } } catch (const std::exception &e) { QMessageBox::critical(this, "Error", QString("Error: ") + QString::fromStdString(e.what())); return; } ui->lineEdit->clear(); cmdBeforeBrowsing = QString(); QString walletID; #ifdef ENABLE_WALLET const int wallet_index = ui->WalletSelector->currentIndex(); if (wallet_index > 0) { walletID = (QString)ui->WalletSelector->itemData(wallet_index) .value(); } if (m_last_wallet_id != walletID) { if (walletID.isEmpty()) { message(CMD_REQUEST, tr("Executing command without any wallet")); } else { message( CMD_REQUEST, tr("Executing command using \"%1\" wallet").arg(walletID)); } m_last_wallet_id = walletID; } #endif message(CMD_REQUEST, QString::fromStdString(strFilteredCmd)); Q_EMIT cmdRequest(cmd, walletID); cmd = QString::fromStdString(strFilteredCmd); // Remove command, if already in history history.removeOne(cmd); // Append command to history history.append(cmd); // Enforce maximum history size while (history.size() > CONSOLE_HISTORY) history.removeFirst(); // Set pointer to end of history historyPtr = history.size(); // Scroll console view to end scrollToEnd(); } } void RPCConsole::browseHistory(int offset) { // store current text when start browsing through the history if (historyPtr == history.size()) { cmdBeforeBrowsing = ui->lineEdit->text(); } historyPtr += offset; if (historyPtr < 0) { historyPtr = 0; } if (historyPtr > history.size()) { historyPtr = history.size(); } QString cmd; if (historyPtr < history.size()) { cmd = history.at(historyPtr); } else if (!cmdBeforeBrowsing.isNull()) { cmd = cmdBeforeBrowsing; } ui->lineEdit->setText(cmd); } void RPCConsole::startExecutor() { RPCExecutor *executor = new RPCExecutor(m_node); executor->moveToThread(&thread); // Replies from executor object must go to this object connect(executor, SIGNAL(reply(int, QString)), this, SLOT(message(int, QString))); // Requests from this object must go to executor connect(this, SIGNAL(cmdRequest(QString, QString)), executor, SLOT(request(QString, QString))); // On stopExecutor signal // - quit the Qt event loop in the execution thread connect(this, SIGNAL(stopExecutor()), &thread, SLOT(quit())); // - queue executor for deletion (in execution thread) connect(&thread, SIGNAL(finished()), executor, SLOT(deleteLater()), Qt::DirectConnection); // Default implementation of QThread::run() simply spins up an event loop in // the thread, which is what we want. thread.start(); } void RPCConsole::on_tabWidget_currentChanged(int index) { if (ui->tabWidget->widget(index) == ui->tab_console) { ui->lineEdit->setFocus(); } else if (ui->tabWidget->widget(index) != ui->tab_peers) { clearSelectedNode(); } } void RPCConsole::on_openDebugLogfileButton_clicked() { GUIUtil::openDebugLogfile(); } void RPCConsole::scrollToEnd() { QScrollBar *scrollbar = ui->messagesWidget->verticalScrollBar(); scrollbar->setValue(scrollbar->maximum()); } void RPCConsole::on_sldGraphRange_valueChanged(int value) { const int multiplier = 5; // each position on the slider represents 5 min int mins = value * multiplier; setTrafficGraphRange(mins); } void RPCConsole::setTrafficGraphRange(int mins) { ui->trafficGraph->setGraphRangeMins(mins); ui->lblGraphRange->setText(GUIUtil::formatDurationStr(mins * 60)); } void RPCConsole::updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut) { ui->lblBytesIn->setText(GUIUtil::formatBytes(totalBytesIn)); ui->lblBytesOut->setText(GUIUtil::formatBytes(totalBytesOut)); } void RPCConsole::peerSelected(const QItemSelection &selected, const QItemSelection &deselected) { Q_UNUSED(deselected); if (!clientModel || !clientModel->getPeerTableModel() || selected.indexes().isEmpty()) return; const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats( selected.indexes().first().row()); if (stats) updateNodeDetail(stats); } void RPCConsole::peerLayoutAboutToChange() { QModelIndexList selected = ui->peerWidget->selectionModel()->selectedIndexes(); cachedNodeids.clear(); for (int i = 0; i < selected.size(); i++) { const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats( selected.at(i).row()); cachedNodeids.append(stats->nodeStats.nodeid); } } void RPCConsole::peerLayoutChanged() { if (!clientModel || !clientModel->getPeerTableModel()) { return; } const CNodeCombinedStats *stats = nullptr; bool fUnselect = false; bool fReselect = false; if (cachedNodeids.empty()) // no node selected yet return; // find the currently selected row int selectedRow = -1; QModelIndexList selectedModelIndex = ui->peerWidget->selectionModel()->selectedIndexes(); if (!selectedModelIndex.isEmpty()) { selectedRow = selectedModelIndex.first().row(); } // check if our detail node has a row in the table (it may not necessarily // be at selectedRow since its position can change after a layout change) int detailNodeRow = clientModel->getPeerTableModel()->getRowByNodeId(cachedNodeids.first()); if (detailNodeRow < 0) { // detail node disappeared from table (node disconnected) fUnselect = true; } else { if (detailNodeRow != selectedRow) { // detail node moved position fUnselect = true; fReselect = true; } // get fresh stats on the detail node. stats = clientModel->getPeerTableModel()->getNodeStats(detailNodeRow); } if (fUnselect && selectedRow >= 0) { clearSelectedNode(); } if (fReselect) { for (int i = 0; i < cachedNodeids.size(); i++) { ui->peerWidget->selectRow( clientModel->getPeerTableModel()->getRowByNodeId( cachedNodeids.at(i))); } } if (stats) updateNodeDetail(stats); } void RPCConsole::updateNodeDetail(const CNodeCombinedStats *stats) { // update the detail ui with latest node information QString peerAddrDetails(QString::fromStdString(stats->nodeStats.addrName) + " "); peerAddrDetails += tr("(node id: %1)").arg(QString::number(stats->nodeStats.nodeid)); if (!stats->nodeStats.addrLocal.empty()) { peerAddrDetails += "
" + tr("via %1").arg(QString::fromStdString( stats->nodeStats.addrLocal)); } ui->peerHeading->setText(peerAddrDetails); ui->peerServices->setText( GUIUtil::formatServicesStr(stats->nodeStats.nServices)); ui->peerLastSend->setText( stats->nodeStats.nLastSend ? GUIUtil::formatDurationStr(GetSystemTimeInSeconds() - stats->nodeStats.nLastSend) : tr("never")); ui->peerLastRecv->setText( stats->nodeStats.nLastRecv ? GUIUtil::formatDurationStr(GetSystemTimeInSeconds() - stats->nodeStats.nLastRecv) : tr("never")); ui->peerBytesSent->setText( GUIUtil::formatBytes(stats->nodeStats.nSendBytes)); ui->peerBytesRecv->setText( GUIUtil::formatBytes(stats->nodeStats.nRecvBytes)); ui->peerConnTime->setText(GUIUtil::formatDurationStr( GetSystemTimeInSeconds() - stats->nodeStats.nTimeConnected)); ui->peerPingTime->setText( GUIUtil::formatPingTime(stats->nodeStats.dPingTime)); ui->peerPingWait->setText( GUIUtil::formatPingTime(stats->nodeStats.dPingWait)); ui->peerMinPing->setText( GUIUtil::formatPingTime(stats->nodeStats.dMinPing)); ui->timeoffset->setText( GUIUtil::formatTimeOffset(stats->nodeStats.nTimeOffset)); ui->peerVersion->setText( QString("%1").arg(QString::number(stats->nodeStats.nVersion))); ui->peerSubversion->setText( QString::fromStdString(stats->nodeStats.cleanSubVer)); ui->peerDirection->setText(stats->nodeStats.fInbound ? tr("Inbound") : tr("Outbound")); ui->peerHeight->setText( QString("%1").arg(QString::number(stats->nodeStats.nStartingHeight))); ui->peerWhitelisted->setText(stats->nodeStats.fWhitelisted ? tr("Yes") : tr("No")); // This check fails for example if the lock was busy and // nodeStateStats couldn't be fetched. if (stats->fNodeStateStatsAvailable) { // Ban score is init to 0 ui->peerBanScore->setText( QString("%1").arg(stats->nodeStateStats.nMisbehavior)); // Sync height is init to -1 if (stats->nodeStateStats.nSyncHeight > -1) { ui->peerSyncHeight->setText( QString("%1").arg(stats->nodeStateStats.nSyncHeight)); } else { ui->peerSyncHeight->setText(tr("Unknown")); } // Common height is init to -1 if (stats->nodeStateStats.nCommonHeight > -1) { ui->peerCommonHeight->setText( QString("%1").arg(stats->nodeStateStats.nCommonHeight)); } else { ui->peerCommonHeight->setText(tr("Unknown")); } } ui->detailWidget->show(); } void RPCConsole::resizeEvent(QResizeEvent *event) { QWidget::resizeEvent(event); } void RPCConsole::showEvent(QShowEvent *event) { QWidget::showEvent(event); if (!clientModel || !clientModel->getPeerTableModel()) { return; } // start PeerTableModel auto refresh clientModel->getPeerTableModel()->startAutoRefresh(); } void RPCConsole::hideEvent(QHideEvent *event) { QWidget::hideEvent(event); if (!clientModel || !clientModel->getPeerTableModel()) { return; } // stop PeerTableModel auto refresh clientModel->getPeerTableModel()->stopAutoRefresh(); } void RPCConsole::showPeersTableContextMenu(const QPoint &point) { QModelIndex index = ui->peerWidget->indexAt(point); if (index.isValid()) peersTableContextMenu->exec(QCursor::pos()); } void RPCConsole::showBanTableContextMenu(const QPoint &point) { QModelIndex index = ui->banlistWidget->indexAt(point); if (index.isValid()) banTableContextMenu->exec(QCursor::pos()); } void RPCConsole::disconnectSelectedNode() { // Get selected peer addresses QList nodes = GUIUtil::getEntryData(ui->peerWidget, PeerTableModel::NetNodeId); for (int i = 0; i < nodes.count(); i++) { // Get currently selected peer address NodeId id = nodes.at(i).data().toLongLong(); // Find the node, disconnect it and clear the selected node if (m_node.disconnect(id)) { clearSelectedNode(); } } } void RPCConsole::banSelectedNode(int bantime) { if (!clientModel) { return; } // Get selected peer addresses QList nodes = GUIUtil::getEntryData(ui->peerWidget, PeerTableModel::NetNodeId); for (int i = 0; i < nodes.count(); i++) { // Get currently selected peer address NodeId id = nodes.at(i).data().toLongLong(); // Get currently selected peer address int detailNodeRow = clientModel->getPeerTableModel()->getRowByNodeId(id); if (detailNodeRow < 0) { return; } // Find possible nodes, ban it and clear the selected node const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(detailNodeRow); if (stats) { m_node.ban(stats->nodeStats.addr, BanReasonManuallyAdded, bantime); } } clearSelectedNode(); clientModel->getBanTableModel()->refresh(); } void RPCConsole::unbanSelectedNode() { if (!clientModel) { return; } // Get selected ban addresses QList nodes = GUIUtil::getEntryData(ui->banlistWidget, BanTableModel::Address); for (int i = 0; i < nodes.count(); i++) { // Get currently selected ban address QString strNode = nodes.at(i).data().toString(); CSubNet possibleSubnet; LookupSubNet(strNode.toStdString().c_str(), possibleSubnet); if (possibleSubnet.IsValid() && m_node.unban(possibleSubnet)) { clientModel->getBanTableModel()->refresh(); } } } void RPCConsole::clearSelectedNode() { ui->peerWidget->selectionModel()->clearSelection(); cachedNodeids.clear(); ui->detailWidget->hide(); ui->peerHeading->setText(tr("Select a peer to view detailed information.")); } void RPCConsole::showOrHideBanTableIfRequired() { if (!clientModel) { return; } bool visible = clientModel->getBanTableModel()->shouldShow(); ui->banlistWidget->setVisible(visible); ui->banHeading->setVisible(visible); } void RPCConsole::setTabFocus(enum TabTypes tabType) { ui->tabWidget->setCurrentIndex(tabType); } diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 5973b6a308..09fa008cd6 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -1,477 +1,477 @@ // Copyright (c) 2011-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include #include #include #include #include #include #include #include #include #include #include // for GetBoolArg #include #include #include #include #include #include WalletModel::WalletModel(std::unique_ptr wallet, interfaces::Node &node, const PlatformStyle *platformStyle, OptionsModel *_optionsModel, QObject *parent) : QObject(parent), m_wallet(std::move(wallet)), m_node(node), optionsModel(_optionsModel), addressTableModel(0), transactionTableModel(0), recentRequestsTableModel(0), cachedEncryptionStatus(Unencrypted), cachedNumBlocks(0) { fHaveWatchOnly = m_wallet->haveWatchOnly(); fForceCheckBalanceChanged = false; addressTableModel = new AddressTableModel(this); transactionTableModel = new TransactionTableModel(platformStyle, this); recentRequestsTableModel = new RecentRequestsTableModel(this); // This timer will be fired repeatedly to update the balance pollTimer = new QTimer(this); connect(pollTimer, SIGNAL(timeout()), this, SLOT(pollBalanceChanged())); pollTimer->start(MODEL_UPDATE_DELAY); subscribeToCoreSignals(); } WalletModel::~WalletModel() { unsubscribeFromCoreSignals(); } void WalletModel::updateStatus() { EncryptionStatus newEncryptionStatus = getEncryptionStatus(); if (cachedEncryptionStatus != newEncryptionStatus) { Q_EMIT encryptionStatusChanged(); } } void WalletModel::pollBalanceChanged() { // Try to get balances and return early if locks can't be acquired. This // avoids the GUI from getting stuck on periodical polls if the core is // holding the locks for a longer time - for example, during a wallet // rescan. interfaces::WalletBalances new_balances; int numBlocks = -1; if (!m_wallet->tryGetBalances(new_balances, numBlocks)) { return; } if (fForceCheckBalanceChanged || m_node.getNumBlocks() != cachedNumBlocks) { fForceCheckBalanceChanged = false; // Balance and number of transactions might have changed cachedNumBlocks = m_node.getNumBlocks(); checkBalanceChanged(new_balances); if (transactionTableModel) { transactionTableModel->updateConfirmations(); } } } void WalletModel::checkBalanceChanged( const interfaces::WalletBalances &new_balances) { if (new_balances.balanceChanged(m_cached_balances)) { m_cached_balances = new_balances; Q_EMIT balanceChanged(new_balances); } } void WalletModel::updateTransaction() { // Balance and number of transactions might have changed fForceCheckBalanceChanged = true; } void WalletModel::updateAddressBook(const QString &address, const QString &label, bool isMine, const QString &purpose, int status) { if (addressTableModel) { addressTableModel->updateEntry(address, label, isMine, purpose, status); } } void WalletModel::updateWatchOnlyFlag(bool fHaveWatchonly) { fHaveWatchOnly = fHaveWatchonly; Q_EMIT notifyWatchonlyChanged(fHaveWatchonly); } bool WalletModel::validateAddress(const QString &address) { return IsValidDestinationString(address.toStdString(), getChainParams()); } WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransaction &transaction, const CCoinControl &coinControl) { Amount total = Amount::zero(); bool fSubtractFeeFromAmount = false; QList recipients = transaction.getRecipients(); std::vector vecSend; if (recipients.empty()) { return OK; } // Used to detect duplicates QSet setAddress; int nAddresses = 0; // Pre-check input data for validity for (const SendCoinsRecipient &rcp : recipients) { if (rcp.fSubtractFeeFromAmount) fSubtractFeeFromAmount = true; // PaymentRequest... if (rcp.paymentRequest.IsInitialized()) { Amount subtotal = Amount::zero(); const payments::PaymentDetails &details = rcp.paymentRequest.getDetails(); for (int i = 0; i < details.outputs_size(); i++) { const payments::Output &out = details.outputs(i); if (out.amount() <= 0) { continue; } subtotal += int64_t(out.amount()) * SATOSHI; const uint8_t *scriptStr = (const uint8_t *)out.script().data(); CScript scriptPubKey(scriptStr, scriptStr + out.script().size()); Amount nAmount = int64_t(out.amount()) * SATOSHI; CRecipient recipient = {scriptPubKey, nAmount, rcp.fSubtractFeeFromAmount}; vecSend.push_back(recipient); } if (subtotal <= Amount::zero()) { return InvalidAmount; } total += subtotal; } else { // User-entered bitcoin address / amount: if (!validateAddress(rcp.address)) { return InvalidAddress; } if (rcp.amount <= Amount::zero()) { return InvalidAmount; } setAddress.insert(rcp.address); ++nAddresses; CScript scriptPubKey = GetScriptForDestination( DecodeDestination(rcp.address.toStdString(), getChainParams())); CRecipient recipient = {scriptPubKey, Amount(rcp.amount), rcp.fSubtractFeeFromAmount}; vecSend.push_back(recipient); total += rcp.amount; } } if (setAddress.size() != nAddresses) { return DuplicateAddress; } Amount nBalance = m_wallet->getAvailableBalance(coinControl); if (total > nBalance) { return AmountExceedsBalance; } Amount nFeeRequired = Amount::zero(); int nChangePosRet = -1; std::string strFailReason; auto &newTx = transaction.getWtx(); newTx = m_wallet->createTransaction(vecSend, coinControl, true /* sign */, nChangePosRet, nFeeRequired, strFailReason); transaction.setTransactionFee(nFeeRequired); if (fSubtractFeeFromAmount && newTx) { transaction.reassignAmounts(nChangePosRet); } if (!newTx) { if (!fSubtractFeeFromAmount && (total + nFeeRequired) > nBalance) { return SendCoinsReturn(AmountWithFeeExceedsBalance); } Q_EMIT message(tr("Send Coins"), QString::fromStdString(strFailReason), CClientUIInterface::MSG_ERROR); return TransactionCreationFailed; } // reject absurdly high fee. (This can never happen because the // wallet caps the fee at maxTxFee. This merely serves as a // belt-and-suspenders check) if (nFeeRequired > m_node.getMaxTxFee()) { return AbsurdFee; } return SendCoinsReturn(OK); } WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &transaction) { /* store serialized transaction */ QByteArray transaction_array; std::vector> vOrderForm; for (const SendCoinsRecipient &rcp : transaction.getRecipients()) { if (rcp.paymentRequest.IsInitialized()) { // Make sure any payment requests involved are still valid. if (PaymentServer::verifyExpired(rcp.paymentRequest.getDetails())) { return PaymentRequestExpired; } // Store PaymentRequests in wtx.vOrderForm in wallet. std::string value; rcp.paymentRequest.SerializeToString(&value); vOrderForm.emplace_back("PaymentRequest", std::move(value)); } else if (!rcp.message.isEmpty()) { // Message from normal bitcoincash:URI // (bitcoincash:123...?message=example) vOrderForm.emplace_back("Message", rcp.message.toStdString()); } } auto &newTx = transaction.getWtx(); std::string rejectReason; if (!newTx->commit({} /* mapValue */, std::move(vOrderForm), {} /* fromAccount */, rejectReason)) { return SendCoinsReturn(TransactionCommitFailed, QString::fromStdString(rejectReason)); } CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); ssTx << newTx->get(); transaction_array.append(&(ssTx[0]), ssTx.size()); - // Add addresses / update labels that we've sent to to the address book, and + // Add addresses / update labels that we've sent to the address book, and // emit coinsSent signal for each recipient for (const SendCoinsRecipient &rcp : transaction.getRecipients()) { // Don't touch the address book when we have a payment request if (!rcp.paymentRequest.IsInitialized()) { std::string strAddress = rcp.address.toStdString(); CTxDestination dest = DecodeDestination(strAddress, getChainParams()); std::string strLabel = rcp.label.toStdString(); // Check if we have a new address or an updated label std::string name; if (!m_wallet->getAddress(dest, &name)) { m_wallet->setAddressBook(dest, strLabel, "send"); } else if (name != strLabel) { // "" means don't change purpose m_wallet->setAddressBook(dest, strLabel, ""); } } Q_EMIT coinsSent(this, rcp, transaction_array); } // update balance immediately, otherwise there could be a short noticeable // delay until pollBalanceChanged hits checkBalanceChanged(m_wallet->getBalances()); return SendCoinsReturn(OK); } OptionsModel *WalletModel::getOptionsModel() { return optionsModel; } AddressTableModel *WalletModel::getAddressTableModel() { return addressTableModel; } TransactionTableModel *WalletModel::getTransactionTableModel() { return transactionTableModel; } RecentRequestsTableModel *WalletModel::getRecentRequestsTableModel() { return recentRequestsTableModel; } WalletModel::EncryptionStatus WalletModel::getEncryptionStatus() const { if (!m_wallet->isCrypted()) { return Unencrypted; } else if (m_wallet->isLocked()) { return Locked; } else { return Unlocked; } } bool WalletModel::setWalletEncrypted(bool encrypted, const SecureString &passphrase) { if (encrypted) { // Encrypt return m_wallet->encryptWallet(passphrase); } else { // Decrypt -- TODO; not supported yet return false; } } bool WalletModel::setWalletLocked(bool locked, const SecureString &passPhrase) { if (locked) { // Lock return m_wallet->lock(); } else { // Unlock return m_wallet->unlock(passPhrase); } } bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureString &newPass) { // Make sure wallet is locked before attempting pass change m_wallet->lock(); return m_wallet->changeWalletPassphrase(oldPass, newPass); } // Handlers for core signals static void NotifyKeyStoreStatusChanged(WalletModel *walletmodel) { qDebug() << "NotifyKeyStoreStatusChanged"; QMetaObject::invokeMethod(walletmodel, "updateStatus", Qt::QueuedConnection); } static void NotifyAddressBookChanged(WalletModel *walletmodel, const CTxDestination &address, const std::string &label, bool isMine, const std::string &purpose, ChangeType status) { QString strAddress = QString::fromStdString(EncodeDestination(address)); QString strLabel = QString::fromStdString(label); QString strPurpose = QString::fromStdString(purpose); qDebug() << "NotifyAddressBookChanged: " + strAddress + " " + strLabel + " isMine=" + QString::number(isMine) + " purpose=" + strPurpose + " status=" + QString::number(status); QMetaObject::invokeMethod(walletmodel, "updateAddressBook", Qt::QueuedConnection, Q_ARG(QString, strAddress), Q_ARG(QString, strLabel), Q_ARG(bool, isMine), Q_ARG(QString, strPurpose), Q_ARG(int, status)); } static void NotifyTransactionChanged(WalletModel *walletmodel, const TxId &hash, ChangeType status) { Q_UNUSED(hash); Q_UNUSED(status); QMetaObject::invokeMethod(walletmodel, "updateTransaction", Qt::QueuedConnection); } static void ShowProgress(WalletModel *walletmodel, const std::string &title, int nProgress) { // emits signal "showProgress" QMetaObject::invokeMethod(walletmodel, "showProgress", Qt::QueuedConnection, Q_ARG(QString, QString::fromStdString(title)), Q_ARG(int, nProgress)); } static void NotifyWatchonlyChanged(WalletModel *walletmodel, bool fHaveWatchonly) { QMetaObject::invokeMethod(walletmodel, "updateWatchOnlyFlag", Qt::QueuedConnection, Q_ARG(bool, fHaveWatchonly)); } void WalletModel::subscribeToCoreSignals() { // Connect signals to wallet m_handler_status_changed = m_wallet->handleStatusChanged( boost::bind(&NotifyKeyStoreStatusChanged, this)); m_handler_address_book_changed = m_wallet->handleAddressBookChanged( boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5)); m_handler_transaction_changed = m_wallet->handleTransactionChanged( boost::bind(NotifyTransactionChanged, this, _1, _2)); m_handler_show_progress = m_wallet->handleShowProgress(boost::bind(ShowProgress, this, _1, _2)); m_handler_watch_only_changed = m_wallet->handleWatchOnlyChanged( boost::bind(NotifyWatchonlyChanged, this, _1)); } void WalletModel::unsubscribeFromCoreSignals() { // Disconnect signals from wallet m_handler_status_changed->disconnect(); m_handler_address_book_changed->disconnect(); m_handler_transaction_changed->disconnect(); m_handler_show_progress->disconnect(); m_handler_watch_only_changed->disconnect(); } // WalletModel::UnlockContext implementation WalletModel::UnlockContext WalletModel::requestUnlock() { bool was_locked = getEncryptionStatus() == Locked; if (was_locked) { // Request UI to unlock wallet Q_EMIT requireUnlock(); } // If wallet is still locked, unlock was failed or cancelled, mark context // as invalid bool valid = getEncryptionStatus() != Locked; return UnlockContext(this, valid, was_locked); } WalletModel::UnlockContext::UnlockContext(WalletModel *_wallet, bool _valid, bool _relock) : wallet(_wallet), valid(_valid), relock(_relock) {} WalletModel::UnlockContext::~UnlockContext() { if (valid && relock) { wallet->setWalletLocked(true); } } void WalletModel::UnlockContext::CopyFrom(const UnlockContext &rhs) { // Transfer context; old object no longer relocks wallet *this = rhs; rhs.relock = false; } void WalletModel::loadReceiveRequests( std::vector &vReceiveRequests) { // receive request vReceiveRequests = m_wallet->getDestValues("rr"); } bool WalletModel::saveReceiveRequest(const std::string &sAddress, const int64_t nId, const std::string &sRequest) { CTxDestination dest = DecodeDestination(sAddress, getChainParams()); std::stringstream ss; ss << nId; // "rr" prefix = "receive request" in destdata std::string key = "rr" + ss.str(); return sRequest.empty() ? m_wallet->eraseDestData(dest, key) : m_wallet->addDestData(dest, key, sRequest); } bool WalletModel::isWalletEnabled() { return !gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET); } QString WalletModel::getWalletName() const { return QString::fromStdString(m_wallet->getWalletName()); } bool WalletModel::isMultiwallet() { return m_node.getWallets().size() > 1; } const CChainParams &WalletModel::getChainParams() const { return GetConfig().GetChainParams(); } diff --git a/src/rest.cpp b/src/rest.cpp index 64f8b3dbb9..e9ee1e1c48 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -1,705 +1,705 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Allow a max of 15 outpoints to be queried at once. static const size_t MAX_GETUTXOS_OUTPOINTS = 15; enum class RetFormat { UNDEF, BINARY, HEX, JSON, }; static const struct { enum RetFormat rf; const char *name; } rf_names[] = { {RetFormat::UNDEF, ""}, {RetFormat::BINARY, "bin"}, {RetFormat::HEX, "hex"}, {RetFormat::JSON, "json"}, }; struct CCoin { uint32_t nHeight; CTxOut out; CCoin() : nHeight(0) {} explicit CCoin(Coin in) : nHeight(in.GetHeight()), out(std::move(in.GetTxOut())) {} ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream &s, Operation ser_action) { uint32_t nTxVerDummy = 0; READWRITE(nTxVerDummy); READWRITE(nHeight); READWRITE(out); } }; static bool RESTERR(HTTPRequest *req, enum HTTPStatusCode status, std::string message) { req->WriteHeader("Content-Type", "text/plain"); req->WriteReply(status, message + "\r\n"); return false; } static enum RetFormat ParseDataFormat(std::string ¶m, const std::string &strReq) { const std::string::size_type pos = strReq.rfind('.'); if (pos == std::string::npos) { param = strReq; return rf_names[0].rf; } param = strReq.substr(0, pos); const std::string suff(strReq, pos + 1); for (size_t i = 0; i < ARRAYLEN(rf_names); i++) { if (suff == rf_names[i].name) { return rf_names[i].rf; } } /* If no suffix is found, return original string. */ param = strReq; return rf_names[0].rf; } static std::string AvailableDataFormatsString() { std::string formats; for (size_t i = 0; i < ARRAYLEN(rf_names); i++) { if (strlen(rf_names[i].name) > 0) { formats.append("."); formats.append(rf_names[i].name); formats.append(", "); } } if (formats.length() > 0) { return formats.substr(0, formats.length() - 2); } return formats; } static bool ParseHashStr(const std::string &strReq, uint256 &v) { if (!IsHex(strReq) || (strReq.size() != 64)) { return false; } v.SetHex(strReq); return true; } static bool CheckWarmup(HTTPRequest *req) { std::string statusmessage; if (RPCIsInWarmup(&statusmessage)) { return RESTERR(req, HTTP_SERVICE_UNAVAILABLE, "Service temporarily unavailable: " + statusmessage); } return true; } static bool rest_headers(Config &config, HTTPRequest *req, const std::string &strURIPart) { if (!CheckWarmup(req)) { return false; } std::string param; const RetFormat rf = ParseDataFormat(param, strURIPart); std::vector path; boost::split(path, param, boost::is_any_of("/")); if (path.size() != 2) { return RESTERR(req, HTTP_BAD_REQUEST, "No header count specified. Use " "/rest/headers//.."); } long count = strtol(path[0].c_str(), nullptr, 10); if (count < 1 || count > 2000) { return RESTERR(req, HTTP_BAD_REQUEST, "Header count out of range: " + path[0]); } std::string hashStr = path[1]; uint256 hash; if (!ParseHashStr(hashStr, hash)) { return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + hashStr); } const CBlockIndex *tip = nullptr; std::vector headers; headers.reserve(count); { LOCK(cs_main); tip = chainActive.Tip(); const CBlockIndex *pindex = LookupBlockIndex(hash); while (pindex != nullptr && chainActive.Contains(pindex)) { headers.push_back(pindex); if (headers.size() == size_t(count)) { break; } pindex = chainActive.Next(pindex); } } CDataStream ssHeader(SER_NETWORK, PROTOCOL_VERSION); for (const CBlockIndex *pindex : headers) { ssHeader << pindex->GetBlockHeader(); } switch (rf) { case RetFormat::BINARY: { std::string binaryHeader = ssHeader.str(); req->WriteHeader("Content-Type", "application/octet-stream"); req->WriteReply(HTTP_OK, binaryHeader); return true; } case RetFormat::HEX: { std::string strHex = HexStr(ssHeader.begin(), ssHeader.end()) + "\n"; req->WriteHeader("Content-Type", "text/plain"); req->WriteReply(HTTP_OK, strHex); return true; } case RetFormat::JSON: { UniValue jsonHeaders(UniValue::VARR); for (const CBlockIndex *pindex : headers) { jsonHeaders.push_back(blockheaderToJSON(tip, pindex)); } std::string strJSON = jsonHeaders.write() + "\n"; req->WriteHeader("Content-Type", "application/json"); req->WriteReply(HTTP_OK, strJSON); return true; } default: { return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: .bin, .hex)"); } } // not reached // continue to process further HTTP reqs on this cxn return true; } static bool rest_block(const Config &config, HTTPRequest *req, const std::string &strURIPart, bool showTxDetails) { if (!CheckWarmup(req)) { return false; } std::string hashStr; const RetFormat rf = ParseDataFormat(hashStr, strURIPart); uint256 hash; if (!ParseHashStr(hashStr, hash)) { return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + hashStr); } CBlock block; CBlockIndex *pblockindex = nullptr; CBlockIndex *tip = nullptr; { LOCK(cs_main); tip = chainActive.Tip(); pblockindex = LookupBlockIndex(hash); if (!pblockindex) { return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found"); } if (fHavePruned && !pblockindex->nStatus.hasData() && pblockindex->nTx > 0) { return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not available (pruned data)"); } if (!ReadBlockFromDisk(block, pblockindex, config)) { return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found"); } } CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags()); ssBlock << block; switch (rf) { case RetFormat::BINARY: { std::string binaryBlock = ssBlock.str(); req->WriteHeader("Content-Type", "application/octet-stream"); req->WriteReply(HTTP_OK, binaryBlock); return true; } case RetFormat::HEX: { std::string strHex = HexStr(ssBlock.begin(), ssBlock.end()) + "\n"; req->WriteHeader("Content-Type", "text/plain"); req->WriteReply(HTTP_OK, strHex); return true; } case RetFormat::JSON: { UniValue objBlock = blockToJSON(block, tip, pblockindex, showTxDetails); std::string strJSON = objBlock.write() + "\n"; req->WriteHeader("Content-Type", "application/json"); req->WriteReply(HTTP_OK, strJSON); return true; } default: { return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: " + AvailableDataFormatsString() + ")"); } } // not reached // continue to process further HTTP reqs on this cxn return true; } static bool rest_block_extended(Config &config, HTTPRequest *req, const std::string &strURIPart) { return rest_block(config, req, strURIPart, true); } static bool rest_block_notxdetails(Config &config, HTTPRequest *req, const std::string &strURIPart) { return rest_block(config, req, strURIPart, false); } static bool rest_chaininfo(Config &config, HTTPRequest *req, const std::string &strURIPart) { if (!CheckWarmup(req)) { return false; } std::string param; const RetFormat rf = ParseDataFormat(param, strURIPart); switch (rf) { case RetFormat::JSON: { JSONRPCRequest jsonRequest; jsonRequest.params = UniValue(UniValue::VARR); UniValue chainInfoObject = getblockchaininfo(config, jsonRequest); std::string strJSON = chainInfoObject.write() + "\n"; req->WriteHeader("Content-Type", "application/json"); req->WriteReply(HTTP_OK, strJSON); return true; } default: { return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: json)"); } } // not reached // continue to process further HTTP reqs on this cxn return true; } static bool rest_mempool_info(Config &config, HTTPRequest *req, const std::string &strURIPart) { if (!CheckWarmup(req)) { return false; } std::string param; const RetFormat rf = ParseDataFormat(param, strURIPart); switch (rf) { case RetFormat::JSON: { UniValue mempoolInfoObject = mempoolInfoToJSON(); std::string strJSON = mempoolInfoObject.write() + "\n"; req->WriteHeader("Content-Type", "application/json"); req->WriteReply(HTTP_OK, strJSON); return true; } default: { return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: json)"); } } // not reached // continue to process further HTTP reqs on this cxn return true; } static bool rest_mempool_contents(Config &config, HTTPRequest *req, const std::string &strURIPart) { if (!CheckWarmup(req)) { return false; } std::string param; const RetFormat rf = ParseDataFormat(param, strURIPart); switch (rf) { case RetFormat::JSON: { UniValue mempoolObject = mempoolToJSON(true); std::string strJSON = mempoolObject.write() + "\n"; req->WriteHeader("Content-Type", "application/json"); req->WriteReply(HTTP_OK, strJSON); return true; } default: { return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: json)"); } } // not reached // continue to process further HTTP reqs on this cxn return true; } static bool rest_tx(Config &config, HTTPRequest *req, const std::string &strURIPart) { if (!CheckWarmup(req)) { return false; } std::string hashStr; const RetFormat rf = ParseDataFormat(hashStr, strURIPart); uint256 hash; if (!ParseHashStr(hashStr, hash)) { return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + hashStr); } const TxId txid(hash); if (g_txindex) { g_txindex->BlockUntilSyncedToCurrentChain(); } CTransactionRef tx; uint256 hashBlock = uint256(); if (!GetTransaction(config, txid, tx, hashBlock, true)) { return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found"); } CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags()); ssTx << tx; switch (rf) { case RetFormat::BINARY: { std::string binaryTx = ssTx.str(); req->WriteHeader("Content-Type", "application/octet-stream"); req->WriteReply(HTTP_OK, binaryTx); return true; } case RetFormat::HEX: { std::string strHex = HexStr(ssTx.begin(), ssTx.end()) + "\n"; req->WriteHeader("Content-Type", "text/plain"); req->WriteReply(HTTP_OK, strHex); return true; } case RetFormat::JSON: { UniValue objTx(UniValue::VOBJ); TxToUniv(*tx, hashBlock, objTx); std::string strJSON = objTx.write() + "\n"; req->WriteHeader("Content-Type", "application/json"); req->WriteReply(HTTP_OK, strJSON); return true; } default: { return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: " + AvailableDataFormatsString() + ")"); } } // not reached // continue to process further HTTP reqs on this cxn return true; } static bool rest_getutxos(Config &config, HTTPRequest *req, const std::string &strURIPart) { if (!CheckWarmup(req)) { return false; } std::string param; const RetFormat rf = ParseDataFormat(param, strURIPart); std::vector uriParts; if (param.length() > 1) { std::string strUriParams = param.substr(1); boost::split(uriParts, strUriParams, boost::is_any_of("/")); } - // throw exception in case of a empty request + // throw exception in case of an empty request std::string strRequestMutable = req->ReadBody(); if (strRequestMutable.length() == 0 && uriParts.size() == 0) { return RESTERR(req, HTTP_BAD_REQUEST, "Error: empty request"); } bool fInputParsed = false; bool fCheckMemPool = false; std::vector vOutPoints; // parse/deserialize input // input-format = output-format, rest/getutxos/bin requires binary input, // gives binary output, ... if (uriParts.size() > 0) { // inputs is sent over URI scheme // (/rest/getutxos/checkmempool/txid1-n/txid2-n/...) if (uriParts[0] == "checkmempool") { fCheckMemPool = true; } for (size_t i = (fCheckMemPool) ? 1 : 0; i < uriParts.size(); i++) { uint256 txid; int32_t nOutput; std::string strTxid = uriParts[i].substr(0, uriParts[i].find("-")); std::string strOutput = uriParts[i].substr(uriParts[i].find("-") + 1); if (!ParseInt32(strOutput, &nOutput) || !IsHex(strTxid)) { return RESTERR(req, HTTP_BAD_REQUEST, "Parse error"); } txid.SetHex(strTxid); vOutPoints.push_back(COutPoint(txid, (uint32_t)nOutput)); } if (vOutPoints.size() > 0) { fInputParsed = true; } else { return RESTERR(req, HTTP_BAD_REQUEST, "Error: empty request"); } } switch (rf) { case RetFormat::HEX: { // convert hex to bin, continue then with bin part std::vector strRequestV = ParseHex(strRequestMutable); strRequestMutable.assign(strRequestV.begin(), strRequestV.end()); } // FALLTHROUGH case RetFormat::BINARY: { try { // deserialize only if user sent a request if (strRequestMutable.size() > 0) { // don't allow sending input over URI and HTTP RAW DATA if (fInputParsed) { return RESTERR(req, HTTP_BAD_REQUEST, "Combination of URI scheme inputs and " "raw post data is not allowed"); } CDataStream oss(SER_NETWORK, PROTOCOL_VERSION); oss << strRequestMutable; oss >> fCheckMemPool; oss >> vOutPoints; } } catch (const std::ios_base::failure &e) { // abort in case of unreadable binary data return RESTERR(req, HTTP_BAD_REQUEST, "Parse error"); } break; } case RetFormat::JSON: { if (!fInputParsed) { return RESTERR(req, HTTP_BAD_REQUEST, "Error: empty request"); } break; } default: { return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: " + AvailableDataFormatsString() + ")"); } } // limit max outpoints if (vOutPoints.size() > MAX_GETUTXOS_OUTPOINTS) { return RESTERR( req, HTTP_BAD_REQUEST, strprintf("Error: max outpoints exceeded (max: %d, tried: %d)", MAX_GETUTXOS_OUTPOINTS, vOutPoints.size())); } // check spentness and form a bitmap (as well as a JSON capable // human-readable string representation) std::vector bitmap; std::vector outs; std::string bitmapStringRepresentation; std::vector hits; bitmap.resize((vOutPoints.size() + 7) / 8); { LOCK2(cs_main, g_mempool.cs); CCoinsView viewDummy; CCoinsViewCache view(&viewDummy); CCoinsViewCache &viewChain = *pcoinsTip; CCoinsViewMemPool viewMempool(&viewChain, g_mempool); if (fCheckMemPool) { // switch cache backend to db+mempool in case user likes to query // mempool. view.SetBackend(viewMempool); } for (size_t i = 0; i < vOutPoints.size(); i++) { Coin coin; bool hit = false; if (view.GetCoin(vOutPoints[i], coin) && !g_mempool.isSpent(vOutPoints[i])) { hit = true; outs.emplace_back(std::move(coin)); } hits.push_back(hit); // form a binary string representation (human-readable for json // output) bitmapStringRepresentation.append(hit ? "1" : "0"); bitmap[i / 8] |= ((uint8_t)hit) << (i % 8); } } switch (rf) { case RetFormat::BINARY: { // serialize data // use exact same output as mentioned in Bip64 CDataStream ssGetUTXOResponse(SER_NETWORK, PROTOCOL_VERSION); ssGetUTXOResponse << chainActive.Height() << chainActive.Tip()->GetBlockHash() << bitmap << outs; std::string ssGetUTXOResponseString = ssGetUTXOResponse.str(); req->WriteHeader("Content-Type", "application/octet-stream"); req->WriteReply(HTTP_OK, ssGetUTXOResponseString); return true; } case RetFormat::HEX: { CDataStream ssGetUTXOResponse(SER_NETWORK, PROTOCOL_VERSION); ssGetUTXOResponse << chainActive.Height() << chainActive.Tip()->GetBlockHash() << bitmap << outs; std::string strHex = HexStr(ssGetUTXOResponse.begin(), ssGetUTXOResponse.end()) + "\n"; req->WriteHeader("Content-Type", "text/plain"); req->WriteReply(HTTP_OK, strHex); return true; } case RetFormat::JSON: { UniValue objGetUTXOResponse(UniValue::VOBJ); // pack in some essentials // use more or less the same output as mentioned in Bip64 objGetUTXOResponse.pushKV("chainHeight", chainActive.Height()); objGetUTXOResponse.pushKV( "chaintipHash", chainActive.Tip()->GetBlockHash().GetHex()); objGetUTXOResponse.pushKV("bitmap", bitmapStringRepresentation); UniValue utxos(UniValue::VARR); for (const CCoin &coin : outs) { UniValue utxo(UniValue::VOBJ); utxo.pushKV("height", int32_t(coin.nHeight)); utxo.pushKV("value", ValueFromAmount(coin.out.nValue)); // include the script in a json output UniValue o(UniValue::VOBJ); ScriptPubKeyToUniv(coin.out.scriptPubKey, o, true); utxo.pushKV("scriptPubKey", o); utxos.push_back(utxo); } objGetUTXOResponse.pushKV("utxos", utxos); // return json string std::string strJSON = objGetUTXOResponse.write() + "\n"; req->WriteHeader("Content-Type", "application/json"); req->WriteReply(HTTP_OK, strJSON); return true; } default: { return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: " + AvailableDataFormatsString() + ")"); } } // not reached // continue to process further HTTP reqs on this cxn return true; } static const struct { const char *prefix; bool (*handler)(Config &config, HTTPRequest *req, const std::string &strReq); } uri_prefixes[] = { {"/rest/tx/", rest_tx}, {"/rest/block/notxdetails/", rest_block_notxdetails}, {"/rest/block/", rest_block_extended}, {"/rest/chaininfo", rest_chaininfo}, {"/rest/mempool/info", rest_mempool_info}, {"/rest/mempool/contents", rest_mempool_contents}, {"/rest/headers/", rest_headers}, {"/rest/getutxos", rest_getutxos}, }; bool StartREST() { for (size_t i = 0; i < ARRAYLEN(uri_prefixes); i++) { RegisterHTTPHandler(uri_prefixes[i].prefix, false, uri_prefixes[i].handler); } return true; } void InterruptREST() {} void StopREST() { for (size_t i = 0; i < ARRAYLEN(uri_prefixes); i++) { UnregisterHTTPHandler(uri_prefixes[i].prefix, false); } } diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 4e89a1f780..c2f7ddd33c 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -1,800 +1,801 @@ // Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static UniValue getconnectioncount(const Config &config, const JSONRPCRequest &request) { if (request.fHelp || request.params.size() != 0) { throw std::runtime_error( "getconnectioncount\n" "\nReturns the number of connections to other nodes.\n" "\nResult:\n" "n (numeric) The connection count\n" "\nExamples:\n" + HelpExampleCli("getconnectioncount", "") + HelpExampleRpc("getconnectioncount", "")); } if (!g_connman) { throw JSONRPCError( RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); } return int(g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL)); } static UniValue ping(const Config &config, const JSONRPCRequest &request) { if (request.fHelp || request.params.size() != 0) { throw std::runtime_error( "ping\n" "\nRequests that a ping be sent to all other nodes, to measure " "ping time.\n" "Results provided in getpeerinfo, pingtime and pingwait fields are " "decimal seconds.\n" "Ping command is handled in queue with all other commands, so it " "measures processing backlog, not just network ping.\n" "\nExamples:\n" + HelpExampleCli("ping", "") + HelpExampleRpc("ping", "")); } if (!g_connman) { throw JSONRPCError( RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); } // Request that each node send a ping during next message processing pass g_connman->ForEachNode([](CNode *pnode) { pnode->fPingQueued = true; }); return NullUniValue; } static UniValue getpeerinfo(const Config &config, const JSONRPCRequest &request) { if (request.fHelp || request.params.size() != 0) { throw std::runtime_error( "getpeerinfo\n" "\nReturns data about each connected network node as a json array " "of objects.\n" "\nResult:\n" "[\n" " {\n" " \"id\": n, (numeric) Peer index\n" - " \"addr\":\"host:port\", (string) The ip address and port " + " \"addr\":\"host:port\", (string) The IP address and port " "of the peer\n" " \"addrbind\":\"ip:port\", (string) Bind address of the " "connection to the peer\n" " \"addrlocal\":\"ip:port\", (string) Local address as " "reported by the peer\n" " \"services\":\"xxxxxxxxxxxxxxxx\", (string) The services " "offered\n" " \"relaytxes\":true|false, (boolean) Whether peer has asked " "us to relay transactions to it\n" " \"lastsend\": ttt, (numeric) The time in seconds " "since epoch (Jan 1 1970 GMT) of the last send\n" " \"lastrecv\": ttt, (numeric) The time in seconds " "since epoch (Jan 1 1970 GMT) of the last receive\n" " \"bytessent\": n, (numeric) The total bytes sent\n" " \"bytesrecv\": n, (numeric) The total bytes " "received\n" " \"conntime\": ttt, (numeric) The connection time in " "seconds since epoch (Jan 1 1970 GMT)\n" " \"timeoffset\": ttt, (numeric) The time offset in " "seconds\n" " \"pingtime\": n, (numeric) ping time (if " "available)\n" " \"minping\": n, (numeric) minimum observed ping " "time (if any at all)\n" " \"pingwait\": n, (numeric) ping wait (if " "non-zero)\n" " \"version\": v, (numeric) The peer version, such " "as 7001\n" " \"subver\": \"/Satoshi:0.8.5/\", (string) The string " "version\n" " \"inbound\": true|false, (boolean) Inbound (true) or " "Outbound (false)\n" " \"addnode\": true|false, (boolean) Whether connection was " "due to addnode/-connect or if it was an automatic/inbound " "connection\n" " \"startingheight\": n, (numeric) The starting height " "(block) of the peer\n" " \"banscore\": n, (numeric) The ban score\n" " \"synced_headers\": n, (numeric) The last header we " "have in common with this peer\n" " \"synced_blocks\": n, (numeric) The last block we have " "in common with this peer\n" " \"inflight\": [\n" " n, (numeric) The heights of blocks " "we're currently asking from this peer\n" " ...\n" " ],\n" " \"whitelisted\": true|false, (boolean) Whether the peer is " "whitelisted\n" " \"bytessent_per_msg\": {\n" " \"addr\": n, (numeric) The total bytes sent " "aggregated by message type\n" " ...\n" " },\n" " \"bytesrecv_per_msg\": {\n" " \"addr\": n, (numeric) The total bytes " "received aggregated by message type\n" " ...\n" " }\n" " }\n" " ,...\n" "]\n" "\nExamples:\n" + HelpExampleCli("getpeerinfo", "") + HelpExampleRpc("getpeerinfo", "")); } if (!g_connman) { throw JSONRPCError( RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); } std::vector vstats; g_connman->GetNodeStats(vstats); UniValue ret(UniValue::VARR); for (const CNodeStats &stats : vstats) { UniValue obj(UniValue::VOBJ); CNodeStateStats statestats; bool fStateStats = GetNodeStateStats(stats.nodeid, statestats); obj.pushKV("id", stats.nodeid); obj.pushKV("addr", stats.addrName); if (!(stats.addrLocal.empty())) { obj.pushKV("addrlocal", stats.addrLocal); } if (stats.addrBind.IsValid()) { obj.pushKV("addrbind", stats.addrBind.ToString()); } obj.pushKV("services", strprintf("%016x", stats.nServices)); obj.pushKV("relaytxes", stats.fRelayTxes); obj.pushKV("lastsend", stats.nLastSend); obj.pushKV("lastrecv", stats.nLastRecv); obj.pushKV("bytessent", stats.nSendBytes); obj.pushKV("bytesrecv", stats.nRecvBytes); obj.pushKV("conntime", stats.nTimeConnected); obj.pushKV("timeoffset", stats.nTimeOffset); if (stats.dPingTime > 0.0) { obj.pushKV("pingtime", stats.dPingTime); } if (stats.dMinPing < std::numeric_limits::max() / 1e6) { obj.pushKV("minping", stats.dMinPing); } if (stats.dPingWait > 0.0) { obj.pushKV("pingwait", stats.dPingWait); } obj.pushKV("version", stats.nVersion); // Use the sanitized form of subver here, to avoid tricksy remote peers // from corrupting or modifying the JSON output by putting special // characters in their ver message. obj.pushKV("subver", stats.cleanSubVer); obj.pushKV("inbound", stats.fInbound); obj.pushKV("addnode", stats.m_manual_connection); obj.pushKV("startingheight", stats.nStartingHeight); if (fStateStats) { obj.pushKV("banscore", statestats.nMisbehavior); obj.pushKV("synced_headers", statestats.nSyncHeight); obj.pushKV("synced_blocks", statestats.nCommonHeight); UniValue heights(UniValue::VARR); for (int height : statestats.vHeightInFlight) { heights.push_back(height); } obj.pushKV("inflight", heights); } obj.pushKV("whitelisted", stats.fWhitelisted); UniValue sendPerMsgCmd(UniValue::VOBJ); for (const mapMsgCmdSize::value_type &i : stats.mapSendBytesPerMsgCmd) { if (i.second > 0) { sendPerMsgCmd.pushKV(i.first, i.second); } } obj.pushKV("bytessent_per_msg", sendPerMsgCmd); UniValue recvPerMsgCmd(UniValue::VOBJ); for (const mapMsgCmdSize::value_type &i : stats.mapRecvBytesPerMsgCmd) { if (i.second > 0) { recvPerMsgCmd.pushKV(i.first, i.second); } } obj.pushKV("bytesrecv_per_msg", recvPerMsgCmd); ret.push_back(obj); } return ret; } static UniValue addnode(const Config &config, const JSONRPCRequest &request) { std::string strCommand; if (request.params.size() == 2) { strCommand = request.params[1].get_str(); } if (request.fHelp || request.params.size() != 2 || (strCommand != "onetry" && strCommand != "add" && strCommand != "remove")) { throw std::runtime_error( "addnode \"node\" \"add|remove|onetry\"\n" - "\nAttempts add or remove a node from the addnode list.\n" + "\nAttempts to add or remove a node from the addnode list.\n" "Or try a connection to a node once.\n" "Nodes added using addnode (or -connect) are protected from DoS " "disconnection and are not required to be\n" "full nodes as other outbound peers are (though " "such peers will not be synced from).\n" "\nArguments:\n" "1. \"node\" (string, required) The node (see getpeerinfo for " "nodes)\n" "2. \"command\" (string, required) 'add' to add a node to the " "list, 'remove' to remove a node from the list, 'onetry' to try a " "connection to the node once\n" "\nExamples:\n" + HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\"") + HelpExampleRpc("addnode", "\"192.168.0.6:8333\", \"onetry\"")); } if (!g_connman) { throw JSONRPCError( RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); } std::string strNode = request.params[0].get_str(); if (strCommand == "onetry") { CAddress addr; g_connman->OpenNetworkConnection(addr, false, nullptr, strNode.c_str(), false, false, true); return NullUniValue; } if ((strCommand == "add") && (!g_connman->AddNode(strNode))) { throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added"); } else if ((strCommand == "remove") && (!g_connman->RemoveAddedNode(strNode))) { throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added."); } return NullUniValue; } static UniValue disconnectnode(const Config &config, const JSONRPCRequest &request) { if (request.fHelp || request.params.size() == 0 || request.params.size() >= 3) { throw std::runtime_error( "disconnectnode \"[address]\" [nodeid]\n" "\nImmediately disconnects from the specified peer node.\n" "\nStrictly one out of 'address' and 'nodeid' can be provided to " "identify the node.\n" "\nTo disconnect by nodeid, either set 'address' to the empty " "string, or call using the named 'nodeid' argument only.\n" "\nArguments:\n" "1. \"address\" (string, optional) The IP address/port of the " "node\n" "2. \"nodeid\" (number, optional) The node ID (see " "getpeerinfo for node IDs)\n" "\nExamples:\n" + HelpExampleCli("disconnectnode", "\"192.168.0.6:8333\"") + HelpExampleCli("disconnectnode", "\"\" 1") + HelpExampleRpc("disconnectnode", "\"192.168.0.6:8333\"") + HelpExampleRpc("disconnectnode", "\"\", 1")); } if (!g_connman) { throw JSONRPCError( RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); } bool success; const UniValue &address_arg = request.params[0]; const UniValue &id_arg = request.params.size() < 2 ? NullUniValue : request.params[1]; if (!address_arg.isNull() && id_arg.isNull()) { /* handle disconnect-by-address */ success = g_connman->DisconnectNode(address_arg.get_str()); } else if (!id_arg.isNull() && (address_arg.isNull() || (address_arg.isStr() && address_arg.get_str().empty()))) { /* handle disconnect-by-id */ NodeId nodeid = (NodeId)id_arg.get_int64(); success = g_connman->DisconnectNode(nodeid); } else { throw JSONRPCError( RPC_INVALID_PARAMS, "Only one of address and nodeid should be provided."); } if (!success) { throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes"); } return NullUniValue; } static UniValue getaddednodeinfo(const Config &config, const JSONRPCRequest &request) { if (request.fHelp || request.params.size() > 1) { throw std::runtime_error( "getaddednodeinfo ( \"node\" )\n" "\nReturns information about the given added node, or all added " "nodes\n" "(note that onetry addnodes are not listed here)\n" "\nArguments:\n" "1. \"node\" (string, optional) If provided, return information " "about this specific node, otherwise all nodes are returned.\n" "\nResult:\n" "[\n" " {\n" - " \"addednode\" : \"192.168.0.201\", (string) The node ip " + " \"addednode\" : \"192.168.0.201\", (string) The node IP " "address or name (as provided to addnode)\n" " \"connected\" : true|false, (boolean) If connected\n" " \"addresses\" : [ (list of objects) Only " "when connected = true\n" " {\n" " \"address\" : \"192.168.0.201:8333\", (string) The " "bitcoin server IP and port we're connected to\n" " \"connected\" : \"outbound\" (string) " "connection, inbound or outbound\n" " }\n" " ]\n" " }\n" " ,...\n" "]\n" "\nExamples:\n" + HelpExampleCli("getaddednodeinfo", "\"192.168.0.201\"") + HelpExampleRpc("getaddednodeinfo", "\"192.168.0.201\"")); } if (!g_connman) { throw JSONRPCError( RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); } std::vector vInfo = g_connman->GetAddedNodeInfo(); if (request.params.size() == 1 && !request.params[0].isNull()) { bool found = false; for (const AddedNodeInfo &info : vInfo) { if (info.strAddedNode == request.params[0].get_str()) { vInfo.assign(1, info); found = true; break; } } if (!found) { throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added."); } } UniValue ret(UniValue::VARR); for (const AddedNodeInfo &info : vInfo) { UniValue obj(UniValue::VOBJ); obj.pushKV("addednode", info.strAddedNode); obj.pushKV("connected", info.fConnected); UniValue addresses(UniValue::VARR); if (info.fConnected) { UniValue address(UniValue::VOBJ); address.pushKV("address", info.resolvedAddress.ToString()); address.pushKV("connected", info.fInbound ? "inbound" : "outbound"); addresses.push_back(address); } obj.pushKV("addresses", addresses); ret.push_back(obj); } return ret; } static UniValue getnettotals(const Config &config, const JSONRPCRequest &request) { if (request.fHelp || request.params.size() > 0) { throw std::runtime_error( "getnettotals\n" "\nReturns information about network traffic, including bytes in, " "bytes out,\n" "and current time.\n" "\nResult:\n" "{\n" " \"totalbytesrecv\": n, (numeric) Total bytes received\n" " \"totalbytessent\": n, (numeric) Total bytes sent\n" " \"timemillis\": t, (numeric) Current UNIX time in " "milliseconds\n" " \"uploadtarget\":\n" " {\n" " \"timeframe\": n, (numeric) Length of " "the measuring timeframe in seconds\n" " \"target\": n, (numeric) Target in " "bytes\n" " \"target_reached\": true|false, (boolean) True if " "target is reached\n" " \"serve_historical_blocks\": true|false, (boolean) True if " "serving historical blocks\n" " \"bytes_left_in_cycle\": t, (numeric) Bytes " "left in current time cycle\n" " \"time_left_in_cycle\": t (numeric) Seconds " "left in current time cycle\n" " }\n" "}\n" "\nExamples:\n" + HelpExampleCli("getnettotals", "") + HelpExampleRpc("getnettotals", "")); } if (!g_connman) { throw JSONRPCError( RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); } UniValue obj(UniValue::VOBJ); obj.pushKV("totalbytesrecv", g_connman->GetTotalBytesRecv()); obj.pushKV("totalbytessent", g_connman->GetTotalBytesSent()); obj.pushKV("timemillis", GetTimeMillis()); UniValue outboundLimit(UniValue::VOBJ); outboundLimit.pushKV("timeframe", g_connman->GetMaxOutboundTimeframe()); outboundLimit.pushKV("target", g_connman->GetMaxOutboundTarget()); outboundLimit.pushKV("target_reached", g_connman->OutboundTargetReached(false)); outboundLimit.pushKV("serve_historical_blocks", !g_connman->OutboundTargetReached(true)); outboundLimit.pushKV("bytes_left_in_cycle", g_connman->GetOutboundTargetBytesLeft()); outboundLimit.pushKV("time_left_in_cycle", g_connman->GetMaxOutboundTimeLeftInCycle()); obj.pushKV("uploadtarget", outboundLimit); return obj; } static UniValue GetNetworksInfo() { UniValue networks(UniValue::VARR); for (int n = 0; n < NET_MAX; ++n) { enum Network network = static_cast(n); if (network == NET_UNROUTABLE || network == NET_INTERNAL) { continue; } proxyType proxy; UniValue obj(UniValue::VOBJ); GetProxy(network, proxy); obj.pushKV("name", GetNetworkName(network)); obj.pushKV("limited", IsLimited(network)); obj.pushKV("reachable", IsReachable(network)); obj.pushKV("proxy", proxy.IsValid() ? proxy.proxy.ToStringIPPort() : std::string()); obj.pushKV("proxy_randomize_credentials", proxy.randomize_credentials); networks.push_back(obj); } return networks; } static UniValue getnetworkinfo(const Config &config, const JSONRPCRequest &request) { if (request.fHelp || request.params.size() != 0) { throw std::runtime_error( "getnetworkinfo\n" "Returns an object containing various state info regarding P2P " "networking.\n" "\nResult:\n" "{\n" " \"version\": xxxxx, (numeric) the server " "version\n" " \"subversion\": \"/Satoshi:x.x.x/\", (string) the server " "subversion string\n" " \"protocolversion\": xxxxx, (numeric) the protocol " "version\n" " \"localservices\": \"xxxxxxxxxxxxxxxx\", (string) the services " "we offer to the network\n" " \"localrelay\": true|false, (bool) true if " "transaction relay is requested from peers\n" " \"timeoffset\": xxxxx, (numeric) the time " "offset\n" " \"connections\": xxxxx, (numeric) the number " "of connections\n" " \"networkactive\": true|false, (bool) whether p2p " "networking is enabled\n" " \"networks\": [ (array) information " "per network\n" " {\n" " \"name\": \"xxx\", (string) network " "(ipv4, ipv6 or onion)\n" " \"limited\": true|false, (boolean) is the " "network limited using -onlynet?\n" " \"reachable\": true|false, (boolean) is the " "network reachable?\n" " \"proxy\": \"host:port\" (string) the proxy " "that is used for this network, or empty if none\n" " \"proxy_randomize_credentials\": true|false, (string) " "Whether randomized credentials are used\n" " }\n" " ,...\n" " ],\n" " \"relayfee\": x.xxxxxxxx, (numeric) minimum " "relay fee for non-free transactions in " + CURRENCY_UNIT + "/kB\n" " \"excessutxocharge\": x.xxxxxxxx, (numeric) minimum " "charge for excess utxos in " + CURRENCY_UNIT + "\n" " \"localaddresses\": [ " "(array) list of local addresses\n" " {\n" " \"address\": \"xxxx\", " "(string) network address\n" " \"port\": xxx, " "(numeric) network port\n" " \"score\": xxx " "(numeric) relative score\n" " }\n" " ,...\n" " ]\n" " \"warnings\": \"...\" (string) any network " "and blockchain warnings\n" "}\n" "\nExamples:\n" + HelpExampleCli("getnetworkinfo", "") + HelpExampleRpc("getnetworkinfo", "")); } LOCK(cs_main); UniValue obj(UniValue::VOBJ); obj.pushKV("version", CLIENT_VERSION); obj.pushKV("subversion", userAgent(config)); obj.pushKV("protocolversion", PROTOCOL_VERSION); if (g_connman) { obj.pushKV("localservices", strprintf("%016x", g_connman->GetLocalServices())); } obj.pushKV("localrelay", fRelayTxes); obj.pushKV("timeoffset", GetTimeOffset()); if (g_connman) { obj.pushKV("networkactive", g_connman->GetNetworkActive()); obj.pushKV("connections", int(g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL))); } obj.pushKV("networks", GetNetworksInfo()); obj.pushKV("relayfee", ValueFromAmount(config.GetMinFeePerKB().GetFeePerK())); obj.pushKV("excessutxocharge", ValueFromAmount(config.GetExcessUTXOCharge())); UniValue localAddresses(UniValue::VARR); { LOCK(cs_mapLocalHost); for (const std::pair &item : mapLocalHost) { UniValue rec(UniValue::VOBJ); rec.pushKV("address", item.first.ToString()); rec.pushKV("port", item.second.nPort); rec.pushKV("score", item.second.nScore); localAddresses.push_back(rec); } } obj.pushKV("localaddresses", localAddresses); obj.pushKV("warnings", GetWarnings("statusbar")); return obj; } static UniValue setban(const Config &config, const JSONRPCRequest &request) { std::string strCommand; if (request.params.size() >= 2) { strCommand = request.params[1].get_str(); } if (request.fHelp || request.params.size() < 2 || (strCommand != "add" && strCommand != "remove")) { throw std::runtime_error( "setban \"subnet\" \"add|remove\" (bantime) (absolute)\n" - "\nAttempts add or remove a IP/Subnet from the banned list.\n" + "\nAttempts to add or remove a IP/Subnet from the banned list.\n" "\nArguments:\n" "1. \"subnet\" (string, required) The IP/Subnet (see " - "getpeerinfo for nodes ip) with a optional netmask (default is /32 " - "= single ip)\n" - "2. \"command\" (string, required) 'add' to add a IP/Subnet " - "to the list, 'remove' to remove a IP/Subnet from the list\n" + "getpeerinfo for nodes IP) with an optional netmask (default is " + "/32 " + "= single IP)\n" + "2. \"command\" (string, required) 'add' to add an IP/Subnet " + "to the list, 'remove' to remove an IP/Subnet from the list\n" "3. \"bantime\" (numeric, optional) time in seconds how long " - "(or until when if [absolute] is set) the ip is banned (0 or empty " + "(or until when if [absolute] is set) the IP is banned (0 or empty " "means using the default time of 24h which can also be overwritten " "by the -bantime startup argument)\n" "4. \"absolute\" (boolean, optional) If set, the bantime must " - "be a absolute timestamp in seconds since epoch (Jan 1 1970 GMT)\n" + "be an absolute timestamp in seconds since epoch (Jan 1 1970 GMT)\n" "\nExamples:\n" + HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400") + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"") + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\", 86400")); } if (!g_connman) { throw JSONRPCError( RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); } CSubNet subNet; CNetAddr netAddr; bool isSubnet = false; if (request.params[0].get_str().find("/") != std::string::npos) { isSubnet = true; } if (!isSubnet) { CNetAddr resolved; LookupHost(request.params[0].get_str().c_str(), resolved, false); netAddr = resolved; } else { LookupSubNet(request.params[0].get_str().c_str(), subNet); } if (!(isSubnet ? subNet.IsValid() : netAddr.IsValid())) { throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Invalid IP/Subnet"); } if (strCommand == "add") { if (isSubnet ? g_connman->IsBanned(subNet) : g_connman->IsBanned(netAddr)) { throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned"); } // Use standard bantime if not specified. int64_t banTime = 0; if (request.params.size() >= 3 && !request.params[2].isNull()) { banTime = request.params[2].get_int64(); } bool absolute = false; if (request.params.size() == 4 && request.params[3].isTrue()) { absolute = true; } isSubnet ? g_connman->Ban(subNet, BanReasonManuallyAdded, banTime, absolute) : g_connman->Ban(netAddr, BanReasonManuallyAdded, banTime, absolute); } else if (strCommand == "remove") { if (!(isSubnet ? g_connman->Unban(subNet) : g_connman->Unban(netAddr))) { throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Unban failed. Requested address/subnet " "was not previously banned."); } } return NullUniValue; } static UniValue listbanned(const Config &config, const JSONRPCRequest &request) { if (request.fHelp || request.params.size() != 0) { throw std::runtime_error("listbanned\n" "\nList all banned IPs/Subnets.\n" "\nExamples:\n" + HelpExampleCli("listbanned", "") + HelpExampleRpc("listbanned", "")); } if (!g_connman) { throw JSONRPCError( RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); } banmap_t banMap; g_connman->GetBanned(banMap); UniValue bannedAddresses(UniValue::VARR); for (const auto &entry : banMap) { const CBanEntry &banEntry = entry.second; UniValue rec(UniValue::VOBJ); rec.pushKV("address", entry.first.ToString()); rec.pushKV("banned_until", banEntry.nBanUntil); rec.pushKV("ban_created", banEntry.nCreateTime); rec.pushKV("ban_reason", banEntry.banReasonToString()); bannedAddresses.push_back(rec); } return bannedAddresses; } static UniValue clearbanned(const Config &config, const JSONRPCRequest &request) { if (request.fHelp || request.params.size() != 0) { throw std::runtime_error("clearbanned\n" "\nClear all banned IPs.\n" "\nExamples:\n" + HelpExampleCli("clearbanned", "") + HelpExampleRpc("clearbanned", "")); } if (!g_connman) { throw JSONRPCError( RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); } g_connman->ClearBanned(); return NullUniValue; } static UniValue setnetworkactive(const Config &config, const JSONRPCRequest &request) { if (request.fHelp || request.params.size() != 1) { throw std::runtime_error( "setnetworkactive true|false\n" "\nDisable/enable all p2p network activity.\n" "\nArguments:\n" "1. \"state\" (boolean, required) true to " "enable networking, false to disable\n"); } if (!g_connman) { throw JSONRPCError( RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); } g_connman->SetNetworkActive(request.params[0].get_bool()); return g_connman->GetNetworkActive(); } // clang-format off static const ContextFreeRPCCommand commands[] = { // category name actor (function) argNames // ------------------- ------------------------ ---------------------- ---------- { "network", "getconnectioncount", getconnectioncount, {} }, { "network", "ping", ping, {} }, { "network", "getpeerinfo", getpeerinfo, {} }, { "network", "addnode", addnode, {"node","command"} }, { "network", "disconnectnode", disconnectnode, {"address", "nodeid"} }, { "network", "getaddednodeinfo", getaddednodeinfo, {"node"} }, { "network", "getnettotals", getnettotals, {} }, { "network", "getnetworkinfo", getnetworkinfo, {} }, { "network", "setban", setban, {"subnet", "command", "bantime", "absolute"} }, { "network", "listbanned", listbanned, {} }, { "network", "clearbanned", clearbanned, {} }, { "network", "setnetworkactive", setnetworkactive, {"state"} }, }; // clang-format on void RegisterNetRPCCommands(CRPCTable &t) { for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) { t.appendCommand(commands[vcidx].name, &commands[vcidx]); } } diff --git a/src/test/arith_uint256_tests.cpp b/src/test/arith_uint256_tests.cpp index 964a070a09..2592f4cab6 100644 --- a/src/test/arith_uint256_tests.cpp +++ b/src/test/arith_uint256_tests.cpp @@ -1,674 +1,674 @@ // Copyright (c) 2011-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include #include #include #include #include #include #include #include #include #include BOOST_FIXTURE_TEST_SUITE(arith_uint256_tests, BasicTestingSetup) /// Convert vector to arith_uint256, via uint256 blob inline arith_uint256 arith_uint256V(const std::vector &vch) { return UintToArith256(uint256(vch)); } const uint8_t R1Array[] = "\x9c\x52\x4a\xdb\xcf\x56\x11\x12\x2b\x29\x12\x5e\x5d\x35\xd2\xd2" "\x22\x81\xaa\xb5\x33\xf0\x08\x32\xd5\x56\xb1\xf9\xea\xe5\x1d\x7d"; const char R1ArrayHex[] = "7D1DE5EAF9B156D53208F033B5AA8122D2d2355d5e12292b121156cfdb4a529c"; // R1L equals roughly R1Ldouble * 2^256 const double R1Ldouble = 0.4887374590559308955; const arith_uint256 R1L = arith_uint256V(std::vector(R1Array, R1Array + 32)); const uint64_t R1LLow64 = 0x121156cfdb4a529cULL; const uint8_t R2Array[] = "\x70\x32\x1d\x7c\x47\xa5\x6b\x40\x26\x7e\x0a\xc3\xa6\x9c\xb6\xbf" "\x13\x30\x47\xa3\x19\x2d\xda\x71\x49\x13\x72\xf0\xb4\xca\x81\xd7"; const arith_uint256 R2L = arith_uint256V(std::vector(R2Array, R2Array + 32)); const char R1LplusR2L[] = "549FB09FEA236A1EA3E31D4D58F1B1369288D204211CA751527CFC175767850C"; const uint8_t ZeroArray[] = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; const arith_uint256 ZeroL = arith_uint256V(std::vector(ZeroArray, ZeroArray + 32)); const uint8_t OneArray[] = "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; const arith_uint256 OneL = arith_uint256V(std::vector(OneArray, OneArray + 32)); const uint8_t MaxArray[] = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"; const arith_uint256 MaxL = arith_uint256V(std::vector(MaxArray, MaxArray + 32)); const arith_uint256 HalfL = (OneL << 255); std::string ArrayToString(const uint8_t A[], unsigned int width) { std::stringstream Stream; Stream << std::hex; for (unsigned int i = 0; i < width; ++i) { Stream << std::setw(2) << std::setfill('0') << (unsigned int)A[width - i - 1]; } return Stream.str(); } // constructors, equality, inequality BOOST_AUTO_TEST_CASE(basics) { BOOST_CHECK(1 == 0 + 1); // constructor arith_uint256(vector): BOOST_CHECK(R1L.ToString() == ArrayToString(R1Array, 32)); BOOST_CHECK(R2L.ToString() == ArrayToString(R2Array, 32)); BOOST_CHECK(ZeroL.ToString() == ArrayToString(ZeroArray, 32)); BOOST_CHECK(OneL.ToString() == ArrayToString(OneArray, 32)); BOOST_CHECK(MaxL.ToString() == ArrayToString(MaxArray, 32)); BOOST_CHECK(OneL.ToString() != ArrayToString(ZeroArray, 32)); // == and != BOOST_CHECK(R1L != R2L); BOOST_CHECK(ZeroL != OneL); BOOST_CHECK(OneL != ZeroL); BOOST_CHECK(MaxL != ZeroL); BOOST_CHECK(~MaxL == ZeroL); BOOST_CHECK(((R1L ^ R2L) ^ R1L) == R2L); uint64_t Tmp64 = 0xc4dab720d9c7acaaULL; for (unsigned int i = 0; i < 256; ++i) { BOOST_CHECK(ZeroL != (OneL << i)); BOOST_CHECK((OneL << i) != ZeroL); BOOST_CHECK(R1L != (R1L ^ (OneL << i))); BOOST_CHECK(((arith_uint256(Tmp64) ^ (OneL << i)) != Tmp64)); } BOOST_CHECK(ZeroL == (OneL << 256)); // String Constructor and Copy Constructor BOOST_CHECK(arith_uint256("0x" + R1L.ToString()) == R1L); BOOST_CHECK(arith_uint256("0x" + R2L.ToString()) == R2L); BOOST_CHECK(arith_uint256("0x" + ZeroL.ToString()) == ZeroL); BOOST_CHECK(arith_uint256("0x" + OneL.ToString()) == OneL); BOOST_CHECK(arith_uint256("0x" + MaxL.ToString()) == MaxL); BOOST_CHECK(arith_uint256(R1L.ToString()) == R1L); BOOST_CHECK(arith_uint256(" 0x" + R1L.ToString() + " ") == R1L); BOOST_CHECK(arith_uint256("") == ZeroL); BOOST_CHECK(R1L == arith_uint256(R1ArrayHex)); BOOST_CHECK(arith_uint256(R1L) == R1L); BOOST_CHECK((arith_uint256(R1L ^ R2L) ^ R2L) == R1L); BOOST_CHECK(arith_uint256(ZeroL) == ZeroL); BOOST_CHECK(arith_uint256(OneL) == OneL); // uint64_t constructor BOOST_CHECK((R1L & arith_uint256("0xffffffffffffffff")) == arith_uint256(R1LLow64)); BOOST_CHECK(ZeroL == arith_uint256(0)); BOOST_CHECK(OneL == arith_uint256(1)); BOOST_CHECK(arith_uint256("0xffffffffffffffff") == arith_uint256(0xffffffffffffffffULL)); // Assignment (from base_uint) arith_uint256 tmpL = ~ZeroL; BOOST_CHECK(tmpL == ~ZeroL); tmpL = ~OneL; BOOST_CHECK(tmpL == ~OneL); tmpL = ~R1L; BOOST_CHECK(tmpL == ~R1L); tmpL = ~R2L; BOOST_CHECK(tmpL == ~R2L); tmpL = ~MaxL; BOOST_CHECK(tmpL == ~MaxL); } void shiftArrayRight(uint8_t *to, const uint8_t *from, unsigned int arrayLength, unsigned int bitsToShift) { for (unsigned int T = 0; T < arrayLength; ++T) { unsigned int F = (T + bitsToShift / 8); if (F < arrayLength) { to[T] = from[F] >> (bitsToShift % 8); } else { to[T] = 0; } if (F + 1 < arrayLength) { to[T] |= from[(F + 1)] << (8 - bitsToShift % 8); } } } void shiftArrayLeft(uint8_t *to, const uint8_t *from, unsigned int arrayLength, unsigned int bitsToShift) { for (unsigned int T = 0; T < arrayLength; ++T) { if (T >= bitsToShift / 8) { unsigned int F = T - bitsToShift / 8; to[T] = from[F] << (bitsToShift % 8); if (T >= bitsToShift / 8 + 1) { to[T] |= from[F - 1] >> (8 - bitsToShift % 8); } } else { to[T] = 0; } } } // "<<" ">>" "<<=" ">>=" BOOST_AUTO_TEST_CASE(shifts) { uint8_t TmpArray[32]; arith_uint256 TmpL; for (unsigned int i = 0; i < 256; ++i) { shiftArrayLeft(TmpArray, OneArray, 32, i); BOOST_CHECK(arith_uint256V(std::vector( TmpArray, TmpArray + 32)) == (OneL << i)); TmpL = OneL; TmpL <<= i; BOOST_CHECK(TmpL == (OneL << i)); BOOST_CHECK((HalfL >> (255 - i)) == (OneL << i)); TmpL = HalfL; TmpL >>= (255 - i); BOOST_CHECK(TmpL == (OneL << i)); shiftArrayLeft(TmpArray, R1Array, 32, i); BOOST_CHECK(arith_uint256V(std::vector( TmpArray, TmpArray + 32)) == (R1L << i)); TmpL = R1L; TmpL <<= i; BOOST_CHECK(TmpL == (R1L << i)); shiftArrayRight(TmpArray, R1Array, 32, i); BOOST_CHECK(arith_uint256V(std::vector( TmpArray, TmpArray + 32)) == (R1L >> i)); TmpL = R1L; TmpL >>= i; BOOST_CHECK(TmpL == (R1L >> i)); shiftArrayLeft(TmpArray, MaxArray, 32, i); BOOST_CHECK(arith_uint256V(std::vector( TmpArray, TmpArray + 32)) == (MaxL << i)); TmpL = MaxL; TmpL <<= i; BOOST_CHECK(TmpL == (MaxL << i)); shiftArrayRight(TmpArray, MaxArray, 32, i); BOOST_CHECK(arith_uint256V(std::vector( TmpArray, TmpArray + 32)) == (MaxL >> i)); TmpL = MaxL; TmpL >>= i; BOOST_CHECK(TmpL == (MaxL >> i)); } arith_uint256 c1L = arith_uint256(0x0123456789abcdefULL); arith_uint256 c2L = c1L << 128; for (unsigned int i = 0; i < 128; ++i) { BOOST_CHECK((c1L << i) == (c2L >> (128 - i))); } for (unsigned int i = 128; i < 256; ++i) { BOOST_CHECK((c1L << i) == (c2L << (i - 128))); } } // ! ~ - BOOST_AUTO_TEST_CASE(unaryOperators) { BOOST_CHECK(!ZeroL); BOOST_CHECK(!(!OneL)); for (unsigned int i = 0; i < 256; ++i) BOOST_CHECK(!(!(OneL << i))); BOOST_CHECK(!(!R1L)); BOOST_CHECK(!(!MaxL)); BOOST_CHECK(~ZeroL == MaxL); uint8_t TmpArray[32]; for (unsigned int i = 0; i < 32; ++i) { TmpArray[i] = ~R1Array[i]; } BOOST_CHECK(arith_uint256V(std::vector(TmpArray, TmpArray + 32)) == (~R1L)); BOOST_CHECK(-ZeroL == ZeroL); BOOST_CHECK(-R1L == (~R1L) + 1); for (unsigned int i = 0; i < 256; ++i) BOOST_CHECK(-(OneL << i) == (MaxL << i)); } // Check if doing _A_ _OP_ _B_ results in the same as applying _OP_ onto each -// element of Aarray and Barray, and then converting the result into a +// element of Aarray and Barray, and then converting the result into an // arith_uint256. #define CHECKBITWISEOPERATOR(_A_, _B_, _OP_) \ for (unsigned int i = 0; i < 32; ++i) { \ TmpArray[i] = _A_##Array[i] _OP_ _B_##Array[i]; \ } \ BOOST_CHECK(arith_uint256V(std::vector( \ TmpArray, TmpArray + 32)) == (_A_##L _OP_ _B_##L)); #define CHECKASSIGNMENTOPERATOR(_A_, _B_, _OP_) \ TmpL = _A_##L; \ TmpL _OP_## = _B_##L; \ BOOST_CHECK(TmpL == (_A_##L _OP_ _B_##L)); BOOST_AUTO_TEST_CASE(bitwiseOperators) { uint8_t TmpArray[32]; CHECKBITWISEOPERATOR(R1, R2, |) CHECKBITWISEOPERATOR(R1, R2, ^) CHECKBITWISEOPERATOR(R1, R2, &) CHECKBITWISEOPERATOR(R1, Zero, |) CHECKBITWISEOPERATOR(R1, Zero, ^) CHECKBITWISEOPERATOR(R1, Zero, &) CHECKBITWISEOPERATOR(R1, Max, |) CHECKBITWISEOPERATOR(R1, Max, ^) CHECKBITWISEOPERATOR(R1, Max, &) CHECKBITWISEOPERATOR(Zero, R1, |) CHECKBITWISEOPERATOR(Zero, R1, ^) CHECKBITWISEOPERATOR(Zero, R1, &) CHECKBITWISEOPERATOR(Max, R1, |) CHECKBITWISEOPERATOR(Max, R1, ^) CHECKBITWISEOPERATOR(Max, R1, &) arith_uint256 TmpL; CHECKASSIGNMENTOPERATOR(R1, R2, |) CHECKASSIGNMENTOPERATOR(R1, R2, ^) CHECKASSIGNMENTOPERATOR(R1, R2, &) CHECKASSIGNMENTOPERATOR(R1, Zero, |) CHECKASSIGNMENTOPERATOR(R1, Zero, ^) CHECKASSIGNMENTOPERATOR(R1, Zero, &) CHECKASSIGNMENTOPERATOR(R1, Max, |) CHECKASSIGNMENTOPERATOR(R1, Max, ^) CHECKASSIGNMENTOPERATOR(R1, Max, &) CHECKASSIGNMENTOPERATOR(Zero, R1, |) CHECKASSIGNMENTOPERATOR(Zero, R1, ^) CHECKASSIGNMENTOPERATOR(Zero, R1, &) CHECKASSIGNMENTOPERATOR(Max, R1, |) CHECKASSIGNMENTOPERATOR(Max, R1, ^) CHECKASSIGNMENTOPERATOR(Max, R1, &) uint64_t Tmp64 = 0xe1db685c9a0b47a2ULL; TmpL = R1L; TmpL |= Tmp64; BOOST_CHECK(TmpL == (R1L | arith_uint256(Tmp64))); TmpL = R1L; TmpL |= 0; BOOST_CHECK(TmpL == R1L); TmpL ^= 0; BOOST_CHECK(TmpL == R1L); TmpL ^= Tmp64; BOOST_CHECK(TmpL == (R1L ^ arith_uint256(Tmp64))); } // <= >= < > BOOST_AUTO_TEST_CASE(comparison) { arith_uint256 TmpL; for (unsigned int i = 0; i < 256; ++i) { TmpL = OneL << i; BOOST_CHECK(TmpL >= ZeroL && TmpL > ZeroL && ZeroL < TmpL && ZeroL <= TmpL); BOOST_CHECK(TmpL >= 0 && TmpL > 0 && 0 < TmpL && 0 <= TmpL); TmpL |= R1L; BOOST_CHECK(TmpL >= R1L); BOOST_CHECK((TmpL == R1L) != (TmpL > R1L)); BOOST_CHECK((TmpL == R1L) || !(TmpL <= R1L)); BOOST_CHECK(R1L <= TmpL); BOOST_CHECK((R1L == TmpL) != (R1L < TmpL)); BOOST_CHECK((TmpL == R1L) || !(R1L >= TmpL)); BOOST_CHECK(!(TmpL < R1L)); BOOST_CHECK(!(R1L > TmpL)); } } BOOST_AUTO_TEST_CASE(plusMinus) { arith_uint256 TmpL = 0; BOOST_CHECK(R1L + R2L == arith_uint256(R1LplusR2L)); TmpL += R1L; BOOST_CHECK(TmpL == R1L); TmpL += R2L; BOOST_CHECK(TmpL == R1L + R2L); BOOST_CHECK(OneL + MaxL == ZeroL); BOOST_CHECK(MaxL + OneL == ZeroL); for (unsigned int i = 1; i < 256; ++i) { BOOST_CHECK((MaxL >> i) + OneL == (HalfL >> (i - 1))); BOOST_CHECK(OneL + (MaxL >> i) == (HalfL >> (i - 1))); TmpL = (MaxL >> i); TmpL += OneL; BOOST_CHECK(TmpL == (HalfL >> (i - 1))); TmpL = (MaxL >> i); TmpL += 1; BOOST_CHECK(TmpL == (HalfL >> (i - 1))); TmpL = (MaxL >> i); BOOST_CHECK(TmpL++ == (MaxL >> i)); BOOST_CHECK(TmpL == (HalfL >> (i - 1))); } BOOST_CHECK(arith_uint256(0xbedc77e27940a7ULL) + 0xee8d836fce66fbULL == arith_uint256(0xbedc77e27940a7ULL + 0xee8d836fce66fbULL)); TmpL = arith_uint256(0xbedc77e27940a7ULL); TmpL += 0xee8d836fce66fbULL; BOOST_CHECK(TmpL == arith_uint256(0xbedc77e27940a7ULL + 0xee8d836fce66fbULL)); TmpL -= 0xee8d836fce66fbULL; BOOST_CHECK(TmpL == 0xbedc77e27940a7ULL); TmpL = R1L; BOOST_CHECK(++TmpL == R1L + 1); BOOST_CHECK(R1L - (-R2L) == R1L + R2L); BOOST_CHECK(R1L - (-OneL) == R1L + OneL); BOOST_CHECK(R1L - OneL == R1L + (-OneL)); for (unsigned int i = 1; i < 256; ++i) { BOOST_CHECK((MaxL >> i) - (-OneL) == (HalfL >> (i - 1))); BOOST_CHECK((HalfL >> (i - 1)) - OneL == (MaxL >> i)); TmpL = (HalfL >> (i - 1)); BOOST_CHECK(TmpL-- == (HalfL >> (i - 1))); BOOST_CHECK(TmpL == (MaxL >> i)); TmpL = (HalfL >> (i - 1)); BOOST_CHECK(--TmpL == (MaxL >> i)); } TmpL = R1L; BOOST_CHECK(--TmpL == R1L - 1); } BOOST_AUTO_TEST_CASE(multiply) { BOOST_CHECK( (R1L * R1L).ToString() == "62a38c0486f01e45879d7910a7761bf30d5237e9873f9bff3642a732c4d84f10"); BOOST_CHECK( (R1L * R2L).ToString() == "de37805e9986996cfba76ff6ba51c008df851987d9dd323f0e5de07760529c40"); BOOST_CHECK((R1L * ZeroL) == ZeroL); BOOST_CHECK((R1L * OneL) == R1L); BOOST_CHECK((R1L * MaxL) == -R1L); BOOST_CHECK((R2L * R1L) == (R1L * R2L)); BOOST_CHECK( (R2L * R2L).ToString() == "ac8c010096767d3cae5005dec28bb2b45a1d85ab7996ccd3e102a650f74ff100"); BOOST_CHECK((R2L * ZeroL) == ZeroL); BOOST_CHECK((R2L * OneL) == R2L); BOOST_CHECK((R2L * MaxL) == -R2L); BOOST_CHECK(MaxL * MaxL == OneL); BOOST_CHECK((R1L * 0) == 0); BOOST_CHECK((R1L * 1) == R1L); BOOST_CHECK( (R1L * 3).ToString() == "7759b1c0ed14047f961ad09b20ff83687876a0181a367b813634046f91def7d4"); BOOST_CHECK( (R2L * 0x87654321UL).ToString() == "23f7816e30c4ae2017257b7a0fa64d60402f5234d46e746b61c960d09a26d070"); } BOOST_AUTO_TEST_CASE(divide) { arith_uint256 D1L("AD7133AC1977FA2B7"); arith_uint256 D2L("ECD751716"); BOOST_CHECK( (R1L / D1L).ToString() == "00000000000000000b8ac01106981635d9ed112290f8895545a7654dde28fb3a"); BOOST_CHECK( (R1L / D2L).ToString() == "000000000873ce8efec5b67150bad3aa8c5fcb70e947586153bf2cec7c37c57a"); BOOST_CHECK(R1L / OneL == R1L); BOOST_CHECK(R1L / MaxL == ZeroL); BOOST_CHECK(MaxL / R1L == 2); BOOST_CHECK_THROW(R1L / ZeroL, uint_error); BOOST_CHECK( (R2L / D1L).ToString() == "000000000000000013e1665895a1cc981de6d93670105a6b3ec3b73141b3a3c5"); BOOST_CHECK( (R2L / D2L).ToString() == "000000000e8f0abe753bb0afe2e9437ee85d280be60882cf0bd1aaf7fa3cc2c4"); BOOST_CHECK(R2L / OneL == R2L); BOOST_CHECK(R2L / MaxL == ZeroL); BOOST_CHECK(MaxL / R2L == 1); BOOST_CHECK_THROW(R2L / ZeroL, uint_error); } bool almostEqual(double d1, double d2) { return fabs(d1 - d2) <= 4 * fabs(d1) * std::numeric_limits::epsilon(); } // GetHex SetHex size() GetLow64 GetSerializeSize, Serialize, Unserialize BOOST_AUTO_TEST_CASE(methods) { BOOST_CHECK(R1L.GetHex() == R1L.ToString()); BOOST_CHECK(R2L.GetHex() == R2L.ToString()); BOOST_CHECK(OneL.GetHex() == OneL.ToString()); BOOST_CHECK(MaxL.GetHex() == MaxL.ToString()); arith_uint256 TmpL(R1L); BOOST_CHECK(TmpL == R1L); TmpL.SetHex(R2L.ToString()); BOOST_CHECK(TmpL == R2L); TmpL.SetHex(ZeroL.ToString()); BOOST_CHECK(TmpL == 0); TmpL.SetHex(HalfL.ToString()); BOOST_CHECK(TmpL == HalfL); TmpL.SetHex(R1L.ToString()); BOOST_CHECK(R1L.size() == 32); BOOST_CHECK(R2L.size() == 32); BOOST_CHECK(ZeroL.size() == 32); BOOST_CHECK(MaxL.size() == 32); BOOST_CHECK(R1L.GetLow64() == R1LLow64); BOOST_CHECK(HalfL.GetLow64() == 0x0000000000000000ULL); BOOST_CHECK(OneL.GetLow64() == 0x0000000000000001ULL); for (unsigned int i = 0; i < 255; ++i) { BOOST_CHECK((OneL << i).getdouble() == ldexp(1.0, i)); } BOOST_CHECK(ZeroL.getdouble() == 0.0); for (int i = 256; i > 53; --i) BOOST_CHECK( almostEqual((R1L >> (256 - i)).getdouble(), ldexp(R1Ldouble, i))); uint64_t R1L64part = (R1L >> 192).GetLow64(); for (int i = 53; i > 0; --i) // doubles can store all integers in {0,...,2^54-1} exactly { BOOST_CHECK((R1L >> (256 - i)).getdouble() == (double)(R1L64part >> (64 - i))); } } BOOST_AUTO_TEST_CASE(bignum_SetCompact) { arith_uint256 num; bool fNegative; bool fOverflow; num.SetCompact(0, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); BOOST_CHECK_EQUAL(num.GetCompact(), 0U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x00123456, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); BOOST_CHECK_EQUAL(num.GetCompact(), 0U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x01003456, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); BOOST_CHECK_EQUAL(num.GetCompact(), 0U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x02000056, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); BOOST_CHECK_EQUAL(num.GetCompact(), 0U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x03000000, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); BOOST_CHECK_EQUAL(num.GetCompact(), 0U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x04000000, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); BOOST_CHECK_EQUAL(num.GetCompact(), 0U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x00923456, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); BOOST_CHECK_EQUAL(num.GetCompact(), 0U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x01803456, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); BOOST_CHECK_EQUAL(num.GetCompact(), 0U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x02800056, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); BOOST_CHECK_EQUAL(num.GetCompact(), 0U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x03800000, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); BOOST_CHECK_EQUAL(num.GetCompact(), 0U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x04800000, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); BOOST_CHECK_EQUAL(num.GetCompact(), 0U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x01123456, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000012"); BOOST_CHECK_EQUAL(num.GetCompact(), 0x01120000U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); // Make sure that we don't generate compacts with the 0x00800000 bit set num = 0x80; BOOST_CHECK_EQUAL(num.GetCompact(), 0x02008000U); num.SetCompact(0x01fedcba, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "000000000000000000000000000000000000000000000000000000000000007e"); BOOST_CHECK_EQUAL(num.GetCompact(true), 0x01fe0000U); BOOST_CHECK_EQUAL(fNegative, true); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x02123456, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000001234"); BOOST_CHECK_EQUAL(num.GetCompact(), 0x02123400U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x03123456, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000123456"); BOOST_CHECK_EQUAL(num.GetCompact(), 0x03123456U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x04123456, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000012345600"); BOOST_CHECK_EQUAL(num.GetCompact(), 0x04123456U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x04923456, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000012345600"); BOOST_CHECK_EQUAL(num.GetCompact(true), 0x04923456U); BOOST_CHECK_EQUAL(fNegative, true); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x05009234, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000092340000"); BOOST_CHECK_EQUAL(num.GetCompact(), 0x05009234U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x20123456, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "1234560000000000000000000000000000000000000000000000000000000000"); BOOST_CHECK_EQUAL(num.GetCompact(), 0x20123456U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0xff123456, &fNegative, &fOverflow); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, true); } // some more tests just to get 100% coverage BOOST_AUTO_TEST_CASE(getmaxcoverage) { // ~R1L give a base_uint<256> BOOST_CHECK((~~R1L >> 10) == (R1L >> 10)); BOOST_CHECK((~~R1L << 10) == (R1L << 10)); BOOST_CHECK(!(~~R1L < R1L)); BOOST_CHECK(~~R1L <= R1L); BOOST_CHECK(!(~~R1L > R1L)); BOOST_CHECK(~~R1L >= R1L); BOOST_CHECK(!(R1L < ~~R1L)); BOOST_CHECK(R1L <= ~~R1L); BOOST_CHECK(!(R1L > ~~R1L)); BOOST_CHECK(R1L >= ~~R1L); BOOST_CHECK(~~R1L + R2L == R1L + ~~R2L); BOOST_CHECK(~~R1L - R2L == R1L - ~~R2L); BOOST_CHECK(~R1L != R1L); BOOST_CHECK(R1L != ~R1L); uint8_t TmpArray[32]; CHECKBITWISEOPERATOR(~R1, R2, |) CHECKBITWISEOPERATOR(~R1, R2, ^) CHECKBITWISEOPERATOR(~R1, R2, &) CHECKBITWISEOPERATOR(R1, ~R2, |) CHECKBITWISEOPERATOR(R1, ~R2, ^) CHECKBITWISEOPERATOR(R1, ~R2, &) } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json index 68e13eef63..d26fc1bd8b 100644 --- a/src/test/data/script_tests.json +++ b/src/test/data/script_tests.json @@ -1,3476 +1,3476 @@ [ ["Format is: [[wit..., amount]?, scriptSig, scriptPubKey, flags, expected_scripterror, ... comments]"], ["It is evaluated as if there was a crediting coinbase transaction with two 0"], ["pushes as scriptSig, and one output of 0 satoshi and given scriptPubKey,"], ["followed by a spending transaction which spends this output as only input (and"], ["correct prevout hash), using the given scriptSig. All nLockTimes are 0, all"], ["nSequences are max."], ["", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "Test the test: we should have an empty stack after scriptSig evaluation"], [" ", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "and multiple spaces should not change that."], [" ", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], [" ", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["1 2", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "OK", "Similarly whitespace around and between symbols"], ["1 2", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "OK"], [" 1 2", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "OK"], ["1 2 ", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "OK"], [" 1 2 ", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "OK"], ["1", "", "P2SH,STRICTENC", "OK"], ["0x02 0x0100", "", "P2SH,STRICTENC", "OK", "all bytes are significant, not only the last one"], ["0x09 0x000000000000000010", "", "P2SH,STRICTENC", "OK", "equals zero when cast to Int64"], ["0x01 0x0b", "11 EQUAL", "P2SH,STRICTENC", "OK", "push 1 byte"], ["0x02 0x417a", "'Az' EQUAL", "P2SH,STRICTENC", "OK"], ["0x4b 0x417a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a", "'Azzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' EQUAL", "P2SH,STRICTENC", "OK", "push 75 bytes"], ["PUSHDATA1 0x01 0x07","7 EQUAL", "P2SH,STRICTENC", "OK"], ["PUSHDATA2 0x0100 0x08","8 EQUAL", "P2SH,STRICTENC", "OK"], ["PUSHDATA4 0x01000000 0x09","9 EQUAL", "P2SH,STRICTENC", "OK"], ["PUSHDATA1 0x00","0 EQUAL", "P2SH,STRICTENC", "OK"], ["PUSHDATA2 0x0000","0 EQUAL", "P2SH,STRICTENC", "OK"], ["PUSHDATA4 0x00000000","0 EQUAL", "P2SH,STRICTENC", "OK"], ["0x4f 1000 ADD","999 EQUAL", "P2SH,STRICTENC", "OK"], ["0", "IF 0x50 ENDIF 1", "P2SH,STRICTENC", "OK", "0x50 is reserved (ok if not executed)"], ["0x51", "0x5f ADD 0x60 EQUAL", "P2SH,STRICTENC", "OK", "0x51 through 0x60 push 1 through 16 onto stack"], ["1","NOP", "P2SH,STRICTENC", "OK"], ["0", "IF VER ELSE 1 ENDIF", "P2SH,STRICTENC", "OK", "VER non-functional (ok if not executed)"], ["0", "IF RESERVED RESERVED1 RESERVED2 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK", "RESERVED ok in un-executed IF"], ["1", "DUP IF ENDIF", "P2SH,STRICTENC", "OK"], ["1", "IF 1 ENDIF", "P2SH,STRICTENC", "OK"], ["1", "DUP IF ELSE ENDIF", "P2SH,STRICTENC", "OK"], ["1", "IF 1 ELSE ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["1 1", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "OK"], ["1 0", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "OK"], ["1 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "OK"], ["0 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "OK"], ["1 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "OK"], ["1 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "OK"], ["1 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "OK"], ["0 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0 ELSE 1 ELSE 0 ENDIF", "P2SH,STRICTENC", "OK", "Multiple ELSE's are valid and executed inverts on each ELSE encountered"], ["1", "IF 1 ELSE 0 ELSE ENDIF", "P2SH,STRICTENC", "OK"], ["1", "IF ELSE 0 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["1", "IF 1 ELSE 0 ELSE 1 ENDIF ADD 2 EQUAL", "P2SH,STRICTENC", "OK"], ["'' 1", "IF SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ENDIF 0x14 0x68ca4fec736264c13b859bac43d5173df6871682 EQUAL", "P2SH,STRICTENC", "OK"], ["1", "NOTIF 0 ELSE 1 ELSE 0 ENDIF", "P2SH,STRICTENC", "OK", "Multiple ELSE's are valid and execution inverts on each ELSE encountered"], ["0", "NOTIF 1 ELSE 0 ELSE ENDIF", "P2SH,STRICTENC", "OK"], ["0", "NOTIF ELSE 0 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "NOTIF 1 ELSE 0 ELSE 1 ENDIF ADD 2 EQUAL", "P2SH,STRICTENC", "OK"], ["'' 0", "NOTIF SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ENDIF 0x14 0x68ca4fec736264c13b859bac43d5173df6871682 EQUAL", "P2SH,STRICTENC", "OK"], ["0", "IF 1 IF RETURN ELSE RETURN ELSE RETURN ENDIF ELSE 1 IF 1 ELSE RETURN ELSE 1 ENDIF ELSE RETURN ENDIF ADD 2 EQUAL", "P2SH,STRICTENC", "OK", "Nested ELSE ELSE"], ["1", "NOTIF 0 NOTIF RETURN ELSE RETURN ELSE RETURN ENDIF ELSE 0 NOTIF 1 ELSE RETURN ELSE 1 ENDIF ELSE RETURN ENDIF ADD 2 EQUAL", "P2SH,STRICTENC", "OK"], ["0", "IF RETURN ENDIF 1", "P2SH,STRICTENC", "OK", "RETURN only works if executed"], ["1 1", "VERIFY", "P2SH,STRICTENC", "OK"], ["1 0x05 0x0100000000", "VERIFY", "P2SH,STRICTENC", "OK", "values >4 bytes can be cast to boolean"], ["1 0x01 0x80", "IF 0 ENDIF", "P2SH,STRICTENC", "OK", "negative 0 is false"], ["10 0 11 TOALTSTACK DROP FROMALTSTACK", "ADD 21 EQUAL", "P2SH,STRICTENC", "OK"], ["'gavin_was_here' TOALTSTACK 11 FROMALTSTACK", "'gavin_was_here' EQUALVERIFY 11 EQUAL", "P2SH,STRICTENC", "OK"], ["0 IFDUP", "DEPTH 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC", "OK"], ["1 IFDUP", "DEPTH 2 EQUALVERIFY 1 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "OK"], ["0x05 0x0100000000 IFDUP", "DEPTH 2 EQUALVERIFY 0x05 0x0100000000 EQUAL", "P2SH,STRICTENC", "OK", "IFDUP dups non ints"], ["0 DROP", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["0", "DUP 1 ADD 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC", "OK"], ["0 1", "NIP", "P2SH,STRICTENC", "OK"], ["1 0", "OVER DEPTH 3 EQUALVERIFY", "P2SH,STRICTENC", "OK"], ["22 21 20", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "OK"], ["22 21 20", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "OK"], ["22 21 20", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "OK"], ["22 21 20", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "OK"], ["22 21 20", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "OK"], ["22 21 20", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "OK"], ["22 21 20", "ROT 22 EQUAL", "P2SH,STRICTENC", "OK"], ["22 21 20", "ROT DROP 20 EQUAL", "P2SH,STRICTENC", "OK"], ["22 21 20", "ROT DROP DROP 21 EQUAL", "P2SH,STRICTENC", "OK"], ["22 21 20", "ROT ROT 21 EQUAL", "P2SH,STRICTENC", "OK"], ["22 21 20", "ROT ROT ROT 20 EQUAL", "P2SH,STRICTENC", "OK"], ["25 24 23 22 21 20", "2ROT 24 EQUAL", "P2SH,STRICTENC", "OK"], ["25 24 23 22 21 20", "2ROT DROP 25 EQUAL", "P2SH,STRICTENC", "OK"], ["25 24 23 22 21 20", "2ROT 2DROP 20 EQUAL", "P2SH,STRICTENC", "OK"], ["25 24 23 22 21 20", "2ROT 2DROP DROP 21 EQUAL", "P2SH,STRICTENC", "OK"], ["25 24 23 22 21 20", "2ROT 2DROP 2DROP 22 EQUAL", "P2SH,STRICTENC", "OK"], ["25 24 23 22 21 20", "2ROT 2DROP 2DROP DROP 23 EQUAL", "P2SH,STRICTENC", "OK"], ["25 24 23 22 21 20", "2ROT 2ROT 22 EQUAL", "P2SH,STRICTENC", "OK"], ["25 24 23 22 21 20", "2ROT 2ROT 2ROT 20 EQUAL", "P2SH,STRICTENC", "OK"], ["1 0", "SWAP 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC", "OK"], ["0 1", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP", "P2SH,STRICTENC", "OK"], ["13 14", "2DUP ROT EQUALVERIFY EQUAL", "P2SH,STRICTENC", "OK"], ["-1 0 1 2", "3DUP DEPTH 7 EQUALVERIFY ADD ADD 3 EQUALVERIFY 2DROP 0 EQUALVERIFY", "P2SH,STRICTENC", "OK"], ["1 2 3 5", "2OVER ADD ADD 8 EQUALVERIFY ADD ADD 6 EQUAL", "P2SH,STRICTENC", "OK"], ["1 3 5 7", "2SWAP ADD 4 EQUALVERIFY ADD 12 EQUAL", "P2SH,STRICTENC", "OK"], ["0", "SIZE 0 EQUAL", "P2SH,STRICTENC", "OK"], ["1", "SIZE 1 EQUAL", "P2SH,STRICTENC", "OK"], ["127", "SIZE 1 EQUAL", "P2SH,STRICTENC", "OK"], ["128", "SIZE 2 EQUAL", "P2SH,STRICTENC", "OK"], ["32767", "SIZE 2 EQUAL", "P2SH,STRICTENC", "OK"], ["32768", "SIZE 3 EQUAL", "P2SH,STRICTENC", "OK"], ["8388607", "SIZE 3 EQUAL", "P2SH,STRICTENC", "OK"], ["8388608", "SIZE 4 EQUAL", "P2SH,STRICTENC", "OK"], ["2147483647", "SIZE 4 EQUAL", "P2SH,STRICTENC", "OK"], ["2147483648", "SIZE 5 EQUAL", "P2SH,STRICTENC", "OK"], ["549755813887", "SIZE 5 EQUAL", "P2SH,STRICTENC", "OK"], ["549755813888", "SIZE 6 EQUAL", "P2SH,STRICTENC", "OK"], ["9223372036854775807", "SIZE 8 EQUAL", "P2SH,STRICTENC", "OK"], ["-1", "SIZE 1 EQUAL", "P2SH,STRICTENC", "OK"], ["-127", "SIZE 1 EQUAL", "P2SH,STRICTENC", "OK"], ["-128", "SIZE 2 EQUAL", "P2SH,STRICTENC", "OK"], ["-32767", "SIZE 2 EQUAL", "P2SH,STRICTENC", "OK"], ["-32768", "SIZE 3 EQUAL", "P2SH,STRICTENC", "OK"], ["-8388607", "SIZE 3 EQUAL", "P2SH,STRICTENC", "OK"], ["-8388608", "SIZE 4 EQUAL", "P2SH,STRICTENC", "OK"], ["-2147483647", "SIZE 4 EQUAL", "P2SH,STRICTENC", "OK"], ["-2147483648", "SIZE 5 EQUAL", "P2SH,STRICTENC", "OK"], ["-549755813887", "SIZE 5 EQUAL", "P2SH,STRICTENC", "OK"], ["-549755813888", "SIZE 6 EQUAL", "P2SH,STRICTENC", "OK"], ["-9223372036854775807", "SIZE 8 EQUAL", "P2SH,STRICTENC", "OK"], ["'abcdefghijklmnopqrstuvwxyz'", "SIZE 26 EQUAL", "P2SH,STRICTENC", "OK"], ["42", "SIZE 1 EQUALVERIFY 42 EQUAL", "P2SH,STRICTENC", "OK", "SIZE does not consume argument"], ["2 -2 ADD", "0 EQUAL", "P2SH,STRICTENC", "OK"], ["2147483647 -2147483647 ADD", "0 EQUAL", "P2SH,STRICTENC", "OK"], ["-1 -1 ADD", "-2 EQUAL", "P2SH,STRICTENC", "OK"], ["0 0","EQUAL", "P2SH,STRICTENC", "OK"], ["1 1 ADD", "2 EQUAL", "P2SH,STRICTENC", "OK"], ["1 1ADD", "2 EQUAL", "P2SH,STRICTENC", "OK"], ["111 1SUB", "110 EQUAL", "P2SH,STRICTENC", "OK"], ["111 1 ADD 12 SUB", "100 EQUAL", "P2SH,STRICTENC", "OK"], ["0 ABS", "0 EQUAL", "P2SH,STRICTENC", "OK"], ["16 ABS", "16 EQUAL", "P2SH,STRICTENC", "OK"], ["-16 ABS", "-16 NEGATE EQUAL", "P2SH,STRICTENC", "OK"], ["0 NOT", "NOP", "P2SH,STRICTENC", "OK"], ["1 NOT", "0 EQUAL", "P2SH,STRICTENC", "OK"], ["11 NOT", "0 EQUAL", "P2SH,STRICTENC", "OK"], ["0 0NOTEQUAL", "0 EQUAL", "P2SH,STRICTENC", "OK"], ["1 0NOTEQUAL", "1 EQUAL", "P2SH,STRICTENC", "OK"], ["111 0NOTEQUAL", "1 EQUAL", "P2SH,STRICTENC", "OK"], ["-111 0NOTEQUAL", "1 EQUAL", "P2SH,STRICTENC", "OK"], ["1 1 BOOLAND", "NOP", "P2SH,STRICTENC", "OK"], ["1 0 BOOLAND", "NOT", "P2SH,STRICTENC", "OK"], ["0 1 BOOLAND", "NOT", "P2SH,STRICTENC", "OK"], ["0 0 BOOLAND", "NOT", "P2SH,STRICTENC", "OK"], ["16 17 BOOLAND", "NOP", "P2SH,STRICTENC", "OK"], ["1 1 BOOLOR", "NOP", "P2SH,STRICTENC", "OK"], ["1 0 BOOLOR", "NOP", "P2SH,STRICTENC", "OK"], ["0 1 BOOLOR", "NOP", "P2SH,STRICTENC", "OK"], ["0 0 BOOLOR", "NOT", "P2SH,STRICTENC", "OK"], ["0x01 0x80", "DUP BOOLOR", "P2SH,STRICTENC", "EVAL_FALSE", "negative-0 negative-0 BOOLOR"], ["0x01 0x00", "DUP BOOLOR", "P2SH,STRICTENC", "EVAL_FALSE", " non-minimal-0 non-minimal-0 BOOLOR"], ["0x01 0x81", "DUP BOOLOR", "P2SH,STRICTENC", "OK", "-1 -1 BOOLOR"], ["0x01 0x80", "DUP BOOLAND", "P2SH,STRICTENC", "EVAL_FALSE", "negative-0 negative-0 BOOLAND"], ["0x01 0x00", "DUP BOOLAND", "P2SH,STRICTENC", "EVAL_FALSE", " non-minimal-0 non-minimal-0 BOOLAND"], ["0x01 0x81", "DUP BOOLAND", "P2SH,STRICTENC", "OK", "-1 -1 BOOLAND"], ["0x01 0x00", "NOT", "P2SH,STRICTENC", "OK", "non-minimal-0 NOT"], ["0x01 0x80", "NOT", "P2SH,STRICTENC", "OK", "negative-0 NOT"], ["0x01 0x81", "NOT", "P2SH,STRICTENC", "EVAL_FALSE", "negative 1 NOT"], ["0x01 0x80 0", "NUMEQUAL", "P2SH", "OK", "-0 0 NUMEQUAL"], ["0x01 0x00 0", "NUMEQUAL", "P2SH", "OK", "non-minimal-0 0 NUMEQUAL"], ["0x02 0x0000 0", "NUMEQUAL", "P2SH", "OK", "non-minimal-0 0 NUMEQUAL"], ["16 17 BOOLOR", "NOP", "P2SH,STRICTENC", "OK"], ["11 10 1 ADD", "NUMEQUAL", "P2SH,STRICTENC", "OK"], ["11 10 1 ADD", "NUMEQUALVERIFY 1", "P2SH,STRICTENC", "OK"], ["11 10 1 ADD", "NUMNOTEQUAL NOT", "P2SH,STRICTENC", "OK"], ["111 10 1 ADD", "NUMNOTEQUAL", "P2SH,STRICTENC", "OK"], ["11 10", "LESSTHAN NOT", "P2SH,STRICTENC", "OK"], ["4 4", "LESSTHAN NOT", "P2SH,STRICTENC", "OK"], ["10 11", "LESSTHAN", "P2SH,STRICTENC", "OK"], ["-11 11", "LESSTHAN", "P2SH,STRICTENC", "OK"], ["-11 -10", "LESSTHAN", "P2SH,STRICTENC", "OK"], ["11 10", "GREATERTHAN", "P2SH,STRICTENC", "OK"], ["4 4", "GREATERTHAN NOT", "P2SH,STRICTENC", "OK"], ["10 11", "GREATERTHAN NOT", "P2SH,STRICTENC", "OK"], ["-11 11", "GREATERTHAN NOT", "P2SH,STRICTENC", "OK"], ["-11 -10", "GREATERTHAN NOT", "P2SH,STRICTENC", "OK"], ["11 10", "LESSTHANOREQUAL NOT", "P2SH,STRICTENC", "OK"], ["4 4", "LESSTHANOREQUAL", "P2SH,STRICTENC", "OK"], ["10 11", "LESSTHANOREQUAL", "P2SH,STRICTENC", "OK"], ["-11 11", "LESSTHANOREQUAL", "P2SH,STRICTENC", "OK"], ["-11 -10", "LESSTHANOREQUAL", "P2SH,STRICTENC", "OK"], ["11 10", "GREATERTHANOREQUAL", "P2SH,STRICTENC", "OK"], ["4 4", "GREATERTHANOREQUAL", "P2SH,STRICTENC", "OK"], ["10 11", "GREATERTHANOREQUAL NOT", "P2SH,STRICTENC", "OK"], ["-11 11", "GREATERTHANOREQUAL NOT", "P2SH,STRICTENC", "OK"], ["-11 -10", "GREATERTHANOREQUAL NOT", "P2SH,STRICTENC", "OK"], ["1 0 MIN", "0 NUMEQUAL", "P2SH,STRICTENC", "OK"], ["0 1 MIN", "0 NUMEQUAL", "P2SH,STRICTENC", "OK"], ["-1 0 MIN", "-1 NUMEQUAL", "P2SH,STRICTENC", "OK"], ["0 -2147483647 MIN", "-2147483647 NUMEQUAL", "P2SH,STRICTENC", "OK"], ["2147483647 0 MAX", "2147483647 NUMEQUAL", "P2SH,STRICTENC", "OK"], ["0 100 MAX", "100 NUMEQUAL", "P2SH,STRICTENC", "OK"], ["-100 0 MAX", "0 NUMEQUAL", "P2SH,STRICTENC", "OK"], ["0 -2147483647 MAX", "0 NUMEQUAL", "P2SH,STRICTENC", "OK"], ["0 0 1", "WITHIN", "P2SH,STRICTENC", "OK"], ["1 0 1", "WITHIN NOT", "P2SH,STRICTENC", "OK"], ["0 -2147483647 2147483647", "WITHIN", "P2SH,STRICTENC", "OK"], ["-1 -100 100", "WITHIN", "P2SH,STRICTENC", "OK"], ["11 -100 100", "WITHIN", "P2SH,STRICTENC", "OK"], ["-2147483647 -100 100", "WITHIN NOT", "P2SH,STRICTENC", "OK"], ["2147483647 -100 100", "WITHIN NOT", "P2SH,STRICTENC", "OK"], ["2147483647 2147483647 SUB", "0 EQUAL", "P2SH,STRICTENC", "OK"], ["2147483647 DUP ADD", "4294967294 EQUAL", "P2SH,STRICTENC", "OK", ">32 bit EQUAL is valid"], ["2147483647 NEGATE DUP ADD", "-4294967294 EQUAL", "P2SH,STRICTENC", "OK"], ["''", "RIPEMD160 0x14 0x9c1185a5c5e9fc54612808977ee8f548b2258d31 EQUAL", "P2SH,STRICTENC", "OK"], ["'a'", "RIPEMD160 0x14 0x0bdc9d2d256b3ee9daae347be6f4dc835a467ffe EQUAL", "P2SH,STRICTENC", "OK"], ["'abcdefghijklmnopqrstuvwxyz'", "RIPEMD160 0x14 0xf71c27109c692c1b56bbdceb5b9d2865b3708dbc EQUAL", "P2SH,STRICTENC", "OK"], ["''", "SHA1 0x14 0xda39a3ee5e6b4b0d3255bfef95601890afd80709 EQUAL", "P2SH,STRICTENC", "OK"], ["'a'", "SHA1 0x14 0x86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 EQUAL", "P2SH,STRICTENC", "OK"], ["'abcdefghijklmnopqrstuvwxyz'", "SHA1 0x14 0x32d10c7b8cf96570ca04ce37f2a19d84240d3a89 EQUAL", "P2SH,STRICTENC", "OK"], ["''", "SHA256 0x20 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 EQUAL", "P2SH,STRICTENC", "OK"], ["'a'", "SHA256 0x20 0xca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb EQUAL", "P2SH,STRICTENC", "OK"], ["'abcdefghijklmnopqrstuvwxyz'", "SHA256 0x20 0x71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73 EQUAL", "P2SH,STRICTENC", "OK"], ["''", "DUP HASH160 SWAP SHA256 RIPEMD160 EQUAL", "P2SH,STRICTENC", "OK"], ["''", "DUP HASH256 SWAP SHA256 SHA256 EQUAL", "P2SH,STRICTENC", "OK"], ["''", "NOP HASH160 0x14 0xb472a266d0bd89c13706a4132ccfb16f7c3b9fcb EQUAL", "P2SH,STRICTENC", "OK"], ["'a'", "HASH160 NOP 0x14 0x994355199e516ff76c4fa4aab39337b9d84cf12b EQUAL", "P2SH,STRICTENC", "OK"], ["'abcdefghijklmnopqrstuvwxyz'", "HASH160 PUSHDATA1 0x14 0xc286a1af0947f58d1ad787385b1c2c4a976f9e71 EQUAL", "P2SH,STRICTENC", "OK"], ["''", "HASH256 0x20 0x5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456 EQUAL", "P2SH,STRICTENC", "OK"], ["'a'", "HASH256 0x20 0xbf5d3affb73efd2ec6c36ad3112dd933efed63c4e1cbffcfa88e2759c144f2d8 EQUAL", "P2SH,STRICTENC", "OK"], ["'abcdefghijklmnopqrstuvwxyz'", "HASH256 PUSHDATA1 0x20 0xca139bc10c2f660da42666f72e89a225936fc60f193c161124a672050c434671 EQUAL", "P2SH,STRICTENC", "OK"], ["1","NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 1 EQUAL", "P2SH,STRICTENC", "OK"], ["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_10' EQUAL", "P2SH,STRICTENC", "OK"], ["1", "NOP", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS", "OK", "Discourage NOPx flag allows OP_NOP"], ["0", "IF NOP10 ENDIF 1", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS", "OK", "Discouraged NOPs are allowed if not executed"], ["0", "IF CHECKDATASIG ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF CHECKDATASIG ELSE 1 ENDIF", "P2SH,STRICTENC,CHECKDATASIG", "OK"], ["0", "IF CHECKDATASIGVERIFY ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF CHECKDATASIGVERIFY ELSE 1 ENDIF", "P2SH,STRICTENC,CHECKDATASIG", "OK"], ["0", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC", "OK", "opcodes >= FIRST_UNDEFINED_OP_VALUE invalid if executed"], ["0", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xc0 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xc1 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xc2 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xc3 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xc4 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xc5 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xc6 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xc7 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xc8 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xc9 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xca ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xcb ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xcc ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xcd ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xce ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xcf ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xd0 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xd1 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xd2 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xd3 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xd4 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xd5 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xd6 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xd7 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xd8 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xd9 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xda ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xdb ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xdc ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xdd ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xde ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xdf ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xe0 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xe1 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xe2 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xe3 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xe4 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xe5 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xe6 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xe7 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xe8 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xe9 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xea ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xeb ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xec ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xed ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xee ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xef ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xf0 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xf1 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xf2 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xf3 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xf4 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xf5 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xf6 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xf7 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xf8 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xf9 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xfa ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xfb ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xfc ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xfd ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xfe ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xff ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["NOP", "'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'", "P2SH,STRICTENC", "OK", "520 byte push"], ["1", "0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "P2SH,STRICTENC", "OK", "201 opcodes executed. 0x61 is NOP"], ["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", "1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", "P2SH,STRICTENC", "OK", "1,000 stack size (0x6f is 3DUP)"], ["1 TOALTSTACK 2 TOALTSTACK 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", "1 2 3 4 5 6 7 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", "P2SH,STRICTENC", "OK", "1,000 stack size (altstack cleared between scriptSig/scriptPubKey)"], ["'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", "'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f 2DUP 0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "P2SH,STRICTENC", "OK", "Max-size (10,000-byte), max-push(520 bytes), max-opcodes(201), max stack size(1,000 items). 0x6f is 3DUP, 0x61 is NOP"], ["0", "IF 0x5050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050 ENDIF 1", "P2SH,STRICTENC", "OK", ">201 opcodes, but RESERVED (0x50) doesn't count towards opcode limit."], ["NOP","1", "P2SH,STRICTENC", "OK"], ["1", "0x01 0x01 EQUAL", "P2SH,STRICTENC", "OK", "The following is useful for checking implementations of BN_bn2mpi"], ["127", "0x01 0x7F EQUAL", "P2SH,STRICTENC", "OK"], ["128", "0x02 0x8000 EQUAL", "P2SH,STRICTENC", "OK", "Leave room for the sign bit"], ["32767", "0x02 0xFF7F EQUAL", "P2SH,STRICTENC", "OK"], ["32768", "0x03 0x008000 EQUAL", "P2SH,STRICTENC", "OK"], ["8388607", "0x03 0xFFFF7F EQUAL", "P2SH,STRICTENC", "OK"], ["8388608", "0x04 0x00008000 EQUAL", "P2SH,STRICTENC", "OK"], ["2147483647", "0x04 0xFFFFFF7F EQUAL", "P2SH,STRICTENC", "OK"], ["2147483648", "0x05 0x0000008000 EQUAL", "P2SH,STRICTENC", "OK"], ["549755813887", "0x05 0xFFFFFFFF7F EQUAL", "P2SH,STRICTENC", "OK"], ["549755813888", "0x06 0x000000008000 EQUAL", "P2SH,STRICTENC", "OK"], ["9223372036854775807", "0x08 0xFFFFFFFFFFFFFF7F EQUAL", "P2SH,STRICTENC", "OK"], ["-1", "0x01 0x81 EQUAL", "P2SH,STRICTENC", "OK", "Numbers are little-endian with the MSB being a sign bit"], ["-127", "0x01 0xFF EQUAL", "P2SH,STRICTENC", "OK"], ["-128", "0x02 0x8080 EQUAL", "P2SH,STRICTENC", "OK"], ["-32767", "0x02 0xFFFF EQUAL", "P2SH,STRICTENC", "OK"], ["-32768", "0x03 0x008080 EQUAL", "P2SH,STRICTENC", "OK"], ["-8388607", "0x03 0xFFFFFF EQUAL", "P2SH,STRICTENC", "OK"], ["-8388608", "0x04 0x00008080 EQUAL", "P2SH,STRICTENC", "OK"], ["-2147483647", "0x04 0xFFFFFFFF EQUAL", "P2SH,STRICTENC", "OK"], ["-2147483648", "0x05 0x0000008080 EQUAL", "P2SH,STRICTENC", "OK"], ["-4294967295", "0x05 0xFFFFFFFF80 EQUAL", "P2SH,STRICTENC", "OK"], ["-549755813887", "0x05 0xFFFFFFFFFF EQUAL", "P2SH,STRICTENC", "OK"], ["-549755813888", "0x06 0x000000008080 EQUAL", "P2SH,STRICTENC", "OK"], ["-9223372036854775807", "0x08 0xFFFFFFFFFFFFFFFF EQUAL", "P2SH,STRICTENC", "OK"], ["2147483647", "1ADD 2147483648 EQUAL", "P2SH,STRICTENC", "OK", "We can do math on 4-byte integers, and compare 5-byte ones"], ["2147483647", "1ADD 1", "P2SH,STRICTENC", "OK"], ["-2147483647", "1ADD 1", "P2SH,STRICTENC", "OK"], ["1", "0x02 0x0100 EQUAL NOT", "P2SH,STRICTENC", "OK", "Not the same byte array..."], ["1", "0x02 0x0100 NUMEQUAL", "P2SH,STRICTENC", "OK", "... but they are numerically equal"], ["11", "PUSHDATA1 0x03 0x0b0000 NUMEQUAL", "P2SH,STRICTENC", "OK"], ["0", "0x01 0x80 EQUAL NOT", "P2SH,STRICTENC", "OK"], ["0", "0x01 0x80 NUMEQUAL", "P2SH,STRICTENC", "OK", "Zero numerically equals negative zero"], ["0", "0x02 0x0080 NUMEQUAL", "P2SH,STRICTENC", "OK"], ["0x03 0x000080", "0x04 0x00000080 NUMEQUAL", "P2SH,STRICTENC", "OK"], ["0x03 0x100080", "0x04 0x10000080 NUMEQUAL", "P2SH,STRICTENC", "OK"], ["0x03 0x100000", "0x04 0x10000000 NUMEQUAL", "P2SH,STRICTENC", "OK"], ["NOP", "NOP 1", "P2SH,STRICTENC", "OK", "The following tests check the if(stack.size() < N) tests in each opcode"], ["1", "IF 1 ENDIF", "P2SH,STRICTENC", "OK", "They are here to catch copy-and-paste errors"], ["0", "NOTIF 1 ENDIF", "P2SH,STRICTENC", "OK", "Most of them are duplicated elsewhere,"], ["1", "VERIFY 1", "P2SH,STRICTENC", "OK", "but, hey, more is always better, right?"], ["0", "TOALTSTACK 1", "P2SH,STRICTENC", "OK"], ["1", "TOALTSTACK FROMALTSTACK", "P2SH,STRICTENC", "OK"], ["0 0", "2DROP 1", "P2SH,STRICTENC", "OK"], ["0 1", "2DUP", "P2SH,STRICTENC", "OK"], ["0 0 1", "3DUP", "P2SH,STRICTENC", "OK"], ["0 1 0 0", "2OVER", "P2SH,STRICTENC", "OK"], ["0 1 0 0 0 0", "2ROT", "P2SH,STRICTENC", "OK"], ["0 1 0 0", "2SWAP", "P2SH,STRICTENC", "OK"], ["1", "IFDUP", "P2SH,STRICTENC", "OK"], ["NOP", "DEPTH 1", "P2SH,STRICTENC", "OK"], ["0", "DROP 1", "P2SH,STRICTENC", "OK"], ["1", "DUP", "P2SH,STRICTENC", "OK"], ["0 1", "NIP", "P2SH,STRICTENC", "OK"], ["1 0", "OVER", "P2SH,STRICTENC", "OK"], ["1 0 0 0 3", "PICK", "P2SH,STRICTENC", "OK"], ["1 0", "PICK", "P2SH,STRICTENC", "OK"], ["1 0 0 0 3", "ROLL", "P2SH,STRICTENC", "OK"], ["1 0", "ROLL", "P2SH,STRICTENC", "OK"], ["1 0 0", "ROT", "P2SH,STRICTENC", "OK"], ["1 0", "SWAP", "P2SH,STRICTENC", "OK"], ["0 1", "TUCK", "P2SH,STRICTENC", "OK"], ["1", "SIZE", "P2SH,STRICTENC", "OK"], ["0 0", "EQUAL", "P2SH,STRICTENC", "OK"], ["0 0", "EQUALVERIFY 1", "P2SH,STRICTENC", "OK"], ["0 0 1", "EQUAL EQUAL", "P2SH,STRICTENC", "OK", "OP_0 and bools must have identical byte representations"], ["0", "1ADD", "P2SH,STRICTENC", "OK"], ["2", "1SUB", "P2SH,STRICTENC", "OK"], ["-1", "NEGATE", "P2SH,STRICTENC", "OK"], ["-1", "ABS", "P2SH,STRICTENC", "OK"], ["0", "NOT", "P2SH,STRICTENC", "OK"], ["-1", "0NOTEQUAL", "P2SH,STRICTENC", "OK"], ["1 0", "ADD", "P2SH,STRICTENC", "OK"], ["1 0", "SUB", "P2SH,STRICTENC", "OK"], ["-1 -1", "BOOLAND", "P2SH,STRICTENC", "OK"], ["-1 0", "BOOLOR", "P2SH,STRICTENC", "OK"], ["0 0", "NUMEQUAL", "P2SH,STRICTENC", "OK"], ["0 0", "NUMEQUALVERIFY 1", "P2SH,STRICTENC", "OK"], ["-1 0", "NUMNOTEQUAL", "P2SH,STRICTENC", "OK"], ["-1 0", "LESSTHAN", "P2SH,STRICTENC", "OK"], ["1 0", "GREATERTHAN", "P2SH,STRICTENC", "OK"], ["0 0", "LESSTHANOREQUAL", "P2SH,STRICTENC", "OK"], ["0 0", "GREATERTHANOREQUAL", "P2SH,STRICTENC", "OK"], ["-1 0", "MIN", "P2SH,STRICTENC", "OK"], ["1 0", "MAX", "P2SH,STRICTENC", "OK"], ["-1 -1 0", "WITHIN", "P2SH,STRICTENC", "OK"], ["0", "RIPEMD160", "P2SH,STRICTENC", "OK"], ["0", "SHA1", "P2SH,STRICTENC", "OK"], ["0", "SHA256", "P2SH,STRICTENC", "OK"], ["0", "HASH160", "P2SH,STRICTENC", "OK"], ["0", "HASH256", "P2SH,STRICTENC", "OK"], ["NOP", "CODESEPARATOR 1", "P2SH,STRICTENC", "OK"], ["NOP", "NOP1 1", "P2SH,STRICTENC", "OK"], ["NOP", "CHECKLOCKTIMEVERIFY 1", "P2SH,STRICTENC", "OK"], ["NOP", "CHECKSEQUENCEVERIFY 1", "P2SH,STRICTENC", "OK"], ["NOP", "NOP4 1", "P2SH,STRICTENC", "OK"], ["NOP", "NOP5 1", "P2SH,STRICTENC", "OK"], ["NOP", "NOP6 1", "P2SH,STRICTENC", "OK"], ["NOP", "NOP7 1", "P2SH,STRICTENC", "OK"], ["NOP", "NOP8 1", "P2SH,STRICTENC", "OK"], ["NOP", "NOP9 1", "P2SH,STRICTENC", "OK"], ["NOP", "NOP10 1", "P2SH,STRICTENC", "OK"], ["", "0 0 0 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "CHECKMULTISIG is allowed to have zero keys and/or sigs"], ["", "0 0 0 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 0 1 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "Zero sigs means no sigs are checked"], ["", "0 0 0 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 0 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "CHECKMULTISIG is allowed to have zero keys and/or sigs"], ["", "0 0 0 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 0 1 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "Zero sigs means no sigs are checked"], ["", "0 0 0 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 2 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "Test from up to 20 pubkeys, all not checked"], ["", "0 0 'a' 'b' 'c' 3 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 4 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 5 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 6 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 7 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 8 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 9 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 10 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 11 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 12 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 13 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 14 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 15 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 16 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 17 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 18 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 19 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 2 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 3 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 4 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 5 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 6 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 7 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 8 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 9 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 10 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 11 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 12 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 13 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 14 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 15 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 16 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 17 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 18 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 19 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG", "P2SH,STRICTENC", "OK", "nOpCount is incremented by the number of keys evaluated in addition to the usual one op per op. In this case we have zero keys, so we can execute 201 CHECKMULTISIGS"], ["1", "0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY", "P2SH,STRICTENC", "OK"], ["", "NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG", "P2SH,STRICTENC", "OK", "Even though there are no signatures being checked nOpCount is incremented by the number of keys."], ["1", "NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY", "P2SH,STRICTENC", "OK"], ["0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "OK", "Very basic P2SH"], ["PUSHDATA1 0x00 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "OK"], ["0x40 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242", "PUSHDATA2 0x4000 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242 EQUAL", "P2SH,STRICTENC", "OK", "Basic PUSH signedness check"], ["PUSHDATA1 0x40 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242", "PUSHDATA2 0x4000 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242 EQUAL", "P2SH,STRICTENC", "OK", "Basic PUSHDATA1 signedness check"], ["all PUSHDATA forms are equivalent"], ["PUSHDATA1 0x4b 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "0x4b 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 EQUAL", "", "OK", "PUSHDATA1 of 75 bytes equals direct push of it"], ["PUSHDATA2 0xFF00 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "PUSHDATA1 0xFF 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 EQUAL", "", "OK", "PUSHDATA2 of 255 bytes equals PUSHDATA1 of it"], ["0x00", "SIZE 0 EQUAL", "P2SH,STRICTENC", "OK", "Basic OP_0 execution"], ["Numeric pushes"], ["0x01 0x81", "0x4f EQUAL", "", "OK", "OP1_NEGATE pushes 0x81"], ["0x01 0x01", "0x51 EQUAL", "", "OK", "OP_1 pushes 0x01"], ["0x01 0x02", "0x52 EQUAL", "", "OK", "OP_2 pushes 0x02"], ["0x01 0x03", "0x53 EQUAL", "", "OK", "OP_3 pushes 0x03"], ["0x01 0x04", "0x54 EQUAL", "", "OK", "OP_4 pushes 0x04"], ["0x01 0x05", "0x55 EQUAL", "", "OK", "OP_5 pushes 0x05"], ["0x01 0x06", "0x56 EQUAL", "", "OK", "OP_6 pushes 0x06"], ["0x01 0x07", "0x57 EQUAL", "", "OK", "OP_7 pushes 0x07"], ["0x01 0x08", "0x58 EQUAL", "", "OK", "OP_8 pushes 0x08"], ["0x01 0x09", "0x59 EQUAL", "", "OK", "OP_9 pushes 0x09"], ["0x01 0x0a", "0x5a EQUAL", "", "OK", "OP_10 pushes 0x0a"], ["0x01 0x0b", "0x5b EQUAL", "", "OK", "OP_11 pushes 0x0b"], ["0x01 0x0c", "0x5c EQUAL", "", "OK", "OP_12 pushes 0x0c"], ["0x01 0x0d", "0x5d EQUAL", "", "OK", "OP_13 pushes 0x0d"], ["0x01 0x0e", "0x5e EQUAL", "", "OK", "OP_14 pushes 0x0e"], ["0x01 0x0f", "0x5f EQUAL", "", "OK", "OP_15 pushes 0x0f"], ["0x01 0x10", "0x60 EQUAL", "", "OK", "OP_16 pushes 0x10"], ["Equivalency of different numeric encodings"], ["0x02 0x8000", "128 NUMEQUAL", "", "OK", "0x8000 equals 128"], ["0x01 0x00", "0 NUMEQUAL", "", "OK", "0x00 numequals 0"], ["0x01 0x80", "0 NUMEQUAL", "", "OK", "0x80 (negative zero) numequals 0"], ["0x02 0x0080", "0 NUMEQUAL", "", "OK", "0x0080 numequals 0"], ["0x02 0x0500", "5 NUMEQUAL", "", "OK", "0x0500 numequals 5"], ["0x03 0xff7f80", "0x02 0xffff NUMEQUAL", "", "OK", ""], ["0x03 0xff7f00", "0x02 0xff7f NUMEQUAL", "", "OK", ""], ["0x04 0xffff7f80", "0x03 0xffffff NUMEQUAL", "", "OK", ""], ["0x04 0xffff7f00", "0x03 0xffff7f NUMEQUAL", "", "OK", ""], ["Unevaluated non-minimal pushes are ignored"], ["0 IF PUSHDATA1 0x00 ENDIF 1", "", "MINIMALDATA", "OK", "non-minimal PUSHDATA1 ignored"], ["0 IF PUSHDATA2 0x0000 ENDIF 1", "", "MINIMALDATA", "OK", "non-minimal PUSHDATA2 ignored"], ["0 IF PUSHDATA4 0x00000000 ENDIF 1", "", "MINIMALDATA", "OK", "non-minimal PUSHDATA4 ignored"], ["0 IF 0x01 0x81 ENDIF 1", "", "MINIMALDATA", "OK", "1NEGATE equiv"], ["0 IF 0x01 0x01 ENDIF 1", "", "MINIMALDATA", "OK", "OP_1 equiv"], ["0 IF 0x01 0x02 ENDIF 1", "", "MINIMALDATA", "OK", "OP_2 equiv"], ["0 IF 0x01 0x03 ENDIF 1", "", "MINIMALDATA", "OK", "OP_3 equiv"], ["0 IF 0x01 0x04 ENDIF 1", "", "MINIMALDATA", "OK", "OP_4 equiv"], ["0 IF 0x01 0x05 ENDIF 1", "", "MINIMALDATA", "OK", "OP_5 equiv"], ["0 IF 0x01 0x06 ENDIF 1", "", "MINIMALDATA", "OK", "OP_6 equiv"], ["0 IF 0x01 0x07 ENDIF 1", "", "MINIMALDATA", "OK", "OP_7 equiv"], ["0 IF 0x01 0x08 ENDIF 1", "", "MINIMALDATA", "OK", "OP_8 equiv"], ["0 IF 0x01 0x09 ENDIF 1", "", "MINIMALDATA", "OK", "OP_9 equiv"], ["0 IF 0x01 0x0a ENDIF 1", "", "MINIMALDATA", "OK", "OP_10 equiv"], ["0 IF 0x01 0x0b ENDIF 1", "", "MINIMALDATA", "OK", "OP_11 equiv"], ["0 IF 0x01 0x0c ENDIF 1", "", "MINIMALDATA", "OK", "OP_12 equiv"], ["0 IF 0x01 0x0d ENDIF 1", "", "MINIMALDATA", "OK", "OP_13 equiv"], ["0 IF 0x01 0x0e ENDIF 1", "", "MINIMALDATA", "OK", "OP_14 equiv"], ["0 IF 0x01 0x0f ENDIF 1", "", "MINIMALDATA", "OK", "OP_15 equiv"], ["0 IF 0x01 0x10 ENDIF 1", "", "MINIMALDATA", "OK", "OP_16 equiv"], ["Numeric minimaldata rules are only applied when a stack item is numerically evaluated; the push itself is allowed"], ["0x01 0x00", "1", "MINIMALDATA", "OK"], ["0x01 0x80", "1", "MINIMALDATA", "OK"], ["0x02 0x0180", "1", "MINIMALDATA", "OK"], ["0x02 0x0100", "1", "MINIMALDATA", "OK"], ["0x02 0x0200", "1", "MINIMALDATA", "OK"], ["0x02 0x0300", "1", "MINIMALDATA", "OK"], ["0x02 0x0400", "1", "MINIMALDATA", "OK"], ["0x02 0x0500", "1", "MINIMALDATA", "OK"], ["0x02 0x0600", "1", "MINIMALDATA", "OK"], ["0x02 0x0700", "1", "MINIMALDATA", "OK"], ["0x02 0x0800", "1", "MINIMALDATA", "OK"], ["0x02 0x0900", "1", "MINIMALDATA", "OK"], ["0x02 0x0a00", "1", "MINIMALDATA", "OK"], ["0x02 0x0b00", "1", "MINIMALDATA", "OK"], ["0x02 0x0c00", "1", "MINIMALDATA", "OK"], ["0x02 0x0d00", "1", "MINIMALDATA", "OK"], ["0x02 0x0e00", "1", "MINIMALDATA", "OK"], ["0x02 0x0f00", "1", "MINIMALDATA", "OK"], ["0x02 0x1000", "1", "MINIMALDATA", "OK"], ["Valid version of the 'Test every numeric-accepting opcode for correct handling of the numeric minimal encoding rule' script_invalid test"], ["1 0x02 0x0000", "PICK DROP", "", "OK"], ["1 0x02 0x0000", "ROLL DROP 1", "", "OK"], ["0x02 0x0000", "1ADD DROP 1", "", "OK"], ["0x02 0x0000", "1SUB DROP 1", "", "OK"], ["0x02 0x0000", "NEGATE DROP 1", "", "OK"], ["0x02 0x0000", "ABS DROP 1", "", "OK"], ["0x02 0x0000", "NOT DROP 1", "", "OK"], ["0x02 0x0000", "0NOTEQUAL DROP 1", "", "OK"], ["0 0x02 0x0000", "ADD DROP 1", "", "OK"], ["0x02 0x0000 0", "ADD DROP 1", "", "OK"], ["0 0x02 0x0000", "SUB DROP 1", "", "OK"], ["0x02 0x0000 0", "SUB DROP 1", "", "OK"], ["0 0x02 0x0000", "BOOLAND DROP 1", "", "OK"], ["0x02 0x0000 0", "BOOLAND DROP 1", "", "OK"], ["0 0x02 0x0000", "BOOLOR DROP 1", "", "OK"], ["0x02 0x0000 0", "BOOLOR DROP 1", "", "OK"], ["0 0x02 0x0000", "NUMEQUAL DROP 1", "", "OK"], ["0x02 0x0000 1", "NUMEQUAL DROP 1", "", "OK"], ["0 0x02 0x0000", "NUMEQUALVERIFY 1", "", "OK"], ["0x02 0x0000 0", "NUMEQUALVERIFY 1", "", "OK"], ["0 0x02 0x0000", "NUMNOTEQUAL DROP 1", "", "OK"], ["0x02 0x0000 0", "NUMNOTEQUAL DROP 1", "", "OK"], ["0 0x02 0x0000", "LESSTHAN DROP 1", "", "OK"], ["0x02 0x0000 0", "LESSTHAN DROP 1", "", "OK"], ["0 0x02 0x0000", "GREATERTHAN DROP 1", "", "OK"], ["0x02 0x0000 0", "GREATERTHAN DROP 1", "", "OK"], ["0 0x02 0x0000", "LESSTHANOREQUAL DROP 1", "", "OK"], ["0x02 0x0000 0", "LESSTHANOREQUAL DROP 1", "", "OK"], ["0 0x02 0x0000", "GREATERTHANOREQUAL DROP 1", "", "OK"], ["0x02 0x0000 0", "GREATERTHANOREQUAL DROP 1", "", "OK"], ["0 0x02 0x0000", "MIN DROP 1", "", "OK"], ["0x02 0x0000 0", "MIN DROP 1", "", "OK"], ["0 0x02 0x0000", "MAX DROP 1", "", "OK"], ["0x02 0x0000 0", "MAX DROP 1", "", "OK"], ["0x02 0x0000 0 0", "WITHIN DROP 1", "", "OK"], ["0 0x02 0x0000 0", "WITHIN DROP 1", "", "OK"], ["0 0 0x02 0x0000", "WITHIN DROP 1", "", "OK"], ["0 0 0x02 0x0000", "CHECKMULTISIG DROP 1", "", "OK"], ["0 0x02 0x0000 0", "CHECKMULTISIG DROP 1", "", "OK"], ["0 0x02 0x0000 0 1", "CHECKMULTISIG DROP 1", "", "OK"], ["0 0 0x02 0x0000", "CHECKMULTISIGVERIFY 1", "", "OK"], ["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", "", "OK"], ["While not really correctly DER encoded, the empty signature is allowed by"], ["STRICTENC to provide a compact way to provide a delibrately invalid signature."], ["0", "0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 CHECKSIG NOT", "STRICTENC", "OK"], ["0 0", "1 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 1 CHECKMULTISIG NOT", "STRICTENC", "OK"], ["CHECKMULTISIG evaluation order tests. CHECKMULTISIG evaluates signatures and"], ["pubkeys in a specific order, and will exit early if the number of signatures"], ["left to check is greater than the number of keys left. As STRICTENC fails the"], ["script when it reaches an invalidly encoded signature or pubkey, we can use it"], ["to test the exact order in which signatures and pubkeys are evaluated by"], ["distinguishing CHECKMULTISIG returning false on the stack and the script as a"], ["whole failing."], ["See also the corresponding inverted versions of these tests in script_invalid.json"], [ "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501", "2 0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT", "STRICTENC", "OK", "2-of-2 CHECKMULTISIG NOT with the second pubkey invalid, and both signatures validly encoded. Valid pubkey fails, and CHECKMULTISIG exits early, prior to evaluation of second invalid pubkey." ], [ "0 0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501", "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT", "STRICTENC", "OK", "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but second signature invalid. Valid pubkey fails, and CHECKMULTISIG exits early, prior to evaluation of second invalid signature." ], ["Increase test coverage for DERSIG"], ["0x4a 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "", "OK", "Overly long signature is correctly encoded"], ["0x25 0x30220220000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "", "OK", "Missing S is correctly encoded"], ["0x27 0x3024021077777777777777777777777777777777020a7777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "S with invalid S length is correctly encoded"], ["0x27 0x302403107777777777777777777777777777777702107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Non-integer R is correctly encoded"], ["0x27 0x302402107777777777777777777777777777777703107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Non-integer S is correctly encoded"], ["0x17 0x3014020002107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Zero-length R is correctly encoded"], ["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "", "OK", "Zero-length S is correctly encoded for DERSIG"], ["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Negative S is correctly encoded"], ["2147483648", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "OK", "CSV passes if stack top bit 1 << 31 is set"], ["", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE", "Test the test: we should have an empty stack after scriptSig evaluation"], [" ", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE", "and multiple spaces should not change that."], [" ", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE"], [" ", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE"], ["", "", "P2SH,STRICTENC","EVAL_FALSE"], ["", "NOP", "P2SH,STRICTENC","EVAL_FALSE"], ["", "NOP DEPTH", "P2SH,STRICTENC", "EVAL_FALSE"], ["NOP", "", "P2SH,STRICTENC", "EVAL_FALSE"], ["NOP", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE"], ["NOP","NOP", "P2SH,STRICTENC", "EVAL_FALSE"], ["NOP","NOP DEPTH", "P2SH,STRICTENC", "EVAL_FALSE"], ["DEPTH", "", "P2SH,STRICTENC", "EVAL_FALSE"], ["0x4c01","0x01 NOP", "P2SH,STRICTENC","BAD_OPCODE", "PUSHDATA1 with not enough bytes"], ["0x4d0200ff","0x01 NOP", "P2SH,STRICTENC","BAD_OPCODE", "PUSHDATA2 with not enough bytes"], ["0x4e03000000ffff","0x01 NOP", "P2SH,STRICTENC","BAD_OPCODE", "PUSHDATA4 with not enough bytes"], ["1", "IF 0x50 ENDIF 1", "P2SH,STRICTENC","BAD_OPCODE", "0x50 is reserved"], ["0x52", "0x5f ADD 0x60 EQUAL", "P2SH,STRICTENC","EVAL_FALSE", "0x51 through 0x60 push 1 through 16 onto stack"], ["0","NOP", "P2SH,STRICTENC","EVAL_FALSE",""], ["1", "IF VER ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VER non-functional"], ["0", "IF VERIF ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VERIF illegal everywhere"], ["0", "IF ELSE 1 ELSE VERIF ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VERIF illegal everywhere"], ["0", "IF VERNOTIF ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VERNOTIF illegal everywhere"], ["0", "IF ELSE 1 ELSE VERNOTIF ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VERNOTIF illegal everywhere"], ["1 IF", "1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "IF/ENDIF can't span scriptSig/scriptPubKey"], ["1 IF 0 ENDIF", "1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], ["1 ELSE 0 ENDIF", "1", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], ["0 NOTIF", "123", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], ["0", "DUP IF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], ["0", "IF 1 ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], ["0", "DUP IF ELSE ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], ["0", "IF 1 ELSE ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], ["0", "NOTIF ELSE 1 ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], ["0 1", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], ["0 0", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], ["1 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], ["0 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], ["0 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], ["0 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], ["1 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], ["0 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], ["1", "IF RETURN ELSE ELSE 1 ENDIF", "P2SH,STRICTENC", "OP_RETURN", "Multiple ELSEs"], ["1", "IF 1 ELSE ELSE RETURN ENDIF", "P2SH,STRICTENC", "OP_RETURN"], ["1", "ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "Malformed IF/ELSE/ENDIF sequence"], ["1", "ELSE ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], ["1", "ENDIF ELSE", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], ["1", "ENDIF ELSE IF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], ["1", "IF ELSE ENDIF ELSE", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], ["1", "IF ELSE ENDIF ELSE ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], ["1", "IF ENDIF ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], ["1", "IF ELSE ELSE ENDIF ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], ["1", "RETURN", "P2SH,STRICTENC", "OP_RETURN"], ["1", "DUP IF RETURN ENDIF", "P2SH,STRICTENC", "OP_RETURN"], ["1", "RETURN 'data'", "P2SH,STRICTENC", "OP_RETURN", "canonical prunable txout format"], ["0 IF", "RETURN ENDIF 1", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "still prunable because IF/ENDIF can't span scriptSig/scriptPubKey"], ["0", "VERIFY 1", "P2SH,STRICTENC", "VERIFY"], ["1", "VERIFY", "P2SH,STRICTENC", "EVAL_FALSE"], ["1", "VERIFY 0", "P2SH,STRICTENC", "EVAL_FALSE"], ["1 TOALTSTACK", "FROMALTSTACK 1", "P2SH,STRICTENC", "INVALID_ALTSTACK_OPERATION", "alt stack not shared between sig/pubkey"], ["IFDUP", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["DROP", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["DUP", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "DUP 1 ADD 2 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], ["NOP", "NIP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "1 NIP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "1 0 NIP", "P2SH,STRICTENC", "EVAL_FALSE"], ["NOP", "OVER 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "OVER", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["0 1", "OVER DEPTH 3 EQUALVERIFY", "P2SH,STRICTENC", "EVAL_FALSE"], ["19 20 21", "PICK 19 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "0 PICK", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "-1 PICK", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["19 20 21", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"], ["19 20 21", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"], ["19 20 21", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"], ["NOP", "0 ROLL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "-1 ROLL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["19 20 21", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"], ["19 20 21", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"], ["19 20 21", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"], ["NOP", "ROT 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "1 ROT 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "1 2 ROT 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "0 1 2 ROT", "P2SH,STRICTENC", "EVAL_FALSE"], ["NOP", "SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["0 1", "SWAP 1 EQUALVERIFY", "P2SH,STRICTENC", "EQUALVERIFY"], ["NOP", "TUCK 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "TUCK 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1 0", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP", "P2SH,STRICTENC", "EVAL_FALSE"], ["NOP", "2DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "2DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "3DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "3DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1 2", "3DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "2OVER 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "2 3 2OVER 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "2SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "2 3 2SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["CAT"], ["", "CAT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "CAT, empty stack"], ["'a'", "CAT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "CAT, one parameter"], ["'abcd' 'efgh'", "CAT 'abcdefgh' EQUAL", "P2SH,STRICTENC", "OK"], ["'' ''", "CAT '' EQUAL", "P2SH,STRICTENC", "OK", "CAT two empty strings"], ["'abc' ''", "CAT 'abc' EQUAL", "P2SH,STRICTENC", "OK", "CAT with empty string"], ["'' 'def'", "CAT 'def' EQUAL", "P2SH,STRICTENC", "OK", "CAT with empty string"], [ "'zngyivniryrgefgnvqwfwqplmramujzilzyrsdvinxfkfmuowdpuzycnzbupwwpzrfxsbyrhdlsyixyzysodseayvvrtbsfxtikrjwkbduulrjyjlwlaigomhyohsukawdwbrpuacdijzzgxh' 'ataguajvuopuktvtklwhsxqvzzfttpdgnxtnbpsiqecxurlczqmoxznlsuejvneiyejetcxlblzrydscnrbydnqytorstjtuzlbbtbyzfiniuehbisqnqhvexylhohjiyiknzgjowvobsrwcxyfowqcvakgdolwpltfcxtrhuysrrvtprzpsucgogsjapdkrbobpxccqgkdumskaleycwsbkabdkuukqiyizceduplmauszwjdzptvmthxocwrignxjogxsvrsjrrlecvdmazlpfkgmskiqqitrevuwiisvpxvkeypzaqjwwiozvmahmtvtjpbolwrymvzfstopzcexalirwbbcqgjvfjfuirrcnlgcfyqnafhh'", "CAT 'zngyivniryrgefgnvqwfwqplmramujzilzyrsdvinxfkfmuowdpuzycnzbupwwpzrfxsbyrhdlsyixyzysodseayvvrtbsfxtikrjwkbduulrjyjlwlaigomhyohsukawdwbrpuacdijzzgxhataguajvuopuktvtklwhsxqvzzfttpdgnxtnbpsiqecxurlczqmoxznlsuejvneiyejetcxlblzrydscnrbydnqytorstjtuzlbbtbyzfiniuehbisqnqhvexylhohjiyiknzgjowvobsrwcxyfowqcvakgdolwpltfcxtrhuysrrvtprzpsucgogsjapdkrbobpxccqgkdumskaleycwsbkabdkuukqiyizceduplmauszwjdzptvmthxocwrignxjogxsvrsjrrlecvdmazlpfkgmskiqqitrevuwiisvpxvkeypzaqjwwiozvmahmtvtjpbolwrymvzfstopzcexalirwbbcqgjvfjfuirrcnlgcfyqnafhh' EQUAL", "P2SH,STRICTENC", "OK", "CAT, maximum length" ], [ "'' 'zngyivniryrgefgnvqwfwqplmramujzilzyrsdvinxfkfmuowdpuzycnzbupwwpzrfxsbyrhdlsyixyzysodseayvvrtbsfxtikrjwkbduulrjyjlwlaigomhyohsukawdwbrpuacdijzzgxhataguajvuopuktvtklwhsxqvzzfttpdgnxtnbpsiqecxurlczqmoxznlsuejvneiyejetcxlblzrydscnrbydnqytorstjtuzlbbtbyzfiniuehbisqnqhvexylhohjiyiknzgjowvobsrwcxyfowqcvakgdolwpltfcxtrhuysrrvtprzpsucgogsjapdkrbobpxccqgkdumskaleycwsbkabdkuukqiyizceduplmauszwjdzptvmthxocwrignxjogxsvrsjrrlecvdmazlpfkgmskiqqitrevuwiisvpxvkeypzaqjwwiozvmahmtvtjpbolwrymvzfstopzcexalirwbbcqgjvfjfuirrcnlgcfyqnafhh'", "CAT 'zngyivniryrgefgnvqwfwqplmramujzilzyrsdvinxfkfmuowdpuzycnzbupwwpzrfxsbyrhdlsyixyzysodseayvvrtbsfxtikrjwkbduulrjyjlwlaigomhyohsukawdwbrpuacdijzzgxhataguajvuopuktvtklwhsxqvzzfttpdgnxtnbpsiqecxurlczqmoxznlsuejvneiyejetcxlblzrydscnrbydnqytorstjtuzlbbtbyzfiniuehbisqnqhvexylhohjiyiknzgjowvobsrwcxyfowqcvakgdolwpltfcxtrhuysrrvtprzpsucgogsjapdkrbobpxccqgkdumskaleycwsbkabdkuukqiyizceduplmauszwjdzptvmthxocwrignxjogxsvrsjrrlecvdmazlpfkgmskiqqitrevuwiisvpxvkeypzaqjwwiozvmahmtvtjpbolwrymvzfstopzcexalirwbbcqgjvfjfuirrcnlgcfyqnafhh' EQUAL", "P2SH,STRICTENC", "OK", "CAT, maximum length with empty string" ], [ "'zngyivniryrgefgnvqwfwqplmramujzilzyrsdvinxfkfmuowdpuzycnzbupwwpzrfxsbyrhdlsyixyzysodseayvvrtbsfxtikrjwkbduulrjyjlwlaigomhyohsukawdwbrpuacdijzzgxhataguajvuopuktvtklwhsxqvzzfttpdgnxtnbpsiqecxurlczqmoxznlsuejvneiyejetcxlblzrydscnrbydnqytorstjtuzlbbtbyzfiniuehbisqnqhvexylhohjiyiknzgjowvobsrwcxyfowqcvakgdolwpltfcxtrhuysrrvtprzpsucgogsjapdkrbobpxccqgkdumskaleycwsbkabdkuukqiyizceduplmauszwjdzptvmthxocwrignxjogxsvrsjrrlecvdmazlpfkgmskiqqitrevuwiisvpxvkeypzaqjwwiozvmahmtvtjpbolwrymvzfstopzcexalirwbbcqgjvfjfuirrcnlgcfyqnafhh' ''", "CAT 'zngyivniryrgefgnvqwfwqplmramujzilzyrsdvinxfkfmuowdpuzycnzbupwwpzrfxsbyrhdlsyixyzysodseayvvrtbsfxtikrjwkbduulrjyjlwlaigomhyohsukawdwbrpuacdijzzgxhataguajvuopuktvtklwhsxqvzzfttpdgnxtnbpsiqecxurlczqmoxznlsuejvneiyejetcxlblzrydscnrbydnqytorstjtuzlbbtbyzfiniuehbisqnqhvexylhohjiyiknzgjowvobsrwcxyfowqcvakgdolwpltfcxtrhuysrrvtprzpsucgogsjapdkrbobpxccqgkdumskaleycwsbkabdkuukqiyizceduplmauszwjdzptvmthxocwrignxjogxsvrsjrrlecvdmazlpfkgmskiqqitrevuwiisvpxvkeypzaqjwwiozvmahmtvtjpbolwrymvzfstopzcexalirwbbcqgjvfjfuirrcnlgcfyqnafhh' EQUAL", "P2SH,STRICTENC", "OK", "CAT, maximum length with empty string" ], [ "'a' 'zngyivniryrgefgnvqwfwqplmramujzilzyrsdvinxfkfmuowdpuzycnzbupwwpzrfxsbyrhdlsyixyzysodseayvvrtbsfxtikrjwkbduulrjyjlwlaigomhyohsukawdwbrpuacdijzzgxhataguajvuopuktvtklwhsxqvzzfttpdgnxtnbpsiqecxurlczqmoxznlsuejvneiyejetcxlblzrydscnrbydnqytorstjtuzlbbtbyzfiniuehbisqnqhvexylhohjiyiknzgjowvobsrwcxyfowqcvakgdolwpltfcxtrhuysrrvtprzpsucgogsjapdkrbobpxccqgkdumskaleycwsbkabdkuukqiyizceduplmauszwjdzptvmthxocwrignxjogxsvrsjrrlecvdmazlpfkgmskiqqitrevuwiisvpxvkeypzaqjwwiozvmahmtvtjpbolwrymvzfstopzcexalirwbbcqgjvfjfuirrcnlgcfyqnafhh'", "CAT", "P2SH,STRICTENC", "PUSH_SIZE", "CAT oversized result" ], ["SPLIT"], ["", "SPLIT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "SPLIT, empty stack"], ["'a'", "SPLIT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "SPLIT, one parameter"], ["'abcdef' 3", "SPLIT 'def' EQUALVERIFY 'abc' EQUAL", "P2SH,STRICTENC", "OK"], ["'' 0", "SPLIT '' EQUALVERIFY '' EQUAL", "P2SH,STRICTENC", "OK", "SPLIT, empty string"], ["'abc' 0", "SPLIT 'abc' EQUALVERIFY '' EQUAL", "P2SH,STRICTENC", "OK", "SPLIT, boundary condition"], ["'abc' 3", "SPLIT '' EQUALVERIFY 'abc' EQUAL", "P2SH,STRICTENC", "OK", "SPLIT, boundary condition"], ["'abc' 4", "SPLIT", "P2SH,STRICTENC", "SPLIT_RANGE", "SPLIT, out of bounds"], ["'abc' -1", "SPLIT", "P2SH,STRICTENC", "SPLIT_RANGE", "SPLIT, out of bounds"], [ "'zngyivniryrgefgnvqwfwqplmramujzilzyrsdvinxfkfmuowdpuzycnzbupwwpzrfxsbyrhdlsyixyzysodseayvvrtbsfxtikrjwkbduulrjyjlwlaigomhyohsukawdwbrpuacdijzzgxhataguajvuopuktvtklwhsxqvzzfttpdgnxtnbpsiqecxurlczqmoxznlsuejvneiyejetcxlblzrydscnrbydnqytorstjtuzlbbtbyzfiniuehbisqnqhvexylhohjiyiknzgjowvobsrwcxyfowqcvakgdolwpltfcxtrhuysrrvtprzpsucgogsjapdkrbobpxccqgkdumskaleycwsbkabdkuukqiyizceduplmauszwjdzptvmthxocwrignxjogxsvrsjrrlecvdmazlpfkgmskiqqitrevuwiisvpxvkeypzaqjwwiozvmahmtvtjpbolwrymvzfstopzcexalirwbbcqgjvfjfuirrcnlgcfyqnafhh'", "145 SPLIT 'ataguajvuopuktvtklwhsxqvzzfttpdgnxtnbpsiqecxurlczqmoxznlsuejvneiyejetcxlblzrydscnrbydnqytorstjtuzlbbtbyzfiniuehbisqnqhvexylhohjiyiknzgjowvobsrwcxyfowqcvakgdolwpltfcxtrhuysrrvtprzpsucgogsjapdkrbobpxccqgkdumskaleycwsbkabdkuukqiyizceduplmauszwjdzptvmthxocwrignxjogxsvrsjrrlecvdmazlpfkgmskiqqitrevuwiisvpxvkeypzaqjwwiozvmahmtvtjpbolwrymvzfstopzcexalirwbbcqgjvfjfuirrcnlgcfyqnafhh' EQUALVERIFY 'zngyivniryrgefgnvqwfwqplmramujzilzyrsdvinxfkfmuowdpuzycnzbupwwpzrfxsbyrhdlsyixyzysodseayvvrtbsfxtikrjwkbduulrjyjlwlaigomhyohsukawdwbrpuacdijzzgxh' EQUAL", "P2SH,STRICTENC", "OK", "SPLIT, maximum length" ], [ "'zngyivniryrgefgnvqwfwqplmramujzilzyrsdvinxfkfmuowdpuzycnzbupwwpzrfxsbyrhdlsyixyzysodseayvvrtbsfxtikrjwkbduulrjyjlwlaigomhyohsukawdwbrpuacdijzzgxhataguajvuopuktvtklwhsxqvzzfttpdgnxtnbpsiqecxurlczqmoxznlsuejvneiyejetcxlblzrydscnrbydnqytorstjtuzlbbtbyzfiniuehbisqnqhvexylhohjiyiknzgjowvobsrwcxyfowqcvakgdolwpltfcxtrhuysrrvtprzpsucgogsjapdkrbobpxccqgkdumskaleycwsbkabdkuukqiyizceduplmauszwjdzptvmthxocwrignxjogxsvrsjrrlecvdmazlpfkgmskiqqitrevuwiisvpxvkeypzaqjwwiozvmahmtvtjpbolwrymvzfstopzcexalirwbbcqgjvfjfuirrcnlgcfyqnafhh'", "0 SPLIT 'zngyivniryrgefgnvqwfwqplmramujzilzyrsdvinxfkfmuowdpuzycnzbupwwpzrfxsbyrhdlsyixyzysodseayvvrtbsfxtikrjwkbduulrjyjlwlaigomhyohsukawdwbrpuacdijzzgxhataguajvuopuktvtklwhsxqvzzfttpdgnxtnbpsiqecxurlczqmoxznlsuejvneiyejetcxlblzrydscnrbydnqytorstjtuzlbbtbyzfiniuehbisqnqhvexylhohjiyiknzgjowvobsrwcxyfowqcvakgdolwpltfcxtrhuysrrvtprzpsucgogsjapdkrbobpxccqgkdumskaleycwsbkabdkuukqiyizceduplmauszwjdzptvmthxocwrignxjogxsvrsjrrlecvdmazlpfkgmskiqqitrevuwiisvpxvkeypzaqjwwiozvmahmtvtjpbolwrymvzfstopzcexalirwbbcqgjvfjfuirrcnlgcfyqnafhh' EQUALVERIFY '' EQUAL", "P2SH,STRICTENC", "OK", "SPLIT, maximum length with empty string" ], [ "'zngyivniryrgefgnvqwfwqplmramujzilzyrsdvinxfkfmuowdpuzycnzbupwwpzrfxsbyrhdlsyixyzysodseayvvrtbsfxtikrjwkbduulrjyjlwlaigomhyohsukawdwbrpuacdijzzgxhataguajvuopuktvtklwhsxqvzzfttpdgnxtnbpsiqecxurlczqmoxznlsuejvneiyejetcxlblzrydscnrbydnqytorstjtuzlbbtbyzfiniuehbisqnqhvexylhohjiyiknzgjowvobsrwcxyfowqcvakgdolwpltfcxtrhuysrrvtprzpsucgogsjapdkrbobpxccqgkdumskaleycwsbkabdkuukqiyizceduplmauszwjdzptvmthxocwrignxjogxsvrsjrrlecvdmazlpfkgmskiqqitrevuwiisvpxvkeypzaqjwwiozvmahmtvtjpbolwrymvzfstopzcexalirwbbcqgjvfjfuirrcnlgcfyqnafhh'", "520 SPLIT '' EQUALVERIFY 'zngyivniryrgefgnvqwfwqplmramujzilzyrsdvinxfkfmuowdpuzycnzbupwwpzrfxsbyrhdlsyixyzysodseayvvrtbsfxtikrjwkbduulrjyjlwlaigomhyohsukawdwbrpuacdijzzgxhataguajvuopuktvtklwhsxqvzzfttpdgnxtnbpsiqecxurlczqmoxznlsuejvneiyejetcxlblzrydscnrbydnqytorstjtuzlbbtbyzfiniuehbisqnqhvexylhohjiyiknzgjowvobsrwcxyfowqcvakgdolwpltfcxtrhuysrrvtprzpsucgogsjapdkrbobpxccqgkdumskaleycwsbkabdkuukqiyizceduplmauszwjdzptvmthxocwrignxjogxsvrsjrrlecvdmazlpfkgmskiqqitrevuwiisvpxvkeypzaqjwwiozvmahmtvtjpbolwrymvzfstopzcexalirwbbcqgjvfjfuirrcnlgcfyqnafhh' EQUAL", "P2SH,STRICTENC", "OK", "SPLIT, maximum length with empty string" ], ["NUM2BIN"], ["", "NUM2BIN 0 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "NUM2BIN, empty stack"], ["0", "NUM2BIN 0 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "NUM2BIN, one parameter"], ["0 0", "NUM2BIN 0 EQUAL", "P2SH,STRICTENC", "OK", "NUM2BIN, canonical argument "], ["0 1", "NUM2BIN 0x01 0x00 EQUAL", "P2SH,STRICTENC", "OK", "NUM2BIN, zero extend"], ["0 7", "NUM2BIN 0x07 0x00000000000000 EQUAL", "P2SH,STRICTENC", "OK", "NUM2BIN, zero extend"], ["1 1", "NUM2BIN 1 EQUAL", "P2SH,STRICTENC", "OK", "NUM2BIN, canonical argument "], ["-42 1", "NUM2BIN -42 EQUAL", "P2SH,STRICTENC", "OK", "NUM2BIN, canonical argument "], ["-42 2", "NUM2BIN 0x02 0x2a80 EQUAL", "P2SH,STRICTENC", "OK", "NUM2BIN, canonical argument "], ["-42 10", "NUM2BIN 0x0a 0x2a000000000000000080 EQUAL", "P2SH,STRICTENC", "OK", "NUM2BIN, large materialization"], ["-42 520", "NUM2BIN", "P2SH,STRICTENC", "OK", "Pushing 520 bytes is ok"], ["-42 521", "NUM2BIN", "P2SH,STRICTENC", "PUSH_SIZE", "Pushing 521 bytes is not"], ["-42 -3", "NUM2BIN", "P2SH,STRICTENC", "PUSH_SIZE", "Negative size"], ["0x05 0xabcdef4280 4", "NUM2BIN 0x04 0xabcdefc2 EQUAL", "P2SH,STRICTENC", "OK", "Item size reduction"], ["0x03 0xabcdef 2", "NUM2BIN", "P2SH,STRICTENC", "IMPOSSIBLE_ENCODING", "output too small"], ["0x03 0xabcdef 3", "NUM2BIN", "P2SH,STRICTENC", "OK"], ["0x01 0x80 0", "NUM2BIN 0 EQUAL", "P2SH,STRICTENC", "OK", "Negative zero"], ["0x01 0x80 3", "NUM2BIN 0x03 0x000000 EQUAL", "P2SH,STRICTENC", "OK", "Negative zero, larger output"], ["0x05 0xabcdef4243 5", "NUM2BIN 0x05 0xabcdef4243 EQUAL", "P2SH,STRICTENC", "OK", "NUM2BIN where len(a) > 4"], ["0x05 0xabcdef4243 6", "NUM2BIN 0x06 0xabcdef424300 EQUAL", "P2SH,STRICTENC", "OK", "pads output properly"], ["0x05 0xabcdef4243 4", "NUM2BIN", "P2SH,STRICTENC", "IMPOSSIBLE_ENCODING", "output too small"], ["0x10 0x0102030405060708090A0B0C0D0E0F10 DUP CAT DUP CAT DUP CAT DUP CAT DUP CAT 0x08 0x0102030405060708 CAT 520", "NUM2BIN 0x10 0x0102030405060708090A0B0C0D0E0F10 DUP CAT DUP CAT DUP CAT DUP CAT DUP CAT 0x08 0x0102030405060708 CAT EQUAL", "P2SH,STRICTENC", "OK", "520 byte 1st operand"], ["0x05 0x0000000000 5", "NUM2BIN 0x05 0x0000000000 EQUAL", "P2SH,STRICTENC", "OK", "1st operand not minimally encoded"], ["0x05 0x0001000000 3", "NUM2BIN 0x03 0x000100 EQUAL", "P2SH,STRICTENC", "OK", "1st operand can shrink"], ["1 0x05 0x0500000000", "NUM2BIN", "P2SH,STRICTENC", "UNKNOWN_ERROR", "2nd operand not minimally encoded"], ["0x04 0xabcdef42 0x05 0xabcdef4243", "NUM2BIN", "P2SH,STRICTENC", "UNKNOWN_ERROR", "2nd operand > 4 bytes"], ["BIN2NUM"], ["", "BIN2NUM 0 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "BIN2NUM, empty stack"], ["0", "BIN2NUM 0 EQUAL", "P2SH,STRICTENC", "OK", "BIN2NUM, canonical argument "], ["1", "BIN2NUM 1 EQUAL", "P2SH,STRICTENC", "OK", "BIN2NUM, canonical argument "], ["-42", "BIN2NUM -42 EQUAL", "P2SH,STRICTENC", "OK", "BIN2NUM, canonical argument "], ["0x01 0x00", "BIN2NUM 0 EQUAL", "P2SH,STRICTENC", "OK", "BIN2NUM, non-canonical argument "], ["0x04 0xffffff7f", "BIN2NUM 2147483647 EQUAL", "P2SH,STRICTENC", "OK", "BIN2NUM, maximum size argument "], ["0x04 0xffffffff", "BIN2NUM -2147483647 EQUAL", "P2SH,STRICTENC", "OK", "BIN2NUM, maximum size argument "], ["0x05 0xffffffff00", "BIN2NUM 2147483647 EQUAL", "P2SH,STRICTENC", "INVALID_NUMBER_RANGE", "BIN2NUM, oversized arguement"], ["0x05 0xffffff7f80", "BIN2NUM -2147483647 EQUAL", "P2SH,STRICTENC", "OK", "BIN2NUM, non-canonical maximum size arguement"], ["0x05 0x0100000000", "BIN2NUM 1 EQUAL", "P2SH,STRICTENC", "OK"], ["0x05 0xFE00000000", "BIN2NUM 254 EQUAL", "P2SH,STRICTENC", "OK"], ["0x05 0x0500000080", "BIN2NUM 0x01 0x85 EQUAL", "P2SH,STRICTENC", "OK"], ["0x03 0x800000", "BIN2NUM 128 EQUAL", "P2SH,STRICTENC", "OK", "Pad where MSB of number is set"], ["0x03 0x800080", "BIN2NUM -128 EQUAL", "P2SH,STRICTENC", "OK", "Pad where MSB of number is set"], ["0x02 0x8000", "BIN2NUM 128 EQUAL", "P2SH,STRICTENC", "OK", "Pad where MSB of number is set"], ["0x02 0x8080", "BIN2NUM -128 EQUAL", "P2SH,STRICTENC", "OK", "Pad where MSB of number is set"], ["0x03 0x0f0000", "BIN2NUM 15 EQUAL", "P2SH,STRICTENC", "OK", "Don't pad where MSB of number is not set"], ["0x03 0x0f0080", "BIN2NUM -15 EQUAL", "P2SH,STRICTENC", "OK", "Don't pad where MSB of number is not set"], ["0x02 0x0f00", "BIN2NUM 15 EQUAL", "P2SH,STRICTENC", "OK", "Don't pad where MSB of number is not set"], ["0x02 0x0f80", "BIN2NUM -15 EQUAL", "P2SH,STRICTENC", "OK", "Don't pad where MSB of number is not set"], ["0x05 0x0100800000", "BIN2NUM 8388609 EQUAL", "P2SH,STRICTENC", "OK", "Ensure significant zero bytes are retained"], ["0x05 0x0100800080", "BIN2NUM -8388609 EQUAL", "P2SH,STRICTENC", "OK", "Ensure significant zero bytes are retained"], ["0x05 0x01000f0000", "BIN2NUM 983041 EQUAL", "P2SH,STRICTENC", "OK", "Ensure significant zero bytes are retained"], ["0x05 0x01000f0080", "BIN2NUM -983041 EQUAL", "P2SH,STRICTENC", "OK", "Ensure significant zero bytes are retained"], ["NOP", "SIZE 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["Disabled opcodes"], ["'abc'", "IF INVERT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "INVERT disabled"], ["2 0 IF 2MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "2MUL disabled"], ["2 0 IF 2DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "2DIV disabled"], ["2 2 0 IF MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "MUL disabled"], ["2 2 0 IF LSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "LSHIFT disabled"], ["2 2 0 IF RSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "RSHIFT disabled"], ["Bitwise opcodes"], ["AND"], ["0 0", "AND 0 EQUAL", "P2SH,STRICTENC", "OK", "AND, empty parameters"], ["0x01 0x00 0x01 0x00", "AND 0x01 0x00 EQUAL", "P2SH,STRICTENC", "OK", "AND, simple and"], ["1 0x01 0x00", "AND 0x01 0x00 EQUAL", "P2SH,STRICTENC", "OK", "AND, simple and"], ["0x01 0x00 1", "AND 0x01 0x00 EQUAL", "P2SH,STRICTENC", "OK", "AND, simple and"], ["1 1", "AND 1 EQUAL", "P2SH,STRICTENC", "OK", "AND, simple and"], ["0", "AND 0 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "AND, invalid parameter count"], ["", "AND 0 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "AND, empty stack"], ["0 1", "AND 1 EQUAL", "P2SH,STRICTENC", "OPERAND_SIZE", "AND, different operand size"], ["0x01 0xab 0x01 0xcd", "AND 0x01 0x89 EQUAL", "P2SH,STRICTENC", "OK", "AND, more complex operands"], ["OR"], ["0 0", "OR 0 EQUAL", "P2SH,STRICTENC", "OK", "OR, empty parameters"], ["0x01 0x00 0x01 0x00", "OR 0x01 0x00 EQUAL", "P2SH,STRICTENC", "OK", "OR, simple and"], ["1 0x01 0x00", "OR 1 EQUAL", "P2SH,STRICTENC", "OK", "OR, simple and"], ["0x01 0x00 1", "OR 1 EQUAL", "P2SH,STRICTENC", "OK", "OR, simple and"], ["1 1", "OR 1 EQUAL", "P2SH,STRICTENC", "OK", "OR, simple and"], ["0", "OR 0 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "OR, invalid parameter count"], ["", "OR 0 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "OR, empty stack"], ["0 1", "OR 1 EQUAL", "P2SH,STRICTENC", "OPERAND_SIZE", "OR, different operand size"], ["0x01 0xab 0x01 0xcd", "OR 0x01 0xef EQUAL", "P2SH,STRICTENC", "OK", "XOR, more complex operands"], ["XOR"], ["0 0", "XOR 0 EQUAL", "P2SH,STRICTENC", "OK", "XOR, empty parameters"], ["0x01 0x00 0x01 0x00", "XOR 0x01 0x00 EQUAL", "P2SH,STRICTENC", "OK", "XOR, simple and"], ["1 0x01 0x00", "XOR 1 EQUAL", "P2SH,STRICTENC", "OK", "XOR, simple and"], ["0x01 0x00 1", "XOR 1 EQUAL", "P2SH,STRICTENC", "OK", "XOR, simple and"], ["1 1", "XOR 0x01 0x00 EQUAL", "P2SH,STRICTENC", "OK", "XOR, simple and"], ["0", "XOR 0 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "XOR, invalid parameter count"], ["", "XOR 0 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "XOR, empty stack"], ["0 1", "XOR 1 EQUAL", "P2SH,STRICTENC", "OPERAND_SIZE", "XOR, different operand size"], ["0x01 0xab 0x01 0xcd", "XOR 0x01 0x66 EQUAL", "P2SH,STRICTENC", "OK", "XOR, more complex operands"], ["DIV"], ["1 1", "DIV 1 EQUAL", "P2SH,STRICTENC", "OK"], ["1 -1", "DIV -1 EQUAL", "P2SH,STRICTENC", "OK"], ["-1 1", "DIV -1 EQUAL", "P2SH,STRICTENC", "OK"], ["-1 -1", "DIV 1 EQUAL", "P2SH,STRICTENC", "OK"], ["28 21", "DIV 1 EQUAL", "P2SH,STRICTENC", "OK", "Round towards zero"], ["12 -7", "DIV -1 EQUAL", "P2SH,STRICTENC", "OK", "Round towards zero"], ["-32 29", "DIV -1 EQUAL", "P2SH,STRICTENC", "OK", "Round towards zero"], ["-42 -27", "DIV 1 EQUAL", "P2SH,STRICTENC", "OK", "Round towards zero"], ["0 123", "DIV 0 EQUAL", "P2SH,STRICTENC", "OK"], ["511 0", "DIV", "P2SH,STRICTENC", "DIV_BY_ZERO", "DIV, divide by zero"], ["1 1", "DIV DEPTH 1 EQUAL", "P2SH,STRICTENC", "OK", "Stack depth correct"], ["1", "DIV", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "Not enough operands"], ["0", "DIV", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "Not enough operands"], ["2147483647 1", "DIV 2147483647 EQUAL", "P2SH,STRICTENC", "OK", "Check boundary condition"], ["1 2147483647", "DIV 0 EQUAL", "P2SH,STRICTENC", "OK", "Check boundary condition"], ["2147483647 2147483647", "DIV 1 EQUAL", "P2SH,STRICTENC", "OK", "Check boundary condition"], ["-2147483647 1", "DIV -2147483647 EQUAL", "P2SH,STRICTENC", "OK", "Check boundary condition"], ["-1 2147483647", "DIV 0 EQUAL", "P2SH,STRICTENC", "OK", "Check boundary condition"], ["-2147483647 2147483647", "DIV -1 EQUAL", "P2SH,STRICTENC", "OK", "Check boundary condition"], ["2147483647 -1", "DIV -2147483647 EQUAL", "P2SH,STRICTENC", "OK", "Check boundary condition"], ["1 -2147483647", "DIV 0 EQUAL", "P2SH,STRICTENC", "OK", "Check boundary condition"], ["2147483647 -2147483647", "DIV -1 EQUAL", "P2SH,STRICTENC", "OK", "Check boundary condition"], ["-2147483647 -1", "DIV 2147483647 EQUAL", "P2SH,STRICTENC", "OK", "Check boundary condition"], ["-1 -2147483647", "DIV 0 EQUAL", "P2SH,STRICTENC", "OK", "Check boundary condition"], ["-2147483647 -2147483647", "DIV 1 EQUAL", "P2SH,STRICTENC", "OK", "Check boundary condition"], ["2147483648 1", "DIV", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"], ["1 2147483648", "DIV", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"], ["-2147483648 1", "DIV", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"], ["1 -2147483648", "DIV", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"], ["MOD"], ["1 1", "MOD 0 EQUAL", "P2SH,STRICTENC", "OK"], ["-1 1", "MOD 0 EQUAL", "P2SH,STRICTENC", "OK"], ["1 -1", "MOD 0 EQUAL", "P2SH,STRICTENC", "OK"], ["-1 -1", "MOD 0 EQUAL", "P2SH,STRICTENC", "OK"], ["82 23", "MOD 13 EQUAL", "P2SH,STRICTENC", "OK"], ["8 -3", "MOD 2 EQUAL", "P2SH,STRICTENC", "OK"], ["-71 13", "MOD -6 EQUAL", "P2SH,STRICTENC", "OK"], ["-110 -31", "MOD -17 EQUAL", "P2SH,STRICTENC", "OK"], ["0 1", "MOD 0 EQUAL", "P2SH,STRICTENC", "OK"], ["1 0", "MOD", "P2SH,STRICTENC", "MOD_BY_ZERO", "MOD, modulo by zero"], ["1 1", "MOD DEPTH 1 EQUAL", "P2SH,STRICTENC", "OK", "Stack depth correct"], ["1", "MOD", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "Not enough operands"], ["0", "MOD", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "Not enough operands"], ["2147483647 123", "MOD 79 EQUAL", "P2SH,STRICTENC", "OK", "Check boundary condition"], ["123 2147483647", "MOD 123 EQUAL", "P2SH,STRICTENC", "OK", "Check boundary condition"], ["2147483647 2147483647", "MOD 0 EQUAL", "P2SH,STRICTENC", "OK", "Check boundary condition"], ["-2147483647 123", "MOD -79 EQUAL", "P2SH,STRICTENC", "OK", "Check boundary condition"], ["-123 2147483647", "MOD -123 EQUAL", "P2SH,STRICTENC", "OK", "Check boundary condition"], ["-2147483647 2147483647", "MOD 0 EQUAL", "P2SH,STRICTENC", "OK", "Check boundary condition"], ["2147483647 -123", "MOD 79 EQUAL", "P2SH,STRICTENC", "OK", "Check boundary condition"], ["123 -2147483647", "MOD 123 EQUAL", "P2SH,STRICTENC", "OK", "Check boundary condition"], ["2147483647 -2147483647", "MOD 0 EQUAL", "P2SH,STRICTENC", "OK", "Check boundary condition"], ["-2147483647 -123", "MOD -79 EQUAL", "P2SH,STRICTENC", "OK", "Check boundary condition"], ["-123 -2147483647", "MOD -123 EQUAL", "P2SH,STRICTENC", "OK", "Check boundary condition"], ["-2147483647 -2147483647", "MOD 0 EQUAL", "P2SH,STRICTENC", "OK", "Check boundary condition"], ["2147483648 1", "MOD", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"], ["1 2147483648", "MOD", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"], ["-2147483648 1", "MOD", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"], ["1 -2147483648", "MOD", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"], ["EQUAL"], ["", "EQUAL NOT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "EQUAL must error when there are no stack items"], ["0", "EQUAL NOT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "EQUAL must error when there are not 2 stack items"], ["0 1","EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], ["1 1 ADD", "0 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], ["11 1 ADD 12 SUB", "11 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], ["CHECKDATASIG"], ["", "CHECKDATASIG", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG", "INVALID_STACK_OPERATION"], ["0", "CHECKDATASIG", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG", "INVALID_STACK_OPERATION"], ["0 0", "CHECKDATASIG", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG", "INVALID_STACK_OPERATION"], [ "0 0", "0 CHECKDATASIG", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG", "PUBKEYTYPE" ], [ "0 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG", "EVAL_FALSE" ], [ "0x08 0x3006020101020101 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG", "P2SH,STRICTENC,CHECKDATASIG", "EVAL_FALSE", "Check that NULLFAIL trigger only when specified" ], [ "0x08 0x3006020101020101 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG", "NULLFAIL" ], [ "0x09 0x300602010102010101 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG", "SIG_DER", "Ensure that sighashtype is ignored" ], [ "0x09 0x300702010102020001 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG", "SIG_DER", "Non cannonical DER encoding" ], ["CHECKDATASIGVERIFY"], ["", "CHECKDATASIGVERIFY 1", "P2SH,STRICTENC,CHECKDATASIG", "INVALID_STACK_OPERATION"], ["0", "CHECKDATASIGVERIFY 1", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG", "INVALID_STACK_OPERATION"], ["0 0", "CHECKDATASIGVERIFY 1", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG", "INVALID_STACK_OPERATION"], [ "0 0", "0 CHECKDATASIGVERIFY 1", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG", "PUBKEYTYPE" ], [ "0 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG", "CHECKDATASIGVERIFY" ], [ "0x08 0x3006020101020101 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", "P2SH,STRICTENC,CHECKDATASIG", "CHECKDATASIGVERIFY", "Check that NULLFAIL trigger only when specified" ], [ "0x08 0x3006020101020101 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG", "NULLFAIL" ], [ "0x09 0x300602010102010101 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG", "SIG_DER", "Ensure that sighashtype is ignored" ], [ "0x09 0x300702010102020001 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG", "SIG_DER", "Non cannonical DER encoding" ], ["Schnorr flag on: CHECKDATASIG unchanged"], ["", "CHECKDATASIG", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG,SCHNORR", "INVALID_STACK_OPERATION"], ["0", "CHECKDATASIG", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG,SCHNORR", "INVALID_STACK_OPERATION"], ["0 0", "CHECKDATASIG", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG,SCHNORR", "INVALID_STACK_OPERATION"], [ "0 0", "0 CHECKDATASIG", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG,SCHNORR", "PUBKEYTYPE" ], [ "0 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG,SCHNORR", "EVAL_FALSE" ], [ "0x08 0x3006020101020101 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG", "P2SH,STRICTENC,CHECKDATASIG,SCHNORR", "EVAL_FALSE", "Check that NULLFAIL trigger only when specified" ], [ "0x08 0x3006020101020101 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG,SCHNORR", "NULLFAIL" ], [ "0x09 0x300602010102010101 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG,SCHNORR", "SIG_DER", "Ensure that sighashtype is ignored" ], [ "0x09 0x300702010102020001 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG,SCHNORR", "SIG_DER", "Non cannonical DER encoding" ], ["Schnorr flag on: CHECKDATASIGVERIFY unchanged"], ["", "CHECKDATASIGVERIFY 1", "P2SH,STRICTENC,CHECKDATASIG,SCHNORR", "INVALID_STACK_OPERATION"], ["0", "CHECKDATASIGVERIFY 1", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG,SCHNORR", "INVALID_STACK_OPERATION"], ["0 0", "CHECKDATASIGVERIFY 1", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG,SCHNORR", "INVALID_STACK_OPERATION"], [ "0 0", "0 CHECKDATASIGVERIFY 1", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG,SCHNORR", "PUBKEYTYPE" ], [ "0 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG,SCHNORR", "CHECKDATASIGVERIFY" ], [ "0x08 0x3006020101020101 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", "P2SH,STRICTENC,CHECKDATASIG,SCHNORR", "CHECKDATASIGVERIFY", "Check that NULLFAIL trigger only when specified" ], [ "0x08 0x3006020101020101 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG,SCHNORR", "NULLFAIL" ], [ "0x09 0x300602010102010101 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG,SCHNORR", "SIG_DER", "Ensure that sighashtype is ignored" ], [ "0x09 0x300702010102020001 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", "P2SH,STRICTENC,NULLFAIL,CHECKDATASIG,SCHNORR", "SIG_DER", "Non cannonical DER encoding" ], ["ADD"], ["2147483648 0 ADD", "NOP", "P2SH,STRICTENC", "UNKNOWN_ERROR", "arithmetic operands must be in range [-2^31...2^31] "], ["-2147483648 0 ADD", "NOP", "P2SH,STRICTENC", "UNKNOWN_ERROR", "arithmetic operands must be in range [-2^31...2^31] "], ["2147483647 DUP ADD", "4294967294 NUMEQUAL", "P2SH,STRICTENC", "UNKNOWN_ERROR", "NUMEQUAL must be in numeric range"], ["'abcdef' NOT", "0 EQUAL", "P2SH,STRICTENC", "UNKNOWN_ERROR", "NOT is an arithmetic operand"], ["2 DUP MUL", "4 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], ["2 2MUL", "4 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], ["2 2DIV", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], ["2 2 LSHIFT", "8 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], ["2 1 RSHIFT", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], ["1", "NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], ["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], ["Ensure 100% coverage of discouraged NOPS"], ["1", "NOP1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], ["1", "CHECKLOCKTIMEVERIFY", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], ["1", "CHECKSEQUENCEVERIFY", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], ["1", "NOP4", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], ["1", "NOP5", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], ["1", "NOP6", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], ["1", "NOP7", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], ["1", "NOP8", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], ["1", "NOP9", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], ["1", "NOP10", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], ["NOP10", "1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in scriptSig"], ["1 0x01 0xb9", "HASH160 0x14 0x15727299b05b45fdaf9ac9ecf7565cfe27c3e567 EQUAL", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in redeemScript"], ["0x50","1", "P2SH,STRICTENC", "BAD_OPCODE", "opcode 0x50 is reserved"], ["1", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "opcodes >= FIRST_UNDEFINED_OP_VALUE invalid if executed"], ["1", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xc0 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xc1 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xc2 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xc3 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xc4 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xc5 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xc6 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xc7 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xc8 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xc9 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xca ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xcb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xcc ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xcd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xce ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xcf ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xd0 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xd1 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xd2 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xd3 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xd4 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xd5 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xd6 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xd7 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xd8 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xd9 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xda ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xdb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xdc ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xdd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xde ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xdf ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xe0 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xe1 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xe2 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xe3 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xe4 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xe5 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xe6 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xe7 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xe8 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xe9 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xea ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xeb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xec ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xed ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xee ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xef ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xf0 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xf1 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xf2 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xf3 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xf4 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xf5 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xf6 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xf7 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xf8 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xf9 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xfa ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xfb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xfc ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xfd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xfe ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xff ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1 IF 1 ELSE", "0xff ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "invalid because scriptSig and scriptPubKey are processed separately"], ["NOP", "RIPEMD160", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "SHA1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "SHA256", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "HASH160", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "HASH256", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'", "P2SH,STRICTENC", "PUSH_SIZE", ">520 byte push"], ["0", "IF 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' ENDIF 1", "P2SH,STRICTENC", "PUSH_SIZE", ">520 byte push in non-executed IF branch"], ["1", "0x61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "P2SH,STRICTENC", "OP_COUNT", ">201 opcodes executed. 0x61 is NOP"], ["0", "IF 0x6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161 ENDIF 1", "P2SH,STRICTENC", "OP_COUNT", ">201 opcodes including non-executed IF branch. 0x61 is NOP"], ["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", "1 2 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", "P2SH,STRICTENC", "STACK_SIZE", ">1,000 stack size (0x6f is 3DUP)"], ["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", "1 TOALTSTACK 2 TOALTSTACK 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", "P2SH,STRICTENC", "STACK_SIZE", ">1,000 stack+altstack size"], ["NOP", "0 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f 2DUP 0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "P2SH,STRICTENC", "SCRIPT_SIZE", "10,001-byte scriptPubKey"], ["NOP1","NOP10", "P2SH,STRICTENC", "EVAL_FALSE"], ["1","VER", "P2SH,STRICTENC", "BAD_OPCODE", "OP_VER is reserved"], ["1","VERIF", "P2SH,STRICTENC", "BAD_OPCODE", "OP_VERIF is reserved"], ["1","VERNOTIF", "P2SH,STRICTENC", "BAD_OPCODE", "OP_VERNOTIF is reserved"], ["1","RESERVED", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED is reserved"], ["1","RESERVED1", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED1 is reserved"], ["1","RESERVED2", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED2 is reserved"], ["1","0xbc", "P2SH,STRICTENC", "BAD_OPCODE", "0xbc == FIRST_UNDEFINED_OP_VALUE"], ["2147483648", "1ADD 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"], ["2147483648", "NEGATE 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"], ["-2147483648", "1ADD 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "Because we use a sign bit, -2147483648 is also 5 bytes"], ["2147483647", "1ADD 1SUB 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers, even if the result is 4-bytes"], ["2147483648", "1SUB 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers, even if the result is 4-bytes"], ["2147483648 1", "BOOLOR 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do BOOLOR on 5-byte integers (but we can still do IF etc)"], ["2147483648 1", "BOOLAND 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do BOOLAND on 5-byte integers"], ["1", "1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "ENDIF without IF"], ["1", "IF 1", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "IF without ENDIF"], ["1 IF 1", "ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "IFs don't carry over"], ["NOP", "IF 1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "The following tests check the if(stack.size() < N) tests in each opcode"], ["NOP", "NOTIF 1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "They are here to catch copy-and-paste errors"], ["NOP", "VERIFY 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "Most of them are duplicated elsewhere,"], ["NOP", "TOALTSTACK 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "but, hey, more is always better, right?"], ["1", "FROMALTSTACK", "P2SH,STRICTENC", "INVALID_ALTSTACK_OPERATION"], ["1", "2DROP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "2DUP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1 1", "3DUP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1 1 1", "2OVER", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1 1 1 1 1", "2ROT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1 1 1", "2SWAP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "IFDUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "DROP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "NIP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "OVER", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1 1 1 3", "PICK", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["0", "PICK 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1 1 1 3", "ROLL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["0", "ROLL 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1 1", "ROT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "SWAP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "TUCK", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "SIZE 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "EQUAL 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "EQUALVERIFY 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "1ADD 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "1SUB 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "NEGATE 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "ABS 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "NOT 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "0NOTEQUAL 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "ADD", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "SUB", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "BOOLAND", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "BOOLOR", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "NUMEQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "NUMEQUALVERIFY 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "NUMNOTEQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "LESSTHAN", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "GREATERTHAN", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "LESSTHANOREQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "GREATERTHANOREQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "MIN", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "MAX", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1 1", "WITHIN", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "RIPEMD160 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "SHA1 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "SHA256 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "HASH160 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "HASH256 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["Increase CHECKSIG and CHECKMULTISIG negative test coverage"], ["", "CHECKSIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKSIG must error when there are no stack items"], ["0", "CHECKSIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKSIG must error when there are not 2 stack items"], ["", "CHECKMULTISIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKMULTISIG must error when there are no stack items"], ["", "-1 CHECKMULTISIG NOT", "STRICTENC", "PUBKEY_COUNT", "CHECKMULTISIG must error when the specified number of pubkeys is negative"], ["", "1 CHECKMULTISIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKMULTISIG must error when there are not enough pubkeys on the stack"], ["", "-1 0 CHECKMULTISIG NOT", "STRICTENC", "SIG_COUNT", "CHECKMULTISIG must error when the specified number of signatures is negative"], ["", "1 'pk1' 1 CHECKMULTISIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKMULTISIG must error when there are not enough signatures on the stack"], ["", "'dummy' 'sig1' 1 'pk1' 1 CHECKMULTISIG IF 1 ENDIF", "", "EVAL_FALSE", "CHECKMULTISIG must push false to stack when signature is invalid when NOT in strict enc mode"], ["", "0 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG", "P2SH,STRICTENC", "OP_COUNT", "202 CHECKMULTISIGS, fails due to 201 op limit"], ["1", "0 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", ""], ["", "NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG", "P2SH,STRICTENC", "OP_COUNT", "Fails due to 201 script operation limit"], ["1", "NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY", "P2SH,STRICTENC", "OP_COUNT", ""], ["0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21", "21 CHECKMULTISIG 1", "P2SH,STRICTENC", "PUBKEY_COUNT", "nPubKeys > 20"], ["0 'sig' 1 0", "CHECKMULTISIG 1", "P2SH,STRICTENC", "SIG_COUNT", "nSigs > nPubKeys"], ["NOP 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "SIG_PUSHONLY", "Tests for Script.IsPushOnly()"], ["NOP1 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "SIG_PUSHONLY"], ["0 0x01 0x50", "HASH160 0x14 0xece424a6bb6ddf4db592c0faed60685047a361b1 EQUAL", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED in P2SH should fail"], ["0 0x01 VER", "HASH160 0x14 0x0f4d7845db968f2a81b530b6f3c1d6246d4c7e01 EQUAL", "P2SH,STRICTENC", "BAD_OPCODE", "OP_VER in P2SH should fail"], ["0x00", "'00' EQUAL", "P2SH,STRICTENC", "EVAL_FALSE", "Basic OP_0 execution"], ["MINIMALDATA enforcement for PUSHDATAs"], ["PUSHDATA1 0x00", "DROP 1", "MINIMALDATA", "MINIMALDATA", "Empty vector minimally represented by OP_0"], ["0x01 0x81", "DROP 1", "MINIMALDATA", "MINIMALDATA", "-1 minimally represented by OP_1NEGATE"], ["0x01 0x01", "DROP 1", "MINIMALDATA", "MINIMALDATA", "1 to 16 minimally represented by OP_1 to OP_16"], ["0x01 0x02", "DROP 1", "MINIMALDATA", "MINIMALDATA"], ["0x01 0x03", "DROP 1", "MINIMALDATA", "MINIMALDATA"], ["0x01 0x04", "DROP 1", "MINIMALDATA", "MINIMALDATA"], ["0x01 0x05", "DROP 1", "MINIMALDATA", "MINIMALDATA"], ["0x01 0x06", "DROP 1", "MINIMALDATA", "MINIMALDATA"], ["0x01 0x07", "DROP 1", "MINIMALDATA", "MINIMALDATA"], ["0x01 0x08", "DROP 1", "MINIMALDATA", "MINIMALDATA"], ["0x01 0x09", "DROP 1", "MINIMALDATA", "MINIMALDATA"], ["0x01 0x0a", "DROP 1", "MINIMALDATA", "MINIMALDATA"], ["0x01 0x0b", "DROP 1", "MINIMALDATA", "MINIMALDATA"], ["0x01 0x0c", "DROP 1", "MINIMALDATA", "MINIMALDATA"], ["0x01 0x0d", "DROP 1", "MINIMALDATA", "MINIMALDATA"], ["0x01 0x0e", "DROP 1", "MINIMALDATA", "MINIMALDATA"], ["0x01 0x0f", "DROP 1", "MINIMALDATA", "MINIMALDATA"], ["0x01 0x10", "DROP 1", "MINIMALDATA", "MINIMALDATA"], ["PUSHDATA1 0x48 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA", "MINIMALDATA", "PUSHDATA1 of 72 bytes minimally represented by direct push"], ["PUSHDATA2 0xFF00 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA", "MINIMALDATA", "PUSHDATA2 of 255 bytes minimally represented by PUSHDATA1"], ["PUSHDATA4 0x00010000 0x11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA", "MINIMALDATA", "PUSHDATA4 of 256 bytes minimally represented by PUSHDATA2"], ["MINIMALDATA enforcement for numeric arguments"], ["0x01 0x00", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 0"], ["0x02 0x0000", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 0"], ["0x01 0x80", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "0x80 (negative zero) numequals 0"], ["0x02 0x0080", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 0"], ["0x02 0x0500", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 5"], ["0x03 0x050000", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 5"], ["0x02 0x0580", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals -5"], ["0x03 0x050080", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals -5"], ["0x03 0xff7f80", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "Minimal encoding is 0xffff"], ["0x03 0xff7f00", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "Minimal encoding is 0xff7f"], ["0x04 0xffff7f80", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "Minimal encoding is 0xffffff"], ["0x04 0xffff7f00", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "Minimal encoding is 0xffff7f"], ["Test every numeric-accepting opcode for correct handling of the numeric minimal encoding rule"], ["1 0x02 0x0000", "PICK DROP", "MINIMALDATA", "UNKNOWN_ERROR"], ["1 0x02 0x0000", "ROLL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0x02 0x0000", "1ADD DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0x02 0x0000", "1SUB DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0x02 0x0000", "NEGATE DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0x02 0x0000", "ABS DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0x02 0x0000", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0x02 0x0000", "0NOTEQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0 0x02 0x0000", "ADD DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0x02 0x0000 0", "ADD DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0 0x02 0x0000", "SUB DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0x02 0x0000 0", "SUB DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0 0x02 0x0000", "BOOLAND DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0x02 0x0000 0", "BOOLAND DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0 0x02 0x0000", "BOOLOR DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0x02 0x0000 0", "BOOLOR DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0 0x02 0x0000", "NUMEQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0x02 0x0000 1", "NUMEQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0 0x02 0x0000", "NUMEQUALVERIFY 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0x02 0x0000 0", "NUMEQUALVERIFY 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0 0x02 0x0000", "NUMNOTEQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0x02 0x0000 0", "NUMNOTEQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0 0x02 0x0000", "LESSTHAN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0x02 0x0000 0", "LESSTHAN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0 0x02 0x0000", "GREATERTHAN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0x02 0x0000 0", "GREATERTHAN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0 0x02 0x0000", "LESSTHANOREQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0x02 0x0000 0", "LESSTHANOREQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0 0x02 0x0000", "GREATERTHANOREQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0x02 0x0000 0", "GREATERTHANOREQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0 0x02 0x0000", "MIN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0x02 0x0000 0", "MIN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0 0x02 0x0000", "MAX DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0x02 0x0000 0", "MAX DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0x02 0x0000 0 0", "WITHIN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0 0x02 0x0000 0", "WITHIN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0 0 0x02 0x0000", "WITHIN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0 0 0x02 0x0000", "CHECKMULTISIG DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0 0x02 0x0000 0", "CHECKMULTISIG DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0 0x02 0x0000 0 1", "CHECKMULTISIG DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0 0 0x02 0x0000", "CHECKMULTISIGVERIFY 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["64/65-byte sig length tests"], ["0x41 0x303e021d4444444444444444444444444444444444444444444444444444444444021d444444444444444444444444444444444444444444444444444444444401", "0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 CHECKSIG NOT", "", "OK"], ["0x40 0x303e021d4444444444444444444444444444444444444444444444444444444444021d4444444444444444444444444444444444444444444444444444444444", "0 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 CHECKDATASIG NOT", "CHECKDATASIG", "OK"], ["0x41 0x303e021d4444444444444444444444444444444444444444444444444444444444021d444444444444444444444444444444444444444444444444444444444401", " 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 CHECKSIG NOT", "SCHNORR", "OK"], ["0x40 0x303e021d4444444444444444444444444444444444444444444444444444444444021d4444444444444444444444444444444444444444444444444444444444", "0 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 CHECKDATASIG NOT", "CHECKDATASIG,SCHNORR", "OK"], ["0 0x41 0x303e021d4444444444444444444444444444444444444444444444444444444444021d444444444444444444444444444444444444444444444444444444444401", "1 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 1 CHECKMULTISIG NOT", "", "OK"], ["0 0x41 0x303e021d4444444444444444444444444444444444444444444444444444444444021d444444444444444444444444444444444444444444444444444444444401", "1 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 1 CHECKMULTISIG NOT", "STRICTENC", "OK"], ["0 0x41 0x303e021d4444444444444444444444444444444444444444444444444444444444021d444444444444444444444444444444444444444444444444444444444401", "1 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 1 CHECKMULTISIG NOT", "SCHNORR", "SIG_BADLENGTH"], ["0 0x41 0x303e021d4444444444444444444444444444444444444444444444444444444444021d444444444444444444444444444444444444444444444444444444444401", "1 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 1 CHECKMULTISIG NOT", "SCHNORR,STRICTENC,NULLFAIL", "SIG_BADLENGTH"], ["0 0x40 0x303d021d4444444444444444444444444444444444444444444444444444444444021c4444444444444444444444444444444444444444444444444444444401", "1 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 1 CHECKMULTISIG NOT", "SCHNORR", "OK"], ["0 0x42 0x303f021d4444444444444444444444444444444444444444444444444444444444021e44444444444444444444444444444444444444444444444444444444444401", "1 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 1 CHECKMULTISIG NOT", "SCHNORR", "OK"], ["0x41 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", "0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 CHECKSIG NOT", "", "OK"], ["0x41 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", "0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 CHECKSIG NOT", "STRICTENC", "SIG_DER"], ["0x41 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", "0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 CHECKSIG NOT", "STRICTENC,SCHNORR", "OK"], ["0x40 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 CHECKDATASIG NOT", "CHECKDATASIG", "OK"], ["0x40 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 CHECKDATASIG NOT", "CHECKDATASIG,STRICTENC", "SIG_DER"], ["0x40 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 CHECKDATASIG NOT", "CHECKDATASIG,STRICTENC,SCHNORR", "OK"], ["0 0x41 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", "1 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 1 CHECKMULTISIG NOT", "", "OK"], ["0 0x41 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", "1 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 1 CHECKMULTISIG NOT", "STRICTENC", "SIG_DER"], ["0 0x41 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", "1 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 1 CHECKMULTISIG NOT", "STRICTENC,SCHNORR", "SIG_BADLENGTH"], ["0 0x41 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", "1 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 1 CHECKMULTISIG NOT", "STRICTENC,NULLFAIL,SCHNORR", "SIG_BADLENGTH"], ["Order of CHECKMULTISIG evaluation tests, inverted by swapping the order of"], ["pubkeys/signatures so they fail due to the STRICTENC rules on validly encoded"], ["signatures and pubkeys."], [ "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501", "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0 2 CHECKMULTISIG NOT", "STRICTENC", "PUBKEYTYPE", "2-of-2 CHECKMULTISIG NOT with the first pubkey invalid, and both signatures validly encoded." ], [ "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 1", "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT", "STRICTENC", "SIG_DER", "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but first signature invalid." ], [ "0 0x47 0x304402205451ce65ad844dbb978b8bdedf5082e33b43cae8279c30f2c74d9e9ee49a94f802203fe95a7ccf74da7a232ee523ef4a53cb4d14bdd16289680cdb97a63819b8f42f01 0x46 0x304402205451ce65ad844dbb978b8bdedf5082e33b43cae8279c30f2c74d9e9ee49a94f802203fe95a7ccf74da7a232ee523ef4a53cb4d14bdd16289680cdb97a63819b8f42f", "2 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 3 CHECKMULTISIG", "P2SH,STRICTENC", "SIG_DER", "2-of-3 with one valid and one invalid signature due to parse error, nSigs > validSigs" ], ["Increase DERSIG test coverage"], ["0x4a 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Overly long signature is incorrectly encoded for DERSIG"], ["0x25 0x30220220000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Missing S is incorrectly encoded for DERSIG"], ["0x27 0x3024021077777777777777777777777777777777020a7777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "S with invalid S length is incorrectly encoded for DERSIG"], ["0x27 0x302403107777777777777777777777777777777702107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Non-integer R is incorrectly encoded for DERSIG"], ["0x27 0x302402107777777777777777777777777777777703107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Non-integer S is incorrectly encoded for DERSIG"], ["0x17 0x3014020002107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Zero-length R is incorrectly encoded for DERSIG"], ["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Zero-length S is incorrectly encoded for DERSIG"], ["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Negative S is incorrectly encoded for DERSIG"], ["Automatically generated test cases"], [ "0x47 0x3044022022127048516d473153d1f74e46e828496776752e3255f672f760a41e83f54e6f0220502956b739ed82aad916dc4a73e1fd55d02aad514b5211f1ba7d0dadf53c637901", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "", "OK", "P2PK" ], [ "0x47 0x3044022022127048516d463153d1f74e46e828496776752e3255f672f760a41e83f54e6f0220502956b739ed82aad916dc4a73e1fd55d02aad514b5211f1ba7d0dadf53c637901", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "", "EVAL_FALSE", "P2PK, bad sig" ], [ "0x47 0x304402201e0ec3c6c263f34049c93e0bc646d7287ca2cc6571d658e4e7269daebc96ef35022009841f101e6dcaba8993d0259e5732a871e253be807556bf5618bf0bc3e84af001 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508", "DUP HASH160 0x14 0x1018853670f9f3b0582c5b9ee8ce93764ac32b93 EQUALVERIFY CHECKSIG", "", "OK", "P2PKH" ], [ "0x47 0x304402201dddd1a3b642f1b543cbecad602558636135d59b3850a4d1646a0b11c712b340022016d58230012421b304d1cc42ccc1e33738206be64f7984be30ed437fa7a2fd0a01 0x21 0x03363d90d446b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640", "DUP HASH160 0x14 0xc0834c0c158f53be706d234c38fd52de7eece656 EQUALVERIFY CHECKSIG", "", "EQUALVERIFY", "P2PKH, bad pubkey" ], [ "0x47 0x304402206e8719d1746852542bed4f05a57f0369759553c7d655229759de2643f371e20002207a7f06790da5757d2f37c4d074de0fe66ac149ee011baeb4dd3fa97f288637f881", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", "", "OK", "P2PK anyonecanpay" ], [ "0x47 0x304402206e8719d1746852542bed4f05a57f0369759553c7d655229759de2643f371e20002207a7f06790da5757d2f37c4d074de0fe66ac149ee011baeb4dd3fa97f288637f801", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", "", "EVAL_FALSE", "P2PK anyonecanpay marked with normal hashtype" ], [ "0x47 0x304402206f04a92fb434b24b06180c7c2af5f4fb73f15427da93b5ab8c167c7d10f4f37902203f0b57300a19fe106d79f427360a6b4720117ab50de44047e52a35de2523291e01 0x23 0x210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac", "HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL", "P2SH", "OK", "P2SH(P2PK)" ], [ "0x47 0x304402206f04a92fb434b24b06180c7c2af5f4fb73f15427da93b5ab8c167c7d10f4f37902203f0b57300a19fe106d79f427360a6b4720117ab50de44047e52a35de2523291e01 0x23 0x210279be667ef9dcbbac54a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac", "HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL", "P2SH", "EVAL_FALSE", "P2SH(P2PK), bad redeemscript" ], [ "0x47 0x304402201799a8feda56fd3c58b816eac4f0bb916136b4f60b5c5da3264f5c29aec13abf022029c9d7779a5376b5d0398e389817699bb2485a305eb1fa5868081c3a9d89bee201 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x19 0x76a91491b24bf9f5288532960ac687abb035127b1d28a588ac", "HASH160 0x14 0x7f67f0521934a57d3039f77f9f32cf313f3ac74b EQUAL", "P2SH", "OK", "P2SH(P2PKH)" ], [ "0x47 0x3044022001aabce638c1bc883223651a4252d36e5918681e85562fe5b112f08bc944644902203110421d46142317ec5ca117ce4d40593ace16ab5b9688eb2ce8103b3a9273c701 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac", "HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL", "", "OK", "P2SH(P2PKH), bad sig but no VERIFY_P2SH" ], [ "0x47 0x3044022001aabce638c1bc883223651a4252d36e5918681e85562fe5b112f08bc944644902203110421d46142317ec5ca117ce4d40593ace16ab5b9688eb2ce8103b3a9273c701 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac", "HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL", "P2SH", "EQUALVERIFY", "P2SH(P2PKH), bad sig" ], [ "0 0x47 0x304402204d69d5caa4dbab259f79fce89d3b459bbd91697c1c052a1554ff3b08b2241cbd0220330a8e17a90d51996e363cb8902fce6278c6350fa59ae12832db2f6a44d64dce01 0x47 0x3044022031a1e5289b0d9c33ec182a7f67210b9997187c710f7d3f0f28bdfb618c4e025c02205d95fe63ee83a20ec44159a06f7c0b43b61d5f0c346ca4a2cc7b91878ad1a85001 0x47 0x304402200a9faba8228f7a86bf6c3b2a0da0e2f9136ea390e5a5f66dbf232e499459f34a0220437bcac47d837870eeb41aabc379cbf2b1dcef954bd887f3968849922694ebd701", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", "", "OK", "3-of-3" ], [ "0 0x47 0x304402204d69d5caa4dbab259f79fce89d3b459bbd91697c1c052a1554ff3b08b2241cbd0220330a8e17a90d51996e363cb8902fce6278c6350fa59ae12832db2f6a44d64dce01 0x47 0x3044022031a1e5289b0d9c33ec182a7f67210b9997187c710f7d3f0f28bdfb618c4e025c02205d95fe63ee83a20ec44159a06f7c0b43b61d5f0c346ca4a2cc7b91878ad1a85001 0", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", "", "EVAL_FALSE", "3-of-3, 2 sigs" ], [ "0 0x47 0x304402205b6256a4755890fe278ea083eddf5c0519d0d7fad14fe265e077c5627171b27e02200d841cb15cdc9a9c8f3ec20c5e4bb1b0e5715d26353f500378f4215195e3558c01 0x47 0x304402200b0620f910e92621934e88ae0177b0bb381ba812d4c23c77afbf1a3ab637a0bb0220275387c859089939e22d803dfae77a4ecd122d951d0feb9e6a65a6918c2b1e0201 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae", "HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL", "P2SH", "OK", "P2SH(2-of-3)" ], [ "0 0x47 0x304402205b6256a4755890fe278ea083eddf5c0519d0d7fad14fe265e077c5627171b27e02200d841cb15cdc9a9c8f3ec20c5e4bb1b0e5715d26353f500378f4215195e3558c01 0 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae", "HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL", "P2SH", "EVAL_FALSE", "P2SH(2-of-3), 1 sig" ], [ "0x47 0x30440220007dc49df798c714600c93a94dcdffc89013aac6683c2be18c54d136fea0a26e0220681bb9fad75a638536c0cfafaca8332a15c6c4047fd3989df5d232c0efa5411f01", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "", "OK", "P2PK with too much R padding but no DERSIG" ], [ "0x47 0x30440220007dc49df798c714600c93a94dcdffc89013aac6683c2be18c54d136fea0a26e0220681bb9fad75a638536c0cfafaca8332a15c6c4047fd3989df5d232c0efa5411f01", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "DERSIG", "SIG_DER", "P2PK with too much R padding" ], [ "0x48 0x304502207a404c8f2bb2ac64db7cbd4d3490eaecb06115172d99e4447e6f4dbfbaa92fe4022100631033d772b4313d4a0d3cda8eacab93654dd8bcdfb9340ba9271be29cfc249c01", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "", "OK", "P2PK with too much S padding but no DERSIG" ], [ "0x48 0x304502207a404c8f2bb2ac64db7cbd4d3490eaecb06115172d99e4447e6f4dbfbaa92fe4022100631033d772b4313d4a0d3cda8eacab93654dd8bcdfb9340ba9271be29cfc249c01", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "DERSIG", "SIG_DER", "P2PK with too much S padding" ], [ "0x47 0x30440220d888248d694d649657d71a5baebb70512525ba5fe76575afb5cbbe9f0680783d022054a16bce5e3957be61e15940b11d66515bc8df1c0e090c47acf32515d56ef95001", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "", "OK", "P2PK with too little R padding but no DERSIG" ], [ "0x47 0x30440220d888248d694d649657d71a5baebb70512525ba5fe76575afb5cbbe9f0680783d022054a16bce5e3957be61e15940b11d66515bc8df1c0e090c47acf32515d56ef95001", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "DERSIG", "SIG_DER", "P2PK with too little R padding" ], [ "0x47 0x30440220001d5bd10da0bc0ab3018cea865f8d936bf625fee21464b127532f6021d5e82b02203b3660b9dccd43ae3def3ec3e1853b2566bb6bd899f5364c06508eec532f700e01", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT", "", "OK", "P2PK NOT with bad sig with too much R padding but no DERSIG" ], [ "0x47 0x30440220001d5bd10da0bc0ab3018cea865f8d936bf625fee21464b127532f6021d5e82b02203b3660b9dccd43ae3def3ec3e1853b2566bb6bd899f5364c06508eec532f700e01", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT", "DERSIG", "SIG_DER", "P2PK NOT with bad sig with too much R padding" ], [ "0x47 0x30440220001d5bd10da0bd0ab3018cea865f8d936bf625fee21464b127532f6021d5e82b02203b3660b9dccd43ae3def3ec3e1853b2566bb6bd899f5364c06508eec532f700e01", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT", "", "EVAL_FALSE", "P2PK NOT with too much R padding but no DERSIG" ], [ "0x47 0x30440220001d5bd10da0bd0ab3018cea865f8d936bf625fee21464b127532f6021d5e82b02203b3660b9dccd43ae3def3ec3e1853b2566bb6bd899f5364c06508eec532f700e01", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT", "DERSIG", "SIG_DER", "P2PK NOT with too much R padding" ], [ "0x47 0x30440220d888248d694d649657d71a5baebb70512525ba5fe76575afb5cbbe9f0680783d022054a16bce5e3957be61e15940b11d66515bc8df1c0e090c47acf32515d56ef95001", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "", "OK", "BIP66 example 1, without DERSIG" ], [ "0x47 0x30440220d888248d694d649657d71a5baebb70512525ba5fe76575afb5cbbe9f0680783d022054a16bce5e3957be61e15940b11d66515bc8df1c0e090c47acf32515d56ef95001", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "DERSIG", "SIG_DER", "BIP66 example 1, with DERSIG" ], [ "0x47 0x304402208eae7755261155b02becf6e6990fe6d1392210ff19d46cbbba5456e4b59a71cd022047054a0a3f229eaf9f597033c85877913596fa7bdaf2f1b55cf5704ce6ee99bc01", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", "", "EVAL_FALSE", "BIP66 example 2, without DERSIG" ], [ "0x47 0x304402208eae7755261155b02becf6e6990fe6d1392210ff19d46cbbba5456e4b59a71cd022047054a0a3f229eaf9f597033c85877913596fa7bdaf2f1b55cf5704ce6ee99bc01", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", "DERSIG", "SIG_DER", "BIP66 example 2, with DERSIG" ], [ "0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "", "EVAL_FALSE", "BIP66 example 3, without DERSIG" ], [ "0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "DERSIG", "EVAL_FALSE", "BIP66 example 3, with DERSIG" ], [ "0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", "", "OK", "BIP66 example 4, without DERSIG" ], [ "0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", "DERSIG", "OK", "BIP66 example 4, with DERSIG" ], [ "0x09 0x300602010102010101", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", "DERSIG", "OK", "BIP66 example 4, with DERSIG, non-null DER-compliant signature" ], [ "0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", "DERSIG,NULLFAIL", "OK", "BIP66 example 4, with DERSIG and NULLFAIL" ], [ "0x09 0x300602010102010101", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", "DERSIG,NULLFAIL", "NULLFAIL", "BIP66 example 4, with DERSIG and NULLFAIL, non-null DER-compliant signature" ], [ "1", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "", "EVAL_FALSE", "BIP66 example 5, without DERSIG" ], [ "1", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "DERSIG", "SIG_DER", "BIP66 example 5, with DERSIG" ], [ "1", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", "", "OK", "BIP66 example 6, without DERSIG" ], [ "1", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", "DERSIG", "SIG_DER", "BIP66 example 6, with DERSIG" ], [ "0 0x47 0x30440220868d1de0f6cc0b0d465992dd177fc545df03381f5a79c171ad55990e623417da022078276700801d7f454b013ded53ddeca5d9ea55bd704e1683832ece986c09fd3201 0x47 0x304402207349bbfeebc59c0efc363dc94e0c0f0491e9c6456a86b753c4ce1ca74b51bfdf02200d94da026a56016b975451d7b0dd2c46780ac3dfa008791e0665af04a235e80f01", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG", "", "OK", "BIP66 example 7, without DERSIG" ], [ "0 0x47 0x30440220868d1de0f6cc0b0d465992dd177fc545df03381f5a79c171ad55990e623417da022078276700801d7f454b013ded53ddeca5d9ea55bd704e1683832ece986c09fd3201 0x47 0x304402207349bbfeebc59c0efc363dc94e0c0f0491e9c6456a86b753c4ce1ca74b51bfdf02200d94da026a56016b975451d7b0dd2c46780ac3dfa008791e0665af04a235e80f01", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG", "DERSIG", "SIG_DER", "BIP66 example 7, with DERSIG" ], [ "0 0x47 0x30440220e8172152b43bc9c788442b116c2345f04591d44d5be77cd6e9acafed7cd3649e022075c0e1014e000cf02e2cc4b33159d74e94c54a5c8d2c046bae2a7e1e38896b2f01 0x47 0x30440220667437f14da10aca92795812e31784b42824d865c535584b7f01a0b1d7bda8b802203331b1f9d6421310aace34a3a8b193853bf17dcec0cfe3f2ddec806bbeee527801", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT", "", "EVAL_FALSE", "BIP66 example 8, without DERSIG" ], [ "0 0x47 0x30440220e8172152b43bc9c788442b116c2345f04591d44d5be77cd6e9acafed7cd3649e022075c0e1014e000cf02e2cc4b33159d74e94c54a5c8d2c046bae2a7e1e38896b2f01 0x47 0x30440220667437f14da10aca92795812e31784b42824d865c535584b7f01a0b1d7bda8b802203331b1f9d6421310aace34a3a8b193853bf17dcec0cfe3f2ddec806bbeee527801", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT", "DERSIG", "SIG_DER", "BIP66 example 8, with DERSIG" ], [ "0 0 0x47 0x30440220e6afebaa7f2b0a06c014519ee51d97e73365151e802a3913bb9b1198021ffdb702200e6cbbe6ba99a5b4424756a544e5ffed5867b67430b9ba893f2b65309a8a762d01", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG", "", "EVAL_FALSE", "BIP66 example 9, without DERSIG" ], [ "0 0 0x47 0x30440220e6afebaa7f2b0a06c014519ee51d97e73365151e802a3913bb9b1198021ffdb702200e6cbbe6ba99a5b4424756a544e5ffed5867b67430b9ba893f2b65309a8a762d01", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG", "DERSIG", "SIG_DER", "BIP66 example 9, with DERSIG" ], [ "0 0 0x47 0x30440220e8e61fae71ba1147b92ea58aae6d314001d6071add352af500da476f466782600220112491a261785241c009386e18a5f79b946a58ba958081a7da1ccec31f3aa9bc01", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT", "", "OK", "BIP66 example 10, without DERSIG" ], [ "0 0 0x47 0x30440220e8e61fae71ba1147b92ea58aae6d314001d6071add352af500da476f466782600220112491a261785241c009386e18a5f79b946a58ba958081a7da1ccec31f3aa9bc01", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT", "DERSIG", "SIG_DER", "BIP66 example 10, with DERSIG" ], [ "0 0x47 0x30440220868d1de0f6cc0b0d465992dd177fc545df03381f5a79c171ad55990e623417da022078276700801d7f454b013ded53ddeca5d9ea55bd704e1683832ece986c09fd3201 0", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG", "", "EVAL_FALSE", "BIP66 example 11, without DERSIG" ], [ "0 0x47 0x30440220868d1de0f6cc0b0d465992dd177fc545df03381f5a79c171ad55990e623417da022078276700801d7f454b013ded53ddeca5d9ea55bd704e1683832ece986c09fd3201 0", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG", "DERSIG", "EVAL_FALSE", "BIP66 example 11, with DERSIG" ], [ "0 0x47 0x30440220e8172152b43bc9c788442b116c2345f04591d44d5be77cd6e9acafed7cd3649e022075c0e1014e000cf02e2cc4b33159d74e94c54a5c8d2c046bae2a7e1e38896b2f01 0", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT", "", "OK", "BIP66 example 12, without DERSIG" ], [ "0 0x47 0x30440220e8172152b43bc9c788442b116c2345f04591d44d5be77cd6e9acafed7cd3649e022075c0e1014e000cf02e2cc4b33159d74e94c54a5c8d2c046bae2a7e1e38896b2f01 0", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66 example 12, with DERSIG" ], [ "0x48 0x3044022032d4a3dec9cad54c94b5585fb058f7e41ac5173843b0c2e7197a40421ee4ab54022041d4d4296d8c2821bb39f6349f0140bc2c95f16496df9fcd894758673d1db7d80101", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", "", "OK", "P2PK with multi-byte hashtype, without DERSIG" ], [ "0x48 0x3044022032d4a3dec9cad54c94b5585fb058f7e41ac5173843b0c2e7197a40421ee4ab54022041d4d4296d8c2821bb39f6349f0140bc2c95f16496df9fcd894758673d1db7d80101", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", "DERSIG", "SIG_DER", "P2PK with multi-byte hashtype, with DERSIG" ], [ "0x48 0x3045022032d4a3dec9cad54c94b5585fb058f7e41ac5173843b0c2e7197a40421ee4ab54022100be2b2bd69273d7de44c609cb60febf428e18eb821869006e368b06259318896901", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", "", "OK", "P2PK with high S but no LOW_S" ], [ "0x48 0x3045022032d4a3dec9cad54c94b5585fb058f7e41ac5173843b0c2e7197a40421ee4ab54022100be2b2bd69273d7de44c609cb60febf428e18eb821869006e368b06259318896901", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", "LOW_S", "SIG_HIGH_S", "P2PK with high S" ], [ "0x47 0x304402201162483d0440fc508d79d314a91cfc4df4ea31b302f02c16893fa15d9c9f7f06022032afebdd5b2964c40c887b967f9599e0e5b5ff5b2f899ab62ada12a5af2a481701", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "", "OK", "P2PK with hybrid pubkey but no STRICTENC" ], [ "0x47 0x304402201162483d0440fc508d79d314a91cfc4df4ea31b302f02c16893fa15d9c9f7f06022032afebdd5b2964c40c887b967f9599e0e5b5ff5b2f899ab62ada12a5af2a481701", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "STRICTENC", "PUBKEYTYPE", "P2PK with hybrid pubkey" ], [ "0x47 0x3044022057a786d0e26b1bad0f928d05b94a995afefe4f523450ef82893779e95cf2042102203b049387f08eac1829061b91a6cf0b67280b4b4948e4e1773d3b4dfbbd64a4c001", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", "", "EVAL_FALSE", "P2PK NOT with hybrid pubkey but no STRICTENC" ], [ "0x47 0x3044022057a786d0e26b1bad0f928d05b94a995afefe4f523450ef82893779e95cf2042102203b049387f08eac1829061b91a6cf0b67280b4b4948e4e1773d3b4dfbbd64a4c001", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", "STRICTENC", "PUBKEYTYPE", "P2PK NOT with hybrid pubkey" ], [ "0x47 0x3044022057a786d0e26b1aad0f928d05b94a995afefe4f523450ef82893779e95cf2042102203b049387f08eac1829061b91a6cf0b67280b4b4948e4e1773d3b4dfbbd64a4c001", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", "", "OK", "P2PK NOT with invalid hybrid pubkey but no STRICTENC" ], [ "0x47 0x3044022057a786d0e26b1aad0f928d05b94a995afefe4f523450ef82893779e95cf2042102203b049387f08eac1829061b91a6cf0b67280b4b4948e4e1773d3b4dfbbd64a4c001", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", "STRICTENC", "PUBKEYTYPE", "P2PK NOT with invalid hybrid pubkey" ], [ "0 0x47 0x30440220379db2a13c8c679bda7f500c93bae36e0d75c96b8af1754316a9c80e843f2923022046ee947cd3b916ab78f95be6ae29cc2f037ddb47f8e59c966b1e6813b270648001", "1 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", "", "OK", "1-of-2 with the second 1 hybrid pubkey and no STRICTENC" ], [ "0 0x47 0x30440220379db2a13c8c679bda7f500c93bae36e0d75c96b8af1754316a9c80e843f2923022046ee947cd3b916ab78f95be6ae29cc2f037ddb47f8e59c966b1e6813b270648001", "1 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", "STRICTENC", "OK", "1-of-2 with the second 1 hybrid pubkey" ], [ "0 0x47 0x304402202d4dd56f6dee2eccc049a4ebd65e77e4325aa3f2940130412b9f96fd28fa8c5a022074963950dd250d2fc943e60c7a4133cc8b1fcc46253e9b19f71c9723d1d894ef01", "1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 2 CHECKMULTISIG", "STRICTENC", "PUBKEYTYPE", "1-of-2 with the first 1 hybrid pubkey" ], [ "0x47 0x30440220020cf2d9ccc6d8a8b2f6f0f90e9805845194d9715392e58f08e1b63d2566c53e02207b75a322355b3820f59dffc5793ed5947aa3f4e460edeb28cc306573db09495705", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", "", "OK", "P2PK with undefined hashtype but no STRICTENC" ], [ "0x47 0x30440220020cf2d9ccc6d8a8b2f6f0f90e9805845194d9715392e58f08e1b63d2566c53e02207b75a322355b3820f59dffc5793ed5947aa3f4e460edeb28cc306573db09495705", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", "STRICTENC", "SIG_HASHTYPE", "P2PK with undefined hashtype" ], [ "0x47 0x3044022070fd4f47970fdb7814b79482d1132a7c3598437bef78f8458de6e5d66ce918fd02204e657846fee57cb6fc3cbaae6b85db8646cc351f96155c86387388c2e8a5a83a21 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", "DUP HASH160 0x14 0x91b24bf9f5288532960ac687abb035127b1d28a5 EQUALVERIFY CHECKSIG", "", "OK", "P2PKH with invalid sighashtype" ], [ "0x47 0x3044022070fd4f47970fdb7814b79482d1132a7c3598437bef78f8458de6e5d66ce918fd02204e657846fee57cb6fc3cbaae6b85db8646cc351f96155c86387388c2e8a5a83a21 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", "DUP HASH160 0x14 0x91b24bf9f5288532960ac687abb035127b1d28a5 EQUALVERIFY CHECKSIG", "STRICTENC", "SIG_HASHTYPE", "P2PKH with invalid sighashtype and STRICTENC" ], [ "0x47 0x30440220643b4c3979d9d2c41842d4843113c1b40ca1df85805c7c654cabb015208c23f702207d3675bf98419065ac9a24865b652551849a0b1e52fdc429cd150f5e7897627821 0x43 0x41048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26cafac", "HASH160 0x14 0x49ba2f86705b5dcd48d93b750f03289db3b8ce21 EQUAL", "P2SH", "OK", "P2SH(P2PK) with invalid sighashtype" ], [ "0x47 0x30440220643b4c3979d9d2c41842d4843113c1b40ca1df85805c7c654cabb015208c23f702207d3675bf98419065ac9a24865b652551849a0b1e52fdc429cd150f5e7897627821 0x43 0x41048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26cafac", "HASH160 0x14 0x49ba2f86705b5dcd48d93b750f03289db3b8ce21 EQUAL", "P2SH,STRICTENC", "SIG_HASHTYPE", "P2SH(P2PK) with invalid sighashtype and STRICTENC" ], [ "0x47 0x304402200cbfa0902c2129020eb09acbf89725a409573096046d4bb7ba0bdc2af1588139022062a9c69be90b7f434c7e38a8a741df604a695610a8f6a0789082f1104f72d57105", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG NOT", "", "OK", "P2PK NOT with invalid sig and undefined hashtype but no STRICTENC" ], [ "0x47 0x304402200cbfa0902c2129020eb09acbf89725a409573096046d4bb7ba0bdc2af1588139022062a9c69be90b7f434c7e38a8a741df604a695610a8f6a0789082f1104f72d57105", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG NOT", "STRICTENC", "SIG_HASHTYPE", "P2PK NOT with invalid sig and undefined hashtype" ], [ "1 0x47 0x304402204d69d5caa4dbab259f79fce89d3b459bbd91697c1c052a1554ff3b08b2241cbd0220330a8e17a90d51996e363cb8902fce6278c6350fa59ae12832db2f6a44d64dce01 0x47 0x3044022031a1e5289b0d9c33ec182a7f67210b9997187c710f7d3f0f28bdfb618c4e025c02205d95fe63ee83a20ec44159a06f7c0b43b61d5f0c346ca4a2cc7b91878ad1a85001 0x47 0x304402200a9faba8228f7a86bf6c3b2a0da0e2f9136ea390e5a5f66dbf232e499459f34a0220437bcac47d837870eeb41aabc379cbf2b1dcef954bd887f3968849922694ebd701", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", "", "OK", "3-of-3 with nonzero dummy but no NULLDUMMY" ], [ "1 0x47 0x304402204d69d5caa4dbab259f79fce89d3b459bbd91697c1c052a1554ff3b08b2241cbd0220330a8e17a90d51996e363cb8902fce6278c6350fa59ae12832db2f6a44d64dce01 0x47 0x3044022031a1e5289b0d9c33ec182a7f67210b9997187c710f7d3f0f28bdfb618c4e025c02205d95fe63ee83a20ec44159a06f7c0b43b61d5f0c346ca4a2cc7b91878ad1a85001 0x47 0x304402200a9faba8228f7a86bf6c3b2a0da0e2f9136ea390e5a5f66dbf232e499459f34a0220437bcac47d837870eeb41aabc379cbf2b1dcef954bd887f3968849922694ebd701", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", "NULLDUMMY", "SIG_NULLDUMMY", "3-of-3 with nonzero dummy" ], [ "1 0x47 0x304402203f78692a12d075d5057dea07265f0ba8ede774f083b85896fe07231efbe155da0220388fc48ffd8fb1c189fbf8bd767ee1c38b3f5d864b18faa1d81d0c3670cda85b01 0x47 0x3044022070a2850b5363fc49db8f617f08f5947bb85a1d439da07a6dc0d2fc178d9a5f3f022019e15a476e9dab8e3cb18a2bcae279366b1701c1b11c020851517cf03132bbff01 0x47 0x304402206457d83204e94902c789a16fa9e2f1f1d25684c7748c93373e9077b01a49b80a02204b0509cba423c7bbad8f80653c54a1ce10c901d33292464a4d5162f2016ddc2901", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG NOT", "", "OK", "3-of-3 NOT with invalid sig and nonzero dummy but no NULLDUMMY" ], [ "1 0x47 0x304402203f78692a12d075d5057dea07265f0ba8ede774f083b85896fe07231efbe155da0220388fc48ffd8fb1c189fbf8bd767ee1c38b3f5d864b18faa1d81d0c3670cda85b01 0x47 0x3044022070a2850b5363fc49db8f617f08f5947bb85a1d439da07a6dc0d2fc178d9a5f3f022019e15a476e9dab8e3cb18a2bcae279366b1701c1b11c020851517cf03132bbff01 0x47 0x304402206457d83204e94902c789a16fa9e2f1f1d25684c7748c93373e9077b01a49b80a02204b0509cba423c7bbad8f80653c54a1ce10c901d33292464a4d5162f2016ddc2901", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG NOT", "NULLDUMMY", "SIG_NULLDUMMY", "3-of-3 NOT with invalid sig with nonzero dummy" ], [ "0 0x47 0x3044022044b11d5a64bebbd4280c616146bc961eed3081300eef527fbe8da91f6775892a022045b044719bf5c7100617cd518fff22c102f93e6768ed986543668be43bc44d1601 DUP", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", "", "OK", "2-of-2 with two identical keys and sigs pushed using OP_DUP but no SIGPUSHONLY" ], [ "0 0x47 0x3044022044b11d5a64bebbd4280c616146bc961eed3081300eef527fbe8da91f6775892a022045b044719bf5c7100617cd518fff22c102f93e6768ed986543668be43bc44d1601 DUP", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", "SIGPUSHONLY", "SIG_PUSHONLY", "2-of-2 with two identical keys and sigs pushed using OP_DUP" ], [ "0x47 0x304402204b26ae3298e583956aed912c1e6a32b94efc4cf3a97495d83f7a6edd64f8c11702204d0b112f3ebbffe8a0626deb57f62f33432fae8dc1a3de1658464bbb12f8260c01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac", "HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL", "", "OK", "P2SH(P2PK) with non-push scriptSig but no P2SH or SIGPUSHONLY" ], [ "0x47 0x3044022032d4a3dec9cad54c94b5585fb058f7e41ac5173843b0c2e7197a40421ee4ab54022041d4d4296d8c2821bb39f6349f0140bc2c95f16496df9fcd894758673d1db7d801 NOP8", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", "", "OK", "P2PK with non-push scriptSig but with P2SH validation" ], [ "0x47 0x304402204b26ae3298e583956aed912c1e6a32b94efc4cf3a97495d83f7a6edd64f8c11702204d0b112f3ebbffe8a0626deb57f62f33432fae8dc1a3de1658464bbb12f8260c01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac", "HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL", "P2SH", "SIG_PUSHONLY", "P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY" ], [ "0x47 0x304402204b26ae3298e583956aed912c1e6a32b94efc4cf3a97495d83f7a6edd64f8c11702204d0b112f3ebbffe8a0626deb57f62f33432fae8dc1a3de1658464bbb12f8260c01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac", "HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL", "SIGPUSHONLY", "SIG_PUSHONLY", "P2SH(P2PK) with non-push scriptSig but not P2SH" ], [ "0 0x47 0x3044022044b11d5a64bebbd4280c616146bc961eed3081300eef527fbe8da91f6775892a022045b044719bf5c7100617cd518fff22c102f93e6768ed986543668be43bc44d1601 0x47 0x3044022044b11d5a64bebbd4280c616146bc961eed3081300eef527fbe8da91f6775892a022045b044719bf5c7100617cd518fff22c102f93e6768ed986543668be43bc44d1601", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", "SIGPUSHONLY", "OK", "2-of-2 with two identical keys and sigs pushed" ], [ "11 0x47 0x3044022022127048516d473153d1f74e46e828496776752e3255f672f760a41e83f54e6f0220502956b739ed82aad916dc4a73e1fd55d02aad514b5211f1ba7d0dadf53c637901", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "P2SH", "OK", "P2PK with unnecessary input but no CLEANSTACK" ], [ "11 0x47 0x3044022022127048516d473153d1f74e46e828496776752e3255f672f760a41e83f54e6f0220502956b739ed82aad916dc4a73e1fd55d02aad514b5211f1ba7d0dadf53c637901", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "CLEANSTACK,P2SH", "CLEANSTACK", "P2PK with unnecessary input" ], [ "11 0x47 0x3044022065066ad31463bd8ebb9cb7ef621e9c96fa3411a3ed393a3e41120a7ea688babf02206869ac4e007f853c1a15bca2670eabeb9a54cac1bddf5c4f73c03f8c17cbffa701 0x43 0x410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac", "HASH160 0x14 0x31edc23bdafda4639e669f89ad6b2318dd79d032 EQUAL", "P2SH", "OK", "P2SH with unnecessary input but no CLEANSTACK" ], [ "11 0x47 0x3044022065066ad31463bd8ebb9cb7ef621e9c96fa3411a3ed393a3e41120a7ea688babf02206869ac4e007f853c1a15bca2670eabeb9a54cac1bddf5c4f73c03f8c17cbffa701 0x43 0x410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac", "HASH160 0x14 0x31edc23bdafda4639e669f89ad6b2318dd79d032 EQUAL", "CLEANSTACK,P2SH", "CLEANSTACK", "P2SH with unnecessary input" ], [ "0x47 0x3044022065066ad31463bd8ebb9cb7ef621e9c96fa3411a3ed393a3e41120a7ea688babf02206869ac4e007f853c1a15bca2670eabeb9a54cac1bddf5c4f73c03f8c17cbffa701 0x43 0x410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac", "HASH160 0x14 0x31edc23bdafda4639e669f89ad6b2318dd79d032 EQUAL", "CLEANSTACK,P2SH", "OK", "P2SH with CLEANSTACK" ], [ [ 123450.00000000 ], "0x47 0x304402206e3afa6dd4d1db87538fa48a0ef3f824d7ec554103fe5fb3527254d78bd79617022066097e981df0d1ce3c07224a73585ca1f5e8ebdf79639b2cc73c20bde066075141", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "SIGHASH_FORKID", "OK", "P2PK FORKID" ], [ [ 123450.00000000 ], "0x47 0x3044022054e19540c81ccb214b62acda158faf01440d98adab2e13ed43a4d35cc551bfff02205b05fc09882819b3fdbe56adfef63243d7faa5c4837db0c72ad9356eae9a5b8c41", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "SIGHASH_FORKID", "EVAL_FALSE", "P2PK INVALID AMOUNT" ], [ [ 123450.00000000 ], "0x47 0x304402206e3afa6dd4d1db87538fa48a0ef3f824d7ec554103fe5fb3527254d78bd79617022066097e981df0d1ce3c07224a73585ca1f5e8ebdf79639b2cc73c20bde066075141", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "STRICTENC", "ILLEGAL_FORKID", "P2PK INVALID FORKID" ], [ [ 123450.00000000 ], "0x47 0x304402205ce75e7249823fe2cc78f861579189f8e10585008aa057d4e6d755bfca1c8c6802200f63547feabc3f198f18742e84d57d6ca4bdd477d10a121554647cba36742f2b41", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "REPLAY_PROTECTION,SIGHASH_FORKID", "OK", "P2PK REPLAY PROTECTED" ], [ [ 123450.00000000 ], "0x47 0x304402206e3afa6dd4d1db87538fa48a0ef3f824d7ec554103fe5fb3527254d78bd79617022066097e981df0d1ce3c07224a73585ca1f5e8ebdf79639b2cc73c20bde066075141", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "REPLAY_PROTECTION,SIGHASH_FORKID", "EVAL_FALSE", "P2PK REPLAY PROTECTED" ], [ "0x46 0x3044022021309a532a60d471cc4ef025a96572c7bf26c4640b53c7d45e411a5aa99980f6022037964f01a61db1b24ea44137b3d67d7095ec25f68bd7b508e01441e5539d96a9 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG", "CHECKDATASIG,NULLFAIL,STRICTENC", "OK", "Standard CHECKDATASIG" ], [ "0x46 0x3044022021309a532a60d471cc4ef025a96572c7bf26c4640b53c7d45e411a5aa99980f6022037964f01a61db1b24ea44137b3d67d7095ec25f68bd7b508e01441e5539d96a9 1", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG NOT", "CHECKDATASIG,NULLFAIL,STRICTENC", "NULLFAIL", "CHECKDATASIG with NULLFAIL flags" ], [ "0x46 0x3044022021309a532a60d471cc4ef025a96572c7bf26c4640b53c7d45e411a5aa99980f6022037964f01a61db1b24ea44137b3d67d7095ec25f68bd7b508e01441e5539d96a9 1", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG NOT", "CHECKDATASIG,STRICTENC", "OK", "CHECKDATASIG without NULLFAIL flags" ], [ "0 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG NOT", "CHECKDATASIG,NULLFAIL,STRICTENC", "OK", "CHECKDATASIG empty signature" ], [ "0x47 0x3045022021309a532a60d471cc4ef025a96572c7bf26c4640b53c7d45e411a5aa99980f6022100c869b0fe59e24e4db15bbec84c29828e24c2b6f02370eb32dfbe1ca77c98aa98 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG", "CHECKDATASIG,NULLFAIL,STRICTENC", "OK", "CHECKDATASIG with High S but no Low S" ], [ "0x47 0x3045022021309a532a60d471cc4ef025a96572c7bf26c4640b53c7d45e411a5aa99980f6022100c869b0fe59e24e4db15bbec84c29828e24c2b6f02370eb32dfbe1ca77c98aa98 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG", "CHECKDATASIG,LOW_S,NULLFAIL,STRICTENC", "SIG_HIGH_S", "CHECKDATASIG with High S" ], [ "0x46 0x3044022093cbfaab2bbef6fc019d1286018fd11e2612d817756d40913b3f82a428f1e90a022045d010bd0f3c31aa470d096bb3f693275214f48d4e727f45a9e0adb2645d7489 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG", "CHECKDATASIG,NULLFAIL", "OK", "CHECKDATASIG with too little R padding but no DERSIG" ], [ "0x46 0x3044022093cbfaab2bbef6fc019d1286018fd11e2612d817756d40913b3f82a428f1e90a022045d010bd0f3c31aa470d096bb3f693275214f48d4e727f45a9e0adb2645d7489 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG", "CHECKDATASIG,NULLFAIL,STRICTENC", "SIG_DER", "CHECKDATASIG with too little R padding" ], [ "0x46 0x304402205ffea7d9fa4e0ce8058c96edfb721aaf2840912080ac4ae86a92d9462e69fde302203567149cb9c8c343523a87d7a64be304983899d2e2c6f267a7136c48ff21908d 0", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIG", "CHECKDATASIG,NULLFAIL", "OK", "CHECKDATASIG with hybrid pubkey but no STRICTENC" ], [ "0x46 0x304402205ffea7d9fa4e0ce8058c96edfb721aaf2840912080ac4ae86a92d9462e69fde302203567149cb9c8c343523a87d7a64be304983899d2e2c6f267a7136c48ff21908d 0", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIG", "CHECKDATASIG,NULLFAIL,STRICTENC", "PUBKEYTYPE", "CHECKDATASIG with hybrid pubkey" ], [ "0x46 0x304402205ffea7d9fa4e0de8058c96edfb721aaf2840912080ac4ae86a92d9462e69fde302203567149cb9c8c343523a87d7a64be304983899d2e2c6f267a7136c48ff21908d 0", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIG NOT", "CHECKDATASIG", "OK", "CHECKDATASIG with invalid hybrid pubkey but no STRICTENC" ], [ "0x46 0x304402205ffea7d9fa4e0de8058c96edfb721aaf2840912080ac4ae86a92d9462e69fde302203567149cb9c8c343523a87d7a64be304983899d2e2c6f267a7136c48ff21908d 0", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIG", "CHECKDATASIG,NULLFAIL,STRICTENC", "PUBKEYTYPE", "CHECKDATASIG with invalid hybrid pubkey" ], [ "0x46 0x3044022021309a532a60d471cc4ef025a96572c7bf26c4640b53c7d45e411a5aa99980f6022037964f01a61db1b24ea44137b3d67d7095ec25f68bd7b508e01441e5539d96a9 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", "CHECKDATASIG,NULLFAIL,STRICTENC", "OK", "Standard CHECKDATASIGVERIFY" ], [ "0x46 0x3044022021309a532a60d471cc4ef025a96572c7bf26c4640b53c7d45e411a5aa99980f6022037964f01a61db1b24ea44137b3d67d7095ec25f68bd7b508e01441e5539d96a9 1", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", "CHECKDATASIG,NULLFAIL,STRICTENC", "NULLFAIL", "CHECKDATASIGVERIFY with NULLFAIL flags" ], [ "0x46 0x3044022021309a532a60d471cc4ef025a96572c7bf26c4640b53c7d45e411a5aa99980f6022037964f01a61db1b24ea44137b3d67d7095ec25f68bd7b508e01441e5539d96a9 1", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", "CHECKDATASIG,STRICTENC", "CHECKDATASIGVERIFY", "CHECKDATASIGVERIFY without NULLFAIL flags" ], [ "0 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", "CHECKDATASIG,NULLFAIL,STRICTENC", "CHECKDATASIGVERIFY", "CHECKDATASIGVERIFY empty signature" ], [ "0x47 0x3045022021309a532a60d471cc4ef025a96572c7bf26c4640b53c7d45e411a5aa99980f6022100c869b0fe59e24e4db15bbec84c29828e24c2b6f02370eb32dfbe1ca77c98aa98 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", "CHECKDATASIG,NULLFAIL,STRICTENC", "OK", "CHECKDATASIG with High S but no Low S" ], [ "0x47 0x3045022021309a532a60d471cc4ef025a96572c7bf26c4640b53c7d45e411a5aa99980f6022100c869b0fe59e24e4db15bbec84c29828e24c2b6f02370eb32dfbe1ca77c98aa98 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", "CHECKDATASIG,LOW_S,NULLFAIL,STRICTENC", "SIG_HIGH_S", "CHECKDATASIG with High S" ], [ "0x46 0x3044022093cbfaab2bbef6fc019d1286018fd11e2612d817756d40913b3f82a428f1e90a022045d010bd0f3c31aa470d096bb3f693275214f48d4e727f45a9e0adb2645d7489 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", "CHECKDATASIG,NULLFAIL", "OK", "CHECKDATASIGVERIFY with too little R padding but no DERSIG" ], [ "0x46 0x3044022093cbfaab2bbef6fc019d1286018fd11e2612d817756d40913b3f82a428f1e90a022045d010bd0f3c31aa470d096bb3f693275214f48d4e727f45a9e0adb2645d7489 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", "CHECKDATASIG,NULLFAIL,STRICTENC", "SIG_DER", "CHECKDATASIGVERIFY with too little R padding" ], [ "0x46 0x304402205ffea7d9fa4e0ce8058c96edfb721aaf2840912080ac4ae86a92d9462e69fde302203567149cb9c8c343523a87d7a64be304983899d2e2c6f267a7136c48ff21908d 0", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIGVERIFY 1", "CHECKDATASIG,NULLFAIL", "OK", "CHECKDATASIGVERIFY with hybrid pubkey but no STRICTENC" ], [ "0x46 0x304402205ffea7d9fa4e0ce8058c96edfb721aaf2840912080ac4ae86a92d9462e69fde302203567149cb9c8c343523a87d7a64be304983899d2e2c6f267a7136c48ff21908d 0", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIGVERIFY 1", "CHECKDATASIG,NULLFAIL,STRICTENC", "PUBKEYTYPE", "CHECKDATASIGVERIFY with hybrid pubkey" ], [ "0x46 0x304402205ffea7d9fa4e0de8058c96edfb721aaf2840912080ac4ae86a92d9462e69fde302203567149cb9c8c343523a87d7a64be304983899d2e2c6f267a7136c48ff21908d 0", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIGVERIFY 1", "CHECKDATASIG", "CHECKDATASIGVERIFY", "CHECKDATASIGVERIFY with invalid hybrid pubkey but no STRICTENC" ], [ "0x46 0x304402205ffea7d9fa4e0de8058c96edfb721aaf2840912080ac4ae86a92d9462e69fde302203567149cb9c8c343523a87d7a64be304983899d2e2c6f267a7136c48ff21908d 0", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIGVERIFY 1", "CHECKDATASIG,NULLFAIL,STRICTENC", "PUBKEYTYPE", "CHECKDATASIGVERIFY with invalid hybrid pubkey" ], [ "0x47 0x3044022022127048516d473153d1f74e46e828496776752e3255f672f760a41e83f54e6f0220502956b739ed82aad916dc4a73e1fd55d02aad514b5211f1ba7d0dadf53c637901", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "SCHNORR", "OK", "P2PK ECDSA with Schnorr flag on" ], [ "0x47 0x3044022022127048516d463153d1f74e46e828496776752e3255f672f760a41e83f54e6f0220502956b739ed82aad916dc4a73e1fd55d02aad514b5211f1ba7d0dadf53c637901", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "SCHNORR", "EVAL_FALSE", "P2PK, bad sig ECDSA with Schnorr flag on" ], [ "0x47 0x304402201e0ec3c6c263f34049c93e0bc646d7287ca2cc6571d658e4e7269daebc96ef35022009841f101e6dcaba8993d0259e5732a871e253be807556bf5618bf0bc3e84af001 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508", "DUP HASH160 0x14 0x1018853670f9f3b0582c5b9ee8ce93764ac32b93 EQUALVERIFY CHECKSIG", "SCHNORR", "OK", "P2PKH ECDSA with Schnorr flag on" ], [ "0 0x47 0x304402205b6256a4755890fe278ea083eddf5c0519d0d7fad14fe265e077c5627171b27e02200d841cb15cdc9a9c8f3ec20c5e4bb1b0e5715d26353f500378f4215195e3558c01 0x47 0x304402200b0620f910e92621934e88ae0177b0bb381ba812d4c23c77afbf1a3ab637a0bb0220275387c859089939e22d803dfae77a4ecd122d951d0feb9e6a65a6918c2b1e0201 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae", "HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL", "P2SH,SCHNORR", "OK", "P2SH(2-of-3) ECDSA with Schnorr flag on" ], [ "0x48 0x3045022032d4a3dec9cad54c94b5585fb058f7e41ac5173843b0c2e7197a40421ee4ab54022100be2b2bd69273d7de44c609cb60febf428e18eb821869006e368b06259318896901", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", "LOW_S,SCHNORR", "SIG_HIGH_S", "LOW_S violating ECDSA with Schnorr flag on" ], [ "0x47 0x304402201162483d0440fc508d79d314a91cfc4df4ea31b302f02c16893fa15d9c9f7f06022032afebdd5b2964c40c887b967f9599e0e5b5ff5b2f899ab62ada12a5af2a481701", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "SCHNORR,STRICTENC", "PUBKEYTYPE", "STRICTENC-violating hybrid pubkey with Schnorr flag on" ], [ "0x46 0x3044022021309a532a60d471cc4ef025a96572c7bf26c4640b53c7d45e411a5aa99980f6022037964f01a61db1b24ea44137b3d67d7095ec25f68bd7b508e01441e5539d96a9 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG", "CHECKDATASIG,NULLFAIL,SCHNORR,STRICTENC", "OK", "Standard CHECKDATASIG" ], [ "0x46 0x3044022021309a532a60d471cc4ef025a96572c7bf26c4640b53c7d45e411a5aa99980f6022037964f01a61db1b24ea44137b3d67d7095ec25f68bd7b508e01441e5539d96a9 1", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG NOT", "CHECKDATASIG,NULLFAIL,SCHNORR,STRICTENC", "NULLFAIL", "CHECKDATASIG with NULLFAIL flags" ], [ "0x46 0x3044022021309a532a60d471cc4ef025a96572c7bf26c4640b53c7d45e411a5aa99980f6022037964f01a61db1b24ea44137b3d67d7095ec25f68bd7b508e01441e5539d96a9 1", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG NOT", "CHECKDATASIG,SCHNORR,STRICTENC", "OK", "CHECKDATASIG without NULLFAIL flags" ], [ "0 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG NOT", "CHECKDATASIG,NULLFAIL,SCHNORR,STRICTENC", "OK", "CHECKDATASIG empty signature" ], [ "0x47 0x3045022021309a532a60d471cc4ef025a96572c7bf26c4640b53c7d45e411a5aa99980f6022100c869b0fe59e24e4db15bbec84c29828e24c2b6f02370eb32dfbe1ca77c98aa98 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG", "CHECKDATASIG,NULLFAIL,SCHNORR,STRICTENC", "OK", "CHECKDATASIG with High S but no Low S" ], [ "0x47 0x3045022021309a532a60d471cc4ef025a96572c7bf26c4640b53c7d45e411a5aa99980f6022100c869b0fe59e24e4db15bbec84c29828e24c2b6f02370eb32dfbe1ca77c98aa98 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG", "CHECKDATASIG,LOW_S,NULLFAIL,SCHNORR,STRICTENC", "SIG_HIGH_S", "CHECKDATASIG with High S" ], [ "0x46 0x3044022093cbfaab2bbef6fc019d1286018fd11e2612d817756d40913b3f82a428f1e90a022045d010bd0f3c31aa470d096bb3f693275214f48d4e727f45a9e0adb2645d7489 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG", "CHECKDATASIG,NULLFAIL,SCHNORR", "OK", "CHECKDATASIG with too little R padding but no DERSIG" ], [ "0x46 0x3044022093cbfaab2bbef6fc019d1286018fd11e2612d817756d40913b3f82a428f1e90a022045d010bd0f3c31aa470d096bb3f693275214f48d4e727f45a9e0adb2645d7489 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG", "CHECKDATASIG,NULLFAIL,SCHNORR,STRICTENC", "SIG_DER", "CHECKDATASIG with too little R padding" ], [ "0x46 0x304402205ffea7d9fa4e0ce8058c96edfb721aaf2840912080ac4ae86a92d9462e69fde302203567149cb9c8c343523a87d7a64be304983899d2e2c6f267a7136c48ff21908d 0", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIG", "CHECKDATASIG,NULLFAIL,SCHNORR", "OK", "CHECKDATASIG with hybrid pubkey but no STRICTENC" ], [ "0x46 0x304402205ffea7d9fa4e0ce8058c96edfb721aaf2840912080ac4ae86a92d9462e69fde302203567149cb9c8c343523a87d7a64be304983899d2e2c6f267a7136c48ff21908d 0", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIG", "CHECKDATASIG,NULLFAIL,SCHNORR,STRICTENC", "PUBKEYTYPE", "CHECKDATASIG with hybrid pubkey" ], [ "0x46 0x304402205ffea7d9fa4e0de8058c96edfb721aaf2840912080ac4ae86a92d9462e69fde302203567149cb9c8c343523a87d7a64be304983899d2e2c6f267a7136c48ff21908d 0", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIG NOT", "CHECKDATASIG", "OK", "CHECKDATASIG with invalid hybrid pubkey but no STRICTENC" ], [ "0x46 0x304402205ffea7d9fa4e0de8058c96edfb721aaf2840912080ac4ae86a92d9462e69fde302203567149cb9c8c343523a87d7a64be304983899d2e2c6f267a7136c48ff21908d 0", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIG", "CHECKDATASIG,NULLFAIL,SCHNORR,STRICTENC", "PUBKEYTYPE", "CHECKDATASIG with invalid hybrid pubkey" ], [ "0x46 0x3044022021309a532a60d471cc4ef025a96572c7bf26c4640b53c7d45e411a5aa99980f6022037964f01a61db1b24ea44137b3d67d7095ec25f68bd7b508e01441e5539d96a9 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", "CHECKDATASIG,NULLFAIL,SCHNORR,STRICTENC", "OK", "Standard CHECKDATASIGVERIFY" ], [ "0x46 0x3044022021309a532a60d471cc4ef025a96572c7bf26c4640b53c7d45e411a5aa99980f6022037964f01a61db1b24ea44137b3d67d7095ec25f68bd7b508e01441e5539d96a9 1", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", "CHECKDATASIG,NULLFAIL,SCHNORR,STRICTENC", "NULLFAIL", "CHECKDATASIGVERIFY with NULLFAIL flags" ], [ "0x46 0x3044022021309a532a60d471cc4ef025a96572c7bf26c4640b53c7d45e411a5aa99980f6022037964f01a61db1b24ea44137b3d67d7095ec25f68bd7b508e01441e5539d96a9 1", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", "CHECKDATASIG,SCHNORR,STRICTENC", "CHECKDATASIGVERIFY", "CHECKDATASIGVERIFY without NULLFAIL flags" ], [ "0 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", "CHECKDATASIG,NULLFAIL,SCHNORR,STRICTENC", "CHECKDATASIGVERIFY", "CHECKDATASIGVERIFY empty signature" ], [ "0x47 0x3045022021309a532a60d471cc4ef025a96572c7bf26c4640b53c7d45e411a5aa99980f6022100c869b0fe59e24e4db15bbec84c29828e24c2b6f02370eb32dfbe1ca77c98aa98 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", "CHECKDATASIG,NULLFAIL,SCHNORR,STRICTENC", "OK", "CHECKDATASIG with High S but no Low S" ], [ "0x47 0x3045022021309a532a60d471cc4ef025a96572c7bf26c4640b53c7d45e411a5aa99980f6022100c869b0fe59e24e4db15bbec84c29828e24c2b6f02370eb32dfbe1ca77c98aa98 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", "CHECKDATASIG,LOW_S,NULLFAIL,SCHNORR,STRICTENC", "SIG_HIGH_S", "CHECKDATASIG with High S" ], [ "0x46 0x3044022093cbfaab2bbef6fc019d1286018fd11e2612d817756d40913b3f82a428f1e90a022045d010bd0f3c31aa470d096bb3f693275214f48d4e727f45a9e0adb2645d7489 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", "CHECKDATASIG,NULLFAIL,SCHNORR", "OK", "CHECKDATASIGVERIFY with too little R padding but no DERSIG" ], [ "0x46 0x3044022093cbfaab2bbef6fc019d1286018fd11e2612d817756d40913b3f82a428f1e90a022045d010bd0f3c31aa470d096bb3f693275214f48d4e727f45a9e0adb2645d7489 0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", "CHECKDATASIG,NULLFAIL,SCHNORR,STRICTENC", "SIG_DER", "CHECKDATASIGVERIFY with too little R padding" ], [ "0x46 0x304402205ffea7d9fa4e0ce8058c96edfb721aaf2840912080ac4ae86a92d9462e69fde302203567149cb9c8c343523a87d7a64be304983899d2e2c6f267a7136c48ff21908d 0", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIGVERIFY 1", "CHECKDATASIG,NULLFAIL,SCHNORR", "OK", "CHECKDATASIGVERIFY with hybrid pubkey but no STRICTENC" ], [ "0x46 0x304402205ffea7d9fa4e0ce8058c96edfb721aaf2840912080ac4ae86a92d9462e69fde302203567149cb9c8c343523a87d7a64be304983899d2e2c6f267a7136c48ff21908d 0", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIGVERIFY 1", "CHECKDATASIG,NULLFAIL,SCHNORR,STRICTENC", "PUBKEYTYPE", "CHECKDATASIGVERIFY with hybrid pubkey" ], [ "0x46 0x304402205ffea7d9fa4e0de8058c96edfb721aaf2840912080ac4ae86a92d9462e69fde302203567149cb9c8c343523a87d7a64be304983899d2e2c6f267a7136c48ff21908d 0", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIGVERIFY 1", "CHECKDATASIG", "CHECKDATASIGVERIFY", "CHECKDATASIGVERIFY with invalid hybrid pubkey but no STRICTENC" ], [ "0x46 0x304402205ffea7d9fa4e0de8058c96edfb721aaf2840912080ac4ae86a92d9462e69fde302203567149cb9c8c343523a87d7a64be304983899d2e2c6f267a7136c48ff21908d 0", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIGVERIFY 1", "CHECKDATASIG,NULLFAIL,SCHNORR,STRICTENC", "PUBKEYTYPE", "CHECKDATASIGVERIFY with invalid hybrid pubkey" ], [ "0x41 0x0df4be7f5fe74b2855b92082720e889038e15d8d747334fa3f300ef4ab1db1eea56aa83d1d60809ff6703791736be87cfb6cbc5c4036aeed3b4ea4e6dab3509001", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "", "EVAL_FALSE", "CHECKSIG Schnorr w/ neither STRICTENC,SCHNORR" ], [ "0x47 0x3044022022127048516d473153d1f74e46e828496776752e3255f672f760a41e83f54e6f0220502956b739ed82aad916dc4a73e1fd55d02aad514b5211f1ba7d0dadf53c637901", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "", "OK", "CHECKSIG ECDSA w/ neither STRICTENC,SCHNORR" ], [ "0x41 0x0df4be7f5fe74b2855b92082720e889038e15d8d747334fa3f300ef4ab1db1eea56aa83d1d60809ff6703791736be87cfb6cbc5c4036aeed3b4ea4e6dab3509001", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "SCHNORR", "OK", "CHECKSIG Schnorr w/ SCHNORR" ], [ "0x47 0x3044022022127048516d473153d1f74e46e828496776752e3255f672f760a41e83f54e6f0220502956b739ed82aad916dc4a73e1fd55d02aad514b5211f1ba7d0dadf53c637901", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "SCHNORR", "OK", "CHECKSIG ECDSA w/ SCHNORR" ], [ "0x41 0x0df4be7f5fe74b2855b92082720e889038e15d8d747334fa3f300ef4ab1db1eea56aa83d1d60809ff6703791736be87cfb6cbc5c4036aeed3b4ea4e6dab3509001", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "STRICTENC", "SIG_DER", "CHECKSIG Schnorr w/ STRICTENC" ], [ "0x47 0x3044022022127048516d473153d1f74e46e828496776752e3255f672f760a41e83f54e6f0220502956b739ed82aad916dc4a73e1fd55d02aad514b5211f1ba7d0dadf53c637901", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "STRICTENC", "OK", "CHECKSIG ECDSA w/ STRICTENC" ], [ "0x41 0x0df4be7f5fe74b2855b92082720e889038e15d8d747334fa3f300ef4ab1db1eea56aa83d1d60809ff6703791736be87cfb6cbc5c4036aeed3b4ea4e6dab3509001", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "SCHNORR,STRICTENC", "OK", "CHECKSIG Schnorr w/ STRICTENC,SCHNORR" ], [ "0x47 0x3044022022127048516d473153d1f74e46e828496776752e3255f672f760a41e83f54e6f0220502956b739ed82aad916dc4a73e1fd55d02aad514b5211f1ba7d0dadf53c637901", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "SCHNORR,STRICTENC", "OK", "CHECKSIG ECDSA w/ STRICTENC,SCHNORR" ], [ "0x41 0x3cf1b3f60b74d0821039f7dc7c21abe3119b9d94ae13f5e5258a8269bee9dfc51c84dbb3ba3eff82de61046f6cfef22ea5cf4a46e3776a5fb35d743aea310f6701", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", "SCHNORR,STRICTENC", "OK", "CHECKSIG Schnorr other key" ], [ "0x41 0x35b32856cbd89eb40130a50c6931ce002e3e9db033179ab6265a276a04795ec8f87e9b4d8343f399915371d7f4a7d4d0c97753f2473b253197695a58eede92de01", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", "SCHNORR,STRICTENC", "OK", "CHECKSIG Schnorr mismatched key" ], [ "0x41 0x8d37e95e36718d7fbc8ffd63b0b4ebb89dd5fb683510a95345869399f810a8724a00e5cbbb2190205ffabac601d80bf110a67013521b7a7c02b2a51e07d723eb01", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIGVERIFY 1", "", "CHECKSIGVERIFY", "CHECKSIGVERIFY Schnorr w/ neither STRICTENC,SCHNORR" ], [ "0x47 0x304402205d5a925acf881167da7850d838cd4f73d077d08aacf9d2885d10b7850c5a828602201f42383e317ec427dbd71f3a6031a0ff27e431b7089fbc80ebea31b5f8949be601", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIGVERIFY 1", "", "OK", "CHECKSIGVERIFY ECDSA w/ neither STRICTENC,SCHNORR" ], [ "0x41 0x8d37e95e36718d7fbc8ffd63b0b4ebb89dd5fb683510a95345869399f810a8724a00e5cbbb2190205ffabac601d80bf110a67013521b7a7c02b2a51e07d723eb01", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIGVERIFY 1", "SCHNORR", "OK", "CHECKSIGVERIFY Schnorr w/ SCHNORR" ], [ "0x47 0x304402205d5a925acf881167da7850d838cd4f73d077d08aacf9d2885d10b7850c5a828602201f42383e317ec427dbd71f3a6031a0ff27e431b7089fbc80ebea31b5f8949be601", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIGVERIFY 1", "SCHNORR", "OK", "CHECKSIGVERIFY ECDSA w/ SCHNORR" ], [ "0x41 0x8d37e95e36718d7fbc8ffd63b0b4ebb89dd5fb683510a95345869399f810a8724a00e5cbbb2190205ffabac601d80bf110a67013521b7a7c02b2a51e07d723eb01", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIGVERIFY 1", "STRICTENC", "SIG_DER", "CHECKSIGVERIFY Schnorr w/ STRICTENC" ], [ "0x47 0x304402205d5a925acf881167da7850d838cd4f73d077d08aacf9d2885d10b7850c5a828602201f42383e317ec427dbd71f3a6031a0ff27e431b7089fbc80ebea31b5f8949be601", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIGVERIFY 1", "STRICTENC", "OK", "CHECKSIGVERIFY ECDSA w/ STRICTENC" ], [ "0x41 0x8d37e95e36718d7fbc8ffd63b0b4ebb89dd5fb683510a95345869399f810a8724a00e5cbbb2190205ffabac601d80bf110a67013521b7a7c02b2a51e07d723eb01", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIGVERIFY 1", "SCHNORR,STRICTENC", "OK", "CHECKSIGVERIFY Schnorr w/ STRICTENC,SCHNORR" ], [ "0x47 0x304402205d5a925acf881167da7850d838cd4f73d077d08aacf9d2885d10b7850c5a828602201f42383e317ec427dbd71f3a6031a0ff27e431b7089fbc80ebea31b5f8949be601", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIGVERIFY 1", "SCHNORR,STRICTENC", "OK", "CHECKSIGVERIFY ECDSA w/ STRICTENC,SCHNORR" ], [ "0x41 0x53c4de3cb6a0190073c98fa415f63b720ea491748c9a760d5d249bb05f13990aa464be04b625cc36cd9e302dc276ad232d5d65d6327bdb18b7c529300d67013f01", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIGVERIFY 1", "SCHNORR,STRICTENC", "OK", "CHECKSIGVERIFY Schnorr other key" ], [ "0x41 0x74c51dae216d8ebee5418204cf90839ea9a288b93eccb1de54b5b5d06bcd69c7028e1b3c6643c001403e7862bee6be39c107e5c8d0a9a8e9143862e5d73c555a01", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIGVERIFY 1", "SCHNORR,STRICTENC", "CHECKSIGVERIFY", "CHECKSIGVERIFY Schnorr mismatched key" ], [ "0x40 0x9db0671f61f1fafa84aaab76ad2e070b27cf9ae85338bafc0b947ac9ad8c56ff7b24aa76c95ad86bb13cbff314742dbe1f545869d1a28efa54b411ccd37717e5", "0 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIG", "CHECKDATASIG", "EVAL_FALSE", "CHECKDATASIG Schnorr w/ neither STRICTENC,SCHNORR" ], [ "0x46 0x304402205ffea7d9fa4e0ce8058c96edfb721aaf2840912080ac4ae86a92d9462e69fde302203567149cb9c8c343523a87d7a64be304983899d2e2c6f267a7136c48ff21908d", "0 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIG", "CHECKDATASIG", "OK", "CHECKDATASIG ECDSA w/ neither STRICTENC,SCHNORR" ], [ "0x40 0x9db0671f61f1fafa84aaab76ad2e070b27cf9ae85338bafc0b947ac9ad8c56ff7b24aa76c95ad86bb13cbff314742dbe1f545869d1a28efa54b411ccd37717e5", "0 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIG", "CHECKDATASIG,SCHNORR", "OK", "CHECKDATASIG Schnorr w/ SCHNORR" ], [ "0x46 0x304402205ffea7d9fa4e0ce8058c96edfb721aaf2840912080ac4ae86a92d9462e69fde302203567149cb9c8c343523a87d7a64be304983899d2e2c6f267a7136c48ff21908d", "0 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIG", "CHECKDATASIG,SCHNORR", "OK", "CHECKDATASIG ECDSA w/ SCHNORR" ], [ "0x40 0x9db0671f61f1fafa84aaab76ad2e070b27cf9ae85338bafc0b947ac9ad8c56ff7b24aa76c95ad86bb13cbff314742dbe1f545869d1a28efa54b411ccd37717e5", "0 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIG", "CHECKDATASIG,STRICTENC", "SIG_DER", "CHECKDATASIG Schnorr w/ STRICTENC" ], [ "0x46 0x304402205ffea7d9fa4e0ce8058c96edfb721aaf2840912080ac4ae86a92d9462e69fde302203567149cb9c8c343523a87d7a64be304983899d2e2c6f267a7136c48ff21908d", "0 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIG", "CHECKDATASIG,STRICTENC", "OK", "CHECKDATASIG ECDSA w/ STRICTENC" ], [ "0x40 0x9db0671f61f1fafa84aaab76ad2e070b27cf9ae85338bafc0b947ac9ad8c56ff7b24aa76c95ad86bb13cbff314742dbe1f545869d1a28efa54b411ccd37717e5", "0 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIG", "CHECKDATASIG,SCHNORR,STRICTENC", "OK", "CHECKDATASIG Schnorr w/ STRICTENC,SCHNORR" ], [ "0x46 0x304402205ffea7d9fa4e0ce8058c96edfb721aaf2840912080ac4ae86a92d9462e69fde302203567149cb9c8c343523a87d7a64be304983899d2e2c6f267a7136c48ff21908d", "0 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIG", "CHECKDATASIG,SCHNORR,STRICTENC", "OK", "CHECKDATASIG ECDSA w/ STRICTENC,SCHNORR" ], [ "0x40 0x65c4bceda6ebb49e692180387e72c84be500f3431daac85d08d5d6c527e296f5b8a5b868a681f76aee309ad05e152b4f190732b3e7c46ef788b68c6035f6eab0", "0 0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKDATASIG", "CHECKDATASIG,SCHNORR,STRICTENC", "OK", "CHECKDATASIG Schnorr other key" ], [ "0x40 0x65c4bceda6ebb49e692180387e72c84be500f3431daac85d08d5d6c527e296f5b8a5b868a681f76aee309ad05e152b4f190732b3e7c46ef788b68c6035f6eab0", "0 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIG NOT", "CHECKDATASIG,SCHNORR,STRICTENC", "OK", "CHECKDATASIG Schnorr mismatched key" ], [ "0x40 0xe20d68eea1c55d8c23310ef33b4c68e3d876b1c5a36595f4dcc9d728894c957879e53bb4aebf8b3aa36861d89266ff864d2c3f513ab6f79c9d226ad45fbf5407", "1 0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKDATASIG", "CHECKDATASIG,SCHNORR,STRICTENC", "OK", "CHECKDATASIG Schnorr other message" ], [ "0x40 0xe20d68eea1c55d8c23310ef33b4c68e3d876b1c5a36595f4dcc9d728894c957879e53bb4aebf8b3aa36861d89266ff864d2c3f513ab6f79c9d226ad45fbf5407", "0 0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKDATASIG NOT", "CHECKDATASIG,SCHNORR,STRICTENC", "OK", "CHECKDATASIG Schnorr wrong message" ], [ "0x40 0x9db0671f61f1fafa84aaab76ad2e070b27cf9ae85338bafc0b947ac9ad8c56ff7b24aa76c95ad86bb13cbff314742dbe1f545869d1a28efa54b411ccd37717e5", "0 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIGVERIFY 1", "CHECKDATASIG", "CHECKDATASIGVERIFY", "CHECKDATASIGVERIFY Schnorr w/ neither STRICTENC,SCHNORR" ], [ "0x46 0x304402205ffea7d9fa4e0ce8058c96edfb721aaf2840912080ac4ae86a92d9462e69fde302203567149cb9c8c343523a87d7a64be304983899d2e2c6f267a7136c48ff21908d", "0 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIGVERIFY 1", "CHECKDATASIG", "OK", "CHECKDATASIGVERIFY ECDSA w/ neither STRICTENC,SCHNORR" ], [ "0x40 0x9db0671f61f1fafa84aaab76ad2e070b27cf9ae85338bafc0b947ac9ad8c56ff7b24aa76c95ad86bb13cbff314742dbe1f545869d1a28efa54b411ccd37717e5", "0 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIGVERIFY 1", "CHECKDATASIG,SCHNORR", "OK", "CHECKDATASIGVERIFY Schnorr w/ SCHNORR" ], [ "0x46 0x304402205ffea7d9fa4e0ce8058c96edfb721aaf2840912080ac4ae86a92d9462e69fde302203567149cb9c8c343523a87d7a64be304983899d2e2c6f267a7136c48ff21908d", "0 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIGVERIFY 1", "CHECKDATASIG,SCHNORR", "OK", "CHECKDATASIGVERIFY ECDSA w/ SCHNORR" ], [ "0x40 0x9db0671f61f1fafa84aaab76ad2e070b27cf9ae85338bafc0b947ac9ad8c56ff7b24aa76c95ad86bb13cbff314742dbe1f545869d1a28efa54b411ccd37717e5", "0 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIGVERIFY 1", "CHECKDATASIG,STRICTENC", "SIG_DER", "CHECKDATASIGVERIFY Schnorr w/ STRICTENC" ], [ "0x46 0x304402205ffea7d9fa4e0ce8058c96edfb721aaf2840912080ac4ae86a92d9462e69fde302203567149cb9c8c343523a87d7a64be304983899d2e2c6f267a7136c48ff21908d", "0 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIGVERIFY 1", "CHECKDATASIG,STRICTENC", "OK", "CHECKDATASIGVERIFY ECDSA w/ STRICTENC" ], [ "0x40 0x9db0671f61f1fafa84aaab76ad2e070b27cf9ae85338bafc0b947ac9ad8c56ff7b24aa76c95ad86bb13cbff314742dbe1f545869d1a28efa54b411ccd37717e5", "0 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIGVERIFY 1", "CHECKDATASIG,SCHNORR,STRICTENC", "OK", "CHECKDATASIGVERIFY Schnorr w/ STRICTENC,SCHNORR" ], [ "0x46 0x304402205ffea7d9fa4e0ce8058c96edfb721aaf2840912080ac4ae86a92d9462e69fde302203567149cb9c8c343523a87d7a64be304983899d2e2c6f267a7136c48ff21908d", "0 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIGVERIFY 1", "CHECKDATASIG,SCHNORR,STRICTENC", "OK", "CHECKDATASIGVERIFY ECDSA w/ STRICTENC,SCHNORR" ], [ "0x40 0x65c4bceda6ebb49e692180387e72c84be500f3431daac85d08d5d6c527e296f5b8a5b868a681f76aee309ad05e152b4f190732b3e7c46ef788b68c6035f6eab0", "0 0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKDATASIGVERIFY 1", "CHECKDATASIG,SCHNORR,STRICTENC", "OK", "CHECKDATASIGVERIFY Schnorr other key" ], [ "0x40 0x65c4bceda6ebb49e692180387e72c84be500f3431daac85d08d5d6c527e296f5b8a5b868a681f76aee309ad05e152b4f190732b3e7c46ef788b68c6035f6eab0", "0 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIGVERIFY 1", "CHECKDATASIG,SCHNORR,STRICTENC", "CHECKDATASIGVERIFY", "CHECKDATASIGVERIFY Schnorr mismatched key" ], [ "0x40 0xe20d68eea1c55d8c23310ef33b4c68e3d876b1c5a36595f4dcc9d728894c957879e53bb4aebf8b3aa36861d89266ff864d2c3f513ab6f79c9d226ad45fbf5407", "1 0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKDATASIGVERIFY 1", "CHECKDATASIG,SCHNORR,STRICTENC", "OK", "CHECKDATASIGVERIFY Schnorr other message" ], [ "0x40 0xe20d68eea1c55d8c23310ef33b4c68e3d876b1c5a36595f4dcc9d728894c957879e53bb4aebf8b3aa36861d89266ff864d2c3f513ab6f79c9d226ad45fbf5407", "0 0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKDATASIGVERIFY 1", "CHECKDATASIG,SCHNORR,STRICTENC", "CHECKDATASIGVERIFY", "CHECKDATASIGVERIFY Schnorr wrong message" ], [ "0 0x41 0x105e4fed395e64ca013ac1ce020ef69b9990a577fe4b74648faafb69e499f76dd53d5c64aa866924361dd3aadde9b7184bbcb4f79520396c9ed17c4d8489a59701", "1 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 1 CHECKMULTISIG", "", "EVAL_FALSE", "CHECKMULTISIG Schnorr w/ neither STRICTENC,SCHNORR" ], [ "0 0x47 0x304402204d0106d6babcaca95277692eaa566bdc89d9f44b1106c18423345c7e9ac40d79022033a3750421038d15f15101ffdca1147a0eb980bb1b809280cb5368c50c10c42c01", "1 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 1 CHECKMULTISIG", "", "OK", "CHECKMULTISIG ECDSA w/ neither STRICTENC,SCHNORR" ], [ "0 0x41 0x105e4fed395e64ca013ac1ce020ef69b9990a577fe4b74648faafb69e499f76dd53d5c64aa866924361dd3aadde9b7184bbcb4f79520396c9ed17c4d8489a59701", "1 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 1 CHECKMULTISIG", "SCHNORR", "SIG_BADLENGTH", "CHECKMULTISIG Schnorr w/ SCHNORR" ], [ "0 0x47 0x304402204d0106d6babcaca95277692eaa566bdc89d9f44b1106c18423345c7e9ac40d79022033a3750421038d15f15101ffdca1147a0eb980bb1b809280cb5368c50c10c42c01", "1 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 1 CHECKMULTISIG", "SCHNORR", "OK", "CHECKMULTISIG ECDSA w/ SCHNORR" ], [ "0 0x41 0x105e4fed395e64ca013ac1ce020ef69b9990a577fe4b74648faafb69e499f76dd53d5c64aa866924361dd3aadde9b7184bbcb4f79520396c9ed17c4d8489a59701", "1 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 1 CHECKMULTISIG", "STRICTENC", "SIG_DER", "CHECKMULTISIG Schnorr w/ STRICTENC" ], [ "0 0x47 0x304402204d0106d6babcaca95277692eaa566bdc89d9f44b1106c18423345c7e9ac40d79022033a3750421038d15f15101ffdca1147a0eb980bb1b809280cb5368c50c10c42c01", "1 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 1 CHECKMULTISIG", "STRICTENC", "OK", "CHECKMULTISIG ECDSA w/ STRICTENC" ], [ "0 0x41 0x105e4fed395e64ca013ac1ce020ef69b9990a577fe4b74648faafb69e499f76dd53d5c64aa866924361dd3aadde9b7184bbcb4f79520396c9ed17c4d8489a59701", "1 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 1 CHECKMULTISIG", "SCHNORR,STRICTENC", "SIG_BADLENGTH", "CHECKMULTISIG Schnorr w/ STRICTENC,SCHNORR" ], [ "0 0x47 0x304402204d0106d6babcaca95277692eaa566bdc89d9f44b1106c18423345c7e9ac40d79022033a3750421038d15f15101ffdca1147a0eb980bb1b809280cb5368c50c10c42c01", "1 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 1 CHECKMULTISIG", "SCHNORR,STRICTENC", "OK", "CHECKMULTISIG ECDSA w/ STRICTENC,SCHNORR" ], [ "0 0x41 0x833682d4f60cc916a22a2c263e658fa662c49badb1e2a8c6208987bf99b1abd740498371480069e7a7a6e7471bf78c27bd9a1fd04fb212a92017346250ac187b01 0x41 0xea4a8d20562a950f4695dc24804565482e9fa111704886179d0c348f2b8a15fe691a305cd599c59c131677146661d5b98cb935330989a85f33afc70d0a21add101 0x41 0xce9011d76a4df05d6280b2382b4d91490dbec7c3e72dc826be1fc9b4718f627955190745cac96521ea46d6d324c7376461e225310e6cd605b9f266d170769b7901", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", "", "EVAL_FALSE", "Schnorr 3-of-3 without SCHNORR flag" ], [ "0 0x41 0x833682d4f60cc916a22a2c263e658fa662c49badb1e2a8c6208987bf99b1abd740498371480069e7a7a6e7471bf78c27bd9a1fd04fb212a92017346250ac187b01 0x41 0xea4a8d20562a950f4695dc24804565482e9fa111704886179d0c348f2b8a15fe691a305cd599c59c131677146661d5b98cb935330989a85f33afc70d0a21add101 0x41 0xce9011d76a4df05d6280b2382b4d91490dbec7c3e72dc826be1fc9b4718f627955190745cac96521ea46d6d324c7376461e225310e6cd605b9f266d170769b7901", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", "SCHNORR", "SIG_BADLENGTH", "Schnorr 3-of-3 with SCHNORR flag" ], [ "0 0x47 0x304402204d69d5caa4dbab259f79fce89d3b459bbd91697c1c052a1554ff3b08b2241cbd0220330a8e17a90d51996e363cb8902fce6278c6350fa59ae12832db2f6a44d64dce01 0x47 0x3044022031a1e5289b0d9c33ec182a7f67210b9997187c710f7d3f0f28bdfb618c4e025c02205d95fe63ee83a20ec44159a06f7c0b43b61d5f0c346ca4a2cc7b91878ad1a85001 0x41 0xce9011d76a4df05d6280b2382b4d91490dbec7c3e72dc826be1fc9b4718f627955190745cac96521ea46d6d324c7376461e225310e6cd605b9f266d170769b7901", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", "SCHNORR", "SIG_BADLENGTH", "Schnorr-ECDSA-mixed 3-of-3 with SCHNORR flag" ], [ "0 0x41 0x17fa4dd3e62694cc7816d32b73d5646ea768072aea4926a09e159e5f57be8fd6523800b259fe2a12e27aa29a3719f19e9e4b99d7f8e465a6f19454f914ccb3ec01", "1 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 1 CHECKMULTISIGVERIFY 1", "", "CHECKMULTISIGVERIFY", "CHECKMULTISIGVERIFY Schnorr w/ neither STRICTENC,SCHNORR" ], [ "0 0x47 0x3044022050635b0b57b07eec8ebba4f5cad9ede25ada7ca1645367dcce8d4412290f00e4022037cf466f1498830d5476cd52e84ce4fd6dc4c7d70f985a6e9ff68a034faa5ea101", "1 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 1 CHECKMULTISIGVERIFY 1", "", "OK", "CHECKMULTISIGVERIFY ECDSA w/ neither STRICTENC,SCHNORR" ], [ "0 0x41 0x17fa4dd3e62694cc7816d32b73d5646ea768072aea4926a09e159e5f57be8fd6523800b259fe2a12e27aa29a3719f19e9e4b99d7f8e465a6f19454f914ccb3ec01", "1 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 1 CHECKMULTISIGVERIFY 1", "SCHNORR", "SIG_BADLENGTH", "CHECKMULTISIGVERIFY Schnorr w/ SCHNORR" ], [ "0 0x47 0x3044022050635b0b57b07eec8ebba4f5cad9ede25ada7ca1645367dcce8d4412290f00e4022037cf466f1498830d5476cd52e84ce4fd6dc4c7d70f985a6e9ff68a034faa5ea101", "1 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 1 CHECKMULTISIGVERIFY 1", "SCHNORR", "OK", "CHECKMULTISIGVERIFY ECDSA w/ SCHNORR" ], [ "0 0x41 0x17fa4dd3e62694cc7816d32b73d5646ea768072aea4926a09e159e5f57be8fd6523800b259fe2a12e27aa29a3719f19e9e4b99d7f8e465a6f19454f914ccb3ec01", "1 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 1 CHECKMULTISIGVERIFY 1", "STRICTENC", "SIG_DER", "CHECKMULTISIGVERIFY Schnorr w/ STRICTENC" ], [ "0 0x47 0x3044022050635b0b57b07eec8ebba4f5cad9ede25ada7ca1645367dcce8d4412290f00e4022037cf466f1498830d5476cd52e84ce4fd6dc4c7d70f985a6e9ff68a034faa5ea101", "1 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 1 CHECKMULTISIGVERIFY 1", "STRICTENC", "OK", "CHECKMULTISIGVERIFY ECDSA w/ STRICTENC" ], [ "0 0x41 0x17fa4dd3e62694cc7816d32b73d5646ea768072aea4926a09e159e5f57be8fd6523800b259fe2a12e27aa29a3719f19e9e4b99d7f8e465a6f19454f914ccb3ec01", "1 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 1 CHECKMULTISIGVERIFY 1", "SCHNORR,STRICTENC", "SIG_BADLENGTH", "CHECKMULTISIGVERIFY Schnorr w/ STRICTENC,SCHNORR" ], [ "0 0x47 0x3044022050635b0b57b07eec8ebba4f5cad9ede25ada7ca1645367dcce8d4412290f00e4022037cf466f1498830d5476cd52e84ce4fd6dc4c7d70f985a6e9ff68a034faa5ea101", "1 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 1 CHECKMULTISIGVERIFY 1", "SCHNORR,STRICTENC", "OK", "CHECKMULTISIGVERIFY ECDSA w/ STRICTENC,SCHNORR" ], [ "0x41 0x6f1b69791cd7284b5510daef44cd5acd5c1f3d61f6a79705e18f106b46122f1ed8c5965f3c92c90943f9b51f57207e9e5b7fc462571281e2c92377e4ef20ab2b01", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", "SCHNORR", "OK", "Schnorr P2PK, bad sig" ], [ "0x41 0x6f1b69791cd7284b5510daef44cd5acd5c1f3d61f6a79705e18f106b46122f1ed8c5965f3c92c90943f9b51f57207e9e5b7fc462571281e2c92377e4ef20ab2b01", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", "SCHNORR,STRICTENC", "OK", "Schnorr P2PK, bad sig STRICTENC" ], [ "0x41 0x6f1b69791cd7284b5510daef44cd5acd5c1f3d61f6a79705e18f106b46122f1ed8c5965f3c92c90943f9b51f57207e9e5b7fc462571281e2c92377e4ef20ab2b01", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", "NULLFAIL,SCHNORR", "NULLFAIL", "Schnorr P2PK, bad sig NULLFAIL" ], [ "0x41 0x4463c103b21e76713571365c4c09224c2a1b343b3cf02e3b56f4f0890a6e7ff96d0bfa2ffa22f8067db3414cc1789abfc48638cb4bc7463907042975f4c84ece01 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508", "DUP HASH160 0x14 0x1018853670f9f3b0582c5b9ee8ce93764ac32b93 EQUALVERIFY CHECKSIG", "SCHNORR", "OK", "Schnorr P2PKH" ], [ "0x41 0xd78d543b601bc93b394b5c669933d16d860dc7480383efcaae9521d6ceb4065ba17c02a6d9289efef762fa7a0482eff9c5bce4dd95f8bea421ee70bdd8d5488d01", "0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 CHECKSIG", "SCHNORR,STRICTENC", "OK", "Schnorr P2PK with compressed pubkey" ], [ "0x41 0x0df4be7f5fe74b2855b92082720e889038e15d8d747334fa3f300ef4ab1db1eea56aa83d1d60809ff6703791736be87cfb6cbc5c4036aeed3b4ea4e6dab3509001", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "SCHNORR,STRICTENC", "OK", "Schnorr P2PK with uncompressed pubkey" ], [ "0x41 0x0df4be7f5fe74b2855b92082720e889038e15d8d747334fa3f300ef4ab1db1eea56aa83d1d60809ff6703791736be87cfb6cbc5c4036aeed3b4ea4e6dab3509001", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "COMPRESSED_PUBKEYTYPE,SCHNORR,STRICTENC", "NONCOMPRESSED_PUBKEY", "Schnorr P2PK with uncompressed pubkey but COMPRESSED_PUBKEYTYPE set" ], [ "0x41 0xd211631fdebf4c8376b3d169ef65a1987460eda43c3312e561b0226fa3069f68a68bac0dbf780f77dd60ff602c66186f1da2bb0a31f10187796242f48295ddbe01", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "SCHNORR,STRICTENC", "PUBKEYTYPE", "Schnorr P2PK with hybrid pubkey" ], [ "0x41 0xd211631fdebf4c8376b3d169ef65a1987460eda43c3312e561b0226fa3069f68a68bac0dbf780f77dd60ff602c66186f1da2bb0a31f10187796242f48295ddbe01", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "SCHNORR", "OK", "Schnorr P2PK with hybrid pubkey but no STRICTENC" ], [ "0x41 0x078b6b4e7d0689f3a1ef9b5283039c39b7ab3a26c04143017ee7136edbc1ccbcf47173c92c5823b778e4aaba3bf9ef2e988eb54c4cb709dbfa8e62110843c19901", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", "SCHNORR", "OK", "Schnorr P2PK NOT with damaged hybrid pubkey but no STRICTENC" ], [ "0x41 0xa522c6aab80595e0fdaf473c89a32e97978858809949fafd6f851254daae231f45338fe53187f79d8507f08c08f8bd2ee795e6ccaca0a04c4e40c613395a685b05", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", "SCHNORR,STRICTENC", "SIG_HASHTYPE", "Schnorr P2PK with undefined basehashtype and STRICTENC" ], [ "0x41 0x128f02ec5b36057a7f3793c5ffdef9e6cca0ea3200a2f07e5c7189a267daafc4feb2b65a8c7f22b203557fef4c078e98382dc99939666b7c6dbcc62bd25b0bf821 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", "DUP HASH160 0x14 0x91b24bf9f5288532960ac687abb035127b1d28a5 EQUALVERIFY CHECKSIG", "SCHNORR", "OK", "Schnorr P2PKH with invalid sighashtype but no STRICTENC" ], [ "0x41 0x128f02ec5b36057a7f3793c5ffdef9e6cca0ea3200a2f07e5c7189a267daafc4feb2b65a8c7f22b203557fef4c078e98382dc99939666b7c6dbcc62bd25b0bf821 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", "DUP HASH160 0x14 0x91b24bf9f5288532960ac687abb035127b1d28a5 EQUALVERIFY CHECKSIG", "SCHNORR,STRICTENC", "SIG_HASHTYPE", "Schnorr P2PKH with invalid sighashtype and STRICTENC" ], [ "0x41 0x3dae009b3fc84066b644b0508d1cc68fbbdefbb91b049aaa46e8de5c3b4598707d93df80a275022354f8e3e65ca6561c55d2f626c8395d237fb1f2b6b93e83f081", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", "SCHNORR", "OK", "Schnorr P2PK anyonecanpay" ], [ "0x41 0x3dae009b3fc84066b644b0508d1cc68fbbdefbb91b049aaa46e8de5c3b4598707d93df80a275022354f8e3e65ca6561c55d2f626c8395d237fb1f2b6b93e83f001", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", "SCHNORR", "EVAL_FALSE", "Schnorr P2PK anyonecanpay marked with normal hashtype" ], [ "0x41 0xd06f2e8e262a974d330c185acdd2eed99622f2c9cc0980eacf976f37965186dba2564a564e8c6697127d9729e6cedd44060ab7ece5c2f0ded2ad3f9a7308c7ce41", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", "SCHNORR,SIGHASH_FORKID,STRICTENC", "OK", "Schnorr P2PK with forkID" ], [ "0x41 0x3cf1b3f60b74d0821039f7dc7c21abe3119b9d94ae13f5e5258a8269bee9dfc51c84dbb3ba3eff82de61046f6cfef22ea5cf4a46e3776a5fb35d743aea310f6701", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", "SCHNORR,SIGHASH_FORKID,STRICTENC", "MISSING_FORKID", "Schnorr P2PK with non-forkID sig" ], [ "0x41 0x3cf1b3f60b74d0821039f7dc7c21abe3119b9d94ae13f5e5258a8269bee9dfc51c84dbb3ba3eff82de61046f6cfef22ea5cf4a46e3776a5fb35d743aea310f6741", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", "SCHNORR,SIGHASH_FORKID,STRICTENC", "EVAL_FALSE", "Schnorr P2PK with cheater forkID bit" ], [ "0x16 0x001491b24bf9f5288532960ac687abb035127b1d28a5", "HASH160 0x14 0x17743beb429c55c942d2ec703b98c4d57c2df5c6 EQUAL", "CLEANSTACK,P2SH", "CLEANSTACK", "v0 P2SH-P2WPKH but no SCRIPT_ALLOW_SEGWIT_RECOVERY" ], [ "0x16 0x001491b24bf9f5288532960ac687abb035127b1d28a5", "HASH160 0x14 0x17743beb429c55c942d2ec703b98c4d57c2df5c6 EQUAL", "ALLOW_SEGWIT_RECOVERY,CLEANSTACK,P2SH", "OK", "v0 P2SH-P2WPKH with SCRIPT_ALLOW_SEGWIT_RECOVERY" ], [ "0 0x16 0x001491b24bf9f5288532960ac687abb035127b1d28a5", "HASH160 0x14 0x17743beb429c55c942d2ec703b98c4d57c2df5c6 EQUAL", "ALLOW_SEGWIT_RECOVERY,CLEANSTACK,P2SH", "CLEANSTACK", "v0 P2SH-P2WPKH with extra stack item and SCRIPT_ALLOW_SEGWIT_RECOVERY" ], [ "0x22 0x00205a0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "HASH160 0x14 0x17a6be2f8fe8e94f033e53d17beefda0f3ac4409 EQUAL", "CLEANSTACK,P2SH", "CLEANSTACK", "v0 P2SH-P2WSH but no SCRIPT_ALLOW_SEGWIT_RECOVERY" ], [ "0x22 0x00205a0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "HASH160 0x14 0x17a6be2f8fe8e94f033e53d17beefda0f3ac4409 EQUAL", "ALLOW_SEGWIT_RECOVERY,CLEANSTACK,P2SH", "OK", "v0 P2SH-P2WSH with SCRIPT_ALLOW_SEGWIT_RECOVERY" ], [ "0 0x22 0x00205a0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "HASH160 0x14 0x17a6be2f8fe8e94f033e53d17beefda0f3ac4409 EQUAL", "ALLOW_SEGWIT_RECOVERY,CLEANSTACK,P2SH", "CLEANSTACK", "v0 P2SH-P2WSH with extra stack item and SCRIPT_ALLOW_SEGWIT_RECOVERY" ], [ "0x03 0x00015a", "HASH160 0x14 0x40b6941895022d458de8f4bbfe27f3aaa4fb9a74 EQUAL", "ALLOW_SEGWIT_RECOVERY,CLEANSTACK,P2SH", "CLEANSTACK", "Invalid witness program (too short) with SCRIPT_ALLOW_SEGWIT_RECOVERY" ], [ "0x04 0x00025a01", "HASH160 0x14 0x86123d8e050333a605e434ecf73128d83815b36f EQUAL", "ALLOW_SEGWIT_RECOVERY,CLEANSTACK,P2SH", "OK", "Valid witness program (min allowed length) with SCRIPT_ALLOW_SEGWIT_RECOVERY" ], [ "0x2a 0x00285a0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324252627", "HASH160 0x14 0xdf7b93f88e83471b479fb219ae90e5b633d6b750 EQUAL", "ALLOW_SEGWIT_RECOVERY,CLEANSTACK,P2SH", "OK", "Valid witness program (max allowed length) with SCRIPT_ALLOW_SEGWIT_RECOVERY" ], [ "0x2b 0x00295a0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728", "HASH160 0x14 0x13aa4fcfd630508e0794dca320cac172c5790aea EQUAL", "ALLOW_SEGWIT_RECOVERY,CLEANSTACK,P2SH", "CLEANSTACK", "Invalid witness program (too long) with SCRIPT_ALLOW_SEGWIT_RECOVERY" ], [ "0x22 0x60205a0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "HASH160 0x14 0x9b0c7017004d3818b7c833ddb3cb5547a22034d0 EQUAL", "ALLOW_SEGWIT_RECOVERY,CLEANSTACK,P2SH", "OK", "Valid witness program (max allowed version) with SCRIPT_ALLOW_SEGWIT_RECOVERY" ], [ "0x22 0x4f205a0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "HASH160 0x14 0x97aa1e96e49ca6d744d7344f649dd9f94bcc35eb EQUAL", "ALLOW_SEGWIT_RECOVERY,CLEANSTACK,P2SH", "CLEANSTACK", "Invalid witness program (invalid version -1) with SCRIPT_ALLOW_SEGWIT_RECOVERY" ], [ "0x23 0x0111205a0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "HASH160 0x14 0x4b5321beb1c09f593ff3c02be4af21c7f949e101 EQUAL", "ALLOW_SEGWIT_RECOVERY,CLEANSTACK,P2SH", "CLEANSTACK", "Invalid witness program (invalid version 17) with SCRIPT_ALLOW_SEGWIT_RECOVERY" ], [ "0x23 0x00205a0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f51", "HASH160 0x14 0x8eb812176c9e71732584123dd06d3246e659b199 EQUAL", "ALLOW_SEGWIT_RECOVERY,CLEANSTACK,P2SH", "CLEANSTACK", "Invalid witness program (more than 2 stack items) with SCRIPT_ALLOW_SEGWIT_RECOVERY" ], [ "0x04 0x00020000", "HASH160 0x14 0x0e01bcfe7c6f3fd2fd8f81092299369744684733 EQUAL", "ALLOW_SEGWIT_RECOVERY,CLEANSTACK,P2SH", "OK", "Valid segwit recovery, in spite of false value being left on stack (0)" ], [ "0x04 0x00020080", "HASH160 0x14 0x10ddc638cb26615f867dad80efacced9e73766bc EQUAL", "ALLOW_SEGWIT_RECOVERY,CLEANSTACK,P2SH", "OK", "Valid segwit recovery, in spite of false value being left on stack (minus 0)" ], [ "0x22 0x50205a0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "HASH160 0x14 0xbe02794ceede051da41b420e88a86fff2802af06 EQUAL", "ALLOW_SEGWIT_RECOVERY,CLEANSTACK,P2SH", "BAD_OPCODE", "Invalid witness program (OP_RESERVED in version field) with SCRIPT_ALLOW_SEGWIT_RECOVERY" ], [ "0x17 0x01001491b24bf9f5288532960ac687abb035127b1d28a5", "HASH160 0x14 0x0718743e67c1ef4911e0421f206c5ff81755718e EQUAL", "ALLOW_SEGWIT_RECOVERY,CLEANSTACK,P2SH", "CLEANSTACK", "Invalid witness program (non-minimal push in version field) with SCRIPT_ALLOW_SEGWIT_RECOVERY" ], [ "0x05 0x004c0245aa", "HASH160 0x14 0xd3ec673296c7fd7e1a9e53bfc36f414de303e905 EQUAL", "ALLOW_SEGWIT_RECOVERY,CLEANSTACK,P2SH", "CLEANSTACK", "Invalid witness program (non-minimal push in program field) with SCRIPT_ALLOW_SEGWIT_RECOVERY" ], [ "0x16 0x001491b24bf9f5288532960ac687abb035127b1d28a5", "HASH160 0x14 0x17a6be2f8fe8e94f033e53d17beefda0f3ac4409 EQUAL", "ALLOW_SEGWIT_RECOVERY,CLEANSTACK,P2SH", "EVAL_FALSE", "v0 P2SH-P2WPKH whose redeem script hash does not match P2SH output and SCRIPT_ALLOW_SEGWIT_RECOVERY" ], [ "0x16 0x001491b24bf9f5288532960ac687abb035127b1d28a5", "1", "ALLOW_SEGWIT_RECOVERY,CLEANSTACK,P2SH", "CLEANSTACK", "v0 P2SH-P2WPKH spending a non-P2SH output and SCRIPT_ALLOW_SEGWIT_RECOVERY" ], ["CHECKSEQUENCEVERIFY tests"], -["", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "INVALID_STACK_OPERATION", "CSV automatically fails on a empty stack"], +["", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "INVALID_STACK_OPERATION", "CSV automatically fails on an empty stack"], ["-1", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "NEGATIVE_LOCKTIME", "CSV automatically fails if stack top is negative"], ["0x0100", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY,MINIMALDATA", "UNKNOWN_ERROR", "CSV fails if stack top is not minimally encoded"], ["0", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME", "CSV fails if stack top bit 1 << 31 is set and the tx version < 2"], ["4294967296", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME", "CSV fails if stack top bit 1 << 31 is not set, and tx version < 2"], ["MINIMALIF tests"], ["MINIMALIF is not applied if the flag is passed"], ["1", "IF 1 ENDIF", "P2SH,MINIMALIF", "OK"], ["2", "IF 1 ENDIF", "P2SH", "OK"], ["2", "IF 1 ENDIF", "P2SH,MINIMALIF", "MINIMALIF"], ["0x02 0x0100", "IF 1 ENDIF", "P2SH", "OK"], ["0x02 0x0100", "IF 1 ENDIF", "P2SH,MINIMALIF", "MINIMALIF"], ["0", "IF 1 ENDIF", "P2SH,MINIMALIF", "EVAL_FALSE"], ["0x01 0x00", "IF 1 ENDIF", "P2SH", "EVAL_FALSE"], ["0x01 0x00", "IF 1 ENDIF", "P2SH,MINIMALIF", "MINIMALIF"], ["1", "NOTIF 1 ENDIF", "P2SH,MINIMALIF", "EVAL_FALSE"], ["2", "NOTIF 1 ENDIF", "P2SH", "EVAL_FALSE"], ["2", "NOTIF 1 ENDIF", "P2SH,MINIMALIF", "MINIMALIF"], ["0x02 0x0100", "NOTIF 1 ENDIF", "P2SH", "EVAL_FALSE"], ["0x02 0x0100", "NOTIF 1 ENDIF", "P2SH,MINIMALIF", "MINIMALIF"], ["0", "NOTIF 1 ENDIF", "P2SH,MINIMALIF", "OK"], ["0x01 0x00", "NOTIF 1 ENDIF", "P2SH", "OK"], ["0x01 0x00", "NOTIF 1 ENDIF", "P2SH,MINIMALIF", "MINIMALIF"], ["Normal P2SH IF 1 ENDIF"], ["1 0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH,MINIMALIF", "OK"], ["2 0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH", "OK"], ["2 0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH,MINIMALIF", "MINIMALIF"], ["0x02 0x0100 0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH", "OK"], ["0x02 0x0100 0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH,MINIMALIF", "MINIMALIF"], ["0 0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH,MINIMALIF", "EVAL_FALSE"], ["0x01 0x00 0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH", "EVAL_FALSE"], ["0x01 0x00 0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH,MINIMALIF", "MINIMALIF"], ["0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH,MINIMALIF", "UNBALANCED_CONDITIONAL"], ["Normal P2SH NOTIF 1 ENDIF"], ["1 0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH,MINIMALIF", "EVAL_FALSE"], ["2 0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH", "EVAL_FALSE"], ["2 0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH,MINIMALIF", "MINIMALIF"], ["0x02 0x0100 0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH", "EVAL_FALSE"], ["0x02 0x0100 0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH,MINIMALIF", "MINIMALIF"], ["0 0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH,MINIMALIF", "OK"], ["0x01 0x00 0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH", "OK"], ["0x01 0x00 0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH,MINIMALIF", "MINIMALIF"], ["0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH,MINIMALIF", "UNBALANCED_CONDITIONAL"], ["NULLFAIL should cover all signatures and signatures only"], ["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66 and NULLFAIL-compliant"], ["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "OK", "BIP66 and NULLFAIL-compliant"], ["1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "OK", "BIP66 and NULLFAIL-compliant, not NULLDUMMY-compliant"], ["1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL,NULLDUMMY", "SIG_NULLDUMMY", "BIP66 and NULLFAIL-compliant, not NULLDUMMY-compliant"], ["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0x09 0x300602010102010101", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66-compliant but not NULLFAIL-compliant"], ["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0x09 0x300602010102010101", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "NULLFAIL", "BIP66-compliant but not NULLFAIL-compliant"], ["0 0x09 0x300602010102010101 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66-compliant but not NULLFAIL-compliant"], ["0 0x09 0x300602010102010101 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "NULLFAIL", "BIP66-compliant but not NULLFAIL-compliant"], ["SIGHASH_FORKID"], ["0x09 0x300602010102010141", "0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 CHECKSIG NOT", "STRICTENC", "ILLEGAL_FORKID"], ["0x09 0x300602010102010141", "0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 CHECKSIG NOT", "SIGHASH_FORKID", "OK"], ["0 0x09 0x300602010102010141", "1 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 1 CHECKMULTISIG NOT", "STRICTENC", "ILLEGAL_FORKID"], ["0 0x09 0x300602010102010141", "1 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 1 CHECKMULTISIG NOT", "SIGHASH_FORKID", "OK"], ["The End"] ] diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json index a6792e9127..5ad0738527 100644 --- a/src/test/data/tx_valid.json +++ b/src/test/data/tx_valid.json @@ -1,347 +1,347 @@ [ ["The following are deserialized transactions which are valid."], ["They are in the form"], ["[[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], ["serializedTransaction, verifyFlags]"], ["Objects that are only a single string (like this one) are ignored"], ["The following is 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"], ["It is of particular interest because it contains an invalidly-encoded signature which OpenSSL accepts"], ["See http://r6.ca/blog/20111119T211504Z.html"], ["It is also the first OP_CHECKMULTISIG transaction in standard form"], [[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000490047304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"], ["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"], ["It is an OP_CHECKMULTISIG with an arbitrary extra byte stuffed into the signature at pos length - 2"], ["The dummy byte is fine however, so the NULLDUMMY flag should be happy"], [[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004a0048304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2bab01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH,NULLDUMMY"], ["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"], ["It is an OP_CHECKMULTISIG with the dummy value set to something other than an empty string"], [[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004a01ff47304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"], ["As above, but using a OP_1"], [[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000495147304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"], ["As above, but using a OP_1NEGATE"], [[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000494f47304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"], ["The following is c99c49da4c38af669dea436d3e73780dfdb6c1ecf9958baa52960e8baee30e73"], ["It is of interest because it contains a 0-sequence as well as a signature of SIGHASH type 0 (which is not a real type)"], [[["406b2b06bcd34d3c8733e6b79f7a394c8a431fbf4ff5ac705c93f4076bb77602", 0, "DUP HASH160 0x14 0xdc44b1164188067c3a32d4780f5996fa14a4f2d9 EQUALVERIFY CHECKSIG"]], "01000000010276b76b07f4935c70acf54fbf1f438a4c397a9fb7e633873c4dd3bc062b6b40000000008c493046022100d23459d03ed7e9511a47d13292d3430a04627de6235b6e51a40f9cd386f2abe3022100e7d25b080f0bb8d8d5f878bba7d54ad2fda650ea8d158a33ee3cbd11768191fd004104b0e2c879e4daf7b9ab68350228c159766676a14f5815084ba166432aab46198d4cca98fa3e9981d0a90b2effc514b76279476550ba3663fdcaff94c38420e9d5000000000100093d00000000001976a9149a7b0f3b80c6baaeedce0a0842553800f832ba1f88ac00000000", "P2SH"], ["A nearly-standard transaction with CHECKSIGVERIFY 1 instead of CHECKSIG"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1"]], "01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", "P2SH"], ["Same as above, but with the signature duplicated in the scriptPubKey with the proper pushdata prefix"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]], "01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", "P2SH"], ["The following is f7fdd091fa6d8f5e7a8c2458f5c38faffff2d3f1406b6e4fe2c99dcc0d2d1cbb"], ["It caught a bug in the workaround for 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63 in an overly simple implementation"], [[["b464e85df2a238416f8bdae11d120add610380ea07f4ef19c5f9dfd472f96c3d", 0, "DUP HASH160 0x14 0xbef80ecf3a44500fda1bc92176e442891662aed2 EQUALVERIFY CHECKSIG"], ["b7978cc96e59a8b13e0865d3f95657561a7f725be952438637475920bac9eb21", 1, "DUP HASH160 0x14 0xbef80ecf3a44500fda1bc92176e442891662aed2 EQUALVERIFY CHECKSIG"]], "01000000023d6cf972d4dff9c519eff407ea800361dd0a121de1da8b6f4138a2f25de864b4000000008a4730440220ffda47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b0e022049cffa1cdc102a0b56e0e04913606c70af702a1149dc3b305ab9439288fee090014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff21ebc9ba20594737864352e95b727f1a565756f9d365083eb1a8596ec98c97b7010000008a4730440220503ff10e9f1e0de731407a4a245531c9ff17676eda461f8ceeb8c06049fa2c810220c008ac34694510298fa60b3f000df01caa244f165b727d4896eb84f81e46bcc4014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff01f0da5200000000001976a914857ccd42dded6df32949d4646dfa10a92458cfaa88ac00000000", "P2SH"], ["The following tests for the presence of a bug in the handling of SIGHASH_SINGLE"], ["It results in signing the constant 1, instead of something generated based on the transaction,"], ["when the input doing the signing has an index greater than the maximum output index"], [[["0000000000000000000000000000000000000000000000000000000000000200", 0, "1"], ["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0xe52b482f2faa8ecbf0db344f93c84ac908557f33 EQUALVERIFY CHECKSIG"]], "01000000020002000000000000000000000000000000000000000000000000000000000000000000000151ffffffff0001000000000000000000000000000000000000000000000000000000000000000000006b483045022100c9cdd08798a28af9d1baf44a6c77bcc7e279f47dc487c8c899911bc48feaffcc0220503c5c50ae3998a733263c5c0f7061b483e2b56c4c41b456e7d2f5a78a74c077032102d5c25adb51b61339d2b05315791e21bbe80ea470a49db0135720983c905aace0ffffffff010000000000000000015100000000", "P2SH"], ["An invalid P2SH Transaction"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]], "010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", "NONE"], ["A valid P2SH Transaction using the standard transaction type put forth in BIP 16"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x8febbed40483661de6958d957412f82deed8e2f7 EQUAL"]], "01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100c66c9cdf4c43609586d15424c54707156e316d88b0a1534c9e6b0d4f311406310221009c0fe51dbc9c4ab7cc25d3fdbeccf6679fe6827f08edf2b4a9f16ee3eb0e438a0123210338e8034509af564c62644c07691942e0c056752008a173c89f60ab2a88ac2ebfacffffffff010000000000000000015100000000", "P2SH"], ["Tests for CheckTransaction()"], ["MAX_MONEY output"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x32afac281462b822adbec5094b8d4d337dd5bd6a EQUAL"]], "01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010040075af0750700015100000000", "P2SH"], ["MAX_MONEY output + 0 output"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xb558cbf4930954aa6a344363a15668d7477ae716 EQUAL"]], "01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022027deccc14aa6668e78a8c9da3484fbcd4f9dcc9bb7d1b85146314b21b9ae4d86022100d0b43dece8cfb07348de0ca8bc5b86276fa88f7f2138381128b7c36ab2e42264012321029bb13463ddd5d2cc05da6e84e37536cb9525703cfd8f43afdb414988987a92f6acffffffff020040075af075070001510000000000000000015100000000", "P2SH"], ["Coinbase of size 2"], ["Note the input is just required to make the tester happy"], [[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]], "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff025151ffffffff010000000000000000015100000000", "P2SH"], ["Coinbase of size 100"], ["Note the input is just required to make the tester happy"], [[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]], "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff6451515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151ffffffff010000000000000000015100000000", "P2SH"], ["Simple transaction with first input is signed with SIGHASH_ALL, second with SIGHASH_ANYONECANPAY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"], ["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]], "010000000200010000000000000000000000000000000000000000000000000000000000000000000049483045022100d180fd2eb9140aeb4210c9204d3f358766eb53842b2a9473db687fa24b12a3cc022079781799cd4f038b85135bbe49ec2b57f306b2bb17101b17f71f000fcab2b6fb01ffffffff0002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000", "P2SH"], ["Same as above, but we change the sequence number of the first input to check that SIGHASH_ANYONECANPAY is being followed"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"], ["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]], "01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df101010000000002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000", "P2SH"], ["afd9c17f8913577ec3509520bd6e5d63e9c0fd2a5f70c787993b097ba6ca9fae which has several SIGHASH_SINGLE signatures"], [[["63cfa5a09dc540bf63e53713b82d9ea3692ca97cd608c384f2aa88e51a0aac70", 0, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"], ["04e8d0fcf3846c6734477b98f0f3d4badfb78f020ee097a0be5fe347645b817d", 1, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"], ["ee1377aff5d0579909e11782e1d2f5f7b84d26537be7f5516dd4e43373091f3f", 1, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"]], "010000000370ac0a1ae588aaf284c308d67ca92c69a39e2db81337e563bf40c59da0a5cf63000000006a4730440220360d20baff382059040ba9be98947fd678fb08aab2bb0c172efa996fd8ece9b702201b4fb0de67f015c90e7ac8a193aeab486a1f587e0f54d0fb9552ef7f5ce6caec032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff7d815b6447e35fbea097e00e028fb7dfbad4f3f0987b4734676c84f3fcd0e804010000006b483045022100c714310be1e3a9ff1c5f7cacc65c2d8e781fc3a88ceb063c6153bf950650802102200b2d0979c76e12bb480da635f192cc8dc6f905380dd4ac1ff35a4f68f462fffd032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff3f1f097333e4d46d51f5e77b53264db8f7f5d2e18217e1099957d0f5af7713ee010000006c493046022100b663499ef73273a3788dea342717c2640ac43c5a1cf862c9e09b206fcb3f6bb8022100b09972e75972d9148f2bdd462e5cb69b57c1214b88fc55ca638676c07cfc10d8032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff0380841e00000000001976a914bfb282c70c4191f45b5a6665cad1682f2c9cfdfb88ac80841e00000000001976a9149857cc07bed33a5cf12b9c5e0500b675d500c81188ace0fd1c00000000001976a91443c52850606c872403c0601e69fa34b26f62db4a88ac00000000", "P2SH"], ["ddc454a1c0c35c188c98976b17670f69e586d9c0f3593ea879928332f0a069e7, which spends an input that pushes using a PUSHDATA1 that is negative when read as signed"], [[["c5510a5dd97a25f43175af1fe649b707b1df8e1a41489bac33a23087027a2f48", 0, "0x4c 0xae 0x606563686f2022553246736447566b58312b5a536e587574356542793066794778625456415675534a6c376a6a334878416945325364667657734f53474f36633338584d7439435c6e543249584967306a486956304f376e775236644546673d3d22203e20743b206f70656e73736c20656e63202d7061737320706173733a5b314a564d7751432d707269766b65792d6865785d202d64202d6165732d3235362d636263202d61202d696e207460 DROP DUP HASH160 0x14 0xbfd7436b6265aa9de506f8a994f881ff08cc2872 EQUALVERIFY CHECKSIG"]], "0100000001482f7a028730a233ac9b48411a8edfb107b749e61faf7531f4257ad95d0a51c5000000008b483045022100bf0bbae9bde51ad2b222e87fbf67530fbafc25c903519a1e5dcc52a32ff5844e022028c4d9ad49b006dd59974372a54291d5764be541574bb0c4dc208ec51f80b7190141049dd4aad62741dc27d5f267f7b70682eee22e7e9c1923b9c0957bdae0b96374569b460eb8d5b40d972e8c7c0ad441de3d94c4a29864b212d56050acb980b72b2bffffffff0180969800000000001976a914e336d0017a9d28de99d16472f6ca6d5a3a8ebc9988ac00000000", "P2SH"], ["Correct signature order"], ["Note the input is just required to make the tester happy"], [[["b3da01dd4aae683c7aee4d5d8b52a540a508e1115f77cd7fa9a291243f501223", 0, "HASH160 0x14 0xb1ce99298d5f07364b57b1e5c9cc00be0b04a954 EQUAL"]], "01000000012312503f2491a2a97fcd775f11e108a540a5528b5d4dee7a3c68ae4add01dab300000000fdfe0000483045022100f6649b0eddfdfd4ad55426663385090d51ee86c3481bdc6b0c18ea6c0ece2c0b0220561c315b07cffa6f7dd9df96dbae9200c2dee09bf93cc35ca05e6cdf613340aa0148304502207aacee820e08b0b174e248abd8d7a34ed63b5da3abedb99934df9fddd65c05c4022100dfe87896ab5ee3df476c2655f9fbe5bd089dccbef3e4ea05b5d121169fe7f5f4014c695221031d11db38972b712a9fe1fc023577c7ae3ddb4a3004187d41c45121eecfdbb5b7210207ec36911b6ad2382860d32989c7b8728e9489d7bbc94a6b5509ef0029be128821024ea9fac06f666a4adc3fc1357b7bec1fd0bdece2b9d08579226a8ebde53058e453aeffffffff0180380100000000001976a914c9b99cddf847d10685a4fabaa0baf505f7c3dfab88ac00000000", "P2SH"], ["cc60b1f899ec0a69b7c3f25ddf32c4524096a9c5b01cbd84c6d0312a0c478984, which is a fairly strange transaction which relies on OP_CHECKSIG returning 0 when checking a completely invalid sig of length 0"], [[["cbebc4da731e8995fe97f6fadcd731b36ad40e5ecb31e38e904f6e5982fa09f7", 0, "0x2102085c6600657566acc2d6382a47bc3f324008d2aa10940dd7705a48aa2a5a5e33ac7c2103f5d0fb955f95dd6be6115ce85661db412ec6a08abcbfce7da0ba8297c6cc0ec4ac7c5379a820d68df9e32a147cffa36193c6f7c43a1c8c69cda530e1c6db354bfabdcfefaf3c875379a820f531f3041d3136701ea09067c53e7159c8f9b2746a56c3d82966c54bbc553226879a5479827701200122a59a5379827701200122a59a6353798277537982778779679a68"]], "0100000001f709fa82596e4f908ee331cb5e0ed46ab331d7dcfaf697fe95891e73dac4ebcb000000008c20ca42095840735e89283fec298e62ac2ddea9b5f34a8cbb7097ad965b87568100201b1b01dc829177da4a14551d2fc96a9db00c6501edfa12f22cd9cefd335c227f483045022100a9df60536df5733dd0de6bc921fab0b3eee6426501b43a228afa2c90072eb5ca02201c78b74266fac7d1db5deff080d8a403743203f109fbcabf6d5a760bf87386d20100ffffffff01c075790000000000232103611f9a45c18f28f06f19076ad571c344c82ce8fcfe34464cf8085217a2d294a6ac00000000", "P2SH"], ["Empty pubkey"], [[["229257c295e7f555421c1bfec8538dd30a4b5c37c1c8810bbe83cafa7811652c", 0, "0x00 CHECKSIG NOT"]], "01000000012c651178faca83be0b81c8c1375c4b0ad38d53c8fe1b1c4255f5e795c25792220000000049483045022100d6044562284ac76c985018fc4a90127847708c9edb280996c507b28babdc4b2a02203d74eca3f1a4d1eea7ff77b528fde6d5dc324ec2dbfdb964ba885f643b9704cd01ffffffff010100000000000000232102c2410f8891ae918cab4ffc4bb4a3b0881be67c7a1e7faa8b5acf9ab8932ec30cac00000000", "P2SH"], ["Empty signature"], [[["9ca93cfd8e3806b9d9e2ba1cf64e3cc6946ee0119670b1796a09928d14ea25f7", 0, "0x21 0x028a1d66975dbdf97897e3a4aef450ebeb5b5293e4a0b4a6d3a2daaa0b2b110e02 CHECKSIG NOT"]], "0100000001f725ea148d92096a79b1709611e06e94c63c4ef61cbae2d9b906388efd3ca99c000000000100ffffffff0101000000000000002321028a1d66975dbdf97897e3a4aef450ebeb5b5293e4a0b4a6d3a2daaa0b2b110e02ac00000000", "P2SH"], [[["444e00ed7840d41f20ecd9c11d3f91982326c731a02f3c05748414a4fa9e59be", 0, "1 0x00 0x21 0x02136b04758b0b6e363e7a6fbe83aaf527a153db2b060d36cc29f7f8309ba6e458 2 CHECKMULTISIG"]], "0100000001be599efaa4148474053c2fa031c7262398913f1dc1d9ec201fd44078ed004e44000000004900473044022022b29706cb2ed9ef0cb3c97b72677ca2dfd7b4160f7b4beb3ba806aa856c401502202d1e52582412eba2ed474f1f437a427640306fd3838725fab173ade7fe4eae4a01ffffffff010100000000000000232103ac4bba7e7ca3e873eea49e08132ad30c7f03640b6539e9b59903cf14fd016bbbac00000000", "P2SH"], [[["e16abbe80bf30c080f63830c8dbf669deaef08957446e95940227d8c5e6db612", 0, "1 0x21 0x03905380c7013e36e6e19d305311c1b81fce6581f5ee1c86ef0627c68c9362fc9f 0x00 2 CHECKMULTISIG"]], "010000000112b66d5e8c7d224059e946749508efea9d66bf8d0c83630f080cf30be8bb6ae100000000490047304402206ffe3f14caf38ad5c1544428e99da76ffa5455675ec8d9780fac215ca17953520220779502985e194d84baa36b9bd40a0dbd981163fa191eb884ae83fc5bd1c86b1101ffffffff010100000000000000232103905380c7013e36e6e19d305311c1b81fce6581f5ee1c86ef0627c68c9362fc9fac00000000", "P2SH"], [[["ebbcf4bfce13292bd791d6a65a2a858d59adbf737e387e40370d4e64cc70efb0", 0, "2 0x21 0x033bcaa0a602f0d44cc9d5637c6e515b0471db514c020883830b7cefd73af04194 0x21 0x03a88b326f8767f4f192ce252afe33c94d25ab1d24f27f159b3cb3aa691ffe1423 2 CHECKMULTISIG NOT"]], "0100000001b0ef70cc644e0d37407e387e73bfad598d852a5aa6d691d72b2913cebff4bceb000000004a00473044022068cd4851fc7f9a892ab910df7a24e616f293bcb5c5fbdfbc304a194b26b60fba022078e6da13d8cb881a22939b952c24f88b97afd06b4c47a47d7f804c9a352a6d6d0100ffffffff0101000000000000002321033bcaa0a602f0d44cc9d5637c6e515b0471db514c020883830b7cefd73af04194ac00000000", "P2SH"], [[["ba4cd7ae2ad4d4d13ebfc8ab1d93a63e4a6563f25089a18bf0fc68f282aa88c1", 0, "2 0x21 0x037c615d761e71d38903609bf4f46847266edc2fb37532047d747ba47eaae5ffe1 0x21 0x02edc823cd634f2c4033d94f5755207cb6b60c4b1f1f056ad7471c47de5f2e4d50 2 CHECKMULTISIG NOT"]], "0100000001c188aa82f268fcf08ba18950f263654a3ea6931dabc8bf3ed1d4d42aaed74cba000000004b0000483045022100940378576e069aca261a6b26fb38344e4497ca6751bb10905c76bb689f4222b002204833806b014c26fd801727b792b1260003c55710f87c5adbd7a9cb57446dbc9801ffffffff0101000000000000002321037c615d761e71d38903609bf4f46847266edc2fb37532047d747ba47eaae5ffe1ac00000000", "P2SH"], ["OP_CODESEPARATOR tests"], ["Test that SignatureHash() removes OP_CODESEPARATOR with FindAndDelete()"], [[["bc7fd132fcf817918334822ee6d9bd95c889099c96e07ca2c1eb2cc70db63224", 0, "CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIG"]], "01000000012432b60dc72cebc1a27ce0969c0989c895bdd9e62e8234839117f8fc32d17fbc000000004a493046022100a576b52051962c25e642c0fd3d77ee6c92487048e5d90818bcf5b51abaccd7900221008204f8fb121be4ec3b24483b1f92d89b1b0548513a134e345c5442e86e8617a501ffffffff010000000000000000016a00000000", "P2SH"], [[["83e194f90b6ef21fa2e3a365b63794fb5daa844bdc9b25de30899fcfe7b01047", 0, "CODESEPARATOR CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIG"]], "01000000014710b0e7cf9f8930de259bdc4b84aa5dfb9437b665a3e3a21ff26e0bf994e183000000004a493046022100a166121a61b4eeb19d8f922b978ff6ab58ead8a5a5552bf9be73dc9c156873ea02210092ad9bc43ee647da4f6652c320800debcf08ec20a094a0aaf085f63ecb37a17201ffffffff010000000000000000016a00000000", "P2SH"], ["Hashed data starts at the CODESEPARATOR"], [[["326882a7f22b5191f1a0cc9962ca4b878cd969cf3b3a70887aece4d801a0ba5e", 0, "0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CODESEPARATOR CHECKSIG"]], "01000000015ebaa001d8e4ec7a88703a3bcf69d98c874bca6299cca0f191512bf2a7826832000000004948304502203bf754d1c6732fbf87c5dcd81258aefd30f2060d7bd8ac4a5696f7927091dad1022100f5bcb726c4cf5ed0ed34cc13dadeedf628ae1045b7cb34421bc60b89f4cecae701ffffffff010000000000000000016a00000000", "P2SH"], ["But only if execution has reached it"], [[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIGVERIFY CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIGVERIFY CODESEPARATOR 1"]], "010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a900000000924830450221009c0a27f886a1d8cb87f6f595fbc3163d28f7a81ec3c4b252ee7f3ac77fd13ffa02203caa8dfa09713c8c4d7ef575c75ed97812072405d932bd11e6a1593a98b679370148304502201e3861ef39a526406bad1e20ecad06be7375ad40ddb582c9be42d26c3a0d7b240221009d0a3985e96522e59635d19cc4448547477396ce0ef17a58e7d74c3ef464292301ffffffff010000000000000000016a00000000", "P2SH"], ["CODESEPARATOR in an unexecuted IF block does not change what is hashed"], [[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "IF CODESEPARATOR ENDIF 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 CHECKSIGVERIFY CODESEPARATOR 1"]], "010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a48304502207a6974a77c591fa13dff60cabbb85a0de9e025c09c65a4b2285e47ce8e22f761022100f0efaac9ff8ac36b10721e0aae1fb975c90500b50c56e8a0cc52b0403f0425dd0100ffffffff010000000000000000016a00000000", "P2SH"], ["As above, with the IF block executed"], [[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "IF CODESEPARATOR ENDIF 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 CHECKSIGVERIFY CODESEPARATOR 1"]], "010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a483045022100fa4a74ba9fd59c59f46c3960cf90cbe0d2b743c471d24a3d5d6db6002af5eebb02204d70ec490fd0f7055a7c45f86514336e3a7f03503dacecabb247fc23f15c83510151ffffffff010000000000000000016a00000000", "P2SH"], ["CHECKSIG is legal in scriptSigs"], [[["ccf7f4053a02e653c36ac75c891b7496d0dc5ce5214f6c913d9cf8f1329ebee0", 0, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]], "0100000001e0be9e32f1f89c3d916c4f21e55cdcd096741b895cc76ac353e6023a05f4f7cc00000000d86149304602210086e5f736a2c3622ebb62bd9d93d8e5d76508b98be922b97160edc3dcca6d8c47022100b23c312ac232a4473f19d2aeb95ab7bdf2b65518911a0d72d50e38b5dd31dc820121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac4730440220508fa761865c8abd81244a168392876ee1d94e8ed83897066b5e2df2400dad24022043f5ee7538e87e9c6aef7ef55133d3e51da7cc522830a9c4d736977a76ef755c0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"], ["Same semantics for OP_CODESEPARATOR"], [[["10c9f0effe83e97f80f067de2b11c6a00c3088a4bce42c5ae761519af9306f3c", 1, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]], "01000000013c6f30f99a5161e75a2ce4bca488300ca0c6112bde67f0807fe983feeff0c91001000000e608646561646265656675ab61493046022100ce18d384221a731c993939015e3d1bcebafb16e8c0b5b5d14097ec8177ae6f28022100bcab227af90bab33c3fe0a9abfee03ba976ee25dc6ce542526e9b2e56e14b7f10121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac493046022100c3b93edcc0fd6250eb32f2dd8a0bba1754b0f6c3be8ed4100ed582f3db73eba2022100bf75b5bd2eff4d6bf2bda2e34a40fcc07d4aa3cf862ceaa77b47b81eff829f9a01ab21038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"], ["Signatures are removed from the script they are in by FindAndDelete() in the CHECKSIG code; even multiple instances of one signature can be removed."], [[["6056ebd549003b10cbbd915cea0d82209fe40b8617104be917a26fa92cbe3d6f", 0, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]], "01000000016f3dbe2ca96fa217e94b1017860be49f20820dea5c91bdcb103b0049d5eb566000000000fd1d0147304402203989ac8f9ad36b5d0919d97fa0a7f70c5272abee3b14477dc646288a8b976df5022027d19da84a066af9053ad3d1d7459d171b7e3a80bc6c4ef7a330677a6be548140147304402203989ac8f9ad36b5d0919d97fa0a7f70c5272abee3b14477dc646288a8b976df5022027d19da84a066af9053ad3d1d7459d171b7e3a80bc6c4ef7a330677a6be548140121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac47304402203757e937ba807e4a5da8534c17f9d121176056406a6465054bdd260457515c1a02200f02eccf1bec0f3a0d65df37889143c2e88ab7acec61a7b6f5aa264139141a2b0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"], ["That also includes ahead of the opcode being executed."], [[["5a6b0021a6042a686b6b94abc36b387bef9109847774e8b1e51eb8cc55c53921", 1, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]], "01000000012139c555ccb81ee5b1e87477840991ef7b386bc3ab946b6b682a04a621006b5a01000000fdb40148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f2204148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390175ac4830450220646b72c35beeec51f4d5bc1cbae01863825750d7f490864af354e6ea4f625e9c022100f04b98432df3a9641719dbced53393022e7249fb59db993af1118539830aab870148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a580039017521038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"], -["Finally CHECKMULTISIG removes all signatures prior to hashing the script containing those signatures. In conjunction with the SIGHASH_SINGLE bug this lets us test whether or not FindAndDelete() is actually present in scriptPubKey/redeemScript evaluation by including a signature of the digest 0x01 We can compute in advance for our pubkey, embed it it in the scriptPubKey, and then also using a normal SIGHASH_ALL signature. If FindAndDelete() wasn't run, the 'bugged' signature would still be in the hashed script, and the normal signature would fail."], +["Finally CHECKMULTISIG removes all signatures prior to hashing the script containing those signatures. In conjunction with the SIGHASH_SINGLE bug this lets us test whether or not FindAndDelete() is actually present in scriptPubKey/redeemScript evaluation by including a signature of the digest 0x01 We can compute in advance for our pubkey, embed it in the scriptPubKey, and then also using a normal SIGHASH_ALL signature. If FindAndDelete() wasn't run, the 'bugged' signature would still be in the hashed script, and the normal signature would fail."], ["Here's an example on mainnet within a P2SH redeemScript. Remarkably it's a standard transaction in <0.9"], [[["b5b598de91787439afd5938116654e0b16b7a0d0f82742ba37564219c5afcbf9", 0, "DUP HASH160 0x14 0xf6f365c40f0739b61de827a44751e5e99032ed8f EQUALVERIFY CHECKSIG"], ["ab9805c6d57d7070d9a42c5176e47bb705023e6b67249fb6760880548298e742", 0, "HASH160 0x14 0xd8dacdadb7462ae15cd906f1878706d0da8660e6 EQUAL"]], "0100000002f9cbafc519425637ba4227f8d0a0b7160b4e65168193d5af39747891de98b5b5000000006b4830450221008dd619c563e527c47d9bd53534a770b102e40faa87f61433580e04e271ef2f960220029886434e18122b53d5decd25f1f4acb2480659fea20aabd856987ba3c3907e0121022b78b756e2258af13779c1a1f37ea6800259716ca4b7f0b87610e0bf3ab52a01ffffffff42e7988254800876b69f24676b3e0205b77be476512ca4d970707dd5c60598ab00000000fd260100483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a53034930460221008431bdfa72bc67f9d41fe72e94c88fb8f359ffa30b33c72c121c5a877d922e1002210089ef5fc22dd8bfc6bf9ffdb01a9862d27687d424d1fefbab9e9c7176844a187a014c9052483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c7153aeffffffff01a08601000000000017a914d8dacdadb7462ae15cd906f1878706d0da8660e68700000000", "P2SH"], ["Same idea, but with bare CHECKMULTISIG"], [[["ceafe58e0f6e7d67c0409fbbf673c84c166e3c5d3c24af58f7175b18df3bb3db", 0, "DUP HASH160 0x14 0xf6f365c40f0739b61de827a44751e5e99032ed8f EQUALVERIFY CHECKSIG"], ["ceafe58e0f6e7d67c0409fbbf673c84c166e3c5d3c24af58f7175b18df3bb3db", 1, "2 0x48 0x3045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 3 CHECKMULTISIG"]], "0100000002dbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce000000006b4830450221009627444320dc5ef8d7f68f35010b4c050a6ed0d96b67a84db99fda9c9de58b1e02203e4b4aaa019e012e65d69b487fdf8719df72f488fa91506a80c49a33929f1fd50121022b78b756e2258af13779c1a1f37ea6800259716ca4b7f0b87610e0bf3ab52a01ffffffffdbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce010000009300483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303ffffffff01a0860100000000001976a9149bc0bbdd3024da4d0c38ed1aecf5c68dd1d3fa1288ac00000000", "P2SH"], ["CHECKLOCKTIMEVERIFY tests"], ["By-height locks, with argument == 0 and == tx nLockTime"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKLOCKTIMEVERIFY 1"]], "010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 CHECKLOCKTIMEVERIFY 1"]], "0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ff64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKLOCKTIMEVERIFY 1"]], "0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ff64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], ["By-time locks, with argument just beyond tx nLockTime (but within numerical boundaries)"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 CHECKLOCKTIMEVERIFY 1"]], "01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKLOCKTIMEVERIFY 1"]], "0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffffff", "P2SH,CHECKLOCKTIMEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 CHECKLOCKTIMEVERIFY 1"]], "0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffffff", "P2SH,CHECKLOCKTIMEVERIFY"], ["Any non-maxint nSequence is fine"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKLOCKTIMEVERIFY 1"]], "010000000100010000000000000000000000000000000000000000000000000000000000000000000000feffffff0100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], ["The argument can be calculated rather than created directly by a PUSHDATA"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 1ADD CHECKLOCKTIMEVERIFY 1"]], "01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], ["Perhaps even by an ADD producing a 5-byte result that is out of bounds for other opcodes"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 2147483647 ADD CHECKLOCKTIMEVERIFY 1"]], "0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000feffffff", "P2SH,CHECKLOCKTIMEVERIFY"], ["5 byte non-minimally-encoded arguments are valid"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x05 0x0000000000 CHECKLOCKTIMEVERIFY 1"]], "010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], ["Valid CHECKLOCKTIMEVERIFY in scriptSig"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]], "01000000010001000000000000000000000000000000000000000000000000000000000000000000000251b1000000000100000000000000000001000000", "P2SH,CHECKLOCKTIMEVERIFY"], ["Valid CHECKLOCKTIMEVERIFY in redeemScript"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xc5b93064159b3b2d6ab506a41b1f50463771b988 EQUAL"]], "0100000001000100000000000000000000000000000000000000000000000000000000000000000000030251b1000000000100000000000000000001000000", "P2SH,CHECKLOCKTIMEVERIFY"], ["A transaction with a non-standard DER signature."], [[["b1dbc81696c8a9c0fccd0693ab66d7c368dbc38c0def4e800685560ddd1b2132", 0, "DUP HASH160 0x14 0x4b3bd7eba3bc0284fd3007be7f3be275e94f5826 EQUALVERIFY CHECKSIG"]], "010000000132211bdd0d568506804eef0d8cc3db68c3d766ab9306cdfcc0a9c89616c8dbb1000000006c493045022100c7bb0faea0522e74ff220c20c022d2cb6033f8d167fb89e75a50e237a35fd6d202203064713491b1f8ad5f79e623d0219ad32510bfaa1009ab30cbee77b59317d6e30001210237af13eb2d84e4545af287b919c2282019c9691cc509e78e196a9d8274ed1be0ffffffff0100000000000000001976a914f1b3ed2eda9a2ebe5a9374f692877cdf87c0f95b88ac00000000", "P2SH"], ["CHECKSEQUENCEVERIFY tests"], ["By-height locks, with argument == 0 and == txin.nSequence"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff00000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["By-time locks, with argument == 0 and == txin.nSequence"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff40000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["Upper sequence with upper sequence is fine"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000800100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000800100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000feffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000feffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["Argument 2^31 with various nSequence"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["Argument 2^32-1 with various nSequence"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["Argument 3<<31 with various nSequence"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["5 byte non-minimally-encoded operandss are valid"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x05 0x0000000000 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["The argument can be calculated rather than created directly by a PUSHDATA"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194303 1ADD CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 1SUB CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff00000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["An ADD producing a 5-byte result that sets CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 65536 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 4259840 ADD CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["Valid CHECKSEQUENCEVERIFY in scriptSig"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]], "02000000010001000000000000000000000000000000000000000000000000000000000000000000000251b2010000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["Valid CHECKSEQUENCEVERIFY in redeemScript"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7c17aff532f22beb54069942f9bf567a66133eaf EQUAL"]], "0200000001000100000000000000000000000000000000000000000000000000000000000000000000030251b2010000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["Unknown version witness program with empty witness"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000]], "010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH"], ["Non witness Single|AnyoneCanPay hash input's position"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x03596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71 CHECKSIG", 1000], ["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x21 0x03596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71 CHECKSIG", 1001]], "01000000020001000000000000000000000000000000000000000000000000000000000000000000004847304402202a0b4b1294d70540235ae033d78e64b4897ec859c7b6f1b2b1d8a02e1d46006702201445e756d2254b0f1dfda9ab8e1e1bc26df9668077403204f32d16a49a36eb6983ffffffff00010000000000000000000000000000000000000000000000000000000000000100000049483045022100acb96cfdbda6dc94b489fd06f2d720983b5f350e31ba906cdbd800773e80b21c02200d74ea5bdf114212b4bbe9ed82c36d2e369e302dff57cb60d01c428f0bd3daab83ffffffff02e8030000000000000151e903000000000000015100000000", "P2SH"], ["FindAndDelete tests"], ["This is a test of FindAndDelete. The first tx is a spend of normal P2SH and the second tx is a spend of bare P2WSH."], ["The redeemScript/witnessScript is CHECKSIGVERIFY <0x30450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e01>."], ["The signature is <0x30450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e01> ,"], ["where the pubkey is obtained through key recovery with sig and correct sighash."], ["This is to show that FindAndDelete is applied only to non-segwit scripts"], ["Non-segwit: correct sighash (with FindAndDelete) = 1ba1fe3bc90c5d1265460e684ce6774e324f0fabdf67619eda729e64e8b6bc08"], [[["f18783ace138abac5d3a7a5cf08e88fe6912f267ef936452e0c27d090621c169", 7000, "HASH160 0x14 0x0c746489e2d83cdbb5b90b432773342ba809c134 EQUAL", 200000]], "010000000169c12106097dc2e0526493ef67f21269fe888ef05c7a3a5dacab38e1ac8387f1581b0000b64830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0121037a3fb04bcdb09eba90f69961ba1692a3528e45e67c85b200df820212d7594d334aad4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e01ffffffff0101000000000000000000000000", "P2SH"], ["This is multisig version of the FindAndDelete tests"], ["Script is 2 CHECKMULTISIGVERIFY DROP"], ["52af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c0395960175"], ["Signature is 0 2 "], ["Non-segwit: correct sighash (with FindAndDelete) = 1d50f00ba4db2917b903b0ec5002e017343bb38876398c9510570f5dce099295"], [[["9628667ad48219a169b41b020800162287d2c0f713c04157e95c484a8dcb7592", 7000, "HASH160 0x14 0x5748407f5ca5cdca53ba30b79040260770c9ee1b EQUAL", 200000]], "01000000019275cb8d4a485ce95741c013f7c0d28722160008021bb469a11982d47a662896581b0000fd6f01004830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c03959601522102cd74a2809ffeeed0092bc124fd79836706e41f048db3f6ae9df8708cefb83a1c2102e615999372426e46fd107b76eaf007156a507584aa2cc21de9eee3bdbd26d36c4c9552af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c0395960175ffffffff0101000000000000000000000000", "P2SH"], ["Make diffs cleaner by leaving a comment here without comma at the end"] ] diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 6d456aed23..83eb1bd15f 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -1,814 +1,814 @@ // Copyright (c) 2015-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /** Default control port */ const std::string DEFAULT_TOR_CONTROL = "127.0.0.1:9051"; /** Tor cookie size (from control-spec.txt) */ static const int TOR_COOKIE_SIZE = 32; /** Size of client/server nonce for SAFECOOKIE */ static const int TOR_NONCE_SIZE = 32; /** For computing serverHash in SAFECOOKIE */ static const std::string TOR_SAFE_SERVERKEY = "Tor safe cookie authentication server-to-controller hash"; /** For computing clientHash in SAFECOOKIE */ static const std::string TOR_SAFE_CLIENTKEY = "Tor safe cookie authentication controller-to-server hash"; /** Exponential backoff configuration - initial timeout in seconds */ static const float RECONNECT_TIMEOUT_START = 1.0; /** Exponential backoff configuration - growth factor */ static const float RECONNECT_TIMEOUT_EXP = 1.5; /** * Maximum length for lines received on TorControlConnection. * tor-control-spec.txt mentions that there is explicitly no limit defined to * line length, this is belt-and-suspenders sanity limit to prevent memory * exhaustion. */ static const int MAX_LINE_LENGTH = 100000; /****** Low-level TorControlConnection ********/ /** Reply from Tor, can be single or multi-line */ class TorControlReply { public: TorControlReply() { Clear(); } int code; std::vector lines; void Clear() { code = 0; lines.clear(); } }; /** * Low-level handling for Tor control connection. * Speaks the SMTP-like protocol as defined in torspec/control-spec.txt */ class TorControlConnection { public: typedef std::function ConnectionCB; typedef std::function ReplyHandlerCB; /** Create a new TorControlConnection. */ explicit TorControlConnection(struct event_base *base); ~TorControlConnection(); /** * Connect to a Tor control port. * target is address of the form host:port. * connected is the handler that is called when connection is successfully * established. * disconnected is a handler that is called when the connection is broken. * Return true on success. */ bool Connect(const std::string &target, const ConnectionCB &connected, const ConnectionCB &disconnected); /** * Disconnect from Tor control port. */ bool Disconnect(); /** * Send a command, register a handler for the reply. * A trailing CRLF is automatically added. * Return true on success. */ bool Command(const std::string &cmd, const ReplyHandlerCB &reply_handler); /** Response handlers for async replies */ boost::signals2::signal async_handler; private: /** Callback when ready for use */ std::function connected; /** Callback when connection lost */ std::function disconnected; /** Libevent event base */ struct event_base *base; /** Connection to control socket */ struct bufferevent *b_conn; /** Message being received */ TorControlReply message; /** Response handlers */ std::deque reply_handlers; /** Libevent handlers: internal */ static void readcb(struct bufferevent *bev, void *ctx); static void eventcb(struct bufferevent *bev, short what, void *ctx); }; TorControlConnection::TorControlConnection(struct event_base *_base) : base(_base), b_conn(nullptr) {} TorControlConnection::~TorControlConnection() { if (b_conn) { bufferevent_free(b_conn); } } void TorControlConnection::readcb(struct bufferevent *bev, void *ctx) { TorControlConnection *self = static_cast(ctx); struct evbuffer *input = bufferevent_get_input(bev); size_t n_read_out = 0; char *line; assert(input); // If there is not a whole line to read, evbuffer_readln returns nullptr while ((line = evbuffer_readln(input, &n_read_out, EVBUFFER_EOL_CRLF)) != nullptr) { std::string s(line, n_read_out); free(line); // Short line if (s.size() < 4) { continue; } // (-|+| ) self->message.code = atoi(s.substr(0, 3)); self->message.lines.push_back(s.substr(4)); // '-','+' or ' ' char ch = s[3]; if (ch == ' ') { // Final line, dispatch reply and clean up if (self->message.code >= 600) { // Dispatch async notifications to async handler. // Synchronous and asynchronous messages are never interleaved self->async_handler(*self, self->message); } else { if (!self->reply_handlers.empty()) { // Invoke reply handler with message self->reply_handlers.front()(*self, self->message); self->reply_handlers.pop_front(); } else { LogPrint(BCLog::TOR, "tor: Received unexpected sync reply %i\n", self->message.code); } } self->message.Clear(); } } // Check for size of buffer - protect against memory exhaustion with very // long lines. Do this after evbuffer_readln to make sure all full lines // have been removed from the buffer. Everything left is an incomplete line. if (evbuffer_get_length(input) > MAX_LINE_LENGTH) { LogPrintf("tor: Disconnecting because MAX_LINE_LENGTH exceeded\n"); self->Disconnect(); } } void TorControlConnection::eventcb(struct bufferevent *bev, short what, void *ctx) { TorControlConnection *self = static_cast(ctx); if (what & BEV_EVENT_CONNECTED) { LogPrint(BCLog::TOR, "tor: Successfully connected!\n"); self->connected(*self); } else if (what & (BEV_EVENT_EOF | BEV_EVENT_ERROR)) { if (what & BEV_EVENT_ERROR) { LogPrint(BCLog::TOR, "tor: Error connecting to Tor control socket\n"); } else { LogPrint(BCLog::TOR, "tor: End of stream\n"); } self->Disconnect(); self->disconnected(*self); } } bool TorControlConnection::Connect(const std::string &target, const ConnectionCB &_connected, const ConnectionCB &_disconnected) { if (b_conn) { Disconnect(); } // Parse target address:port struct sockaddr_storage connect_to_addr; int connect_to_addrlen = sizeof(connect_to_addr); if (evutil_parse_sockaddr_port(target.c_str(), (struct sockaddr *)&connect_to_addr, &connect_to_addrlen) < 0) { LogPrintf("tor: Error parsing socket address %s\n", target); return false; } // Create a new socket, set up callbacks and enable notification bits b_conn = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE); if (!b_conn) { return false; } bufferevent_setcb(b_conn, TorControlConnection::readcb, nullptr, TorControlConnection::eventcb, this); bufferevent_enable(b_conn, EV_READ | EV_WRITE); this->connected = _connected; this->disconnected = _disconnected; // Finally, connect to target if (bufferevent_socket_connect(b_conn, (struct sockaddr *)&connect_to_addr, connect_to_addrlen) < 0) { LogPrintf("tor: Error connecting to address %s\n", target); return false; } return true; } bool TorControlConnection::Disconnect() { if (b_conn) { bufferevent_free(b_conn); } b_conn = nullptr; return true; } bool TorControlConnection::Command(const std::string &cmd, const ReplyHandlerCB &reply_handler) { if (!b_conn) { return false; } struct evbuffer *buf = bufferevent_get_output(b_conn); if (!buf) { return false; } evbuffer_add(buf, cmd.data(), cmd.size()); evbuffer_add(buf, "\r\n", 2); reply_handlers.push_back(reply_handler); return true; } /****** General parsing utilities ********/ /* Split reply line in the form 'AUTH METHODS=...' into a type * 'AUTH' and arguments 'METHODS=...'. */ static std::pair SplitTorReplyLine(const std::string &s) { size_t ptr = 0; std::string type; while (ptr < s.size() && s[ptr] != ' ') { type.push_back(s[ptr]); ++ptr; } if (ptr < s.size()) { // skip ' ' ++ptr; } return make_pair(type, s.substr(ptr)); } /** * Parse reply arguments in the form 'METHODS=COOKIE,SAFECOOKIE * COOKIEFILE=".../control_auth_cookie"'. */ static std::map ParseTorReplyMapping(const std::string &s) { std::map mapping; size_t ptr = 0; while (ptr < s.size()) { std::string key, value; while (ptr < s.size() && s[ptr] != '=') { key.push_back(s[ptr]); ++ptr; } // unexpected end of line if (ptr == s.size()) { return std::map(); } // skip '=' ++ptr; // Quoted string if (ptr < s.size() && s[ptr] == '"') { // skip '=' ++ptr; bool escape_next = false; while (ptr < s.size() && (!escape_next && s[ptr] != '"')) { escape_next = (s[ptr] == '\\'); value.push_back(s[ptr]); ++ptr; } // unexpected end of line if (ptr == s.size()) { return std::map(); } // skip closing '"' ++ptr; /* TODO: unescape value - according to the spec this depends on the * context, some strings use C-LogPrintf style escape codes, some * don't. So may be better handled at the call site. */ } else { // Unquoted value. Note that values can contain '=' at will, just no // spaces while (ptr < s.size() && s[ptr] != ' ') { value.push_back(s[ptr]); ++ptr; } } if (ptr < s.size() && s[ptr] == ' ') { // skip ' ' after key=value ++ptr; } mapping[key] = value; } return mapping; } /** * Read full contents of a file and return them in a std::string. * Returns a pair . * If an error occurred, status will be false, otherwise status will be true and * the data will be returned in string. * * @param maxsize Puts a maximum size limit on the file that is read. If the * file is larger than this, truncated data * (with len > maxsize) will be returned. */ static std::pair ReadBinaryFile(const fs::path &filename, size_t maxsize = std::numeric_limits::max()) { FILE *f = fsbridge::fopen(filename, "rb"); if (f == nullptr) { return std::make_pair(false, ""); } std::string retval; char buffer[128]; size_t n; while ((n = fread(buffer, 1, sizeof(buffer), f)) > 0) { retval.append(buffer, buffer + n); if (retval.size() > maxsize) { break; } } fclose(f); return std::make_pair(true, retval); } /** * Write contents of std::string to a file. * @return true on success. */ static bool WriteBinaryFile(const fs::path &filename, const std::string &data) { FILE *f = fsbridge::fopen(filename, "wb"); if (f == nullptr) { return false; } if (fwrite(data.data(), 1, data.size(), f) != data.size()) { fclose(f); return false; } fclose(f); return true; } /****** Bitcoin specific TorController implementation ********/ /** * Controller that connects to Tor control socket, authenticate, then create - * and maintain a ephemeral hidden service. + * and maintain an ephemeral hidden service. */ class TorController { public: TorController(struct event_base *base, const std::string &target); ~TorController(); /** Get name fo file to store private key in */ fs::path GetPrivateKeyFile(); /** Reconnect, after getting disconnected */ void Reconnect(); private: struct event_base *base; std::string target; TorControlConnection conn; std::string private_key; std::string service_id; bool reconnect; struct event *reconnect_ev; float reconnect_timeout; CService service; /** Cookie for SAFECOOKIE auth */ std::vector cookie; /** ClientNonce for SAFECOOKIE auth */ std::vector clientNonce; /** Callback for ADD_ONION result */ void add_onion_cb(TorControlConnection &conn, const TorControlReply &reply); /** Callback for AUTHENTICATE result */ void auth_cb(TorControlConnection &conn, const TorControlReply &reply); /** Callback for AUTHCHALLENGE result */ void authchallenge_cb(TorControlConnection &conn, const TorControlReply &reply); /** Callback for PROTOCOLINFO result */ void protocolinfo_cb(TorControlConnection &conn, const TorControlReply &reply); /** Callback after successful connection */ void connected_cb(TorControlConnection &conn); /** Callback after connection lost or failed connection attempt */ void disconnected_cb(TorControlConnection &conn); /** Callback for reconnect timer */ static void reconnect_cb(evutil_socket_t fd, short what, void *arg); }; TorController::TorController(struct event_base *_base, const std::string &_target) : base(_base), target(_target), conn(base), reconnect(true), reconnect_ev(0), reconnect_timeout(RECONNECT_TIMEOUT_START) { reconnect_ev = event_new(base, -1, 0, reconnect_cb, this); if (!reconnect_ev) { LogPrintf( "tor: Failed to create event for reconnection: out of memory?\n"); } // Start connection attempts immediately if (!conn.Connect(_target, boost::bind(&TorController::connected_cb, this, _1), boost::bind(&TorController::disconnected_cb, this, _1))) { LogPrintf("tor: Initiating connection to Tor control port %s failed\n", _target); } // Read service private key if cached std::pair pkf = ReadBinaryFile(GetPrivateKeyFile()); if (pkf.first) { LogPrint(BCLog::TOR, "tor: Reading cached private key from %s\n", GetPrivateKeyFile()); private_key = pkf.second; } } TorController::~TorController() { if (reconnect_ev) { event_free(reconnect_ev); reconnect_ev = nullptr; } if (service.IsValid()) { RemoveLocal(service); } } void TorController::add_onion_cb(TorControlConnection &_conn, const TorControlReply &reply) { if (reply.code == 250) { LogPrint(BCLog::TOR, "tor: ADD_ONION successful\n"); for (const std::string &s : reply.lines) { std::map m = ParseTorReplyMapping(s); std::map::iterator i; if ((i = m.find("ServiceID")) != m.end()) { service_id = i->second; } if ((i = m.find("PrivateKey")) != m.end()) { private_key = i->second; } } service = LookupNumeric(std::string(service_id + ".onion").c_str(), GetListenPort()); LogPrintf("tor: Got service ID %s, advertising service %s\n", service_id, service.ToString()); if (WriteBinaryFile(GetPrivateKeyFile(), private_key)) { LogPrint(BCLog::TOR, "tor: Cached service private key to %s\n", GetPrivateKeyFile()); } else { LogPrintf("tor: Error writing service private key to %s\n", GetPrivateKeyFile()); } AddLocal(service, LOCAL_MANUAL); // ... onion requested - keep connection open } else if (reply.code == 510) { // 510 Unrecognized command LogPrintf("tor: Add onion failed with unrecognized command (You " "probably need to upgrade Tor)\n"); } else { LogPrintf("tor: Add onion failed; error code %d\n", reply.code); } } void TorController::auth_cb(TorControlConnection &_conn, const TorControlReply &reply) { if (reply.code == 250) { LogPrint(BCLog::TOR, "tor: Authentication successful\n"); // Now that we know Tor is running setup the proxy for onion addresses // if -onion isn't set to something else. if (gArgs.GetArg("-onion", "") == "") { CService resolved(LookupNumeric("127.0.0.1", 9050)); proxyType addrOnion = proxyType(resolved, true); SetProxy(NET_ONION, addrOnion); SetLimited(NET_ONION, false); } // Finally - now create the service // No private key, generate one if (private_key.empty()) { // Explicitly request RSA1024 - see issue #9214 private_key = "NEW:RSA1024"; } // Request hidden service, redirect port. // Note that the 'virtual' port doesn't have to be the same as our // internal port, but this is just a convenient choice. TODO; refactor // the shutdown sequence some day. _conn.Command(strprintf("ADD_ONION %s Port=%i,127.0.0.1:%i", private_key, GetListenPort(), GetListenPort()), boost::bind(&TorController::add_onion_cb, this, _1, _2)); } else { LogPrintf("tor: Authentication failed\n"); } } /** Compute Tor SAFECOOKIE response. * * ServerHash is computed as: * HMAC-SHA256("Tor safe cookie authentication server-to-controller hash", * CookieString | ClientNonce | ServerNonce) * (with the HMAC key as its first argument) * * After a controller sends a successful AUTHCHALLENGE command, the * next command sent on the connection must be an AUTHENTICATE command, * and the only authentication string which that AUTHENTICATE command * will accept is: * * HMAC-SHA256("Tor safe cookie authentication controller-to-server hash", * CookieString | ClientNonce | ServerNonce) * */ static std::vector ComputeResponse(const std::string &key, const std::vector &cookie, const std::vector &clientNonce, const std::vector &serverNonce) { CHMAC_SHA256 computeHash((const uint8_t *)key.data(), key.size()); std::vector computedHash(CHMAC_SHA256::OUTPUT_SIZE, 0); computeHash.Write(cookie.data(), cookie.size()); computeHash.Write(clientNonce.data(), clientNonce.size()); computeHash.Write(serverNonce.data(), serverNonce.size()); computeHash.Finalize(computedHash.data()); return computedHash; } void TorController::authchallenge_cb(TorControlConnection &_conn, const TorControlReply &reply) { if (reply.code == 250) { LogPrint(BCLog::TOR, "tor: SAFECOOKIE authentication challenge successful\n"); std::pair l = SplitTorReplyLine(reply.lines[0]); if (l.first == "AUTHCHALLENGE") { std::map m = ParseTorReplyMapping(l.second); std::vector serverHash = ParseHex(m["SERVERHASH"]); std::vector serverNonce = ParseHex(m["SERVERNONCE"]); LogPrint(BCLog::TOR, "tor: AUTHCHALLENGE ServerHash %s ServerNonce %s\n", HexStr(serverHash), HexStr(serverNonce)); if (serverNonce.size() != 32) { LogPrintf( "tor: ServerNonce is not 32 bytes, as required by spec\n"); return; } std::vector computedServerHash = ComputeResponse( TOR_SAFE_SERVERKEY, cookie, clientNonce, serverNonce); if (computedServerHash != serverHash) { LogPrintf("tor: ServerHash %s does not match expected " "ServerHash %s\n", HexStr(serverHash), HexStr(computedServerHash)); return; } std::vector computedClientHash = ComputeResponse( TOR_SAFE_CLIENTKEY, cookie, clientNonce, serverNonce); _conn.Command("AUTHENTICATE " + HexStr(computedClientHash), boost::bind(&TorController::auth_cb, this, _1, _2)); } else { LogPrintf("tor: Invalid reply to AUTHCHALLENGE\n"); } } else { LogPrintf("tor: SAFECOOKIE authentication challenge failed\n"); } } void TorController::protocolinfo_cb(TorControlConnection &_conn, const TorControlReply &reply) { if (reply.code == 250) { std::set methods; std::string cookiefile; /* * 250-AUTH METHODS=COOKIE,SAFECOOKIE * COOKIEFILE="/home/x/.tor/control_auth_cookie" * 250-AUTH METHODS=NULL * 250-AUTH METHODS=HASHEDPASSWORD */ for (const std::string &s : reply.lines) { std::pair l = SplitTorReplyLine(s); if (l.first == "AUTH") { std::map m = ParseTorReplyMapping(l.second); std::map::iterator i; if ((i = m.find("METHODS")) != m.end()) { boost::split(methods, i->second, boost::is_any_of(",")); } if ((i = m.find("COOKIEFILE")) != m.end()) { cookiefile = i->second; } } else if (l.first == "VERSION") { std::map m = ParseTorReplyMapping(l.second); std::map::iterator i; if ((i = m.find("Tor")) != m.end()) { LogPrint(BCLog::TOR, "tor: Connected to Tor version %s\n", i->second); } } } for (const std::string &s : methods) { LogPrint(BCLog::TOR, "tor: Supported authentication method: %s\n", s); } // Prefer NULL, otherwise SAFECOOKIE. If a password is provided, use // HASHEDPASSWORD /* Authentication: * cookie: hex-encoded ~/.tor/control_auth_cookie * password: "password" */ std::string torpassword = gArgs.GetArg("-torpassword", ""); if (!torpassword.empty()) { if (methods.count("HASHEDPASSWORD")) { LogPrint(BCLog::TOR, "tor: Using HASHEDPASSWORD authentication\n"); boost::replace_all(torpassword, "\"", "\\\""); _conn.Command( "AUTHENTICATE \"" + torpassword + "\"", boost::bind(&TorController::auth_cb, this, _1, _2)); } else { LogPrintf("tor: Password provided with -torpassword, but " "HASHEDPASSWORD authentication is not available\n"); } } else if (methods.count("NULL")) { LogPrint(BCLog::TOR, "tor: Using NULL authentication\n"); _conn.Command("AUTHENTICATE", boost::bind(&TorController::auth_cb, this, _1, _2)); } else if (methods.count("SAFECOOKIE")) { // Cookie: hexdump -e '32/1 "%02x""\n"' ~/.tor/control_auth_cookie LogPrint(BCLog::TOR, "tor: Using SAFECOOKIE authentication, " "reading cookie authentication from %s\n", cookiefile); std::pair status_cookie = ReadBinaryFile(cookiefile, TOR_COOKIE_SIZE); if (status_cookie.first && status_cookie.second.size() == TOR_COOKIE_SIZE) { // _conn.Command("AUTHENTICATE " + HexStr(status_cookie.second), // boost::bind(&TorController::auth_cb, this, _1, _2)); cookie = std::vector(status_cookie.second.begin(), status_cookie.second.end()); clientNonce = std::vector(TOR_NONCE_SIZE, 0); GetRandBytes(&clientNonce[0], TOR_NONCE_SIZE); _conn.Command("AUTHCHALLENGE SAFECOOKIE " + HexStr(clientNonce), boost::bind(&TorController::authchallenge_cb, this, _1, _2)); } else { if (status_cookie.first) { LogPrintf("tor: Authentication cookie %s is not exactly %i " "bytes, as is required by the spec\n", cookiefile, TOR_COOKIE_SIZE); } else { LogPrintf("tor: Authentication cookie %s could not be " "opened (check permissions)\n", cookiefile); } } } else if (methods.count("HASHEDPASSWORD")) { LogPrintf("tor: The only supported authentication mechanism left " "is password, but no password provided with " "-torpassword\n"); } else { LogPrintf("tor: No supported authentication method\n"); } } else { LogPrintf("tor: Requesting protocol info failed\n"); } } void TorController::connected_cb(TorControlConnection &_conn) { reconnect_timeout = RECONNECT_TIMEOUT_START; // First send a PROTOCOLINFO command to figure out what authentication is // expected if (!_conn.Command( "PROTOCOLINFO 1", boost::bind(&TorController::protocolinfo_cb, this, _1, _2))) { LogPrintf("tor: Error sending initial protocolinfo command\n"); } } void TorController::disconnected_cb(TorControlConnection &_conn) { // Stop advertising service when disconnected if (service.IsValid()) { RemoveLocal(service); } service = CService(); if (!reconnect) { return; } LogPrint(BCLog::TOR, "tor: Not connected to Tor control port %s, trying to reconnect\n", target); // Single-shot timer for reconnect. Use exponential backoff. struct timeval time = MillisToTimeval(int64_t(reconnect_timeout * 1000.0)); if (reconnect_ev) { event_add(reconnect_ev, &time); } reconnect_timeout *= RECONNECT_TIMEOUT_EXP; } void TorController::Reconnect() { /* Try to reconnect and reestablish if we get booted - for example, Tor may * be restarting. */ if (!conn.Connect(target, boost::bind(&TorController::connected_cb, this, _1), boost::bind(&TorController::disconnected_cb, this, _1))) { LogPrintf( "tor: Re-initiating connection to Tor control port %s failed\n", target); } } fs::path TorController::GetPrivateKeyFile() { return GetDataDir() / "onion_private_key"; } void TorController::reconnect_cb(evutil_socket_t fd, short what, void *arg) { TorController *self = static_cast(arg); self->Reconnect(); } /****** Thread ********/ static struct event_base *gBase; static std::thread torControlThread; static void TorControlThread() { TorController ctrl(gBase, gArgs.GetArg("-torcontrol", DEFAULT_TOR_CONTROL)); event_base_dispatch(gBase); } void StartTorControl() { assert(!gBase); #ifdef WIN32 evthread_use_windows_threads(); #else evthread_use_pthreads(); #endif gBase = event_base_new(); if (!gBase) { LogPrintf("tor: Unable to create event_base\n"); return; } torControlThread = std::thread( std::bind(&TraceThread, "torcontrol", &TorControlThread)); } void InterruptTorControl() { if (gBase) { LogPrintf("tor: Thread interrupt\n"); event_base_loopbreak(gBase); } } void StopTorControl() { if (gBase) { torControlThread.join(); event_base_free(gBase); gBase = nullptr; } } diff --git a/src/txmempool.cpp b/src/txmempool.cpp index b4a8c298b4..c658f2c3ae 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -1,1395 +1,1395 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include #include // for GetConsensus. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef &_tx, const Amount _nFee, int64_t _nTime, double _entryPriority, unsigned int _entryHeight, Amount _inChainInputValue, bool _spendsCoinbase, int64_t _sigOpsCount, LockPoints lp) : tx(_tx), nFee(_nFee), nTime(_nTime), entryPriority(_entryPriority), entryHeight(_entryHeight), inChainInputValue(_inChainInputValue), spendsCoinbase(_spendsCoinbase), sigOpCount(_sigOpsCount), lockPoints(lp) { nTxSize = tx->GetTotalSize(); nTxBillableSize = tx->GetBillableSize(); nModSize = tx->CalculateModifiedSize(GetTxSize()); nUsageSize = RecursiveDynamicUsage(tx); nCountWithDescendants = 1; nSizeWithDescendants = GetTxSize(); nBillableSizeWithDescendants = GetTxBillableSize(); nModFeesWithDescendants = nFee; Amount nValueIn = tx->GetValueOut() + nFee; assert(inChainInputValue <= nValueIn); feeDelta = Amount::zero(); nCountWithAncestors = 1; nSizeWithAncestors = GetTxSize(); nBillableSizeWithAncestors = GetTxBillableSize(); nModFeesWithAncestors = nFee; nSigOpCountWithAncestors = sigOpCount; } double CTxMemPoolEntry::GetPriority(unsigned int currentHeight) const { double deltaPriority = double((currentHeight - entryHeight) * (inChainInputValue / SATOSHI)) / nModSize; double dResult = entryPriority + deltaPriority; // This should only happen if it was called with a height below entry height if (dResult < 0) { dResult = 0; } return dResult; } void CTxMemPoolEntry::UpdateFeeDelta(Amount newFeeDelta) { nModFeesWithDescendants += newFeeDelta - feeDelta; nModFeesWithAncestors += newFeeDelta - feeDelta; feeDelta = newFeeDelta; } void CTxMemPoolEntry::UpdateLockPoints(const LockPoints &lp) { lockPoints = lp; } // Update the given tx for any in-mempool descendants. // Assumes that setMemPoolChildren is correct for the given tx and all // descendants. void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap &cachedDescendants, const std::set &setExclude) { setEntries stageEntries, setAllDescendants; stageEntries = GetMemPoolChildren(updateIt); while (!stageEntries.empty()) { const txiter cit = *stageEntries.begin(); setAllDescendants.insert(cit); stageEntries.erase(cit); const setEntries &setChildren = GetMemPoolChildren(cit); for (const txiter childEntry : setChildren) { cacheMap::iterator cacheIt = cachedDescendants.find(childEntry); if (cacheIt != cachedDescendants.end()) { // We've already calculated this one, just add the entries for // this set but don't traverse again. for (const txiter cacheEntry : cacheIt->second) { setAllDescendants.insert(cacheEntry); } } else if (!setAllDescendants.count(childEntry)) { // Schedule for later processing stageEntries.insert(childEntry); } } } // setAllDescendants now contains all in-mempool descendants of updateIt. // Update and add to cached descendant map int64_t modifySize = 0; int64_t modifyBillableSize = 0; int64_t modifyCount = 0; Amount modifyFee = Amount::zero(); for (txiter cit : setAllDescendants) { if (!setExclude.count(cit->GetTx().GetId())) { modifySize += cit->GetTxSize(); modifyBillableSize += cit->GetTxBillableSize(); modifyFee += cit->GetModifiedFee(); modifyCount++; cachedDescendants[updateIt].insert(cit); // Update ancestor state for each descendant mapTx.modify(cit, update_ancestor_state(updateIt->GetTxSize(), updateIt->GetTxBillableSize(), updateIt->GetModifiedFee(), 1, updateIt->GetSigOpCount())); } } mapTx.modify(updateIt, update_descendant_state(modifySize, modifyBillableSize, modifyFee, modifyCount)); } // txidsToUpdate is the set of transaction hashes from a disconnected block // which has been re-added to the mempool. For each entry, look for descendants // that are outside txidsToUpdate, and add fee/size information for such // descendants to the parent. For each such descendant, also update the ancestor // state to include the parent. void CTxMemPool::UpdateTransactionsFromBlock( const std::vector &txidsToUpdate) { LOCK(cs); // For each entry in txidsToUpdate, store the set of in-mempool, but not // in-txidsToUpdate transactions, so that we don't have to recalculate // descendants when we come across a previously seen entry. cacheMap mapMemPoolDescendantsToUpdate; // Use a set for lookups into txidsToUpdate (these entries are already // accounted for in the state of their ancestors) std::set setAlreadyIncluded(txidsToUpdate.begin(), txidsToUpdate.end()); - // Iterate in reverse, so that whenever we are looking at at a transaction + // Iterate in reverse, so that whenever we are looking at a transaction // we are sure that all in-mempool descendants have already been processed. // This maximizes the benefit of the descendant cache and guarantees that // setMemPoolChildren will be updated, an assumption made in // UpdateForDescendants. for (const TxId &txid : reverse_iterate(txidsToUpdate)) { // we cache the in-mempool children to avoid duplicate updates setEntries setChildren; // calculate children from mapNextTx txiter it = mapTx.find(txid); if (it == mapTx.end()) { continue; } auto iter = mapNextTx.lower_bound(COutPoint(txid, 0)); // First calculate the children, and update setMemPoolChildren to // include them, and update their setMemPoolParents to include this tx. for (; iter != mapNextTx.end() && iter->first->GetTxId() == txid; ++iter) { const TxId &childTxId = iter->second->GetId(); txiter childIter = mapTx.find(childTxId); assert(childIter != mapTx.end()); // We can skip updating entries we've encountered before or that are // in the block (which are already accounted for). if (setChildren.insert(childIter).second && !setAlreadyIncluded.count(childTxId)) { UpdateChild(it, childIter, true); UpdateParent(childIter, it, true); } } UpdateForDescendants(it, mapMemPoolDescendantsToUpdate, setAlreadyIncluded); } } bool CTxMemPool::CalculateMemPoolAncestors( const CTxMemPoolEntry &entry, setEntries &setAncestors, uint64_t limitAncestorCount, uint64_t limitAncestorSize, uint64_t limitDescendantCount, uint64_t limitDescendantSize, std::string &errString, bool fSearchForParents /* = true */) const { LOCK(cs); setEntries parentHashes; const CTransaction &tx = entry.GetTx(); if (fSearchForParents) { // Get parents of this transaction that are in the mempool // GetMemPoolParents() is only valid for entries in the mempool, so we // iterate mapTx to find parents. for (const CTxIn &in : tx.vin) { txiter piter = mapTx.find(in.prevout.GetTxId()); if (piter == mapTx.end()) { continue; } parentHashes.insert(piter); if (parentHashes.size() + 1 > limitAncestorCount) { errString = strprintf("too many unconfirmed parents [limit: %u]", limitAncestorCount); return false; } } } else { // If we're not searching for parents, we require this to be an entry in // the mempool already. txiter it = mapTx.iterator_to(entry); parentHashes = GetMemPoolParents(it); } size_t totalSizeWithAncestors = entry.GetTxSize(); while (!parentHashes.empty()) { txiter stageit = *parentHashes.begin(); setAncestors.insert(stageit); parentHashes.erase(stageit); totalSizeWithAncestors += stageit->GetTxSize(); if (stageit->GetSizeWithDescendants() + entry.GetTxSize() > limitDescendantSize) { errString = strprintf( "exceeds descendant size limit for tx %s [limit: %u]", stageit->GetTx().GetId().ToString(), limitDescendantSize); return false; } if (stageit->GetCountWithDescendants() + 1 > limitDescendantCount) { errString = strprintf("too many descendants for tx %s [limit: %u]", stageit->GetTx().GetId().ToString(), limitDescendantCount); return false; } if (totalSizeWithAncestors > limitAncestorSize) { errString = strprintf("exceeds ancestor size limit [limit: %u]", limitAncestorSize); return false; } const setEntries &setMemPoolParents = GetMemPoolParents(stageit); for (const txiter &phash : setMemPoolParents) { // If this is a new ancestor, add it. if (setAncestors.count(phash) == 0) { parentHashes.insert(phash); } if (parentHashes.size() + setAncestors.size() + 1 > limitAncestorCount) { errString = strprintf("too many unconfirmed ancestors [limit: %u]", limitAncestorCount); return false; } } } return true; } void CTxMemPool::UpdateAncestorsOf(bool add, txiter it, setEntries &setAncestors) { setEntries parentIters = GetMemPoolParents(it); // add or remove this tx as a child of each parent for (txiter piter : parentIters) { UpdateChild(piter, it, add); } const int64_t updateCount = (add ? 1 : -1); const int64_t updateSize = updateCount * it->GetTxSize(); const int64_t updateBillableSize = updateCount * it->GetTxBillableSize(); const Amount updateFee = updateCount * it->GetModifiedFee(); for (txiter ancestorIt : setAncestors) { mapTx.modify(ancestorIt, update_descendant_state(updateSize, updateBillableSize, updateFee, updateCount)); } } void CTxMemPool::UpdateEntryForAncestors(txiter it, const setEntries &setAncestors) { int64_t updateCount = setAncestors.size(); int64_t updateSize = 0; int64_t updateBillableSize = 0; int64_t updateSigOpsCount = 0; Amount updateFee = Amount::zero(); for (txiter ancestorIt : setAncestors) { updateSize += ancestorIt->GetTxSize(); updateBillableSize += ancestorIt->GetTxBillableSize(); updateFee += ancestorIt->GetModifiedFee(); updateSigOpsCount += ancestorIt->GetSigOpCount(); } mapTx.modify(it, update_ancestor_state(updateSize, updateBillableSize, updateFee, updateCount, updateSigOpsCount)); } void CTxMemPool::UpdateChildrenForRemoval(txiter it) { const setEntries &setMemPoolChildren = GetMemPoolChildren(it); for (txiter updateIt : setMemPoolChildren) { UpdateParent(updateIt, it, false); } } void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove, bool updateDescendants) { // For each entry, walk back all ancestors and decrement size associated // with this transaction. const uint64_t nNoLimit = std::numeric_limits::max(); if (updateDescendants) { // updateDescendants should be true whenever we're not recursively // removing a tx and all its descendants, eg when a transaction is // confirmed in a block. Here we only update statistics and not data in // mapLinks (which we need to preserve until we're finished with all // operations that need to traverse the mempool). for (txiter removeIt : entriesToRemove) { setEntries setDescendants; CalculateDescendants(removeIt, setDescendants); setDescendants.erase(removeIt); // don't update state for self int64_t modifySize = -int64_t(removeIt->GetTxSize()); int64_t modifyBillableSize = -int64_t(removeIt->GetTxBillableSize()); Amount modifyFee = -1 * removeIt->GetModifiedFee(); int modifySigOps = -removeIt->GetSigOpCount(); for (txiter dit : setDescendants) { mapTx.modify( dit, update_ancestor_state(modifySize, modifyBillableSize, modifyFee, -1, modifySigOps)); } } } for (txiter removeIt : entriesToRemove) { setEntries setAncestors; const CTxMemPoolEntry &entry = *removeIt; std::string dummy; // Since this is a tx that is already in the mempool, we can call CMPA // with fSearchForParents = false. If the mempool is in a consistent // state, then using true or false should both be correct, though false // should be a bit faster. // However, if we happen to be in the middle of processing a reorg, then // the mempool can be in an inconsistent state. In this case, the set of // ancestors reachable via mapLinks will be the same as the set of // ancestors whose packages include this transaction, because when we // add a new transaction to the mempool in addUnchecked(), we assume it // has no children, and in the case of a reorg where that assumption is // false, the in-mempool children aren't linked to the in-block tx's // until UpdateTransactionsFromBlock() is called. So if we're being // called during a reorg, ie before UpdateTransactionsFromBlock() has // been called, then mapLinks[] will differ from the set of mempool // parents we'd calculate by searching, and it's important that we use // the mapLinks[] notion of ancestor transactions as the set of things // to update for removal. CalculateMemPoolAncestors(entry, setAncestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy, false); // Note that UpdateAncestorsOf severs the child links that point to // removeIt in the entries for the parents of removeIt. UpdateAncestorsOf(false, removeIt, setAncestors); } // After updating all the ancestor sizes, we can now sever the link between // each transaction being removed and any mempool children (ie, update // setMemPoolParents for each direct child of a transaction being removed). for (txiter removeIt : entriesToRemove) { UpdateChildrenForRemoval(removeIt); } } void CTxMemPoolEntry::UpdateDescendantState(int64_t modifySize, int64_t modifyBillableSize, Amount modifyFee, int64_t modifyCount) { nSizeWithDescendants += modifySize; assert(int64_t(nSizeWithDescendants) > 0); nBillableSizeWithDescendants += modifyBillableSize; assert(int64_t(nBillableSizeWithDescendants) >= 0); nModFeesWithDescendants += modifyFee; nCountWithDescendants += modifyCount; assert(int64_t(nCountWithDescendants) > 0); } void CTxMemPoolEntry::UpdateAncestorState(int64_t modifySize, int64_t modifyBillableSize, Amount modifyFee, int64_t modifyCount, int modifySigOps) { nSizeWithAncestors += modifySize; assert(int64_t(nSizeWithAncestors) > 0); nBillableSizeWithAncestors += modifyBillableSize; assert(int64_t(nBillableSizeWithAncestors) >= 0); nModFeesWithAncestors += modifyFee; nCountWithAncestors += modifyCount; assert(int64_t(nCountWithAncestors) > 0); nSigOpCountWithAncestors += modifySigOps; assert(int(nSigOpCountWithAncestors) >= 0); } CTxMemPool::CTxMemPool() : nTransactionsUpdated(0) { // lock free clear _clear(); // Sanity checks off by default for performance, because otherwise accepting // transactions becomes O(N^2) where N is the number of transactions in the // pool nCheckFrequency = 0; } CTxMemPool::~CTxMemPool() {} bool CTxMemPool::isSpent(const COutPoint &outpoint) { LOCK(cs); return mapNextTx.count(outpoint); } unsigned int CTxMemPool::GetTransactionsUpdated() const { LOCK(cs); return nTransactionsUpdated; } void CTxMemPool::AddTransactionsUpdated(unsigned int n) { LOCK(cs); nTransactionsUpdated += n; } bool CTxMemPool::addUnchecked(const uint256 &hash, const CTxMemPoolEntry &entry, setEntries &setAncestors) { NotifyEntryAdded(entry.GetSharedTx()); // Add to memory pool without checking anything. // Used by AcceptToMemoryPool(), which DOES do all the appropriate checks. LOCK(cs); indexed_transaction_set::iterator newit = mapTx.insert(entry).first; mapLinks.insert(make_pair(newit, TxLinks())); // Update transaction for any feeDelta created by PrioritiseTransaction // TODO: refactor so that the fee delta is calculated before inserting into // mapTx. std::map::const_iterator pos = mapDeltas.find(hash); if (pos != mapDeltas.end()) { const TXModifier &deltas = pos->second; if (deltas.second != Amount::zero()) { mapTx.modify(newit, update_fee_delta(deltas.second)); } } // Update cachedInnerUsage to include contained transaction's usage. // (When we update the entry for in-mempool parents, memory usage will be // further updated.) cachedInnerUsage += entry.DynamicMemoryUsage(); const CTransaction &tx = newit->GetTx(); std::set setParentTransactions; for (const CTxIn &in : tx.vin) { mapNextTx.insert(std::make_pair(&in.prevout, &tx)); setParentTransactions.insert(in.prevout.GetTxId()); } // Don't bother worrying about child transactions of this one. Normal case // of a new transaction arriving is that there can't be any children, // because such children would be orphans. An exception to that is if a // transaction enters that used to be in a block. In that case, our // disconnect block logic will call UpdateTransactionsFromBlock to clean up // the mess we're leaving here. // Update ancestors with information about this tx for (const uint256 &phash : setParentTransactions) { txiter pit = mapTx.find(phash); if (pit != mapTx.end()) { UpdateParent(newit, pit, true); } } UpdateAncestorsOf(true, newit, setAncestors); UpdateEntryForAncestors(newit, setAncestors); nTransactionsUpdated++; totalTxSize += entry.GetTxSize(); vTxHashes.emplace_back(tx.GetHash(), newit); newit->vTxHashesIdx = vTxHashes.size() - 1; return true; } void CTxMemPool::removeUnchecked(txiter it, MemPoolRemovalReason reason) { NotifyEntryRemoved(it->GetSharedTx(), reason); for (const CTxIn &txin : it->GetTx().vin) { mapNextTx.erase(txin.prevout); } if (vTxHashes.size() > 1) { vTxHashes[it->vTxHashesIdx] = std::move(vTxHashes.back()); vTxHashes[it->vTxHashesIdx].second->vTxHashesIdx = it->vTxHashesIdx; vTxHashes.pop_back(); if (vTxHashes.size() * 2 < vTxHashes.capacity()) { vTxHashes.shrink_to_fit(); } } else { vTxHashes.clear(); } totalTxSize -= it->GetTxSize(); cachedInnerUsage -= it->DynamicMemoryUsage(); cachedInnerUsage -= memusage::DynamicUsage(mapLinks[it].parents) + memusage::DynamicUsage(mapLinks[it].children); mapLinks.erase(it); mapTx.erase(it); nTransactionsUpdated++; } // Calculates descendants of entry that are not already in setDescendants, and // adds to setDescendants. Assumes entryit is already a tx in the mempool and // setMemPoolChildren is correct for tx and all descendants. Also assumes that // if an entry is in setDescendants already, then all in-mempool descendants of // it are already in setDescendants as well, so that we can save time by not // iterating over those entries. void CTxMemPool::CalculateDescendants(txiter entryit, setEntries &setDescendants) const { setEntries stage; if (setDescendants.count(entryit) == 0) { stage.insert(entryit); } // Traverse down the children of entry, only adding children that are not // accounted for in setDescendants already (because those children have // either already been walked, or will be walked in this iteration). while (!stage.empty()) { txiter it = *stage.begin(); setDescendants.insert(it); stage.erase(it); const setEntries &setChildren = GetMemPoolChildren(it); for (const txiter &childiter : setChildren) { if (!setDescendants.count(childiter)) { stage.insert(childiter); } } } } void CTxMemPool::removeRecursive(const CTransaction &origTx, MemPoolRemovalReason reason) { // Remove transaction from memory pool. LOCK(cs); setEntries txToRemove; txiter origit = mapTx.find(origTx.GetId()); if (origit != mapTx.end()) { txToRemove.insert(origit); } else { // When recursively removing but origTx isn't in the mempool be sure to // remove any children that are in the pool. This can happen during // chain re-orgs if origTx isn't re-accepted into the mempool for any // reason. for (size_t i = 0; i < origTx.vout.size(); i++) { auto it = mapNextTx.find(COutPoint(origTx.GetId(), i)); if (it == mapNextTx.end()) { continue; } txiter nextit = mapTx.find(it->second->GetId()); assert(nextit != mapTx.end()); txToRemove.insert(nextit); } } setEntries setAllRemoves; for (txiter it : txToRemove) { CalculateDescendants(it, setAllRemoves); } RemoveStaged(setAllRemoves, false, reason); } void CTxMemPool::removeForReorg(const Config &config, const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags) { // Remove transactions spending a coinbase which are now immature and // no-longer-final transactions. LOCK(cs); setEntries txToRemove; for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) { const CTransaction &tx = it->GetTx(); LockPoints lp = it->GetLockPoints(); bool validLP = TestLockPointValidity(&lp); CValidationState state; if (!ContextualCheckTransactionForCurrentBlock(config, tx, state, flags) || !CheckSequenceLocks(tx, flags, &lp, validLP)) { // Note if CheckSequenceLocks fails the LockPoints may still be // invalid. So it's critical that we remove the tx and not depend on // the LockPoints. txToRemove.insert(it); } else if (it->GetSpendsCoinbase()) { for (const CTxIn &txin : tx.vin) { indexed_transaction_set::const_iterator it2 = mapTx.find(txin.prevout.GetTxId()); if (it2 != mapTx.end()) { continue; } const Coin &coin = pcoins->AccessCoin(txin.prevout); if (nCheckFrequency != 0) { assert(!coin.IsSpent()); } if (coin.IsSpent() || (coin.IsCoinBase() && int64_t(nMemPoolHeight) - coin.GetHeight() < COINBASE_MATURITY)) { txToRemove.insert(it); break; } } } if (!validLP) { mapTx.modify(it, update_lock_points(lp)); } } setEntries setAllRemoves; for (txiter it : txToRemove) { CalculateDescendants(it, setAllRemoves); } RemoveStaged(setAllRemoves, false, MemPoolRemovalReason::REORG); } void CTxMemPool::removeConflicts(const CTransaction &tx) { // Remove transactions which depend on inputs of tx, recursively LOCK(cs); for (const CTxIn &txin : tx.vin) { auto it = mapNextTx.find(txin.prevout); if (it != mapNextTx.end()) { const CTransaction &txConflict = *it->second; if (txConflict != tx) { ClearPrioritisation(txConflict.GetId()); removeRecursive(txConflict, MemPoolRemovalReason::CONFLICT); } } } } /** * Called when a block is connected. Removes from mempool and updates the miner * fee estimator. */ void CTxMemPool::removeForBlock(const std::vector &vtx, unsigned int nBlockHeight) { LOCK(cs); DisconnectedBlockTransactions disconnectpool; disconnectpool.addForBlock(vtx); std::vector entries; for (const CTransactionRef &tx : reverse_iterate(disconnectpool.GetQueuedTx().get())) { uint256 txid = tx->GetId(); indexed_transaction_set::iterator i = mapTx.find(txid); if (i != mapTx.end()) { entries.push_back(&*i); } } for (const CTransactionRef &tx : reverse_iterate(disconnectpool.GetQueuedTx().get())) { txiter it = mapTx.find(tx->GetId()); if (it != mapTx.end()) { setEntries stage; stage.insert(it); RemoveStaged(stage, true, MemPoolRemovalReason::BLOCK); } removeConflicts(*tx); ClearPrioritisation(tx->GetId()); } disconnectpool.clear(); lastRollingFeeUpdate = GetTime(); blockSinceLastRollingFeeBump = true; } void CTxMemPool::_clear() { mapLinks.clear(); mapTx.clear(); mapNextTx.clear(); vTxHashes.clear(); totalTxSize = 0; cachedInnerUsage = 0; lastRollingFeeUpdate = GetTime(); blockSinceLastRollingFeeBump = false; rollingMinimumFeeRate = 0; ++nTransactionsUpdated; } void CTxMemPool::clear() { LOCK(cs); _clear(); } void CTxMemPool::check(const CCoinsViewCache *pcoins) const { if (nCheckFrequency == 0) { return; } if (GetRand(std::numeric_limits::max()) >= nCheckFrequency) { return; } LogPrint(BCLog::MEMPOOL, "Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size()); uint64_t checkTotal = 0; uint64_t innerUsage = 0; CCoinsViewCache mempoolDuplicate(const_cast(pcoins)); const int64_t nSpendHeight = GetSpendHeight(mempoolDuplicate); LOCK(cs); std::list waitingOnDependants; for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) { unsigned int i = 0; checkTotal += it->GetTxSize(); innerUsage += it->DynamicMemoryUsage(); const CTransaction &tx = it->GetTx(); txlinksMap::const_iterator linksiter = mapLinks.find(it); assert(linksiter != mapLinks.end()); const TxLinks &links = linksiter->second; innerUsage += memusage::DynamicUsage(links.parents) + memusage::DynamicUsage(links.children); bool fDependsWait = false; setEntries setParentCheck; int64_t parentSizes = 0; int64_t parentSigOpCount = 0; for (const CTxIn &txin : tx.vin) { // Check that every mempool transaction's inputs refer to available // coins, or other mempool tx's. indexed_transaction_set::const_iterator it2 = mapTx.find(txin.prevout.GetTxId()); if (it2 != mapTx.end()) { const CTransaction &tx2 = it2->GetTx(); assert(tx2.vout.size() > txin.prevout.GetN() && !tx2.vout[txin.prevout.GetN()].IsNull()); fDependsWait = true; if (setParentCheck.insert(it2).second) { parentSizes += it2->GetTxSize(); parentSigOpCount += it2->GetSigOpCount(); } } else { assert(pcoins->HaveCoin(txin.prevout)); } // Check whether its inputs are marked in mapNextTx. auto it3 = mapNextTx.find(txin.prevout); assert(it3 != mapNextTx.end()); assert(it3->first == &txin.prevout); assert(it3->second == &tx); i++; } assert(setParentCheck == GetMemPoolParents(it)); // Verify ancestor state is correct. setEntries setAncestors; uint64_t nNoLimit = std::numeric_limits::max(); std::string dummy; CalculateMemPoolAncestors(*it, setAncestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy); uint64_t nCountCheck = setAncestors.size() + 1; uint64_t nSizeCheck = it->GetTxSize(); Amount nFeesCheck = it->GetModifiedFee(); int64_t nSigOpCheck = it->GetSigOpCount(); for (txiter ancestorIt : setAncestors) { nSizeCheck += ancestorIt->GetTxSize(); nFeesCheck += ancestorIt->GetModifiedFee(); nSigOpCheck += ancestorIt->GetSigOpCount(); } assert(it->GetCountWithAncestors() == nCountCheck); assert(it->GetSizeWithAncestors() == nSizeCheck); assert(it->GetSigOpCountWithAncestors() == nSigOpCheck); assert(it->GetModFeesWithAncestors() == nFeesCheck); // Check children against mapNextTx CTxMemPool::setEntries setChildrenCheck; auto iter = mapNextTx.lower_bound(COutPoint(it->GetTx().GetId(), 0)); int64_t childSizes = 0; for (; iter != mapNextTx.end() && iter->first->GetTxId() == it->GetTx().GetId(); ++iter) { txiter childit = mapTx.find(iter->second->GetId()); // mapNextTx points to in-mempool transactions assert(childit != mapTx.end()); if (setChildrenCheck.insert(childit).second) { childSizes += childit->GetTxSize(); } } assert(setChildrenCheck == GetMemPoolChildren(it)); // Also check to make sure size is greater than sum with immediate // children. Just a sanity check, not definitive that this calc is // correct... assert(it->GetSizeWithDescendants() >= childSizes + it->GetTxSize()); if (fDependsWait) { waitingOnDependants.push_back(&(*it)); } else { CValidationState state; bool fCheckResult = tx.IsCoinBase() || Consensus::CheckTxInputs( tx, state, mempoolDuplicate, nSpendHeight); assert(fCheckResult); UpdateCoins(mempoolDuplicate, tx, 1000000); } } unsigned int stepsSinceLastRemove = 0; while (!waitingOnDependants.empty()) { const CTxMemPoolEntry *entry = waitingOnDependants.front(); waitingOnDependants.pop_front(); CValidationState state; if (!mempoolDuplicate.HaveInputs(entry->GetTx())) { waitingOnDependants.push_back(entry); stepsSinceLastRemove++; assert(stepsSinceLastRemove < waitingOnDependants.size()); } else { bool fCheckResult = entry->GetTx().IsCoinBase() || Consensus::CheckTxInputs(entry->GetTx(), state, mempoolDuplicate, nSpendHeight); assert(fCheckResult); UpdateCoins(mempoolDuplicate, entry->GetTx(), 1000000); stepsSinceLastRemove = 0; } } for (auto it = mapNextTx.cbegin(); it != mapNextTx.cend(); it++) { uint256 txid = it->second->GetId(); indexed_transaction_set::const_iterator it2 = mapTx.find(txid); const CTransaction &tx = it2->GetTx(); assert(it2 != mapTx.end()); assert(&tx == it->second); } assert(totalTxSize == checkTotal); assert(innerUsage == cachedInnerUsage); } bool CTxMemPool::CompareDepthAndScore(const uint256 &hasha, const uint256 &hashb) { LOCK(cs); indexed_transaction_set::const_iterator i = mapTx.find(hasha); if (i == mapTx.end()) { return false; } indexed_transaction_set::const_iterator j = mapTx.find(hashb); if (j == mapTx.end()) { return true; } uint64_t counta = i->GetCountWithAncestors(); uint64_t countb = j->GetCountWithAncestors(); if (counta == countb) { return CompareTxMemPoolEntryByScore()(*i, *j); } return counta < countb; } namespace { class DepthAndScoreComparator { public: bool operator()(const CTxMemPool::indexed_transaction_set::const_iterator &a, const CTxMemPool::indexed_transaction_set::const_iterator &b) { uint64_t counta = a->GetCountWithAncestors(); uint64_t countb = b->GetCountWithAncestors(); if (counta == countb) { return CompareTxMemPoolEntryByScore()(*a, *b); } return counta < countb; } }; } // namespace std::vector CTxMemPool::GetSortedDepthAndScore() const { std::vector iters; AssertLockHeld(cs); iters.reserve(mapTx.size()); for (indexed_transaction_set::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi) { iters.push_back(mi); } std::sort(iters.begin(), iters.end(), DepthAndScoreComparator()); return iters; } void CTxMemPool::queryHashes(std::vector &vtxid) { LOCK(cs); auto iters = GetSortedDepthAndScore(); vtxid.clear(); vtxid.reserve(mapTx.size()); for (auto it : iters) { vtxid.push_back(it->GetTx().GetId()); } } static TxMempoolInfo GetInfo(CTxMemPool::indexed_transaction_set::const_iterator it) { return TxMempoolInfo{it->GetSharedTx(), it->GetTime(), CFeeRate(it->GetFee(), it->GetTxBillableSize()), it->GetModifiedFee() - it->GetFee()}; } std::vector CTxMemPool::infoAll() const { LOCK(cs); auto iters = GetSortedDepthAndScore(); std::vector ret; ret.reserve(mapTx.size()); for (auto it : iters) { ret.push_back(GetInfo(it)); } return ret; } CTransactionRef CTxMemPool::get(const uint256 &txid) const { LOCK(cs); indexed_transaction_set::const_iterator i = mapTx.find(txid); if (i == mapTx.end()) { return nullptr; } return i->GetSharedTx(); } TxMempoolInfo CTxMemPool::info(const uint256 &txid) const { LOCK(cs); indexed_transaction_set::const_iterator i = mapTx.find(txid); if (i == mapTx.end()) { return TxMempoolInfo(); } return GetInfo(i); } CFeeRate CTxMemPool::estimateFee() const { LOCK(cs); uint64_t maxMempoolSize = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; // minerPolicy uses recent blocks to figure out a reasonable fee. This // may disagree with the rollingMinimumFeerate under certain scenarios // where the mempool increases rapidly, or blocks are being mined which // do not contain propagated transactions. return std::max(GetConfig().GetMinFeePerKB(), GetMinFee(maxMempoolSize)); } void CTxMemPool::PrioritiseTransaction(const uint256 &hash, double dPriorityDelta, const Amount nFeeDelta) { { LOCK(cs); TXModifier &deltas = mapDeltas[hash]; deltas.first += dPriorityDelta; deltas.second += nFeeDelta; txiter it = mapTx.find(hash); if (it != mapTx.end()) { mapTx.modify(it, update_fee_delta(deltas.second)); // Now update all ancestors' modified fees with descendants setEntries setAncestors; uint64_t nNoLimit = std::numeric_limits::max(); std::string dummy; CalculateMemPoolAncestors(*it, setAncestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy, false); for (txiter ancestorIt : setAncestors) { mapTx.modify(ancestorIt, update_descendant_state(0, 0, nFeeDelta, 0)); } // Now update all descendants' modified fees with ancestors setEntries setDescendants; CalculateDescendants(it, setDescendants); setDescendants.erase(it); for (txiter descendantIt : setDescendants) { mapTx.modify(descendantIt, update_ancestor_state(0, 0, nFeeDelta, 0, 0)); } } } LogPrintf("PrioritiseTransaction: %s priority += %f, fee += %d\n", hash.ToString(), dPriorityDelta, FormatMoney(nFeeDelta)); } void CTxMemPool::ApplyDeltas(const uint256 hash, double &dPriorityDelta, Amount &nFeeDelta) const { LOCK(cs); std::map::const_iterator pos = mapDeltas.find(hash); if (pos == mapDeltas.end()) { return; } const TXModifier &deltas = pos->second; dPriorityDelta += deltas.first; nFeeDelta += deltas.second; } void CTxMemPool::ClearPrioritisation(const uint256 hash) { LOCK(cs); mapDeltas.erase(hash); } bool CTxMemPool::HasNoInputsOf(const CTransaction &tx) const { for (const CTxIn &in : tx.vin) { if (exists(in.prevout.GetTxId())) { return false; } } return true; } CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView *baseIn, const CTxMemPool &mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) {} bool CCoinsViewMemPool::GetCoin(const COutPoint &outpoint, Coin &coin) const { // If an entry in the mempool exists, always return that one, as it's // guaranteed to never conflict with the underlying cache, and it cannot // have pruned entries (as it contains full) transactions. First checking // the underlying cache risks returning a pruned entry instead. CTransactionRef ptx = mempool.get(outpoint.GetTxId()); if (ptx) { if (outpoint.GetN() < ptx->vout.size()) { coin = Coin(ptx->vout[outpoint.GetN()], MEMPOOL_HEIGHT, false); return true; } return false; } return base->GetCoin(outpoint, coin) && !coin.IsSpent(); } bool CCoinsViewMemPool::HaveCoin(const COutPoint &outpoint) const { return mempool.exists(outpoint) || base->HaveCoin(outpoint); } size_t CTxMemPool::DynamicMemoryUsage() const { LOCK(cs); // Estimate the overhead of mapTx to be 15 pointers + an allocation, as no // exact formula for boost::multi_index_contained is implemented. return memusage::MallocUsage(sizeof(CTxMemPoolEntry) + 15 * sizeof(void *)) * mapTx.size() + memusage::DynamicUsage(mapNextTx) + memusage::DynamicUsage(mapDeltas) + memusage::DynamicUsage(mapLinks) + memusage::DynamicUsage(vTxHashes) + cachedInnerUsage; } void CTxMemPool::RemoveStaged(setEntries &stage, bool updateDescendants, MemPoolRemovalReason reason) { AssertLockHeld(cs); UpdateForRemoveFromMempool(stage, updateDescendants); for (const txiter &it : stage) { removeUnchecked(it, reason); } } int CTxMemPool::Expire(int64_t time) { LOCK(cs); indexed_transaction_set::index::type::iterator it = mapTx.get().begin(); setEntries toremove; while (it != mapTx.get().end() && it->GetTime() < time) { toremove.insert(mapTx.project<0>(it)); it++; } setEntries stage; for (txiter removeit : toremove) { CalculateDescendants(removeit, stage); } RemoveStaged(stage, false, MemPoolRemovalReason::EXPIRY); return stage.size(); } void CTxMemPool::LimitSize(size_t limit, unsigned long age) { int expired = Expire(GetTime() - age); if (expired != 0) { LogPrint(BCLog::MEMPOOL, "Expired %i transactions from the memory pool\n", expired); } std::vector vNoSpendsRemaining; TrimToSize(limit, &vNoSpendsRemaining); for (const COutPoint &removed : vNoSpendsRemaining) { pcoinsTip->Uncache(removed); } } bool CTxMemPool::addUnchecked(const uint256 &hash, const CTxMemPoolEntry &entry) { LOCK(cs); setEntries setAncestors; uint64_t nNoLimit = std::numeric_limits::max(); std::string dummy; CalculateMemPoolAncestors(entry, setAncestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy); return addUnchecked(hash, entry, setAncestors); } void CTxMemPool::UpdateChild(txiter entry, txiter child, bool add) { setEntries s; if (add && mapLinks[entry].children.insert(child).second) { cachedInnerUsage += memusage::IncrementalDynamicUsage(s); } else if (!add && mapLinks[entry].children.erase(child)) { cachedInnerUsage -= memusage::IncrementalDynamicUsage(s); } } void CTxMemPool::UpdateParent(txiter entry, txiter parent, bool add) { setEntries s; if (add && mapLinks[entry].parents.insert(parent).second) { cachedInnerUsage += memusage::IncrementalDynamicUsage(s); } else if (!add && mapLinks[entry].parents.erase(parent)) { cachedInnerUsage -= memusage::IncrementalDynamicUsage(s); } } const CTxMemPool::setEntries & CTxMemPool::GetMemPoolParents(txiter entry) const { assert(entry != mapTx.end()); txlinksMap::const_iterator it = mapLinks.find(entry); assert(it != mapLinks.end()); return it->second.parents; } const CTxMemPool::setEntries & CTxMemPool::GetMemPoolChildren(txiter entry) const { assert(entry != mapTx.end()); txlinksMap::const_iterator it = mapLinks.find(entry); assert(it != mapLinks.end()); return it->second.children; } CFeeRate CTxMemPool::GetMinFee(size_t sizelimit) const { LOCK(cs); if (!blockSinceLastRollingFeeBump || rollingMinimumFeeRate == 0) { return CFeeRate(int64_t(ceill(rollingMinimumFeeRate)) * SATOSHI); } int64_t time = GetTime(); if (time > lastRollingFeeUpdate + 10) { double halflife = ROLLING_FEE_HALFLIFE; if (DynamicMemoryUsage() < sizelimit / 4) { halflife /= 4; } else if (DynamicMemoryUsage() < sizelimit / 2) { halflife /= 2; } rollingMinimumFeeRate = rollingMinimumFeeRate / pow(2.0, (time - lastRollingFeeUpdate) / halflife); lastRollingFeeUpdate = time; } return CFeeRate(int64_t(ceill(rollingMinimumFeeRate)) * SATOSHI); } void CTxMemPool::trackPackageRemoved(const CFeeRate &rate) { AssertLockHeld(cs); if ((rate.GetFeePerK() / SATOSHI) > rollingMinimumFeeRate) { rollingMinimumFeeRate = rate.GetFeePerK() / SATOSHI; blockSinceLastRollingFeeBump = false; } } void CTxMemPool::TrimToSize(size_t sizelimit, std::vector *pvNoSpendsRemaining) { LOCK(cs); unsigned nTxnRemoved = 0; CFeeRate maxFeeRateRemoved(Amount::zero()); while (!mapTx.empty() && DynamicMemoryUsage() > sizelimit) { indexed_transaction_set::index::type::iterator it = mapTx.get().begin(); // We set the new mempool min fee to the feerate of the removed set, // plus the "minimum reasonable fee rate" (ie some value under which we // consider txn to have 0 fee). This way, we don't allow txn to enter // mempool with feerate equal to txn which were removed with no block in // between. CFeeRate removed(it->GetModFeesWithDescendants(), it->GetSizeWithDescendants()); removed += MEMPOOL_FULL_FEE_INCREMENT; trackPackageRemoved(removed); maxFeeRateRemoved = std::max(maxFeeRateRemoved, removed); setEntries stage; CalculateDescendants(mapTx.project<0>(it), stage); nTxnRemoved += stage.size(); std::vector txn; if (pvNoSpendsRemaining) { txn.reserve(stage.size()); for (txiter iter : stage) { txn.push_back(iter->GetTx()); } } RemoveStaged(stage, false, MemPoolRemovalReason::SIZELIMIT); if (pvNoSpendsRemaining) { for (const CTransaction &tx : txn) { for (const CTxIn &txin : tx.vin) { if (exists(txin.prevout.GetTxId())) { continue; } if (!mapNextTx.count(txin.prevout)) { pvNoSpendsRemaining->push_back(txin.prevout); } } } } } if (maxFeeRateRemoved > CFeeRate(Amount::zero())) { LogPrint(BCLog::MEMPOOL, "Removed %u txn, rolling minimum fee bumped to %s\n", nTxnRemoved, maxFeeRateRemoved.ToString()); } } bool CTxMemPool::TransactionWithinChainLimit(const uint256 &txid, size_t chainLimit) const { LOCK(cs); auto it = mapTx.find(txid); return it == mapTx.end() || (it->GetCountWithAncestors() < chainLimit && it->GetCountWithDescendants() < chainLimit); } SaltedTxidHasher::SaltedTxidHasher() : k0(GetRand(std::numeric_limits::max())), k1(GetRand(std::numeric_limits::max())) {} /** Maximum bytes for transactions to store for processing during reorg */ static const size_t MAX_DISCONNECTED_TX_POOL_SIZE = 20 * DEFAULT_MAX_BLOCK_SIZE; void DisconnectedBlockTransactions::addForBlock( const std::vector &vtx) { for (const auto &tx : reverse_iterate(vtx)) { // If we already added it, just skip. auto it = queuedTx.find(tx->GetId()); if (it != queuedTx.end()) { continue; } // Insert the transaction into the pool. addTransaction(tx); // Fill in the set of parents. std::unordered_set parents; for (const CTxIn &in : tx->vin) { parents.insert(in.prevout.GetTxId()); } // In order to make sure we keep things in topological order, we check // if we already know of the parent of the current transaction. If so, // we remove them from the set and then add them back. while (parents.size() > 0) { std::unordered_set worklist( std::move(parents)); parents.clear(); for (const TxId &txid : worklist) { // If we do not have that txid in the set, nothing needs to be // done. auto pit = queuedTx.find(txid); if (pit == queuedTx.end()) { continue; } // We have parent in our set, we reinsert them at the right // position. const CTransactionRef ptx = *pit; queuedTx.erase(pit); queuedTx.insert(ptx); // And we make sure ancestors are covered. for (const CTxIn &in : ptx->vin) { parents.insert(in.prevout.GetTxId()); } } } } // Keep the size under control. while (DynamicMemoryUsage() > MAX_DISCONNECTED_TX_POOL_SIZE) { // Drop the earliest entry, and remove its children from the // mempool. auto it = queuedTx.get().begin(); g_mempool.removeRecursive(**it, MemPoolRemovalReason::REORG); removeEntry(it); } } void DisconnectedBlockTransactions::importMempool(CTxMemPool &pool) { // addForBlock's algorithm sorts a vector of transactions back into // topological order. We use it in a separate object to create a valid // ordering of all mempool transactions, which we then splice in front of // the current queuedTx. This results in a valid sequence of transactions to // be reprocessed in updateMempoolForReorg. // We create vtx in order of the entry_time index to facilitate for // addForBlocks (which iterates in reverse order), as vtx probably end in // the correct ordering for queuedTx. std::vector vtx; { LOCK(pool.cs); vtx.reserve(pool.mapTx.size()); for (const CTxMemPoolEntry &e : pool.mapTx.get()) { vtx.push_back(e.GetSharedTx()); } pool.clear(); } // Use addForBlocks to sort the transactions and then splice them in front // of queuedTx DisconnectedBlockTransactions orderedTxnPool; orderedTxnPool.addForBlock(vtx); cachedInnerUsage += orderedTxnPool.cachedInnerUsage; queuedTx.get().splice( queuedTx.get().begin(), orderedTxnPool.queuedTx.get()); // We limit memory usage because we can't know if more blocks will be // disconnected while (DynamicMemoryUsage() > MAX_DISCONNECTED_TX_POOL_SIZE) { // Drop the earliest entry which, by definition, has no children removeEntry(queuedTx.get().begin()); } } void DisconnectedBlockTransactions::updateMempoolForReorg(const Config &config, bool fAddToMempool) { AssertLockHeld(cs_main); std::vector txidsUpdate; // disconnectpool's insertion_order index sorts the entries from oldest to // newest, but the oldest entry will be the last tx from the latest mined // block that was disconnected. // Iterate disconnectpool in reverse, so that we add transactions back to // the mempool starting with the earliest transaction that had been // previously seen in a block. for (const CTransactionRef &tx : reverse_iterate(queuedTx.get())) { // ignore validation errors in resurrected transactions CValidationState stateDummy; if (!fAddToMempool || tx->IsCoinBase() || !AcceptToMemoryPool(config, g_mempool, stateDummy, tx, false, nullptr, true)) { // If the transaction doesn't make it in to the mempool, remove any // transactions that depend on it (which would now be orphans). g_mempool.removeRecursive(*tx, MemPoolRemovalReason::REORG); } else if (g_mempool.exists(tx->GetId())) { txidsUpdate.push_back(tx->GetId()); } } queuedTx.clear(); // AcceptToMemoryPool/addUnchecked all assume that new mempool entries have // no in-mempool children, which is generally not true when adding // previously-confirmed transactions back to the mempool. // UpdateTransactionsFromBlock finds descendants of any transactions in the // disconnectpool that were added back and cleans up the mempool state. g_mempool.UpdateTransactionsFromBlock(txidsUpdate); // We also need to remove any now-immature transactions g_mempool.removeForReorg(config, pcoinsTip.get(), chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS); // Re-limit mempool size, in case we added any transactions g_mempool.LimitSize( gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60); } diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp index e3abe31de9..3a52835901 100644 --- a/src/utilstrencodings.cpp +++ b/src/utilstrencodings.cpp @@ -1,813 +1,813 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include #include #include #include #include #include static const std::string CHARS_ALPHA_NUM = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; static const std::string SAFE_CHARS[] = { // SAFE_CHARS_DEFAULT CHARS_ALPHA_NUM + " .,;-_/:?@()", // SAFE_CHARS_UA_COMMENT CHARS_ALPHA_NUM + " .,;-_?@", // SAFE_CHARS_FILENAME CHARS_ALPHA_NUM + ".-_", }; std::string SanitizeString(const std::string &str, int rule) { std::string strResult; for (std::string::size_type i = 0; i < str.size(); i++) { if (SAFE_CHARS[rule].find(str[i]) != std::string::npos) { strResult.push_back(str[i]); } } return strResult; } const signed char p_util_hexdigit[256] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }; signed char HexDigit(char c) { return p_util_hexdigit[(uint8_t)c]; } bool IsHex(const std::string &str) { for (std::string::const_iterator it(str.begin()); it != str.end(); ++it) { if (HexDigit(*it) < 0) { return false; } } return (str.size() > 0) && (str.size() % 2 == 0); } bool IsHexNumber(const std::string &str) { size_t starting_location = 0; if (str.size() > 2 && *str.begin() == '0' && *(str.begin() + 1) == 'x') { starting_location = 2; } for (auto c : str.substr(starting_location)) { if (HexDigit(c) < 0) { return false; } } // Return false for empty string or "0x". return (str.size() > starting_location); } std::vector ParseHex(const char *psz) { // convert hex dump to vector std::vector vch; while (true) { while (IsSpace(*psz)) { psz++; } signed char c = HexDigit(*psz++); if (c == (signed char)-1) { break; } uint8_t n = (c << 4); c = HexDigit(*psz++); if (c == (signed char)-1) { break; } n |= c; vch.push_back(n); } return vch; } std::vector ParseHex(const std::string &str) { return ParseHex(str.c_str()); } void SplitHostPort(std::string in, int &portOut, std::string &hostOut) { size_t colon = in.find_last_of(':'); // if a : is found, and it either follows a [...], or no other : is in the // string, treat it as port separator bool fHaveColon = colon != in.npos; bool fBracketed = fHaveColon && (in[0] == '[' && in[colon - 1] == ']'); // if there is a colon, and // in[0]=='[', colon is not 0, // so in[colon-1] is safe bool fMultiColon = fHaveColon && (in.find_last_of(':', colon - 1) != in.npos); if (fHaveColon && (colon == 0 || fBracketed || !fMultiColon)) { int32_t n; if (ParseInt32(in.substr(colon + 1), &n) && n > 0 && n < 0x10000) { in = in.substr(0, colon); portOut = n; } } if (in.size() > 0 && in[0] == '[' && in[in.size() - 1] == ']') { hostOut = in.substr(1, in.size() - 2); } else { hostOut = in; } } std::string EncodeBase64(const uint8_t *pch, size_t len) { static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; std::string strRet; strRet.reserve((len + 2) / 3 * 4); int mode = 0, left = 0; const uint8_t *pchEnd = pch + len; while (pch < pchEnd) { int enc = *(pch++); switch (mode) { case 0: // we have no bits strRet += pbase64[enc >> 2]; left = (enc & 3) << 4; mode = 1; break; case 1: // we have two bits strRet += pbase64[left | (enc >> 4)]; left = (enc & 15) << 2; mode = 2; break; case 2: // we have four bits strRet += pbase64[left | (enc >> 6)]; strRet += pbase64[enc & 63]; mode = 0; break; } } if (mode) { strRet += pbase64[left]; strRet += '='; if (mode == 1) { strRet += '='; } } return strRet; } std::string EncodeBase64(const std::string &str) { return EncodeBase64((const uint8_t *)str.c_str(), str.size()); } std::vector DecodeBase64(const char *p, bool *pfInvalid) { static const int decode64_table[256] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; if (pfInvalid) { *pfInvalid = false; } std::vector vchRet; vchRet.reserve(strlen(p) * 3 / 4); int mode = 0; int left = 0; while (1) { int dec = decode64_table[(uint8_t)*p]; if (dec == -1) { break; } p++; switch (mode) { case 0: // we have no bits and get 6 left = dec; mode = 1; break; case 1: // we have 6 bits and keep 4 vchRet.push_back((left << 2) | (dec >> 4)); left = dec & 15; mode = 2; break; case 2: // we have 4 bits and get 6, we keep 2 vchRet.push_back((left << 4) | (dec >> 2)); left = dec & 3; mode = 3; break; case 3: // we have 2 bits and get 6 vchRet.push_back((left << 6) | dec); mode = 0; break; } } if (pfInvalid) { switch (mode) { case 0: // 4n base64 characters processed: ok break; case 1: // 4n+1 base64 character processed: impossible *pfInvalid = true; break; case 2: // 4n+2 base64 characters processed: require '==' if (left || p[0] != '=' || p[1] != '=' || decode64_table[(uint8_t)p[2]] != -1) { *pfInvalid = true; } break; case 3: // 4n+3 base64 characters processed: require '=' if (left || p[0] != '=' || decode64_table[(uint8_t)p[1]] != -1) { *pfInvalid = true; } break; } } return vchRet; } std::string DecodeBase64(const std::string &str) { std::vector vchRet = DecodeBase64(str.c_str()); return std::string((const char *)vchRet.data(), vchRet.size()); } std::string EncodeBase32(const uint8_t *pch, size_t len) { static const char *pbase32 = "abcdefghijklmnopqrstuvwxyz234567"; std::string strRet; strRet.reserve((len + 4) / 5 * 8); int mode = 0, left = 0; const uint8_t *pchEnd = pch + len; while (pch < pchEnd) { int enc = *(pch++); switch (mode) { case 0: // we have no bits strRet += pbase32[enc >> 3]; left = (enc & 7) << 2; mode = 1; break; case 1: // we have three bits strRet += pbase32[left | (enc >> 6)]; strRet += pbase32[(enc >> 1) & 31]; left = (enc & 1) << 4; mode = 2; break; case 2: // we have one bit strRet += pbase32[left | (enc >> 4)]; left = (enc & 15) << 1; mode = 3; break; case 3: // we have four bits strRet += pbase32[left | (enc >> 7)]; strRet += pbase32[(enc >> 2) & 31]; left = (enc & 3) << 3; mode = 4; break; case 4: // we have two bits strRet += pbase32[left | (enc >> 5)]; strRet += pbase32[enc & 31]; mode = 0; } } static const int nPadding[5] = {0, 6, 4, 3, 1}; if (mode) { strRet += pbase32[left]; for (int n = 0; n < nPadding[mode]; n++) { strRet += '='; } } return strRet; } std::string EncodeBase32(const std::string &str) { return EncodeBase32((const uint8_t *)str.c_str(), str.size()); } std::vector DecodeBase32(const char *p, bool *pfInvalid) { static const int decode32_table[256] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; if (pfInvalid) { *pfInvalid = false; } std::vector vchRet; vchRet.reserve((strlen(p)) * 5 / 8); int mode = 0; int left = 0; while (1) { int dec = decode32_table[(uint8_t)*p]; if (dec == -1) { break; } p++; switch (mode) { case 0: // we have no bits and get 5 left = dec; mode = 1; break; case 1: // we have 5 bits and keep 2 vchRet.push_back((left << 3) | (dec >> 2)); left = dec & 3; mode = 2; break; case 2: // we have 2 bits and keep 7 left = left << 5 | dec; mode = 3; break; case 3: // we have 7 bits and keep 4 vchRet.push_back((left << 1) | (dec >> 4)); left = dec & 15; mode = 4; break; case 4: // we have 4 bits, and keep 1 vchRet.push_back((left << 4) | (dec >> 1)); left = dec & 1; mode = 5; break; case 5: // we have 1 bit, and keep 6 left = left << 5 | dec; mode = 6; break; case 6: // we have 6 bits, and keep 3 vchRet.push_back((left << 2) | (dec >> 3)); left = dec & 7; mode = 7; break; case 7: // we have 3 bits, and keep 0 vchRet.push_back((left << 5) | dec); mode = 0; break; } } if (pfInvalid) switch (mode) { case 0: // 8n base32 characters processed: ok break; case 1: // 8n+1 base32 characters processed: impossible case 3: // +3 case 6: // +6 *pfInvalid = true; break; case 2: // 8n+2 base32 characters processed: require '======' if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || p[3] != '=' || p[4] != '=' || p[5] != '=' || decode32_table[(uint8_t)p[6]] != -1) { *pfInvalid = true; } break; case 4: // 8n+4 base32 characters processed: require '====' if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || p[3] != '=' || decode32_table[(uint8_t)p[4]] != -1) { *pfInvalid = true; } break; case 5: // 8n+5 base32 characters processed: require '===' if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || decode32_table[(uint8_t)p[3]] != -1) { *pfInvalid = true; } break; case 7: // 8n+7 base32 characters processed: require '=' if (left || p[0] != '=' || decode32_table[(uint8_t)p[1]] != -1) { *pfInvalid = true; } break; } return vchRet; } std::string DecodeBase32(const std::string &str) { std::vector vchRet = DecodeBase32(str.c_str()); return std::string((const char *)vchRet.data(), vchRet.size()); } static bool ParsePrechecks(const std::string &str) { // No empty string allowed if (str.empty()) { return false; } // No padding allowed if (str.size() >= 1 && (IsSpace(str[0]) || IsSpace(str[str.size() - 1]))) { return false; } // No embedded NUL characters allowed if (str.size() != strlen(str.c_str())) { return false; } return true; } bool ParseInt32(const std::string &str, int32_t *out) { if (!ParsePrechecks(str)) { return false; } char *endp = nullptr; // strtol will not set errno if valid errno = 0; long int n = strtol(str.c_str(), &endp, 10); if (out) { *out = (int32_t)n; } - // Note that strtol returns a *long int*, so even if strtol doesn't report a - // over/underflow we still have to check that the returned value is within - // the range of an *int32_t*. On 64-bit platforms the size of these types - // may be different. + // Note that strtol returns a *long int*, so even if strtol doesn't report + // an over/underflow we still have to check that the returned value is + // within the range of an *int32_t*. On 64-bit platforms the size of these + // types may be different. return endp && *endp == 0 && !errno && n >= std::numeric_limits::min() && n <= std::numeric_limits::max(); } bool ParseInt64(const std::string &str, int64_t *out) { if (!ParsePrechecks(str)) { return false; } char *endp = nullptr; // strtoll will not set errno if valid errno = 0; long long int n = strtoll(str.c_str(), &endp, 10); if (out) { *out = (int64_t)n; } // Note that strtoll returns a *long long int*, so even if strtol doesn't - // report a over/underflow we still have to check that the returned value is - // within the range of an *int64_t*. + // report an over/underflow we still have to check that the returned value + // is within the range of an *int64_t*. return endp && *endp == 0 && !errno && n >= std::numeric_limits::min() && n <= std::numeric_limits::max(); } bool ParseUInt32(const std::string &str, uint32_t *out) { if (!ParsePrechecks(str)) { return false; } // Reject negative values, unfortunately strtoul accepts these by default if // they fit in the range if (str.size() >= 1 && str[0] == '-') { return false; } char *endp = nullptr; // strtoul will not set errno if valid errno = 0; unsigned long int n = strtoul(str.c_str(), &endp, 10); if (out) { *out = (uint32_t)n; } // Note that strtoul returns a *unsigned long int*, so even if it doesn't - // report a over/underflow we still have to check that the returned value is - // within the range of an *uint32_t*. On 64-bit platforms the size of these - // types may be different. + // report an over/underflow we still have to check that the returned value + // is within the range of an *uint32_t*. On 64-bit platforms the size of + // these types may be different. return endp && *endp == 0 && !errno && n <= std::numeric_limits::max(); } bool ParseUInt64(const std::string &str, uint64_t *out) { if (!ParsePrechecks(str)) { return false; } // Reject negative values, unfortunately strtoull accepts these by default // if they fit in the range if (str.size() >= 1 && str[0] == '-') { return false; } char *endp = nullptr; // strtoull will not set errno if valid errno = 0; unsigned long long int n = strtoull(str.c_str(), &endp, 10); if (out) { *out = (uint64_t)n; } // Note that strtoull returns a *unsigned long long int*, so even if it - // doesn't report a over/underflow we still have to check that the returned + // doesn't report an over/underflow we still have to check that the returned // value is within the range of an *uint64_t*. return endp && *endp == 0 && !errno && n <= std::numeric_limits::max(); } bool ParseDouble(const std::string &str, double *out) { if (!ParsePrechecks(str)) { return false; } // No hexadecimal floats allowed if (str.size() >= 2 && str[0] == '0' && str[1] == 'x') { return false; } std::istringstream text(str); text.imbue(std::locale::classic()); double result; text >> result; if (out) { *out = result; } return text.eof() && !text.fail(); } std::string FormatParagraph(const std::string &in, size_t width, size_t indent) { std::stringstream out; size_t ptr = 0; size_t indented = 0; while (ptr < in.size()) { size_t lineend = in.find_first_of('\n', ptr); if (lineend == std::string::npos) { lineend = in.size(); } const size_t linelen = lineend - ptr; const size_t rem_width = width - indented; if (linelen <= rem_width) { out << in.substr(ptr, linelen + 1); ptr = lineend + 1; indented = 0; } else { size_t finalspace = in.find_last_of(" \n", ptr + rem_width); if (finalspace == std::string::npos || finalspace < ptr) { // No place to break; just include the entire word and move on finalspace = in.find_first_of("\n ", ptr); if (finalspace == std::string::npos) { // End of the string, just add it and break out << in.substr(ptr); break; } } out << in.substr(ptr, finalspace - ptr) << "\n"; if (in[finalspace] == '\n') { indented = 0; } else if (indent) { out << std::string(indent, ' '); indented = indent; } ptr = finalspace + 1; } } return out.str(); } std::string i64tostr(int64_t n) { return strprintf("%d", n); } std::string itostr(int n) { return strprintf("%d", n); } int64_t atoi64(const char *psz) { #ifdef _MSC_VER return _atoi64(psz); #else return strtoll(psz, nullptr, 10); #endif } int64_t atoi64(const std::string &str) { #ifdef _MSC_VER return _atoi64(str.c_str()); #else return strtoll(str.c_str(), nullptr, 10); #endif } int atoi(const std::string &str) { return atoi(str.c_str()); } /** * Upper bound for mantissa. * 10^18-1 is the largest arbitrary decimal that will fit in a signed 64-bit * integer. Larger integers cannot consist of arbitrary combinations of 0-9: * * 999999999999999999 1^18-1 * 9223372036854775807 (1<<63)-1 (max int64_t) * 9999999999999999999 1^19-1 (would overflow) */ static const int64_t UPPER_BOUND = 1000000000000000000LL - 1LL; /** Helper function for ParseFixedPoint */ static inline bool ProcessMantissaDigit(char ch, int64_t &mantissa, int &mantissa_tzeros) { if (ch == '0') { ++mantissa_tzeros; } else { for (int i = 0; i <= mantissa_tzeros; ++i) { // overflow if (mantissa > (UPPER_BOUND / 10LL)) { return false; } mantissa *= 10; } mantissa += ch - '0'; mantissa_tzeros = 0; } return true; } bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out) { int64_t mantissa = 0; int64_t exponent = 0; int mantissa_tzeros = 0; bool mantissa_sign = false; bool exponent_sign = false; int ptr = 0; int end = val.size(); int point_ofs = 0; if (ptr < end && val[ptr] == '-') { mantissa_sign = true; ++ptr; } if (ptr < end) { if (val[ptr] == '0') { // pass single 0 ++ptr; } else if (val[ptr] >= '1' && val[ptr] <= '9') { while (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') { if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros)) { // overflow return false; } ++ptr; } } else { // missing expected digit return false; } } else { // empty string or loose '-' return false; } if (ptr < end && val[ptr] == '.') { ++ptr; if (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') { while (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') { if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros)) { // overflow return false; } ++ptr; ++point_ofs; } } else { // missing expected digit return false; } } if (ptr < end && (val[ptr] == 'e' || val[ptr] == 'E')) { ++ptr; if (ptr < end && val[ptr] == '+') { ++ptr; } else if (ptr < end && val[ptr] == '-') { exponent_sign = true; ++ptr; } if (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') { while (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') { if (exponent > (UPPER_BOUND / 10LL)) { // overflow return false; } exponent = exponent * 10 + val[ptr] - '0'; ++ptr; } } else { // missing expected digit return false; } } if (ptr != end) { // trailing garbage return false; } // finalize exponent if (exponent_sign) { exponent = -exponent; } exponent = exponent - point_ofs + mantissa_tzeros; // finalize mantissa if (mantissa_sign) { mantissa = -mantissa; } // convert to one 64-bit fixed-point value exponent += decimals; if (exponent < 0) { // cannot represent values smaller than 10^-decimals return false; } if (exponent >= 18) { // cannot represent values larger than or equal to 10^(18-decimals) return false; } for (int i = 0; i < exponent; ++i) { if (mantissa > (UPPER_BOUND / 10LL) || mantissa < -(UPPER_BOUND / 10LL)) { // overflow return false; } mantissa *= 10; } if (mantissa > UPPER_BOUND || mantissa < -UPPER_BOUND) { // overflow return false; } if (amount_out) { *amount_out = mantissa; } return true; } void Downcase(std::string &str) { std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c) { return ToLower(c); }); } std::string Capitalize(std::string str) { if (str.empty()) return str; str[0] = ToUpper(str.front()); return str; } diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 0171bdde2b..d1f8442d79 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -1,1476 +1,1476 @@ // Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include #include #include #include #include #include #include #include