Repository: bitcoin/bitcoin
File: src/wallet/migrate.cpp (C++)

Code before:

static void SeekToPage(AutoFile& s, uint32_t page_num, uint32_t page_size)
{
    int64_t pos = int64_t{page_num} * page_size;
    s.seek(pos, SEEK_SET);
}

void BerkeleyRODatabase::Open()
{
    // Open the file
    FILE* file = fsbridge::fopen(m_filepath, "rb");
    AutoFile db_file(file);
    if (db_file.IsNull()) {
        throw std::runtime_error("BerkeleyRODatabase: Failed to open database file");
    }

    uint32_t page_size = 4096; // Default page size

    // Read the outer metapage
    // Expected page number is 0
    MetaPage outer_meta(0);
    db_file >> outer_meta;
    page_size = outer_meta.pagesize;

    // Verify the size of the file is a multiple of the page size
    db_file.seek(0, SEEK_END);
    int64_t size = db_file.tell();

    // Since BDB stores everything in a page, the file size should be a multiple of the page size;
    // However, BDB doesn't actually check that this is the case, and enforcing this check results
    // in us rejecting a database that BDB would not, so this check needs to be excluded.
    // This is left commented out as a reminder to not accidentally implement this in the future.
    // if (size % page_size != 0) {
    //     throw std::runtime_error("File size is not a multiple of page size");
    // }

    // Check the last page number
    uint32_t expected_last_page{uint32_t((size / page_size) - 1)};
    if (outer_meta.last_page != expected_last_page) {
        throw std::runtime_error("Last page number could not fit in file");
    }

    // Make sure encryption is disabled
    if (outer_meta.encrypt_algo != 0) {
        throw std::runtime_error("BDB builtin encryption is not supported");
    }

    // Check all Log Sequence Numbers (LSN) point to file 0 and offset 1 which indicates that the LSNs were
    // reset and that the log files are not necessary to get all of the data in the database.
    for (uint32_t i = 0; i < outer_meta.last_page; ++i) {
        // The LSN is composed of 2 32-bit ints, the first is a file id, the second an offset

Review comment (suggestion):
nit:
```suggestion
    const int64_t size{db_file.size()};
```

Code after:

static void SeekToPage(AutoFile& s, uint32_t page_num, uint32_t page_size)
{
    int64_t pos = int64_t{page_num} * page_size;
    s.seek(pos, SEEK_SET);
}

void BerkeleyRODatabase::Open()
{
    // Open the file
    FILE* file = fsbridge::fopen(m_filepath, "rb");
    AutoFile db_file(file);
    if (db_file.IsNull()) {
        throw std::runtime_error("BerkeleyRODatabase: Failed to open database file");
    }

    uint32_t page_size = 4096; // Default page size

    // Read the outer metapage
    // Expected page number is 0
    MetaPage outer_meta(0);
    db_file >> outer_meta;
    page_size = outer_meta.pagesize;

    // Verify the size of the file is a multiple of the page size
    const int64_t size{db_file.size()};

    // Since BDB stores everything in a page, the file size should be a multiple of the page size;
    // However, BDB doesn't actually check that this is the case, and enforcing this check results
    // in us rejecting a database that BDB would not, so this check needs to be excluded.
    // This is left commented out as a reminder to not accidentally implement this in the future.
    // if (size % page_size != 0) {
    //     throw std::runtime_error("File size is not a multiple of page size");
    // }

    // Check the last page number
    uint32_t expected_last_page{uint32_t((size / page_size) - 1)};
    if (outer_meta.last_page != expected_last_page) {
        throw std::runtime_error("Last page number could not fit in file");
    }

    // Make sure encryption is disabled
    if (outer_meta.encrypt_algo != 0) {
        throw std::runtime_error("BDB builtin encryption is not supported");
    }

    // Check all Log Sequence Numbers (LSN) point to file 0 and offset 1 which indicates that the LSNs were
    // reset and that the log files are not necessary to get all of the data in the database.
    for (uint32_t i = 0; i < outer_meta.last_page; ++i) {
        // The LSN is composed of 2 32-bit ints, the first is a file id, the second an offset
        // It will always be the first 8 bytes of a page, so we deserialize it directly for every page