Compare commits

...

23 Commits

Author SHA1 Message Date
Sjors Provoost ec5cc3a7c4
Merge 3a2f50a75b into b510893d00 2025-10-08 01:59:57 +02:00
Ava Chow b510893d00
Merge bitcoin/bitcoin#33494: depends: Update URL for `qrencode` package source tarball
93a70a42d3 depends: Update URL for `qrencode` package source tarball (Hennadii Stepanov)
6de8051263 depends: Use hash instead of file name for package download stamp (Hennadii Stepanov)
46135d90ea depends: Drop redundant check for downloaded file (Hennadii Stepanov)
771978952a depends: Fix `$(package)_fetched` target (Hennadii Stepanov)

Pull request description:

  The https://fukuchi.org/ homepage no longer links to the source tarball, and previously available files appear to have been removed. The homepage now instructs users to download source tarballs from the GitHub [releases](https://github.com/fukuchi/libqrencode/releases) page instead.

  The diff between the source trees is immaterial:
  ```diff
  --- old
  +++ new
  @@ -1,19 +1,16 @@
   27e7deccd2925c94e4190ee64794a051199f215f145f76fd664cdebedbbf8a35  acinclude.m4
  -e1e35b1309482f699a9700a2065a0bce09c2108dd1f78ba7bfbe0f7f0bdcd2e6  aclocal.m4
   a9308eec78790720dbcd5452ab8f241b5f1c6939ccf3389917b8e78cb2b58c9e  autogen.sh
   aa36725d577048f0370dc7415a1acb578fbdfb531c1b384a836d9360a81f6f5c  bitstream.c
   3feaacd7d096834fc5956215598564ec287ad443185c4433c3f8007cc53ceaa6  bitstream.h
   21bd5a34c90d3d6ee540ceb48c3d5aea5f21bd6b829ef3112db832af0bd423d8  ChangeLog
   f8a7a94c9622fab721df47e8121533ebfcb79885aca01ecec2fff00dfb84caef  cmake/FindIconv.cmake
   6345e7eecb92473f361a8eb98dd373aa09cae79a43408cf4b42b00b411c9c197  CMakeLists.txt
  -031d560570eab2eda57c2f9ee9952445002f8bf4a23965fcaf43bbc2c61590e2  config.h.in
  -d2f42cc5771b69f2d2ecd4b31509864ae2b18b25c823986390bb372ee07030fa  configure
   02867a8ea08206c84d5f4c05f41a15c639291091e3dfac27f3a9029d8f5d3028  configure.ac
   a9bdde5616ecdd1e980b44f360600ee8783b1f99b8cc83a2beb163a0a390e861  COPYING
   76c41754bccbf69a60fb7833776637c60b86f59104705c0a5cea9ee3a2968f3d  Doxyfile
   36d84f714cf28397b02d6c44860106a7cb858fc6d25239a2698a72fa5136e5c3  libqrencode.pc.in
   f0ce93a7e1b1f0fab87dd071ec3c8dd80a567d778dfc5930d9f375d676ecb9a0  Makefile.am
  -507c2385fb49c5724e8e3dfca97feb24cbdd4e651f3f0bfa62524e60088091a0  Makefile.in
  +dcb782b1b382328c0bce9194944bdcc65a6035d8e9f89e39436ed2e55ae8b969  makeREADME.sh
   6046d347c6c564fc13a24dc0a15a09a83023e00a4e0d0f23029a81f86ac4d024  mask.c
   9f853cee7d72191a8dbf018b7a86c0f0b6ca661e27a51fab677af911f2ff9e7e  mask.h
   a4e17b68d8db573e152132ebcbdc837b55415c12027f81232662db645faf79f0  mmask.c
  @@ -30,7 +27,7 @@
   6e9ff66002b4a839c6e78bcd6a55342d9eb8b289273fa838441b27ee9969e293  qrinput.h
   68831e02ee1ba602b1937328abec000e616c4472d9dc40067dd45ab7072df172  qrspec.c
   a2a9a5af4d62015e82b48b8316aea2b70031dcdc1ed2b829c0102ea5dc02aca2  qrspec.h
  -8730d006f1d45b90dc0ef9a20e4119420f15b37a09483c929baa4225e21f7900  README
  +a56773b55989ea5cae8a43f2d845ce0afa9576a26170937fbe36a69fee953cd4  README.md
   ace480f2e16001e276c73a5e965c282915ad81e2c28cce3ef574b5a8db7210e8  rsecc.c
   c731ebe26d58d5e5df3b2d694de0fb1c4ae80a36cf0559c49b04e989dee8b182  rsecc.h
   8ed1af4414b5628845519581c82bf51ba2b4dee1f8352c1fd01b50afcd0a0ed7  split.c
  @@ -46,7 +43,6 @@
   e26b20198a7393b3c060891876fa45edb81488aef9df6d6cf45893a605e5e5e4  tests/decoder.h
   adabfbddb0f25de2e2cae970195fcfdf11ad1fa66ce64e237d83f821346f64c4  tests/frame
   23c283a3d3b5f1bbb3108603ebf05d7a95951ba86a288e09140eab612a5eb258  tests/Makefile.am
  -c8b819bf7f00c979ab0b6f0d0fb10289d2006bc6acda1737d2f1c383a60e1e66  tests/Makefile.in
   ebd71b937d4d39f382f8c57f362a01f11fd617b66dbdf6f1a3c4897c8c42e235  tests/prof_qrencode.c
   d4adcb234d4c31473cd9ffedd1bfa9645ba336d426640ba5893dfe6e75db171d  tests/pthread_qrencode.c
   62298641504b0a2c1d199cd7f656cb376959200169042de76f7c5950d2d42395  tests/rscode.c
  @@ -63,6 +59,7 @@
   cf5792cbfb92ba46f7f5f14b98f00813b0e7e4f5e7c790c6a28793774474bf26  tests/test_monkey.c
   3a2c58346d57f6bb2a634d6febf3c65ac524259a2d789657f8d60c678bf8d658  tests/test_mqrspec.c
   b9d8c569ba36a2258cb1ad0d1f85ce4fb2935fad519e902bade59aa9772321aa  tests/test_qrencode.c
  +785fe14a6f8bc096b20ec271771fb09f22f29eb4f9d729f5b40d6b4cc824ce36  tests/test_qrenc.sh
   d0eee6eddf98ee4595c07f7da40c7de548651bf839b26995756e94db2599451f  tests/test_qrinput.c
   ace7885e435ef77cc127da0ac23c724498aaa8d80d53b908063f79c9f0b7acce  tests/test_qrspec.c
   fde9c2735ce94be51e1b0bbffe65415aa3afd2da5bd4c0e2c5e50e1a2f1ea3f7  tests/test_rs.c
  @@ -71,12 +68,4 @@
   6f35c0e1235b31d0068c4ab175d8110c736e60df0309d4be7b3e57dd62d316f6  tests/URI_testset.inc
   6be3983fc397cd5dade1dd219ad6cbe7977f416410b1509984006ecec51605b5  tests/view_qrcode.c
   92b5be1ca2239399232d51503715c848dae9bf3db71b1f03157bfa9779826910  TODO
  -c8af04e62bad4ab75dafd22119026e5e3943f385bdcbe7731a4938102453754c  use/compile
  -1d9048b0ac9d4d1dfce7aa4e3a0b59ccfd32db2f7693814aa6f4c778560f5669  use/config.guess
   b522487f9c47661d321367d133f3d41247dd16d435f2d4b9c643dee95bf65eee  use/config.rpath
  -5bf0da2576ebb21ab60a9d9291a85b40af0e956a9eafb709ca8b20dcb105f4ee  use/config.sub
  -732bcd6b9e23f241e015d71b0a3a862104053aba20718c1f56b292cee7e29371  use/depcomp
  -608b76d735bb2ec2bcb1271644c3d5e7a428fb8d2338e114e8a48ebf91ccfd23  use/install-sh
  -2304d53af1f63b76a11651efdd18578adf2bda1ffc2c257100cba374b55f284b  use/ltmain.sh
  -f038345dab184e538098d22a8edc423762da66a90ebe269f23bfef85287cd30c  use/missing
  -7c1ae35455771ae32050c2ed109e3d297160b6d1a2f70b0278cf6968e5e7e98c  use/test-driver
  ```

  ---

  **UPDATE 2025-09-30**

  A few commits have been added:

  1. The first commit fixes the `$(package)_fetched` target, which erroneously succeeds on the second run after a failure on the master branch:
  ```
  $ gmake -C depends clean-all
  $ gmake -C depends qrencode_fetched FALLBACK_DOWNLOAD_PATH="https://fallback.invalid"
  $ gmake -C depends qrencode_fetched FALLBACK_DOWNLOAD_PATH="https://fallback.invalid"
  $ echo $?
  0
  ```
  With the first commit applied:
  ```
  $ gmake -C depends clean-all
  $ gmake -C depends qrencode_fetched FALLBACK_DOWNLOAD_PATH="https://fallback.invalid"
  $ gmake -C depends qrencode_fetched FALLBACK_DOWNLOAD_PATH="https://fallback.invalid"
  $ echo $?
  2
  ```

  2. The second and third commits allow the depends build subsystem to detect when the source tarball content has been modified and needs to be re-downloaded, even if the file name remains the same.

ACKs for top commit:
  m3dwards:
    ACK 93a70a42d3
  achow101:
    ACK 93a70a42d3
  vasild:
    ACK 93a70a42d3
  janb84:
    ACK 93a70a42d3

Tree-SHA512: 38b7c029070426196c747fc45c9d00bae534eeeb2d9cd9f221580fce8380f4f8aecb6c48b2563e322edd8c9534f5dd42d8f4e110ada42bb83568cf2dcfb7dc22
2025-10-07 16:57:58 -07:00
Hennadii Stepanov ec5841888d
Merge bitcoin/bitcoin#32513: ci: remove 3rd party js from windows dll gha job
156927903d ci: Check windows manifests for all executables (Max Edwards)
e1a1b14c93 ci: use a more generic way of finding mt.exe (Max Edwards)
7ae0497eef ci: remove 3rd party js from windows dll gha job (Max Edwards)

Pull request description:

  The windows job uses the external dependency `ilammy/msvc-dev-cmd` which runs javascript. We use this to put various tools on the path such as `MSBuild.exe` and `mt.exe`. We can remove this dependency and use `vswhere.exe` directly to find these tools and create a "[Developer command prompt](https://github.com/microsoft/vswhere/wiki/Start-Developer-Command-Prompt#using-powershell)" as someone would on their dev machine.

  While in this area of the code, this PR also runs some additional manifest checks on the windows binaries.

  Fixes: #32508

ACKs for top commit:
  davidgumberg:
    crACK 156927903d
  hebasto:
    ACK 156927903d.

Tree-SHA512: df640dff27579a1c95daddc5a5ba8fd655bbd0a6f2aff74d0f63439c7185c0b18a90abfee3f1f032fe833cd19b822ef71812f44b24c4c044222e46d01c271864
2025-10-08 00:44:05 +01:00
Ava Chow d735e2e9b3
Merge bitcoin/bitcoin#32998: Bump SCRIPT_VERIFY flags to 64 bit
652424ad16 test: additional test coverage for script_verify_flags (Anthony Towns)
417437eb01 script/verify_flags: extend script_verify_flags to 64 bits (Anthony Towns)
3cbbcb66ef script/interpreter: make script_verify_flag_name an ordinary enum (Anthony Towns)
bddcadee82 script/verify_flags: make script_verify_flags type safe (Anthony Towns)
a5ead122fe script/interpreter: introduce script_verify_flags typename (Anthony Towns)
4577fb2b1e rpc: have getdeploymentinfo report script verify flags (Anthony Towns)
a3986935f0 validation: export GetBlockScriptFlags() (Anthony Towns)
5db8cd2d37 Move mapFlagNames and FormatScriptFlags logic to script/interpreter.h (Anthony Towns)

