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); }
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_); }
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); }
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; }
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); }
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; }
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); }
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; }
void write_network_address(network_address_type addr) { write_8_bytes(addr.services); write_data(addr.ip); write_data(uncast_type(addr.port, true)); }