Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 47 additions & 23 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -211,11 +211,16 @@ jobs:
steps:
- *CHECKOUT

- name: Configure Developer Command Prompt for Microsoft Visual C++
# Using microsoft/setup-msbuild is not enough.
uses: ilammy/msvc-dev-cmd@v1
with:
arch: x64
- &SET_UP_VS
name: Set up VS Developer Prompt
shell: pwsh -Command "$PSVersionTable; $PSNativeCommandUseErrorActionPreference = $true; $ErrorActionPreference = 'Stop'; & '{0}'"
run: |
$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
shell: pwsh
Expand All @@ -235,7 +240,7 @@ jobs:
sed -i '1s/^/set(ENV{CMAKE_POLICY_VERSION_MINIMUM} 3.5)\n/' "${VCPKG_INSTALLATION_ROOT}/scripts/ports.cmake"

- name: vcpkg tools cache
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: C:/vcpkg/downloads/tools
key: ${{ github.job }}-vcpkg-tools
Expand Down Expand Up @@ -263,14 +268,26 @@ jobs:
run: |
cmake --build . -j $NUMBER_OF_PROCESSORS --config Release

- name: Get bitcoind manifest
- name: Check executable manifests
if: matrix.job-type == 'standard'
working-directory: build
shell: pwsh -Command "$PSVersionTable; $PSNativeCommandUseErrorActionPreference = $true; $ErrorActionPreference = 'Stop'; & '{0}'"
run: |
mt.exe -nologo -inputresource:bin/Release/bitcoind.exe -out:bitcoind.manifest
cat bitcoind.manifest
echo
mt.exe -nologo -inputresource:bin/Release/bitcoind.exe -validate_manifest
mt.exe -nologo -inputresource:bin\Release\bitcoind.exe -out:bitcoind.manifest
Get-Content bitcoind.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
if: matrix.job-type == 'standard'
Expand Down Expand Up @@ -341,7 +358,7 @@ jobs:
uses: ./.github/actions/save-caches

- name: Upload built executables
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: x86_64-w64-mingw32-executables-${{ github.run_id }}
path: |
Expand All @@ -363,26 +380,33 @@ jobs:
- *CHECKOUT

- name: Download built executables
uses: actions/download-artifact@v4
uses: actions/download-artifact@v7
with:
name: x86_64-w64-mingw32-executables-${{ github.run_id }}

- name: Run bitcoind.exe
run: ./bin/bitcoind.exe -version

- name: Find mt.exe tool
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
- *SET_UP_VS

