Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
501BOOST_CHECK(bf.SetPos(0));502bf >> i;503BOOST_CHECK_EQUAL(i, 0);504bf >> i;505BOOST_CHECK_EQUAL(i, 1);507bf.SkipTo(11);508bf >> i;509BOOST_CHECK_EQUAL(i, 11);511// SkipTo() honors the transfer limit; we can't position beyond the limit.512bf.SetLimit(13);513BOOST_CHECK_EXCEPTION(bf.SkipTo(14), std::ios_base::failure, HasReason{"Attempt to position past buffer limit"});515// We can position exactly to the transfer limit.516bf.SkipTo(13);517BOOST_CHECK_EQUAL(bf.GetPos(), 13U);519BOOST_REQUIRE_EQUAL(file.fclose(), 0);520fs::remove(streams_test_filename);521}523BOOST_AUTO_TEST_CASE(streams_buffered_file_rand)524{525// Make this test deterministic.526SeedRandomForTest(SeedRand::ZEROS);528fs::path streams_test_filename = m_args.GetDataDirBase() / "streams_test_tmp";529for (int rep = 0; rep < 50; ++rep) {530AutoFile file{fsbridge::fopen(streams_test_filename, "w+b")};531size_t fileSize = m_rng.randrange(256);532for (uint8_t i = 0; i < fileSize; ++i) {533file << i;534}535file.seek(0, SEEK_SET);537size_t bufSize = m_rng.randrange(300) + 1;538size_t rewindSize = m_rng.randrange(bufSize);539BufferedFile bf{file, bufSize, rewindSize};540size_t currentPos = 0;541size_t maxPos = 0;542for (int step = 0; step < 100; ++step) {543if (currentPos >= fileSize)544break;546// We haven't read to the end of the file yet.547BOOST_CHECK(!bf.eof());548BOOST_CHECK_EQUAL(bf.GetPos(), currentPos);550// Pretend the file consists of a series of objects of varying551// sizes; the boundaries of the objects can interact arbitrarily552// with the CBufferFile's internal buffer. These first three553// cases simulate objects of various sizes (1, 2, 5 bytes).554switch (m_rng.randrange(6)) {555case 0: {556uint8_t a[1];557if (currentPos + 1 > fileSize)558continue;559bf.SetLimit(currentPos + 1);560bf >> a;561for (uint8_t i = 0; i < 1; ++i) {562BOOST_CHECK_EQUAL(a[i], currentPos);563currentPos++;564}565break;566}567case 1: {568uint8_t a[2];569if (currentPos + 2 > fileSize)570continue;571bf.SetLimit(currentPos + 2);572bf >> a;573for (uint8_t i = 0; i < 2; ++i) {574BOOST_CHECK_EQUAL(a[i], currentPos);575currentPos++;576}577break;578}579case 2: {580uint8_t a[5];581if (currentPos + 5 > fileSize)582continue;583bf.SetLimit(currentPos + 5);584bf >> a;585for (uint8_t i = 0; i < 5; ++i) {586BOOST_CHECK_EQUAL(a[i], currentPos);587currentPos++;588}589break;590}591case 3: {592// SkipTo is similar to the "read" cases above, except593// we don't receive the data.594size_t skip_length{static_cast<size_t>(m_rng.randrange(5))};595if (currentPos + skip_length > fileSize) continue;596bf.SetLimit(currentPos + skip_length);597bf.SkipTo(currentPos + skip_length);598currentPos += skip_length;599break;600}601case 4: {602// Find a byte value (that is at or ahead of the current position).603size_t find = currentPos + m_rng.randrange(8);604if (find >= fileSize)605find = fileSize - 1;606bf.FindByte(std::byte(find));607// The value at each offset is the offset.608BOOST_CHECK_EQUAL(bf.GetPos(), find);609currentPos = find;611bf.SetLimit(currentPos + 1);612uint8_t i;613bf >> i;614BOOST_CHECK_EQUAL(i, currentPos);615currentPos++;616break;617}618case 5: {619size_t requestPos = m_rng.randrange(maxPos + 4);620bool okay = bf.SetPos(requestPos);621// The new position may differ from the requested position622// because we may not be able to rewind beyond the rewind623// window, and we may not be able to move forward beyond the624// farthest position we've reached so far.625currentPos = bf.GetPos();626BOOST_CHECK_EQUAL(okay, currentPos == requestPos);627// Check that we can position within the rewind window.628if (requestPos <= maxPos &&629maxPos > rewindSize &&630requestPos >= maxPos - rewindSize) {631// We requested a position within the rewind window.632BOOST_CHECK(okay);633}634break;635}636}637if (maxPos < currentPos)638maxPos = currentPos;639}640BOOST_REQUIRE_EQUAL(file.fclose(), 0);641}642fs::remove(streams_test_filename);643}645BOOST_AUTO_TEST_CASE(buffered_reader_matches_autofile_random_content)646{647const size_t file_size{1 + m_rng.randrange<size_t>(1 << 17)};648const size_t buf_size{1 + m_rng.randrange(file_size)};649const FlatFilePos pos{0, 0};651const FlatFileSeq test_file{m_args.GetDataDirBase(), "buffered_file_test_random", node::BLOCKFILE_CHUNK_SIZE};652const Obfuscation obfuscation{m_rng.randbytes<Obfuscation::KEY_SIZE>()};654// Write out the file with random content655{656AutoFile f{test_file.Open(pos, /*read_only=*/false), obfuscation};657f.write(m_rng.randbytes<std::byte>(file_size));658BOOST_REQUIRE_EQUAL(f.fclose(), 0);659}660BOOST_CHECK_EQUAL(fs::file_size(test_file.FileName(pos)), file_size);662{663AutoFile direct_file{test_file.Open(pos, /*read_only=*/true), obfuscation};665AutoFile buffered_file{test_file.Open(pos, /*read_only=*/true), obfuscation};666BufferedReader buffered_reader{std::move(buffered_file), buf_size};668for (size_t total_read{0}; total_read < file_size;) {669const size_t read{Assert(std::min(1 + m_rng.randrange(m_rng.randbool() ? buf_size : 2 * buf_size), file_size - total_read))};671DataBuffer direct_file_buffer{read};672direct_file.read(direct_file_buffer);674DataBuffer buffered_buffer{read};675buffered_reader.read(buffered_buffer);677BOOST_CHECK_EQUAL_COLLECTIONS(678direct_file_buffer.begin(), direct_file_buffer.end(),679buffered_buffer.begin(), buffered_buffer.end()680);682total_read += read;683}685{686DataBuffer excess_byte{1};687BOOST_CHECK_EXCEPTION(direct_file.read(excess_byte), std::ios_base::failure, HasReason{"end of file"});688}690{691DataBuffer excess_byte{1};692BOOST_CHECK_EXCEPTION(buffered_reader.read(excess_byte), std::ios_base::failure, HasReason{"end of file"});693}694}696fs::remove(test_file.FileName(pos));697}699BOOST_AUTO_TEST_CASE(buffered_writer_matches_autofile_random_content)700{701const size_t file_size{1 + m_rng.randrange<size_t>(1 << 17)};702const size_t buf_size{1 + m_rng.randrange(file_size)};703const FlatFilePos pos{0, 0};705const FlatFileSeq test_buffered{m_args.GetDataDirBase(), "buffered_write_test", node::BLOCKFILE_CHUNK_SIZE};706const FlatFileSeq test_direct{m_args.GetDataDirBase(), "direct_write_test", node::BLOCKFILE_CHUNK_SIZE};707const Obfuscation obfuscation{m_rng.randbytes<Obfuscation::KEY_SIZE>()};709{710DataBuffer test_data{m_rng.randbytes<std::byte>(file_size)};712AutoFile direct_file{test_direct.Open(pos, /*read_only=*/false), obfuscation};714AutoFile buffered_file{test_buffered.Open(pos, /*read_only=*/false), obfuscation};715{716BufferedWriter buffered{buffered_file, buf_size};718for (size_t total_written{0}; total_written < file_size;) {719const size_t write_size{Assert(std::min(1 + m_rng.randrange(m_rng.randbool() ? buf_size : 2 * buf_size), file_size - total_written))};721auto current_span = std::span{test_data}.subspan(total_written, write_size);722direct_file.write(current_span);723buffered.write(current_span);725total_written += write_size;726}727}728BOOST_REQUIRE_EQUAL(buffered_file.fclose(), 0);729BOOST_REQUIRE_EQUAL(direct_file.fclose(), 0);730}732// Compare the resulting files733DataBuffer direct_result{file_size};734{735AutoFile verify_direct{test_direct.Open(pos, /*read_only=*/true), obfuscation};736verify_direct.read(direct_result);738DataBuffer excess_byte{1};739BOOST_CHECK_EXCEPTION(verify_direct.read(excess_byte), std::ios_base::failure, HasReason{"end of file"});740}742DataBuffer buffered_result{file_size};743{744AutoFile verify_buffered{test_buffered.Open(pos, /*read_only=*/true), obfuscation};745verify_buffered.read(buffered_result);747DataBuffer excess_byte{1};748BOOST_CHECK_EXCEPTION(verify_buffered.read(excess_byte), std::ios_base::failure, HasReason{"end of file"});749}
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.