void block_database::write_position(const position_type position)
{
    const index_type height = index_.allocate();
    record_type record = index_.get(height);
    auto serial = make_serializer(record);
    serial.write_8_bytes(position);
}
void block_database::write_position(const position_type position)
{
    const auto record = index_.allocate();
    const auto data = index_.get(record);
    auto serial = make_serializer(data);
    serial.write_8_bytes(position);
}
예제 #3
0
void hashtable_database_writer::write_records_size()
{
    const size_t header_size = 24 + buckets_ * 8;
    BITCOIN_ASSERT(file_.size() >= header_size + total_records_size_);
    auto serial = make_serializer(file_.data() + 16);
    serial.write_8_bytes(total_records_size_);
}
예제 #4
0
void hashtable_database_writer::link_record(
    uint64_t bucket_index, uint64_t record_begin)
{
    BITCOIN_ASSERT(file_.size() > 24 + buckets_ * 8);
    BITCOIN_ASSERT(bucket_index < buckets_);
    uint8_t* bucket_begin = file_.data() + bucket_offset(bucket_index);
    auto serial = make_serializer(bucket_begin);
    serial.write_8_bytes(record_begin);
}
예제 #5
0
data_chunk create_address_key(
    const payment_address& address, const output_point& outpoint)
{
    data_chunk result(1 + short_hash_size + 8);
    auto serial = make_serializer(result.begin());
    serial.write_byte(address.version());
    serial.write_short_hash(address.hash());
    serial.write_8_bytes(addr_key_checksum(outpoint));
    BITCOIN_ASSERT(serial.iterator() == result.end());
    return result;
}
예제 #6
0
void hashtable_database_writer::store(const hash_digest& key_hash,
    size_t value_size, write_value_function write)
{
    // Calculate the end of the last record.
    const uint64_t header_size = 24 + buckets_ * 8;
    const uint64_t records_end_offset = header_size + total_records_size_;
    // [ tx hash ]              32
    // [ varuint value size ]
    // [ ... value data ... ]
    // [ next tx in bucket ]    8
    const size_t record_size =
        32 + variable_uint_size(value_size) + value_size + 8;
    // If a record crosses a page boundary then we align it with
    // the beginning of the next page.
    const size_t record_begin =
        align_if_crossing_page(page_size_, records_end_offset, record_size);
    BITCOIN_ASSERT(file_.size() >= record_begin + record_size);
    // We will insert new transactions at the beginning of the bucket's list.
    // I assume that more recent transactions in the blockchain are used
    // more often than older ones.
    // We lookup the existing value in the bucket first.
    const uint64_t bucket_index = remainder(key_hash.data(), buckets_);
    BITCOIN_ASSERT(bucket_index < buckets_);
    const uint64_t previous_bucket_value = read_bucket_value(bucket_index);
    // Now begin writing the record itself.
    uint8_t* entry = file_.data() + record_begin;
    auto serial = make_serializer(entry);
    serial.write_hash(key_hash);
    serial.write_variable_uint(value_size);
    // Call the supplied callback to serialize the data.
    write(serial.iterator());
    serial.set_iterator(serial.iterator() + value_size);
    serial.write_8_bytes(previous_bucket_value);
    BITCOIN_ASSERT(serial.iterator() == entry + record_size);
    // Change file size value at file start.
    // This must be done first so any subsequent writes don't
    // overwrite this record in case of a crash or interruption.
    BITCOIN_ASSERT(record_begin >= header_size);
    const uint64_t alignment_padding =
        record_begin - header_size - total_records_size_;
    BITCOIN_ASSERT(alignment_padding <= page_size_);
    total_records_size_ += record_size + alignment_padding;
    // Now add record to bucket.
    const uint64_t record_begin_offset = record_begin - header_size;
    link_record(bucket_index, record_begin_offset);
}
예제 #7
0
bool add_credit(leveldb::WriteBatch& batch,
    const payment_address& address, uint64_t output_value,
    const output_point& outpoint, uint32_t block_height)
{
    data_chunk addr_key = create_address_key(address, outpoint);
    // outpoint, value, block_height
    data_chunk row_info(36 + 8 + 4);
    auto serial = make_serializer(row_info.begin());
    // outpoint
    serial.write_hash(outpoint.hash);
    serial.write_4_bytes(outpoint.index);
    // value
    serial.write_8_bytes(output_value);
    // block_height
    serial.write_4_bytes(block_height);
    BITCOIN_ASSERT(
        std::distance(row_info.begin(), serial.iterator()) == 36 + 8 + 4);
    batch.Put(slice(addr_key), slice(row_info));
    return true;
}
예제 #8
0
 void write_variable_uint(uint64_t value)
 {
     if (value < 0xfd)
     {
         write_byte(value);
     }
     else if (value <= 0xffff)
     {
         write_byte(0xfd);
         write_2_bytes(value);
     }
     else if (value <= 0xffffffff)
     {
         write_byte(0xfe);
         write_4_bytes(value);
     }
     else
     {
         write_byte(0xff);
         write_8_bytes(value);
     }
 }
void history_scan_database::add(const address_bitset& key,
    const uint8_t marker, const point_type& point,
    uint32_t block_height, uint64_t value)
{
    BITCOIN_ASSERT(key.size() >= settings_.sharded_bitsize);
    // Both add() and sync() must have identical lookup of shards.
    hsdb_shard& shard = lookup(key);
    address_bitset sub_key = drop_prefix(key);
    BITCOIN_ASSERT(sub_key.size() == settings_.scan_bitsize());
#ifdef HSDB_DEBUG
    log_debug(LOG_HSDB) << "Sub key = " << sub_key;
#endif
    data_chunk row_data(settings_.row_value_size);
    auto serial = make_serializer(row_data.begin());
    serial.write_byte(marker);
    serial.write_hash(point.hash);
    serial.write_4_bytes(point.index);
    serial.write_4_bytes(block_height);
    serial.write_8_bytes(value);
    BITCOIN_ASSERT(serial.iterator() ==
        row_data.begin() + settings_.row_value_size);
    shard.add(sub_key, row_data);
}
예제 #10
0
bool add_credit(leveldb::WriteBatch& batch,
    const transaction_output_type& output, const output_point& outpoint,
    uint32_t block_height)
{
    payment_address address;
    // Not a Bitcoin address so skip this output.
    if (!extract(address, output.script))
        return true;
    data_chunk addr_key = create_address_key(address, outpoint);
    // outpoint, value, block_height
    data_chunk row_info(36 + 8 + 4);
    auto serial = make_serializer(row_info.begin());
    // outpoint
    serial.write_hash(outpoint.hash);
    serial.write_4_bytes(outpoint.index);
    // value
    serial.write_8_bytes(output.value);
    // block_height
    serial.write_4_bytes(block_height);
    BITCOIN_ASSERT(
        std::distance(row_info.begin(), serial.iterator()) == 36 + 8 + 4);
    batch.Put(slice(addr_key), slice(row_info));
    return true;
}
예제 #11
0
 void write_network_address(network_address_type addr)
 {
     write_8_bytes(addr.services);
     write_data(addr.ip);
     write_data(uncast_type(addr.port, true));
 }