- name: Get bitcoind manifest
shell: pwsh
- name: Check executable manifests
shell: pwsh -Command "$PSVersionTable; $PSNativeCommandUseErrorActionPreference = $true; $ErrorActionPreference = 'Stop'; & '{0}'"
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
& $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
# Can't use ctest here like other jobs as we don't have a CMake build tree.
Expand Down
10 changes: 2 additions & 8 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -479,14 +479,8 @@ configure_file(contrib/filter-lcov.py filter-lcov.py USE_SOURCE_PERMISSIONS COPY
# Don't allow extended (non-ASCII) symbols in identifiers. This is easier for code review.
try_append_cxx_flags("-fno-extended-identifiers" TARGET core_interface SKIP_LINK)

# Avoiding the `-ffile-prefix-map` compiler option because it implies
# `-fcoverage-prefix-map` on Clang or `-fprofile-prefix-map` on GCC,
# which can cause issues with coverage builds, particularly when using
# Clang in the OSS-Fuzz environment due to its use of other options
# and a third party script, or with GCC.
try_append_cxx_flags("-fdebug-prefix-map=A=B" TARGET core_interface SKIP_LINK
IF_CHECK_PASSED "-fdebug-prefix-map=${PROJECT_SOURCE_DIR}/src=."
)
# Set `-fmacro-prefix-map`, so that source file names are expanded without the
# src prefix.
try_append_cxx_flags("-fmacro-prefix-map=A=B" TARGET core_interface SKIP_LINK
IF_CHECK_PASSED "-fmacro-prefix-map=${PROJECT_SOURCE_DIR}/src=."
)
Expand Down
1 change: 1 addition & 0 deletions contrib/guix/libexec/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ CONFIGFLAGS="-DREDUCE_EXPORTS=ON -DBUILD_BENCH=OFF -DBUILD_GUI_TESTS=OFF -DBUILD
# CFLAGS
HOST_CFLAGS="-O2 -g"
HOST_CFLAGS+=$(find /gnu/store -maxdepth 1 -mindepth 1 -type d -exec echo -n " -ffile-prefix-map={}=/usr" \;)
HOST_CFLAGS+=" -fdebug-prefix-map=${DISTSRC}/src=."
case "$HOST" in
*mingw*) HOST_CFLAGS+=" -fno-ident" ;;
*darwin*) unset HOST_CFLAGS ;;
Expand Down
1 change: 1 addition & 0 deletions doc/bips.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,4 @@ BIPs that are implemented by Bitcoin Core:
* [`BIP 386`](https://github.com/bitcoin/bips/blob/master/bip-0386.mediawiki): tr() Output Script Descriptors are implemented as of **v22.0** ([PR 22051](https://github.com/bitcoin/bitcoin/pull/22051)).
* [`BIP 387`](https://github.com/bitcoin/bips/blob/master/bip-0387.mediawiki): Tapscript Multisig Output Script Descriptors are implemented as of **v24.0** ([PR 24043](https://github.com/bitcoin/bitcoin/pull/24043)).
* [`BIP 431`](https://github.com/bitcoin/bips/blob/master/bip-0431.mediawiki): transactions with nVersion=3 are standard and treated as Topologically Restricted Until Confirmation as of **v28.0** ([PR 29496](https://github.com/bitcoin/bitcoin/pull/29496)).
* [`BIP 433`](https://github.com/bitcoin/bips/blob/master/bip-0433.mediawiki): Spending of Pay to Anchor (P2A) outputs is standard as of **v28.0** ([PR 30352](https://github.com/bitcoin/bitcoin/pull/30352)).
31 changes: 0 additions & 31 deletions doc/developer-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -305,37 +305,6 @@ If you need to build exclusively for debugging, set the `-DCMAKE_BUILD_TYPE`
to `Debug` (i.e. `-DCMAKE_BUILD_TYPE=Debug`). You can always check the cmake
build options of an existing build with `ccmake build`.

### Show sources in debugging

If you have ccache enabled, absolute paths are stripped from debug information
with the `-fdebug-prefix-map` and `-fmacro-prefix-map` options (if supported by the
compiler). This might break source file detection in case you move binaries
after compilation, debug from the directory other than the project root or use
an IDE that only supports absolute paths for debugging (e.g. it won't stop at breakpoints).

There are a few possible fixes:

1. Configure source file mapping.

For `gdb` create or append to [`.gdbinit` file](https://sourceware.org/gdb/current/onlinedocs/gdb#gdbinit-man):
```
set substitute-path ./src /path/to/project/root/src
```

For `lldb` create or append to [`.lldbinit` file](https://lldb.llvm.org/man/lldb.html#configuration-files):
```
settings set target.source-map ./src /path/to/project/root/src
```

2. Add a symlink to the `./src` directory:
```
ln -s /path/to/project/root/src src
```

3. Use `debugedit` to modify debug information in the binary.

4. If your IDE has an option for this, change your breakpoints to use the file name only.

### debug.log

If the code is behaving strangely, take a look in the `debug.log` file in the data directory;
Expand Down
44 changes: 20 additions & 24 deletions doc/release-notes.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
v30.2 Release Notes
v30.x Release Notes
===================

Bitcoin Core version v30.2 is now available from:
Bitcoin Core version v30.x is now available from:

<https://bitcoincore.org/bin/bitcoin-core-30.2/>
<https://bitcoincore.org/bin/bitcoin-core-30.x/>

This release includes new features, various bug fixes and performance
improvements, as well as updated translations.
Expand Down Expand Up @@ -42,50 +42,46 @@ Notable changes

### Wallet

- #34156 wallet: fix unnamed legacy wallet migration failure
- #34215 wallettool: fix unnamed createfromdump failure walletsdir deletion
- #34221 test: migration, avoid backup name mismatch in default_wallet_failure
- #34358 wallet: fix removeprunedfunds bug with conflicting transactions

### IPC
### PSBT

- #33511 init: Fix Ctrl-C shutdown hangs during wait calls
- #34272 psbt: Fix PSBTInputSignedAndVerified bounds assert

### Build

- #33950 guix: reduce allowed exported symbols
- #34107 build: Update minimum required Boost version
- #34227 guix: Fix osslsigncode tests
- #34281 build: Temporarily remove confusing and brittle -fdebug-prefix-map

### Test

- #34137 test: Avoid hard time.sleep(1) in feature_init.py
- #34226 wallet: test: Relative wallet failed migration cleanup

### Fuzz

- #34091 fuzz: doc: remove any mention to address_deserialize_v2
- #34185 test: fix feature_pruning when built without wallet
- #34282 qa: Fix Windows logging bug
- #34390 test: allow overriding tar in get_previous_releases.py

### Doc

- #34182 doc: Update OpenBSD Build Guide
- #34252 doc: add 433 (Pay to Anchor) to bips.md
- #34413 doc: Remove outdated -fdebug-prefix-map section in dev notes

### Misc
### CI

- #34174 doc: update copyright year to 2026
- #32513 ci: remove 3rd party js from windows dll gha job
- #34344 ci: update GitHub Actions versions

Credits
=======

Thanks to everyone who directly contributed to this release:

- Ava Chow
- brunoerg
- davidgumberg
- fanquake
- furszy
- Hennadii Stepanov
- Lőrinc
- m3dwards
- MarcoFalke
- Ryan Ofsky
- mzumsande
- Padraic Slattery
- Sebastian Falbesoner

As well as to everyone that helped with translations on
[Transifex](https://explore.transifex.com/bitcoin/bitcoin/).
2 changes: 1 addition & 1 deletion src/psbt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ bool PSBTInputSigned(const PSBTInput& input)
bool PSBTInputSignedAndVerified(const PartiallySignedTransaction psbt, unsigned int input_index, const PrecomputedTransactionData* txdata)
{
CTxOut utxo;
assert(psbt.inputs.size() >= input_index);
assert(input_index < psbt.inputs.size());
const PSBTInput& input = psbt.inputs[input_index];

if (input.non_witness_utxo) {
Expand Down
11 changes: 9 additions & 2 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2383,8 +2383,15 @@ util::Result<void> CWallet::RemoveTxs(WalletBatch& batch, std::vector<Txid>& txs
for (const auto& it : erased_txs) {
const Txid hash{it->first};
wtxOrdered.erase(it->second.m_it_wtxOrdered);
for (const auto& txin : it->second.tx->vin)
mapTxSpends.erase(txin.prevout);
for (const auto& txin : it->second.tx->vin) {
auto range = mapTxSpends.equal_range(txin.prevout);
for (auto iter = range.first; iter != range.second; ++iter) {
if (iter->second == hash) {
mapTxSpends.erase(iter);
break;
}
}
}
for (unsigned int i = 0; i < it->second.tx->vout.size(); ++i) {
m_txos.erase(COutPoint(hash, i));
}
Expand Down
22 changes: 14 additions & 8 deletions test/functional/feature_pruning.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,20 +346,22 @@ def has_block(index):

self.log.info("Success")

def wallet_test(self):
def test_wallet_rescan(self):
# check that the pruning node's wallet is still in good shape
self.log.info("Stop and start pruning node to trigger wallet rescan")
self.restart_node(2, extra_args=["-prune=550"])
self.log.info("Success")

wallet_info = self.nodes[2].getwalletinfo()
self.wait_until(lambda: wallet_info["scanning"] == False)
self.wait_until(lambda: wallet_info["lastprocessedblock"]["height"] == self.nodes[2].getblockcount())

# check that wallet loads successfully when restarting a pruned node after IBD.
# this was reported to fail in #7494.
self.log.info("Syncing node 5 to test wallet")
self.connect_nodes(0, 5)
nds = [self.nodes[0], self.nodes[5]]
self.sync_blocks(nds, wait=5, timeout=300)
self.restart_node(5, extra_args=["-prune=550", "-blockfilterindex=1"]) # restart to trigger rescan
self.log.info("Success")

wallet_info = self.nodes[5].getwalletinfo()
self.wait_until(lambda: wallet_info["scanning"] == False)
self.wait_until(lambda: wallet_info["lastprocessedblock"]["height"] == self.nodes[0].getblockcount())

def run_test(self):
self.log.info("Warning! This test requires 4GB of disk space")
Expand Down Expand Up @@ -467,9 +469,13 @@ def run_test(self):
self.log.info("Test manual pruning with timestamps")
self.manual_test(4, use_timestamp=True)

self.log.info("Syncing node 5 to node 0")
self.connect_nodes(0, 5)
self.sync_blocks([self.nodes[0], self.nodes[5]], wait=5, timeout=300)

if self.is_wallet_compiled():
self.log.info("Test wallet re-scan")
self.wallet_test()
self.test_wallet_rescan()

self.log.info("Test it's not possible to rescan beyond pruned data")
self.test_rescan_blockchain()
Expand Down
2 changes: 1 addition & 1 deletion test/functional/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,7 @@ def get_next(self):
status = "Passed"
elif proc.returncode == TEST_EXIT_SKIPPED:
status = "Skipped"
skip_reason = re.search(r"Test Skipped: (.*)", stdout).group(1)
skip_reason = re.search(r"Test Skipped: (.*)", stdout).group(1).strip()
else:
status = "Failed"
self.jobs.remove(job)
Expand Down
28 changes: 28 additions & 0 deletions test/functional/wallet_importprunedfunds.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
assert_not_equal,
assert_raises_rpc_error,
wallet_importprivkey,
)
Expand Down Expand Up @@ -129,6 +130,33 @@ def run_test(self):
mb.header.nTime += 1 # modify arbitrary block header field to change block hash
assert_raises_rpc_error(-5, "Block not found in chain", w1.importprunedfunds, rawtxn1, mb.serialize().hex())

self.log.info("Test removeprunedfunds with conflicting transactions")
node = self.nodes[0]

# Create a transaction
utxo = node.listunspent()[0]
addr = node.getnewaddress()
tx1_id = node.send(outputs=[{addr: 1}], inputs=[utxo])["txid"]
tx1_fee = node.gettransaction(tx1_id)["fee"]

# Create a conflicting tx with a larger fee (tx1_fee is negative)
output_value = utxo["amount"] + tx1_fee - Decimal("0.00001")
raw_tx2 = node.createrawtransaction(inputs=[utxo], outputs=[{addr: output_value}])
signed_tx2 = node.signrawtransactionwithwallet(raw_tx2)
tx2_id = node.sendrawtransaction(signed_tx2["hex"])
assert_not_equal(tx2_id, tx1_id)

# Both txs should be in the wallet, tx2 replaced tx1 in mempool
assert tx1_id in [tx["txid"] for tx in node.listtransactions()]
assert tx2_id in [tx["txid"] for tx in node.listtransactions()]

# Remove the replaced tx from wallet
node.removeprunedfunds(tx1_id)

# The UTXO should still be considered spent (by tx2)
available_utxos = [u["txid"] for u in node.listunspent(minconf=0)]
assert utxo["txid"] not in available_utxos, "UTXO should still be spent by conflicting tx"


if __name__ == '__main__':
ImportPrunedFundsTest(__file__).main()
Loading
Loading