Skip to content

Commit ceda819

Browse files
committed
Merge bitcoin/bitcoin#28060: util: Teach AutoFile how to XOR
fa633aa streams: Teach AutoFile how to XOR (MarcoFalke) 000019e Add AutoFile::detail_fread member function (MarcoFalke) fa7724b refactor: Modernize AutoFile (MarcoFalke) fa8d227 doc: Remove comments that just repeat what the code does (MarcoFalke) fafe2ca refactor: Remove redundant file check from AutoFile shift operators (MarcoFalke) 9999a49 Extract util::Xor, Add key_offset option, Add bench (MarcoFalke) Pull request description: This allows `AutoFile` to roll an XOR pattern while reading or writing to the underlying file. This is needed for bitcoin/bitcoin#28052, but can also be used in any other place. Also, there are tests, so I've split this up from the larger pull to make review easier, hopefully. ACKs for top commit: Crypt-iQ: crACK fa633aa willcl-ark: Lightly tested ACK fa633aa jamesob: reACK fa633aa ([`jamesob/ackr/28060.4.MarcoFalke.util_add_xorfile`](https://github.com/jamesob/bitcoin/tree/ackr/28060.4.MarcoFalke.util_add_xorfile)) Tree-SHA512: 6d66cad0a089a096d3f95e4f2b28bce80b349d4b76f53d09dc9a0bea4fc1b7c0652724469c37971ba27728c7d46398a4c1d289c252af4c0f83bb2fcbc6f8e90b
2 parents e5a9f2f + fa633aa commit ceda819

File tree

8 files changed

+191
-77
lines changed

8 files changed

+191
-77
lines changed

src/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,7 @@ libbitcoin_util_a_SOURCES = \
717717
logging.cpp \
718718
random.cpp \
719719
randomenv.cpp \
720+
streams.cpp \
720721
support/cleanse.cpp \
721722
sync.cpp \
722723
util/asmap.cpp \
@@ -959,6 +960,7 @@ libbitcoinkernel_la_SOURCES = \
959960
script/sigcache.cpp \
960961
script/standard.cpp \
961962
signet.cpp \
963+
streams.cpp \
962964
support/cleanse.cpp \
963965
support/lockedpool.cpp \
964966
sync.cpp \

src/Makefile.bench.include

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ bench_bench_bitcoin_SOURCES = \
5252
bench/streams_findbyte.cpp \
5353
bench/strencodings.cpp \
5454
bench/util_time.cpp \
55-
bench/verify_script.cpp
55+
bench/verify_script.cpp \
56+
bench/xor.cpp
5657

5758
nodist_bench_bench_bitcoin_SOURCES = $(GENERATED_BENCH_FILES)
5859

src/bench/bench.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#include <string>
1515
#include <vector>
1616

17-
#include <bench/nanobench.h>
17+
#include <bench/nanobench.h> // IWYU pragma: export
1818

1919
/*
2020
* Usage:

src/bench/xor.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright (c) The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or https://opensource.org/license/mit/.
4+
5+
#include <bench/bench.h>
6+
7+
#include <random.h>
8+
#include <streams.h>
9+
10+
#include <cstddef>
11+
#include <vector>
12+
13+
static void Xor(benchmark::Bench& bench)
14+
{
15+
FastRandomContext frc{/*fDeterministic=*/true};
16+
auto data{frc.randbytes<std::byte>(1024)};
17+
auto key{frc.randbytes<std::byte>(31)};
18+
19+
bench.batch(data.size()).unit("byte").run([&] {
20+
util::Xor(data, key);
21+
});
22+
}
23+
24+
BENCHMARK(Xor, benchmark::PriorityLevel::HIGH);

src/hash.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,6 @@ class CHashWriter : public HashWriter
160160

161161
template<typename T>
162162
CHashWriter& operator<<(const T& obj) {
163-
// Serialize to this stream
164163
::Serialize(*this, obj);
165164
return (*this);
166165
}
@@ -228,7 +227,6 @@ class CHashVerifier : public CHashWriter
228227
template<typename T>
229228
CHashVerifier<Source>& operator>>(T&& obj)
230229
{
231-
// Unserialize from this stream
232230
::Unserialize(*this, obj);
233231
return (*this);
234232
}

src/streams.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Copyright (c) 2009-present The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or https://opensource.org/license/mit/.
4+
5+
#include <span.h>
6+
#include <streams.h>
7+
8+
#include <array>
9+
10+
std::size_t AutoFile::detail_fread(Span<std::byte> dst)
11+
{
12+
if (!m_file) throw std::ios_base::failure("AutoFile::read: file handle is nullptr");
13+
if (m_xor.empty()) {
14+
return std::fread(dst.data(), 1, dst.size(), m_file);
15+
} else {
16+
const auto init_pos{std::ftell(m_file)};
17+
if (init_pos < 0) throw std::ios_base::failure("AutoFile::read: ftell failed");
18+
std::size_t ret{std::fread(dst.data(), 1, dst.size(), m_file)};
19+
util::Xor(dst.subspan(0, ret), m_xor, init_pos);
20+
return ret;
21+
}
22+
}
23+
24+
void AutoFile::read(Span<std::byte> dst)
25+
{
26+
if (detail_fread(dst) != dst.size()) {
27+
throw std::ios_base::failure(feof() ? "AutoFile::read: end of file" : "AutoFile::read: fread failed");
28+
}
29+
}
30+
31+
void AutoFile::ignore(size_t nSize)
32+
{
33+
if (!m_file) throw std::ios_base::failure("AutoFile::ignore: file handle is nullptr");
34+
unsigned char data[4096];
35+
while (nSize > 0) {
36+
size_t nNow = std::min<size_t>(nSize, sizeof(data));
37+
if (std::fread(data, 1, nNow, m_file) != nNow) {
38+
throw std::ios_base::failure(feof() ? "AutoFile::ignore: end of file" : "AutoFile::ignore: fread failed");
39+
}
40+
nSize -= nNow;
41+
}
42+
}
43+
44+
void AutoFile::write(Span<const std::byte> src)
45+
{
46+
if (!m_file) throw std::ios_base::failure("AutoFile::write: file handle is nullptr");
47+
if (m_xor.empty()) {
48+
if (std::fwrite(src.data(), 1, src.size(), m_file) != src.size()) {
49+
throw std::ios_base::failure("AutoFile::write: write failed");
50+
}
51+
} else {
52+
auto current_pos{std::ftell(m_file)};
53+
if (current_pos < 0) throw std::ios_base::failure("AutoFile::write: ftell failed");
54+
std::array<std::byte, 4096> buf;
55+
while (src.size() > 0) {
56+
auto buf_now{Span{buf}.first(std::min<size_t>(src.size(), buf.size()))};
57+
std::copy(src.begin(), src.begin() + buf_now.size(), buf_now.begin());
58+
util::Xor(buf_now, m_xor, current_pos);
59+
if (std::fwrite(buf_now.data(), 1, buf_now.size(), m_file) != buf_now.size()) {
60+
throw std::ios_base::failure{"XorFile::write: failed"};
61+
}
62+
src = src.subspan(buf_now.size());
63+
current_pos += buf_now.size();
64+
}
65+
}
66+
}

0 commit comments

Comments
 (0)