From b40d10787b2dc161e236e50eb296bdf02f93933f Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Wed, 21 Jun 2023 10:13:08 +0200 Subject: util: Allow std::byte and char Span serialization Github-Pull: bitcoin/bitcoin#27927 Rebased-From: fa257bc8312b91c2d281f48ca2500d9cba353cc5 --- src/serialize.h | 7 ++++--- src/test/serialize_tests.cpp | 9 +++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/serialize.h b/src/serialize.h index 7bc7b10779..348a6ae4f1 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -188,6 +188,7 @@ template const X& ReadWriteAsHelper(const X& x) { return x; } } \ FORMATTER_METHODS(cls, obj) +// clang-format off #ifndef CHAR_EQUALS_INT8 template void Serialize(Stream&, char) = delete; // char serialization forbidden. Use uint8_t or int8_t #endif @@ -201,8 +202,7 @@ template inline void Serialize(Stream& s, int64_t a ) { ser_wri template inline void Serialize(Stream& s, uint64_t a) { ser_writedata64(s, a); } template inline void Serialize(Stream& s, const char (&a)[N]) { s.write(MakeByteSpan(a)); } template inline void Serialize(Stream& s, const unsigned char (&a)[N]) { s.write(MakeByteSpan(a)); } -template inline void Serialize(Stream& s, const Span& span) { s.write(AsBytes(span)); } -template inline void Serialize(Stream& s, const Span& span) { s.write(AsBytes(span)); } +template void Serialize(Stream& s, Span span) { (void)/* force byte-type */UCharCast(span.data()); s.write(AsBytes(span)); } #ifndef CHAR_EQUALS_INT8 template void Unserialize(Stream&, char) = delete; // char serialization forbidden. Use uint8_t or int8_t @@ -217,10 +217,11 @@ template inline void Unserialize(Stream& s, int64_t& a ) { a = template inline void Unserialize(Stream& s, uint64_t& a) { a = ser_readdata64(s); } template inline void Unserialize(Stream& s, char (&a)[N]) { s.read(MakeWritableByteSpan(a)); } template inline void Unserialize(Stream& s, unsigned char (&a)[N]) { s.read(MakeWritableByteSpan(a)); } -template inline void Unserialize(Stream& s, Span& span) { s.read(AsWritableBytes(span)); } +template void Unserialize(Stream& s, Span span) { (void)/* force byte-type */UCharCast(span.data()); s.read(AsWritableBytes(span)); } template inline void Serialize(Stream& s, bool a) { uint8_t f = a; ser_writedata8(s, f); } template inline void Unserialize(Stream& s, bool& a) { uint8_t f = ser_readdata8(s); a = f; } +// clang-format on /** diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp index 09f77d2b61..88543a8aef 100644 --- a/src/test/serialize_tests.cpp +++ b/src/test/serialize_tests.cpp @@ -241,6 +241,15 @@ BOOST_AUTO_TEST_CASE(class_methods) ss2 << intval << boolval << stringval << charstrval << txval; ss2 >> methodtest3; BOOST_CHECK(methodtest3 == methodtest4); + { + DataStream ds; + const std::string in{"ab"}; + ds << Span{in}; + std::array out; + ds >> Span{out}; + BOOST_CHECK_EQUAL(out.at(0), std::byte{'a'}); + BOOST_CHECK_EQUAL(out.at(1), std::byte{'b'}); + } } BOOST_AUTO_TEST_SUITE_END() -- cgit v1.2.3 From 6acfc4324cc98a10e083e5f391435bbfde4d8f69 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Thu, 22 Jun 2023 17:02:28 +0200 Subject: Use only Span{} constructor for byte-like types where possible This removes bloat that is not needed. Github-Pull: bitcoin/bitcoin#27927 Rebased-From: fa38d862358b87219b12bf31236c52f28d9fc5d6 --- src/bench/load_external.cpp | 2 +- src/net.cpp | 4 ++-- src/pubkey.h | 4 ++-- src/test/fuzz/p2p_transport_serialization.cpp | 2 +- src/test/serialize_tests.cpp | 14 +++++++------- src/uint256.h | 2 +- src/wallet/dump.cpp | 12 ++++++------ src/wallet/wallet.cpp | 4 +--- src/wallet/walletdb.cpp | 2 +- 9 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/bench/load_external.cpp b/src/bench/load_external.cpp index 0fd842c7c3..c6883af6d1 100644 --- a/src/bench/load_external.cpp +++ b/src/bench/load_external.cpp @@ -33,7 +33,7 @@ static void LoadExternalBlockFile(benchmark::Bench& bench) ss << static_cast(benchmark::data::block413567.size()); // We can't use the streaming serialization (ss << benchmark::data::block413567) // because that first writes a compact size. - ss.write(MakeByteSpan(benchmark::data::block413567)); + ss << Span{benchmark::data::block413567}; // Create the test file. { diff --git a/src/net.cpp b/src/net.cpp index 903fedb2fb..39b6200a0e 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2939,13 +2939,13 @@ void CaptureMessageToFile(const CAddress& addr, AutoFile f{fsbridge::fopen(path, "ab")}; ser_writedata64(f, now.count()); - f.write(MakeByteSpan(msg_type)); + f << Span{msg_type}; for (auto i = msg_type.length(); i < CMessageHeader::COMMAND_SIZE; ++i) { f << uint8_t{'\0'}; } uint32_t size = data.size(); ser_writedata32(f, size); - f.write(AsBytes(data)); + f << data; } std::function void Unserialize(Stream& s) { const unsigned int len(::ReadCompactSize(s)); if (len <= SIZE) { - s.read(AsWritableBytes(Span{vch, len})); + s >> Span{vch, len}; if (len != size()) { Invalidate(); } diff --git a/src/test/fuzz/p2p_transport_serialization.cpp b/src/test/fuzz/p2p_transport_serialization.cpp index 96254aa222..098498bffd 100644 --- a/src/test/fuzz/p2p_transport_serialization.cpp +++ b/src/test/fuzz/p2p_transport_serialization.cpp @@ -76,7 +76,7 @@ FUZZ_TARGET_INIT(p2p_transport_serialization, initialize_p2p_transport_serializa assert(msg.m_time == m_time); std::vector header; - auto msg2 = CNetMsgMaker{msg.m_recv.GetVersion()}.Make(msg.m_type, MakeUCharSpan(msg.m_recv)); + auto msg2 = CNetMsgMaker{msg.m_recv.GetVersion()}.Make(msg.m_type, Span{msg.m_recv}); serializer.prepareForTransport(msg2, header); } } diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp index 88543a8aef..b445ff8ffc 100644 --- a/src/test/serialize_tests.cpp +++ b/src/test/serialize_tests.cpp @@ -186,32 +186,32 @@ BOOST_AUTO_TEST_CASE(noncanonical) std::vector::size_type n; // zero encoded with three bytes: - ss.write(MakeByteSpan("\xfd\x00\x00").first(3)); + ss << Span{"\xfd\x00\x00"}.first(3); BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException); // 0xfc encoded with three bytes: - ss.write(MakeByteSpan("\xfd\xfc\x00").first(3)); + ss << Span{"\xfd\xfc\x00"}.first(3); BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException); // 0xfd encoded with three bytes is OK: - ss.write(MakeByteSpan("\xfd\xfd\x00").first(3)); + ss << Span{"\xfd\xfd\x00"}.first(3); n = ReadCompactSize(ss); BOOST_CHECK(n == 0xfd); // zero encoded with five bytes: - ss.write(MakeByteSpan("\xfe\x00\x00\x00\x00").first(5)); + ss << Span{"\xfe\x00\x00\x00\x00"}.first(5); BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException); // 0xffff encoded with five bytes: - ss.write(MakeByteSpan("\xfe\xff\xff\x00\x00").first(5)); + ss << Span{"\xfe\xff\xff\x00\x00"}.first(5); BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException); // zero encoded with nine bytes: - ss.write(MakeByteSpan("\xff\x00\x00\x00\x00\x00\x00\x00\x00").first(9)); + ss << Span{"\xff\x00\x00\x00\x00\x00\x00\x00\x00"}.first(9); BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException); // 0x01ffffff encoded with nine bytes: - ss.write(MakeByteSpan("\xff\xff\xff\xff\x01\x00\x00\x00\x00").first(9)); + ss << Span{"\xff\xff\xff\xff\x01\x00\x00\x00\x00"}.first(9); BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException); } diff --git a/src/uint256.h b/src/uint256.h index 1cc3721487..135907dcf7 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -77,7 +77,7 @@ public: template void Serialize(Stream& s) const { - s.write(MakeByteSpan(m_data)); + s << Span(m_data); } template diff --git a/src/wallet/dump.cpp b/src/wallet/dump.cpp index 31b6eb4ae1..15a3d2b7e1 100644 --- a/src/wallet/dump.cpp +++ b/src/wallet/dump.cpp @@ -57,12 +57,12 @@ bool DumpWallet(const ArgsManager& args, CWallet& wallet, bilingual_str& error) // Write out a magic string with version std::string line = strprintf("%s,%u\n", DUMP_MAGIC, DUMP_VERSION); dump_file.write(line.data(), line.size()); - hasher.write(MakeByteSpan(line)); + hasher << Span{line}; // Write out the file format line = strprintf("%s,%s\n", "format", db.Format()); dump_file.write(line.data(), line.size()); - hasher.write(MakeByteSpan(line)); + hasher << Span{line}; if (ret) { @@ -83,7 +83,7 @@ bool DumpWallet(const ArgsManager& args, CWallet& wallet, bilingual_str& error) std::string value_str = HexStr(ss_value); line = strprintf("%s,%s\n", key_str, value_str); dump_file.write(line.data(), line.size()); - hasher.write(MakeByteSpan(line)); + hasher << Span{line}; } } @@ -160,7 +160,7 @@ bool CreateFromDump(const ArgsManager& args, const std::string& name, const fs:: return false; } std::string magic_hasher_line = strprintf("%s,%s\n", magic_key, version_value); - hasher.write(MakeByteSpan(magic_hasher_line)); + hasher << Span{magic_hasher_line}; // Get the stored file format std::string format_key; @@ -191,7 +191,7 @@ bool CreateFromDump(const ArgsManager& args, const std::string& name, const fs:: warnings.push_back(strprintf(_("Warning: Dumpfile wallet format \"%s\" does not match command line specified format \"%s\"."), format_value, file_format)); } std::string format_hasher_line = strprintf("%s,%s\n", format_key, format_value); - hasher.write(MakeByteSpan(format_hasher_line)); + hasher << Span{format_hasher_line}; DatabaseOptions options; DatabaseStatus status; @@ -236,7 +236,7 @@ bool CreateFromDump(const ArgsManager& args, const std::string& name, const fs:: } std::string line = strprintf("%s,%s\n", key, value); - hasher.write(MakeByteSpan(line)); + hasher << Span{line}; if (key.empty() || value.empty()) { continue; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 07bc742090..0d664a4539 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3863,9 +3863,7 @@ bool CWallet::MigrateToSQLite(bilingual_str& error) bool began = batch->TxnBegin(); assert(began); // This is a critical error, the new db could not be written to. The original db exists as a backup, but we should not continue execution. for (const auto& [key, value] : records) { - DataStream ss_key{key}; - DataStream ss_value{value}; - if (!batch->Write(ss_key, ss_value)) { + if (!batch->Write(Span{key}, Span{value})) { batch->TxnAbort(); m_database->Close(); fs::remove(m_database->Filename()); diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index c8e8ce4614..460a5bad59 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -1132,7 +1132,7 @@ bool WalletBatch::EraseRecords(const std::unordered_set& types) } // Make a copy of key to avoid data being deleted by the following read of the type - Span key_data = MakeUCharSpan(key); + Span key_data{key}; std::string type; key >> type; -- cgit v1.2.3 From cf0f43ee42f0bf8d345b109b0ba552faf7cb62e1 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Thu, 4 Jan 2024 12:18:07 +0100 Subject: wallet: Fix use-after-free in WalletBatch::EraseRecords Github-Pull: bitcoin/bitcoin#29176 Rebased-From: faebf1df2afe207f5d2d4f73f50ac66824fe34bb --- src/wallet/walletdb.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 460a5bad59..4f04cdf912 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -1132,13 +1132,13 @@ bool WalletBatch::EraseRecords(const std::unordered_set& types) } // Make a copy of key to avoid data being deleted by the following read of the type - Span key_data{key}; + const SerializeData key_data{key.begin(), key.end()}; std::string type; key >> type; if (types.count(type) > 0) { - m_batch->Erase(key_data); + m_batch->Erase(Span{key_data}); } } return true; -- cgit v1.2.3 From 65c617178420d5904fd43399eb3c87e00aff524e Mon Sep 17 00:00:00 2001 From: Ava Chow Date: Wed, 21 Feb 2024 18:39:11 -0500 Subject: build: Bump to 25.2rc1 --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 5fcb4212ff..9e2af8d8b5 100644 --- a/configure.ac +++ b/configure.ac @@ -1,8 +1,8 @@ AC_PREREQ([2.69]) define(_CLIENT_VERSION_MAJOR, 25) -define(_CLIENT_VERSION_MINOR, 1) +define(_CLIENT_VERSION_MINOR, 2) define(_CLIENT_VERSION_BUILD, 0) -define(_CLIENT_VERSION_RC, 0) +define(_CLIENT_VERSION_RC, 1) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2023) define(_COPYRIGHT_HOLDERS,[The %s developers]) -- cgit v1.2.3 From a27662b16a626ade5f26613e9f5323edcd6e9105 Mon Sep 17 00:00:00 2001 From: Ava Chow Date: Wed, 21 Feb 2024 18:48:50 -0500 Subject: doc: update manpages for 25.2rc1 --- doc/man/bitcoin-cli.1 | 6 +++--- doc/man/bitcoin-qt.1 | 8 ++++---- doc/man/bitcoin-tx.1 | 6 +++--- doc/man/bitcoin-util.1 | 6 +++--- doc/man/bitcoin-wallet.1 | 6 +++--- doc/man/bitcoind.1 | 8 ++++---- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/doc/man/bitcoin-cli.1 b/doc/man/bitcoin-cli.1 index 571b5f75de..2dbe83068e 100644 --- a/doc/man/bitcoin-cli.1 +++ b/doc/man/bitcoin-cli.1 @@ -1,7 +1,7 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH BITCOIN-CLI "1" "October 2023" "bitcoin-cli v25.1.0" "User Commands" +.TH BITCOIN-CLI "1" "February 2024" "bitcoin-cli v25.2.0rc1" "User Commands" .SH NAME -bitcoin-cli \- manual page for bitcoin-cli v25.1.0 +bitcoin-cli \- manual page for bitcoin-cli v25.2.0rc1 .SH SYNOPSIS .B bitcoin-cli [\fI\,options\/\fR] \fI\, \/\fR[\fI\,params\/\fR] \fI\,Send command to Bitcoin Core\/\fR @@ -15,7 +15,7 @@ bitcoin-cli \- manual page for bitcoin-cli v25.1.0 .B bitcoin-cli [\fI\,options\/\fR] \fI\,help Get help for a command\/\fR .SH DESCRIPTION -Bitcoin Core RPC client version v25.1.0 +Bitcoin Core RPC client version v25.2.0rc1 .SH OPTIONS .HP \-? diff --git a/doc/man/bitcoin-qt.1 b/doc/man/bitcoin-qt.1 index c2d3f73d57..4204d5ca73 100644 --- a/doc/man/bitcoin-qt.1 +++ b/doc/man/bitcoin-qt.1 @@ -1,12 +1,12 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH BITCOIN-QT "1" "October 2023" "bitcoin-qt v25.1.0" "User Commands" +.TH BITCOIN-QT "1" "February 2024" "bitcoin-qt v25.2.0rc1" "User Commands" .SH NAME -bitcoin-qt \- manual page for bitcoin-qt v25.1.0 +bitcoin-qt \- manual page for bitcoin-qt v25.2.0rc1 .SH SYNOPSIS .B bitcoin-qt [\fI\,command-line options\/\fR] .SH DESCRIPTION -Bitcoin Core version v25.1.0 +Bitcoin Core version v25.2.0rc1 .SH OPTIONS .HP \-? @@ -116,7 +116,7 @@ Do not keep transactions in the mempool longer than hours (default: .HP \fB\-par=\fR .IP -Set the number of script verification threads (\fB\-10\fR to 15, 0 = auto, <0 = +Set the number of script verification threads (\fB\-64\fR to 15, 0 = auto, <0 = leave that many cores free, default: 0) .HP \fB\-persistmempool\fR diff --git a/doc/man/bitcoin-tx.1 b/doc/man/bitcoin-tx.1 index 75fe2fb1a1..b97f1bd9aa 100644 --- a/doc/man/bitcoin-tx.1 +++ b/doc/man/bitcoin-tx.1 @@ -1,7 +1,7 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH BITCOIN-TX "1" "October 2023" "bitcoin-tx v25.1.0" "User Commands" +.TH BITCOIN-TX "1" "February 2024" "bitcoin-tx v25.2.0rc1" "User Commands" .SH NAME -bitcoin-tx \- manual page for bitcoin-tx v25.1.0 +bitcoin-tx \- manual page for bitcoin-tx v25.2.0rc1 .SH SYNOPSIS .B bitcoin-tx [\fI\,options\/\fR] \fI\, \/\fR[\fI\,commands\/\fR] \fI\,Update hex-encoded bitcoin transaction\/\fR @@ -9,7 +9,7 @@ bitcoin-tx \- manual page for bitcoin-tx v25.1.0 .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 v25.1.0 +Bitcoin Core bitcoin\-tx utility version v25.2.0rc1 .SH OPTIONS .HP \-? diff --git a/doc/man/bitcoin-util.1 b/doc/man/bitcoin-util.1 index 0e04024173..02593581c1 100644 --- a/doc/man/bitcoin-util.1 +++ b/doc/man/bitcoin-util.1 @@ -1,12 +1,12 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH BITCOIN-UTIL "1" "October 2023" "bitcoin-util v25.1.0" "User Commands" +.TH BITCOIN-UTIL "1" "February 2024" "bitcoin-util v25.2.0rc1" "User Commands" .SH NAME -bitcoin-util \- manual page for bitcoin-util v25.1.0 +bitcoin-util \- manual page for bitcoin-util v25.2.0rc1 .SH SYNOPSIS .B bitcoin-util [\fI\,options\/\fR] [\fI\,commands\/\fR] \fI\,Do stuff\/\fR .SH DESCRIPTION -Bitcoin Core bitcoin\-util utility version v25.1.0 +Bitcoin Core bitcoin\-util utility version v25.2.0rc1 .SH OPTIONS .HP \-? diff --git a/doc/man/bitcoin-wallet.1 b/doc/man/bitcoin-wallet.1 index ef063c90b0..dda630ff6a 100644 --- a/doc/man/bitcoin-wallet.1 +++ b/doc/man/bitcoin-wallet.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH BITCOIN-WALLET "1" "October 2023" "bitcoin-wallet v25.1.0" "User Commands" +.TH BITCOIN-WALLET "1" "February 2024" "bitcoin-wallet v25.2.0rc1" "User Commands" .SH NAME -bitcoin-wallet \- manual page for bitcoin-wallet v25.1.0 +bitcoin-wallet \- manual page for bitcoin-wallet v25.2.0rc1 .SH DESCRIPTION -Bitcoin Core bitcoin\-wallet version v25.1.0 +Bitcoin Core bitcoin\-wallet version v25.2.0rc1 .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. diff --git a/doc/man/bitcoind.1 b/doc/man/bitcoind.1 index d833621ad9..30fe309972 100644 --- a/doc/man/bitcoind.1 +++ b/doc/man/bitcoind.1 @@ -1,12 +1,12 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH BITCOIND "1" "October 2023" "bitcoind v25.1.0" "User Commands" +.TH BITCOIND "1" "February 2024" "bitcoind v25.2.0rc1" "User Commands" .SH NAME -bitcoind \- manual page for bitcoind v25.1.0 +bitcoind \- manual page for bitcoind v25.2.0rc1 .SH SYNOPSIS .B bitcoind [\fI\,options\/\fR] \fI\,Start Bitcoin Core\/\fR .SH DESCRIPTION -Bitcoin Core version v25.1.0 +Bitcoin Core version v25.2.0rc1 .SH OPTIONS .HP \-? @@ -116,7 +116,7 @@ Do not keep transactions in the mempool longer than hours (default: .HP \fB\-par=\fR .IP -Set the number of script verification threads (\fB\-10\fR to 15, 0 = auto, <0 = +Set the number of script verification threads (\fB\-64\fR to 15, 0 = auto, <0 = leave that many cores free, default: 0) .HP \fB\-persistmempool\fR -- cgit v1.2.3 From 9f13dc1ed3020d55ba79b1a62ca0db6b510357ab Mon Sep 17 00:00:00 2001 From: Ava Chow Date: Wed, 21 Feb 2024 18:52:41 -0500 Subject: doc: Update release notes for 25.2rc1 --- doc/release-notes.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index fdca90f36f..eb85c31a6b 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -1,9 +1,9 @@ -25.x Release Notes +25.2rc1 Release Notes ================== -Bitcoin Core version 25.x is now available from: +Bitcoin Core version 25.2rc1 is now available from: - + This release includes various bug fixes and performance improvements, as well as updated translations. @@ -48,6 +48,10 @@ Notable changes - #29003 rpc: fix getrawtransaction segfault +### Wallet + +- #29176 wallet: Fix use-after-free in WalletBatch::EraseRecords + Credits ======= @@ -55,6 +59,7 @@ Thanks to everyone who directly contributed to this release: - Martin Zumsande - Sebastian Falbesoner +- MarcoFalke As well as to everyone that helped with translations on [Transifex](https://www.transifex.com/bitcoin/bitcoin/). -- cgit v1.2.3