Pull request description:

  We currently use 21 of 32 possible bits for `SCRIPT_VERIFY_*` flags, with open PRs that may use 8 more (#29247, #31989, #32247, #32453). The mutinynet fork that has included many experimental soft fork features is [already reusing bits here](d4a86277ed/src/script/interpreter.h (L175-L195)). Therefore, bump this to 64 bits.

  In order to make it easier to update this logic in future, this PR also introduces a dedicated type for the script flags, and disables implicit conversion between that type and the underlying integer type. To make verifying that this change doesn't cause flags to disappear, this PR also resurrects the changes from #28806 so that the script flags that are consensus enforced on each block can be queried via getdeploymentinfo.

ACKs for top commit:
  instagibbs:
    reACK 652424ad16
  achow101:
    ACK 652424ad16
  darosior:
    ACK 652424ad16
  theStack:
    Code-review ACK 652424ad16 🎏

Tree-SHA512: 7b30152196cdfdef8b9700b571b7d7d4e94d28fbc5c26ea7532788037efc02e4b1d8de392b0b20507badfdc26f5c125f8356a479604a9149b8aae23a7cf5549f
2025-10-07 14:51:22 -07:00
Ava Chow de1dc6b47b
Merge bitcoin/bitcoin#33515: Improve LastCommonAncestor performance + add tests
3635d62f5a chain: make use of pskip in LastCommonAncestor (optimization) (Pieter Wuille)
2e09d66fbb tests: add unit tests for CBlockIndex::GetAncestor and LastCommonAncestor (Pieter Wuille)

Pull request description:

  In theory, the `LastCommonAncestor` function in chain.cpp can take $\mathcal{O}(n)$ time, walking over the entire chain, if the forking point is very early, which could take ~milliseconds. I expect this to be very rare in normal occurrences, but it seems nontrivial to reason about worst cases as it's accessible from several places in net_processing.

  This PR modifies the algorithm to make use of the `CBlockIndex::pskip` skip pointers to find the forking point in sublinear time (a simulation shows that for heights up to $34 \cdot 4^k - 2$ and $k \geq 8$, no more than $k^2 + 10k + 13$ steps are ever needed), in a way that should be nearly free - at worst the same number of memory accesses should be made, with a tiny increase in computation.

  As it appears we didn't really have tests for this function, unit tests are added for that function as well as `CBlockIndex::GetAncestor()`.

  This is inspired by https://github.com/bitcoin/bitcoin/pull/32180#discussion_r2394877881

ACKs for top commit:
  optout21:
    ACK 3635d62f5a
  achow101:
    ACK 3635d62f5a
  vasild:
    ACK 3635d62f5a
  mzumsande:
    Code Review ACK 3635d62f5a
  furszy:
    ACK 3635d62f5a
  stratospher:
    ACK 3635d62f5a.

Tree-SHA512: f9b7dea1e34c1cc1ec1da3fb9e90c4acbf4aaf0f04768844f538201efa6b11eeeefc97b720509e78c21878977192e2c4031fd8974151667e2e756247002b8164
2025-10-07 13:54:25 -07:00
Sjors Provoost 3a2f50a75b
doc: how to update a subtree 2025-10-07 20:13:52 +02:00
Pieter Wuille 3635d62f5a chain: make use of pskip in LastCommonAncestor (optimization)
By using the pskip pointer, which regularly allows jumping back much faster
than pprev, the forking point between two CBlockIndex entries can be found
much faster.

A simulation shows that no more than 136 steps are needed to jump anywhere
within the first 2^20 block heights, and on average 65 jumps for uniform
forking points around that height.
2025-10-02 10:34:12 -04:00
Pieter Wuille 2e09d66fbb tests: add unit tests for CBlockIndex::GetAncestor and LastCommonAncestor 2025-10-02 10:34:09 -04:00
Max Edwards 156927903d ci: Check windows manifests for all executables
The other executables have manifests and these should be checked in
addition to bitcoind. Skipping fuzz.exe, bench_bitcoin.exe and
test_bitcoin-qt.exe as they do not have manifests.
2025-10-02 15:13:29 +01:00
Max Edwards e1a1b14c93 ci: use a more generic way of finding mt.exe
This sets up a vs developer command prompt and should hopefully should
be more resilient to upstream changes

Co-authored-by: David Gumberg <davidzgumberg@gmail.com>
2025-10-02 15:13:26 +01:00
Hennadii Stepanov 93a70a42d3
depends: Update URL for `qrencode` package source tarball
The https://fukuchi.org/ homepage no longer links to the source tarball,
and previously available files appear to have been removed. The homepage
now instructs users to download source tarballs from the GitHub releases
page instead.

The diff between the source trees is immaterial.
2025-09-30 11:26:47 +01:00
Hennadii Stepanov 6de8051263
depends: Use hash instead of file name for package download stamp
The package version is still included for convenience.
2025-09-30 11:26:29 +01:00
Hennadii Stepanov 46135d90ea
depends: Drop redundant check for downloaded file
The `fetch_file` commands are invoked for the `$($(package)_fetched)`
target, so the existence of the download stamp has already been tested.
2025-09-30 11:22:50 +01:00
Hennadii Stepanov 771978952a
depends: Fix `$(package)_fetched` target
Ensure the download timestamp is created only after a successful
download.
2025-09-30 11:20:12 +01:00
Max Edwards 7ae0497eef ci: remove 3rd party js from windows dll gha job
We can use vswhere.exe directly to create a vs developer
prompt and so can remove this third party dependency.

Co-authored-by: David Gumberg <davidzgumberg@gmail.com>
2025-09-25 18:12:02 +01:00
Anthony Towns 652424ad16 test: additional test coverage for script_verify_flags 2025-09-11 11:24:09 +10:00
Anthony Towns 417437eb01 script/verify_flags: extend script_verify_flags to 64 bits 2025-08-14 10:17:32 +10:00
Anthony Towns 3cbbcb66ef script/interpreter: make script_verify_flag_name an ordinary enum
Instead of having `SCRIPT_VERIFY_FOO = (1U << n)` just have it
be `n` directly, and do the bit shifting when converting it to
`script_verify_flags`.
2025-08-14 10:17:32 +10:00
Anthony Towns bddcadee82 script/verify_flags: make script_verify_flags type safe
`using script_verify_flags = uint32_t` allows implicit conversion to
and from int, so replace it with a class to have the compiler ensure we
use the correct type. Provide from_int and as_int to allow for explicit
conversions when desired.

Introduces the type `script_verify_flag_name` for the individual flag
name enumeration.
2025-08-14 10:17:32 +10:00
Anthony Towns a5ead122fe script/interpreter: introduce script_verify_flags typename
Previously the SCRIPT_VERIFY_* flags were specified as either uint32_t,
unsigned int, or unsigned. This converts them to a common type alias in
preparation for changing the underlying type.
2025-08-14 10:17:32 +10:00
Anthony Towns 4577fb2b1e rpc: have getdeploymentinfo report script verify flags 2025-08-14 10:17:32 +10:00
Anthony Towns a3986935f0 validation: export GetBlockScriptFlags() 2025-08-14 10:17:32 +10:00
Anthony Towns 5db8cd2d37 Move mapFlagNames and FormatScriptFlags logic to script/interpreter.h
Moves FormatScriptFlags logic into GetScriptFlagNames which returns a
vector of strings. For completeness, also has GetScriptFlagNames report
on any bits that do not match a known script flag.
2025-08-14 10:17:30 +10:00
35 changed files with 471 additions and 200 deletions

View File

@ -211,11 +211,16 @@ jobs:
steps: steps:
- *CHECKOUT - *CHECKOUT
- name: Configure Developer Command Prompt for Microsoft Visual C++ - &SET_UP_VS
# Using microsoft/setup-msbuild is not enough. name: Set up VS Developer Prompt
uses: ilammy/msvc-dev-cmd@v1 shell: pwsh -Command "$PSVersionTable; $PSNativeCommandUseErrorActionPreference = $true; $ErrorActionPreference = 'Stop'; & '{0}'"
with: run: |
arch: x64 $vswherePath = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
$installationPath = & $vswherePath -latest -property installationPath
& "${env:COMSPEC}" /s /c "`"$installationPath\Common7\Tools\vsdevcmd.bat`" -arch=x64 -no_logo && set" | foreach-object {
$name, $value = $_ -split '=', 2
echo "$name=$value" >> $env:GITHUB_ENV
}
- name: Get tool information - name: Get tool information
shell: pwsh shell: pwsh
@ -263,14 +268,26 @@ jobs:
run: | run: |
cmake --build . -j $NUMBER_OF_PROCESSORS --config Release cmake --build . -j $NUMBER_OF_PROCESSORS --config Release
- name: Get bitcoind manifest - name: Check executable manifests
if: matrix.job-type == 'standard' if: matrix.job-type == 'standard'
working-directory: build working-directory: build
shell: pwsh -Command "$PSVersionTable; $PSNativeCommandUseErrorActionPreference = $true; $ErrorActionPreference = 'Stop'; & '{0}'"
run: | run: |
mt.exe -nologo -inputresource:bin/Release/bitcoind.exe -out:bitcoind.manifest mt.exe -nologo -inputresource:bin\Release\bitcoind.exe -out:bitcoind.manifest
cat bitcoind.manifest Get-Content bitcoind.manifest
echo
mt.exe -nologo -inputresource:bin/Release/bitcoind.exe -validate_manifest Get-ChildItem -Filter "bin\Release\*.exe" | ForEach-Object {
$exeName = $_.Name
# Skip as they currently do not have manifests
if ($exeName -eq "fuzz.exe" -or $exeName -eq "bench_bitcoin.exe" -or $exeName -eq "test_bitcoin-qt.exe") {
Write-Host "Skipping $exeName (no manifest present)"
return
}
Write-Host "Checking $exeName"
& mt.exe -nologo -inputresource:$_.FullName -validate_manifest
}
- name: Run test suite - name: Run test suite
if: matrix.job-type == 'standard' if: matrix.job-type == 'standard'
@ -370,19 +387,26 @@ jobs:
- name: Run bitcoind.exe - name: Run bitcoind.exe
run: ./bin/bitcoind.exe -version run: ./bin/bitcoind.exe -version
- name: Find mt.exe tool - *SET_UP_VS
shell: pwsh
run: |
$sdk_dir = (Get-ItemProperty 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows Kits\Installed Roots' -Name KitsRoot10).KitsRoot10
$sdk_latest = (Get-ChildItem "$sdk_dir\bin" -Directory | Where-Object { $_.Name -match '^\d+\.\d+\.\d+\.\d+$' } | Sort-Object Name -Descending | Select-Object -First 1).Name
"MT_EXE=${sdk_dir}bin\${sdk_latest}\x64\mt.exe" >> $env:GITHUB_ENV
- name: Get bitcoind manifest - name: Check executable manifests
shell: pwsh shell: pwsh -Command "$PSVersionTable; $PSNativeCommandUseErrorActionPreference = $true; $ErrorActionPreference = 'Stop'; & '{0}'"
run: | run: |
& $env:MT_EXE -nologo -inputresource:bin\bitcoind.exe -out:bitcoind.manifest mt.exe -nologo -inputresource:bin\bitcoind.exe -out:bitcoind.manifest
Get-Content bitcoind.manifest Get-Content bitcoind.manifest
& $env:MT_EXE -nologo -inputresource:bin\bitcoind.exe -validate_manifest
Get-ChildItem -Filter "bin\*.exe" | ForEach-Object {
$exeName = $_.Name
# Skip as they currently do not have manifests
if ($exeName -eq "fuzz.exe" -or $exeName -eq "bench_bitcoin.exe") {
Write-Host "Skipping $exeName (no manifest present)"
return
}
Write-Host "Checking $exeName"
& mt.exe -nologo -inputresource:$_.FullName -validate_manifest
}
- name: Run unit tests - name: Run unit tests
# Can't use ctest here like other jobs as we don't have a CMake build tree. # Can't use ctest here like other jobs as we don't have a CMake build tree.

View File

@ -36,9 +36,8 @@ define fetch_file_inner
endef endef
define fetch_file define fetch_file
( test -f $$($(1)_source_dir)/$(4) || \
( $(call fetch_file_inner,$(1),$(2),$(3),$(4),$(5)) || \ ( $(call fetch_file_inner,$(1),$(2),$(3),$(4),$(5)) || \
$(call fetch_file_inner,$(1),$(FALLBACK_DOWNLOAD_PATH),$(3),$(4),$(5)))) $(call fetch_file_inner,$(1),$(FALLBACK_DOWNLOAD_PATH),$(3),$(4),$(5)))
endef endef
# Shell script to create a source tarball in $(1)_source from local directory # Shell script to create a source tarball in $(1)_source from local directory
@ -109,7 +108,7 @@ $(1)_prefixbin:=$($($(1)_type)_prefix)/bin/
$(1)_all_sources=$($(1)_file_name) $($(1)_extra_sources) $(1)_all_sources=$($(1)_file_name) $($(1)_extra_sources)
#stamps #stamps
$(1)_fetched=$(SOURCES_PATH)/download-stamps/.stamp_fetched-$(1)-$($(1)_file_name).hash $(1)_fetched=$(SOURCES_PATH)/download-stamps/.stamp_fetched-$(1)-$($(1)_version)-$($(1)_sha256_hash).hash
$(1)_extracted=$$($(1)_extract_dir)/.stamp_extracted $(1)_extracted=$$($(1)_extract_dir)/.stamp_extracted
$(1)_preprocessed=$$($(1)_extract_dir)/.stamp_preprocessed $(1)_preprocessed=$$($(1)_extract_dir)/.stamp_preprocessed
$(1)_cleaned=$$($(1)_extract_dir)/.stamp_cleaned $(1)_cleaned=$$($(1)_extract_dir)/.stamp_cleaned
@ -247,7 +246,6 @@ endif
$($(1)_fetched): $($(1)_fetched):
mkdir -p $$(@D) $(SOURCES_PATH) mkdir -p $$(@D) $(SOURCES_PATH)
rm -f $$@ rm -f $$@
touch $$@
cd $$(@D); $($(1)_fetch_cmds) cd $$(@D); $($(1)_fetch_cmds)
cd $($(1)_source_dir); $(foreach source,$($(1)_all_sources),$(build_SHA256SUM) $(source) >> $$(@);) cd $($(1)_source_dir); $(foreach source,$($(1)_all_sources),$(build_SHA256SUM) $(source) >> $$(@);)
touch $$@ touch $$@

View File

@ -1,8 +1,9 @@
package=qrencode package=qrencode
$(package)_version=4.1.1 $(package)_version=4.1.1
$(package)_download_path=https://fukuchi.org/works/qrencode/ $(package)_download_path=https://github.com/fukuchi/libqrencode/archive/refs/tags/
$(package)_download_file=v$($(package)_version).tar.gz
$(package)_file_name=$(package)-$($(package)_version).tar.gz $(package)_file_name=$(package)-$($(package)_version).tar.gz
$(package)_sha256_hash=da448ed4f52aba6bcb0cd48cac0dd51b8692bccc4cd127431402fca6f8171e8e $(package)_sha256_hash=5385bc1b8c2f20f3b91d258bf8ccc8cf62023935df2d2676b5b67049f31a049c
$(package)_patches=cmake_fixups.patch $(package)_patches=cmake_fixups.patch
define $(package)_set_vars define $(package)_set_vars

View File

@ -1119,6 +1119,19 @@ to check a subtree directory for consistency with its upstream repository.
The tool instructions also include a list of the subtrees managed by Bitcoin Core. The tool instructions also include a list of the subtrees managed by Bitcoin Core.
To fully verify or update a subtree, add it as a remote:
```sh
git remote add --fetch libmultiprocess https://github.com/bitcoin-core/libmultiprocess.git
```
To update the subtree:
```sh
git fetch libmultiprocess
git subtree pull --prefix=src/ipc/libmultiprocess libmultiprocess master --squash
```
The ultimate upstream of the few externally managed subtrees are: The ultimate upstream of the few externally managed subtrees are:
- src/leveldb - src/leveldb

View File

@ -24,7 +24,7 @@ static void VerifyScriptBench(benchmark::Bench& bench)
{ {
ECC_Context ecc_context{}; ECC_Context ecc_context{};
const uint32_t flags{SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH}; const script_verify_flags flags{SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH};
const int witnessversion = 0; const int witnessversion = 0;
// Key pair. // Key pair.

View File

@ -5,6 +5,7 @@
#include <chain.h> #include <chain.h>
#include <tinyformat.h> #include <tinyformat.h>
#include <util/check.h>
#include <util/time.h> #include <util/time.h>
std::string CBlockFileInfo::ToString() const std::string CBlockFileInfo::ToString() const
@ -158,18 +159,26 @@ int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& fr
/** Find the last common ancestor two blocks have. /** Find the last common ancestor two blocks have.
* Both pa and pb must be non-nullptr. */ * Both pa and pb must be non-nullptr. */
const CBlockIndex* LastCommonAncestor(const CBlockIndex* pa, const CBlockIndex* pb) { const CBlockIndex* LastCommonAncestor(const CBlockIndex* pa, const CBlockIndex* pb) {
// First rewind to the last common height (the forking point cannot be past one of the two).
if (pa->nHeight > pb->nHeight) { if (pa->nHeight > pb->nHeight) {
pa = pa->GetAncestor(pb->nHeight); pa = pa->GetAncestor(pb->nHeight);
} else if (pb->nHeight > pa->nHeight) { } else if (pb->nHeight > pa->nHeight) {
pb = pb->GetAncestor(pa->nHeight); pb = pb->GetAncestor(pa->nHeight);
} }
while (pa != pb) {
while (pa != pb && pa && pb) { // Jump back until pa and pb have a common "skip" ancestor.
while (pa->pskip != pb->pskip) {
// This logic relies on the property that equal-height blocks have equal-height skip
// pointers.
Assume(pa->nHeight == pb->nHeight);
Assume(pa->pskip->nHeight == pb->pskip->nHeight);
pa = pa->pskip;
pb = pb->pskip;
}
// At this point, pa and pb are different, but have equal pskip. The forking point lies in
// between pa/pb on the one end, and pa->pskip/pb->pskip on the other end.
pa = pa->pprev; pa = pa->pprev;
pb = pb->pprev; pb = pb->pprev;
} }
// Eventually all chain branches meet at the genesis block.
assert(pa == pb);
return pa; return pa;
} }

View File

@ -6,6 +6,7 @@
#ifndef BITCOIN_CONSENSUS_PARAMS_H #ifndef BITCOIN_CONSENSUS_PARAMS_H
#define BITCOIN_CONSENSUS_PARAMS_H #define BITCOIN_CONSENSUS_PARAMS_H
#include <script/verify_flags.h>
#include <uint256.h> #include <uint256.h>
#include <array> #include <array>
@ -89,7 +90,7 @@ struct Params {
* - buried in the chain, and * - buried in the chain, and
* - fail if the default script verify flags are applied. * - fail if the default script verify flags are applied.
*/ */
std::map<uint256, uint32_t> script_flag_exceptions; std::map<uint256, script_verify_flags> script_flag_exceptions;
/** Block height and hash at which BIP34 becomes active */ /** Block height and hash at which BIP34 becomes active */
int BIP34Height; int BIP34Height;
uint256 BIP34Hash; uint256 BIP34Hash;

View File

@ -140,7 +140,7 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in
return nSigOps; return nSigOps;
} }
int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, uint32_t flags) int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, script_verify_flags flags)
{ {
int64_t nSigOps = GetLegacySigOpCount(tx) * WITNESS_SCALE_FACTOR; int64_t nSigOps = GetLegacySigOpCount(tx) * WITNESS_SCALE_FACTOR;

View File

@ -6,6 +6,7 @@
#define BITCOIN_CONSENSUS_TX_VERIFY_H #define BITCOIN_CONSENSUS_TX_VERIFY_H
#include <consensus/amount.h> #include <consensus/amount.h>
#include <script/verify_flags.h>
#include <cstdint> #include <cstdint>
#include <vector> #include <vector>
@ -52,7 +53,7 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& ma
* @param[in] flags Script verification flags * @param[in] flags Script verification flags
* @return Total signature operation cost of tx * @return Total signature operation cost of tx
*/ */
int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, uint32_t flags); int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, script_verify_flags flags);
/** /**
* Check if transaction is final and can be included in a block with the * Check if transaction is final and can be included in a block with the

View File

@ -8,8 +8,10 @@
#include <consensus/params.h> #include <consensus/params.h>
#include <array> #include <array>
#include <cassert>
#include <optional> #include <optional>
#include <string> #include <string>
#include <string_view>
struct VBDeploymentInfo { struct VBDeploymentInfo {
/** Deployment name */ /** Deployment name */

View File

@ -98,7 +98,7 @@ static constexpr unsigned int MAX_DUST_OUTPUTS_PER_TX{1};
* Note that this does not affect consensus validity; see GetBlockScriptFlags() * Note that this does not affect consensus validity; see GetBlockScriptFlags()
* for that. * for that.
*/ */
static constexpr unsigned int MANDATORY_SCRIPT_VERIFY_FLAGS{SCRIPT_VERIFY_P2SH | static constexpr script_verify_flags MANDATORY_SCRIPT_VERIFY_FLAGS{SCRIPT_VERIFY_P2SH |
SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_DERSIG |
SCRIPT_VERIFY_NULLDUMMY | SCRIPT_VERIFY_NULLDUMMY |
SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY | SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY |
@ -112,7 +112,7 @@ static constexpr unsigned int MANDATORY_SCRIPT_VERIFY_FLAGS{SCRIPT_VERIFY_P2SH |
* the additional (non-mandatory) rules here, to improve forwards and * the additional (non-mandatory) rules here, to improve forwards and
* backwards compatibility. * backwards compatibility.
*/ */
static constexpr unsigned int STANDARD_SCRIPT_VERIFY_FLAGS{MANDATORY_SCRIPT_VERIFY_FLAGS | static constexpr script_verify_flags STANDARD_SCRIPT_VERIFY_FLAGS{MANDATORY_SCRIPT_VERIFY_FLAGS |
SCRIPT_VERIFY_STRICTENC | SCRIPT_VERIFY_STRICTENC |
SCRIPT_VERIFY_MINIMALDATA | SCRIPT_VERIFY_MINIMALDATA |
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS | SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS |
@ -128,7 +128,7 @@ static constexpr unsigned int STANDARD_SCRIPT_VERIFY_FLAGS{MANDATORY_SCRIPT_VERI
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE}; SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE};
/** For convenience, standard but not mandatory verify flags. */ /** For convenience, standard but not mandatory verify flags. */
static constexpr unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS{STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS}; static constexpr script_verify_flags STANDARD_NOT_MANDATORY_VERIFY_FLAGS{STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS};
/** Used as the flags parameter to sequence and nLocktime checks in non-consensus code. */ /** Used as the flags parameter to sequence and nLocktime checks in non-consensus code. */
static constexpr unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS{LOCKTIME_VERIFY_SEQUENCE}; static constexpr unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS{LOCKTIME_VERIFY_SEQUENCE};

View File

@ -1469,6 +1469,9 @@ RPCHelpMan getdeploymentinfo()
RPCResult::Type::OBJ, "", "", { RPCResult::Type::OBJ, "", "", {
{RPCResult::Type::STR, "hash", "requested block hash (or tip)"}, {RPCResult::Type::STR, "hash", "requested block hash (or tip)"},
{RPCResult::Type::NUM, "height", "requested block height (or tip)"}, {RPCResult::Type::NUM, "height", "requested block height (or tip)"},
{RPCResult::Type::ARR, "script_flags", "script verify flags for the block", {
{RPCResult::Type::STR, "flag", "a script verify flag"},
}},
{RPCResult::Type::OBJ_DYN, "deployments", "", { {RPCResult::Type::OBJ_DYN, "deployments", "", {
{RPCResult::Type::OBJ, "xxxx", "name of the deployment", RPCHelpForDeployment} {RPCResult::Type::OBJ, "xxxx", "name of the deployment", RPCHelpForDeployment}
}}, }},
@ -1495,6 +1498,12 @@ RPCHelpMan getdeploymentinfo()
UniValue deploymentinfo(UniValue::VOBJ); UniValue deploymentinfo(UniValue::VOBJ);
deploymentinfo.pushKV("hash", blockindex->GetBlockHash().ToString()); deploymentinfo.pushKV("hash", blockindex->GetBlockHash().ToString());
deploymentinfo.pushKV("height", blockindex->nHeight); deploymentinfo.pushKV("height", blockindex->nHeight);
{
const auto flagnames = GetScriptFlagNames(GetBlockScriptFlags(*blockindex, chainman));
UniValue uv_flagnames(UniValue::VARR);
uv_flagnames.push_backV(flagnames.begin(), flagnames.end());
deploymentinfo.pushKV("script_flags", uv_flagnames);
}
deploymentinfo.pushKV("deployments", DeploymentInfo(blockindex, chainman)); deploymentinfo.pushKV("deployments", DeploymentInfo(blockindex, chainman));
return deploymentinfo; return deploymentinfo;
}, },

View File

@ -10,6 +10,7 @@
#include <crypto/sha256.h> #include <crypto/sha256.h>
#include <pubkey.h> #include <pubkey.h>
#include <script/script.h> #include <script/script.h>
#include <tinyformat.h>
#include <uint256.h> #include <uint256.h>
typedef std::vector<unsigned char> valtype; typedef std::vector<unsigned char> valtype;
@ -197,7 +198,7 @@ bool static IsDefinedHashtypeSignature(const valtype &vchSig) {
return true; return true;
} }
bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned int flags, ScriptError* serror) { bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, script_verify_flags flags, ScriptError* serror) {
// Empty signature. Not strictly DER encoded, but allowed to provide a // Empty signature. Not strictly DER encoded, but allowed to provide a
// compact way to provide an invalid signature for use with CHECK(MULTI)SIG // compact way to provide an invalid signature for use with CHECK(MULTI)SIG
if (vchSig.size() == 0) { if (vchSig.size() == 0) {
@ -214,7 +215,7 @@ bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned i
return true; return true;
} }
bool static CheckPubKeyEncoding(const valtype &vchPubKey, unsigned int flags, const SigVersion &sigversion, ScriptError* serror) { bool static CheckPubKeyEncoding(const valtype &vchPubKey, script_verify_flags flags, const SigVersion &sigversion, ScriptError* serror) {
if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && !IsCompressedOrUncompressedPubKey(vchPubKey)) { if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && !IsCompressedOrUncompressedPubKey(vchPubKey)) {
return set_error(serror, SCRIPT_ERR_PUBKEYTYPE); return set_error(serror, SCRIPT_ERR_PUBKEYTYPE);
} }
@ -317,7 +318,7 @@ public:
}; };
} }
static bool EvalChecksigPreTapscript(const valtype& vchSig, const valtype& vchPubKey, CScript::const_iterator pbegincodehash, CScript::const_iterator pend, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror, bool& fSuccess) static bool EvalChecksigPreTapscript(const valtype& vchSig, const valtype& vchPubKey, CScript::const_iterator pbegincodehash, CScript::const_iterator pend, script_verify_flags flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror, bool& fSuccess)
{ {
assert(sigversion == SigVersion::BASE || sigversion == SigVersion::WITNESS_V0); assert(sigversion == SigVersion::BASE || sigversion == SigVersion::WITNESS_V0);
@ -343,7 +344,7 @@ static bool EvalChecksigPreTapscript(const valtype& vchSig, const valtype& vchPu
return true; return true;
} }
static bool EvalChecksigTapscript(const valtype& sig, const valtype& pubkey, ScriptExecutionData& execdata, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror, bool& success) static bool EvalChecksigTapscript(const valtype& sig, const valtype& pubkey, ScriptExecutionData& execdata, script_verify_flags flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror, bool& success)
{ {
assert(sigversion == SigVersion::TAPSCRIPT); assert(sigversion == SigVersion::TAPSCRIPT);
@ -388,7 +389,7 @@ static bool EvalChecksigTapscript(const valtype& sig, const valtype& pubkey, Scr
* A return value of false means the script fails entirely. When true is returned, the * A return value of false means the script fails entirely. When true is returned, the
* success variable indicates whether the signature check itself succeeded. * success variable indicates whether the signature check itself succeeded.
*/ */
static bool EvalChecksig(const valtype& sig, const valtype& pubkey, CScript::const_iterator pbegincodehash, CScript::const_iterator pend, ScriptExecutionData& execdata, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror, bool& success) static bool EvalChecksig(const valtype& sig, const valtype& pubkey, CScript::const_iterator pbegincodehash, CScript::const_iterator pend, ScriptExecutionData& execdata, script_verify_flags flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror, bool& success)
{ {
switch (sigversion) { switch (sigversion) {
case SigVersion::BASE: case SigVersion::BASE:
@ -403,7 +404,7 @@ static bool EvalChecksig(const valtype& sig, const valtype& pubkey, CScript::con
assert(false); assert(false);
} }
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* serror) bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, script_verify_flags flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* serror)
{ {
static const CScriptNum bnZero(0); static const CScriptNum bnZero(0);
static const CScriptNum bnOne(1); static const CScriptNum bnOne(1);
@ -1233,7 +1234,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
return set_success(serror); return set_success(serror);
} }
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror) bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, script_verify_flags flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror)
{ {
ScriptExecutionData execdata; ScriptExecutionData execdata;
return EvalScript(stack, script, flags, checker, sigversion, execdata, serror); return EvalScript(stack, script, flags, checker, sigversion, execdata, serror);
@ -1824,7 +1825,7 @@ bool GenericTransactionSignatureChecker<T>::CheckSequence(const CScriptNum& nSeq
template class GenericTransactionSignatureChecker<CTransaction>; template class GenericTransactionSignatureChecker<CTransaction>;
template class GenericTransactionSignatureChecker<CMutableTransaction>; template class GenericTransactionSignatureChecker<CMutableTransaction>;
static bool ExecuteWitnessScript(const std::span<const valtype>& stack_span, const CScript& exec_script, unsigned int flags, SigVersion sigversion, const BaseSignatureChecker& checker, ScriptExecutionData& execdata, ScriptError* serror) static bool ExecuteWitnessScript(const std::span<const valtype>& stack_span, const CScript& exec_script, script_verify_flags flags, SigVersion sigversion, const BaseSignatureChecker& checker, ScriptExecutionData& execdata, ScriptError* serror)
{ {
std::vector<valtype> stack{stack_span.begin(), stack_span.end()}; std::vector<valtype> stack{stack_span.begin(), stack_span.end()};
@ -1909,7 +1910,7 @@ static bool VerifyTaprootCommitment(const std::vector<unsigned char>& control, c
return q.CheckTapTweak(p, merkle_root, control[0] & 1); return q.CheckTapTweak(p, merkle_root, control[0] & 1);
} }
static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion, const std::vector<unsigned char>& program, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror, bool is_p2sh) static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion, const std::vector<unsigned char>& program, script_verify_flags flags, const BaseSignatureChecker& checker, ScriptError* serror, bool is_p2sh)
{ {
CScript exec_script; //!< Actually executed script (last stack item in P2WSH; implied P2PKH script in P2WPKH; leaf script in P2TR) CScript exec_script; //!< Actually executed script (last stack item in P2WSH; implied P2PKH script in P2WPKH; leaf script in P2TR)
std::span stack{witness.stack}; std::span stack{witness.stack};
@ -1994,7 +1995,7 @@ static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion,
// There is intentionally no return statement here, to be able to use "control reaches end of non-void function" warnings to detect gaps in the logic above. // There is intentionally no return statement here, to be able to use "control reaches end of non-void function" warnings to detect gaps in the logic above.
} }
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror) bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, script_verify_flags flags, const BaseSignatureChecker& checker, ScriptError* serror)
{ {
static const CScriptWitness emptyWitness; static const CScriptWitness emptyWitness;
if (witness == nullptr) { if (witness == nullptr) {
@ -2131,7 +2132,7 @@ size_t static WitnessSigOps(int witversion, const std::vector<unsigned char>& wi
return 0; return 0;
} }
size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags) size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, script_verify_flags flags)
{ {
static const CScriptWitness witnessEmpty; static const CScriptWitness witnessEmpty;
@ -2161,3 +2162,48 @@ size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey,
return 0; return 0;
} }
#define FLAG_NAME(flag) {std::string(#flag), SCRIPT_VERIFY_##flag}
const std::map<std::string, script_verify_flag_name> g_verify_flag_names{
FLAG_NAME(P2SH),
FLAG_NAME(STRICTENC),
FLAG_NAME(DERSIG),
FLAG_NAME(LOW_S),
FLAG_NAME(SIGPUSHONLY),
FLAG_NAME(MINIMALDATA),
FLAG_NAME(NULLDUMMY),
FLAG_NAME(DISCOURAGE_UPGRADABLE_NOPS),
FLAG_NAME(CLEANSTACK),
FLAG_NAME(MINIMALIF),
FLAG_NAME(NULLFAIL),
FLAG_NAME(CHECKLOCKTIMEVERIFY),
FLAG_NAME(CHECKSEQUENCEVERIFY),
FLAG_NAME(WITNESS),
FLAG_NAME(DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM),
FLAG_NAME(WITNESS_PUBKEYTYPE),
FLAG_NAME(CONST_SCRIPTCODE),
FLAG_NAME(TAPROOT),
FLAG_NAME(DISCOURAGE_UPGRADABLE_PUBKEYTYPE),
FLAG_NAME(DISCOURAGE_OP_SUCCESS),
FLAG_NAME(DISCOURAGE_UPGRADABLE_TAPROOT_VERSION),
};
#undef FLAG_NAME
std::vector<std::string> GetScriptFlagNames(script_verify_flags flags)
{
std::vector<std::string> res;
if (flags == SCRIPT_VERIFY_NONE) {
return res;
}
script_verify_flags leftover = flags;
for (const auto& [name, flag] : g_verify_flag_names) {
if ((flags & flag) != 0) {
res.push_back(name);
leftover &= ~flag;
}
}
if (leftover != 0) {
res.push_back(strprintf("0x%08x", leftover.as_int()));
}
return res;
}

View File

@ -10,6 +10,7 @@
#include <hash.h> #include <hash.h>
#include <primitives/transaction.h> #include <primitives/transaction.h>
#include <script/script_error.h> // IWYU pragma: export #include <script/script_error.h> // IWYU pragma: export
#include <script/verify_flags.h> // IWYU pragma: export
#include <span.h> #include <span.h>
#include <uint256.h> #include <uint256.h>
@ -42,35 +43,36 @@ enum
* All flags are intended to be soft forks: the set of acceptable scripts under * All flags are intended to be soft forks: the set of acceptable scripts under
* flags (A | B) is a subset of the acceptable scripts under flag (A). * flags (A | B) is a subset of the acceptable scripts under flag (A).
*/ */
enum : uint32_t {
SCRIPT_VERIFY_NONE = 0,
static constexpr script_verify_flags SCRIPT_VERIFY_NONE{0};
enum class script_verify_flag_name : uint8_t {
// Evaluate P2SH subscripts (BIP16). // Evaluate P2SH subscripts (BIP16).
SCRIPT_VERIFY_P2SH = (1U << 0), SCRIPT_VERIFY_P2SH,
// Passing a non-strict-DER signature or one with undefined hashtype to a checksig operation causes script failure. // Passing a non-strict-DER signature or one with undefined hashtype to a checksig operation causes script failure.
// Evaluating a pubkey that is not (0x04 + 64 bytes) or (0x02 or 0x03 + 32 bytes) by checksig causes script failure. // Evaluating a pubkey that is not (0x04 + 64 bytes) or (0x02 or 0x03 + 32 bytes) by checksig causes script failure.
// (not used or intended as a consensus rule). // (not used or intended as a consensus rule).
SCRIPT_VERIFY_STRICTENC = (1U << 1), SCRIPT_VERIFY_STRICTENC,
// Passing a non-strict-DER signature to a checksig operation causes script failure (BIP62 rule 1) // Passing a non-strict-DER signature to a checksig operation causes script failure (BIP62 rule 1)
SCRIPT_VERIFY_DERSIG = (1U << 2), SCRIPT_VERIFY_DERSIG,
// Passing a non-strict-DER signature or one with S > order/2 to a checksig operation causes script failure // Passing a non-strict-DER signature or one with S > order/2 to a checksig operation causes script failure
// (BIP62 rule 5). // (BIP62 rule 5).
SCRIPT_VERIFY_LOW_S = (1U << 3), SCRIPT_VERIFY_LOW_S,
// verify dummy stack item consumed by CHECKMULTISIG is of zero-length (BIP62 rule 7). // verify dummy stack item consumed by CHECKMULTISIG is of zero-length (BIP62 rule 7).
SCRIPT_VERIFY_NULLDUMMY = (1U << 4), SCRIPT_VERIFY_NULLDUMMY,
// Using a non-push operator in the scriptSig causes script failure (BIP62 rule 2). // Using a non-push operator in the scriptSig causes script failure (BIP62 rule 2).
SCRIPT_VERIFY_SIGPUSHONLY = (1U << 5), SCRIPT_VERIFY_SIGPUSHONLY,
// Require minimal encodings for all push operations (OP_0... OP_16, OP_1NEGATE where possible, direct // Require minimal encodings for all push operations (OP_0... OP_16, OP_1NEGATE where possible, direct
// pushes up to 75 bytes, OP_PUSHDATA up to 255 bytes, OP_PUSHDATA2 for anything larger). Evaluating // pushes up to 75 bytes, OP_PUSHDATA up to 255 bytes, OP_PUSHDATA2 for anything larger). Evaluating
// any other push causes the script to fail (BIP62 rule 3). // any other push causes the script to fail (BIP62 rule 3).
// In addition, whenever a stack element is interpreted as a number, it must be of minimal length (BIP62 rule 4). // In addition, whenever a stack element is interpreted as a number, it must be of minimal length (BIP62 rule 4).
SCRIPT_VERIFY_MINIMALDATA = (1U << 6), SCRIPT_VERIFY_MINIMALDATA,
// Discourage use of NOPs reserved for upgrades (NOP1-10) // Discourage use of NOPs reserved for upgrades (NOP1-10)
// //
@ -82,7 +84,7 @@ enum : uint32_t {
// executed, e.g. within an unexecuted IF ENDIF block, are *not* rejected. // executed, e.g. within an unexecuted IF ENDIF block, are *not* rejected.
// NOPs that have associated forks to give them new meaning (CLTV, CSV) // NOPs that have associated forks to give them new meaning (CLTV, CSV)
// are not subject to this rule. // are not subject to this rule.
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS = (1U << 7), SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS,
// Require that only a single stack element remains after evaluation. This changes the success criterion from // Require that only a single stack element remains after evaluation. This changes the success criterion from
// "At least one stack element must remain, and when interpreted as a boolean, it must be true" to // "At least one stack element must remain, and when interpreted as a boolean, it must be true" to
@ -91,64 +93,72 @@ enum : uint32_t {
// Note: CLEANSTACK should never be used without P2SH or WITNESS. // Note: CLEANSTACK should never be used without P2SH or WITNESS.
// Note: WITNESS_V0 and TAPSCRIPT script execution have behavior similar to CLEANSTACK as part of their // Note: WITNESS_V0 and TAPSCRIPT script execution have behavior similar to CLEANSTACK as part of their
// consensus rules. It is automatic there and does not need this flag. // consensus rules. It is automatic there and does not need this flag.
SCRIPT_VERIFY_CLEANSTACK = (1U << 8), SCRIPT_VERIFY_CLEANSTACK,
// Verify CHECKLOCKTIMEVERIFY // Verify CHECKLOCKTIMEVERIFY
// //
// See BIP65 for details. // See BIP65 for details.
SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9), SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY,
// support CHECKSEQUENCEVERIFY opcode // support CHECKSEQUENCEVERIFY opcode
// //
// See BIP112 for details // See BIP112 for details
SCRIPT_VERIFY_CHECKSEQUENCEVERIFY = (1U << 10), SCRIPT_VERIFY_CHECKSEQUENCEVERIFY,
// Support segregated witness // Support segregated witness
// //
SCRIPT_VERIFY_WITNESS = (1U << 11), SCRIPT_VERIFY_WITNESS,
// Making v1-v16 witness program non-standard // Making v1-v16 witness program non-standard
// //
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM = (1U << 12), SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM,
// Segwit script only: Require the argument of OP_IF/NOTIF to be exactly 0x01 or empty vector // Segwit script only: Require the argument of OP_IF/NOTIF to be exactly 0x01 or empty vector
// //
// Note: TAPSCRIPT script execution has behavior similar to MINIMALIF as part of its consensus // Note: TAPSCRIPT script execution has behavior similar to MINIMALIF as part of its consensus
// rules. It is automatic there and does not depend on this flag. // rules. It is automatic there and does not depend on this flag.
SCRIPT_VERIFY_MINIMALIF = (1U << 13), SCRIPT_VERIFY_MINIMALIF,
// Signature(s) must be empty vector if a CHECK(MULTI)SIG operation failed // Signature(s) must be empty vector if a CHECK(MULTI)SIG operation failed
// //
SCRIPT_VERIFY_NULLFAIL = (1U << 14), SCRIPT_VERIFY_NULLFAIL,
// Public keys in segregated witness scripts must be compressed // Public keys in segregated witness scripts must be compressed
// //
SCRIPT_VERIFY_WITNESS_PUBKEYTYPE = (1U << 15), SCRIPT_VERIFY_WITNESS_PUBKEYTYPE,
// Making OP_CODESEPARATOR and FindAndDelete fail any non-segwit scripts // Making OP_CODESEPARATOR and FindAndDelete fail any non-segwit scripts
// //
SCRIPT_VERIFY_CONST_SCRIPTCODE = (1U << 16), SCRIPT_VERIFY_CONST_SCRIPTCODE,
// Taproot/Tapscript validation (BIPs 341 & 342) // Taproot/Tapscript validation (BIPs 341 & 342)
// //
SCRIPT_VERIFY_TAPROOT = (1U << 17), SCRIPT_VERIFY_TAPROOT,
// Making unknown Taproot leaf versions non-standard // Making unknown Taproot leaf versions non-standard
// //
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION = (1U << 18), SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION,
// Making unknown OP_SUCCESS non-standard // Making unknown OP_SUCCESS non-standard
SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS = (1U << 19), SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS,
// Making unknown public key versions (in BIP 342 scripts) non-standard // Making unknown public key versions (in BIP 342 scripts) non-standard
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE = (1U << 20), SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE,
// Constants to point to the highest flag in use. Add new flags above this line. // Constants to point to the highest flag in use. Add new flags above this line.
// //
SCRIPT_VERIFY_END_MARKER SCRIPT_VERIFY_END_MARKER
}; };
using enum script_verify_flag_name;
bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned int flags, ScriptError* serror); static constexpr int MAX_SCRIPT_VERIFY_FLAGS_BITS = static_cast<int>(SCRIPT_VERIFY_END_MARKER);
// assert there is still a spare bit
static_assert(0 < MAX_SCRIPT_VERIFY_FLAGS_BITS && MAX_SCRIPT_VERIFY_FLAGS_BITS <= 63);
static constexpr script_verify_flags::value_type MAX_SCRIPT_VERIFY_FLAGS = ((script_verify_flags::value_type{1} << MAX_SCRIPT_VERIFY_FLAGS_BITS) - 1);
bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, script_verify_flags flags, ScriptError* serror);
struct PrecomputedTransactionData struct PrecomputedTransactionData
{ {
@ -363,12 +373,16 @@ uint256 ComputeTapbranchHash(std::span<const unsigned char> a, std::span<const u
* Requires control block to have valid length (33 + k*32, with k in {0,1,..,128}). */ * Requires control block to have valid length (33 + k*32, with k in {0,1,..,128}). */
uint256 ComputeTaprootMerkleRoot(std::span<const unsigned char> control, const uint256& tapleaf_hash); uint256 ComputeTaprootMerkleRoot(std::span<const unsigned char> control, const uint256& tapleaf_hash);
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* error = nullptr); bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, script_verify_flags flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* error = nullptr);
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* error = nullptr); bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, script_verify_flags flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* error = nullptr);
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror = nullptr); bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, script_verify_flags flags, const BaseSignatureChecker& checker, ScriptError* serror = nullptr);
size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags); size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, script_verify_flags flags);
int FindAndDelete(CScript& script, const CScript& b); int FindAndDelete(CScript& script, const CScript& b);
extern const std::map<std::string, script_verify_flag_name> g_verify_flag_names;
std::vector<std::string> GetScriptFlagNames(script_verify_flags flags);
#endif // BITCOIN_SCRIPT_INTERPRETER_H #endif // BITCOIN_SCRIPT_INTERPRETER_H

71
src/script/verify_flags.h Normal file
View File

@ -0,0 +1,71 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-present The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_SCRIPT_VERIFY_FLAGS_H
#define BITCOIN_SCRIPT_VERIFY_FLAGS_H
#include <compare>
#include <cstdint>
enum class script_verify_flag_name : uint8_t;
class script_verify_flags
{
public:
using value_type = uint64_t;
consteval script_verify_flags() = default;
// also allow construction with hard-coded 0 (but not other integers)
consteval explicit(false) script_verify_flags(value_type f) : m_value{f} { if (f != 0) throw 0; }
// implicit construction from a hard-coded SCRIPT_VERIFY_* constant is also okay
constexpr explicit(false) script_verify_flags(script_verify_flag_name f) : m_value{value_type{1} << static_cast<uint8_t>(f)} { }
// rule of 5
constexpr script_verify_flags(const script_verify_flags&) = default;
constexpr script_verify_flags(script_verify_flags&&) = default;
constexpr script_verify_flags& operator=(const script_verify_flags&) = default;
constexpr script_verify_flags& operator=(script_verify_flags&&) = default;
constexpr ~script_verify_flags() = default;
// integer conversion needs to be very explicit
static constexpr script_verify_flags from_int(value_type f) { script_verify_flags r; r.m_value = f; return r; }
constexpr value_type as_int() const { return m_value; }
// bitwise operations
constexpr script_verify_flags operator~() const { return from_int(~m_value); }
friend constexpr script_verify_flags operator|(script_verify_flags a, script_verify_flags b) { return from_int(a.m_value | b.m_value); }
friend constexpr script_verify_flags operator&(script_verify_flags a, script_verify_flags b) { return from_int(a.m_value & b.m_value); }
// in-place bitwise operations
constexpr script_verify_flags& operator|=(script_verify_flags vf) { m_value |= vf.m_value; return *this; }
constexpr script_verify_flags& operator&=(script_verify_flags vf) { m_value &= vf.m_value; return *this; }
// tests
constexpr explicit operator bool() const { return m_value != 0; }
constexpr bool operator==(script_verify_flags other) const { return m_value == other.m_value; }
/** Compare two script_verify_flags. <, >, <=, and >= are auto-generated from this. */
friend constexpr std::strong_ordering operator<=>(const script_verify_flags& a, const script_verify_flags& b) noexcept
{
return a.m_value <=> b.m_value;
}
private:
value_type m_value{0}; // default value is SCRIPT_VERIFY_NONE
};
inline constexpr script_verify_flags operator~(script_verify_flag_name f)
{
return ~script_verify_flags{f};
}
inline constexpr script_verify_flags operator|(script_verify_flag_name f1, script_verify_flag_name f2)
{
return script_verify_flags{f1} | f2;
}
#endif // BITCOIN_SCRIPT_VERIFY_FLAGS_H

View File

@ -26,7 +26,7 @@
static constexpr uint8_t SIGNET_HEADER[4] = {0xec, 0xc7, 0xda, 0xa2}; static constexpr uint8_t SIGNET_HEADER[4] = {0xec, 0xc7, 0xda, 0xa2};
static constexpr unsigned int BLOCK_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_NULLDUMMY; static constexpr script_verify_flags BLOCK_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_NULLDUMMY;
static bool FetchAndClearCommitmentSection(const std::span<const uint8_t> header, CScript& witness_commitment, std::vector<uint8_t>& result) static bool FetchAndClearCommitmentSection(const std::span<const uint8_t> header, CScript& witness_commitment, std::vector<uint8_t>& result)
{ {

View File

@ -26,6 +26,7 @@ add_executable(test_bitcoin
bloom_tests.cpp bloom_tests.cpp
bswap_tests.cpp bswap_tests.cpp
caches_tests.cpp caches_tests.cpp
chain_tests.cpp
chainstate_write_tests.cpp chainstate_write_tests.cpp
checkqueue_tests.cpp checkqueue_tests.cpp
cluster_linearize_tests.cpp cluster_linearize_tests.cpp

85
src/test/chain_tests.cpp Normal file
View File

@ -0,0 +1,85 @@
// Copyright (c) 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 <boost/test/unit_test.hpp>
#include <chain.h>
#include <test/util/setup_common.h>
#include <memory>
BOOST_FIXTURE_TEST_SUITE(chain_tests, BasicTestingSetup)
namespace {
const CBlockIndex* NaiveGetAncestor(const CBlockIndex* a, int height)
{
while (a->nHeight > height) {
a = a->pprev;
}
BOOST_REQUIRE_EQUAL(a->nHeight, height);
return a;
}
const CBlockIndex* NaiveLastCommonAncestor(const CBlockIndex* a, const CBlockIndex* b)
{
while (a->nHeight > b->nHeight) {
a = a->pprev;
}
while (b->nHeight > a->nHeight) {
b = b->pprev;
}
while (a != b) {
BOOST_REQUIRE_EQUAL(a->nHeight, b->nHeight);
a = a->pprev;
b = b->pprev;
}
BOOST_REQUIRE_EQUAL(a, b);
return a;
}
} // namespace
BOOST_AUTO_TEST_CASE(chain_test)
{
FastRandomContext ctx;
std::vector<std::unique_ptr<CBlockIndex>> block_index;
// Run 10 iterations of the whole test.
for (int i = 0; i < 10; ++i) {
block_index.clear();
// Create genesis block.
auto genesis = std::make_unique<CBlockIndex>();
genesis->nHeight = 0;
block_index.push_back(std::move(genesis));
// Create 10000 more blocks.
for (int b = 0; b < 10000; ++b) {
auto new_index = std::make_unique<CBlockIndex>();
// 95% of blocks build on top of the last block; the others fork off randomly.
if (ctx.randrange(20) != 0) {
new_index->pprev = block_index.back().get();
} else {
new_index->pprev = block_index[ctx.randrange(block_index.size())].get();
}
new_index->nHeight = new_index->pprev->nHeight + 1;
new_index->BuildSkip();
block_index.push_back(std::move(new_index));
}
// Run 10000 random GetAncestor queries.
for (int q = 0; q < 10000; ++q) {
const CBlockIndex* block = block_index[ctx.randrange(block_index.size())].get();
unsigned height = ctx.randrange<unsigned>(block->nHeight + 1);
const CBlockIndex* result = block->GetAncestor(height);
BOOST_CHECK(result == NaiveGetAncestor(block, height));
}
// Run 10000 random LastCommonAncestor queries.
for (int q = 0; q < 10000; ++q) {
const CBlockIndex* block1 = block_index[ctx.randrange(block_index.size())].get();
const CBlockIndex* block2 = block_index[ctx.randrange(block_index.size())].get();
const CBlockIndex* result = LastCommonAncestor(block1, block2);
BOOST_CHECK(result == NaiveLastCommonAncestor(block1, block2));
}
}
}
BOOST_AUTO_TEST_SUITE_END()

View File

@ -288,7 +288,7 @@ void TestCoinsView(FuzzedDataProvider& fuzzed_data_provider, CCoinsView& backend
// consensus/tx_verify.cpp:130: unsigned int GetP2SHSigOpCount(const CTransaction &, const CCoinsViewCache &): Assertion `!coin.IsSpent()' failed. // consensus/tx_verify.cpp:130: unsigned int GetP2SHSigOpCount(const CTransaction &, const CCoinsViewCache &): Assertion `!coin.IsSpent()' failed.
return; return;
} }
const auto flags{fuzzed_data_provider.ConsumeIntegral<uint32_t>()}; const auto flags = script_verify_flags::from_int(fuzzed_data_provider.ConsumeIntegral<script_verify_flags::value_type>());
if (!transaction.vin.empty() && (flags & SCRIPT_VERIFY_WITNESS) != 0 && (flags & SCRIPT_VERIFY_P2SH) == 0) { if (!transaction.vin.empty() && (flags & SCRIPT_VERIFY_WITNESS) != 0 && (flags & SCRIPT_VERIFY_P2SH) == 0) {
// Avoid: // Avoid:
// script/interpreter.cpp:1705: size_t CountWitnessSigOps(const CScript &, const CScript &, const CScriptWitness *, unsigned int): Assertion `(flags & SCRIPT_VERIFY_P2SH) != 0' failed. // script/interpreter.cpp:1705: size_t CountWitnessSigOps(const CScript &, const CScript &, const CScriptWitness *, unsigned int): Assertion `(flags & SCRIPT_VERIFY_P2SH) != 0' failed.

View File

@ -12,7 +12,7 @@
FUZZ_TARGET(eval_script) FUZZ_TARGET(eval_script)
{ {
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const unsigned int flags = fuzzed_data_provider.ConsumeIntegral<unsigned int>(); const auto flags = script_verify_flags::from_int(fuzzed_data_provider.ConsumeIntegral<script_verify_flags::value_type>());
const std::vector<uint8_t> script_bytes = [&] { const std::vector<uint8_t> script_bytes = [&] {
if (fuzzed_data_provider.remaining_bytes() != 0) { if (fuzzed_data_provider.remaining_bytes() != 0) {
return fuzzed_data_provider.ConsumeRemainingBytes<uint8_t>(); return fuzzed_data_provider.ConsumeRemainingBytes<uint8_t>();

View File

@ -118,8 +118,8 @@ FUZZ_TARGET(script, .init = initialize_script)
(void)FindAndDelete(script_mut, *other_script); (void)FindAndDelete(script_mut, *other_script);
} }
const std::vector<std::string> random_string_vector = ConsumeRandomLengthStringVector(fuzzed_data_provider); const std::vector<std::string> random_string_vector = ConsumeRandomLengthStringVector(fuzzed_data_provider);
const uint32_t u32{fuzzed_data_provider.ConsumeIntegral<uint32_t>()}; const auto flags_rand{fuzzed_data_provider.ConsumeIntegral<script_verify_flags::value_type>()};
const uint32_t flags{u32 | SCRIPT_VERIFY_P2SH}; const auto flags = script_verify_flags::from_int(flags_rand) | SCRIPT_VERIFY_P2SH;
{ {
CScriptWitness wit; CScriptWitness wit;
for (const auto& s : random_string_vector) { for (const auto& s : random_string_vector) {

View File

@ -90,22 +90,22 @@ CScriptWitness ScriptWitnessFromJSON(const UniValue& univalue)
return scriptwitness; return scriptwitness;
} }
const std::map<std::string, unsigned int> FLAG_NAMES = { const std::map<std::string, script_verify_flag_name> FLAG_NAMES = {
{std::string("P2SH"), (unsigned int)SCRIPT_VERIFY_P2SH}, {std::string("P2SH"), SCRIPT_VERIFY_P2SH},
{std::string("DERSIG"), (unsigned int)SCRIPT_VERIFY_DERSIG}, {std::string("DERSIG"), SCRIPT_VERIFY_DERSIG},
{std::string("NULLDUMMY"), (unsigned int)SCRIPT_VERIFY_NULLDUMMY}, {std::string("NULLDUMMY"), SCRIPT_VERIFY_NULLDUMMY},
{std::string("CHECKLOCKTIMEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY}, {std::string("CHECKLOCKTIMEVERIFY"), SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY},
{std::string("CHECKSEQUENCEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKSEQUENCEVERIFY}, {std::string("CHECKSEQUENCEVERIFY"), SCRIPT_VERIFY_CHECKSEQUENCEVERIFY},
{std::string("WITNESS"), (unsigned int)SCRIPT_VERIFY_WITNESS}, {std::string("WITNESS"), SCRIPT_VERIFY_WITNESS},
{std::string("TAPROOT"), (unsigned int)SCRIPT_VERIFY_TAPROOT}, {std::string("TAPROOT"), SCRIPT_VERIFY_TAPROOT},
}; };
std::vector<unsigned int> AllFlags() std::vector<script_verify_flags> AllFlags()
{ {
std::vector<unsigned int> ret; std::vector<script_verify_flags> ret;
for (unsigned int i = 0; i < 128; ++i) { for (unsigned int i = 0; i < 128; ++i) {
unsigned int flag = 0; script_verify_flags flag = 0;
if (i & 1) flag |= SCRIPT_VERIFY_P2SH; if (i & 1) flag |= SCRIPT_VERIFY_P2SH;
if (i & 2) flag |= SCRIPT_VERIFY_DERSIG; if (i & 2) flag |= SCRIPT_VERIFY_DERSIG;
if (i & 4) flag |= SCRIPT_VERIFY_NULLDUMMY; if (i & 4) flag |= SCRIPT_VERIFY_NULLDUMMY;
@ -125,13 +125,13 @@ std::vector<unsigned int> AllFlags()
return ret; return ret;
} }
const std::vector<unsigned int> ALL_FLAGS = AllFlags(); const std::vector<script_verify_flags> ALL_FLAGS = AllFlags();
unsigned int ParseScriptFlags(const std::string& str) script_verify_flags ParseScriptFlags(const std::string& str)
{ {
if (str.empty()) return 0; if (str.empty()) return 0;
unsigned int flags = 0; script_verify_flags flags = 0;
std::vector<std::string> words = SplitString(str, ','); std::vector<std::string> words = SplitString(str, ',');
for (const std::string& word : words) { for (const std::string& word : words) {
@ -153,7 +153,7 @@ void Test(const std::string& str)
if (prevouts.size() != tx.vin.size()) throw std::runtime_error("Incorrect number of prevouts"); if (prevouts.size() != tx.vin.size()) throw std::runtime_error("Incorrect number of prevouts");
size_t idx = test["index"].getInt<int64_t>(); size_t idx = test["index"].getInt<int64_t>();
if (idx >= tx.vin.size()) throw std::runtime_error("Invalid index"); if (idx >= tx.vin.size()) throw std::runtime_error("Invalid index");
unsigned int test_flags = ParseScriptFlags(test["flags"].get_str()); script_verify_flags test_flags = ParseScriptFlags(test["flags"].get_str());
bool final = test.exists("final") && test["final"].get_bool(); bool final = test.exists("final") && test["final"].get_bool();
if (test.exists("success")) { if (test.exists("success")) {

View File

@ -15,6 +15,15 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
static DataStream& operator>>(DataStream& ds, script_verify_flags& f)
{
script_verify_flags::value_type n{0};
ds >> n;
f = script_verify_flags::from_int(n);
assert(n == f.as_int());
return ds;
}
FUZZ_TARGET(script_flags) FUZZ_TARGET(script_flags)
{ {
if (buffer.size() > 100'000) return; if (buffer.size() > 100'000) return;
@ -22,12 +31,14 @@ FUZZ_TARGET(script_flags)
try { try {
const CTransaction tx(deserialize, TX_WITH_WITNESS, ds); const CTransaction tx(deserialize, TX_WITH_WITNESS, ds);
unsigned int verify_flags; script_verify_flags verify_flags;
ds >> verify_flags; ds >> verify_flags;
assert(verify_flags == script_verify_flags::from_int(verify_flags.as_int()));
if (!IsValidFlagCombination(verify_flags)) return; if (!IsValidFlagCombination(verify_flags)) return;
unsigned int fuzzed_flags; script_verify_flags fuzzed_flags;
ds >> fuzzed_flags; ds >> fuzzed_flags;
std::vector<CTxOut> spent_outputs; std::vector<CTxOut> spent_outputs;

View File

@ -51,7 +51,7 @@ public:
FUZZ_TARGET(signature_checker) FUZZ_TARGET(signature_checker)
{ {
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const unsigned int flags = fuzzed_data_provider.ConsumeIntegral<unsigned int>(); const auto flags = script_verify_flags::from_int(fuzzed_data_provider.ConsumeIntegral<script_verify_flags::value_type>());
const SigVersion sig_version = fuzzed_data_provider.PickValueInArray({SigVersion::BASE, SigVersion::WITNESS_V0}); const SigVersion sig_version = fuzzed_data_provider.PickValueInArray({SigVersion::BASE, SigVersion::WITNESS_V0});
const auto script_1{ConsumeScript(fuzzed_data_provider)}; const auto script_1{ConsumeScript(fuzzed_data_provider)};
const auto script_2{ConsumeScript(fuzzed_data_provider)}; const auto script_2{ConsumeScript(fuzzed_data_provider)};

View File

@ -38,7 +38,7 @@ sign_multisig(const CScript& scriptPubKey, const std::vector<CKey>& keys, const
BOOST_AUTO_TEST_CASE(multisig_verify) BOOST_AUTO_TEST_CASE(multisig_verify)
{ {
unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC; script_verify_flags flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
ScriptError err; ScriptError err;
CKey key[4]; CKey key[4];

View File

@ -25,7 +25,7 @@
#include <univalue.h> #include <univalue.h>
unsigned int ParseScriptFlags(std::string strFlags); script_verify_flags ParseScriptFlags(std::string strFlags);
BOOST_AUTO_TEST_SUITE(script_assets_tests) BOOST_AUTO_TEST_SUITE(script_assets_tests)
@ -71,12 +71,12 @@ static CScriptWitness ScriptWitnessFromJSON(const UniValue& univalue)
return scriptwitness; return scriptwitness;
} }
static std::vector<unsigned int> AllConsensusFlags() static std::vector<script_verify_flags> AllConsensusFlags()
{ {
std::vector<unsigned int> ret; std::vector<script_verify_flags> ret;
for (unsigned int i = 0; i < 128; ++i) { for (unsigned int i = 0; i < 128; ++i) {
unsigned int flag = 0; script_verify_flags flag = 0;
if (i & 1) flag |= SCRIPT_VERIFY_P2SH; if (i & 1) flag |= SCRIPT_VERIFY_P2SH;
if (i & 2) flag |= SCRIPT_VERIFY_DERSIG; if (i & 2) flag |= SCRIPT_VERIFY_DERSIG;
if (i & 4) flag |= SCRIPT_VERIFY_NULLDUMMY; if (i & 4) flag |= SCRIPT_VERIFY_NULLDUMMY;
@ -97,7 +97,7 @@ static std::vector<unsigned int> AllConsensusFlags()
} }
/** Precomputed list of all valid combinations of consensus-relevant script validation flags. */ /** Precomputed list of all valid combinations of consensus-relevant script validation flags. */
static const std::vector<unsigned int> ALL_CONSENSUS_FLAGS = AllConsensusFlags(); static const std::vector<script_verify_flags> ALL_CONSENSUS_FLAGS = AllConsensusFlags();
static void AssetTest(const UniValue& test, SignatureCache& signature_cache) static void AssetTest(const UniValue& test, SignatureCache& signature_cache)
{ {
@ -107,7 +107,7 @@ static void AssetTest(const UniValue& test, SignatureCache& signature_cache)
const std::vector<CTxOut> prevouts = TxOutsFromJSON(test["prevouts"]); const std::vector<CTxOut> prevouts = TxOutsFromJSON(test["prevouts"]);
BOOST_CHECK(prevouts.size() == mtx.vin.size()); BOOST_CHECK(prevouts.size() == mtx.vin.size());
size_t idx = test["index"].getInt<int64_t>(); size_t idx = test["index"].getInt<int64_t>();
uint32_t test_flags{ParseScriptFlags(test["flags"].get_str())}; script_verify_flags test_flags{ParseScriptFlags(test["flags"].get_str())};
bool fin = test.exists("final") && test["final"].get_bool(); bool fin = test.exists("final") && test["final"].get_bool();
if (test.exists("success")) { if (test.exists("success")) {

View File

@ -9,6 +9,7 @@
#include <core_io.h> #include <core_io.h>
#include <key.h> #include <key.h>
#include <rpc/util.h> #include <rpc/util.h>
#include <script/interpreter.h>
#include <script/script.h> #include <script/script.h>
#include <script/script_error.h> #include <script/script_error.h>
#include <script/sigcache.h> #include <script/sigcache.h>
@ -22,6 +23,7 @@
#include <test/util/transaction_utils.h> #include <test/util/transaction_utils.h>
#include <util/fs.h> #include <util/fs.h>
#include <util/strencodings.h> #include <util/strencodings.h>
#include <util/string.h>
#include <cstdint> #include <cstdint>
#include <fstream> #include <fstream>
@ -38,10 +40,9 @@
using namespace util::hex_literals; using namespace util::hex_literals;
static const unsigned int gFlags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC; static const script_verify_flags gFlags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
unsigned int ParseScriptFlags(std::string strFlags); script_verify_flags ParseScriptFlags(std::string strFlags);
std::string FormatScriptFlags(unsigned int flags);
struct ScriptErrorDesc struct ScriptErrorDesc
{ {
@ -95,6 +96,11 @@ static ScriptErrorDesc script_errors[]={
{SCRIPT_ERR_SIG_FINDANDDELETE, "SIG_FINDANDDELETE"}, {SCRIPT_ERR_SIG_FINDANDDELETE, "SIG_FINDANDDELETE"},
}; };
static std::string FormatScriptFlags(script_verify_flags flags)
{
return util::Join(GetScriptFlagNames(flags), ",");
}
static std::string FormatScriptError(ScriptError_t err) static std::string FormatScriptError(ScriptError_t err)
{ {
for (const auto& se : script_errors) for (const auto& se : script_errors)
@ -114,7 +120,7 @@ static ScriptError_t ParseScriptError(const std::string& name)
} }
struct ScriptTest : BasicTestingSetup { struct ScriptTest : BasicTestingSetup {
void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScriptWitness& scriptWitness, uint32_t flags, const std::string& message, int scriptError, CAmount nValue = 0) void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScriptWitness& scriptWitness, script_verify_flags flags, const std::string& message, int scriptError, CAmount nValue = 0)
{ {
bool expect = (scriptError == SCRIPT_ERR_OK); bool expect = (scriptError == SCRIPT_ERR_OK);
if (flags & SCRIPT_VERIFY_CLEANSTACK) { if (flags & SCRIPT_VERIFY_CLEANSTACK) {
@ -128,13 +134,13 @@ void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScript
BOOST_CHECK_MESSAGE(err == scriptError, FormatScriptError(err) + " where " + FormatScriptError((ScriptError_t)scriptError) + " expected: " + message); BOOST_CHECK_MESSAGE(err == scriptError, FormatScriptError(err) + " where " + FormatScriptError((ScriptError_t)scriptError) + " expected: " + message);
// Verify that removing flags from a passing test or adding flags to a failing test does not change the result. // Verify that removing flags from a passing test or adding flags to a failing test does not change the result.
for (int i = 0; i < 16; ++i) { for (int i = 0; i < 256; ++i) {
uint32_t extra_flags(m_rng.randbits(16)); script_verify_flags extra_flags = script_verify_flags::from_int(m_rng.randbits(MAX_SCRIPT_VERIFY_FLAGS_BITS));
uint32_t combined_flags{expect ? (flags & ~extra_flags) : (flags | extra_flags)}; script_verify_flags combined_flags{expect ? (flags & ~extra_flags) : (flags | extra_flags)};
// Weed out some invalid flag combinations. // Weed out some invalid flag combinations.
if (combined_flags & SCRIPT_VERIFY_CLEANSTACK && ~combined_flags & (SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS)) continue; if (combined_flags & SCRIPT_VERIFY_CLEANSTACK && ~combined_flags & (SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS)) continue;
if (combined_flags & SCRIPT_VERIFY_WITNESS && ~combined_flags & SCRIPT_VERIFY_P2SH) continue; if (combined_flags & SCRIPT_VERIFY_WITNESS && ~combined_flags & SCRIPT_VERIFY_P2SH) continue;
BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, &scriptWitness, combined_flags, MutableTransactionSignatureChecker(&tx, 0, txCredit.vout[0].nValue, MissingDataBehavior::ASSERT_FAIL), &err) == expect, message + strprintf(" (with flags %x)", combined_flags)); BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, &scriptWitness, combined_flags, MutableTransactionSignatureChecker(&tx, 0, txCredit.vout[0].nValue, MissingDataBehavior::ASSERT_FAIL), &err) == expect, message + strprintf(" (with flags %x)", combined_flags.as_int()));
} }
} }
}; // struct ScriptTest }; // struct ScriptTest
@ -226,7 +232,7 @@ private:
bool havePush{false}; bool havePush{false};
std::vector<unsigned char> push; std::vector<unsigned char> push;
std::string comment; std::string comment;
uint32_t flags; script_verify_flags flags;
int scriptError{SCRIPT_ERR_OK}; int scriptError{SCRIPT_ERR_OK};
CAmount nValue; CAmount nValue;
@ -246,7 +252,7 @@ private:
} }
public: public:
TestBuilder(const CScript& script_, const std::string& comment_, uint32_t flags_, bool P2SH = false, WitnessMode wm = WitnessMode::NONE, int witnessversion = 0, CAmount nValue_ = 0) : script(script_), comment(comment_), flags(flags_), nValue(nValue_) TestBuilder(const CScript& script_, const std::string& comment_, script_verify_flags flags_, bool P2SH = false, WitnessMode wm = WitnessMode::NONE, int witnessversion = 0, CAmount nValue_ = 0) : script(script_), comment(comment_), flags(flags_), nValue(nValue_)
{ {
CScript scriptPubKey = script; CScript scriptPubKey = script;
if (wm == WitnessMode::PKH) { if (wm == WitnessMode::PKH) {
@ -963,7 +969,7 @@ BOOST_AUTO_TEST_CASE(script_json_test)
} else { } else {
scriptPubKey = ParseScript(scriptPubKeyString); scriptPubKey = ParseScript(scriptPubKeyString);
} }
unsigned int scriptflags = ParseScriptFlags(test[pos++].get_str()); script_verify_flags scriptflags = ParseScriptFlags(test[pos++].get_str());
int scriptError = ParseScriptError(test[pos++].get_str()); int scriptError = ParseScriptError(test[pos++].get_str());
DoTest(scriptPubKey, scriptSig, witness, scriptflags, strTest, scriptError, nValue); DoTest(scriptPubKey, scriptSig, witness, scriptflags, strTest, scriptError, nValue);
@ -1706,4 +1712,15 @@ BOOST_AUTO_TEST_CASE(compute_tapleaf)
BOOST_CHECK_EQUAL(ComputeTapleafHash(0xc2, std::span(script)), tlc2); BOOST_CHECK_EQUAL(ComputeTapleafHash(0xc2, std::span(script)), tlc2);
} }
BOOST_AUTO_TEST_CASE(formatscriptflags)
{
// quick check that FormatScriptFlags reports any unknown/unexpected bits
BOOST_CHECK_EQUAL(FormatScriptFlags(SCRIPT_VERIFY_P2SH), "P2SH");
BOOST_CHECK_EQUAL(FormatScriptFlags(SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_TAPROOT), "P2SH,TAPROOT");
BOOST_CHECK_EQUAL(FormatScriptFlags(SCRIPT_VERIFY_P2SH | script_verify_flags::from_int(1u<<31)), "P2SH,0x80000000");
BOOST_CHECK_EQUAL(FormatScriptFlags(SCRIPT_VERIFY_TAPROOT | script_verify_flags::from_int(1u<<27)), "TAPROOT,0x08000000");
BOOST_CHECK_EQUAL(FormatScriptFlags(SCRIPT_VERIFY_TAPROOT | script_verify_flags::from_int((1u<<28) | (1ull<<58))), "TAPROOT,0x400000010000000");
BOOST_CHECK_EQUAL(FormatScriptFlags(script_verify_flags::from_int(1u<<26)), "0x04000000");
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

View File

@ -69,7 +69,7 @@ BOOST_AUTO_TEST_CASE(GetSigOpCount)
* Verifies script execution of the zeroth scriptPubKey of tx output and * Verifies script execution of the zeroth scriptPubKey of tx output and
* zeroth scriptSig and witness of tx input. * zeroth scriptSig and witness of tx input.
*/ */
static ScriptError VerifyWithFlag(const CTransaction& output, const CMutableTransaction& input, uint32_t flags) static ScriptError VerifyWithFlag(const CTransaction& output, const CMutableTransaction& input, script_verify_flags flags)
{ {
ScriptError error; ScriptError error;
CTransaction inputi(input); CTransaction inputi(input);
@ -122,7 +122,7 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
CKey key = GenerateRandomKey(); CKey key = GenerateRandomKey();
CPubKey pubkey = key.GetPubKey(); CPubKey pubkey = key.GetPubKey();
// Default flags // Default flags
const uint32_t flags{SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH}; const script_verify_flags flags{SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH};
// Multisig script (legacy counting) // Multisig script (legacy counting)
{ {

View File

@ -17,6 +17,7 @@
#include <policy/policy.h> #include <policy/policy.h>
#include <policy/settings.h> #include <policy/settings.h>
#include <primitives/transaction_identifier.h> #include <primitives/transaction_identifier.h>
#include <script/interpreter.h>
#include <script/script.h> #include <script/script.h>
#include <script/script_error.h> #include <script/script_error.h>
#include <script/sigcache.h> #include <script/sigcache.h>
@ -49,41 +50,21 @@ typedef std::vector<unsigned char> valtype;
static CFeeRate g_dust{DUST_RELAY_TX_FEE}; static CFeeRate g_dust{DUST_RELAY_TX_FEE};
static bool g_bare_multi{DEFAULT_PERMIT_BAREMULTISIG}; static bool g_bare_multi{DEFAULT_PERMIT_BAREMULTISIG};
static std::map<std::string, unsigned int> mapFlagNames = { static const std::map<std::string, script_verify_flag_name>& mapFlagNames = g_verify_flag_names;
{std::string("P2SH"), (unsigned int)SCRIPT_VERIFY_P2SH},
{std::string("STRICTENC"), (unsigned int)SCRIPT_VERIFY_STRICTENC},
{std::string("DERSIG"), (unsigned int)SCRIPT_VERIFY_DERSIG},
{std::string("LOW_S"), (unsigned int)SCRIPT_VERIFY_LOW_S},
{std::string("SIGPUSHONLY"), (unsigned int)SCRIPT_VERIFY_SIGPUSHONLY},
{std::string("MINIMALDATA"), (unsigned int)SCRIPT_VERIFY_MINIMALDATA},
{std::string("NULLDUMMY"), (unsigned int)SCRIPT_VERIFY_NULLDUMMY},
{std::string("DISCOURAGE_UPGRADABLE_NOPS"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS},
{std::string("CLEANSTACK"), (unsigned int)SCRIPT_VERIFY_CLEANSTACK},
{std::string("MINIMALIF"), (unsigned int)SCRIPT_VERIFY_MINIMALIF},
{std::string("NULLFAIL"), (unsigned int)SCRIPT_VERIFY_NULLFAIL},
{std::string("CHECKLOCKTIMEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY},
{std::string("CHECKSEQUENCEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKSEQUENCEVERIFY},
{std::string("WITNESS"), (unsigned int)SCRIPT_VERIFY_WITNESS},
{std::string("DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM},
{std::string("WITNESS_PUBKEYTYPE"), (unsigned int)SCRIPT_VERIFY_WITNESS_PUBKEYTYPE},
{std::string("CONST_SCRIPTCODE"), (unsigned int)SCRIPT_VERIFY_CONST_SCRIPTCODE},
{std::string("TAPROOT"), (unsigned int)SCRIPT_VERIFY_TAPROOT},
{std::string("DISCOURAGE_UPGRADABLE_PUBKEYTYPE"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE},
{std::string("DISCOURAGE_OP_SUCCESS"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS},
{std::string("DISCOURAGE_UPGRADABLE_TAPROOT_VERSION"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION},
};
unsigned int ParseScriptFlags(std::string strFlags) script_verify_flags ParseScriptFlags(std::string strFlags)
{ {
unsigned int flags = SCRIPT_VERIFY_NONE; script_verify_flags flags = SCRIPT_VERIFY_NONE;
if (strFlags.empty() || strFlags == "NONE") return flags; if (strFlags.empty() || strFlags == "NONE") return flags;
std::vector<std::string> words = SplitString(strFlags, ','); std::vector<std::string> words = SplitString(strFlags, ',');
for (const std::string& word : words) for (const std::string& word : words)
{ {
if (!mapFlagNames.count(word)) if (!mapFlagNames.count(word)) {
BOOST_ERROR("Bad test: unknown verification flag '" << word << "'"); BOOST_ERROR("Bad test: unknown verification flag '" << word << "'");
flags |= mapFlagNames[word]; continue;
}
flags |= mapFlagNames.at(word);
} }
return flags; return flags;
} }
@ -91,34 +72,18 @@ unsigned int ParseScriptFlags(std::string strFlags)
// Check that all flags in STANDARD_SCRIPT_VERIFY_FLAGS are present in mapFlagNames. // Check that all flags in STANDARD_SCRIPT_VERIFY_FLAGS are present in mapFlagNames.
bool CheckMapFlagNames() bool CheckMapFlagNames()
{ {
unsigned int standard_flags_missing{STANDARD_SCRIPT_VERIFY_FLAGS}; script_verify_flags standard_flags_missing{STANDARD_SCRIPT_VERIFY_FLAGS};
for (const auto& pair : mapFlagNames) { for (const auto& pair : mapFlagNames) {
standard_flags_missing &= ~(pair.second); standard_flags_missing &= ~(pair.second);
} }
return standard_flags_missing == 0; return standard_flags_missing == 0;
} }
std::string FormatScriptFlags(unsigned int flags)
{
if (flags == SCRIPT_VERIFY_NONE) {
return "";
}
std::string ret;
std::map<std::string, unsigned int>::const_iterator it = mapFlagNames.begin();
while (it != mapFlagNames.end()) {
if (flags & it->second) {
ret += it->first + ",";
}
it++;
}
return ret.substr(0, ret.size() - 1);
}
/* /*
* Check that the input scripts of a transaction are valid/invalid as expected. * Check that the input scripts of a transaction are valid/invalid as expected.
*/ */
bool CheckTxScripts(const CTransaction& tx, const std::map<COutPoint, CScript>& map_prevout_scriptPubKeys, bool CheckTxScripts(const CTransaction& tx, const std::map<COutPoint, CScript>& map_prevout_scriptPubKeys,
const std::map<COutPoint, int64_t>& map_prevout_values, unsigned int flags, const std::map<COutPoint, int64_t>& map_prevout_values, script_verify_flags flags,
const PrecomputedTransactionData& txdata, const std::string& strTest, bool expect_valid) const PrecomputedTransactionData& txdata, const std::string& strTest, bool expect_valid)
{ {
bool tx_valid = true; bool tx_valid = true;
@ -152,18 +117,18 @@ bool CheckTxScripts(const CTransaction& tx, const std::map<COutPoint, CScript>&
* CLEANSTACK must be used WITNESS and P2SH * CLEANSTACK must be used WITNESS and P2SH
*/ */
unsigned int TrimFlags(unsigned int flags) script_verify_flags TrimFlags(script_verify_flags flags)
{ {
// WITNESS requires P2SH // WITNESS requires P2SH
if (!(flags & SCRIPT_VERIFY_P2SH)) flags &= ~(unsigned int)SCRIPT_VERIFY_WITNESS; if (!(flags & SCRIPT_VERIFY_P2SH)) flags &= ~SCRIPT_VERIFY_WITNESS;
// CLEANSTACK requires WITNESS (and transitively CLEANSTACK requires P2SH) // CLEANSTACK requires WITNESS (and transitively CLEANSTACK requires P2SH)
if (!(flags & SCRIPT_VERIFY_WITNESS)) flags &= ~(unsigned int)SCRIPT_VERIFY_CLEANSTACK; if (!(flags & SCRIPT_VERIFY_WITNESS)) flags &= ~SCRIPT_VERIFY_CLEANSTACK;
Assert(IsValidFlagCombination(flags)); Assert(IsValidFlagCombination(flags));
return flags; return flags;
} }
unsigned int FillFlags(unsigned int flags) script_verify_flags FillFlags(script_verify_flags flags)
{ {
// CLEANSTACK implies WITNESS // CLEANSTACK implies WITNESS
if (flags & SCRIPT_VERIFY_CLEANSTACK) flags |= SCRIPT_VERIFY_WITNESS; if (flags & SCRIPT_VERIFY_CLEANSTACK) flags |= SCRIPT_VERIFY_WITNESS;
@ -178,11 +143,11 @@ unsigned int FillFlags(unsigned int flags)
// that are valid and without duplicates. For example: if flags=1111 and the 4 possible flags are // that are valid and without duplicates. For example: if flags=1111 and the 4 possible flags are
// 0001, 0010, 0100, and 1000, this should return the set {0111, 1011, 1101, 1110}. // 0001, 0010, 0100, and 1000, this should return the set {0111, 1011, 1101, 1110}.
// Assumes that mapFlagNames contains all script verify flags. // Assumes that mapFlagNames contains all script verify flags.
std::set<unsigned int> ExcludeIndividualFlags(unsigned int flags) std::set<script_verify_flags> ExcludeIndividualFlags(script_verify_flags flags)
{ {
std::set<unsigned int> flags_combos; std::set<script_verify_flags> flags_combos;
for (const auto& pair : mapFlagNames) { for (const auto& pair : mapFlagNames) {
const unsigned int flags_excluding_one = TrimFlags(flags & ~(pair.second)); script_verify_flags flags_excluding_one = TrimFlags(flags & ~(pair.second));
if (flags != flags_excluding_one) { if (flags != flags_excluding_one) {
flags_combos.insert(flags_excluding_one); flags_combos.insert(flags_excluding_one);
} }
@ -247,7 +212,7 @@ BOOST_AUTO_TEST_CASE(tx_valid)
BOOST_CHECK(state.IsValid()); BOOST_CHECK(state.IsValid());
PrecomputedTransactionData txdata(tx); PrecomputedTransactionData txdata(tx);
unsigned int verify_flags = ParseScriptFlags(test[2].get_str()); script_verify_flags verify_flags = ParseScriptFlags(test[2].get_str());
// Check that the test gives a valid combination of flags (otherwise VerifyScript will throw). Don't edit the flags. // Check that the test gives a valid combination of flags (otherwise VerifyScript will throw). Don't edit the flags.
if (~verify_flags != FillFlags(~verify_flags)) { if (~verify_flags != FillFlags(~verify_flags)) {
@ -260,14 +225,14 @@ BOOST_AUTO_TEST_CASE(tx_valid)
// Backwards compatibility of script verification flags: Removing any flag(s) should not invalidate a valid transaction // Backwards compatibility of script verification flags: Removing any flag(s) should not invalidate a valid transaction
for (const auto& [name, flag] : mapFlagNames) { for (const auto& [name, flag] : mapFlagNames) {
// Removing individual flags // Removing individual flags
unsigned int flags = TrimFlags(~(verify_flags | flag)); script_verify_flags flags = TrimFlags(~(verify_flags | flag));
if (!CheckTxScripts(tx, mapprevOutScriptPubKeys, mapprevOutValues, flags, txdata, strTest, /*expect_valid=*/true)) { if (!CheckTxScripts(tx, mapprevOutScriptPubKeys, mapprevOutValues, flags, txdata, strTest, /*expect_valid=*/true)) {
BOOST_ERROR("Tx unexpectedly failed with flag " << name << " unset: " << strTest); BOOST_ERROR("Tx unexpectedly failed with flag " << name << " unset: " << strTest);
} }
// Removing random combinations of flags // Removing random combinations of flags
flags = TrimFlags(~(verify_flags | (unsigned int)m_rng.randbits(mapFlagNames.size()))); flags = TrimFlags(~(verify_flags | script_verify_flags::from_int(m_rng.randbits(MAX_SCRIPT_VERIFY_FLAGS_BITS))));
if (!CheckTxScripts(tx, mapprevOutScriptPubKeys, mapprevOutValues, flags, txdata, strTest, /*expect_valid=*/true)) { if (!CheckTxScripts(tx, mapprevOutScriptPubKeys, mapprevOutValues, flags, txdata, strTest, /*expect_valid=*/true)) {
BOOST_ERROR("Tx unexpectedly failed with random flags " << ToString(flags) << ": " << strTest); BOOST_ERROR("Tx unexpectedly failed with random flags " << ToString(flags.as_int()) << ": " << strTest);
} }
} }
@ -337,7 +302,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
} }
PrecomputedTransactionData txdata(tx); PrecomputedTransactionData txdata(tx);
unsigned int verify_flags = ParseScriptFlags(test[2].get_str()); script_verify_flags verify_flags = ParseScriptFlags(test[2].get_str());
// Check that the test gives a valid combination of flags (otherwise VerifyScript will throw). Don't edit the flags. // Check that the test gives a valid combination of flags (otherwise VerifyScript will throw). Don't edit the flags.
if (verify_flags != FillFlags(verify_flags)) { if (verify_flags != FillFlags(verify_flags)) {
@ -350,13 +315,13 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
// Backwards compatibility of script verification flags: Adding any flag(s) should not validate an invalid transaction // Backwards compatibility of script verification flags: Adding any flag(s) should not validate an invalid transaction
for (const auto& [name, flag] : mapFlagNames) { for (const auto& [name, flag] : mapFlagNames) {
unsigned int flags = FillFlags(verify_flags | flag); script_verify_flags flags = FillFlags(verify_flags | flag);
// Adding individual flags // Adding individual flags
if (!CheckTxScripts(tx, mapprevOutScriptPubKeys, mapprevOutValues, flags, txdata, strTest, /*expect_valid=*/false)) { if (!CheckTxScripts(tx, mapprevOutScriptPubKeys, mapprevOutValues, flags, txdata, strTest, /*expect_valid=*/false)) {
BOOST_ERROR("Tx unexpectedly passed with flag " << name << " set: " << strTest); BOOST_ERROR("Tx unexpectedly passed with flag " << name << " set: " << strTest);
} }
// Adding random combinations of flags // Adding random combinations of flags
flags = FillFlags(verify_flags | (unsigned int)m_rng.randbits(mapFlagNames.size())); flags = FillFlags(verify_flags | script_verify_flags::from_int(m_rng.randbits(MAX_SCRIPT_VERIFY_FLAGS_BITS)));
if (!CheckTxScripts(tx, mapprevOutScriptPubKeys, mapprevOutValues, flags, txdata, strTest, /*expect_valid=*/false)) { if (!CheckTxScripts(tx, mapprevOutScriptPubKeys, mapprevOutValues, flags, txdata, strTest, /*expect_valid=*/false)) {
BOOST_ERROR("Tx unexpectedly passed with random flags " << name << ": " << strTest); BOOST_ERROR("Tx unexpectedly passed with random flags " << name << ": " << strTest);
} }
@ -488,7 +453,7 @@ static void CreateCreditAndSpend(const FillableSigningProvider& keystore, const
assert(input.vin[0].scriptWitness.stack == inputm.vin[0].scriptWitness.stack); assert(input.vin[0].scriptWitness.stack == inputm.vin[0].scriptWitness.stack);
} }
static void CheckWithFlag(const CTransactionRef& output, const CMutableTransaction& input, uint32_t flags, bool success) static void CheckWithFlag(const CTransactionRef& output, const CMutableTransaction& input, script_verify_flags flags, bool success)
{ {
ScriptError error; ScriptError error;
CTransaction inputi(input); CTransaction inputi(input);

View File

@ -21,7 +21,7 @@ struct Dersig100Setup : public TestChain100Setup {
}; };
bool CheckInputScripts(const CTransaction& tx, TxValidationState& state, bool CheckInputScripts(const CTransaction& tx, TxValidationState& state,
const CCoinsViewCache& inputs, unsigned int flags, bool cacheSigStore, const CCoinsViewCache& inputs, script_verify_flags flags, bool cacheSigStore,
bool cacheFullScriptStore, PrecomputedTransactionData& txdata, bool cacheFullScriptStore, PrecomputedTransactionData& txdata,
ValidationCache& validation_cache, ValidationCache& validation_cache,
std::vector<CScriptCheck>* pvChecks) EXCLUSIVE_LOCKS_REQUIRED(cs_main); std::vector<CScriptCheck>* pvChecks) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
@ -120,7 +120,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, Dersig100Setup)
// should fail. // should fail.
// Capture this interaction with the upgraded_nop argument: set it when evaluating // Capture this interaction with the upgraded_nop argument: set it when evaluating
// any script flag that is implemented as an upgraded NOP code. // any script flag that is implemented as an upgraded NOP code.
static void ValidateCheckInputsForAllFlags(const CTransaction &tx, uint32_t failing_flags, bool add_to_cache, CCoinsViewCache& active_coins_tip, ValidationCache& validation_cache) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) static void ValidateCheckInputsForAllFlags(const CTransaction &tx, script_verify_flags failing_flags, bool add_to_cache, CCoinsViewCache& active_coins_tip, ValidationCache& validation_cache) EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
{ {
PrecomputedTransactionData txdata; PrecomputedTransactionData txdata;
@ -130,7 +130,7 @@ static void ValidateCheckInputsForAllFlags(const CTransaction &tx, uint32_t fail
TxValidationState state; TxValidationState state;
// Randomly selects flag combinations // Randomly selects flag combinations
uint32_t test_flags = (uint32_t) insecure_rand.randrange((SCRIPT_VERIFY_END_MARKER - 1) << 1); script_verify_flags test_flags = script_verify_flags::from_int(insecure_rand.randrange(MAX_SCRIPT_VERIFY_FLAGS));
// Filter out incompatible flag choices // Filter out incompatible flag choices
if ((test_flags & SCRIPT_VERIFY_CLEANSTACK)) { if ((test_flags & SCRIPT_VERIFY_CLEANSTACK)) {

View File

@ -5,7 +5,7 @@
#include <script/interpreter.h> #include <script/interpreter.h>
#include <test/util/script.h> #include <test/util/script.h>
bool IsValidFlagCombination(unsigned flags) bool IsValidFlagCombination(script_verify_flags flags)
{ {
if (flags & SCRIPT_VERIFY_CLEANSTACK && ~flags & (SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS)) return false; if (flags & SCRIPT_VERIFY_CLEANSTACK && ~flags & (SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS)) return false;
if (flags & SCRIPT_VERIFY_WITNESS && ~flags & SCRIPT_VERIFY_P2SH) return false; if (flags & SCRIPT_VERIFY_WITNESS && ~flags & SCRIPT_VERIFY_P2SH) return false;

View File

@ -7,6 +7,7 @@
#include <crypto/sha256.h> #include <crypto/sha256.h>
#include <script/script.h> #include <script/script.h>
#include <script/verify_flags.h>
static const std::vector<uint8_t> WITNESS_STACK_ELEM_OP_TRUE{uint8_t{OP_TRUE}}; static const std::vector<uint8_t> WITNESS_STACK_ELEM_OP_TRUE{uint8_t{OP_TRUE}};
static const CScript P2WSH_OP_TRUE{ static const CScript P2WSH_OP_TRUE{
@ -31,6 +32,6 @@ static const std::vector<std::vector<uint8_t>> P2WSH_EMPTY_TRUE_STACK{{static_ca
static const std::vector<std::vector<uint8_t>> P2WSH_EMPTY_TWO_STACK{{static_cast<uint8_t>(OP_2)}, {}}; static const std::vector<std::vector<uint8_t>> P2WSH_EMPTY_TWO_STACK{{static_cast<uint8_t>(OP_2)}, {}};
/** Flags that are not forbidden by an assert in script validation */ /** Flags that are not forbidden by an assert in script validation */
bool IsValidFlagCombination(unsigned flags); bool IsValidFlagCombination(script_verify_flags flags);
#endif // BITCOIN_TEST_UTIL_SCRIPT_H #endif // BITCOIN_TEST_UTIL_SCRIPT_H

View File

@ -139,7 +139,7 @@ const CBlockIndex* Chainstate::FindForkInGlobalIndex(const CBlockLocator& locato
} }
bool CheckInputScripts(const CTransaction& tx, TxValidationState& state, bool CheckInputScripts(const CTransaction& tx, TxValidationState& state,
const CCoinsViewCache& inputs, unsigned int flags, bool cacheSigStore, const CCoinsViewCache& inputs, script_verify_flags flags, bool cacheSigStore,
bool cacheFullScriptStore, PrecomputedTransactionData& txdata, bool cacheFullScriptStore, PrecomputedTransactionData& txdata,
ValidationCache& validation_cache, ValidationCache& validation_cache,
std::vector<CScriptCheck>* pvChecks = nullptr) std::vector<CScriptCheck>* pvChecks = nullptr)
@ -262,9 +262,6 @@ bool CheckSequenceLocksAtTip(CBlockIndex* tip,
return EvaluateSequenceLocks(index, {lock_points.height, lock_points.time}); return EvaluateSequenceLocks(index, {lock_points.height, lock_points.time});
} }
// Returns the script flags which should be checked for a given block
static unsigned int GetBlockScriptFlags(const CBlockIndex& block_index, const ChainstateManager& chainman);
static void LimitMempoolSize(CTxMemPool& pool, CCoinsViewCache& coins_cache) static void LimitMempoolSize(CTxMemPool& pool, CCoinsViewCache& coins_cache)
EXCLUSIVE_LOCKS_REQUIRED(::cs_main, pool.cs) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, pool.cs)
{ {
@ -398,7 +395,7 @@ void Chainstate::MaybeUpdateMempoolForReorg(
* */ * */
static bool CheckInputsFromMempoolAndCache(const CTransaction& tx, TxValidationState& state, static bool CheckInputsFromMempoolAndCache(const CTransaction& tx, TxValidationState& state,
const CCoinsViewCache& view, const CTxMemPool& pool, const CCoinsViewCache& view, const CTxMemPool& pool,
unsigned int flags, PrecomputedTransactionData& txdata, CCoinsViewCache& coins_tip, script_verify_flags flags, PrecomputedTransactionData& txdata, CCoinsViewCache& coins_tip,
ValidationCache& validation_cache) ValidationCache& validation_cache)
EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs)
{ {
@ -1251,7 +1248,7 @@ bool MemPoolAccept::PolicyScriptChecks(const ATMPArgs& args, Workspace& ws)
const CTransaction& tx = *ws.m_ptx; const CTransaction& tx = *ws.m_ptx;
TxValidationState& state = ws.m_state; TxValidationState& state = ws.m_state;
constexpr unsigned int scriptVerifyFlags = STANDARD_SCRIPT_VERIFY_FLAGS; constexpr script_verify_flags scriptVerifyFlags = STANDARD_SCRIPT_VERIFY_FLAGS;
// Check input scripts and signatures. // Check input scripts and signatures.
// This is done last to help prevent CPU exhaustion denial-of-service attacks. // This is done last to help prevent CPU exhaustion denial-of-service attacks.
@ -1290,7 +1287,7 @@ bool MemPoolAccept::ConsensusScriptChecks(const ATMPArgs& args, Workspace& ws)
// There is a similar check in CreateNewBlock() to prevent creating // There is a similar check in CreateNewBlock() to prevent creating
// invalid blocks (using TestBlockValidity), however allowing such // invalid blocks (using TestBlockValidity), however allowing such
// transactions into the mempool can be exploited as a DoS attack. // transactions into the mempool can be exploited as a DoS attack.
unsigned int currentBlockScriptVerifyFlags{GetBlockScriptFlags(*m_active_chainstate.m_chain.Tip(), m_active_chainstate.m_chainman)}; script_verify_flags currentBlockScriptVerifyFlags{GetBlockScriptFlags(*m_active_chainstate.m_chain.Tip(), m_active_chainstate.m_chainman)};
if (!CheckInputsFromMempoolAndCache(tx, state, m_view, m_pool, currentBlockScriptVerifyFlags, if (!CheckInputsFromMempoolAndCache(tx, state, m_view, m_pool, currentBlockScriptVerifyFlags,
ws.m_precomputed_txdata, m_active_chainstate.CoinsTip(), GetValidationCache())) { ws.m_precomputed_txdata, m_active_chainstate.CoinsTip(), GetValidationCache())) {
LogPrintf("BUG! PLEASE REPORT THIS! CheckInputScripts failed against latest-block but not STANDARD flags %s, %s\n", hash.ToString(), state.ToString()); LogPrintf("BUG! PLEASE REPORT THIS! CheckInputScripts failed against latest-block but not STANDARD flags %s, %s\n", hash.ToString(), state.ToString());
@ -2098,7 +2095,7 @@ std::optional<std::pair<ScriptError, std::string>> CScriptCheck::operator()() {
const CScript &scriptSig = ptxTo->vin[nIn].scriptSig; const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;
const CScriptWitness *witness = &ptxTo->vin[nIn].scriptWitness; const CScriptWitness *witness = &ptxTo->vin[nIn].scriptWitness;
ScriptError error{SCRIPT_ERR_UNKNOWN_ERROR}; ScriptError error{SCRIPT_ERR_UNKNOWN_ERROR};
if (VerifyScript(scriptSig, m_tx_out.scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, m_tx_out.nValue, cacheStore, *m_signature_cache, *txdata), &error)) { if (VerifyScript(scriptSig, m_tx_out.scriptPubKey, witness, m_flags, CachingTransactionSignatureChecker(ptxTo, nIn, m_tx_out.nValue, cacheStore, *m_signature_cache, *txdata), &error)) {
return std::nullopt; return std::nullopt;
} else { } else {
auto debug_str = strprintf("input %i of %s (wtxid %s), spending %s:%i", nIn, ptxTo->GetHash().ToString(), ptxTo->GetWitnessHash().ToString(), ptxTo->vin[nIn].prevout.hash.ToString(), ptxTo->vin[nIn].prevout.n); auto debug_str = strprintf("input %i of %s (wtxid %s), spending %s:%i", nIn, ptxTo->GetHash().ToString(), ptxTo->GetWitnessHash().ToString(), ptxTo->vin[nIn].prevout.hash.ToString(), ptxTo->vin[nIn].prevout.n);
@ -2142,7 +2139,7 @@ ValidationCache::ValidationCache(const size_t script_execution_cache_bytes, cons
* Non-static (and redeclared) in src/test/txvalidationcache_tests.cpp * Non-static (and redeclared) in src/test/txvalidationcache_tests.cpp
*/ */
bool CheckInputScripts(const CTransaction& tx, TxValidationState& state, bool CheckInputScripts(const CTransaction& tx, TxValidationState& state,
const CCoinsViewCache& inputs, unsigned int flags, bool cacheSigStore, const CCoinsViewCache& inputs, script_verify_flags flags, bool cacheSigStore,
bool cacheFullScriptStore, PrecomputedTransactionData& txdata, bool cacheFullScriptStore, PrecomputedTransactionData& txdata,
ValidationCache& validation_cache, ValidationCache& validation_cache,
std::vector<CScriptCheck>* pvChecks) std::vector<CScriptCheck>* pvChecks)
@ -2330,7 +2327,7 @@ DisconnectResult Chainstate::DisconnectBlock(const CBlock& block, const CBlockIn
return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN; return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN;
} }
static unsigned int GetBlockScriptFlags(const CBlockIndex& block_index, const ChainstateManager& chainman) script_verify_flags GetBlockScriptFlags(const CBlockIndex& block_index, const ChainstateManager& chainman)
{ {
const Consensus::Params& consensusparams = chainman.GetConsensus(); const Consensus::Params& consensusparams = chainman.GetConsensus();
@ -2342,7 +2339,7 @@ static unsigned int GetBlockScriptFlags(const CBlockIndex& block_index, const Ch
// mainnet. // mainnet.
// For simplicity, always leave P2SH+WITNESS+TAPROOT on except for the two // For simplicity, always leave P2SH+WITNESS+TAPROOT on except for the two
// violating blocks. // violating blocks.
uint32_t flags{SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_TAPROOT}; script_verify_flags flags{SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_TAPROOT};
const auto it{consensusparams.script_flag_exceptions.find(*Assert(block_index.phashBlock))}; const auto it{consensusparams.script_flag_exceptions.find(*Assert(block_index.phashBlock))};
if (it != consensusparams.script_flag_exceptions.end()) { if (it != consensusparams.script_flag_exceptions.end()) {
flags = it->second; flags = it->second;
@ -2556,7 +2553,7 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
} }
// Get the script flags for this block // Get the script flags for this block
unsigned int flags{GetBlockScriptFlags(*pindex, m_chainman)}; script_verify_flags flags{GetBlockScriptFlags(*pindex, m_chainman)};
const auto time_2{SteadyClock::now()}; const auto time_2{SteadyClock::now()};
m_chainman.time_forks += time_2 - time_1; m_chainman.time_forks += time_2 - time_1;

View File

@ -23,6 +23,7 @@
#include <policy/policy.h> #include <policy/policy.h>
#include <script/script_error.h> #include <script/script_error.h>
#include <script/sigcache.h> #include <script/sigcache.h>
#include <script/verify_flags.h>
#include <sync.h> #include <sync.h>
#include <txdb.h> #include <txdb.h>
#include <txmempool.h> #include <txmempool.h>
@ -336,14 +337,14 @@ private:
CTxOut m_tx_out; CTxOut m_tx_out;
const CTransaction *ptxTo; const CTransaction *ptxTo;
unsigned int nIn; unsigned int nIn;
unsigned int nFlags; script_verify_flags m_flags;
bool cacheStore; bool cacheStore;
PrecomputedTransactionData *txdata; PrecomputedTransactionData *txdata;
SignatureCache* m_signature_cache; SignatureCache* m_signature_cache;
public: public:
CScriptCheck(const CTxOut& outIn, const CTransaction& txToIn, SignatureCache& signature_cache, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn, PrecomputedTransactionData* txdataIn) : CScriptCheck(const CTxOut& outIn, const CTransaction& txToIn, SignatureCache& signature_cache, unsigned int nInIn, script_verify_flags flags, bool cacheIn, PrecomputedTransactionData* txdataIn) :
m_tx_out(outIn), ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), txdata(txdataIn), m_signature_cache(&signature_cache) { } m_tx_out(outIn), ptxTo(&txToIn), nIn(nInIn), m_flags(flags), cacheStore(cacheIn), txdata(txdataIn), m_signature_cache(&signature_cache) { }
CScriptCheck(const CScriptCheck&) = delete; CScriptCheck(const CScriptCheck&) = delete;
CScriptCheck& operator=(const CScriptCheck&) = delete; CScriptCheck& operator=(const CScriptCheck&) = delete;
@ -1365,4 +1366,7 @@ bool IsBIP30Repeat(const CBlockIndex& block_index);
/** Identifies blocks which coinbase output was subsequently overwritten in the UTXO set (see BIP30) */ /** Identifies blocks which coinbase output was subsequently overwritten in the UTXO set (see BIP30) */
bool IsBIP30Unspendable(const uint256& block_hash, int block_height); bool IsBIP30Unspendable(const uint256& block_hash, int block_height);
// Returns the script flags which should be checked for a given block
script_verify_flags GetBlockScriptFlags(const CBlockIndex& block_index, const ChainstateManager& chainman);
#endif // BITCOIN_VALIDATION_H #endif // BITCOIN_VALIDATION_H

View File

@ -213,6 +213,7 @@ class BlockchainTest(BitcoinTestFramework):
assert_equal(gdi_result, { assert_equal(gdi_result, {
"hash": blockhash, "hash": blockhash,
"height": height, "height": height,
"script_flags": ["CHECKLOCKTIMEVERIFY","CHECKSEQUENCEVERIFY","DERSIG","NULLDUMMY","P2SH","TAPROOT","WITNESS"],
"deployments": { "deployments": {
'bip34': {'type': 'buried', 'active': True, 'height': 2}, 'bip34': {'type': 'buried', 'active': True, 'height': 2},
'bip66': {'type': 'buried', 'active': True, 'height': 3}, 'bip66': {'type': 'buried', 'active': True, 'height': 3},