|
19 | 19 | #include <pow.h>
|
20 | 20 | #include <primitives/block.h>
|
21 | 21 | #include <primitives/transaction.h>
|
| 22 | +#include <random.h> |
22 | 23 | #include <reverse_iterator.h>
|
23 | 24 | #include <serialize.h>
|
24 | 25 | #include <signet.h>
|
@@ -818,13 +819,13 @@ void BlockManager::UnlinkPrunedFiles(const std::set<int>& setFilesToPrune) const
|
818 | 819 |
|
819 | 820 | AutoFile BlockManager::OpenBlockFile(const FlatFilePos& pos, bool fReadOnly) const
|
820 | 821 | {
|
821 |
| - return AutoFile{m_block_file_seq.Open(pos, fReadOnly)}; |
| 822 | + return AutoFile{m_block_file_seq.Open(pos, fReadOnly), m_xor_key}; |
822 | 823 | }
|
823 | 824 |
|
824 | 825 | /** Open an undo file (rev?????.dat) */
|
825 | 826 | AutoFile BlockManager::OpenUndoFile(const FlatFilePos& pos, bool fReadOnly) const
|
826 | 827 | {
|
827 |
| - return AutoFile{m_undo_file_seq.Open(pos, fReadOnly)}; |
| 828 | + return AutoFile{m_undo_file_seq.Open(pos, fReadOnly), m_xor_key}; |
828 | 829 | }
|
829 | 830 |
|
830 | 831 | fs::path BlockManager::GetBlockPosFilename(const FlatFilePos& pos) const
|
@@ -1144,6 +1145,54 @@ FlatFilePos BlockManager::SaveBlockToDisk(const CBlock& block, int nHeight)
|
1144 | 1145 | return blockPos;
|
1145 | 1146 | }
|
1146 | 1147 |
|
| 1148 | +static auto InitBlocksdirXorKey(const BlockManager::Options& opts) |
| 1149 | +{ |
| 1150 | + // Bytes are serialized without length indicator, so this is also the exact |
| 1151 | + // size of the XOR-key file. |
| 1152 | + std::array<std::byte, 8> xor_key{}; |
| 1153 | + |
| 1154 | + if (opts.use_xor && fs::is_empty(opts.blocks_dir)) { |
| 1155 | + // Only use random fresh key when the boolean option is set and on the |
| 1156 | + // very first start of the program. |
| 1157 | + FastRandomContext{}.fillrand(xor_key); |
| 1158 | + } |
| 1159 | + |
| 1160 | + const fs::path xor_key_path{opts.blocks_dir / "xor.dat"}; |
| 1161 | + if (fs::exists(xor_key_path)) { |
| 1162 | + // A pre-existing xor key file has priority. |
| 1163 | + AutoFile xor_key_file{fsbridge::fopen(xor_key_path, "rb")}; |
| 1164 | + xor_key_file >> xor_key; |
| 1165 | + } else { |
| 1166 | + // Create initial or missing xor key file |
| 1167 | + AutoFile xor_key_file{fsbridge::fopen(xor_key_path, |
| 1168 | +#ifdef __MINGW64__ |
| 1169 | + "wb" // Temporary workaround for https://github.com/bitcoin/bitcoin/issues/30210 |
| 1170 | +#else |
| 1171 | + "wbx" |
| 1172 | +#endif |
| 1173 | + )}; |
| 1174 | + xor_key_file << xor_key; |
| 1175 | + } |
| 1176 | + // If the user disabled the key, it must be zero. |
| 1177 | + if (!opts.use_xor && xor_key != decltype(xor_key){}) { |
| 1178 | + throw std::runtime_error{ |
| 1179 | + strprintf("The blocksdir XOR-key can not be disabled when a random key was already stored! " |
| 1180 | + "Stored key: '%s', stored path: '%s'.", |
| 1181 | + HexStr(xor_key), fs::PathToString(xor_key_path)), |
| 1182 | + }; |
| 1183 | + } |
| 1184 | + LogInfo("Using obfuscation key for blocksdir *.dat files (%s): '%s'\n", fs::PathToString(opts.blocks_dir), HexStr(xor_key)); |
| 1185 | + return std::vector<std::byte>{xor_key.begin(), xor_key.end()}; |
| 1186 | +} |
| 1187 | + |
| 1188 | +BlockManager::BlockManager(const util::SignalInterrupt& interrupt, Options opts) |
| 1189 | + : m_prune_mode{opts.prune_target > 0}, |
| 1190 | + m_xor_key{InitBlocksdirXorKey(opts)}, |
| 1191 | + m_opts{std::move(opts)}, |
| 1192 | + m_block_file_seq{FlatFileSeq{m_opts.blocks_dir, "blk", m_opts.fast_prune ? 0x4000 /* 16kB */ : BLOCKFILE_CHUNK_SIZE}}, |
| 1193 | + m_undo_file_seq{FlatFileSeq{m_opts.blocks_dir, "rev", UNDOFILE_CHUNK_SIZE}}, |
| 1194 | + m_interrupt{interrupt} {} |
| 1195 | + |
1147 | 1196 | class ImportingNow
|
1148 | 1197 | {
|
1149 | 1198 | std::atomic<bool>& m_importing;
|
|
0 commit comments