mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-03-15 07:52:39 +00:00
Merge bitcoin/bitcoin#34620: [28.x] backports and 28.4rc2
44e6dda745aa1e6cbb80ee1a48206dc924453170 doc: update manpages for v28.4rc2 (Ava Chow) 46ff3698f800201cf1e9fa8c18d8dfbeea00a3bc doc: Update release notes for v28.4rc2 (Ava Chow) 6cf3d8226dee8fd4ae7061b1ef0507631383070f build: bump version to v28.4rc2 (Ava Chow) 931f12dcf79d090e88bde3e671aae53cc1e7c86f doc: Update Guix install for Debian/Ubuntu (MarcoFalke) 242b9ae3f3e65419ac29caa53da6abfdc142730f QA: tool_wallet: Check that db.log is deleted with a lone legacy wallet, but not with a shared db environment (Luke Dashjr) c5d9f75c4b4a9f43e1f47f70367741c62da557b8 Bugfix: Wallet/Migration: Move backup into wallet directory when migrating from non-directory (Luke Dashjr) 6494072295154fdf3e896e892f0051afd3d1e677 Wallet/Migration: Skip moving the backup file back and forth for no reason (Luke Dashjr) 619480bd785e28b3fa251c629c7527e49edf53e6 Wallet/Migration: If loading the new watchonly or solvables wallet fails, log the correct wallet name in error message (Luke Dashjr) 29abedc97b9ca9e4ff4b9abb47ab90ea8586b327 Wallet/bdb: Safely and correctly list files only used by the single wallet (Luke Dashjr) Pull request description: Backports: * #34370 * #34671 And the rc2 release process things ACKs for top commit: willcl-ark: ACK 44e6dda745aa1e6cbb80ee1a48206dc924453170 Tree-SHA512: beb478a057b14c3ad9f1ce049f304fa1a5ff948c3492efbd39c51b9bb73a695a5382292513ee53f9ee64ecbbe6370cbbf2781bee01cf3dc262623be4110eacd8
This commit is contained in:
commit
ed80bb21e4
@ -2,7 +2,7 @@ AC_PREREQ([2.69])
|
||||
define(_CLIENT_VERSION_MAJOR, 28)
|
||||
define(_CLIENT_VERSION_MINOR, 4)
|
||||
define(_CLIENT_VERSION_BUILD, 0)
|
||||
define(_CLIENT_VERSION_RC, 1)
|
||||
define(_CLIENT_VERSION_RC, 2)
|
||||
define(_CLIENT_VERSION_IS_RELEASE, true)
|
||||
define(_COPYRIGHT_YEAR, 2026)
|
||||
define(_COPYRIGHT_HOLDERS,[The %s developers])
|
||||
|
||||
@ -71,13 +71,13 @@ https://repology.org/project/guix/versions
|
||||
|
||||
### Debian / Ubuntu
|
||||
|
||||
Guix is available as a distribution package in [Debian
|
||||
](https://packages.debian.org/search?keywords=guix) and [Ubuntu
|
||||
](https://packages.ubuntu.com/search?keywords=guix).
|
||||
Currently, the `guix` package is no longer present in recent Debian or Ubuntu
|
||||
repositories. Any other installation option mentioned in this document may be
|
||||
used.
|
||||
|
||||
To install:
|
||||
If you previously installed `guix` via `apt`, you can remove it with:
|
||||
```sh
|
||||
sudo apt install guix
|
||||
sudo apt purge guix
|
||||
```
|
||||
|
||||
### Arch Linux
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
|
||||
.TH BITCOIN-CLI "1" "February 2026" "bitcoin-cli v28.4.0rc1" "User Commands"
|
||||
.TH BITCOIN-CLI "1" "February 2026" "bitcoin-cli v28.4.0rc2" "User Commands"
|
||||
.SH NAME
|
||||
bitcoin-cli \- manual page for bitcoin-cli v28.4.0rc1
|
||||
bitcoin-cli \- manual page for bitcoin-cli v28.4.0rc2
|
||||
.SH SYNOPSIS
|
||||
.B bitcoin-cli
|
||||
[\fI\,options\/\fR] \fI\,<command> \/\fR[\fI\,params\/\fR] \fI\,Send command to Bitcoin Core\/\fR
|
||||
@ -15,7 +15,7 @@ bitcoin-cli \- manual page for bitcoin-cli v28.4.0rc1
|
||||
.B bitcoin-cli
|
||||
[\fI\,options\/\fR] \fI\,help <command> Get help for a command\/\fR
|
||||
.SH DESCRIPTION
|
||||
Bitcoin Core RPC client version v28.4.0rc1
|
||||
Bitcoin Core RPC client version v28.4.0rc2
|
||||
.SH OPTIONS
|
||||
.HP
|
||||
\-?
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
|
||||
.TH BITCOIN-QT "1" "February 2026" "bitcoin-qt v28.4.0rc1" "User Commands"
|
||||
.TH BITCOIN-QT "1" "February 2026" "bitcoin-qt v28.4.0rc2" "User Commands"
|
||||
.SH NAME
|
||||
bitcoin-qt \- manual page for bitcoin-qt v28.4.0rc1
|
||||
bitcoin-qt \- manual page for bitcoin-qt v28.4.0rc2
|
||||
.SH SYNOPSIS
|
||||
.B bitcoin-qt
|
||||
[\fI\,command-line options\/\fR] [\fI\,URI\/\fR]
|
||||
.SH DESCRIPTION
|
||||
Bitcoin Core version v28.4.0rc1
|
||||
Bitcoin Core version v28.4.0rc2
|
||||
.PP
|
||||
Optional URI is a Bitcoin address in BIP21 URI format.
|
||||
.SH OPTIONS
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
|
||||
.TH BITCOIN-TX "1" "February 2026" "bitcoin-tx v28.4.0rc1" "User Commands"
|
||||
.TH BITCOIN-TX "1" "February 2026" "bitcoin-tx v28.4.0rc2" "User Commands"
|
||||
.SH NAME
|
||||
bitcoin-tx \- manual page for bitcoin-tx v28.4.0rc1
|
||||
bitcoin-tx \- manual page for bitcoin-tx v28.4.0rc2
|
||||
.SH SYNOPSIS
|
||||
.B bitcoin-tx
|
||||
[\fI\,options\/\fR] \fI\,<hex-tx> \/\fR[\fI\,commands\/\fR] \fI\,Update hex-encoded bitcoin transaction\/\fR
|
||||
@ -9,7 +9,7 @@ bitcoin-tx \- manual page for bitcoin-tx v28.4.0rc1
|
||||
.B bitcoin-tx
|
||||
[\fI\,options\/\fR] \fI\,-create \/\fR[\fI\,commands\/\fR] \fI\,Create hex-encoded bitcoin transaction\/\fR
|
||||
.SH DESCRIPTION
|
||||
Bitcoin Core bitcoin\-tx utility version v28.4.0rc1
|
||||
Bitcoin Core bitcoin\-tx utility version v28.4.0rc2
|
||||
.SH OPTIONS
|
||||
.HP
|
||||
\-?
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
|
||||
.TH BITCOIN-UTIL "1" "February 2026" "bitcoin-util v28.4.0rc1" "User Commands"
|
||||
.TH BITCOIN-UTIL "1" "February 2026" "bitcoin-util v28.4.0rc2" "User Commands"
|
||||
.SH NAME
|
||||
bitcoin-util \- manual page for bitcoin-util v28.4.0rc1
|
||||
bitcoin-util \- manual page for bitcoin-util v28.4.0rc2
|
||||
.SH SYNOPSIS
|
||||
.B bitcoin-util
|
||||
[\fI\,options\/\fR] [\fI\,commands\/\fR] \fI\,Do stuff\/\fR
|
||||
.SH DESCRIPTION
|
||||
Bitcoin Core bitcoin\-util utility version v28.4.0rc1
|
||||
Bitcoin Core bitcoin\-util utility version v28.4.0rc2
|
||||
.SH OPTIONS
|
||||
.HP
|
||||
\-?
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
|
||||
.TH BITCOIN-WALLET "1" "February 2026" "bitcoin-wallet v28.4.0rc1" "User Commands"
|
||||
.TH BITCOIN-WALLET "1" "February 2026" "bitcoin-wallet v28.4.0rc2" "User Commands"
|
||||
.SH NAME
|
||||
bitcoin-wallet \- manual page for bitcoin-wallet v28.4.0rc1
|
||||
bitcoin-wallet \- manual page for bitcoin-wallet v28.4.0rc2
|
||||
.SH DESCRIPTION
|
||||
Bitcoin Core bitcoin\-wallet version v28.4.0rc1
|
||||
Bitcoin Core bitcoin\-wallet version v28.4.0rc2
|
||||
.PP
|
||||
bitcoin\-wallet is an offline tool for creating and interacting with Bitcoin Core wallet files.
|
||||
By default bitcoin\-wallet will act on wallets in the default mainnet wallet directory in the datadir.
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
|
||||
.TH BITCOIND "1" "February 2026" "bitcoind v28.4.0rc1" "User Commands"
|
||||
.TH BITCOIND "1" "February 2026" "bitcoind v28.4.0rc2" "User Commands"
|
||||
.SH NAME
|
||||
bitcoind \- manual page for bitcoind v28.4.0rc1
|
||||
bitcoind \- manual page for bitcoind v28.4.0rc2
|
||||
.SH SYNOPSIS
|
||||
.B bitcoind
|
||||
[\fI\,options\/\fR] \fI\,Start Bitcoin Core\/\fR
|
||||
.SH DESCRIPTION
|
||||
Bitcoin Core version v28.4.0rc1
|
||||
Bitcoin Core version v28.4.0rc2
|
||||
.SH OPTIONS
|
||||
.HP
|
||||
\-?
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
Bitcoin Core version 28.4rc1 is now available from:
|
||||
Bitcoin Core version 28.4rc2 is now available from:
|
||||
|
||||
<https://bitcoincore.org/bin/bitcoin-core-28.4/test.rc1/>
|
||||
<https://bitcoincore.org/bin/bitcoin-core-28.4/test.rc2/>
|
||||
|
||||
This release includes various bug fixes and performance
|
||||
improvements, as well as updated translations.
|
||||
@ -42,6 +42,7 @@ Notable changes
|
||||
- #34156 wallet: fix unnamed legacy wallet migration failure
|
||||
- #34215 wallettool: fix unnamed createfromdump failure walletsdir deletion
|
||||
- #34226 wallet: test: Relative wallet failed migration cleanup
|
||||
- #34370 Fix #34222 backport bugs
|
||||
|
||||
### P2P
|
||||
|
||||
@ -71,6 +72,7 @@ Thanks to everyone who directly contributed to this release:
|
||||
- fanquake
|
||||
- furszy
|
||||
- Hennadii Stepanov
|
||||
- Luke Dashjr
|
||||
- m3dwards
|
||||
- Padraic Slattery
|
||||
- SatsAndSports
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
#include <util/strencodings.h>
|
||||
#include <util/translation.h>
|
||||
|
||||
#include <set>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <db_cxx.h>
|
||||
@ -340,6 +341,53 @@ bool BerkeleyDatabase::Verify(bilingual_str& errorStr)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<fs::path> BerkeleyDatabase::Files()
|
||||
{
|
||||
std::vector<fs::path> files;
|
||||
// If the wallet is the *only* file, clean up the entire BDB environment
|
||||
constexpr auto build_files_list = [](std::vector<fs::path>& files, const std::shared_ptr<BerkeleyEnvironment>& env, const fs::path& filename) {
|
||||
if (env->m_databases.size() != 1) return false;
|
||||
|
||||
const auto env_dir = env->Directory();
|
||||
const auto db_subdir = env_dir / "database";
|
||||
if (fs::exists(db_subdir)) {
|
||||
if (!fs::is_directory(db_subdir)) return false;
|
||||
for (const auto& entry : fs::directory_iterator(db_subdir)) {
|
||||
const auto& path = entry.path().filename();
|
||||
if (!fs::PathToString(path).starts_with("log.")) {
|
||||
return false;
|
||||
}
|
||||
files.emplace_back(entry.path());
|
||||
}
|
||||
}
|
||||
const std::set<fs::path> allowed_paths = {
|
||||
filename,
|
||||
"db.log",
|
||||
".walletlock",
|
||||
"database"
|
||||
};
|
||||
for (const auto& entry : fs::directory_iterator(env_dir)) {
|
||||
const auto& path = entry.path().filename();
|
||||
if (allowed_paths.contains(path)) {
|
||||
files.emplace_back(entry.path());
|
||||
} else if (fs::is_directory(entry.path())) {
|
||||
// Subdirectories can't possibly be using this db env, and is expected if this is a non-directory wallet
|
||||
// Do not include them in Files, but still allow the env cleanup
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
try {
|
||||
if (build_files_list(files, env, m_filename)) return files;
|
||||
} catch (...) {
|
||||
// Give up building the comprehensive file list if any error occurs
|
||||
}
|
||||
// Otherwise, it's only really safe to delete the one wallet file
|
||||
return {env->Directory() / m_filename};
|
||||
}
|
||||
|
||||
void BerkeleyEnvironment::CheckpointLSN(const std::string& strFile)
|
||||
{
|
||||
dbenv->txn_checkpoint(0, 0, 0);
|
||||
|
||||
@ -132,20 +132,7 @@ public:
|
||||
/** Return path to main database filename */
|
||||
std::string Filename() override { return fs::PathToString(env->Directory() / m_filename); }
|
||||
|
||||
std::vector<fs::path> Files() override
|
||||
{
|
||||
std::vector<fs::path> files;
|
||||
files.emplace_back(env->Directory() / m_filename);
|
||||
if (env->m_databases.size() == 1) {
|
||||
files.emplace_back(env->Directory() / "db.log");
|
||||
files.emplace_back(env->Directory() / ".walletlock");
|
||||
files.emplace_back(env->Directory() / "database" / "log.0000000001");
|
||||
files.emplace_back(env->Directory() / "database");
|
||||
// Note that this list is not exhaustive as BDB may create more log files, and possibly other ones too
|
||||
// However it should be good enough for the only calls to Files()
|
||||
}
|
||||
return files;
|
||||
}
|
||||
std::vector<fs::path> Files() override;
|
||||
|
||||
std::string Format() override { return "bdb"; }
|
||||
/**
|
||||
|
||||
@ -4474,7 +4474,7 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
|
||||
to_reload = LoadWallet(context, name, /*load_on_start=*/std::nullopt, options, status, error, warnings);
|
||||
if (!to_reload) {
|
||||
LogError("Failed to load wallet '%s' after migration. Rolling back migration to preserve consistency. "
|
||||
"Error cause: %s\n", wallet_name, error.original);
|
||||
"Error cause: %s\n", name, error.original);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -4523,6 +4523,12 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
|
||||
// First change to using SQLite
|
||||
if (!local_wallet->MigrateToSQLite(error)) return util::Error{error};
|
||||
|
||||
// In case we're migrating from file to directory, move the backup into it
|
||||
this_wallet_dir = fs::absolute(fs::PathFromString(local_wallet->GetDatabase().Filename())).parent_path();
|
||||
backup_path = this_wallet_dir / backup_filename;
|
||||
fs::rename(res.backup_path, backup_path);
|
||||
res.backup_path = backup_path;
|
||||
|
||||
// Do the migration of keys and scripts for non-blank wallets, and cleanup if it fails
|
||||
success = local_wallet->IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET);
|
||||
if (!success) {
|
||||
@ -4576,9 +4582,6 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
|
||||
}
|
||||
if (!success) {
|
||||
// Migration failed, cleanup
|
||||
// Copy the backup to the actual wallet dir
|
||||
fs::path temp_backup_location = fsbridge::AbsPathJoin(GetWalletDir(), backup_filename);
|
||||
fs::rename(backup_path, temp_backup_location);
|
||||
|
||||
// Make list of wallets to cleanup
|
||||
std::vector<std::shared_ptr<CWallet>> created_wallets;
|
||||
@ -4619,16 +4622,15 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
|
||||
}
|
||||
|
||||
// Restore the backup
|
||||
DatabaseStatus status;
|
||||
std::vector<bilingual_str> warnings;
|
||||
if (!RestoreWallet(context, temp_backup_location, wallet_name, /*load_on_start=*/std::nullopt, status, error, warnings)) {
|
||||
error += _("\nUnable to restore backup of wallet.");
|
||||
// Convert the backup file to the wallet db file by renaming it and moving it into the wallet's directory.
|
||||
// Reload it into memory if the wallet was previously loaded.
|
||||
bilingual_str restore_error;
|
||||
const auto& ptr_wallet = RestoreWallet(context, backup_path, wallet_name, /*load_on_start=*/std::nullopt, status, restore_error, warnings);
|
||||
if (!restore_error.empty()) {
|
||||
error += restore_error + _("\nUnable to restore backup of wallet.");
|
||||
return util::Error{error};
|
||||
}
|
||||
|
||||
// Move the backup to the wallet dir
|
||||
fs::rename(temp_backup_location, backup_path);
|
||||
|
||||
return util::Error{error};
|
||||
}
|
||||
return res;
|
||||
|
||||
@ -411,17 +411,30 @@ class ToolWalletTest(BitcoinTestFramework):
|
||||
self.assert_raises_tool_error('Error: Checksum is not the correct size', '-wallet=badload', '-dumpfile={}'.format(bad_sum_wallet_dump), 'createfromdump')
|
||||
assert not (self.nodes[0].wallets_path / "badload").is_dir()
|
||||
if not self.options.descriptors:
|
||||
os.rename(self.nodes[0].wallets_path / "wallet.dat", self.nodes[0].wallets_path / "default.wallet.dat")
|
||||
os.rename(self.nodes[0].wallets_path / "wallet.dat", self.nodes[0].wallets_path / "../default.wallet.dat")
|
||||
(self.nodes[0].wallets_path / "db.log").unlink(missing_ok=True)
|
||||
self.assert_raises_tool_error('Error: Checksum is not the correct size', '-wallet=', '-dumpfile={}'.format(bad_sum_wallet_dump), 'createfromdump')
|
||||
assert self.nodes[0].wallets_path.exists()
|
||||
assert not (self.nodes[0].wallets_path / "wallet.dat").exists()
|
||||
if not self.options.descriptors:
|
||||
assert not (self.nodes[0].wallets_path / "db.log").exists()
|
||||
|
||||
self.log.info('Checking createfromdump with an unnamed wallet')
|
||||
self.do_tool_createfromdump("", "wallet.dump")
|
||||
assert (self.nodes[0].wallets_path / "wallet.dat").exists()
|
||||
os.unlink(self.nodes[0].wallets_path / "wallet.dat")
|
||||
if not self.options.descriptors:
|
||||
os.rename(self.nodes[0].wallets_path / "default.wallet.dat", self.nodes[0].wallets_path / "wallet.dat")
|
||||
os.rename(self.nodes[0].wallets_path / "../default.wallet.dat", self.nodes[0].wallets_path / "wallet.dat")
|
||||
|
||||
self.log.info('Checking createfromdump with multiple non-directory wallets')
|
||||
assert not (self.nodes[0].wallets_path / "wallet.dat").is_dir()
|
||||
assert (self.nodes[0].wallets_path / "db.log").exists()
|
||||
os.rename(self.nodes[0].wallets_path / "wallet.dat", self.nodes[0].wallets_path / "test.dat")
|
||||
self.assert_raises_tool_error('Error: Checksum is not the correct size', '-wallet=', '-dumpfile={}'.format(bad_sum_wallet_dump), 'createfromdump')
|
||||
assert not (self.nodes[0].wallets_path / "wallet.dat").exists()
|
||||
assert (self.nodes[0].wallets_path / "test.dat").exists()
|
||||
assert (self.nodes[0].wallets_path / "db.log").exists()
|
||||
os.rename(self.nodes[0].wallets_path / "test.dat", self.nodes[0].wallets_path / "wallet.dat")
|
||||
|
||||
def test_chainless_conflicts(self):
|
||||
self.log.info("Test wallet tool when wallet contains conflicting transactions")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user